Lcd_delay1ms();}/*********************************************函数功能:
判断液晶模块的忙碌状态
返回值:
result。
result=1,忙碌丁esult=O,不忙
*********************************************/
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的显示模式进行初始化设置******************/1K1Tx。
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);//清屏幕指令,将以前的显示内容清除
图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为电子时钟程序设计流程图。
MdGY。
图7.1.2电子时钟程序设计流程图
2、温度测量模块
温度测量程序主要包括主程序,读出温度子程序,温度转换子程序,计算温度子程序,显示
数据子程序等。
主程序的主要功能是负责温度的实时显示、读出并处理DS18B20的测量的当前温度值,温
度测量每1s进行一次。
这样可以在一秒之内测量一次被测温度,其系统程序流程见图7.2.1
所示。
RD40S
3、红外遥控解码模块
(1)遥控器发射端程序流程图:
[匸戶序斤升女台]
I±_--十氐电〒月打-
口MtS
£
IW幷x^r彳氐半
I鬥工月氷沖违十蚁
>:
*I』■-
兀」屁功台旨巫呈序
(二)程序源代码
1、实时时钟模块
/*************DSi302
#include
#include
#include
#defineuintunsignedint
#defineucharunsignedchar
//变量定义
sbitSCLK=P1A4;
sbitDATA_IO=P1A5;
sbitRESET=P1A6;
sbitACC0=ACCA0;
sbitACC7=ACCA7;
uchartable1[16];
uchartable2[16];
ucharsecond,minute,hour,day,month,year;〃定义秒分时日月年变量/*********DS1302寸寸钟部分子程^序****************************/
//向DS1302写入一个字节的函数
时寸钟显示程^序**********************/
//DS1302时钟控制总线
//DS1302数据传送总线
//DS1302复位总线
〃移位时的第0位
〃移位时的第7位
ivjYT。
PeuzH。
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:
要写的数据DSE4d。
{RESET=0;//复位引脚为低电平所有数据传送中止
SCLK=0;//清时钟总线
RESET=1;〃复位引脚为高电平逻辑控制有效
delay(10);
SentByte(Address);//写入地址命令
SentByte(Data);//写入1字节数据
SCLK=1;〃时钟总线置高
RESET=0;//逻辑操作完毕,清复位总线
}
//读取DS1302某地址的数据
ucharReadClock(ucharAddress)//Address:
要读取数据的DS1302地址NptBl。
{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:
00WriteClock(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码转换成十进制数据GGFaO
ReadValue=ReadClock(0x83);
if(ReadValue>0x60)
ReadValue=ReadClock(0x83);
minute=((ReadValue&0x70)>>4)*10+(ReadValue&0x0F);//将读取的分数据的BCD码转换成十进制数据rDczK。
ReadValue=ReadClock(0x85);
if(ReadValue>0x24)
ReadValue=ReadClock(0x85);
hour=((ReadValue&0x70)>>4)*10+(ReadValue&0x0F);//将读取的时数据的BCD码转换成十进制数据16KBJ。
ReadValue=ReadClock(0x87);day=((ReadValue&0x70)>>4)*10+(ReadValue&0x0F);//将读取的日数据的BCD码转换成十进制数据YcjtR。
ReadValue=ReadClock(0x89);
month=((ReadValue&0x70)>>4)*10+(ReadValue&0x0F);//将读取的月数据的BCD码转换成十进制数据lvdkY。
ReadValue=ReadClock(0x8d);
year=((ReadValue&0xf0)>>4)*10+(ReadValue&0x0F);//将读取的年数据的BCD码转
换成十进制数据vwTxL。
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()
1个字
1个字
{uinti;
Lcd_WriteAddress(0x00);//设置显示位置为第一行的第
for(i=0;i<16;i++)//显示字符
{Lcd_WriteData(table1[i]);
delay(10);}
Lcd_WriteAddress(0x40);//设置显示位置为第二行的第
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
#defineuintunsignedint
sbitDQ=P1A7;//DS18B20与单片机连接口
unsignedchara,b;
uinttvalue;//温度值
uchardisdata[12];
voiddelay_18B20(unsignedinti)//延时1微秒
{while(i--);
_nop_();
_nop_();
}
voiddelay1ms(uintm)//延时m毫秒
{while(m--)
delay_18B20(1000);
}
voidDS18B20rst()/*ds18b20复位*/
{DQ=1;//DQ复位
delay_18B20(10);//延时
DQ=0;//DQ拉低
delay_18B20(600);
DQ=1;//拉高
_nop_();
_nop_();
while(DQ);
_nop_();
_nop_();
while(~DQ);
_nop_();
}
ucharDS18B20rd()/*读数据*/
{unsignedchari;
unsignedchardat;
DQ=1;
for(i=8;i>0;i--)
{dat>>=1;
DQ=0;//给脉冲信号
_nop_();
_nop_();
_nop_();
_nop_();
DQ=1;//给脉冲信号delay_18B20(5);if(DQ){dat|=0x80;}delay_18B20(50);}return(dat);
}
voidDS18B20wr(ucharwdata)/*写数据*/{unsignedchard;
inti;
DQ=1;
for(i=8;i>0;i--)
{d=wdata&0x01;
wdata>>=1;
if(d)
{DQ=0;delay_18B20
(2);
DQ=1;
delay_18B20(60);}
else
{DQ=0;delay_18B20(60);
DQ=1;
_nop_();
_nop_();}
}
}
read_temp()/*读取温度值并转换*/
{DS18B20rst();
DS18B20wr(0xcc);//*跳过读序列号*/DS18B20wr(0x44);//*启动温度转换*/delay1ms(30);
DS18B20rst();
DS18B20wr(0xcc);//*跳过读序列号*/
DS18B20wr(0xbe);//*读取温度*/a=DS18B20rd();
b=DS18B20rd();tvalue=b;
tvalue=tvalue<<8;tvalue=tvalue|a;
if(tvalue&0x8000)tvalue=~tvalue+1;
tvalue=tvalue*(0.625);return(tvalue);
}
voidDS18B20disp()//温度值显示
{uinti;
disdata[0]='T';disdata[1]='e';
disdata[2]='m';disdata[3]='p';disdata[4]='t';disdata[5]=':
';
disdata[6]=(int)tvalue/1000+0x30;//百位数disdata[7]=(int)(tvalue%1000)/100+0x30;//十位数disdata[8]=(int)(tvalue%100)/10+0x30;//个位数disdata[9]='.';
disdata[10]=(int)tvalue%10+0x30;//小数位disdata[11]='C';
Lcd_WriteAddress(0x40);//设置显示位置为第二行