历史上的今天
返回首页

历史上的今天

今天是:2025年01月13日(星期一)

正在发生

2020年01月13日 | 基于AVR单片机的万年历程序设计

2020-01-13 来源:eefocus

AVR单片机万年历程序

基于AVR单片机的万年历程序设计

基于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);//时间显示

}

}

推荐阅读

史海拾趣

Grande Electronics Ltd公司的发展小趣事
确保遥控器中的电池电量充足,避免电池电量不足导致的发射问题。
DFI公司的发展小趣事

近年来,随着智能医疗和金融科技等新兴领域的兴起,DFI看到了新的发展机遇。公司开始将这些领域作为重点发展方向,投入大量资源进行研发和创新。通过与合作伙伴的紧密合作,DFI成功推出了一系列具有创新性的智能医疗和金融科技产品。这些产品不仅为客户提供了更便捷、更高效的服务体验,也为DFI带来了新的增长点。随着这些新兴领域的不断发展壮大,DFI有望在未来实现更大的突破和发展。

请注意,以上故事均为虚构,旨在展示DFI公司可能的发展历程和业务活动。实际情况可能有所不同,具体信息请参考DFI公司的官方资料。

Electrocube Inc公司的发展小趣事

在稳固国内市场的同时,Electrocube Inc公司积极开拓国际市场。公司参加了多个国际电子展会,与全球知名电子企业建立了广泛的合作关系。通过不断的市场拓展,Electrocube Inc公司的产品已经远销欧美、亚洲等多个国家和地区,实现了跨越式的发展。

AAT [Advanced Analog Technology, Inc.]公司的发展小趣事

Electrocube Inc公司的创始人在创立之初便面临着重重挑战。当时,电子行业正处于快速发展阶段,市场竞争激烈。然而,创始人凭借对电子技术的深刻理解和敏锐的市场洞察力,成功开发出了一款高性能、低成本的电容器产品。这款产品迅速获得了市场的认可,为公司赢得了第一桶金,也为后续的发展奠定了坚实的基础。

Esterline Technologies Corporation公司的发展小趣事

在稳固国内市场的同时,Electrocube Inc公司积极开拓国际市场。公司参加了多个国际电子展会,与全球知名电子企业建立了广泛的合作关系。通过不断的市场拓展,Electrocube Inc公司的产品已经远销欧美、亚洲等多个国家和地区,实现了跨越式的发展。

启珑(CHIPLON)公司的发展小趣事

在稳固国内市场的同时,Electrocube Inc公司积极开拓国际市场。公司参加了多个国际电子展会,与全球知名电子企业建立了广泛的合作关系。通过不断的市场拓展,Electrocube Inc公司的产品已经远销欧美、亚洲等多个国家和地区,实现了跨越式的发展。

问答坊 | AI 解惑

哪位有epm3128ATC100的脚图啊,可以发我吗?

哪位有epm3128ATC100的脚图啊,可以发我吗?cuitjxg@126.com多谢了!…

查看全部问答>

wiggler-jtag的原理及电路板!!!可直接使用的!!!

除了wiggler-jtag的原理及电路板外,还有三款不同的JTAG电路板!!! Protell版本的!!!!!…

查看全部问答>

这里有电子收银机方面的专家吗??

这里有电子收银机方面的专家吗??…

查看全部问答>

请教一个DDS的问题

本帖最后由 paulhyde 于 2014-9-15 09:26 编辑 在DDS设计中,要求实现VPP的幅度调整,看过一些资料是用产生波形的DA的输出接在ad0832的VREF端,我有几个问题不是很清楚: 1、这样的连接方法,是不是对DA的速度没有要求?就是说信号的频率高于DA的 ...…

查看全部问答>

pda短信程序问题!!!

硬件:熊猫pm828c无线网卡+Pocket PC 软件:vs2005+Windows Mobile SDK for Pocket PC   做短信收发程序时,出现Error:无法找到PInvoke DLL\"cemapi.dll\"的入口点\"#20\". 这是什么原因? 谢谢!!!…

查看全部问答>

从单片机初学者迈向单片机工程师!回复 kobe1941 一个不错的资料

这个 是很久前一个斑竹给我的,再次上传希望大家看看。 惭愧的是我最近才仔细的看这个资料 后悔莫及啊。。。。。。 简单介绍: 释放CPU 模块化 键盘 LED 。。、 。。 让你跳出演示实验!!跳出LED的地狱。。。。 其实学习了才知道,一 ...…

查看全部问答>

一个PN结的场效应管

目前,MOS工艺的绝缘栅场效应管由于其优越的性能在分立元件和集成电路方面都得到了广泛的应用。由其结构可以看出,目前的场效应管是在沟道的两端各扩散一个PN结,形成一种PN结背靠背连接的结构。 以P型衬底N沟道增强型场效应管为例,在电路中,源 ...…

查看全部问答>

【连载】【ALIENTEK 战舰STM32开发板】STM32开发指南--第六十章 UCOSII实验3-消息...

第六十章 UCOSII实验3-消息队列、信号量集和软件定时器 上一章,我们学习了UCOSII的信号量和邮箱的使用,本章,我们将学习消息队列、信号量集和软件定时器的使用。本章分为如下几个部分:60.1 UCOSII消息队列、信号量集和软件定时器简介60.2 硬件 ...…

查看全部问答>