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

📄 iic.c

📁 在iic总线上挂载时间芯片PCF8563,也可用于对支持iic总线的EEPROM的芯片读写
💻 C
字号:

#define VARS_IIC

#include "main.h"
#include "iic.h"

//===========================================================================================================
//================================		变量声明		=====================================================
//===========================================================================================================

/*---------------------------PCF8583有关的变量----------------------------*/
bit   dis_clock_flag,read_clock_flag,set_clock_flag;
uchar xdata year,year1,month,day,week,hour,minute,second;

/*---------------------------SMBUS接口相关变量----------------------------*/
bit   iic_error_flag,sm_busy;
uchar xdata watch_buf[20];
uchar xdata iic_read_buf[20]={0};
uchar xdata iic_write_buf[20]={0};
uchar xdata slave_add,iic_ram_add,send_byte,write_start_num,read_start_num;
uchar xdata iic_send_count,iic_receive_count,iic_send_len,iic_receive_len,watch;

//===========================================================================================================
//====================================		函数		=====================================================
//===========================================================================================================

/**********************************************************************
* 函数名称: DlyMS
* 功能描述: 延时函数,延时ms毫秒
* 输入参数: ms:毫秒数
* 输出参数: none
* 返 回 值: none
* 其它说明: none
* 修改日期      版本号     修改人	      修改内容
* --------------------------------------------------
*   
***********************************************************************/
void DlyMS(int ms)
{
    unsigned int ldlm1,ldlm2;

    for(ldlm1 = 0; ldlm1 < ms; ldlm1 ++)
    {
        for(ldlm2 = 0; ldlm2 < 1427; ldlm2 ++);
    }
}
/**********************************************************************
* 函数名称: hex_bcd
* 功能描述: 完成HEX(99以内)到BCD(两位)的确转换
* 输入参数: none
* 输出参数: none
* 返 回 值: none
* 其它说明: none
* 修改日期      版本号     修改人	      修改内容
* --------------------------------------------------
*   
***********************************************************************/
uchar hex_bcd(uchar hex_value)
{
    return(((hex_value/10)<<4)|(hex_value%10));
}

/**********************************************************************
* 函数名称: smbus_send
* 功能描述: 通过SMBus发送数据
* 输入参数: none
* 输出参数: none
* 返 回 值: none
* 其它说明: none
* 修改日期      版本号     修改人	      修改内容
* --------------------------------------------------
*   
***********************************************************************/
void smbus_send (uchar chip_select,byte_address,write_num)
{
    while(sm_busy);                       // Wait for SMBus to be free.
    sm_busy=1;                            // Occupy SMBus (set to busy)
    write_start_num=0;
    slave_add=chip_select;                // Chip select + WRITE
    iic_ram_add=byte_address;             // PCF8563的寄存器地址
    iic_send_len=write_num;               // 写PCF8563字节数
    STA=1;                                // Start transfer
    while (sm_busy);
}

/**********************************************************************
* 函数名称: smbus_receive
* 功能描述: 通过SMBus接收数据
* 输入参数: none
* 输出参数: none
* 返 回 值: none
* 其它说明: none
* 修改日期      版本号     修改人	      修改内容
* --------------------------------------------------
*   
***********************************************************************/
void smbus_receive (uchar chip_select,receive_num)
{    
    while (sm_busy);                    // Wait for bus to be free.
    sm_busy=1;                          // Occupy SMBus (set to busy)
    read_start_num=0;
    slave_add=chip_select;              // Chip select + READ
    iic_receive_len=receive_num; 
    STA=1;                              // Start transfer
    while(sm_busy);                     // Wait for transfer to finish
}

/**********************************************************************
* 函数名称: write_8563
* 功能描述: 写时间芯片pcf8563
* 输入参数: none
* 输出参数: none
* 返 回 值: none
* 其它说明: none
* 修改日期      版本号     修改人	      修改内容
* --------------------------------------------------
*   
***********************************************************************/
void write_8563(uchar ram_add,write_num)
{
    smbus_send(write_pcf8563,ram_add,write_num);
	DlyMS(1);
}

/**********************************************************************
* 函数名称: read_8563
* 功能描述: 读时间芯片pcf8563
* 输入参数: none
* 输出参数: none
* 返 回 值: none
* 其它说明: none
* 修改日期      版本号     修改人	      修改内容
* --------------------------------------------------
*   
***********************************************************************/
void read_8563(uchar read_num)
{
    smbus_receive(read_pcf8563,read_num);
}

