最近老师布置一个小任务用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)
|