HC32 IIC/I2C读写

IIC状态码

IIC 初始化

cpp 复制代码
void iicInit(uint32_t speed)
{
    stc_gpio_cfg_t stcGpioCfg;
    DDL_ZERO_STRUCT(stcGpioCfg);
    Sysctrl_SetPeripheralGate(SysctrlPeripheralGpio, TRUE);  //开启GPIO时钟门控
    stcGpioCfg.enDir = GpioDirOut;                           ///< 端口方向配置->输出
    stcGpioCfg.enOD = GpioOdEnable;                          ///< 开漏输出
    stcGpioCfg.enPu = GpioPuEnable;                          ///< 端口上拉配置->使能
    stcGpioCfg.enPd = GpioPdDisable;                         ///< 端口下拉配置->禁止
    Gpio_Init(GpioPortB, GpioPin8, &stcGpioCfg);             ///< 端口初始化
    Gpio_Init(GpioPortB, GpioPin9, &stcGpioCfg);
    Gpio_SetAfMode(GpioPortB, GpioPin8, GpioAf1);            ///< 配置PB08为SCL
    Gpio_SetAfMode(GpioPortB, GpioPin9, GpioAf1);            ///< 配置PB09为SDA
    stc_i2c_cfg_t stcI2cCfg;
    DDL_ZERO_STRUCT(stcI2cCfg);                            ///< 初始化结构体变量的值为0
    Sysctrl_SetPeripheralGate(SysctrlPeripheralI2c0, TRUE); ///< 开启I2C0时钟门控
    stcI2cCfg.u32Pclk = Sysctrl_GetPClkFreq();             ///< 获取PCLK时钟
    stcI2cCfg.u32Baud = speed;                           ///< 1MHz
    stcI2cCfg.enMode = I2cMasterMode;                      ///< 主机模式
    stcI2cCfg.u8SlaveAddr = SLAVE_ADDR;             ///< 从地址,主模式无效
    stcI2cCfg.bGc = FALSE;                                 ///< 广播地址应答使能关闭
    I2C_Init(M0P_I2C0, &stcI2cCfg);                        ///< 模块初始化
}

IIC读写

cpp 复制代码
/**
 ******************************************************************************
 ** 主机接收函数
 ** @param: I2CX
 ** @param: I2C_DEVADDR    从机设备地址
 ** @param:register_addr  读取寄存器addr
 ** @param:pu8Data        读取addr的 data值
 ** @param: u32Len         读取长度
 **
 ******************************************************************************/
en_result_t I2C_MasterReadData(M0P_I2C_TypeDef *I2CX, uint8_t I2C_DEVADDR, uint8_t register_addr, uint8_t *pu8Data, uint32_t u32Len)
{
    en_result_t enRet = Error;
    uint8_t u8i = 0, u8State;

    I2C_SetFunc(I2CX, I2cStart_En);

    while (1)
    {
        while (0 == I2C_GetIrq(I2CX))
        {;}
        u8State = I2C_GetState(I2CX);
        switch (u8State)
        {
        case 0x08:                                    //已发送起始条件,将发送SLA+R
            I2C_ClearFunc(I2CX, I2cStart_En);
            I2C_WriteByte(I2CX, (I2C_DEVADDR));       //发送SLA+W
            break;
        case 0x18:                                    //已发送SLA+W,并接收到ACK
            I2C_WriteByte(I2CX, register_addr);       //发送内存地址
            break;
        case 0x28:                                    //已发送数据,接收到ACK
            I2C_SetFunc(I2CX, I2cStart_En);
            break;
        case 0x10:                                    //已发送重复起始条件
            I2C_ClearFunc(I2CX, I2cStart_En);
            I2C_WriteByte(I2CX, (I2C_DEVADDR) | 0x01); //读命令发送
            break;
        case 0x40:                                    //已发送SLA+R,并接收到ACK
            if (u32Len > 1)
            {
                I2C_SetFunc(I2CX, I2cAck_En);
            }
            break;
        case 0x50:                                    //已接收数据字节,并已返回ACK信号
            pu8Data[u8i++] = I2C_ReadByte(I2CX);
            if (u8i == u32Len - 1)
            {
                I2C_ClearFunc(I2CX, I2cAck_En);       //读数据时,倒数第二个字节ACK关闭
            }
            break;
        case 0x58:                                    //已接收到最后一个数据,NACK已返回
            pu8Data[u8i++] = I2C_ReadByte(I2CX);
            I2C_SetFunc(I2CX, I2cStop_En);            //发送停止条件
            break;
        case 0x38:                                    //在发送地址或数据时,仲裁丢失
            I2C_SetFunc(I2CX, I2cStart_En);           //当总线空闲时发起起始条件
            break;
        case 0x48:                                    //发送SLA+R后,收到一个NACK
            I2C_SetFunc(I2CX, I2cStop_En);
            I2C_SetFunc(I2CX, I2cStart_En);
            break;
        default:                                      //其他错误状态,重新发送起始条件
            I2C_SetFunc(I2CX, I2cStart_En);           //其他错误状态,重新发送起始条件
            break;
        }
        I2C_ClearIrq(I2CX);                               //清除中断状态标志位
        if (u8i == u32Len)                                //数据全部读取完成,跳出while循环
        {
            break;
        }
    }
    enRet = Ok;
    return enRet;
}

