找回密码
 注册会员
更新自动建库工具PCB Footprint Expert 2024.04 Pro / Library Expert 破解版

自学AVR单片机二十六(LCD1602液晶显示)

[复制链接]
慧龙 发表于 2010-5-7 11:34:21 | 显示全部楼层 |阅读模式

本文包含原理图、PCB、源代码、封装库、中英文PDF等资源

您需要 登录 才可以下载或查看,没有账号?注册会员

×
LCD1602液晶是一种字符型液晶,它可以显示两行字符,每行可以显示16个字符。本实例采用深圳锦昌电子公司的JCM1602C液晶,这种液晶是HD44780的兼容电路,管脚和指令系统与HD44780完全一致。具体的使用手册可到该公司网站下载。也可以采用其他兼容HD44780的其他液晶,控制方式和程序一样。
    HD44780系列兼容液晶管脚如下图所示:
8160_1243303239JD25.jpg
一、电路实现
在本实例中,LCD1602的电路原理图如下;

8160_1243303239JD25.jpg
二、控制流程


a)端口初始化:设置单片机与LCD1602相连接的各个端口的输入输出状态以及电平状态。


b)
液晶(LCD)初始化:设置液晶显示字符前需要进行的操作,依次为:清屏、显示模式设置、显示开关控制、光标设置。主要目的是首先清除液晶屏上原来保存的数据,使液晶屏显示内容为空,然后设置液晶显示模式,接着选择是否打开液晶显示(当然要打开显示了)以及设定光标是否显示和闪烁,最后要设置每当显示一个字符后字符地址指针加一还是减一(也就是下一个字符要显示在这个字符的左边还是右边)。




c)
液晶显示字符,可以指定位置显示,也可以连续显示多个字符。


三、程序代码
lcd1602.h头文件的内容
  1. /*
  2. LCD1602.h 文件
  3. 引脚连接
  4. mcu lcd
  5. GND VSS
  6. Vcc Vcc
  7. 偏压信号,接可调电阻 VEE
  8. PG0 RS
  9. PG1 R/W
  10. PG2 E
  11. PB0 D0
  12. PB1 D1
  13. PB2 D2
  14. PB3 D3
  15. PB4 D4
  16. PB5 D5
  17. PB6 D6
  18. PB7 D7
  19. Vcc VCC
  20. GND GND
  21. */
  22. //端口位定义
  23. #define RS PG0 //数据/命令控制端 0命令,1数据
  24. #define RW PG1 //读/写选择控制端 0写,1读
  25. #define E PG2 //使能端 下降沿读,高电平写
  26. //函数声明
  27. void LCDPort_Init(void); //液晶端口初始化
  28. void LCD_Init(void); //LCD初始化
  29. void Write_Com(unsigned char LCD_Com); //LCD写指令
  30. void Write_Data_Byte(unsigned char LCD_Data); //LCD写字节数据
  31. void Write_Place_xy(unsigned char x,unsigned char y); //指定当前写字符的位置
  32. void Write_Data_String(unsigned char x,unsigned char y,unsigned char *data);
  33. //在指定的(x,y)位置上写入字符串数据
  34. void Write_Data_Char(unsigned char x,unsigned char y,unsigned char data);
  35. //在指定的(x,y)位置上写入字符数据
  36. void Check_Busy(void); //读写检测函数,每次对液晶操作前都要进行读写检测
  37. void Delayus(unsigned int lus); //us延时函数
  38. void Delayms(unsigned int lms); //ms延时函数
复制代码


lcd1602.c文件的内容

  1. /*
  2. LCD1602.c 文件
  3. */
  4. #include <AVR/io.h>
  5. #include <util/delay.h>
  6. #include "LCD1602.h"
  7. void LCDPort_Init()
  8. {      
  9. //LCD数据端口设置
  10. PORTB = 0X00;         //
  11. DDRB = 0XFF;           //配置端口PB全部为输出口,LCD数据端口

  12. //LCD控制端口设置
  13. PORTG &= ~((1 << RS) | (1 << RW) | (1 << E));         //
  14. DDRG |= (1 << RS) | (1 << RW) | (1 << E);
  15. }
  16. //LCD初始化
  17. void LCD_Init()
  18. {
  19. Write_Com(0X01);  //清屏
  20. Delayms(5);
  21. Write_Com(0X38);  //显示模式设置 16x2显示,5x7点阵,8位数据接口
  22. Delayms(5);
  23. //Write_Com(0X0f);  //显示开关控制,开显示,光标显示,光标闪烁
  24. Write_Com(0X0c);  //显示开关控制,开显示,光标不显示,光标不闪烁
  25. Delayms(5);
  26. Write_Com(0X06);  //光标设置,读或写一个字符后,地址指针加一,光标加一,整屏不移动
  27. Delayms(5);
  28. }
  29. //LCD写指令
  30. void Write_Com(unsigned char LCD_Com)
  31. {
  32. Check_Busy();

  33. PORTG &= ~(1 << RS);     //RS=0,写命令
  34. PORTG &= ~(1 << RW);     //RW=0,写指令
  35. PORTG |= (1 << E);       //E=1,写操作
  36. Delayms(15);
  37. PORTB = LCD_Com;         //指令送数据端口
  38. PORTG &= ~(1 << E);     //E=0,停止写操作
  39. Delayms(15);
  40. }
  41. //LCD写字节数据
  42. void Write_Data_Byte(unsigned char LCD_Data)
  43. {
  44. Check_Busy();
  45. PORTG |= (1 << RS);      //RS=1,写数据
  46. PORTG &= ~(1 << RW);    //RW=0,写指令
  47. PORTG |= (1 << E);      //E=1,写操作
  48. Delayms(15);  
  49. PORTB = LCD_Data;        // 数据送数据端口   
  50. PORTG &= ~(1 << E);    //E=0,停止写操作
  51. Delayms(15);
  52. }
  53. //指定当前写字符的位置  
  54. void Write_Place_xy(unsigned char x,unsigned char y)
  55. {
  56. unsigned char address;
  57. if(y == 0)                   //行位置
  58. {
  59.   address = 0x80 + x;      //列位置,
  60. }
  61. else
  62. {
  63.   address = 0x80 + 0x40 + x;  //
  64. }
  65. Write_Com(address);          //写地址
  66. }
  67. //在指定的(x,y)位置上写入字符串数据
  68. void Write_Data_String(unsigned char x,unsigned char y,unsigned char *data)
  69. {
  70. Write_Place_xy(x,y);    //写地址
  71. while(*data)
  72. {
  73.   Write_Data_Byte(*data);        //写字符串
  74.   data++;                //指针地址加1
  75. }
  76. }
  77.                                          
  78. //在指定的(x,y)位置上写入字符数据  x列位置,y行位置        
  79. void Write_Data_Char(unsigned char x,unsigned char y,unsigned char data)
  80. {
  81. Write_Place_xy(x,y);           //
  82. Write_Data_Byte(data);          //
  83. }                                         
  84. //读写检测函数,每次对液晶操作前都要进行读写检测
  85. void Check_Busy()
  86. {     
  87. DDRB = 0X00;             //PB口置为输入口,准备读取数据
  88. PORTG &= ~(1 << RS);      //RS=0,读命令
  89. PORTG |= (1 << RW);    //RW=1,读指令
  90. PORTG |= (1 << E);      //E=1,使能

  91. while(0X80 & PINB);   //监测忙信号,直到忙信号为0,才能进行读写操作
  92. PORTG &= ~(1 << E);   //E=0
  93. DDRB = 0XFF;          //PB口置为输出口,准备向端口发送数据
  94. }
  95. //us级别的延时函数
  96. void Delayus(unsigned int lus)
  97. {
  98. while(lus--)
  99. {
  100.   _delay_loop_2(4);      //_delay_loop_2(1)是延时4个时钟周期,参数为4则延时16
  101.              //个时钟周期,本实验用16M晶体,则16个时钟周期为16/16=1us
  102.     }
  103. }
  104. //ms级别的延时函数
  105. void Delayms(unsigned int lms)
  106. {
  107. while(lms--)
  108. {
  109.   Delayus(1000);        //延时1ms
  110.     }
  111. }

