/*********************************************************
*Copyright (C), 2021, Shanghai Eastsoft Microelectronics Co., Ltd.
*文件名: iics
*作 者: AE Team
*版 本: V1.0
*日 期: 2022/03/31
*描 述: I2C从动程序
1.当I2CSRIF标志位置1,且I2CRW位为0时表示主机写从机,即从机接收数据。从机接收数据缓冲器满时,
中断标志位I2CRBIF置位,读取一次接收数据缓冲器I2CRB,I2CRBIF标志位自动清零,其他使用注意事
项请参考芯片数据手册。
2.当I2CSRIF标志位置位,且I2CRW位为1时表示主机读从机,即从机发送数据。I2CTB发送数据缓冲器不
满时,中断标志位I2CTBIF置位,写发送数据缓冲器I2CTB,若数据缓冲器写满,I2CTBIF标志位自动清
零,若发出一个字节,数据缓冲器未满,则中断标志位I2CTBIF置位。
3.从机接收到STOP信号时,收发数据缓冲器不会自动清零,需置位I2CRST位来软件复位I2C模块。复位后,
需重新初始化I2C模块。
4.例程中主机写一个数据给从机,再读回两个数据。从机将接收到的数据以原码和反码的形式发回给主机。
*备 注: 适用于ES7P2131
本软件仅供学习和演示使用,对用户直接引用代码所带来的风险或后果不承担任何法律责任。
**********************************************************/
#include <hic.h>
sbit I2C_restart;
unsigned char I2CRB_reg;
unsigned char I2CTB_reg;
/********************************************************
函数名: void ram_clear(void)
描 述: 通用RAM区清零子程序
输入值: 无
输出值: 无
返回值: 无
**********************************************************/
void ram_clear(void)
{
GIE = 0;
for(IAAH = 0; IAAH < 0x04; IAAH++)
{
for(IAAL = 0; IAAL < 0xFF; IAAL++)
{
IAD = 0x00;
}
IAD = 0x00;
//clr_wdt();
}
}
/*********************************************************
函数名: void Int_vectors_init(void)
描 述: 通用中断模式设置子程序
输入值: 无
输出值: 无
返回值: 无
**********************************************************/
void Int_vectors_init(void)
{
INTVEN0 = 1; // 向量中断模式
INTV0 = 0;
INTV1 = 0; // 向量表优先级00组
INTP = 0x40; // IG6优先级最高
GIEL = 1;
}
/*********************************************************
函数名: void Init_i2c(void)
描 述: I2CS模块初始化
输入值: 无
输出值: 无
返回值: 无
**********************************************************/
void Init_i2c(void)
{
//PSFT = 0x04; //选择SDA,SCL
I2CRST = 1;
while(I2CRST);
I2CX16 = 0x00; //禁止采样滤波
I2CC = 0xE0; //I2C端口使能,上拉,开漏输出,发送ACK
I2CSA = 0x5A; //从机地址=0x5A
I2CIEC = 0x43; //I2C接收未应答中断使能位 I2C接收结束位中断使能 I2C接收“起始位+从机地址匹配+发送应答位”中断使能
I2CIFC = 0x00; //清中断标志
I2CIE = 1; //I2C通讯总中断使能
I2CEN = 1; //I2C使能
}
/*********************************************************
函数名: void isr_i2c_handler(void) interrupt_high 0x0020
描 述: 中断服务程序
输入值: 无
输出值: 无
返回值: 无
**********************************************************/
void isr_i2c_handler(void) interrupt_high 0x0020
{
if(I2CIF && I2CIE)
{
if(I2CSRIE && I2CSRIF) //收到起始位+地址匹配+发送应答位
{
I2CSRIF = 0; //清I2C起始位+地址匹配+发送应答位标志位
if(I2CRW == 1) //主机读
{
I2CRBIE = 0; //I2C接收中断禁止
I2CTBIE = 1; //I2C发送中断使能
I2C_restart = 1;
}
else if(I2CRW == 0) //主机写
{
I2CRBIE = 1; //I2C接收中断使能
I2CTBIE = 0; //I2C发送中断禁止
}
}
if(I2CRBIE && I2CRBIF) //I2C接收缓冲器有接收数据
{
I2CRB_reg = I2CRB; //读接收缓冲器,硬件清接收中断标志
}
if(I2CTBIE && I2CTBIF) //I2C发送缓冲器未满标志
{
if(I2C_restart == 1)
{
I2CTB = I2CRB_reg; //写原码至发送缓冲器
I2CTE = 1;
I2C_restart = 0;
}
else
{
I2CTB_reg = ~I2CRB_reg;
I2CTB = I2CTB_reg; //写反码至发送缓冲器
I2CTE = 1;
I2C_restart = 1;
}
}
if(I2CNAIE && I2CNAIF) //I2C接收溢出中断使能
{
I2CTBIE = 0;
I2CNAIF = 0;
}
if(I2CSPIE && I2CSPIF) //收到结束位
{
I2CSPIF = 0; //清结束位中断标志
I2C_restart = 0;
I2CRST = 1; //I2C模块复位使能
while(I2CRST); //I2C模块复位完成
I2CX16 = 0x00; //禁止采样滤波
I2CC = 0xE0; //I2C使能,上拉,开漏输入输出,I2C时钟下拉等待使能
I2CSA = 0x5A; //从机地址=0x5A
I2CIEC = 0x43; //I2C接收未应答中断使能位 I2C接收结束位中断使能 I2C接收“起始位+从机地址匹配+发送应答位”中断使能
I2CIFC = 0x00; //清中断标志
I2CIE = 1; //I2C通讯总中断使能
I2CEN = 1; //I2C使能
}
I2CIF = 0;
}
}
/*********************************************************
函数名: void main()
描 述: 主函数
输入值: 无
输出值: 无
返回值: 无
**********************************************************/
void main()
{
ram_clear(); //RAM初始化
Int_vectors_init(); //向量中断模式
PBS = 0; //数字I/O
PBT4 = 1; //PB4(SCL)
PBT5 = 1; //PB5(SDA)
PBPU4 = 1; //使能上拉
PBPU5 = 1;
I2C_restart = 0;
Init_i2c();
GIE = 1;
while (1)
{
__Asm CWDT;
}
}