/**********************************************************************
* 函数名称: set_clock
* 功能描述: 设置时间芯片pcf8563时间
* 输入参数: none
* 输出参数: none
* 返 回 值: none
* 其它说明: none
* 修改日期      版本号     修改人	      修改内容
* --------------------------------------------------
*   
***********************************************************************/
void set_clock(unsigned char xdata *p_XramAdd)
{
	year = *p_XramAdd;
	p_XramAdd ++;
	month = *p_XramAdd;
	p_XramAdd ++;
	day = *p_XramAdd;
	p_XramAdd ++;
	hour = *p_XramAdd;
	p_XramAdd ++;
	minute = *p_XramAdd;
	p_XramAdd ++;
	second = *p_XramAdd;
	p_XramAdd ++;
	week = *p_XramAdd;

/*	second=0x50;
	minute=0x07;
	hour=0x0A;
	day=0x10;
//	week=0x05;
	month=0x09;
	year=0x08; */

    iic_write_buf[0]=hex_bcd(second);           //设置秒
    iic_write_buf[1]=hex_bcd(minute);           //设置分
    iic_write_buf[2]=hex_bcd(hour);             //设置时
    iic_write_buf[3]=hex_bcd(day); 
    iic_write_buf[4]=hex_bcd(week); 
    iic_write_buf[5]=hex_bcd(month); 
    iic_write_buf[6]=hex_bcd(year); 
    write_8563(pcf8563_second,0x07);
}

/**********************************************************************
* 函数名称: read_clock
* 功能描述: 读时间芯片pcf8563时间
* 输入参数: none
* 输出参数: none
* 返 回 值: none
* 其它说明: none
* 修改日期      版本号     修改人	      修改内容
* --------------------------------------------------
*   
***********************************************************************/
void read_clock(void)
{	
	unsigned char xdata *p_XramAdd;

    write_8563(pcf8563_second,0x00);				//将光标放在秒地址处,释放总线
	read_8563(0x07);   								//smbus_receive(read_pcf8563,0x07);
    second=iic_read_buf[0]&0x7f;
    second=((second&0xf0)>>4)*10+(second&0x0f);		//将BCD码转换成HEX
    minute=iic_read_buf[1]&0x7f;
    minute=((minute&0xf0)>>4)*10+(minute&0x0f);		//将BCD码转换成HEX
    hour=iic_read_buf[2]&0x3f;
    hour=((hour&0xf0)>>4)*10+(hour&0x0f);			//将BCD码转换成HEX
    day=iic_read_buf[3]&0x3f;
    day=((day&0xf0)>>4)*10+(day&0x0f);				//将BCD码转换成HEX
    week=iic_read_buf[4]&0x07;
    week=((week&0xf0)>>4)*10+(week&0x0f);			//将BCD码转换成HEX
    month=iic_read_buf[5]&0x1f;    
    month=((month&0xf0)>>4)*10+(month&0x0f);		//将BCD码转换成HEX
    year=iic_read_buf[6];
    year=((year&0xf0)>>4)*10+(year&0x0f);			//将BCD码转换成HEX

	p_XramAdd = TIME_STOR;
	*p_XramAdd = year;
	p_XramAdd ++;
	*p_XramAdd = month;
	p_XramAdd ++;
	*p_XramAdd = day;
	p_XramAdd ++;
	*p_XramAdd = hour;
	p_XramAdd ++;
	*p_XramAdd = minute;
	p_XramAdd ++;
	*p_XramAdd = second;
	p_XramAdd ++;
	*p_XramAdd = week;
}

/**********************************************************************
* 函数名称: init_pcf8563
* 功能描述: 时间芯片pcf8563初始化
* 输入参数: none
* 输出参数: none
* 返 回 值: none
* 其它说明: none
* 修改日期      版本号     修改人	      修改内容
* --------------------------------------------------
*   
***********************************************************************/
void init_pcf8563(void)
{
    iic_write_buf[0]=0x00;
    write_8563(pcf8563_control1,0x01);
    iic_write_buf[0]=0x00;
    write_8563(pcf8563_control2,0x01);
    iic_write_buf[0]=0x81;
    write_8563(pcf8563_clk_reg,0x01);		//CLK输出频率1K
    iic_write_buf[0]=0x00;
    write_8563(pcf8563_min_arm,0x01);		//分报警无效
    iic_write_buf[0]=0x00;
    write_8563(pcf8563_hou_arm,0x01);		//时报警无效
    iic_write_buf[0]=0x00;
    write_8563(pcf8563_dat_arm,0x01);		//日报警无效
    iic_write_buf[0]=0x00;
    write_8563(pcf8563_wek_arm,0x01);		//星期报警无效
}

