📄 rtc._c
字号:
/*******************************************
文件:RTC.C
环境:编译为ICC AVR6.25A,仿真为AVR Studio4.10
硬件:ATMEGA16芯片
日期:2006年12月10日
功能:驱动开发板上的DS1302时钟芯片
备注:参考《AVR系列单片机C语言编程与应用实例》(清华大学出版社)
/******************************************/
//#include <iom16v.h> //包含型号头文件
//#include <macros.h> //包含"位"操作头文件
//#include <stdio.h> //标准输入输出头文件
//#include <AVR_PQ1A.h> //包含自定义常量头文件
//#include "YJ12864.C"
//#include "YJ1602.C" //包含1602液晶函数文件
//#include "MKEY.C" //包含矩阵键盘函数文件
/*******************************************
函数名称: DS1302_init
功 能: 初始化DS1302的数据接口
参 数: 无
返回值 : 无
/********************************************/
void DS1302_portinit(void)
{
DDRB|=BIT(RTC_CLK)|BIT(RTC_DATA)|BIT(RTC_CS);//将时钟端(RTC_CLK)数据端(RTC_DATA)片选端(RTC_CS)设置为输出
}
/*******************************************
函数名称: DS1302_writeB
功 能: 向DS1302写入一个字节数据(没有RST操作)
参 数: byte--要写入的数据
返回值 : 无
/********************************************/
void DS1302_writeB(uchar byte)
{
uchar i;
for(i=0;i<8;i++) //8位数据计数
{
PORTB&=~BIT(RTC_CLK); //拉低时钟端
if(byte&0x01) //当前位是否是1
{
PORTB|=BIT(RTC_DATA); //当前位是1,拉高数据端
}
else
{
PORTB&=~BIT(RTC_DATA); //当前位是0,拉低数据端
}
Delayus(10); //调整时钟和脉冲宽度
PORTB|=BIT(RTC_CLK); //时钟上升沿(DS1302采样数据)
byte>>=1; //数据右移1位,为送出新数据位做准备
}
}
/*******************************************
函数名称: DS1302_readB
功 能: 从DS1302读出一个字节数据(没有RST操作)
参 数: 无
返回值 : byte--读出的数据
/********************************************/
uchar DS1302_readB(void)
{
uchar i,byte=0;
DDRB&=~BIT(RTC_DATA); //将数据端口设置为输入
PORTB&=~BIT(RTC_DATA); //无上拉电阻
for(i=0;i<8;i++) //8位数据计数
{
byte>>=1; //保存读入的数据位
PORTB|=BIT(RTC_CLK); //时钟上升沿
Delayus(10); //延时,调整时钟脉冲宽度
PORTB&=~BIT(RTC_CLK); //时钟下降沿,DS1302输出数据位
Delayus(10); //等待数据变化(MEGA16太快,必须等待DS1302的数据位输出,否则不能正确读出)
if(PINB&BIT(RTC_DATA)) //当前位是否是高电平
{
byte|=BIT(PB7); //是高电平就将返回数据的当前位置1
}
else
{
byte&=~BIT(PB7); //是低电平就将返回数据的当前位置0
}
}
DDRB|=BIT(RTC_DATA); //最后将数据端口设置为输出
return byte; //返回读出的数据
}
/*******************************************
函数名称: DS1302_writeD
功 能: 向DS1302的某个地址写入一个字节数据
参 数: addr--地址值(寄存器或RAM)
data--要写入的地址
返回值 : 无
/********************************************/
void DS1302_writeD(uchar addr,uchar data)
{
PORTC&=~BIT(RTC_CS); //拉低片选端
PORTB&=~BIT(RTC_CLK); //拉低时钟端
Delayus(10);
PORTC|=BIT(RTC_CS); //拉高片选端
Delayus(10); //调整片选脉冲
DS1302_writeB(addr); //写入操作命令(地址)
Delayus(10);
PORTB&=~BIT(RTC_CLK); //拉低时钟端
Delayus(10);
DS1302_writeB(data); //写入数据
PORTB&=~BIT(RTC_CLK); //拉低时钟端
Delayus(10); //调整片选脉冲
PORTC&=~BIT(RTC_CS); //拉低片选端
}
/*******************************************
函数名称: DS1302_readD
功 能: 从DS1302的某个地址读出一个字节数据
参 数: addr--地址值(寄存器或RAM)
返回值 : data--读出的数据
/********************************************/
uchar DS1302_readD(uchar addr)
{
uchar data;
PORTC&=~BIT(RTC_CS); //拉低片选端
PORTB&=~BIT(RTC_CLK); //拉低时钟端
Delayus(10);
PORTC|=BIT(RTC_CS); //拉高片选端
Delayus(10); //调整片选脉冲
DS1302_writeB(addr); //写入操作命令(地址)
Delayus(10);
data=DS1302_readB(); //读出数据
Delayus(10);
PORTB&=~BIT(RTC_CLK); //拉低时钟端
PORTC&=~BIT(RTC_CS); //拉低片选端
return data; //返回读出的数据
}
/*******************************************
函数名称: DS1302_setT
功 能: 设置DS1302的时间
参 数: ptTimeD--设置时间数组指针
返回值 : 无
/********************************************/
void DS1302_setT(uchar ptTimeD[])
{
uchar i;
uchar addr = 0x80; //写入地址从秒寄存器开始
DS1302_writeD(C_WP|WR,UPROTECT); //控制命令,WP位为0,允许写操作
Delayms(5);
for(i=0;i<7;i++)
{
DS1302_writeD(addr|WR,ptTimeD[i]); // 秒 分 时 日 月 星期 年
addr+=2;
Delayms(1);
}
DS1302_writeD(C_WP|WR,PROTECT); //控制命令,WP位为1,不允许写操作
}
/*******************************************
函数名称: DS1302_getT
功 能: 读取DS1302的当前时间
参 数: time[]--读取的时间数组
返回值 : 无
/********************************************/
void DS1302_getT(uchar time[])
{
uchar i;
uchar addr = 0x80; //读取地址从秒寄存器开始
for(i=0;i<7;i++)
{
time[i]=DS1302_readD(addr|RD); // 秒 分 时 日 月 星期 年
addr+=2;
}
PORTB&=~BIT(RTC_CLK); //拉低时钟端(时钟端在不操作时为低)
}
/*******************************************
函数名称: DS1302_check
功 能: 检测DS1302是否正常工作
参 数: 无
返回值 : exist--为TRUE为检测到DS1302,为FALSE为没检测到
/********************************************/
uchar DS1302_check(void)
{
uchar exist;
DS1302_writeD(C_WP|WR,UPROTECT); //写入写允许命令
DS1302_writeD(C_RAMBASE|WR,0xA5); //RAM0写入0xA5
exist=DS1302_readD(C_RAMBASE|RD); //读取RAM0
if(exist==0xA5)
{
exist=TRUE; //如果读取值与写入值相等,返回TRUE
}
else
{
exist=FALSE; //如果读取值与写入值不相等,返回FALSE
}
return exist;
}
/*******************************************
函数名称: DS1302_init
功 能: 初始化DS1302
参 数: 无
返回值 : 无
/********************************************/
void DS1302_init(void)
{
DS1302_writeD(C_WP|WR,UPROTECT); //写入写允许命令
DS1302_writeD(C_SEC|WR,CLK_START); //启动振荡器,DS1302开始工作
DS1302_writeD(C_WP|WR,PROTECT); //控制命令,WP位为1,不允许写操作
}
/*******************************************
函数名称: BCD_ASCII
功 能: 将压缩BCD码转换成ascii码
参 数: BCD--将要转换的压缩BCD码
ptasc--转换后的ASCII码数组指针
返回值 : 无
/********************************************/
void BCD_ASCII(uchar BCD,uchar *ptasc)
{
*ptasc=BCD/16|0x30; //转换十位
*(ptasc+1)=BCD&0x0F|0x30; //转换个位
}
/*******************************************
函数名称: Disp_time
功 能: 在1602液晶上显示当前时间(第1行格式:年-月-日 星期;第2行格式:时-分-秒)
参 数: time[]--时间数组
返回值 : 无
/********************************************/
void Disp_time(uchar time[])
{
uchar i,asc[2];
//uchar line1[11]={0,0,'-',0,0,'-',0,0,' ',0,'\0'};//显示第1行的字符数组
// uchar line2[9]={0,0,':',0,0,':',0,0,'\0'}; //显示第2行的字符数组
uchar linex1[5]={' ','0',' ','0','\0'};//显示第1行的字符数组
uchar linex1_1[5]={' ','0',' ','0','\0'};//显示第1行的字符数组
uchar linex2[5]={' ',0,' ',0,'\0'};//显示第1行的字符数组
uchar linex2_2[3]={' ','0','\0'};//显示第1行的字符数组
uchar linex3[17]={' ',0,' ',0,' ',':',' ','0',' ','0',' ',':',' ','0',' ','0','\0'};//显示第1行的字符数组
// uchar linex4[11]={'\0'};//显示第1行的字符数组
/*
for(i=0;i<3;i++) //为第2行的字符数组赋值
{
BCD_ASCII(time[2-i],asc);
line2[i*3]=asc[0]&0x7F;
line2[i*3+1]=asc[1];
} */
BCD_ASCII(time[0],asc); //秒 //为第1行的年赋值
linex3[13]=asc[0];
linex3[15]=asc[1];
BCD_ASCII(time[1],asc); //分 //为第1行的年赋值
linex3[7]=asc[0];
linex3[9]=asc[1];
BCD_ASCII(time[2],asc); //时 //为第1行的年赋值
linex3[1]=asc[0];
linex3[3]=asc[1];
BCD_ASCII(time[6],asc); //年 //为第1行的年赋值
linex1[1]=asc[0];
linex1[3]=asc[1];
BCD_ASCII(time[4],asc); //月 //为第1行的年赋值
linex1_1[1]=asc[0];
linex1_1[3]=asc[1];
BCD_ASCII(time[3],asc); //日 //为第1行的年赋值
linex2[1]=asc[0];
linex2[3]=asc[1];
BCD_ASCII(time[5],asc); //星期 //为第1行的年赋值
linex2_2[1]=asc[1];
while(LCD12864_readBF());
LCD12864_gotoXY(1,0); //第1行,第1列显示
// Delayms(200);
LCD12864_sendstr(" 2 0");
LCD12864_sendstr(linex1);
LCD12864_sendstr("年");
LCD12864_sendstr(linex1_1);
LCD12864_sendstr("月");
// while(LCD12864_readBF());
LCD12864_gotoXY(2,0); //第2行,第3列显示
// Delayms(200);
LCD12864_sendstr(linex2);
LCD12864_sendstr("号");
LCD12864_sendstr(" 星期");
LCD12864_sendstr(linex2_2);
// while(LCD12864_readBF());
LCD12864_gotoXY(3,0); //第2行,第3列显示
// Delayms(200);
LCD12864_sendstr(linex3);
while(LCD12864_readBF());
LCD12864_gotoXY(4,2); //第2行,第3列显示
// Delayms(200);
LCD12864_sendstr("4 取消");
/*
BCD_ASCII(time[6],asc); //为第1行的年赋值
line1[0]=asc[0];
line1[1]=asc[1];
BCD_ASCII(time[4],asc); //为第1行的月赋值
line1[3]=asc[0];
line1[4]=asc[1];
BCD_ASCII(time[3],asc); //为第1行的日赋值
line1[6]=asc[0];
line1[7]=asc[1];
BCD_ASCII(time[5],asc); //为第1行的星期赋值
line1[9]=asc[1];
while(LCD12864_readBF());
LCD12864_gotoXY(2,1); //第1行,第1列显示
// Delayms(200);
LCD12864_sendstr("20");
LCD12864_sendstr(line1);
while(LCD12864_readBF());
LCD12864_gotoXY(3,2); //第2行,第3列显示
// Delayms(200);
LCD12864_sendstr(line2);
LCD12864_gotoXY(4,2); //第2行,第3列显示
// Delayms(200);
LCD12864_sendstr("4 取消");
*/
/*
while(LCD1602_readBF());
LCD1602_gotoXY(1,2); //第1行从第3个位置开始显示
LCD1602_sendstr("20"); //将07年显示为2007的形式
LCD1602_sendstr(line1); //第1行显示
while(LCD1602_readBF());
LCD1602_gotoXY(2,4); //第2行从第5个位置开始显示
LCD1602_sendstr(line2); //第2行显示
*/
}
/*******************************************
函数名称: main
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -