📄 万年历.c
字号:
#include<reg51.h>
#include<stdio.h>
#include <intrins.h>
#include <time.h>
#define unit unsigned int
#define unchar unsigned char
unsigned char SystemError;
sbit SCL= P1^0; //定义串行时钟线所在口 使用时根据自己的需要来定义
sbit SDA= P1^1; //定义串行数据线所在口 使用时根据自己的需要来定义
//**********6进制转BCD格式子程序HEXtoBCD()****
unsigned char HEXtoBCD(unsigned char a)
{
unsigned char b,c;
b=a%10;
c=b;
a=a/10;
b=a%10;
c=c|(b<<4);
return c;
}
//*************延时子程序****
void Delay(unit n)
{
unsigned char i;
for(i=0; i<n; i++) //根据晶振频率制定延时时间
_nop_();
}
//***启动子程序IIC_Start( )*******
void IIC_Start(void)
{
SDA=1; //时钟线拉高,为由高到低跳变做准备
SCL=1; //数据线拉高
_nop_(); //数据线保持高
_nop_();
_nop_();
SDA=0; //时钟线从高到低一次跳变,IIC通信开始
_nop_();
_nop_();
_nop_();
SCL=0; //恢复时钟线
}
//****停止子程序IIC_Stop( )****
void IIC_Stop(void)
{
SCL=0; //时钟线拉低
SDA=0; //数据线拉低
_nop_(); //数据线保持低
_nop_();
_nop_();
SCL=1; //时钟线拉高,为停止通信做准备
_nop_(); //时钟线保持高
_nop_();
_nop_();
SDA=1; //时钟线从低到高一次跳变,IIC通信停止
}
//*****应答程序Send_Ack( )
/*----------------------------------------------------------------------
Send_Ack() 函数说明:主器件为接收方,从器件为发送方,发生应答信号
----------------------------------------------------------------------*/
void Send_Ack(void)
{
SDA=0; //从器件将数据线拉低
_nop_(); //数据线保持低
_nop_();
_nop_();
SCL=1; //时钟线拉高
_nop_(); //时钟线保持高
_nop_();
_nop_();
SCL=0; //时钟线发生一次从高低的跳变 发送一个应答信号
_nop_();
_nop_();
SDA=1; //数据线拉高,进入下一个传送周期
}
//***无应答程序Send_NoAck()
/*---------------------------------------------------------------------
Send_NoAck()函数说明:主器件为接收方,从器件为发送方,发送非应答信号。
----------------------------------------------------------------------*/
void Send_NoAck(void)
{
SDA=1; //数据线拉高
_nop_(); //数据线保持高
_nop_();
SCL=1; //时钟线拉高
_nop_(); //时钟线保持高
_nop_();
SCL=0; //时钟线发生一次从高低的跳变 没有应答
}
//*****应答检查子程序 CACK_flg()
bit CACK_flg(void)
{
bit ack_flag;
SDA=1; //应答位检查
_nop_();
_nop_();
SCL=1;
_nop_();
_nop_();
if(SDA==0)
{
ack_flag=1; //若SDA=1表明无应答,置位无应答标志
}
else
{
ack_flag=0;
}
SCL=0;
return ack_flag;
}
//*void IIC_SendByte() 函数说明:向IIC总线发送数据**********
void IIC_SendByte(char xy )
{
unsigned char i=8;
while (i--)
{
SCL=0; //时钟保持低可以发送数据
_nop_();
SDA=(bit)(xy&0x80); //发送数据最高位
xy <<=1;
_nop_();
_nop_();
SCL=1; //标志一个位发送完毕
_nop_();
_nop_();
} //一个字节数据发送完毕
SCL=0; //保持时钟线为低,从器件进行数据处理,主器件进入等待状态
}
//******从I2C总线接收数据。
/*----------------------------------------------------------------------
IIC_ReceiveByte () 函数说明:从I2C总线接受数据
----------------------------------------------------------------------*/
unsigned char IIC_ReceiveByte (void)
{
unsigned char i,dat=0;
SDA=1; //数据线拉高
for(i=0;i<8;i++)
{
dat <<=1; //数据左移一位
SCL=0; //时钟线拉低
_nop_();
_nop_();
SCL=1; //时钟做一次从低到高的跳变,可以接收数据
_nop_();
_nop_();
dat|=SDA;
}
SCL=0; //保持时钟线为低,从器件进行数据处理,主器件进入等待状态
return dat; //返回接收到的一个字节的数据
}
//**往IIC总线上器件指定地址写一个字节的数据子程序IIC_write_byte()***********************
//在该程序中,cadd为器件地址,data_address为数据地址,data_byte为要写的字节数据。写数据失败返回0,写数据成功返回1。
bit IIC_write_byte(unsigned char cadd,unsigned char data_address,unsigned char data_byte)
{
IIC_Start(); //发送IIC START信号
IIC_SendByte(cadd); //发送器件从地址
if (CACK_flg()==0) //检测应答信号
{
return 0;
}
IIC_SendByte (data_address); //发送数据地址
if (CACK_flg ()==0) //检测应答信号
{
return 0;
}
IIC_SendByte (data_byte);
if (CACK_flg ()==0)
{
return 0;
}
IIC_Stop(); //发送IIC STOP信号
return 1;
}
///往IIC总线上器件指定地址开始写指定长度的数据IIC_write_lendata()*******
unsigned char IIC_write_lendata(unsigned char cadd, unsigned char data_addr, unsigned char *ptr, unsigned char len)
{
IIC_Start(); // 发送IIC START信号
IIC_SendByte(cadd); // 发送器件从地址
if(CACK_flg()==0) // 检测应答信号
{
return 0;
}
IIC_SendByte (data_addr); // 发送数据地址
if(CACK_flg()==0) // 检测应答信号
{
return 0;
}
for(;len>0;len--) // 连续发送LEN长度的字节数据
{
IIC_SendByte (*ptr++);
if(CACK_flg()==0)
{
return 0;
}
}
IIC_Stop(); // 发送IIC STOP信号
return 1;
}
//********从IIC总线上器件指定地址读一个字节的数据IIC_read_byte()***
unsigned char IIC_read_byte (unsigned char cadd, unsigned char data_address)
{
unsigned int temp;
IIC_Start(); // 发送I2C START信号
IIC_SendByte (cadd); // 发送从器件写命令
if(CACK_flg()==0) // 检测应答信号
{
return 0;
}
IIC_SendByte (data_address); // 发送数据地址
if(CACK_flg()==0) // 检测应答信号
{
return 0;
}
IIC_Start(); // 重新发送IIC START信号
IIC_SendByte (cadd |0x01); // 发送器件读命令
if(CACK_flg()==0) // 检测应答信号
{
return 0;
}
temp= IIC_ReceiveByte ();
Send_NoAck(); // 接收最后一个字节后发送无应答信号
IIC_Stop(); // 发送IIC停止信号
return temp;
}
//**********从IIC总线上器件指定地址读指定长度的数据IIC_read_lendata()***
bit IIC_read_lendata (unsigned char cadd, unsigned char data_address, unsigned char *ptr, unsigned char len)
{
IIC_Start(); //发送IIC 启动信号
IIC_SendByte (cadd); //发送从器件写命令
if(CACK_flg()==0) //检测应答信号
{
return 0;
}
IIC_SendByte (data_address); //发送数据地址
if(CACK_flg()==0) //检测应答信号
{
return 0;
}
IIC_Start(); //重新发送IIC启动信号
IIC_SendByte (cadd|0x01); //发送器件读命令
if(CACK_flg()==0) //检测应答信号
{
return 0;
}
for(;len>1;len--) //连续接收LEN-1长度的字节数据
{
*ptr++= IIC_ReceiveByte ();
Send_Ack (); //发送应答信号
}
*ptr= IIC_ReceiveByte (); //接收最后一个字节
Send_NoAck(); // 发送无应答信号
IIC_Stop(); // 发送IIC停止信号
return 1;
}
//**********从PCF8563中读取时间子程序PCF8563_read_time()******
void PCF8563_read_time(struct time * ptm)
{
IIC_read_lendata(0xA2,2,*ptm,sizeof(struct time));
//从PCF8563中读取时间//PCF8563的地址为0xA2;从秒开始读。
ptm->second &=0x7F; //取秒字节,屏蔽无效位
ptm->minute &=0x7F; //取分钟字节,屏蔽无效位
ptm->hour &=0x3F; //取小时字节,屏蔽无效位
ptm->day &=0x3F; //取天字节,屏蔽无效位
ptm->weekday &=0x07; //取星期字节,屏蔽无效位
ptm->mon &=0x1F; //取月字节,屏蔽无效位
ptm->year &=0xFF; //取年字节,屏蔽无效位
}
//*********向PCF8563写时间子程序PCF8563_write_time()***
void PCF8563_write_time(struct time *ptm)
{
ptm.second = HEXtoBCD(ptm.second); //将秒数值变换为BCD码格式
ptm.minute = HEXtoBCD (ptm.minute); //将分钟数值变换为BCD码格式
ptm.hour = HEXtoBCD (ptm.hour); //将小时数值变换为BCD码格式
ptm.day = HEXtoBCD (ptm.day); //将天数值变换为BCD码格式
ptm.weekday = HEXtoBCD (ptm.weekday); //将星期数值变换为BCD码格式
ptm.mon = HEXtoBCD (ptm.mon); //将月数值变换为BCD码格式
ptm.year = HEXtoBCD (ptm.year); //将年数值变换为BCD码格式
IIC_write_lendata(0xA2,2,*ptm,sizeof(struct time)); //向PCF8563
//写时间
}
//********** PCF8563读闹钟子程序PCF8563_read _alm()********
void PCF8563_read_alm( struct alarm * alm)
{
IIC_ read_lendata(0xA2,9,&alm->minute,1); //读分钟字节
IIC_ read_lendata(0xA2,10,&alm->hour,1); //读小时字节
IIC_ read_lendata(0xA2,11,&alm->day,1); //读天字节
IIC_ read_lendata(0xA2,12,&alm->weekday,1); //读星期字节
alm->minute & 0x7F; //取分钟字节,屏蔽无效位
alm->hour & 0x3F; //取小时字节,屏蔽无效位
alm->day & 0x3F; //取天字节,屏蔽无效位
alm->weekday & 0x07; //取星期字节,屏蔽无效位
}
//*********PCF8563设置闹钟子程序PCF8563_set_alm()**
void PCF8563_set_alm( struct alarm alm, bit smin, bit shour, bit sday, bit sweek)
{
if( smin ) //如果有小时报警
{
alm.minute = HEXtoBCD ( alm.minute); //将分钟数值转换为BCD格式
alm.minute = alm.minute & 0x7F; //取分钟字节,屏蔽无效位
}
else //如果没有小时报警
{
alm.minute = alm.minute | 0x80; //清小时报警数据
}
if( shour ) //如果有日报警
{
alm.hour = HEXtoBCD ( alm.hour); //将小时数值转换为BCD格式
alm.hour = alm.hour & 0x3F; //取小时字节,屏蔽无效位
}
else //如果没有日报警
{
alm.hour = alm.hour | 0x80; //清日报警数据
}
if( sday ) //如果有月报警
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -