lcd1602显示字符串(stm32+hal+lcd1602)
一、lcd1602说明
是一种字符型液晶显示模块,不能显示汉字。
有16个引脚,如下:
我们在代码中使用了11个引脚,如上图红色标记,分别是:
RS:区分命令和数据,0表示命令,1表示数据
RW:读写区分,1读,0写
E:使能位,高电平使能
DB0-DB7:数据或命令
二、stm32芯片的引脚分别与lcd1602的11个引脚相连,使用stm32CubeMX软件进行初始化工程,我的连接如下图
引脚都配置成输出模式,并取别名,建议以lcd1602引脚名来命名,方便记忆:
当然还需要配置时钟、下载方式、工程属性等,最后自动生成初始化代码。
三、使用keil软件打开工程,并添加文件lcd1602.c、lcd1602.c,加入到工程
lcd1602.c代码如下
#include "lcd1602.h"
//内部函数,写一个字节显示数据
void WriteByteData(char c)
{
RS_H();
RW_L();
E_L();
//将c的8个bit位分别放到DB0到DB7
HAL_GPIO_WritePin(GPIOB,DB0_Pin,(GPIO_PinState)(c&0x01));
HAL_GPIO_WritePin(GPIOB,DB1_Pin,(GPIO_PinState)((c>>1)&0x01));
HAL_GPIO_WritePin(GPIOB,DB2_Pin,(GPIO_PinState)((c>>2)&0x01));
HAL_GPIO_WritePin(GPIOB,DB3_Pin,(GPIO_PinState)((c>>3)&0x01));
HAL_GPIO_WritePin(GPIOB,DB4_Pin,(GPIO_PinState)((c>>4)&0x01));
HAL_GPIO_WritePin(GPIOC,DB5_Pin,(GPIO_PinState)((c>>5)&0x01));
HAL_GPIO_WritePin(GPIOC,DB6_Pin,(GPIO_PinState)((c>>6)&0x01));
HAL_GPIO_WritePin(GPIOC,DB7_Pin,(GPIO_PinState)((c>>7)&0x01));
//补充完整代码
E_H();
HAL_Delay(1);
E_L();
}
//内部函数,写一个字节命令
void WriteByteCmd(char c)
{
RS_L();
RW_L();
E_L();
//将C的8个bit位分别放到DB0到DB7
HAL_GPIO_WritePin(GPIOB,DB0_Pin,(GPIO_PinState)(c&0x01));
HAL_GPIO_WritePin(GPIOB,DB1_Pin,(GPIO_PinState)((c>>1)&0x01));
HAL_GPIO_WritePin(GPIOB,DB2_Pin,(GPIO_PinState)((c>>2)&0x01));
HAL_GPIO_WritePin(GPIOB,DB3_Pin,(GPIO_PinState)((c>>3)&0x01));
HAL_GPIO_WritePin(GPIOB,DB4_Pin,(GPIO_PinState)((c>>4)&0x01));
HAL_GPIO_WritePin(GPIOC,DB5_Pin,(GPIO_PinState)((c>>5)&0x01));
HAL_GPIO_WritePin(GPIOC,DB6_Pin,(GPIO_PinState)((c>>6)&0x01));
HAL_GPIO_WritePin(GPIOC,DB7_Pin,(GPIO_PinState)((c>>7)&0x01));
//补充完整代码
E_H();
HAL_Delay(1);
E_L();
}
//初始化函数定义
void lcd1602_init(void)
{
WriteByteCmd(0x38);//8个数据线,显示两行,5*7点阵
WriteByteCmd(0x0C);//显示功能打开0x0c
WriteByteCmd(0x06);//光标自动右边移动0x06
WriteByteCmd(0x01);//清屏0x01
}
//内部函数:设置显示的起始地址
int setAddr(int row,int col)
{
char addr;
if(row == 0)
addr = 0x80+col;
else if(row == 1)
addr = 0x80+0x40+col;
else
return -1;
WriteByteCmd(addr);
return 0;
}
//写字符串函数定义
void ShowString(int row,int col,char data[])
{
//定位
int ret = setAddr(row,col);
if(ret !=0)
return ;
char *p = data;
while(*p)
{
WriteByteData(*p);
p++;
}
}
//清屏函数定义
void clearScreen(void)
{
WriteByteCmd(0x01);//清屏0x01
}
lcd1602.h代码:
#ifndef __LCD1602_H__
#define __LCD1602_H__
#include "main.h"
#define RS_H() HAL_GPIO_WritePin(GPIOC,RS1602_Pin,GPIO_PIN_SET)
#define RS_L() HAL_GPIO_WritePin(GPIOC,RS1602_Pin,GPIO_PIN_RESET)
#define RW_H() HAL_GPIO_WritePin(GPIOA,RW1602_Pin,GPIO_PIN_SET)
#define RW_L() HAL_GPIO_WritePin(GPIOA,RW1602_Pin,GPIO_PIN_RESET)
#define E_H() HAL_GPIO_WritePin(GPIOB,E1602_Pin,GPIO_PIN_SET)
#define E_L() HAL_GPIO_WritePin(GPIOB,E1602_Pin,GPIO_PIN_RESET)
//初始化函数声明
void lcd1602_init(void);
//显示字符串函数声明
void ShowString(int row,int col,char data[]);
//清屏函数声明
void clearScreen(void);
#endif
main函数中添加lcd1602头文件,然后添加代码如下:
#include "lcd1602.h"
四、编译、烧写代码,然后观察现象
五、代码解析
1)写时序如下:
如下图可以看出,使能的持续实践至少是tpw,为150纳秒,HAL库函数没有提供到纳秒的延时(可以自己写),我们就延时一毫秒,时间是足够的。
根据上两张图,完成代码如下所示:
2)lcd1602显示的每个位置都有地址,将光标指向那个地址就在那显示数据
所以上面每个字符的显示位置要加上0x80。说明一下,由于我们是芯片向lcd1602写数据显示,所以检查忙的动作可以不用做。
根据上面写出代码:
3)stm32与lcd1602,总共要用到11个引脚,在芯片资源比较紧张的情况下,可以4条数据线进行数据或命令传输,传输一个字节信息需要传两次,这种情况需要借助于HD44780来完成。
作者:蓉城儿女