21

GD32VF103 I2C从机模板

 4 years ago
source link: https://www.taterli.com/6191/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

作为I2C从机程序,关键变量aReceiveBuffer以及关键常量I2C0_SLAVE_ADDRESS7,第一个是I2C设备寄存器内容,第二个是I2C地址.

当上位机读写寄存器时候,实际上读写的是aReceiveBuffer的内容,除了0x00这个之外,其他全部可以读写.算是比较方便实现某些功能.

编译器:toolchain-gd32v 9.2.0 [GCC]

#include "gd32vf103.h"
#include "systick.h"
#include <stdio.h>
#include <stdint.h>
 
/* 这里指定的地址是0x41. */
#define I2C0_SLAVE_ADDRESS7 0x82
 
uint8_t ubRegIndex = 0;
uint8_t aReceiveBuffer[255];
 
/* GD32VF103 I2C 事件处理模块 */
void I2C0_EV_IRQHandler(void)
{
    /* 收到地址请求 */
    if (i2c_interrupt_flag_get(I2C0, I2C_INT_FLAG_ADDSEND))
    {
        i2c_interrupt_flag_clear(I2C0, I2C_INT_FLAG_ADDSEND);
        /* 收到主机写入有2个可能,写地址/写数据. */
    }
    else if (i2c_interrupt_flag_get(I2C0, I2C_INT_FLAG_RBNE))
    {
        if (ubRegIndex == 0)
        {
            ubRegIndex = i2c_data_receive(I2C0);
        }
        else
        {
            aReceiveBuffer[ubRegIndex++] = i2c_data_receive(I2C0);
        }
        /* 收到主机读取就应该把读取内容送上 */
    }
    else if (i2c_interrupt_flag_get(I2C0, I2C_INT_FLAG_TBE))
    {
        i2c_data_transmit(I2C0, aReceiveBuffer[ubRegIndex++]);
        /* 如果收到主机停,那应该停. */
    }
    else if (i2c_interrupt_flag_get(I2C0, I2C_INT_FLAG_STPDET))
    {
        i2c_stop_on_bus(I2C0);
        ubRegIndex = 0;
        /* 如果收到的是NACK,也代表主机不想再发数据了. */
    }
    else if (i2c_interrupt_flag_get(I2C0, I2C_INT_FLAG_AERR))
    {
        ubRegIndex = 0;
    }
}
 
void I2C0_ER_IRQHandler(void)
{
}
 
int main(void)
{
    /* 时钟初始化 */
    rcu_periph_clock_enable(RCU_GPIOB);
    rcu_periph_clock_enable(RCU_I2C0);
    /* I2C GPIO 初始化 : PB6 => I2C0_SCL,PB7 => I2C0_SDA */
    gpio_init(GPIOB, GPIO_MODE_AF_OD, GPIO_OSPEED_50MHZ, GPIO_PIN_6 | GPIO_PIN_7);
    /* 复位I2C外设 */
    i2c_software_reset_config(I2C0, I2C_SRESET_SET);
    i2c_software_reset_config(I2C0, I2C_SRESET_RESET);
    /* I2C时钟配置,作为从机,这个不重要. */
    i2c_clock_config(I2C0, 100000, I2C_DTCY_2);
    /* I2C地址配置 */
    i2c_mode_addr_config(I2C0, I2C_I2CMODE_ENABLE, I2C_ADDFORMAT_7BITS, I2C0_SLAVE_ADDRESS7);
    /* 使能I2C */
    i2c_enable(I2C0);
    /* 允许ACK */
    i2c_ack_config(I2C0, I2C_ACK_ENABLE);
    /* 开启中断事务处理 */
    i2c_interrupt_enable(I2C0, I2C_INT_ERR);
    i2c_interrupt_enable(I2C0, I2C_INT_EV);
    i2c_interrupt_enable(I2C0, I2C_INT_BUF);
 
    eclic_global_interrupt_enable();
    eclic_irq_enable(I2C0_EV_IRQn, 1, 0);
 
    while (1)
    {
    }
}

效果演示.

yYN7Rza.png!web

为了可读性,就没必要脱裤子放屁写寄存器版本了,我相信编译器能把这点差距抹平,就这么用吧.


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK