litong 发表于 2024-5-1 09:09:06

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

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

一、电路实现
在本实例中,LCD1602的电路原理图如下;

二、控制流程

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

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



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


三、程序代码
lcd1602.h头文件的内容
/*LCD1602.h 文件引脚连接mcu lcdGND VSSVcc Vcc偏压信号,接可调电阻 VEEPG0 RSPG1 R/WPG2 EPB0 D0PB1 D1PB2 D2PB3 D3PB4 D4PB5 D5PB6 D6 PB7 D7Vcc VCCGND GND*///端口位定义#define RS PG0 //数据/命令控制端 0命令,1数据#define RW PG1 //读/写选择控制端 0写,1读#define E PG2 //使能端 下降沿读,高电平写//函数声明void LCDPort_Init(void); //液晶端口初始化void LCD_Init(void); //LCD初始化void Write_Com(unsigned char LCD_Com); //LCD写指令void Write_Data_Byte(unsigned char LCD_Data); //LCD写字节数据void Write_Place_xy(unsigned char x,unsigned char y); //指定当前写字符的位置void Write_Data_String(unsigned char x,unsigned char y,unsigned char *data); //在指定的(x,y)位置上写入字符串数据void Write_Data_Char(unsigned char x,unsigned char y,unsigned char data);//在指定的(x,y)位置上写入字符数据void Check_Busy(void); //读写检测函数,每次对液晶操作前都要进行读写检测void Delayus(unsigned int lus); //us延时函数void Delayms(unsigned int lms); //ms延时函数

lcd1602.c文件的内容
/*LCD1602.c 文件*/#include <AVR/io.h>#include <util/delay.h>#include "LCD1602.h"void LCDPort_Init(){      //LCD数据端口设置PORTB = 0X00;         //DDRB = 0XFF;         //配置端口PB全部为输出口,LCD数据端口//LCD控制端口设置PORTG &= ~((1 << RS) | (1 << RW) | (1 << E));         //DDRG |= (1 << RS) | (1 << RW) | (1 << E); }//LCD初始化void LCD_Init(){Write_Com(0X01);//清屏Delayms(5);Write_Com(0X38);//显示模式设置 16x2显示,5x7点阵,8位数据接口Delayms(5);//Write_Com(0X0f);//显示开关控制,开显示,光标显示,光标闪烁Write_Com(0X0c);//显示开关控制,开显示,光标不显示,光标不闪烁Delayms(5);Write_Com(0X06);//光标设置,读或写一个字符后,地址指针加一,光标加一,整屏不移动Delayms(5);}//LCD写指令void Write_Com(unsigned char LCD_Com){Check_Busy();PORTG &= ~(1 << RS);   //RS=0,写命令PORTG &= ~(1 << RW);   //RW=0,写指令PORTG |= (1 << E);       //E=1,写操作Delayms(15);PORTB = LCD_Com;         //指令送数据端口PORTG &= ~(1 << E);   //E=0,停止写操作Delayms(15); }//LCD写字节数据void Write_Data_Byte(unsigned char LCD_Data){Check_Busy();PORTG |= (1 << RS);      //RS=1,写数据PORTG &= ~(1 << RW);    //RW=0,写指令PORTG |= (1 << E);      //E=1,写操作Delayms(15);PORTB = LCD_Data;      // 数据送数据端口   PORTG &= ~(1 << E);    //E=0,停止写操作Delayms(15); }//指定当前写字符的位置void Write_Place_xy(unsigned char x,unsigned char y) {unsigned char address;if(y == 0)                   //行位置{address = 0x80 + x;      //列位置,}else{address = 0x80 + 0x40 + x;//}Write_Com(address);          //写地址}//在指定的(x,y)位置上写入字符串数据void Write_Data_String(unsigned char x,unsigned char y,unsigned char *data) {Write_Place_xy(x,y);    //写地址while(*data){Write_Data_Byte(*data);      //写字符串data++;                //指针地址加1}}                                       //在指定的(x,y)位置上写入字符数据x列位置,y行位置      void Write_Data_Char(unsigned char x,unsigned char y,unsigned char data){Write_Place_xy(x,y);         //Write_Data_Byte(data);          //}                                       //读写检测函数,每次对液晶操作前都要进行读写检测void Check_Busy(){   DDRB = 0X00;             //PB口置为输入口,准备读取数据PORTG &= ~(1 << RS);      //RS=0,读命令PORTG |= (1 << RW);    //RW=1,读指令PORTG |= (1 << E);      //E=1,使能while(0X80 & PINB);   //监测忙信号,直到忙信号为0,才能进行读写操作PORTG &= ~(1 << E);   //E=0DDRB = 0XFF;          //PB口置为输出口,准备向端口发送数据}//us级别的延时函数void Delayus(unsigned int lus){while(lus--){_delay_loop_2(4);      //_delay_loop_2(1)是延时4个时钟周期,参数为4则延时16             //个时钟周期,本实验用16M晶体,则16个时钟周期为16/16=1us    }}//ms级别的延时函数void Delayms(unsigned int lms){while(lms--){Delayus(1000);      //延时1ms    }}


主程序文件
//头文件包含#include <avr/io.h>      //io端口寄存器配置文件,必须包含#include <util/delay.h>       //GCC中的延时函数头文件#include "LCD1602.h"//全局变量声明unsigned char LCD_DispBuff1[]="Let's study AVR";unsigned char LCD_DispBuff2[]=" WWW.LT430.COM";int main(void)            {    unsigned char Disp_Number;   LCDPort_Init();   //端口初始化LCD_Init();    //LCD初始化//在任意位置处显示字符//Write_Com(0X80+0X05);   //发送字符显示位置指令。0x05可以换成00-0f,40-4f之间的任意值//Write_Data_Byte('a');      //发送要显示的字符/*//下面这段程序演示在LCD上显示两行字符Write_Com(0X80+0X00);                     //指定写数据的位置,从第一行第0列开始for(Disp_Number = 0;Disp_Number < 15;Disp_Number++){Write_Data_Byte(LCD_DispBuff1);   //写入要显示的数据_delay_ms(5);                            //一定要延时一会,因为液晶的速度比较慢}Write_Com(0X80+0X40);                     //指定写数据的位置,第二行第0列开始for(Disp_Number = 0;Disp_Number < 14;Disp_Number++){Write_Data_Byte(LCD_DispBuff2);//写入要显示的数据_delay_ms(5);}*///下面这段程序演示在LCD上显示两行字符,字符从屏幕右边移动到屏幕左边/*Write_Com(0X80+0X10);                              //指定写数据的位置,第一行第17个字符开始for(Disp_Number = 0;Disp_Number < 15;Disp_Number++){Write_Data_Byte(LCD_DispBuff1);         //写入要显示的数据_delay_ms(5);}Write_Com(0X80+0X50);                              //指定写数据的位置,第二行第17个字符开始for(Disp_Number = 0;Disp_Number < 14;Disp_Number++){Write_Data_Byte(LCD_DispBuff2);    //写入要显示的数据_delay_ms(5);}for(Disp_Number = 0;Disp_Number < 16;Disp_Number++){Write_Com(0X18);               //发送数据移位指令,移动16位_delay_ms(200);}*/Write_Data_String(1,0,"LCD1602 DEMO");      //在第一行第1列开始显示Write_Data_String(0,1,"Welcome to here!");   //在第二行第0列开始显示Write_Data_Char(14,0,'a');                   //在第一行,第14列显示一个字符while(1){}}

ohicerebag 发表于 2024-5-1 09:09:33

谢谢提供.................................
页: [1]
查看完整版本: 自学AVR单片机二十六(LCD1602液晶显示)