【STM32】驱动LCD1602液晶8线并、4线并

简介: 【STM32】驱动LCD1602液晶8线并、4线并

LCD1602液晶

液晶模块和数码管相比,液晶模块会显得更加专业、漂亮。液晶显示器以其体积小、功耗低、超薄、轻巧、显示内容丰富、使用方便等等诸多有点,在电子设备、通讯、家用电器、仪器仪表等低功耗应用系统之中得到越来越广泛的应用了,使得这一些电子设备的人机界面变得越来越直观、越来越形象了,液晶模块现在已经广泛的应用于液晶电视机、电子表、复印机、计算器、便携式电脑、IC卡电话机、掌上型电子玩具、传真机等许多方面。1602的字符型液晶模块(带背光),是现在工控系统之中使用最为广泛的液晶屏之一了。1602采用了标准的16脚接口。

引脚定义说明

5ad30f90bf0b48dafb279bfdf37e2a20_00d43d2e0ba940c29c08187c3cdae757.png

字库概述

       1602的液晶模块内一般都是带有标准字库的,在内部的字符发生存储器(CGROM)已经是存储了192个5×7的点阵字符,32个5×10的点阵字符。另外还会有字符生成RAM(CGRAM) 512字节,供给用户来自定义字符,比如表1所示,这一些字符都有:英文字母的大小写、阿拉伯数组、常用的符号以及日文假名等,每一个字符都会有一个固定的代码,比如大写的英文字母“A”的代码是01000001B(41H),显示是模块会吧地址41H中的点阵字符图形给显示出来,我们就能看到字母“A”了。

       液晶显示模块时一个慢显示器件,所以在执行每一条指令之前都一定要确认模块得忙标志位为低电平,代表不忙,否则此指令会失效。要显示字符时需要先输入显示字符地址,也就是说告诉模块在哪里显示字符。

LCD1602原理图

d556eb86567bc015498a7c019db005e5_78917fe64f76488c8c7a26b615322cc6.png

LCD1602时序图

e0c872a5bb996cc308253f1cda58e9ed_ffb30f58673e4b5088e3a94fbd2a275d.png

RS = 0 写指令;RS = 1 写数据

LCD1602代码

LCD1602.c

1. #include "LCD1602.h"
2. 
3. void LCD1602_UserInit(void)
4. {
5.  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);
6.  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOF, ENABLE);
7. 
8.  //配置控制I/O口
9.  GPIO_InitTypeDef GPIO_InitStructure;
10.   GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_Out_PP; //推挽输出
11.   GPIO_InitStructure.GPIO_Pin   = RS | RW | EN;
12.   GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz;
13.   GPIO_Init(CMD_PROT, &GPIO_InitStructure);
14. 
15.   //配置数据I/O口
16.   GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_Out_PP; //推挽输出
17.   GPIO_InitStructure.GPIO_Pin   = DATA;
18.   GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz;
19.   GPIO_Init(CMD_PROT, &GPIO_InitStructure); 
20. }
21. 
22. void LCD1602_Write_Cmd_Data(uint8_t cmd, uint8_t data)
23. {
24.   if (cmd) //1 数据
25.   {        
26.     RS_HIGH;
27.     RW_LOW;
28.     EN_LOW;   
29.     GPIO_Write(DATA_PROT, data); Delay_ms(3);   
30.     EN_HIGH; Delay_ms(3);
31.     EN_LOW;   
32.   }        
33.   else   //0 指令
34.   {
35.     RS_LOW;
36.     RW_LOW;
37.     EN_LOW;   
38.     GPIO_Write(DATA_PROT, data); Delay_ms(3);   
39.     EN_HIGH; Delay_ms(3);
40.     EN_LOW;
41.   }
42. }
43. 
44. void LCD1602_Write_Init(void)
45. {
46.   LCD1602_Write_Cmd_Data(CMD, 0x38);  //基本设置 显示模式设置
47.   LCD1602_Write_Cmd_Data(CMD, 0x06);  //显示光标移动位置
48.   LCD1602_Write_Cmd_Data(CMD, 0x0C);  //开启显示 不显示光标 并且光标不闪烁
49.   LCD1602_Write_Cmd_Data(CMD, 0x01);  //清除屏幕内容
50.   LCD1602_Write_Cmd_Data(CMD, 0x80);  //设置起始地址
51. }
52. 
53. //开启显示
54. void LCD1602_Open(void)
55. {
56.   LCD1602_Write_Cmd_Data(CMD, 0x38);  //基本设置 显示模式设置
57.   LCD1602_Write_Cmd_Data(CMD, 0x0C);
58. }
59. 
60. //关闭显示
61. void LCD1602_Shut(void)
62. {
63.   LCD1602_Write_Cmd_Data(CMD, 0x38);  //基本设置 显示模式设置
64.   LCD1602_Write_Cmd_Data(CMD, 0x08);
65. }
66. 
67. /**
68.  * @brief  
69.  * @param  com  写的地址   //1602 第一行数据0x80~0x8F 第二行数据0xC0~0xCF
70.  * @param  num  写的长度
71.  * @param  *dat 写的内容
72.  * @retval 无
73.  */
74. void LCD1602_Write_Word_Display(uint8_t com, uint8_t num, uint8_t *dat)
75. {
76.   LCD1602_Write_Cmd_Data(CMD, com);
77.   for (uint8_t i = 0; i < num; i ++)
78.   {
79.     LCD1602_Write_Cmd_Data(DAT,*dat++);
80.   }
81. 
82. }
83.

LCD1602.h

1. #ifndef __LCD1602_H__
2. #define __LCD1602_H__
3. 
4. #include "stm32f10x.h"                  // Device header
5. #include "Delay.h"
6. 
7. #define RS GPIO_Pin_0  //RS = 0,指令;RS = 1,数据
8. #define RW GPIO_Pin_1  //RW = 0,写  ;RW = 1,读
9. #define EN GPIO_Pin_2
10. #define CMD_PROT  GPIOC
11. 
12. #define DATA 0x00FF //0~7引脚
13. #define DATA_PROT GPIOF
14. 
15. #define RS_HIGH GPIO_SetBits  (CMD_PROT, RS)
16. #define RS_LOW  GPIO_ResetBits(CMD_PROT, RS)
17. 
18. #define RW_HIGH GPIO_SetBits  (CMD_PROT, RW)
19. #define RW_LOW  GPIO_ResetBits(CMD_PROT, RW)
20. 
21. #define EN_HIGH GPIO_SetBits  (CMD_PROT, EN)
22. #define EN_LOW  GPIO_ResetBits(CMD_PROT, EN)
23. 
24. #define CMD 0 //代表RS = 0,指令
25. #define DAT 1 //代表RS = 1,数据
26. 
27. void LCD1602_UserInit(void);  //LCD1602初始化
28. void LCD1602_Write_Init(void);  //LCD1602写初始化
29. void LCD1602_Open(void);
30. void LCD1602_Shut(void);
31. void LCD1602_Write_Word_Display(uint8_t com, uint8_t num, uint8_t *dat);
32. 
33. #endif
34.

主函数

1. #include "stm32f10x.h"                  // Device header
2. //#include "Delay.h"
3. #include "LCD1602.h"
4. 
5. int main(void)
6. {
7.  Delay_Init (72);
8. 
9.  LCD1602_UserInit();   //LCD1602初始化
10.   LCD1602_Write_Init(); //LCD1602写初始化
11. //  LCD1602_Open();
12. //  LCD1602_Shut();
13.   LCD1602_Write_Word_Display(0x80, 16, (u8*)&"xiaoliangtongxue" );  
14. 
15.   while(1)
16.   {
17. 
18.   }
19. }
20. 
21. /***********************************END OF FILE***********************************/
22.

接线图

(参考51单片机接线图)

RS RW EN 分别是PC0、PC1、PC2,数据线依次为PF0、PF1、PF2……

28124f847a0f64c43b8f8bd79402ed6d_00defc46d7c04b0d90cc8a271e154a27.png

崩溃瞬间

插了好一会杜邦线,你竟然不亮

9b8cc9006ae7d4573f8dbd518a8781ee_0661538315d84f76b0486ed7c621d315.png