复制代码



主程序文件

  1. //头文件包含
  2. #include <avr/io.h>        //io端口寄存器配置文件,必须包含
  3. #include <util/delay.h>       //GCC中的延时函数头文件
  4. #include "LCD1602.h"
  5. //全局变量声明
  6. unsigned char LCD_DispBuff1[]="Let's study AVR";
  7. unsigned char LCD_DispBuff2[]=" WWW.LT430.COM";
  8. int main(void)            
  9. {
  10.     unsigned char Disp_Number;
  11.    
  12. LCDPort_Init();   //端口初始化
  13. LCD_Init();    //LCD初始化

  14. //在任意位置处显示字符
  15. //Write_Com(0X80+0X05);   //发送字符显示位置指令。0x05可以换成00-0f,40-4f之间的任意值
  16. //Write_Data_Byte('a');        //发送要显示的字符

  17. /*
  18. //下面这段程序演示在LCD上显示两行字符
  19. Write_Com(0X80+0X00);                       //指定写数据的位置,从第一行第0列开始
  20. for(Disp_Number = 0;Disp_Number < 15;Disp_Number++)
  21. {
  22.   Write_Data_Byte(LCD_DispBuff1[Disp_Number]);   //写入要显示的数据
  23.   _delay_ms(5);                            //一定要延时一会,因为液晶的速度比较慢
  24. }
  25. Write_Com(0X80+0X40);                       //指定写数据的位置,第二行第0列开始
  26. for(Disp_Number = 0;Disp_Number < 14;Disp_Number++)
  27. {
  28.   Write_Data_Byte(LCD_DispBuff2[Disp_Number]);  //写入要显示的数据
  29.   _delay_ms(5);
  30. }
  31. */


  32. //下面这段程序演示在LCD上显示两行字符,字符从屏幕右边移动到屏幕左边
  33. /*
  34. Write_Com(0X80+0X10);                                //指定写数据的位置,第一行第17个字符开始
  35. for(Disp_Number = 0;Disp_Number < 15;Disp_Number++)
  36. {
  37.   Write_Data_Byte(LCD_DispBuff1[Disp_Number]);         //写入要显示的数据
  38.   _delay_ms(5);
  39. }
  40. Write_Com(0X80+0X50);                                //指定写数据的位置,第二行第17个字符开始
  41. for(Disp_Number = 0;Disp_Number < 14;Disp_Number++)
  42. {
  43.   Write_Data_Byte(LCD_DispBuff2[Disp_Number]);    //写入要显示的数据
  44.   _delay_ms(5);
  45. }
  46. for(Disp_Number = 0;Disp_Number < 16;Disp_Number++)
  47. {
  48.   Write_Com(0X18);                 //发送数据移位指令,移动16位
  49.   _delay_ms(200);
  50. }
  51. */

  52. Write_Data_String(1,0,"LCD1602 DEMO");      //在第一行第1列开始显示
  53. Write_Data_String(0,1,"Welcome to here!");   //在第二行第0列开始显示
  54. Write_Data_Char(14,0,'a');                   //在第一行,第14列显示一个字符

  55. while(1)
  56. {
  57.   
  58. }
  59. }
复制代码
kevintang 发表于 2010-7-24 11:57:21 | 显示全部楼层
谢谢提供.................................
*滑块验证:
您需要登录后才可以回帖 登录 | 注册会员

本版积分规则

QQ|手机版|MCU资讯论坛 ( 京ICP备18035221号-2 )|网站地图

GMT+8, 2024-12-23 13:40 , Processed in 0.058851 second(s), 11 queries , Redis On.

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表