/**********************************************************************
* 函数名称: init_pcf8563
* 功能描述: SMBUS中断服务程序
* 输入参数: none
* 输出参数: none
* 返 回 值: none
* 其它说明: none
* 修改日期      版本号     修改人	      修改内容
* --------------------------------------------------
*   
***********************************************************************/
void smbus(void) interrupt 7
{
    watch=SMB0STA;
    switch (watch)						//SMBUS状态寄存器SMB0STA
    {                                   //iic_error_flag=1说明SMBus有问题
        case 0x08:                    	//主发送/接收:起始条件已发出.    
        	STA=0;
			iic_error_flag=0;
			AA=1;                		//人工清除起始位STA
            iic_receive_count=0;
			iic_send_count=0;
            SMB0DAT=slave_add;     		//从地址+读/写标志送SMB0DAT,
	//		DlyMS(1);
        break;        
        
        case 0x10:                    	//主发送/接收:重复起始条件已发出。
        	STA=0;
			AA=1;            			//人工清除起始位STA
            SMB0DAT=slave_add;        	//从地址+读/写标志送SMB0DAT
            iic_receive_len=iic_receive_len+iic_receive_count;
            iic_send_len=iic_send_len+iic_send_count;
            iic_receive_count=0;
			iic_send_count=0;
			DlyMS(1);
        break;

        case 0x18:                              //主发送器:从地址+写标志已发出,收到ACK
            SMB0DAT=iic_ram_add;
			write_start_num=0;					//将要发送的数据装入SMB0DAT.
			DlyMS(1);
        break;        
    
        case 0x20:                  
                                                //主发送器:从地址+写标志已发出,收到NACK
			write_start_num++;
            if(write_start_num>5)
      		{
				STO=1;
				sm_busy=0;
				iic_error_flag=1;
			}									//如果超过5次不成功则释放总线  
            else
			{
				STO=1;
				STA=1;
			}                					//确认查询重复,置位STO+STA。
			DlyMS(1);
            break;

        case 0x28:              				//数据字节已发出,收到ACK,将下一字节装入SMB0DAT;
        	switch(iic_send_len)
        	{
        		case 0x00:    
           			STO=1;
					sm_busy=0;            		//如果数据已经发送结束则释放总线                            
        		break;    
  				default  :
            		SMB0DAT=iic_write_buf[iic_send_count++];
					iic_send_len--;    
             	break;
        	}
			DlyMS(1);
        break;

        case 0x30:                      		//主发送器:数据字节已发出,收到NACK,
             write_start_num++;
             if(write_start_num>5)
    		 {    
			 	STO=1;
				sm_busy=0;
				iic_error_flag=1;
			 }									//如果超过5次不成功则释放总线  
             else
    		 {
				STO=1;
				STA=1;
			 }                      			//重试传输或置位STO
			 DlyMS(1);
        break;

        case 0x38:                              //主发送器:竞争失败,保存当前数据
             write_start_num++;
             if(write_start_num>5)
    		 {
				STO=1;
				sm_busy=0;
				iic_error_flag=1;
			 } 									//如果超过5次不成功则释放总线  
             else 
			 {
				STO=1;
				STA=1;
			 }
			 DlyMS(1);
        break;

        case 0x40:    
             read_start_num=0;                  //主接收器:从地址+读标志已发出,收到ACK,
             if(iic_receive_len<2)	AA=0;       //如果只接收一个字节,清AA位(收到字节后发NACK),等待接收数据
			 DlyMS(1);
        break;

        case 0x48:                              //主接收器:从地址+读标志已发出,收到NACK,
             read_start_num++;
             if(read_start_num>5)
    		 {
			 	STO=1;
				sm_busy=0;
				iic_error_flag=1;
			 } 									//如果超过5次不成功则释放总线
             else
    		{
				STO=1;
				STA=1;
			}
			DlyMS(1);
        break; 												//确认查询重复,置位STO+STA。

        case 0x50:                              			//主接收器:数据字节收到,ACK已发出;读SMB0DAT,等待
			iic_read_buf[iic_receive_count++]=SMB0DAT;
            iic_receive_len--;
            if(iic_receive_len<2)	AA=0;       			//下一个字节,如下一个字节是最后字节,清除AA。
			DlyMS(1);
        break;

        case 0x58:                              			//主接收器:数据字节收到,NACK已发出,置位STO。
             iic_read_buf[iic_receive_count++]=SMB0DAT; 	//读操作已经完成,读数据寄存器并且发出STOP.
             iic_receive_len--;
             STO=1;
			 sm_busy=0;                        	//Free SMBus  
  		     DlyMS(1);
        break;

        default:
             STO=1;
			 sm_busy=0;
			 iic_error_flag=1;       			//Reset communication. 
             DlyMS(1);
        break;
    }
    SI=0;                                       //clear interrupt flag
}



⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -