[研电赛技术支持] GD32 硬件I2C从机代码

[复制链接]
 楼主| heimaojingzhang 发表于 2025-6-11 18:37 | 显示全部楼层 |阅读模式
本工程使用GD32E230单片机做从机,接收到主机的命令字节,然后从机发送相应数据,亲测可使用。

首先完成从机I2C的初始化配置。然后完成事件中断代码,本例程代码实现功能是:从机收到主机的命令字节raw_CMD=0x01,然后进入接收数据中断,进入条件语if(data_CMD[0]==raw_CMD)。将diff_16t数组四个int16_t的数据分别拆分成两个字节,然后赋值给发送缓冲区tx_data。

具体代码如下:

#include <string.h>  // 需要包含头文件
volatile uint8_t raw_CMD = 0x01;//读取原始数据   
uint8_t tx_data[16] = {0};  // 待发送数据

extern int16_t diff_16t[8];
uint8_t my_addr = 0x0A;

/* 初始化I2C从机 */
void i2c_slave_init(void)
{
    // 1. 使能时钟
    rcu_periph_clock_enable(RCU_GPIOA);
    rcu_periph_clock_enable(RCU_I2C0);
    // 2. 配置GPIO: PA9(SCL), PA10(SDA)
        gpio_af_set(GPIOA, GPIO_AF_4, GPIO_PIN_9 | GPIO_PIN_10);
    gpio_mode_set(GPIOA, GPIO_MODE_AF, GPIO_PUPD_PULLUP, GPIO_PIN_9 | GPIO_PIN_10);
    gpio_output_options_set(GPIOA, GPIO_OTYPE_OD, GPIO_OSPEED_50MHZ, GPIO_PIN_9 | GPIO_PIN_10);
    // 3. 配置I2C从机模式
    i2c_clock_config(I2C0, 400000, I2C_DTCY_2);           // 400kHz标准模式
    i2c_mode_addr_config(I2C0, I2C_I2CMODE_ENABLE, I2C_ADDFORMAT_7BITS, my_addr);
    i2c_enable(I2C0);
        i2c_ack_config(I2C0, I2C_ACK_ENABLE);                 // 启用ACK
    //i2c_stretch_scl_low_config(I2C0, I2C_SCLSTRETCH_ENABLE); // 启用时钟拉伸
       
        i2c_interrupt_enable(I2C0, I2C_INT_ERR);
    i2c_interrupt_enable(I2C0, I2C_INT_BUF);
    i2c_interrupt_enable(I2C0, I2C_INT_EV);
       
        nvic_irq_enable(I2C0_EV_IRQn, 1);     // 仅需中断号和优先级
        nvic_irq_enable(I2C0_ER_IRQn, 0);     // 优先级0
}

/* I2C事件中断处理 */
void I2C0_EV_IRQHandler(void)
{
    uint32_t stat0 = I2C_STAT0(I2C0);

    // 地址匹配中断
    if (i2c_interrupt_flag_get(I2C0, I2C_INT_FLAG_ADDSEND))
        {
        i2c_interrupt_flag_clear(I2C0, I2C_INT_FLAG_ADDSEND);
    }
    // 接收数据中断
    else if (i2c_interrupt_flag_get(I2C0, I2C_INT_FLAG_RBNE))
        {
        rx_data = i2c_data_receive(I2C0);
                data_CMD[add]=rx_data;
                add ++;
               
                if(data_CMD[0]==raw_CMD)
                {
                        tx_data[0] = diff_16t[0] & 0xFF;
                        tx_data[1]= (diff_16t[0] >> 8) & 0xFF;

                        tx_data[2] = diff_16t[1] & 0xFF;
                        tx_data[3]= (diff_16t[1] >> 8) & 0xFF;

                        tx_data[4] = diff_16t[3] & 0xFF;
                        tx_data[5] = (diff_16t[3] >> 8) & 0xFF;

                        tx_data[6] = diff_16t[4] & 0xFF;
                        tx_data[7] = (diff_16t[4] >> 8) & 0xFF;       
                       
                        add=0;
                }
    }
    // 发送数据中断
    else if (i2c_interrupt_flag_get(I2C0, I2C_INT_FLAG_TBE))
        {
        if (data_CMD[0]==raw_CMD && tx_index < 8)
                {
                        i2c_data_transmit(I2C0, tx_data[tx_index++]);
        }
                else
                {
                        i2c_data_transmit(I2C0, 0xFF); // 数据发送完毕后填充0
        }
    }
    // 停止条件检测
    else if (i2c_interrupt_flag_get(I2C0, I2C_INT_FLAG_STPDET))
        {
                i2c_stop_on_bus(I2C0);
                tx_index=0;
    }
        else if (i2c_interrupt_flag_get(I2C0, I2C_INT_FLAG_AERR))
    {
        tx_index = 0;
    }
}

/* I2C错误中断处理 */
void I2C0_ER_IRQHandler(void)
{
    if (i2c_interrupt_flag_get(I2C0, I2C_INT_FLAG_BERR))
        {
        i2c_interrupt_flag_clear(I2C0, I2C_INT_FLAG_BERR);
    }
    if (i2c_interrupt_flag_get(I2C0, I2C_INT_FLAG_LOSTARB))
        {
        i2c_interrupt_flag_clear(I2C0, I2C_INT_FLAG_LOSTARB);
    }
    if (i2c_interrupt_flag_get(I2C0, I2C_INT_FLAG_AERR))
        {
        i2c_interrupt_flag_clear(I2C0, I2C_INT_FLAG_AERR);
    }
    if (i2c_interrupt_flag_get(I2C0, I2C_INT_FLAG_OUERR))
        {
        i2c_interrupt_flag_clear(I2C0, I2C_INT_FLAG_OUERR);
    }
}


————————————————

                            版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。

原文链接:https://blog.csdn.net/kangcongcong/article/details/148012331

您需要登录后才可以回帖 登录 | 注册

本版积分规则

106

主题

4333

帖子

4

粉丝
快速回复 在线客服 返回列表 返回顶部