华大单片机HC32L130/HC32L136从机IIC通信

从机IIC理论知识

主机IIC的做法比较多,从机IIC的就相对比较难一点。
先补充一下从机IIC的思路:
在这里插入图片描述
先看IIC时序图,然后根据时序图理清IIC从机需要做哪些判断:
从机发送:
·判断IIC START信号,有IIC start信号过来之后进入从机地址接收判断
·判断SCL搞低电平
·在IIC高电平期间判断SDA电平
·接收到八位从机地址后判断地址是否跟设备从机地址一致
·接收到的从机地址跟设备地址一致则从机发送ACK
·判断地址位的最低位是0还是1,0为主机写数据,1为主机读数据
·接收八位寄存器地址
·再次检测IIC START信号
·接收八位从机地址
·进入从机发送数据的程序。
从机发送:
·判断IIC START信号,有IIC start信号过来之后进入从机地址接收判断
·判断SCL搞低电平
·在IIC高电平期间判断SDA电平
·接收到八位从机地址后判断地址是否跟设备从机地址一致
·接收到的从机地址跟设备地址一致则从机发送ACK
·判断地址位的最低位是0还是1,0为主机写数据,1为主机读数据
·接收八位寄存器地址
·接收数据

华大单片机HC32L130/HC32L136从机IIC通信

选用中断方式进行:

uint8_t u8Recdata1[10] = {0x00};
uint8_t u8Recdata[10]={0x00};
uint8_t u8SendLen=0;
uint8_t u8RecvLen=0;
uint8_t u8RecvLen1=0;
uint8_t u8State = 0;
static void I2c0CallBack(void)
{
u8State = I2C_GetState(I2C0);
    switch(u8State)
    {
    case 0x60:
        case 0x70:
        case 0xa0:
            u8RecvLen = 0;
            I2C_SetFunc(I2C0,I2cAck_En);
            break;
        case 0x68:
        case 0x78:
        case 0x88:
        case 0x98:
            I2C_SetFunc(I2C0,I2cAck_En);
            break;
        case 0x80:
  case 0x90:    
   u8Recdata[u8RecvLen++] = I2C_ReadByte(I2C0);//接收数据
            break;  
        case 0xa8://接收读命令返回ACK
  case 0xb0:
            u8SendLen = 0;
            I2C_WriteByte(I2C0,u8Recdata[u8SendLen++]);//发送数据首字节
            break;
        case 0xb8:
            I2C_WriteByte(I2C0,u8Recdata[u8SendLen++]);
            break;
        case 0xc0:
        case 0xc8:
            break;
    }
    I2C_ClearIrq(I2C0);
}


void IIC_SlaveGpioConfig(void)
{
stc_i2c_addr_t stcSlaveAddr;
    stc_gpio_config_t stcGpioCfg;
    stc_i2c_config_t stcI2cCfg;
    stc_sysctrl_clk_config_t stcCfg;
    DDL_ZERO_STRUCT(stcCfg);
    DDL_ZERO_STRUCT(stcI2cCfg);
    DDL_ZERO_STRUCT(stcGpioCfg);
    DDL_ZERO_STRUCT(stcSlaveAddr);
    Sysctrl_ClkSourceEnable(SysctrlClkRCL,TRUE);
    Sysctrl_SysClkSwitch(SysctrlClkRCL);
    Sysctrl_SetRCHTrim(SysctrlRchFreq24MHz);
 Sysctrl_SysClkSwitch(SysctrlClkRCH);
 Sysctrl_ClkSourceEnable(SysctrlClkRCL,FALSE);
    Sysctrl_SetPeripheralGate(SysctrlPeripheralGpio,TRUE);
    Sysctrl_SetPeripheralGate(SysctrlPeripheralI2c0,TRUE);
    stcGpioCfg.enDir = GpioDirOut;
    stcGpioCfg.enOD = GpioOdEnable;
    stcGpioCfg.enPuPd = GpioPu;
    Gpio_Init(GpioPortB, GpioPin8,&stcGpioCfg);//端口初始化
    Gpio_Init(GpioPortB, GpioPin9,&stcGpioCfg);
    Gpio_SetAfMode(GpioPortB, GpioPin8,GpioAf1);//SCL
    Gpio_SetAfMode(GpioPortB, GpioPin9,GpioAf1);//SDA
    stcI2cCfg.enFunc = I2cBaud_En;
    stcI2cCfg.u8Tm = 0x02;//1M=(24000000/(8*(2+1))//波特率配置
    stcI2cCfg.pfnI2c0Cb = I2c0CallBack;
    stcI2cCfg.bTouchNvic = TRUE;
    I2C_DeInit(I2C0);
    stcSlaveAddr.Addr = 0x12;
    stcSlaveAddr.Gc = 0;
    I2C_Init(I2C0,&stcI2cCfg);//模块初始化
 I2C_WriteSlaveAddr(I2C0,&stcSlaveAddr);//写从机设备地址
    I2C_SetFunc(I2C0,I2cMode_En);//模块使能
    I2C_SetFunc(I2C0,I2cAck_En);//ACK打开
  if(TRUE == stcI2cCfg.bTouchNvic)
  {
  EnableNvic(I2C0_IRQn,IrqLevel3,TRUE);
  }
}

int32_t main(void)
{
IIC_SlaveGpioConfig()while(1)
{
}
}

自己找一个主机跟这个例程通信就可以了,有一个需要注意的点就是,从机地址跟主机地址必须一致才行。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值