c00c5d20d7978b86f52db8b1f9d56a11_f727ba58505849b0aba5ae5542a57fc2.png

这块LCD1602好像是坏了

13ea6cfdeedff5c78cc244131c25f644_9c82ed990db64dbba2ad5112c48f81aa.jpeg

算了算了,继续敲


用结构体的方式显示字符

在LCD1602.h文件里添加结构体的声明

1. //使用结构体
2. typedef struct{
3.  uint8_t com;
4.  uint8_t num;
5.  uint8_t *data;
6. }LCD_InitTypeDef;

将LCD1602.c文件里最后一个函数的形参改成结构体,函数里对应的数据也要修改成结构体成员

1. void LCD1602_Write_Word_Display(LCD_InitTypeDef  LCD_InitStructure)
2. {
3.  LCD1602_Write_Cmd_Data(CMD, LCD_InitStructure.com);
4.  for (uint8_t i = 0; i < LCD_InitStructure.num; i ++)
5.  {
6.    LCD1602_Write_Cmd_Data(DAT,*LCD_InitStructure.data++);
7.  }
8. 
9. }

main.c

1. #include "stm32f10x.h"                  // Device header
2. //#include "Delay.h"
3. #include "LCD1602.h"
4. 
5. LCD_InitTypeDef  LCD_InitStructure;
6. 
7. int main(void)
8. {
9.  Delay_Init (72);
10. 
11.   LCD1602_UserInit();   //LCD1602初始化
12.   LCD1602_Write_Init(); //LCD1602写初始化
13. //  LCD1602_Open();
14. //  LCD1602_Shut(); 
15. 
16.   LCD_InitStructure.com = 0xC0; //第二行
17.   LCD_InitStructure.num = sizeof("xinniankuaile666")-1; //计算长度
18.   LCD_InitStructure.data = (u8*)&"xinniankuaile666";  //显示的内容
19. 
20.   LCD1602_Write_Word_Display(LCD_InitStructure);  
21.   while(1)
22.   {
23. 
24.   }
25. }

LCD1602动态显示数字

1. void LCD1602_Number_Display(u8 com, u8 num)  //数据范围0~255
2. {
3.  const u8 numcode[] = {"0123456789"};  //只读,不可修改
4. 
5.  LCD1602_Write_Cmd_Data(CMD, com);
6.  LCD1602_Write_Cmd_Data(DAT, numcode[num/100]);//数位分离
7.  LCD1602_Write_Cmd_Data(DAT, numcode[num/10%10]);
8.  LCD1602_Write_Cmd_Data(DAT, numcode[num%10]);
9. }

while(1)里的代码

1. for(u8 i = 0; i < 255; i ++)
2. {
3.     LCD1602_Number_Display(0x87, i);
4.     Delay_ms(300);
5. }

4线驱动LCD1602

a8cace8f63193674ab7f1e17a835375b_d7ab27637d264622b69d8aa690b3fde8.png

只用4567  四个数据引脚

数据以四位四位的方式发送

代码部分

