一、系统方案
1、本设计采用51单片机作为主控器。
2、DS1302采集年月日时分秒送到液晶12864显示。
3、按键年月日时分秒,两路闹钟。
二、硬件设计
原理图如下:
三、单片机软件设计
1、首先是系统初始化
uchar clock_time[6] = {0X00,0X59,0X23,0X09,0X04,0X11}; //定义时间变量 秒 分 时 日 月 年
uchar alarm_time[2] = { 10, 6}; //闹钟设置 alarm_time[0]: 分钟 alarm_time[1] :小时
uchar alarm_time2[2] = { 15, 7};
Lcd_Initial(); //LCD初始化
Clock_Fresh( clock_time ); //我把时间刷新放在这里,proteus会调用当前系统时间,
Clock_Initial( clock_time ); //时钟初试化
/***********************中断初始化***************************/
EA = 1; //开总中断
ET0 = 1; //Timer0 开中断
TMOD = 0x01; //Timer0 工作方式 1
TH0 = 0x3c;
TL0 = 0XB0; //延时 50 ms
2、液晶显示程序
void showXY(uchar row,uchar col,uchar x,uchar y,uchar tab){
uchar i,j;
bit right;
if(col<64){right=0;}
else {col-=64;right=1;}
for(i=0;i<y;i++){
if(right)cs1=1,cs2=0;
else cs1=0,cs2=1;
Lcd_Write_Command(addX0+row+i);
Lcd_Write_Command(addY0+col);
for(j=0;j<x;j++){
if(col+j<64)Lcd_Write_Byte(tab[ix+j]);
else if(right0)
{
cs1=1,cs2=0;
Lcd_Write_Command(addX0+row+i);
Lcd_Write_Command(addY0+(col+j-64));
Lcd_Write_Byte(tab[ix+j]);
}
}
}
}
/ 返回一个8*16字符索引位置 /
uchar enN(uchar s){
uchar i;
for(i=0;zm8x16_index[i]!=0;i++)
if(zm8x16_index[i]==s[0])break;
return i;
}
/ 返回一个1616字符索引位置 */
uchar cnN(uchar *s){
uchar i;
for(i=0;zm16x16_index[i]!=0;i+=2)
if(zm16x16_index[i]s&&zm16x16_index[i+1]==(s+1))break ;
return i/2;
}
/* 显示中英文字符串 /
void showStr(uchar row,uchar col,uchar s)
{
uchar i;
for(i=0;s[i]!=0;i++){
if(s[i]<0x80){
showXY(row,col,8,2,zm8x16_Table[enN(&s[i])]);
col+=8;
}else{
showXY(row,col,16,2,zm16x16_Table[cnN(&s[i])]);
col+=16;i+=1;
}
if(col>120)
{
col=0;
row+=2;
}
}
}
3、按键程序
/******************************************************************************************
- 函数名称:Key_Idle()
- 功 能:键盘松开
- 入口参数:无
- 出口参数:无
*********************************************************************************************/
void Key_Idle()
{
while( ( P1 & 0x0f ) != 0x0f );
}
/********************************************************************************************
-
函数名称:Key_Scan()
-
功 能:键盘扫描
-
入口参数:无
-
出口参数:键值
*********************************************************************************************/
uchar Key_Scan()
{
if( ( P1 & 0x0f ) != 0x0f ) //判断按键
{
Delay(10); //消除抖动
// Lcd_Initial();
if( ( P1 & 0x0f ) != 0x0f )
{
switch ( P1 & 0x0f ) //将按键码转换成键值
{
case 0x0e: return up_array;
case 0x0d: return down_array;
case 0x0b: return clear_array;
case 0x07: return function_array;
default : return null;
}
}
}
return null;
}
4、核心算法程序
void main( void )
{
uchar clock_time[6] = {0X00,0X59,0X23,0X09,0X04,0X11}; //定义时间变量 秒 分 时 日 月 年
uchar alarm_time[2] = { 10, 6}; //闹钟设置 alarm_time[0]: 分钟 alarm_time[1] :小时
uchar alarm_time2[2] = { 15, 7};
Lcd_Initial(); //LCD初始化
Clock_Fresh( clock_time ); //我把时间刷新放在这里,proteus会调用当前系统时间,
Clock_Initial( clock_time ); //时钟初试化/中断初始化****/
EA = 1; //开总中断
ET0 = 1; //Timer0 开中断
TMOD = 0x01; //Timer0 工作方式 1
TH0 = 0x3c;
TL0 = 0XB0; //延时 50 mswhile( 1 )
{{ Clock_Fresh( clock_time ); //时间刷新 Lcd_Clock( clock_time ); //时间显示 Calendar_Convert( 0 , clock_time ); Week_Convert( 0, clock_time ); //闹钟1报警 if( * alarm_time == HexNum_Convert(* ( clock_time + 1 ) )) //分钟相吻合 if( * ( alarm_time + 1 ) == HexNum_Convert(*( clock_time + 2 )) ) //小时相吻合 { if(HexNum_Convert(*( clock_time )) == 2) TR0 = 1; //启动Timer0 } //闹钟2报警 if( * alarm_time2 == HexNum_Convert(* ( clock_time + 1 ) )) //分钟相吻合 if( * ( alarm_time2 + 1 ) == HexNum_Convert(*( clock_time + 2 )) ) //小时相吻合 { if(HexNum_Convert(*( clock_time )) == 2) TR0 = 1; //启动Timer0 } } switch( Key_Scan() ) { case up_array: { //Lcd_Initial(); Key_Idle(); } break; case down_array: { // Lcd_Initial(); Key_Idle(); } break; case clear_array: { // Lcd_Initial(); Key_Idle(); } break; case function_array: { //Lcd_Initial(); Key_Function( clock_time, alarm_time ,alarm_time2); } break; case null: break; }
}
}
四、 proteus仿真设计
Proteus软件是一款应用比较广泛的工具,它可以在没有硬件平台的基础上通过自身的软件仿真出硬件平台的运行情况,这样就可以通过软件仿真来验证我们设计的方案有没有问题,如果有问题,可以重新选择器件,连接器件,直到达到我们设定的目的,避免我们搭建实物的时候,如果当初选择的方案有问题,我们器件都已经焊接好了,再去卸载下去,再去焊接新的方案的器件,测试,这样会浪费人力和物力,也给开发者带来一定困惑,Proteus仿真软件就很好的解决这个问题,我们在设计之初,就使用该软件进行模拟仿真,测试,选择满足我们设计的最优方案。最后根据测试没问题的仿真图纸,焊接实物,调试,最终完成本设计的作品。