当前位置:首页 > 单片机 > 单片机
[导读] AVR单片机万年历程序//***************************FileName:RTC.C************************////***************************ICCAVRV6.30编译**********************//#include//寄存器定义文件#includ

AVR单片机万年历程序

//***************************FileName:RTC.C************************//


//***************************ICCAVRV6.30编译**********************//

#include//寄存器定义文件
#include//使用到宏
#defineucharunsignedchar//数据类型定义
#defineuintunsignedchar//数据类型定义
#defineSD23030x64//SD2303器件IIC识别码


ucharTable[12]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x38,0x76};
//显示数据表0123456789LH
ucharData[4]={0,0,0,0};//DS1722
ucharEnter_Flag;//确定
ucharF_Flag;//数据应答标志

voidDelayMs(uinti)//延时函数1
{ucharj;
for(;i!=0;i--)
{for(j=2000;j!=0;j--){;}}
}

voidDisplay(uchar*p)//显示函数
{uchari,sel=0x00;
for(i=0;i<16;i++)
{PORTC=sel;
PORTA=Table[p[i]];
DelayMs(10);
sel=sel<<1;
}
}


voidNOPNOP(uchari)//延时函数2
{for(;i!=0;i--)NOP();}

voidSetSCL(uchari)//IIC时钟线SCL设置
{if(i==1)PORTB=PORTB|0x01;
elsePORTB=PORTB&0xFE;}

voidSetSDA(uchari)//IIC数据线SDA设置
{if(i==1)PORTB=PORTB|0x02;
elsePORTB=PORTB&0xFD;}

//SCL=PB^0;SD2303时钟线
//SDA=PB^1;SD2303数据线
//INTRB=PB^3;SD2303中断线A
//INTRA=PB^2;SD2303中断线B

voidStart()//IIC总线开始信号
{SetSDA(1);
SetSCL(1);
NOPNOP(50);
SetSDA(0);
NOPNOP(50);
SetSCL(0);
}

voidStop()//IIC总线停止信号
{SetSDA(0);
SetSCL(1);
NOPNOP(50);
SetSDA(1);
NOPNOP(50);
SetSCL(0);
}

voidAck()//单片机应答信号
{SetSDA(0);
SetSCL(1);
NOPNOP(50);
SetSCL(0);
SetSDA(1);
}

voidNack()//单片机非应答信号
{SetSDA(1);
SetSCL(1);
NOPNOP(50);
SetSCL(0);
SetSDA(0);
}

voidCheck_Ack()//器件应答信号检查
{SetSDA(1);
SetSCL(1);
F_Flag=0;
DDRB=DDRB&0xFD;
if((PINB&0x02)==0)
{SetSCL(0);
NOPNOP(50);}
else
{F_Flag=1;
SetSCL(0);
NOPNOP(50);}
DDRB=DDRB|0x02;
}

voidWrite_Bit0()//向IIC总线写0
{SetSDA(0);
SetSCL(1);
NOPNOP(50);
SetSCL(0);
}

voidWrite_Bit1()//向IIC总线写1
{SetSDA(1);
SetSCL(1);
NOPNOP(50);
SetSCL(0);
SetSDA(0);
}

voidWrite_Byte(ucharData)//向IIC总线写一字节数据
{uchari;
for(i=0;i<8;i++)
{if((Data&0x80)>0)
Write_Bit1();
else
Write_Bit0();
Data<<=1;
}
}


ucharRead_Byte()//从IIC总线读一字节数据
{ucharnn=0xff;
ucharj;
for(j=0;j<8;j++)
{SetSDA(1);
SetSCL(1);
DDRB=DDRB&0xFB;

if((PINB&0x02)==0)
{nn<<=1;
nn=(nn&0xfe);
SetSCL(0);}
else
{nn<<=1;
nn=(nn|0x01);
SetSCL(0);}
}
DDRB=DDRB|0x02;
return(nn);
}