1. #include "LCD1602.h"
2. 
3. void LCD1602_UserInit(void)
4. {
5.  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);
6.  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOF, ENABLE);
7. 
8.  //配置控制I/O口
9.  GPIO_InitTypeDef GPIO_InitStructure;
10.   GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_Out_PP; //推挽输出
11.   GPIO_InitStructure.GPIO_Pin   = RS | RW | EN;
12.   GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz;
13.   GPIO_Init(CMD_PROT, &GPIO_InitStructure);
14. 
15.   //配置数据I/O口
16.   GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_Out_PP; //推挽输出
17.   GPIO_InitStructure.GPIO_Pin   = DATA;
18.   GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz;
19.   GPIO_Init(CMD_PROT, &GPIO_InitStructure); 
20. }
21. 
22. /*4线传输*/
23. void LCD1602_Write_Cmd_Data(uint8_t cmd, uint8_t data)
24. {
25. //  /*代码优化*/
26. //  if (cmd) //1 数据       
27. //    RS_HIGH;
28. //  else   //0 指令
29. //    RS_LOW;
30. 
31.   //对上面四行代码继续优化,用到了三目运算符
32.   (CMD) ? RS_HIGH : RS_LOW;
33. 
34. 
35.   //依次执行
36.   RW_LOW;
37.   EN_LOW; 
38. 
39.   GPIO_Write(DATA_PROT, data | 0x0f); Delay_ms(3);//传输高四位数据 
40.   EN_HIGH; Delay_ms(3);
41.   EN_LOW;
42. 
43.   GPIO_Write(DATA_PROT, (data << 4) | 0x0f); Delay_ms(3);//左移四位,将低四位数据传输
44.   EN_HIGH; Delay_ms(3);
45.   EN_LOW; 
46. 
47. 
48. }
49. 
50. void LCD1602_Write_Init(void)
51. {
52.   LCD1602_Write_Cmd_Data(CMD, 0x38);  //基本设置 显示模式设置
53.   LCD1602_Write_Cmd_Data(CMD, 0x33);  //设置显示模式
54.   LCD1602_Write_Cmd_Data(CMD, 0x32);  //设置8线转4线显示模式
55.   LCD1602_Write_Cmd_Data(CMD, 0x28);  //设置指定模式初始化
56.   LCD1602_Write_Cmd_Data(CMD, 0x06);  //显示光标移动位置
57.   LCD1602_Write_Cmd_Data(CMD, 0x0C);  //开启显示 不显示光标 并且光标不闪烁
58.   LCD1602_Write_Cmd_Data(CMD, 0x01);  //清除屏幕内容
59.   LCD1602_Write_Cmd_Data(CMD, 0x80);  //设置起始地址
60. }
61. 
62. //开启显示
63. void LCD1602_Open(void)
64. {
65.   LCD1602_Write_Cmd_Data(CMD, 0x38);  //基本设置 显示模式设置
66.   LCD1602_Write_Cmd_Data(CMD, 0x33);  //设置显示模式
67.   LCD1602_Write_Cmd_Data(CMD, 0x32);  //设置8线转4线显示模式
68.   LCD1602_Write_Cmd_Data(CMD, 0x28);  //设置指定模式初始化
69.   LCD1602_Write_Cmd_Data(CMD, 0x0C);
70. }
71. 
72. //关闭显示
73. void LCD1602_Shut(void)
74. {
75.   LCD1602_Write_Cmd_Data(CMD, 0x38);  //基本设置 显示模式设置
76.   LCD1602_Write_Cmd_Data(CMD, 0x33);  //设置显示模式
77.   LCD1602_Write_Cmd_Data(CMD, 0x32);  //设置8线转4线显示模式
78.   LCD1602_Write_Cmd_Data(CMD, 0x28);  //设置指定模式初始化
79.   LCD1602_Write_Cmd_Data(CMD, 0x08);
80. }
81. 
82. /**
83.  * @brief  
84.  * @param  com  写的地址   //1602 第一行数据0x80~0x8F 第二行数据0xC0~0xCF
85.  * @param  num  写的长度
86.  * @param  *dat 写的内容
87.  * @retval 无
88.  */
89. void LCD1602_Write_Word_Display(LCD_InitTypeDef  LCD_InitStructure)
90. {
91.   LCD1602_Write_Cmd_Data(CMD, LCD_InitStructure.com);
92.   for (uint8_t i = 0; i < LCD_InitStructure.num; i ++)
93.   {
94.     LCD1602_Write_Cmd_Data(DAT,*LCD_InitStructure.data++);
95.   }
96. 
97. }
98. 
99. void LCD1602_Number_Display(u8 com, u8 num) //数据范围0~255
100. {
101.  const u8 numcode[] = {"0123456789"};  //只读,不可修改
102. 
103.  LCD1602_Write_Cmd_Data(CMD, com);
104.  LCD1602_Write_Cmd_Data(DAT, numcode[num/100]);//数位分离
105.  LCD1602_Write_Cmd_Data(DAT, numcode[num/10%10]);
106.  LCD1602_Write_Cmd_Data(DAT, numcode[num%10]);
107. }
108.
1. #ifndef __LCD1602_H__
2. #define __LCD1602_H__
3. 
4. #include "stm32f10x.h"                  // Device header
5. #include "Delay.h"
6. 
7. //使用结构体
8. typedef struct{
9.  uint8_t com;
10.   uint8_t num;
11.   uint8_t *data;
12. }LCD_InitTypeDef;
13. 
14. #define RS  GPIO_Pin_0  //RS = 0,指令;RS = 1,数据
15. #define RW  GPIO_Pin_1  //RW = 0,写  ;RW = 1,读
16. #define EN  GPIO_Pin_2
17. #define CMD_PROT  GPIOC
18. 
19. #define DATA 0x00F0 //4~7引脚
20. #define DATA_PROT GPIOF
21. 
22. #define RS_HIGH GPIO_SetBits  (CMD_PROT, RS)
23. #define RS_LOW  GPIO_ResetBits(CMD_PROT, RS)
24. 
25. #define RW_HIGH GPIO_SetBits  (CMD_PROT, RW)
26. #define RW_LOW  GPIO_ResetBits(CMD_PROT, RW)
27. 
28. #define EN_HIGH GPIO_SetBits  (CMD_PROT, EN)
29. #define EN_LOW  GPIO_ResetBits(CMD_PROT, EN)
30. 
31. #define CMD 0 //代表RS = 0,指令
32. #define DAT 1 //代表RS = 1,数据
33. 
34. void LCD1602_UserInit(void);  //LCD1602初始化
35. void LCD1602_Write_Init(void);  //LCD1602写初始化
36. void LCD1602_Open(void);
37. void LCD1602_Shut(void);
38. 
39. void LCD1602_Write_Word_Display(LCD_InitTypeDef  LCD_InitStructure);
40. 
41. void LCD1602_Number_Display(u8 com, u8 num);
42. 
43. #endif
1. #include "stm32f10x.h"                  // Device header
2. //#include "Delay.h"
3. #include "LCD1602.h"
4. 
5. LCD_InitTypeDef  LCD_InitStructure;
6. 
7. int main(void)
8. {
9.  Delay_Init (72);
10. 
11.   LCD1602_UserInit();   //LCD1602初始化
12.   LCD1602_Write_Init(); //LCD1602写初始化
13.   LCD1602_Open();
14. //  LCD1602_Shut();   
15. 
16.   LCD_InitStructure.com = 0xC0; //第二行
17.   LCD_InitStructure.num = sizeof("xinniankuaile666")-1; //计算长度
18.   LCD_InitStructure.data = (u8*)&"xinniankuaile666";  //显示的内容
19.   LCD1602_Write_Word_Display(LCD_InitStructure);  
20. 
21.   while(1)
22.   {
23.     for(u8 i = 0; i < 255; i ++)
24.     {
25.       LCD1602_Number_Display(0x87, i);
26.       Delay_ms(300);
27.     }
28. 
29.   }
30. }

