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

2020-01-13来源: eefocus关键字:AVR  单片机  万年历程序

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;//时

[1] [2]
关键字:AVR  单片机  万年历程序 编辑:什么鱼 引用地址:http://news.kanmaya.com/mcu/ic485496.html 如意彩_[官网首页]本网站转载的所有的文章、图片、音频视频文件等资料的版权归版权所有人所有,本站采用的非本站原创文章及图片等内容无法一一联系确认版权者。如果本网所选内容的文章作者及编辑认为其作品不宜公开自由传播,或不应无偿使用,请及时通过电子邮件或电话通知我们,以迅速采取适当措施,避免给双方造成不必要的经济损失。

上一篇:解决AVR单片机烧写过程中弄错熔丝位而造成无法读写问题
下一篇:如何解决AVR单片机上电复位工作混乱的问题

关注eeworld公众号 快捷获取更多信息
关注eeworld公众号
快捷获取更多信息
关注eeworld服务号 享受更多官方福利
关注eeworld服务号
享受更多官方福利

推荐阅读

AVR单片机控制继电器吸合与断开的仿真设计
继电器(Relay),作用是用弱电控制强电。比如,我们用avr单片控制一个220V电压的灯泡,这就必须用到继电器。本课用avr单片机来控制继电器的吸合与断开。Proteus仿真实验器件:1 atmega128一块2 button,按键一个3 relay,通用继电器一个,并把继电器的Component Value设置为5V4 pnp三极管一个5 LAMP,灯泡一个改为220V6 resistor 1k7 DIODE 二极管一个这个程序实际上很简单,主要要学习继电器的用法,注意的是,继电器必须接一个二极管。仿真程序如下:#include#include#define int8u unsigned
发表于 2020-01-19
AVR单片机控制继电器吸合与断开的仿真设计
AVR单片机在工业控制系统中的应用
远离仪表机壳,实测结果电容效应几乎为零。从而乱码和花屏现象不再出现。如意彩_[官网首页]2.6外部看门狗与外部时钟看门狗也称程序监视定时器。尽管 AVR单片机系统内也有该功能的设置,但在应用实践中发现当干扰严重时该功能会失效,即系统死机后单片机内部的看门狗也无法复位。故有必要在单片机外部单独设计看门狗电路。如图 5所示,由 MC4060芯片及外围电路构成一个看门狗电路。MC4060是一个带外接振荡的 14分频定时计数器,R18和 C2时间常数决定振荡频率。采用如图 5所示的参数时,该振荡频率经过 2秒左右时间后 14分频计数器将被记满,Q14由低电平变高电平经三极管 Q3构成的反相器使输出变为低电平,M16单片机被复位。程序正常运行时,会在
发表于 2020-01-19
AVR单片机在工业控制系统中的应用
AVR单片机外部中断实例及下载烧录的方法
的。Notes:1.在编程锁定位前先编程熔丝位。2.“1”表示未被编程,“0”表示被编程。。下载方法与使用STK500的几乎完全一样。在上面的介绍中,设备不选STK500,改成选JTAGICE 就能进入。支持的芯片:仅支持带JTAG接口的芯片。按官方文档的描述,支持的芯片清单为:ATmega128, ATmega64, ATmega32,ATmega16, ATmega162, ATmega165, ATmega169, ATmega323可见JTAG下载很有局限。另外由于通信协议的不同,感觉JTAG下载的速度,尤其是瞬时反应速度,没有STK500快。(但如果大量的数据传输,速度感觉差不多)。AVR单片机熔丝位(Fuse)快速入门
发表于 2020-01-19
AVR单片机外部中断实例及下载烧录的方法
AVR单片机的监控系统设计方案
众所周知,安全是电力企业一个永恒的主题,而安全工器具的好坏,将直接影响着电力企业在生产过程中的人身和设备安全。笔者提出了一种基于AVR单片机的安全工器具监控系统的设计方案,主要是对安全工器具的离就位状态信息、有效使用期限和安全工器具柜内的温湿度状况等进行监控,可以根据实现安全工器具柜内温湿度的自动调节,能够自动记录安全工器具的相关信息。如意彩_[官网首页]本文首先阐述了系统的总体结构,然后详细论述了系统的硬件设计和软件设计。1 安全工器具监控系统的总体结构1.1 系统结构本文所设计的安全工器具监控系统主要分为下位机数据采集和上位机数据管理两个部分,两者之间通过网络进行通信。系统首先通过数据采集板对安全工器具柜的相关量进行采集,然后将采集得到的数据进行
发表于 2020-01-19
AVR单片机的监控系统设计方案
AVR单片机详细介绍
ATMEL公司的AVR单片机,是增强型RISC内载Flash的单片机,芯片上的Flash存储器附在用户的产品中,可随时编程,再编程,使用户的产品设计容易,更新换代方便。如意彩_[官网首页]AVR单片机采用增强的RISC结构,使其具有高速处理能力,在一个时钟周期内可执行复杂的指令,每MHz可实现1MIPS的处理能力。AVR单片机工作电压为2.7-6.0V,可以实现耗电最优化。AVR的单片机广泛应用于计算机外部设备,工业实时控制,仪器仪表,通讯设备,家用电器,宇航设备等各个领域。ATMEL公司的90系列单片机 是基于新的精简指令RISC结构的。这种结构是在90年代开发出来的,综合了半导体集成技术和软件性能的新结构。这种结构使得在8位微处理器市场上
发表于 2020-01-19
AVR单片机详细介绍
AVR单片机模拟比较器的设计
模拟比较器对正极PB2(AINO)和负极PB3(AINI)的输入电压进行比较,当PB2的电压高于PB3的电压时,模拟比较器输出脚ACO置l。模拟比较器的控制和状态寄存器ACSR地址为$018($28),复位时值为$O。各位定义如下:ACD:模拟比较器禁止。置l时,模拟比较器的电源被关闭。改变ACD时,必须清ACIE位,否则将产生中断。ACO:模拟比较器输出。ACO直接与模拟比较器的输出脚相连接。ACI:模拟比较器中断标志。有模拟比较器输出事件时,该位置1。若ACIE置1,且SREG中的1置1,产生中断。中断执行后,ACI由硬件清O。ACIE:模拟比较器中断使能位。ACIE置l允许中断,清O禁止中断。ACIC:模拟比较器输入捕获使能。
发表于 2020-01-19
AVR单片机模拟比较器的设计
小广播
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

电子工程世界版权所有 京ICP证060456号 京ICP备10001474号 电信业务审批[2006]字第258号函 京公海网安备110108001534 Copyright © 2005-2020 kanmaya.com, Inc. All rights reserved

页面底部区域 foot.htm