带I2C的LCD1602液晶显示51单片机程序
实现功能:液晶屏上显示日期及动态时间,由中断函数来实现时间的动态变换
#include <reg52.h>//头文件 #include <intrins.h> #define uint unsigned int #define uchar unsigned char #define C51_SCL P3^0 //SCL引脚 #define C51_SDA P3^1 //SDA引脚 #define ADDR 0X4E //设备地址 #define String_len1 16 //液晶显示第一行字符串长度 #define String_len2 16 //液晶显示第二行字符串长度 uchar miao,shi,fen; //显示时分秒 uchar count; /*******************************************/ sbit SCL = C51_SCL; //I2C串口 sbit SDA = C51_SDA; //I2C串口 uchar code table[]="21-7-30 "; //LCD初始化显示内容 uchar code table1[]="23:59:45 "; /*********************延时函数*************************************/ static void delay_us() { ;; //用两个空语句实现短时间延时,当晶振为11.0592MHz时,约4~5微秒 } void delay(uchar n) { int i,j; for(i=0;i<n;i++) for(j=0;j<120;j++); } /**********************************************/ /************IIC协议的起始信号*****************/ void IIC_Start() { SDA=1; SCL=1; delay_us(); SDA=0; delay_us(); } /** IIC协议的应答信号 * @param None * @retval None */ void IIC_Ack() { uchar i; SCL=1; delay_us(); while((SDA==1)&&(i<250))i++; SCL=0; delay_us(); } /** * @brief 写入一个字节到I2C总线 * @param date:将要被写入的数据 * @retval None */ void IIC_Write_Byte(uchar date) { uchar i,temp; temp=date; for(i=0;i<8;i++) { temp=temp<<1; SCL=0; delay_us(); SDA=CY; delay_us(); SCL=1; delay_us(); } SCL=0; delay_us(); SDA=1; delay_us(); } /** * @brief 通过IIC协议写一个命令到1602液晶上 * @param comm:将要被写入的命令 * @retval None */ void IIC_Write_Comm_LCD(uchar comm) { uchar data_h = comm & 0xf0; uchar data_l = (comm & 0x0f) << 4; IIC_Write_Byte(0x00+data_h); IIC_Ack(); IIC_Write_Byte(0x04+data_h); IIC_Ack(); IIC_Write_Byte(0x00+data_h); IIC_Ack(); delay(5); IIC_Write_Byte(0x00+data_l); IIC_Ack(); IIC_Write_Byte(0x04+data_l); IIC_Ack(); IIC_Write_Byte(0x00+data_l); IIC_Ack(); delay(5); } /** * @brief 通过IIC写一个数据到1602液晶上 * @param date:将要被写入的数据 * @retval None */ void IIC_Write_Date_LCD(uchar date) { uchar data_h = date & 0xf0; uchar data_l = (date & 0x0f) << 4; IIC_Write_Byte(0x01+data_h); IIC_Ack(); IIC_Write_Byte(0x05+data_h); IIC_Ack(); IIC_Write_Byte(0x01+data_h); IIC_Ack(); delay(5); IIC_Write_Byte(0x01+data_l); IIC_Ack(); IIC_Write_Byte(0x05+data_l); IIC_Ack(); IIC_Write_Byte(0x01+data_l); IIC_Ack(); delay(5); } /********************************************************/ /** * @brief 初始化1602液晶,由于只有一个设备,所以一直占用总线 * @param None * @retval None */ /***********************1602程序初始化函数*************************************/ void LCD1602_Init() { uchar i = 0; IIC_Start(); IIC_Write_Byte(ADDR); IIC_Ack(); IIC_Write_Comm_LCD(0x02); //设置四线发送数据 IIC_Write_Comm_LCD(0x28); //设置显示模式 IIC_Write_Comm_LCD(0x08); //显示关闭 IIC_Write_Comm_LCD(0x0c); //设置光标开关 IIC_Write_Comm_LCD(0x06); //设置光标移动 IIC_Write_Comm_LCD(0x01); //清屏 for(i=0;i<String_len1;i++) //显示预先设定值 { IIC_Write_Date_LCD(table[i]); } IIC_Write_Comm_LCD(0xc0); for(i=0;i<String_len2;i++) { IIC_Write_Date_LCD(table1[i]); } TMOD=0x01; //定时器 TH0=(65536-50000)/256; TL0=(65536-50000)%256; EA=1; ET0=1; TR0=1; } /**********************显示时分**********************************/ void write_sfm(uchar add,uchar date) { uchar shi,ge; shi=date/10; ge=date%10; IIC_Write_Comm_LCD(0x80+0x40+add); IIC_Write_Date_LCD(0x30+shi); IIC_Write_Date_LCD(0x30+ge); } /*******************主函数***********************************/ void main() { LCD1602_Init();//LCD1602初始化程序 while(1); } /**************************中断程序**************************/ void timer0() interrupt 1//实现时分秒的动态变换 { TH0=(65536-50000)/256; TL0=(65536-50000)%256; count++; if(count==18) { count=0; miao++; if(miao==60) { miao=0; fen++; if(fen==60) { fen=0; shi++; if(shi==24) { shi=0; } write_sfm(0,shi);//待修改液晶屏的地址及数据 } write_sfm(3,fen); } write_sfm(6,miao); } }