/**
 ******************************************************************************
 ** 主机发送函数
 ** @param: I2CX
 ** @param: I2C_DEVADDR    从机设备地址
 ** @param:register_addr  写入寄存器addr
 ** @param:pu8Data        写入addr的 data值
 ** @param: u32Len         写入长度
 **
 ******************************************************************************/
en_result_t I2C_MasterWriteData(M0P_I2C_TypeDef *I2CX, uint8_t I2C_DEVADDR, uint8_t register_addr, uint8_t *pu8Data, uint32_t u32Len)
{
    en_result_t enRet = Error;
    uint8_t u8i = 0, u8State;
    I2C_SetFunc(I2CX, I2cStart_En);
    while (1)
    {
        while (0 == I2C_GetIrq(I2CX))
        {;}
        u8State = I2C_GetState(I2CX);
        switch (u8State)
        {
        case 0x08:                                 ///已发送起始条件
            I2C_ClearFunc(I2CX, I2cStart_En);
            I2C_WriteByte(I2CX, (I2C_DEVADDR));    ///从设备地址发送
            break;
        case 0x18:                                 ///已发送SLA+W,并接收到ACK
            I2C_WriteByte(I2CX, register_addr);
            break;
        case 0x28:                                 ///上一次发送数据后接收到ACK
            I2C_WriteByte(I2CX, pu8Data[u8i++]);
            break;
        case 0x20:                                 ///上一次发送SLA+W后,收到NACK
        case 0x38:                                 ///上一次在SLA+读或写时丢失仲裁
            I2C_SetFunc(I2CX, I2cStart_En);        ///当I2C总线空闲时发送起始条件
            break;
        case 0x30:                                 ///已发送I2Cx_DATA中的数据,收到NACK,将传输一个STOP条件
            I2C_SetFunc(I2CX, I2cStop_En);         ///发送停止条件
            break;
        default:
            break;
        }
        if (u8i > u32Len)
        {
            I2C_SetFunc(I2CX, I2cStop_En);             ///此顺序不能调换,出停止条件
            I2C_ClearIrq(I2CX);
            break;
        }
        I2C_ClearIrq(I2CX);                            ///清除中断状态标志位
    }
    enRet = Ok;
    return enRet;
}
相关推荐
hsjiasb1 天前
FreeRTOS学习(二十六)——动态内存管理heap_1到heap_5
stm32·单片机·学习·学习笔记·freertos
周洲08301 天前
STM32 GPIO 外部中断深度解析:边沿触发 / 电平触发、NVIC 优先级配置、中断嵌套实战
stm32·单片机·嵌入式硬件
LCG元1 天前
STM32F103 CAN 总线通信实战:标准库双机通信与过滤器配置精讲
stm32·单片机·嵌入式硬件
zlinear数据采集卡1 天前
D223的PWM电机控制:6路独立脉冲+加减速算法深度解析
arm开发·stm32·嵌入式硬件·算法·fpga开发·架构
Kuakewei8881 天前
平芯微42V热拔插OVP过压保护芯片:PW1600
嵌入式硬件
ACP广源盛139246256731 天前
WAIC2026 国产超节点算力浪潮下@ACP#IX9104 在算力矩阵中的定位与落地场景
大数据·数据库·人工智能·嵌入式硬件·线性代数·矩阵
z20348315201 天前
STM32单片机控制无源蜂鸣器播放《晴天》
stm32·单片机·嵌入式硬件
国科安芯1 天前
详解ADC 规则组外部触发:CH2、CH3 与 TRGO2
运维·网络·单片机·嵌入式硬件·mcu·系统架构
ACP广源盛139246256731 天前
WAIC2026 国产算力浪潮@ACP#YLB3118 在算力矩阵中的存储定位与落地场景
大数据·人工智能·分布式·单片机·嵌入式硬件
ACP广源盛139246256731 天前
WAIC2026 国产算力浪潮下@ACP#IX8024 在算力矩阵中的定位与落地场景
大数据·数据库·人工智能·嵌入式硬件·线性代数·矩阵