⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 万年历.c

📁 单片机数据通讯典型应用(光盘内容)
💻 C
📖 第 1 页 / 共 2 页
字号:
#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 + -