最近老師布置一個小任務用STM32控制1602,本來覺得應該很簡單,但是在學習過程中也出現很多問題,很多疑問。
1、TFTLCD可以被當做SRAM使用,LCD1602可以當做什么使用嗎?
2、可以通過FSMC想TFT一樣嗎?
3、對于5V的LCD1602,3.3VSTM32引腳應該怎么設置?
因為擔心不小心就燒壞芯片,所以我用最小系統來做,用面包板來搭1602的電路。
我發現大家都是直接用51上使用的方法直接在STM32上用,自己也沒有繼續在想其他辦法。
程序基本是:1、利用位帶操作設置好1602三只控制腳和指示燈(八個數據腳用數據寄存器來完成)
2、LCD1602寫入8位命令子函數和LCD1602寫入8位數據子函數、LCD1602初始化子程序
3、GPIO初始化
最后的效果是1602顯示正常,LED閃爍。
值得留意的是:八個數據腳用數據寄存器來完成
GPIO初始化的時候,數據的引腳GPIOE(2-9)用開漏輸出,控制引腳用推挽輸出GPIOF(0-3)(其實我是想全部設置成開漏輸出的,因為網上大家都是找到FT(可以承受5V的引腳),然后設置開漏輸出,但是控制引腳用開漏輸出無法正常顯示,不知道什么原因)
除了標有ADC其他引腳都是可以承受5V的,芯片數據手冊和原理圖可以查閱。
STM32連接LCD1602要接保護電阻,偷懶就沒有加上了 。
不懂寄存器可以查參考手冊。
GPIO輸出方式可以看固件庫使用手冊。
制作出來的實物圖如下:
電路原理圖如下:
單片機源程序如下:
- #include "stm32f10x.h"
- //位帶操作,實現51類似的GPIO控制功能
- //具體實現思想,參考<<CM3權威指南>>第五章(87頁~92頁).
- //IO口操作宏定義
- #define BITBAND(addr, bitnum) ((addr & 0xF0000000)+0x2000000+((addr &0xFFFFF)<<5)+(bitnum<<2))
- #define MEM_ADDR(addr) *((volatile unsigned long *)(addr))
- #define BIT_ADDR(addr, bitnum) MEM_ADDR(BITBAND(addr, bitnum))
- //IO口地址映射
- #define GPIOA_ODR_Addr (GPIOA_BASE+12) //0x4001080C
- #define GPIOB_ODR_Addr (GPIOB_BASE+12) //0x40010C0C
- #define GPIOC_ODR_Addr (GPIOC_BASE+12) //0x4001100C
- #define GPIOD_ODR_Addr (GPIOD_BASE+12) //0x4001140C
- #define GPIOE_ODR_Addr (GPIOE_BASE+12) //0x4001180C
- #define GPIOF_ODR_Addr (GPIOF_BASE+12) //0x40011A0C
- #define GPIOG_ODR_Addr (GPIOG_BASE+12) //0x40011E0C
- #define GPIOA_IDR_Addr (GPIOA_BASE+8) //0x40010808
- #define GPIOB_IDR_Addr (GPIOB_BASE+8) //0x40010C08
- #define GPIOC_IDR_Addr (GPIOC_BASE+8) //0x40011008
- #define GPIOD_IDR_Addr (GPIOD_BASE+8) //0x40011408
- #define GPIOE_IDR_Addr (GPIOE_BASE+8) //0x40011808
- #define GPIOF_IDR_Addr (GPIOF_BASE+8) //0x40011A08
- #define GPIOG_IDR_Addr (GPIOG_BASE+8) //0x40011E08
-
- //IO口操作,只對單一的IO口!
- //確保n的值小于16!
- #define PAout(n) BIT_ADDR(GPIOA_ODR_Addr,n) //輸出
- #define PAin(n) BIT_ADDR(GPIOA_IDR_Addr,n) //輸入
- #define PBout(n) BIT_ADDR(GPIOB_ODR_Addr,n) //輸出
- #define PBin(n) BIT_ADDR(GPIOB_IDR_Addr,n) //輸入
- #define PCout(n) BIT_ADDR(GPIOC_ODR_Addr,n) //輸出
- #define PCin(n) BIT_ADDR(GPIOC_IDR_Addr,n) //輸入
- #define PDout(n) BIT_ADDR(GPIOD_ODR_Addr,n) //輸出
- #define PDin(n) BIT_ADDR(GPIOD_IDR_Addr,n) //輸入
- #define PEout(n) BIT_ADDR(GPIOE_ODR_Addr,n) //輸出
- #define PEin(n) BIT_ADDR(GPIOE_IDR_Addr,n) //輸入
- #define PFout(n) BIT_ADDR(GPIOF_ODR_Addr,n) //輸出
- #define PFin(n) BIT_ADDR(GPIOF_IDR_Addr,n) //輸入
- #define PGout(n) BIT_ADDR(GPIOG_ODR_Addr,n) //輸出
- #define PGin(n) BIT_ADDR(GPIOG_IDR_Addr,n) //輸入
- #define LCD1602_E PFout(0) //LCD1602_E連接的是PC2管腳
- #define LCD1602_RS PFout(1) //LCD1602_RS連接的是PC3管腳
- #define LCD1602_RW PFout(2) //LCD1602_RW連接的是PC4管腳
- #define Led PFout(3)
- /*??????*/
- #define TIME_MS 12000 //@72M
- #define TIME_US 10 //@72M
- /*************************
- 函數聲明
- *************************/
- /*延時函數*/
- void Delay_ms(u16 n);
- /*LCD1602寫入8位命令子函數*/
- void LcdWriteCom(u16 com);
- /*LCD1602寫入8位數據子函數*/
- void LcdWriteData(u16 dat);
- /*LCD1602初始化子程序*/
- void LcdInit(void);
- /*GPIO初始化*/
- void LCD_1602GPIO_Init(void);
- u8 Disp[] = " Pechin Science ";
- u8 dat[]="0123456789ABCDEF";
- /*?????*/
- void Delay_ms(u16 n)
- {
- u16 i,j;
-
- for(i=n;i>0;i--)
- for(j=TIME_MS;j>0;j--);
- }
- /*?????*/
- void Delay_us(u16 n)
- {
- u16 i,j;
-
- for(i=n;i>0;i--)
- for(j=TIME_US;j>0;j--);
- }
- /*GPIO初始化函數*/
- void LCD_1602GPIO_Init(void)
- {
- GPIO_InitTypeDef GPIO_InitStructure;//定義結構體變量
-
- RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOE,ENABLE);//使能GPIOE時鐘
-
- GPIO_InitStructure.GPIO_Pin=GPIO_Pin_2|GPIO_Pin_3|GPIO_Pin_4|GPIO_Pin_5|GPIO_Pin_6|GPIO_Pin_7|GPIO_Pin_8|GPIO_Pin_9;//選擇你要設置的IO口
- GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_OD; //設置開漏輸出模式
- GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;//設置傳輸速率
- GPIO_Init(GPIOE,&GPIO_InitStructure); //初始化GPIO
-
- GPIO_SetBits(GPIOE,GPIO_Pin_2|GPIO_Pin_3|GPIO_Pin_4|GPIO_Pin_5|GPIO_Pin_6|GPIO_Pin_7|GPIO_Pin_8|GPIO_Pin_9); //將GPIOE端口拉高,熄滅所有LED
- RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOF,ENABLE);//使能GPIOF時鐘
-
- GPIO_InitStructure.GPIO_Pin=GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3;//選擇你要設置的IO口
- GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP; //設置推挽輸出模式
- GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;//設置傳輸速率
- GPIO_Init(GPIOF,&GPIO_InitStructure); //初始化GPIO
-
- GPIO_SetBits(GPIOF,GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3); //將GPIOE端口拉高,熄滅所有LED
- }
- /*******************************************************************************
- * 函 數 名 : LcdWriteCom
- * 函數功能 : 向LCD寫入一個字節的命令
- * 輸 入 : com
- * 輸 出 : 無
- *******************************************************************************/
- void LcdWriteCom(u16 com)
- {
- LCD1602_E = 0; //使能
- LCD1602_RS = 0; //選擇發送命令
- LCD1602_RW = 0; //選擇寫入
-
- GPIOE->ODR = com<<2; //放入命令
- Delay_ms(1); //等待數據穩定
-
- LCD1602_E = 1; //寫入時序
- Delay_ms(5); //保持時間
- LCD1602_E = 0;
- }
- /*******************************************************************************
- * 函 數 名 : LcdWriteData
- * 函數功能 : 向LCD寫入一個字節的數據
- * 輸 入 : dat
- * 輸 出 : 無
- *******************************************************************************/
- void LcdWriteData(u16 dat) //寫入數據
- {
- LCD1602_E = 0; //使能清零
- LCD1602_RS = 1; //選擇輸入數據
- LCD1602_RW = 0; //選擇寫入
-
- GPIOE->ODR = dat<<2; //寫入數據
- Delay_ms(1);
-
- LCD1602_E = 1; //寫入時序
- Delay_ms(5); //保持時間
- LCD1602_E = 0;
-
- }
- /*******************************************************************************
- * 函 數 名 : LcdInit()
- * 函數功能 : 初始化LCD屏
- * 輸 入 : 無
- * 輸 出 : 無
- *******************************************************************************/
- void LcdInit(void) //LCD初始化程序
- {
- LcdWriteCom(0x38); //開顯示
- LcdWriteCom(0x0c); //開顯示不顯示光標
- LcdWriteCom(0x06); //寫一個指針加1
- LcdWriteCom(0x01); //清屏
- LcdWriteCom(0x80); //設置數據指針起點
-
- }
- int main(void)
- {
- u8 i;
- LCD_1602GPIO_Init();
- LcdInit();
- LcdWriteCom(0x80);
- for(i=0;i<16;i++)
- {
- LcdWriteData('A');
- }
- while(1)
- {
- Led = 1;
- Delay_ms(1000);
- Led = 0;
- Delay_ms(1000);
- }
- }
復制代碼
所有資料51hei提供下載:
嵌入式.7z
(237.08 KB, 下載次數: 81)
2019-1-22 02:29 上傳
點擊文件名下載附件
|