• 单片机C语言实例:18、LCD1602液晶显示


     LCD1602的显示原理

    单片机的小朋友应该都见过这个显示器--LCD1602,这是最古老最简单的显示屏,上世纪80年代的产物。

    它显示的图案如下所示

    显示部分放大就是下面这样 ,像素就是一个个小方块,相当于描点法绘图了。

    如果把所有像素全部显示出来就是下面这样,全部是小黑点

     全部点亮的像素点如下所示,16列,2行,这就是1602名字的来历

    每个显示区域又可以细分为35个像素,7行5列

     整个屏幕就是35*16*2 = 1120个像素

    要想搞清楚这1120个像素的控制,就得先明白一个像素是这么控制的。显示屏的最下面是一层LED背光板,

    只要通上电就会发光

    在背光板上铺上一层液晶,每一小块的液晶就可以控制一个像素点

    当不给液晶施加电压,液晶就是透明的,给某一块液晶施加电压后,就不透光了,看到的就是一个小黑点,常见的LCD背光有白光、蓝光、绿光,所以大家一般看到的要么是黑点,要么是背光。控制像素点就是控制他所对应的液晶的电压高低。

    数码管只有8段,8个IO口就够了,可以用单片机直接控制,但是LCD1602有1120个像素点,1120个引脚的单片机我还没遇到,怎么办?这时候显示芯片HD44780U可以出场了。44780有80个引脚

    单片机把想要显示的东西发给HD44780U,HD44780U再来控制显示屏就可以

    所以这个HD44780U就有点像电脑的显卡了。

    LCD1602液晶屏的背面长这个样子,首先映入眼帘的就是那两个大黑点,大黑点里面封装的就是芯片,大的那个是HD44780U,小一点的那个黑点是HD44100H,他的作用后面会讲到。关于芯片的封装,大家可能都觉得芯片 就应该是哪种方形的,有引脚的哪种,其实还有一种COB的封装,就像狗皮膏药一样黏在PCB上,这种封装便宜啊。

    LCD1602一共有16个引脚,其中数据引脚又8个,控制这8个引脚的数据,就能控制液晶屏的显示内容。因为每个显示区域就35个像素,描点法也只能描出简单的图案,比如数字,字面,符号等。

    比如大些字母A,ASCII码表是0100 0001,对应的数据引脚电平就是:

    0         1         0         0         0        0        0        1

    低       高       低        低      低       低      低        高

    但是这个A在哪个区域显示呢?HD44780U里面给每个显示区域都规定的地址,这个地址就存在芯片内部的DRAM里面,

     

      这个DRAM就相当于显卡的显存了,只是大小只有80个字节,可以同时控制80个字符

     

    LCD1602最多也就能显示32个字符,HD44780U为什么能控制80个字符,因为他是通用的芯片,不是为LCD1602定制的,多的部分可以空着不用。

     后面的红色部分就是多余的地址,控制不用

     先发送显存的地址,再发送需要显示的内容,这样数据就会被保存在相应的显存里面

    比如让液晶屏的第一块显示区域显示大些字母A,就先发送第一块显示区域的地址0x00,再发送A的ASCII码0100 0001,怎么显示那就是显示芯片HD44780U的事情了。

    HD44780U的芯片管脚分布如下那些SEG和COM引脚就是控制引脚,是不是似曾相识,数码管的SEG引脚和COM引脚,原理可以说是差不多的。

     COM引脚控制行,SEG引脚控制列,如果要显示A,那就是在相应的交叉点输出不同的电压就行了

    因为不能同时控制所有行列的电压,只能用扫描的方式,一行一行的控制,是不是也似曾相识,多为数码管的动态显示也是这样的。

    扫描第一行,并输出对应的电压 

    扫描第二行并输出对应的电压

    扫描第三行并输出对应的电压

    扫描第四行并输出对应的电压 

    扫描第五行并输出对应的电压 

    扫描第六行,并输出对应的电压

    扫描第七行并输出对应的电压 

    扫描快一点,根根人眼的视觉残留,就能看到完整的A了

     HD44780U的SEG引脚只有40个,5个SEG脚才能控制一列显示区,40个SEG脚一共也只能控制8列显示区啊,LCD1602可是有16列显示区的,那另外的8列的显示区怎么控制,而且前面也说了,HD44780U能控制80个字符,现在怎么才16个。对HD44780U的显存DRAM是可以控制80个字符,但是引脚不够啊,这个时候该HD44100H出场了。

    HD44100H就是那个小一点的黑点

    它正好也有40个SEG引脚

     将HD44780U和HD44100H拼在一起不就好了

     加4个HD44100H,换一个能显示80个字符的液晶显示屏,就能显示80个字符了,HD44780U里面的DRAM就只有80个地址,只能显示80个字符。

    LCD1602相关的寄存器以及电路

     1、认识LCD

    LCD == Liquid Crystal Display ==液晶显示器

    LCD1602表示一种液晶屏,能同时显示2行16列,共32个字符,这个字符可以是字母,数字,符号等

    LCD结构上主要由3部分组成:

    液晶:液态晶体,液晶本身不发光,但他在通电的时候可以让光线透过去,不通电时光线透不过去;

    光源:这个光源才是点亮LCD的关键;

    偏光片:又上下两片,液晶就在上下偏光片之间,改变偏光片的角度就可以让光线在特定的地方透过

    上下两片偏光片有点像两个石子交叉的百叶窗,自己去脑补一下。

    2、LCD1602的管脚以及管脚功能

    管脚序号

    管脚符号

    管脚说明

    1

    VSS

    电源地,

    2

    VDD

    电源正极,是LCD1602驱动系统的电源

    3

    VO

    液晶显示对比度调整管脚,接正电源是对比度最低,接地时对比度最高,但是对比度太高,就容易看到一些不该看到的东西,俗称“鬼影”,一般在这个脚通过电阻再接地。

    4

    RS

    Register Select的缩写,字面意思就是寄存器选择;当RS=1的时候,通讯的是数据;当RS=0的时候,通讯的是命令。

    5

    R/W

    读,写选择,当R/W = 1的时候表示读LCD里面的数据,R/W = 0的时候表示往LCD里面写数据。

    6

    E

    使能信号,当E=1的时候读取信息,当E由1变为0的时候,液晶模块开始执行命令;要配合控制时序来用。

    7

    D0

    数据第0位,D0--D7是双向的数据线,对LCD模块进行读写。

    8

    D1

    数据第1位

    9

    D2

    数据第2位

    10

    D3

    数据第3位

    11

    D4

    数据第4位

    12

    D5

    数据第5位

    13

    D6

    数据第6位

    14

    D7

    数据第7位

    15

    BLA

    背光源正极,可以理解为那个背光LED的正极电源,可以直接接VDD

    16

    BLK

    背光源负极,可以理解为那个背光LED的负极电源,可以直接接VSS

    3、LCD1602 的RAM地址映射

    LCD1602能同时显示2行16列,一共32个位置,每个位置都对应着一个地址,每个地址里面可以促一个字节的字符,需要在哪个位置显示某种字符,就在他对应的地址上写入某种字符。

    下图就是这32个显示位置所对应的地址,这个地址也就是DDRAM地址;

    其实LCD1602的DDRAM一共有80个地址,依然是两行,每行40个地址,但是LCD1602一行只能同时显示16个地址的数据,剩下的24个在后面隐藏着。怎么办,只能用光标移动的方法把隐藏的部分显示出来。

    4、LCD1602的显示设置

    比如你想在第1行,第3列的位置显示个字符A,该怎么处理?

    首先确定位置,第1行第3列的地址是02,转换为2进制就是0000 0010,但是LCD1602有自己的规矩,就是写地址的时候,最高位必须是1,也就是说写进LCD的地址应该为1000 0010。

    然后确定字符,LCD1602模块里面有个字符产生器,简称CGROM(Character Generator ROM)里面存着一些常用的字模,你只需要根据地址来查询就可以了,比如字符A的地址就是0x41。

    5、LCD1602的命令列表

    6、单片机控制LCD1602电路

     

    LCD1602液晶静态显示

    程序实例1:

    1. #include //包含头文件,一般情况不需要改动,头文件包含特殊功能寄存器的定义
    2. #include
    3. sbit RS = P2^4; //定义端口
    4. sbit RW = P2^5;
    5. sbit EN = P2^6;
    6. #define RS_CLR RS=0
    7. #define RS_SET RS=1
    8. #define RW_CLR RW=0
    9. #define RW_SET RW=1
    10. #define EN_CLR EN=0
    11. #define EN_SET EN=1
    12. #define DataPort P0
    13. /*------------------------------------------------
    14. uS延时函数,含有输入参数 unsigned char t,无返回值
    15. unsigned char 是定义无符号字符变量,其值的范围是
    16. 0~255 这里使用晶振12M,精确延时请使用汇编,大致延时
    17. 长度如下 T=tx2+5 uS
    18. ------------------------------------------------*/
    19. void DelayUs2x(unsigned char t)
    20. {
    21. while(--t);
    22. }
    23. /*------------------------------------------------
    24. mS延时函数,含有输入参数 unsigned char t,无返回值
    25. unsigned char 是定义无符号字符变量,其值的范围是
    26. 0~255 这里使用晶振12M,精确延时请使用汇编
    27. ------------------------------------------------*/
    28. void DelayMs(unsigned char t)
    29. {
    30. while(t--)
    31. {
    32. //大致延时1mS
    33. DelayUs2x(245);
    34. DelayUs2x(245);
    35. }
    36. }
    37. /*------------------------------------------------
    38. 判忙函数
    39. ------------------------------------------------*/
    40. bit LCD_Check_Busy(void)
    41. {
    42. DataPort= 0xFF;
    43. RS_CLR;
    44. RW_SET;
    45. EN_CLR;
    46. _nop_();
    47. EN_SET;
    48. return (bit)(DataPort & 0x80);
    49. }
    50. /*------------------------------------------------
    51. 写入命令函数
    52. ------------------------------------------------*/
    53. void LCD_Write_Com(unsigned char com)
    54. {
    55. while(LCD_Check_Busy()); //忙则等待
    56. RS_CLR;
    57. RW_CLR;
    58. EN_SET;
    59. DataPort= com;
    60. _nop_();
    61. EN_CLR;
    62. }
    63. /*------------------------------------------------
    64. 写入数据函数
    65. ------------------------------------------------*/
    66. void LCD_Write_Data(unsigned char Data)
    67. {
    68. while(LCD_Check_Busy()); //忙则等待
    69. RS_SET;
    70. RW_CLR;
    71. EN_SET;
    72. DataPort= Data;
    73. _nop_();
    74. EN_CLR;
    75. }
    76. /*------------------------------------------------
    77. 清屏函数
    78. ------------------------------------------------*/
    79. void LCD_Clear(void)
    80. {
    81. LCD_Write_Com(0x01);
    82. DelayMs(5);
    83. }
    84. /*------------------------------------------------
    85. 写入字符串函数
    86. ------------------------------------------------*/
    87. void LCD_Write_String(unsigned char x,unsigned char y,unsigned char *s)
    88. {
    89. if (y == 0)
    90. {
    91. LCD_Write_Com(0x80 + x); //表示第一行
    92. }
    93. else
    94. {
    95. LCD_Write_Com(0xC0 + x); //表示第二行
    96. }
    97. while (*s)
    98. {
    99. LCD_Write_Data( *s);
    100. s ++;
    101. }
    102. }
    103. /*------------------------------------------------
    104. 写入字符函数
    105. ------------------------------------------------*/
    106. void LCD_Write_Char(unsigned char x,unsigned char y,unsigned char Data)
    107. {
    108. if (y == 0)
    109. {
    110. LCD_Write_Com(0x80 + x);
    111. }
    112. else
    113. {
    114. LCD_Write_Com(0xC0 + x);
    115. }
    116. LCD_Write_Data( Data);
    117. }
    118. /*------------------------------------------------
    119. 初始化函数
    120. ------------------------------------------------*/
    121. void LCD_Init(void)
    122. {
    123. LCD_Write_Com(0x38); /*显示模式设置*/
    124. DelayMs(5);
    125. LCD_Write_Com(0x38);
    126. DelayMs(5);
    127. LCD_Write_Com(0x38);
    128. DelayMs(5);
    129. LCD_Write_Com(0x38);
    130. LCD_Write_Com(0x08); /*显示关闭*/
    131. LCD_Write_Com(0x01); /*显示清屏*/
    132. LCD_Write_Com(0x06); /*显示光标移动设置*/
    133. DelayMs(5);
    134. LCD_Write_Com(0x0C); /*显示开及光标设置*/
    135. }
    136. /*------------------------------------------------
    137. 主函数
    138. ------------------------------------------------*/
    139. void main(void)
    140. {
    141. LCD_Init();
    142. LCD_Clear();//清屏
    143. while (1)
    144. {
    145. LCD_Write_Char(7,0,'o');
    146. LCD_Write_Char(8,0,'k');
    147. LCD_Write_String(1,1,"hello world!");
    148. while(1);
    149. }
    150. }

    LCD1602液晶动态显示

    程序实例2:

    1. #include //包含头文件,一般情况不需要改动,头文件包含特殊功能寄存器的定义
    2. #include
    3. sbit RS = P2^4; //定义端口
    4. sbit RW = P2^5;
    5. sbit EN = P2^6;
    6. #define RS_CLR RS=0
    7. #define RS_SET RS=1
    8. #define RW_CLR RW=0
    9. #define RW_SET RW=1
    10. #define EN_CLR EN=0
    11. #define EN_SET EN=1
    12. #define DataPort P0
    13. /*------------------------------------------------
    14. uS延时函数,含有输入参数 unsigned char t,无返回值
    15. unsigned char 是定义无符号字符变量,其值的范围是
    16. 0~255 这里使用晶振12M,精确延时请使用汇编,大致延时
    17. 长度如下 T=tx2+5 uS
    18. ------------------------------------------------*/
    19. void DelayUs2x(unsigned char t)
    20. {
    21. while(--t);
    22. }
    23. /*------------------------------------------------
    24. mS延时函数,含有输入参数 unsigned char t,无返回值
    25. unsigned char 是定义无符号字符变量,其值的范围是
    26. 0~255 这里使用晶振12M,精确延时请使用汇编
    27. ------------------------------------------------*/
    28. void DelayMs(unsigned char t)
    29. {
    30. while(t--)
    31. {
    32. //大致延时1mS
    33. DelayUs2x(245);
    34. DelayUs2x(245);
    35. }
    36. }
    37. /*------------------------------------------------
    38. 判忙函数
    39. ------------------------------------------------*/
    40. bit LCD_Check_Busy(void)
    41. {
    42. DataPort= 0xFF;
    43. RS_CLR;
    44. RW_SET;
    45. EN_CLR;
    46. _nop_();
    47. EN_SET;
    48. return (bit)(DataPort & 0x80);
    49. }
    50. /*------------------------------------------------
    51. 写入命令函数
    52. ------------------------------------------------*/
    53. void LCD_Write_Com(unsigned char com)
    54. {
    55. while(LCD_Check_Busy()); //忙则等待
    56. RS_CLR;
    57. RW_CLR;
    58. EN_SET;
    59. DataPort= com;
    60. _nop_();
    61. EN_CLR;
    62. }
    63. /*------------------------------------------------
    64. 写入数据函数
    65. ------------------------------------------------*/
    66. void LCD_Write_Data(unsigned char Data)
    67. {
    68. while(LCD_Check_Busy()); //忙则等待
    69. RS_SET;
    70. RW_CLR;
    71. EN_SET;
    72. DataPort= Data;
    73. _nop_();
    74. EN_CLR;
    75. }
    76. /*------------------------------------------------
    77. 清屏函数
    78. ------------------------------------------------*/
    79. void LCD_Clear(void)
    80. {
    81. LCD_Write_Com(0x01);
    82. DelayMs(5);
    83. }
    84. /*------------------------------------------------
    85. 写入字符串函数
    86. ------------------------------------------------*/
    87. void LCD_Write_String(unsigned char x,unsigned char y,unsigned char *s)
    88. {
    89. if (y == 0)
    90. {
    91. LCD_Write_Com(0x80 + x);
    92. }
    93. else
    94. {
    95. LCD_Write_Com(0xC0 + x);
    96. }
    97. while (*s)
    98. {
    99. LCD_Write_Data( *s);
    100. s ++;
    101. }
    102. }
    103. /*------------------------------------------------
    104. 写入字符函数
    105. ------------------------------------------------*/
    106. void LCD_Write_Char(unsigned char x,unsigned char y,unsigned char Data)
    107. {
    108. if (y == 0)
    109. {
    110. LCD_Write_Com(0x80 + x);
    111. }
    112. else
    113. {
    114. LCD_Write_Com(0xC0 + x);
    115. }
    116. LCD_Write_Data( Data);
    117. }
    118. /*------------------------------------------------
    119. 初始化函数
    120. ------------------------------------------------*/
    121. void LCD_Init(void)
    122. {
    123. LCD_Write_Com(0x38); /*显示模式设置*/
    124. DelayMs(5);
    125. LCD_Write_Com(0x38);
    126. DelayMs(5);
    127. LCD_Write_Com(0x38);
    128. DelayMs(5);
    129. LCD_Write_Com(0x38);
    130. LCD_Write_Com(0x08); /*显示关闭*/
    131. LCD_Write_Com(0x01); /*显示清屏*/
    132. LCD_Write_Com(0x06); /*显示光标移动设置*/
    133. DelayMs(5);
    134. LCD_Write_Com(0x0C); /*显示开及光标设置*/
    135. }
    136. /*------------------------------------------------
    137. 主函数
    138. ------------------------------------------------*/
    139. void main(void)
    140. {
    141. unsigned char i;
    142. unsigned char *p;
    143. LCD_Init();
    144. while (1)
    145. {
    146. i = 1;
    147. p = "hello world!";
    148. LCD_Clear();
    149. LCD_Write_String(2,0,"Welcome to");
    150. DelayMs(250);
    151. while (*p)
    152. {
    153. LCD_Write_Char(i,1,*p);
    154. i ++;
    155. p ++;
    156. DelayMs(250);
    157. }
    158. DelayMs(250);
    159. }
    160. }

    LCD1602液晶滚动显示

    程序实例3:

    1. #include //包含头文件,一般情况不需要改动,头文件包含特殊功能寄存器的定义
    2. #include
    3. sbit RS = P2^4; //定义端口
    4. sbit RW = P2^5;
    5. sbit EN = P2^6;
    6. #define RS_CLR RS=0
    7. #define RS_SET RS=1
    8. #define RW_CLR RW=0
    9. #define RW_SET RW=1
    10. #define EN_CLR EN=0
    11. #define EN_SET EN=1
    12. #define DataPort P0
    13. /*------------------------------------------------
    14. uS延时函数,含有输入参数 unsigned char t,无返回值
    15. unsigned char 是定义无符号字符变量,其值的范围是
    16. 0~255 这里使用晶振12M,精确延时请使用汇编,大致延时
    17. 长度如下 T=tx2+5 uS
    18. ------------------------------------------------*/
    19. void DelayUs2x(unsigned char t)
    20. {
    21. while(--t);
    22. }
    23. /*------------------------------------------------
    24. mS延时函数,含有输入参数 unsigned char t,无返回值
    25. unsigned char 是定义无符号字符变量,其值的范围是
    26. 0~255 这里使用晶振12M,精确延时请使用汇编
    27. ------------------------------------------------*/
    28. void DelayMs(unsigned char t)
    29. {
    30. while(t--)
    31. {
    32. //大致延时1mS
    33. DelayUs2x(245);
    34. DelayUs2x(245);
    35. }
    36. }
    37. /*------------------------------------------------
    38. 判忙函数
    39. ------------------------------------------------*/
    40. bit LCD_Check_Busy(void)
    41. {
    42. DataPort= 0xFF;
    43. RS_CLR;
    44. RW_SET;
    45. EN_CLR;
    46. _nop_();
    47. EN_SET;
    48. return (bit)(DataPort & 0x80);
    49. }
    50. /*------------------------------------------------
    51. 写入命令函数
    52. ------------------------------------------------*/
    53. void LCD_Write_Com(unsigned char com)
    54. {
    55. while(LCD_Check_Busy()); //忙则等待
    56. RS_CLR;
    57. RW_CLR;
    58. EN_SET;
    59. DataPort= com;
    60. _nop_();
    61. EN_CLR;
    62. }
    63. /*------------------------------------------------
    64. 写入数据函数
    65. ------------------------------------------------*/
    66. void LCD_Write_Data(unsigned char Data)
    67. {
    68. while(LCD_Check_Busy()); //忙则等待
    69. RS_SET;
    70. RW_CLR;
    71. EN_SET;
    72. DataPort= Data;
    73. _nop_();
    74. EN_CLR;
    75. }
    76. /*------------------------------------------------
    77. 清屏函数
    78. ------------------------------------------------*/
    79. void LCD_Clear(void)
    80. {
    81. LCD_Write_Com(0x01);
    82. DelayMs(5);
    83. }
    84. /*------------------------------------------------
    85. 写入字符串函数
    86. ------------------------------------------------*/
    87. void LCD_Write_String(unsigned char x,unsigned char y,unsigned char *s)
    88. {
    89. if (y == 0)
    90. {
    91. LCD_Write_Com(0x80 + x); //表示第一行
    92. }
    93. else
    94. {
    95. LCD_Write_Com(0xC0 + x); //表示第二行
    96. }
    97. while (*s)
    98. {
    99. LCD_Write_Data( *s);
    100. s ++;
    101. }
    102. }
    103. /*------------------------------------------------
    104. 写入字符函数
    105. ------------------------------------------------*/
    106. void LCD_Write_Char(unsigned char x,unsigned char y,unsigned char Data)
    107. {
    108. if (y == 0)
    109. {
    110. LCD_Write_Com(0x80 + x);
    111. }
    112. else
    113. {
    114. LCD_Write_Com(0xC0 + x);
    115. }
    116. LCD_Write_Data( Data);
    117. }
    118. /*------------------------------------------------
    119. 初始化函数
    120. ------------------------------------------------*/
    121. void LCD_Init(void)
    122. {
    123. LCD_Write_Com(0x38); /*显示模式设置*/
    124. DelayMs(5);
    125. LCD_Write_Com(0x38);
    126. DelayMs(5);
    127. LCD_Write_Com(0x38);
    128. DelayMs(5);
    129. LCD_Write_Com(0x38);
    130. LCD_Write_Com(0x08); /*显示关闭*/
    131. LCD_Write_Com(0x01); /*显示清屏*/
    132. LCD_Write_Com(0x06); /*显示光标移动设置*/
    133. DelayMs(5);
    134. LCD_Write_Com(0x0C); /*显示开及光标设置*/
    135. }
    136. /*------------------------------------------------
    137. 主函数
    138. ------------------------------------------------*/
    139. void main(void)
    140. {
    141. LCD_Init();
    142. LCD_Clear();//清屏
    143. LCD_Write_Char(7,0,'o');
    144. LCD_Write_Char(8,0,'k');
    145. LCD_Write_String(1,1,"hello world!");
    146. while (1)
    147. {
    148. DelayMs(200);
    149. LCD_Write_Com(0x18);//左平移画面 0x1C 是右平移
    150. }
    151. }

    LCD1602移动显示

    程序实例4:

    1. #include //包含头文件,一般情况不需要改动,头文件包含特殊功能寄存器的定义
    2. #include
    3. sbit RS = P2^4; //定义端口
    4. sbit RW = P2^5;
    5. sbit EN = P2^6;
    6. #define RS_CLR RS=0
    7. #define RS_SET RS=1
    8. #define RW_CLR RW=0
    9. #define RW_SET RW=1
    10. #define EN_CLR EN=0
    11. #define EN_SET EN=1
    12. #define DataPort P0
    13. /*------------------------------------------------
    14. uS延时函数,含有输入参数 unsigned char t,无返回值
    15. unsigned char 是定义无符号字符变量,其值的范围是
    16. 0~255 这里使用晶振12M,精确延时请使用汇编,大致延时
    17. 长度如下 T=tx2+5 uS
    18. ------------------------------------------------*/
    19. void DelayUs2x(unsigned char t)
    20. {
    21. while(--t);
    22. }
    23. /*------------------------------------------------
    24. mS延时函数,含有输入参数 unsigned char t,无返回值
    25. unsigned char 是定义无符号字符变量,其值的范围是
    26. 0~255 这里使用晶振12M,精确延时请使用汇编
    27. ------------------------------------------------*/
    28. void DelayMs(unsigned char t)
    29. {
    30. while(t--)
    31. {
    32. //大致延时1mS
    33. DelayUs2x(245);
    34. DelayUs2x(245);
    35. }
    36. }
    37. /*------------------------------------------------
    38. 判忙函数
    39. ------------------------------------------------*/
    40. bit LCD_Check_Busy(void)
    41. {
    42. DataPort= 0xFF;
    43. RS_CLR;
    44. RW_SET;
    45. EN_CLR;
    46. _nop_();
    47. EN_SET;
    48. return (bit)(DataPort & 0x80);
    49. }
    50. /*------------------------------------------------
    51. 写入命令函数
    52. ------------------------------------------------*/
    53. void LCD_Write_Com(unsigned char com)
    54. {
    55. while(LCD_Check_Busy()); //忙则等待
    56. RS_CLR;
    57. RW_CLR;
    58. EN_SET;
    59. DataPort= com;
    60. _nop_();
    61. EN_CLR;
    62. }
    63. /*------------------------------------------------
    64. 写入数据函数
    65. ------------------------------------------------*/
    66. void LCD_Write_Data(unsigned char Data)
    67. {
    68. while(LCD_Check_Busy()); //忙则等待
    69. RS_SET;
    70. RW_CLR;
    71. EN_SET;
    72. DataPort= Data;
    73. _nop_();
    74. EN_CLR;
    75. }
    76. /*------------------------------------------------
    77. 清屏函数
    78. ------------------------------------------------*/
    79. void LCD_Clear(void)
    80. {
    81. LCD_Write_Com(0x01);
    82. DelayMs(5);
    83. }
    84. /*------------------------------------------------
    85. 写入字符串函数
    86. ------------------------------------------------*/
    87. void LCD_Write_String(unsigned char x,unsigned char y,unsigned char *s)
    88. {
    89. if (y == 0)
    90. {
    91. LCD_Write_Com(0x80 + x);
    92. }
    93. else
    94. {
    95. LCD_Write_Com(0xC0 + x);
    96. }
    97. while (*s)
    98. {
    99. LCD_Write_Data( *s);
    100. s ++;
    101. }
    102. }
    103. /*------------------------------------------------
    104. 写入字符函数
    105. ------------------------------------------------*/
    106. void LCD_Write_Char(unsigned char x,unsigned char y,unsigned char Data)
    107. {
    108. if (y == 0)
    109. {
    110. LCD_Write_Com(0x80 + x);
    111. }
    112. else
    113. {
    114. LCD_Write_Com(0xC0 + x);
    115. }
    116. LCD_Write_Data( Data);
    117. }
    118. /*------------------------------------------------
    119. 初始化函数
    120. ------------------------------------------------*/
    121. void LCD_Init(void)
    122. {
    123. LCD_Write_Com(0x38); /*显示模式设置*/
    124. DelayMs(5);
    125. LCD_Write_Com(0x38);
    126. DelayMs(5);
    127. LCD_Write_Com(0x38);
    128. DelayMs(5);
    129. LCD_Write_Com(0x38);
    130. LCD_Write_Com(0x08); /*显示关闭*/
    131. LCD_Write_Com(0x01); /*显示清屏*/
    132. LCD_Write_Com(0x06); /*显示光标移动设置*/
    133. DelayMs(5);
    134. LCD_Write_Com(0x0C); /*显示开及光标设置*/
    135. }
    136. /*------------------------------------------------
    137. 主函数
    138. ------------------------------------------------*/
    139. void main(void)
    140. {
    141. unsigned char i;
    142. unsigned char *pa,*pb;
    143. LCD_Init();
    144. LCD_Write_Com(0x0f);//光标开,光标闪烁开
    145. while (1)
    146. {
    147. pa = "Welcome to";
    148. pb = "hello world!";
    149. LCD_Clear();
    150. LCD_Write_String(2,0,pa); //显示2行信息
    151. LCD_Write_String(1,1,pb);
    152. for(i=0;i<8;i++) //延时2s左右
    153. DelayMs(250);
    154. LCD_Clear(); //清屏显示其他信息
    155. i = 2;
    156. while (*pa) //循环输入方式显示2行信息
    157. {
    158. LCD_Write_Char(i,0,*pa);
    159. i ++;
    160. pa ++;
    161. DelayMs(250);
    162. }
    163. i=1;
    164. while (*pb)
    165. {
    166. LCD_Write_Char(i,1,*pb);
    167. i ++;
    168. pb ++;
    169. DelayMs(250);
    170. }
    171. DelayMs(250);
    172. }
    173. }

    LCD1602液晶按键输入显示

    程序实例5:

    1. #include //包含头文件,一般情况不需要改动,头文件包含特殊功能寄存器的定义
    2. #include
    3. sbit RS = P2^4; //定义端口
    4. sbit RW = P2^5;
    5. sbit EN = P2^6;
    6. #define RS_CLR RS=0
    7. #define RS_SET RS=1
    8. #define RW_CLR RW=0
    9. #define RW_SET RW=1
    10. #define EN_CLR EN=0
    11. #define EN_SET EN=1
    12. #define DataPort P0
    13. #define KeyPort P1
    14. unsigned char code show_code[]={'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};//转换成液晶显示的字符
    15. /*------------------------------------------------
    16. uS延时函数,含有输入参数 unsigned char t,无返回值
    17. unsigned char 是定义无符号字符变量,其值的范围是
    18. 0~255 这里使用晶振12M,精确延时请使用汇编,大致延时
    19. 长度如下 T=tx2+5 uS
    20. ------------------------------------------------*/
    21. void DelayUs2x(unsigned char t)
    22. {
    23. while(--t);
    24. }
    25. /*------------------------------------------------
    26. mS延时函数,含有输入参数 unsigned char t,无返回值
    27. unsigned char 是定义无符号字符变量,其值的范围是
    28. 0~255 这里使用晶振12M,精确延时请使用汇编
    29. ------------------------------------------------*/
    30. void DelayMs(unsigned char t)
    31. {
    32. while(t--)
    33. {
    34. //大致延时1mS
    35. DelayUs2x(245);
    36. DelayUs2x(245);
    37. }
    38. }
    39. /*------------------------------------------------
    40. 判忙函数
    41. ------------------------------------------------*/
    42. bit LCD_Check_Busy(void)
    43. {
    44. DataPort= 0xFF;
    45. RS_CLR;
    46. RW_SET;
    47. EN_CLR;
    48. _nop_();
    49. EN_SET;
    50. return (bit)(DataPort & 0x80);
    51. }
    52. /*------------------------------------------------
    53. 写入命令函数
    54. ------------------------------------------------*/
    55. void LCD_Write_Com(unsigned char com)
    56. {
    57. while(LCD_Check_Busy()); //忙则等待
    58. RS_CLR;
    59. RW_CLR;
    60. EN_SET;
    61. DataPort= com;
    62. _nop_();
    63. EN_CLR;
    64. }
    65. /*------------------------------------------------
    66. 写入数据函数
    67. ------------------------------------------------*/
    68. void LCD_Write_Data(unsigned char Data)
    69. {
    70. while(LCD_Check_Busy()); //忙则等待
    71. RS_SET;
    72. RW_CLR;
    73. EN_SET;
    74. DataPort= Data;
    75. _nop_();
    76. EN_CLR;
    77. }
    78. /*------------------------------------------------
    79. 清屏函数
    80. ------------------------------------------------*/
    81. void LCD_Clear(void)
    82. {
    83. LCD_Write_Com(0x01);
    84. DelayMs(5);
    85. }
    86. /*------------------------------------------------
    87. 写入字符串函数
    88. ------------------------------------------------*/
    89. void LCD_Write_String(unsigned char x,unsigned char y,unsigned char *s)
    90. {
    91. if (y == 0)
    92. {
    93. LCD_Write_Com(0x80 + x);
    94. }
    95. else
    96. {
    97. LCD_Write_Com(0xC0 + x);
    98. }
    99. while (*s)
    100. {
    101. LCD_Write_Data( *s);
    102. s ++;
    103. }
    104. }
    105. /*------------------------------------------------
    106. 写入字符函数
    107. ------------------------------------------------*/
    108. void LCD_Write_Char(unsigned char x,unsigned char y,unsigned char Data)
    109. {
    110. if (y == 0)
    111. {
    112. LCD_Write_Com(0x80 + x);
    113. }
    114. else
    115. {
    116. LCD_Write_Com(0xC0 + x);
    117. }
    118. LCD_Write_Data( Data);
    119. }
    120. /*------------------------------------------------
    121. 初始化函数
    122. ------------------------------------------------*/
    123. void LCD_Init(void)
    124. {
    125. LCD_Write_Com(0x38); /*显示模式设置*/
    126. DelayMs(5);
    127. LCD_Write_Com(0x38);
    128. DelayMs(5);
    129. LCD_Write_Com(0x38);
    130. DelayMs(5);
    131. LCD_Write_Com(0x38);
    132. LCD_Write_Com(0x08); /*显示关闭*/
    133. LCD_Write_Com(0x01); /*显示清屏*/
    134. LCD_Write_Com(0x06); /*显示光标移动设置*/
    135. DelayMs(5);
    136. LCD_Write_Com(0x0C); /*显示开及光标设置*/
    137. }
    138. /*------------------------------------------------
    139. 按键扫描函数,返回扫描键值
    140. ------------------------------------------------*/
    141. unsigned char KeyScan(void) //键盘扫描函数,使用行列反转扫描法
    142. {
    143. unsigned char cord_h,cord_l;//行列值中间变量
    144. KeyPort=0x0f; //行线输出全为0
    145. cord_h=KeyPort&0x0f; //读入列线值
    146. if(cord_h!=0x0f) //先检测有无按键按下
    147. {
    148. DelayMs(10); //去抖
    149. if((KeyPort&0x0f)!=0x0f)
    150. {
    151. cord_h=KeyPort&0x0f; //读入列线值
    152. KeyPort=cord_h|0xf0; //输出当前列线值
    153. cord_l=KeyPort&0xf0; //读入行线值
    154. while((KeyPort&0xf0)!=0xf0);//等待松开并输出
    155. return(cord_h+cord_l);//键盘最后组合码值
    156. }
    157. }
    158. return(0xff); //返回该值
    159. }
    160. /*------------------------------------------------
    161. 按键值处理函数,返回扫键值
    162. ------------------------------------------------*/
    163. unsigned char KeyPro(void)
    164. {
    165. switch(KeyScan())
    166. {
    167. case 0x7e:return 0;break;//0 按下相应的键显示相对应的码值
    168. case 0x7d:return 1;break;//1
    169. case 0x7b:return 2;break;//2
    170. case 0x77:return 3;break;//3
    171. case 0xbe:return 4;break;//4
    172. case 0xbd:return 5;break;//5
    173. case 0xbb:return 6;break;//6
    174. case 0xb7:return 7;break;//7
    175. case 0xde:return 8;break;//8
    176. case 0xdd:return 9;break;//9
    177. case 0xdb:return 10;break;//a
    178. case 0xd7:return 11;break;//b
    179. case 0xee:return 12;break;//c
    180. case 0xed:return 13;break;//d
    181. case 0xeb:return 14;break;//e
    182. case 0xe7:return 15;break;//f
    183. default:return 0xff;break;
    184. }
    185. }
    186. /*------------------------------------------------
    187. 主函数
    188. ------------------------------------------------*/
    189. void main(void)
    190. {
    191. unsigned char i,j,num;
    192. LCD_Init();
    193. LCD_Write_Com(0x0F);//光标开,光标闪烁开
    194. LCD_Write_String(0,0,"Press the key !");
    195. while (1)
    196. {
    197. num=KeyPro();
    198. if(num!=0xff)
    199. {
    200. if((i==0)&&(j==0))//回到第一个字符时清屏
    201. LCD_Clear();//清屏
    202. LCD_Write_Char(0+i,0+j,show_code[num]);//依次显示输入字符
    203. i++;
    204. if(i==16)//如果第一行显示满,转到第二行
    205. {
    206. i=0;j++;
    207. if(j==2)//如果2行都显示满,清屏后重新从第一行显示
    208. {
    209. j=0;
    210. }
    211. }
    212. }
    213. }
    214. }

  • 相关阅读:
    mybatis判断是否为空或null
    HDMI接口类型种类区分图(高清图)
    Qt应用开发(基础篇)——表格视图 QTableView
    “的修“报修工单管理系统有哪些功能和作用?
    C# + easyui 写的一个web项目
    奥比中光亮相全球1024开发者节,与科大讯飞达成战略合作
    Boost库学习笔记(三)内存对齐模块
    【PTA-训练day11】L2-023 图着色问题 + L1-039 古风排版
    GESP:2024-6月等级5-T1-黑白格
    C&C++volatile关键字详解
  • 原文地址:https://blog.csdn.net/m0_49968063/article/details/132795774