//****************************写N个字节子程序**********************//
//函数参数说明:
//Slave:IIC器件地址,如上文定义的SD2303
//Address:起始地址
//Array:读数据存放的数组
//Number:读取的字节数
voidWrite_Nbyte(ucharSlave,ucharAddress,uchar*Array,ucharNumber)
{uchark;
writ:do//开始->写IIC器件地址->检查应答位
{Start();
Write_Byte(Slave);
Check_Ack();
}while(F_Flag==1);
do
{Write_Byte(Address<<4);//送起始地址->检查应答位
Check_Ack();
}while(F_Flag==1);
for(k=0;k{Write_Byte(*Array);
Array++;
Check_Ack();}//检查应答位
Stop();
}

//****************************写一个字节子程序**********************//
//函数参数说明:
//Slave:IIC器件地址,如上文定义的SD2303
//Address:IIC器件寄存器地址
//Data:数据
voidWrite_1byte(ucharSlave,ucharAddress,ucharData)
{writ:do//开始->写IIC器件地址->检查应答位
{Start();
Write_Byte(Slave);
Check_Ack();
}while(F_Flag==1);
do
{Write_Byte(Address<<4);//送起始地址->检查应答位
Check_Ack();
}while(F_Flag==1);
Write_Byte(Data);
Check_Ack();//检查应答位
Stop();//停止信号
}


//***************************读N个字节子程序***********************//
//函数参数说明:
//Slave:IIC器件地址,如上文定义的SD2303
//Address:起始地址
//Array:读数据存放的数组
//Number:读取的字节数
voidRead_Nbyte(ucharSlave,ucharAddress,uchar*Array,ucharNumber)
{uchardata0,x;
//第一步:开始信号->写IIC器件地址->检查应答位
do{Start();Write_Byte(Slave);Check_Ack();}while(F_Flag==1);
//第二步:写起始地址->检查应答位
do{Write_Byte(Address<<4);Check_Ack();}while(F_Flag==1);
//第三步:开始信号->写IIC器件地址+1(表示读)->检查应答位
do{Start();Write_Byte(Slave+1);Check_Ack();}while(F_Flag==1);
//第四步:读N字节,每读完一字节发一个Ack应答,最后一字节发Nack
for(x=0;x{data0=Read_Byte();*Array=data0;Array++;
if(x<(Number-1)){Ack();}}
Nack();
//第五步:发停止信号,结束读操作
Stop();
}

//***************************按键处理程序**************************//
//说明:为简化程序设计,此程序不保证输入的时间数据的合理性。
voidKey_Process(void)
{uchartemp1[17]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
//输入数据格式依次为年、月、日、星期、小时和分钟
uchartemp2[7]={0,0,0,0,0,0,0,};
ucharteMP3[3]={0,0,0xff};
//输入数据格式依次为小时和分钟
ucharKey;
uchar*Flag;
uchari;
Flag=temp1;
if(PIND!=0xff)
{DelayMs(20);//延时去抖
if(PIND!=0xff)
Key=PINB;
if(Key==0xfe)//"时间设置"键按下
{temp1[0]|=0x80;//年高位设置提示
while(!Enter_Flag)//直到按下确定键方停止
{for(i=0;i<50;i++)
Display(temp1);//显示和延时
Key=~PIND;
switch(Key)
{case0x04://"+"键处理
(*Flag)++;
if(((*Flag)&0x7f)==10)*Flag=0|0x80;
break;
case0x08://"-"键处理
if(((*Flag)&0x7f)==0)*Flag=10|0x80;
(*Flag)--;
break;
case0x10://"下一位"键处理
Flag++;
(*(Flag-1))&=0x7f;//上一位去掉小数点显示
(*Flag)|=0x80;//当前位加上小数点显示
if(Flag==temp1+13)
{Flag=temp1;
(*Flag)|=0x80;
(*(Flag+13))&=0x7f;}
break;
case0x20://"上一位"键处理
if(Flag==temp1)
{(*Flag)&=0x7f;
Flag=temp1+13;
(*Flag)|=0x80;}
elseFlag--;
(*Flag)|=0x80;//当前位加上小数点显示
(*(Flag+1))&=0x7f;//下一位去掉点小数点显示
break;
case0x40:Enter_Flag=1;break;//"确定"键处理
//case0x80:Enter_Flag=1;break;//测试用
default:break;}

}
Enter_Flag=0;//按键状态恢复
temp2[0]=0x00;//秒,默认从00开始计时
temp2[1]=(temp1[11]<<4)|temp1[12];//分
temp2[2]=(temp1[9]<<4)|temp1[10];//时
temp2[3]=temp1[8];//周
temp2[4]=(temp1[6]<<4)|temp1[7];//日
temp2[5]=(temp1[4]<<4)|temp1[5];//月
temp2[6]=(temp1[2]<<4)|temp1[3];//年
Write_Nbyte(SD2303,0x00,temp2,7);//初始化设定时间
}
if(Key==0xfd)//"闹铃设置"键按下
{temp1[9]|=0x80;
Flag=temp1+9;//定时小时高位设置提示
while(!Enter_Flag)//直到按下确定键方停止
{for(i=0;i<50;i++)
Display(temp1);
Key=~PINB;
switch(Key)
{case0x04://"+"按键处理
(*Flag)++;
if(((*Flag)&0x7f)==10)*Flag=0|0x80;
break;
case0x08://"-"按键处理
if(((*Flag)&0x7f)==0)*Flag=10|0x80;
(*Flag)--;
break;
case0x10://"下一位"按键处理
Flag++;
(*(Flag-1))&=0x7f;//上一位去掉小数点显示
(*Flag)|=0x80;//当前位加上小数点显示
if(Flag==temp1+13)
{(*Flag)&=0x7f;
Flag=temp1+9;
(*Flag)|=0x80;}
break;
case0x20://"上一位"按键处理
if(Flag==temp1+9)
{(*Flag)&=0x7f;
Flag=temp1+13;
(*Flag)|=0x80;}
elseFlag--;
(*Flag)|=0x80;//当前位加上小数点显示
(*(Flag+1))&=0x7f;//下一位去掉小数点显示
break;
case0x40:Enter_Flag=1;break;//"确定"键处理
//case0x80:Enter_Flag=1;break;//测试用
default:break;}

}
Enter_Flag=0;
temp3[0]=((temp1[11]<<4)|temp1[12])&0x7f;//分数据处理,去掉小数点
temp3[1]=((temp1[9]<<4)|temp1[10])&0x7f;//时数据处理,去掉小数点
if((temp3[0]<0x60)&&(temp3[1]<0x24))//判断是否为合法时间
{Write_1byte(SD2303,0x0e,0b10110000);//开启闹铃使能
Write_1byte(SD2303,0x0f,0b00101000);//开始中断使能
Write_Nbyte(SD2303,0x08,temp3,3);}//初始化闹铃设置
else
Write_1byte(SD2303,0x0e,0b00110000);//取消闹铃功能
}
}
}


//***************************DS1722函数开始************************//

voidConvert(ucharp1,uchar*p2)
{uchartemp;
if(p1&0x80)
{p2[13]=10;//零下温度用10表示
p1=0xff-p1;}//温度绝对值
else
p2[13]=11;//零上温度用11表示
p2[14]=p1/10;//温度十位
p2[15]=p1-p2[14]*10;//温度个位
}

//***************************通过SPI接口写数据函数*****************//
//函数参数说明:
//Address:DS1722寄存器地址
//Data:写入的数据
voidDSWrite_Byte(ucharAddress,ucharData)
{ucharclear;
PORTB=PORTB|0x10;//使能SPI器件
SPDR=Address;
while(!(SPSR&0x80)){;}
clear=SPSR;
clear=SPDR;
SPDR=Data;
while(!(SPSR&0x80)){;}
clear=SPSR;
clear=SPDR;
PORTB=PORTB&0xef;
}


//***************************通过SPI接口读数据函数*****************//
//函数参数说明:
//Address:DS1722寄存器地址
//返回值:读取的温度数据
ucharDSRead_Byte(ucharAddress)
{ucharclear;
ucharData;
PORTB=PORTB|0x10;
SPDR=Address;
while(!(SPSR&0x80)){;}
clear=SPSR;
clear=SPDR;
SPDR=Address;//发空数据
while(!(SPSR&0x80)){;}
clear=SPSR;
Data=SPDR;
PORTB=PORTB&0xef;
return(Data);
}

voidmain(void)
{uchari;
uchartime[16]={2,0,0,4,1,2,2,7,1,1,7,3,0,0,0,0};
ucharSet_Time[7]={0x50,0x30,0x20,0x03,0x05,0x01,0x05};
//初始化时间2005-01-05Wed20-30-50
ucharSD,DS;
ucharSD2303_Controller1=0x00;//禁止中断
ucharSD2303_Controller2=0x20;//时间格式:24小时制
DDRA=0xff;//A口输出
DDRC=0xff;//C口输出
DDRD=0x80;//D口最高位输出,其他带上拉输入
PORTD=0x7F;
DDRB=0xF3;//B口带第2、3位带上拉输入,其他输出
PORTB=0xF3;
Write_1byte(SD2303,0x0e,SD2303_Controller1);//写控制字
Write_1byte(SD2303,0x0f,SD2303_Controller2);//写控制字
Write_Nbyte(SD2303,0x00,Set_Time,7);//初始化时间
SPCR=0b01011100;
DSWrite_Byte(0x80,0xf0);//DS17228位分辨率自由转换模式
while(1)
{Key_Process();//按键处理
Read_Nbyte(SD2303,0x00,Set_Time,7);//读取时间
time[2]=Set_Time[6]>>4;//年高位;
time[3]=Set_Time[6]&0x0f;//年低位;
time[4]=Set_Time[5]>>4;//月高位;
time[5]=Set_Time[5]&0x0f;//月低位;
time[6]=Set_Time[4]>>4;//日高位;
time[7]=Set_Time[4]&0x0f;//日低位;
time[8]=Set_Time[3];//星期;
time[9]=Set_Time[2]>>4;//时高位;
time[10]=Set_Time[2]&0x0f;//时低位;
time[11]=Set_Time[1]>>4;//分高位;
time[12]=Set_Time[1]&0x0f;//分低位;
time[13]=Set_Time[0]>>4;//秒高位;
time[14]=Set_Time[0]&0x0f;//秒低位;
Read_Nbyte(SD2303,0x0f,&SD,1);//读取中断标志位
if(SD&0x02)PORTD=PORTD|0x80;//响铃1分钟
elsePORTD=PORTD&0x7F;//关闭闹铃
DS=DSRead_Byte(0x02);//读取温度值
Convert(DS,time);
Display(time);//时间显示
}
}

本站声明: 本文章由作者或相关机构授权发布,目的在于传递更多信息,并不代表本站赞同其观点,本站亦不保证或承诺内容真实性等。需要转载请联系该专栏作者,如若文章内容侵犯您的权益,请及时联系本站删除。
换一批
延伸阅读

该系列产品有助于嵌入式设计人员在更广泛的系统中轻松实现USB功能

关键字: 单片机 嵌入式设计 USB

单片机编程语言是程序员与微控制器进行交流的桥梁,它们构成了单片机系统的软件开发基石,决定着如何有效、高效地控制和管理单片机的各项资源。随着微控制器技术的不断发展,针对不同应用场景的需求,形成了丰富多样的编程语言体系。本文...

关键字: 单片机 微控制器

单片机,全称为“单片微型计算机”或“微控制器”(Microcontroller Unit,简称MCU),是一种高度集成化的电子器件,它是现代科技领域的关键组件,尤其在自动化控制、物联网、消费电子、汽车电子、工业控制等领域...

关键字: 单片机 MCU

STM32是由意法半导体公司(STMicroelectronics)推出的基于ARM Cortex-M内核的32位微控制器系列,以其高性能、低功耗、丰富的外设接口和强大的生态系统深受广大嵌入式开发者喜爱。本文将详细介绍S...

关键字: STM32 单片机

在当前的科技浪潮中,单片机作为嵌入式系统的重要组成部分,正以其强大的功能和广泛的应用领域受到越来越多行业的青睐。在众多单片机中,W79E2051以其卓越的性能和稳定的工作特性,成为市场上的明星产品。本文将深入探讨W79E...

关键字: 单片机 w79e2051单片机

单片机,又称为微控制器或微处理器,是现代电子设备中的核心部件之一。它集成了中央处理器、存储器、输入输出接口等电路,通过外部信号引脚与外部设备进行通信,实现对设备的控制和管理。本文将详细介绍单片机的外部信号引脚名称及其功能...

关键字: 单片机 微控制器 中央处理器

随着科技的飞速发展,单片机和嵌入式系统在现代电子设备中的应用越来越广泛。它们不仅提高了设备的智能化水平,还推动了各行各业的创新与发展。在单片机和嵌入式系统的开发中,编程语言的选择至关重要。本文将深入探讨单片机和嵌入式系统...

关键字: 单片机 嵌入式系统 电子设备

PLC(可编程逻辑控制器)和单片机是两种不同的控制设备,它们之间存在明显的区别:

关键字: 单片机 plc 控制器

Holtek隆重推出全新一代32-bit Arm® Cortex®-M0+ 5V CAN MCU - HT32F53231/HT32F53241/HT32F53242/HT32F53252。这一系列单片机带有来自Bosc...

关键字: MCU 工业自动化 单片机

Holtek精益求精,宣布推出全新5V宽电压Arm® Cortex®-M0+ 32-bit MCU系列HT32F50431/HT32F50441/HT32F50442/HT32F50452。此系列MCU经多方位升级能满...

关键字: 单片机 智能家居 工业控制
关闭
关闭