📄 iic.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 + -