好像是这个函数没有取消注释才不亮 LCD1602_Open();

5c53bab3dd73b6331eecaf0d0479a75b_316cbf272e82454c83ee3b787cdb76f6.jpeg

相关文章
STM32Cubemx PWM驱动加湿器模拟火山喷发效果
STM32Cubemx PWM驱动加湿器模拟火山喷发效果
273 14
STM32Cubemx PWM驱动SG90舵机
STM32Cubemx PWM驱动SG90舵机
633 13
STM32CubeMX mpu6050驱动
STM32CubeMX mpu6050驱动
214 10
STM32CubeMX EC11旋转编码器驱动
STM32CubeMX EC11旋转编码器驱动
1109 10
STM32CubeMX OLED驱动
STM32CubeMX OLED驱动
216 10
|
芯片
STM32CubeMX TM1637驱动数码管
STM32CubeMX TM1637驱动数码管
744 6
|
传感器
手把手在STM32F103C8T6上构建可扩展可移植的DHT11驱动
【8月更文挑战第29天】本文详细介绍在STM32F103C8T6上构建可扩展且可移植的DHT11温湿度传感器驱动的步骤,包括硬件与软件准备、硬件连接、驱动代码编写及测试。通过这些步骤,可根据实际项目需求优化和扩展代码。
593 0
STM32CubeMX WS2812B灯驱动
STM32CubeMX WS2812B灯驱动
892 1