Lcd_delay1ms();}
/*********************************************
函数功能:
判断液晶模块的忙碌状态
返回值:
result。
result=1,忙碌;result=0,不忙
*********************************************/
bitLcd_BusyTest(void)
{bitresult;
RS=0;//根据规定,RS为低电平,RW为高电平时,可以读状态
RW=1;
E=1;//E=1,才允许读写
_nop_();//空操作
_nop_();
_nop_();
_nop_();//空操作四个机器周期,给硬件反应时间
result=BF;//将忙碌标志电平赋给result
E=0;
returnresult;}
/*********************************************
函数功能:
将模式设置指令或显示地址写入液晶模块
入口参数:
dictate
*********************************************/
voidLcd_WriteCom(unsignedchardictate)
{while(Lcd_BusyTest()==1);//忙就等待
RS=0;//根据规定,RS和RW同时为低电平时,可以写入指令
RW=0;
E=0;//E置低电平(写指令时,就是让E从0到1发生正跳变,所以应先置"0"
_nop_();
_nop_();//空操作两个机器周期,给硬件反应时间
LCD_Data=dictate;
_nop_();
_nop_();
_nop_();
_nop_();//空操作四个机器周期,给硬件反应时间
E=1;//E置高电平
_nop_();
_nop_();
_nop_();
_nop_();//空操作四个机器周期,给硬件反应时间
E=0;//当E由高电平跳变成低电平时,液晶模块开始执行命令
}
/*********************************************
函数功能:
指定字符显示的实际地址
入口参数:
x
注:
此函数已经加上了0x80,故只需写上实际地址就行
*********************************************/
voidLcd_WriteAddress(unsignedcharx)
{Lcd_WriteCom(x|0x80);//显示位置的确定方法规定为"80H+地址码x"
}
/*********************************************
函数功能:
将数据(字符的标准ASCII码)写入液晶模块
入口参数:
y(为字符常量)
*********************************************/
voidLcd_WriteData(unsignedchary)
{while(Lcd_BusyTest()==1);
RS=1;//RS为高电平,RW为低电平时,可以写入数据
RW=0;
E=0;//E置低电平(写指令时,就是让E从0到1发生正跳变,所以应先置"0"
LCD_Data=y;//将数据送入P0口,即将数据写入液晶模块
_nop_();
_nop_();
_nop_();
_nop_();//空操作四个机器周期,给硬件反应时间
E=1;//E置高电平
_nop_();
_nop_();
_nop_();
_nop_();//空操作四个机器周期,给硬件反应时间
E=0;//当E由高电平跳变成低电平时,液晶模块开始执行命令
}
/**********函数功能:
对LCD的显示模式进行初始化设置******************/
voidLcd_Int(void)
{Lcd_delay(15);//延时15ms,首次写指令时应给LCD一段较长的反应时间
Lcd_WriteCom(0x38);//显示模式设置:
16*2显示,5*7点阵,8位数据接口
Lcd_delay(5);//延时5ms
Lcd_WriteCom(0x38);
Lcd_delay(5);
Lcd_WriteCom(0x38);//3次写设置模式
Lcd_delay(5);
Lcd_WriteCom(0x0C);//显示模式设置:
显示开,有光标,光标不闪烁
Lcd_delay(5);
Lcd_WriteCom(0x06);//显示模式设置:
光标右移,字符不移
Lcd_delay(5);
Lcd_WriteCom(0x01);//清屏幕指令,将以前的显示内容清除
Lcd_delay(5);}
/*****************函数功能:
LCD的显示********************/
voidhuanying_show(void)
{unsignedintLcd_i;
Lcd_WriteCom(0x01);//清显示:
清屏幕指令
Lcd_delay
(1);
Lcd_WriteAddress(0x00);//设置显示位置为第一行的第1个字
Lcd_delay
(1);
for(Lcd_i=0;Lcd_i<16;Lcd_i++)//显示字符LIUJING
{Lcd_WriteData(string1[Lcd_i]);
Lcd_delay(150);}
Lcd_WriteAddress(0x40);//设置显示位置为第二行的第1个字
for(Lcd_i=0;Lcd_i<16;Lcd_i++)//显示字符080104020013
{Lcd_WriteData(string2[Lcd_i]);
Lcd_delay(150);}
Lcd_delay(1000);
}
//右侧移位进来
voiddongtai_show(void)
{unsignedintLcd_i;
Lcd_WriteCom(0x01);//清显示:
清屏幕指令
Lcd_delay
(2);
Lcd_WriteAddress(0x10);//设置显示位置为最右侧
Lcd_delay
(2);
for(Lcd_i=0;Lcd_i<16;Lcd_i++)//显示字符LIUJING
{Lcd_WriteData(string1[Lcd_i]);
Lcd_delay
(2);}
Lcd_WriteAddress(0x50);//设置显示位置为最右侧
for(Lcd_i=0;Lcd_i<16;Lcd_i++)//显示字符080104020013
{Lcd_WriteData(string2[Lcd_i]);
Lcd_delay
(2);}
for(Lcd_i=0;Lcd_i<16;Lcd_i++)//开始左移
{Lcd_WriteCom(0x18);//左移指令
Lcd_delay(400);}
Lcd_delay(1000);
Lcd_WriteCom(0x08);
Lcd_delay(400);
Lcd_WriteCom(0x0c);
Lcd_delay(400);
Lcd_WriteCom(0x08);
Lcd_delay(400);
Lcd_WriteCom(0x0c);
Lcd_delay(400);
Lcd_WriteCom(0x08);
Lcd_delay(400);
Lcd_WriteCom(0x0c);
Lcd_delay(400);
Lcd_WriteCom(0x08);
Lcd_delay(400);
Lcd_WriteCom(0x0c);
Lcd_delay
(1);
Lcd_WriteCom(0x01);//清显示:
清屏幕指令
Lcd_delay
(1);
}
七、实时时钟、温度测量、红外遥控解码等程序的流程图、程序源代码
(一)流程图
1、实时时钟模块
图7.1.1为电子时钟设计框图,系统由主控制器STC12C5A60S2、时钟电路DS1302、显示电路LCD1602及键扫描电路组成。
电子万年历的程序主要包括3个方面的内容:
一是DS1302从单片机中读取数据进行计数,二是利用按键进行时间的调整,三是MAX7219从单片机中读取数据驱动LED数码管显示时间。
图7.1.1电子时钟设计框图
STC12C5A60S2单片机主要I/O口的分配,P1.4、P1.5、P1.6分别接DS1302的SCLK,MCUIO,RST端,P0口接LCD1602八位数据口,P2.7、P3.6、P3.7分别接LCD1602的E、RW、RS端,P2.0-P2.3分别接按键K1-K4.下图7.1.2为电子时钟程序设计流程图。
图7.1.2电子时钟程序设计流程图
2、温度测量模块
温度测量程序主要包括主程序,读出温度子程序,温度转换子程序,计算温度子程序,显示数据子程序等。
主程序的主要功能是负责温度的实时显示、读出并处理DS18B20的测量的当前温度值,温度测量每1s进行一次。
这样可以在一秒之内测量一次被测温度,其系统程序流程见图7.2.1所示。
图7.2.1温度测量主程序流程图
图7.2.2读温度流程图
3、红外遥控解码模块
(1)遥控器发射端程序流程图:
(2)遥控器接收端程序流程图:
(二)程序源代码
1、实时时钟模块
/*************DS1302时钟显示程序**********************/
#include
#include
#include
#defineuintunsignedint
#defineucharunsignedchar
//变量定义
sbitSCLK=P1^4;//DS1302时钟控制总线
sbitDATA_IO=P1^5;//DS1302数据传送总线
sbitRESET=P1^6;//DS1302复位总线
sbitACC0=ACC^0;//移位时的第0位
sbitACC7=ACC^7;//移位时的第7位
uchartable1[16];
uchartable2[16];
ucharsecond,minute,hour,day,month,year;//定义秒分时日月年变量
/*********DS1302时钟部分子程序****************************/
//向DS1302写入一个字节的函数
voidSentByte(ucharbyte)
{uchari;
ACC=byte;
for(i=8;i>0;i--)//相当于汇编中的RRC
{DATA_IO=ACC0;//将自己的最低位传到时钟的数据总线上
SCLK=1;//时钟上升沿发送数据有效
SCLK=0;//清时钟总线
ACC=ACC>>1;//将累加器中的数据右移1位
}
}
//从DS1302读取一个字节函数
ucharReceiveByte(void)
{uchari;
for(i=8;i>0;i--)//相当于汇编中的RRC
{ACC=ACC>>1;//将累加器中的数据右移1位
ACC7=DATA_IO;//将数据线上的1位数据存入累加器中
SCLK=1;//时钟上升沿发送数据有效
SCLK=0;//清时钟总线
}
return(ACC);//函数最终返回读取的1字节数据
}
//向DS1302的某个地址里写入数据函数
voidWriteClock(ucharAddress,ucharData)//Address:
要写入数据的DS1302地址;Data:
要写的数据
{RESET=0;//复位引脚为低电平所有数据传送中止
SCLK=0;//清时钟总线
RESET=1;//复位引脚为高电平逻辑控制有效
delay(10);
SentByte(Address);//写入地址命令
SentByte(Data);//写入1字节数据
SCLK=1;//时钟总线置高
RESET=0;//逻辑操作完毕,清复位总线
}
//读取DS1302某地址的数据
ucharReadClock(ucharAddress)//Address:
要读取数据的DS1302地址
{ucharData;//定义数据变量
RESET=0;//复位引脚为低电平所有数据传送终止
SCLK=0;//清时钟总线
RESET=1;//复位引脚为高电平逻辑控制有效
delay
(1);
SentByte(Address|0X01);//写入地址命令,读取地址为写入地址+1H
Data=ReceiveByte();//读取1字节数据
SCLK=1;//时钟总线置高
RESET=0;//逻辑操作完毕,清复位总线
return(Data);//返回读取的数据
}
//时钟芯片初始化函数
voidInit_Clock(void)
{ucharSecond=ReadClock(0x81);//读取秒数据
if(Second&0x80)//判断时钟芯片是否关闭
{WriteClock(0x8e,0x00);//写入允许
WriteClock(0x8c,0x11);//一下写入初始化时间11年11月25日15:
05:
00
WriteClock(0x88,0x11);
WriteClock(0x86,0x25);
WriteClock(0x84,0x15);
WriteClock(0x82,0x05);
WriteClock(0x80,0x00);
WriteClock(0x8e,0x80);//禁止写入
}
}
voidRead_Date(void)
{ucharReadValue;//定义变量
ReadValue=ReadClock(0x81);
second=((ReadValue&0x70)>>4)*10+(ReadValue&0x0F);//将读取的秒数据的BCD码转换成十进制数据
ReadValue=ReadClock(0x83);
if(ReadValue>0x60)
ReadValue=ReadClock(0x83);
minute=((ReadValue&0x70)>>4)*10+(ReadValue&0x0F);//将读取的分数据的BCD码转换成十进制数据
ReadValue=ReadClock(0x85);
if(ReadValue>0x24)
ReadValue=ReadClock(0x85);
hour=((ReadValue&0x70)>>4)*10+(ReadValue&0x0F);//将读取的时数据的BCD码转换成十进制数据
ReadValue=ReadClock(0x87);
day=((ReadValue&0x70)>>4)*10+(ReadValue&0x0F);//将读取的日数据的BCD码转换成十进制数据
ReadValue=ReadClock(0x89);
month=((ReadValue&0x70)>>4)*10+(ReadValue&0x0F);//将读取的月数据的BCD码转换成十进制数据
ReadValue=ReadClock(0x8d);
year=((ReadValue&0xf0)>>4)*10+(ReadValue&0x0F);//将读取的年数据的BCD码转换成十进制数据
table1[0]='D';
table1[1]='a';
table1[2]='t';
table1[3]='a';
table1[4]=':
';
table1[5]='2';
table1[6]='0';
table1[7]=0x30+year/10;
table1[8]=0x30+year%10;
table1[9]='-';
table1[10]=0x30+month/10;
table1[11]=0x30+month%10;
table1[12]='-';
table1[13]=0x30+day/10;
table1[14]=0x30+day%10;
table1[15]='';
table2[0]='';
table2[1]='';
table2[2]='';
table2[3]='';
table2[4]=0x30+hour/10;
table2[5]=0x30+hour%10;
table2[6]=':
';
table2[7]=0x30+minute/10;
table2[8]=0x30+minute%10;
table2[9]=':
';
table2[10]=0x30+second/10;
table2[11]=0x30+second%10;
table2[12]='';
table2[13]='';
table2[14]='';
table2[15]='';
}
//时钟显示函数
voidshow_Data()
{uinti;
Lcd_WriteAddress(0x00);//设置显示位置为第一行的第1个字
for(i=0;i<16;i++)//显示字符
{Lcd_WriteData(table1[i]);
delay(10);}
Lcd_WriteAddress(0x40);//设置显示位置为第二行的第1个字
for(i=0;i<16;i++)//显示字符
{Lcd_WriteData(table2[i]);
delay(10);}
}
voidmain()
{Lcd_Int();//1602初始化
huanying_show();
Lcd_WriteCom(0x01);
Init_Clock();//将1302初始化
while
(1)
{Read_Date();
show_Data();}
}
2、温度测量模块
/*********DS18B29温度显示程序**********************/
#include
#include
#include
#defineucharunsignedchar
#defineuin