打印
[ARM入门]

【每周分享】I2C原理代码结合(干货)看图易懂

[复制链接]
901|3
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
本帖最后由 虚幻的是灵魂 于 2024-10-15 15:19 编辑

#申请原创#
@21小跑堂
I2C通讯规则

I2C总线包括两根信号线:SDA(串行数据线)和SCL(串行时钟线)。这两根信号线共用一个总线,因此在总线上可以连接多个设备。在I2C总线上,每个设备都有一个唯一的地址,用于标识设备。

SCL线是时钟线,用于控制数据传输的速度和时序;SDA线是数据线,用于传输实际的数据。

I2C写操作

流程如下:

  • 开始。
  • 发送设备地址,等待从设备响应
  • 发送寄存器地址,等待从设备响应
  • 发送一个字节,等待从设备响应。这个操作是循环执行,直到没有数据。
  • 停止。


I2C读流程

流程如下:

  • 开始。
  • 发送设备地址(写地址),等待从设备响应
  • 发送寄存器地址,等待从设备响应。
  • 开始
  • 发送设备地址(读地址),等待从设备响应
  • 接收一个字节,发送响应给从设备。这个操作是循环执行,直到没有数据。当是最后一个数据时,发送空响应。
  • 停止。

通讯信号开始

Start代码表示
static void start() {
    SDA_OUT();

    SDA(1);
    delay_1us(5);
    SCL(1);
    delay_1us(5);

    SDA(0);
    delay_1us(5);
    SCL(0);
    delay_1us(5);
}
结束


Stop代码表示
static void stop() {
    SDA_OUT();

    SCL(0);
    SDA(0);

    SCL(1);
    delay_1us(5);
    SDA(1);
    delay_1us(5);
}
发送数据bit发送


数据有效性:
  • SCL上升沿到下降沿这个阶段,SDA电平的高低,表示数据bit的1和0
  • 如果SDA电平在这个阶段发生变化,则无效,参考start和stop信号。

Byte发送

基于数据有效性,将byte按bit位变化为高低电平,发送出去。

发送byte表示

static void send(uint8_t data) {
    uint8_t i;
    SDA_OUT();

    for(i = 0; i < 8; i++) {
        if(data & 0x80) {
            SDA(1);
        } else {
            SDA(0);
        }
        SCL(1);
        delay_1us(5);
        SCL(0);
        delay_1us(5);
        data <<= 1;
    }
}

等待响应
wait ack:Acknowledge character。表示等待响应,每发送一个数据,需要确认对方是否收到,就需要等待对方响应。



等待响应表示
static uint8_t wait_ack() {
    int8_t retry = 10;

    SCL(0);
    SDA(1);
    SDA_IN();
    delay_1us(5);
    SCL(1);
    delay_1us(5);

    while(SDA_STATE() == 1 && retry > 0) {
        retry --;
        delay_1us(5);
    }

    if(retry <= 0) {
        stop();
        return 1;
    } else {
        SCL(0);
        SDA_OUT();
    }
    return 0;
}
结合代码

接收数据bit接收

Byte接收

逻辑分析仪测的:

说明: 在上升沿写入数据时,会获取从设备控制权,   上升沿写入数据; SCL在高电平时,会释放从设备控制权, 直到从设备被拉低后,主设备才响应成功。


接收byte代码表示

static uint8_t recv() {
    uint8_t i, data;
    SDA_IN();
    data = 0;
    for(i = 0; i < 8; i++) {
        SCL(0);
        delay_1us(5);
        SCL(1);
        delay_1us(5);

        data <<= 1;

        data |= SDA_STATE();

        delay_1us(5);
    }
    SCL(0);
    return data;
}

发送响应


发送ACK
static void send_ack() {
    SDA_OUT();
    SCL(0);
    SDA(0);
    delay_1us(5);

    SDA(0);

    SCL(1);
    delay_1us(5);
    SCL(0);
    SDA(1);
}
发送NACK

static void send_nack() {
    SDA_OUT();
    SCL(0);
    SDA(0);
    delay_1us(5);

    SDA(1);

    SCL(1);
    delay_1us(5);
    SCL(0);
    SDA(1);
}
软件I2C开发流程
  • 引脚初始化
  • 引脚功能定义
  • 实现读操作
  • 实现写操作

GD32软件I2C初始化

void SoftI2C_init() {
    // 时钟配置
    rcu_periph_clock_enable(SCL_RCU);
    // 设置输出模式
    gpio_mode_set(SCL_PORT, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, SCL_PIN);
    gpio_output_options_set(SCL_PORT, GPIO_OTYPE_OD, GPIO_OSPEED_50MHZ, SCL_PIN);

    // 时钟配置
    rcu_periph_clock_enable(SDA_RCU);
    // 设置输出模式
    gpio_mode_set(SDA_PORT, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, SDA_PIN);
    gpio_output_options_set(SDA_PORT, GPIO_OTYPE_OD, GPIO_OSPEED_50MHZ, SDA_PIN);
}
  • I2C引脚高低电平
GD32软件I2C引脚功能
#define SCL_RCU                RCU_GPIOB
#define SCL_PORT        GPIOB
#define SCL_PIN                GPIO_PIN_6
#define SCL_AF                GPIO_AF_4

#define SDA_RCU                RCU_GPIOB
#define SDA_PORT        GPIOB
#define SDA_PIN                GPIO_PIN_7
#define SDA_AF                GPIO_AF_4

/************** io ***************/
#define SCL(BIT)                 gpio_bit_write(SCL_PORT, SCL_PIN, BIT?SET:RESET)
#define SDA(BIT)                 gpio_bit_write(SDA_PORT, SDA_PIN, BIT?SET:RESET)
#define SDA_STATE()         gpio_input_bit_get(SDA_PORT, SDA_PIN)

#define SDA_IN()          gpio_mode_set(SDA_PORT, GPIO_MODE_INPUT,  GPIO_PUPD_NONE, SDA_PIN)
#define SDA_OUT()         gpio_mode_set(SDA_PORT, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, SDA_PIN)
  • IO引脚定义
  • 引脚输出模式高低电平输出:SCL高和低,SDA高和低
  • SDA模式配置:SDA输出模式,SDA输入模式
  • SDA输入模式状态读取。
写操作


代码:
uint8_t SoftI2C_write(uint8_t addr, uint8_t reg, uint8_t* data, uint32_t len) {
    start();

    send(addr << 1);                        //发送设备写地址
    if(wait_ack()) return 1;        //等待响应

    send(reg);                                        //发送寄存器地址
    if(wait_ack()) return 2;        //等待响应

    do {
        send(*data++);
        if(wait_ack()) return 3;
    } while(--len);

    stop();
    return 0;
}
读操作

代码:
uint8_t SoftI2C_read(uint8_t addr, uint8_t reg, uint8_t* data, uint32_t len) {
    start();

    send(addr << 1);                                //发送设备写地址
    if(wait_ack()) return 1;                //等待响应

    send(reg);                                                //发送寄存器地址
    if(wait_ack()) return 2;                //等待响应

    start();
    send((addr << 1) | 0x01);                //发送设备读地址
    if(wait_ack()) return 3;                //等待响应

    do {
        *data = recv();
        data++;
        if(len != 1) send_ack();        // 发送 NACK
    } while(--len);
    send_nack();                                        // 发送 NACK
    stop();

    return 0;
}
逻辑分析仪解析:

说明:读取时,会有两个开始标记。从设备会获取控制权,获取数据并发送给主设备。





硬件I2C-GD32F4系列初始化操作
uint32_t i2cx_scl_port_rcu = RCU_GPIOB;
uint32_t i2cx_scl_port = GPIOB;
uint32_t i2cx_scl_pin = GPIO_PIN_6;
uint32_t i2cx_scl_af = GPIO_AF_4;

uint32_t i2cx_sda_port_rcu = RCU_GPIOB;
uint32_t i2cx_sda_port = GPIOB;
uint32_t i2cx_sda_pin = GPIO_PIN_7;
uint32_t i2cx_sda_af = GPIO_AF_4;

uint32_t i2cx = I2C0;
uint32_t i2cx_rcu = RCU_I2C0;
uint32_t i2cx_speed = 400000;
/****************** GPIO config **********************/
// 时钟配置
rcu_periph_clock_enable(i2cx_scl_port_rcu);
// 设置复用功能
gpio_af_set(i2cx_scl_port, i2cx_scl_af, i2cx_scl_pin);
// 设置输出模式
gpio_mode_set(i2cx_scl_port, GPIO_MODE_AF, GPIO_PUPD_NONE, i2cx_scl_pin);
gpio_output_options_set(i2cx_scl_port, GPIO_OTYPE_OD, GPIO_OSPEED_50MHZ, i2cx_scl_pin);

// 时钟配置
rcu_periph_clock_enable(i2cx_sda_port_rcu);
// 设置复用功能
gpio_af_set(i2cx_sda_port, i2cx_sda_af, i2cx_sda_pin);
// 设置输出模式
gpio_mode_set(i2cx_sda_port, GPIO_MODE_AF, GPIO_PUPD_NONE, i2cx_sda_pin);
gpio_output_options_set(i2cx_sda_port, GPIO_OTYPE_OD, GPIO_OSPEED_50MHZ, i2cx_sda_pin);

/****************** I2C config  **********************/
i2c_deinit(i2cx);
// 时钟配置
rcu_periph_clock_enable(i2cx_rcu);
// I2C速率配置
i2c_clock_config(i2cx, i2cx_speed, I2C_DTCY_2);

// 使能i2c
i2c_mode_addr_config(i2cx, I2C_I2CMODE_ENABLE, I2C_ADDFORMAT_7BITS, 0x00);
i2c_enable(i2cx);

// i2c ack enable
i2c_ack_config(i2cx, I2C_ACK_ENABLE);
  • 哪个I2C
  • SCL是哪个引脚
  • SDA是哪个引脚
  • 速度是多快
写操作流程开始
/************* start ***********************/
// 等待I2C闲置
if(I2C_waitn(i2cx, I2C_FLAG_I2CBSY)) return 1;

// start
i2c_start_on_bus(i2cx);

// 等待I2C主设备成功发送起始信号
if(I2C_wait(i2cx, I2C_FLAG_SBSEND)) return 2;
发送设备地址
/************* device address **************/
// 发送设备地址
i2c_master_addressing(i2cx, address, I2C_TRANSMITTER);
// 等待地址发送完成
if(I2C_wait(i2cx, I2C_FLAG_ADDSEND)) return 3;
i2c_flag_clear(i2cx, I2C_FLAG_ADDSEND);
发送寄存器地址
/************ register address ************/
// 寄存器地址
// 等待发送数据缓冲区为空
if(I2C_wait(i2cx, I2C_FLAG_TBE)) return 4;

// 发送数据
i2c_data_transmit(i2cx, reg);

// 等待数据发送完成
if(I2C_wait(i2cx, I2C_FLAG_BTC)) return 5;
数据发送
/***************** data ******************/
// 发送数据
uint32_t i;
for(i = 0; i < data_len; i++) {
    uint32_t d = data[i];

    // 等待发送数据缓冲区为空
    if(I2C_wait(i2cx, I2C_FLAG_TBE)) return 6;

    // 发送数据
    i2c_data_transmit(i2cx, d);

    // 等待数据发送完成
    if(I2C_wait(i2cx, I2C_FLAG_BTC)) return 7;
}
停止
/***************** stop ********************/
// stop
i2c_stop_on_bus(i2cx);
if(I2C_waitn(i2cx, I2C_CTL0(I2C0)&I2C_CTL0_STOP)) return 8;
读操作流程开始
/************* start ***********************/
// 等待I2C空闲
if(I2C_waitn(i2cx, I2C_FLAG_I2CBSY)) return 1;

// 发送启动信号
i2c_start_on_bus(i2cx);
if(I2C_wait(i2cx, I2C_FLAG_SBSEND)) return 2;
发送设备地址(写)
/************* device address **************/
// 发送从设备地址
i2c_master_addressing(i2cx, address, I2C_TRANSMITTER);

if(I2C_wait(i2cx, I2C_FLAG_ADDSEND)) return 3;
i2c_flag_clear(i2cx, I2C_FLAG_ADDSEND);
发送寄存器地址
/********** register address **************/
// 等待发送缓冲区        
if(I2C_wait(i2cx, I2C_FLAG_TBE)) return 4;

// 发送寄存器地址
i2c_data_transmit(i2cx, reg);

// 等待发送数据完成        
if(I2C_wait(i2cx, I2C_FLAG_BTC)) return 5;

if(I2C_wait(i2cx, I2C_FLAG_TBE)) return 6;
开始
/************* start ***********************/
// 发送再启动信号
i2c_start_on_bus(i2cx);

if(I2C_wait(i2cx, I2C_FLAG_SBSEND)) return 7;
发送设备地址(读)
/************* device address **************/
// 发送从设备地址
i2c_master_addressing(i2cx, address, I2C_RECEIVER);
if(I2C_wait(i2cx, I2C_FLAG_ADDSEND)) return 8;
i2c_flag_clear(i2cx, I2C_FLAG_ADDSEND);

//ack
i2c_ack_config(i2cx, I2C_ACK_ENABLE);
i2c_ackpos_config(i2cx, I2C_ACKPOS_CURRENT);
if(I2C_wait(i2cx, (I2C_CTL0(i2cx) & I2C_CTL0_ACKEN))) return 23;
数据读取
/************* data **************/
//ack
i2c_ack_config(i2cx, I2C_ACK_ENABLE);
i2c_ackpos_config(i2cx, I2C_ACKPOS_CURRENT);
if(I2C_wait(i2cx, (I2C_CTL0(i2cx) & I2C_CTL0_ACKEN))) return 11;

// 读取数据
uint8_t i;
for (i = 0; i < len; i++) {
    if(i != len - 1) {
        // 等待接收缓冲区        
        if(I2C_wait(i2cx, I2C_FLAG_BTC)) return 9;
    }

    // 等待ACK数据发送完成
    // 等待接收缓冲区        
    if(I2C_wait(i2cx, I2C_FLAG_RBNE)) return 10;
    data[i] = i2c_data_receive(i2cx);

    if (i == len - 1) {
        // 在读取最后一个字节之前,禁用ACK,并发送停止信号
        // 配置自动NACK
        i2c_ack_config(i2cx, I2C_ACK_DISABLE);
    }
}
结束
/***************** stop ********************/
i2c_stop_on_bus(i2cx);
if(I2C_waitn(i2cx, I2C_CTL0(I2C0) & I2C_CTL0_STOP)) return 11;
完整代码

I2C0.H

#ifndef __I2C0_H__
#define __I2C0_H__

#include "systick.h"
#include "gd32f4xx.h"

void I2C0_init();

uint8_t I2C0_read(uint8_t addr, uint8_t reg, uint8_t* data, uint32_t len);

uint8_t I2C0_write(uint8_t addr, uint8_t reg, uint8_t* data, uint32_t len);

uint8_t I2C0_write2(uint8_t addr, uint8_t reg, uint8_t* data, uint32_t offset, uint32_t len);

void I2C0_deinit();

#endif

I2C.C

#include "I2C0.h"

void I2C0_init() {
                uint32_t i2cx_scl_port_rcu = RCU_GPIOB;
    uint32_t i2cx_scl_port = GPIOB;
    uint32_t i2cx_scl_pin = GPIO_PIN_6;
    uint32_t i2cx_scl_af = GPIO_AF_4;

    uint32_t i2cx_sda_port_rcu = RCU_GPIOB;
    uint32_t i2cx_sda_port = GPIOB;
    uint32_t i2cx_sda_pin = GPIO_PIN_7;
    uint32_t i2cx_sda_af = GPIO_AF_4;

    uint32_t i2cx = I2C0;
    uint32_t i2cx_rcu = RCU_I2C0;
    uint32_t i2cx_speed = 400000;
    /****************** GPIO config **********************/
    // 时钟配置
    rcu_periph_clock_enable(i2cx_scl_port_rcu);
                // 设置复用功能
    gpio_af_set(i2cx_scl_port, i2cx_scl_af, i2cx_scl_pin);
                // 设置输出模式
    gpio_mode_set(i2cx_scl_port, GPIO_MODE_AF, GPIO_PUPD_NONE, i2cx_scl_pin);
    gpio_output_options_set(i2cx_scl_port, GPIO_OTYPE_OD, GPIO_OSPEED_50MHZ, i2cx_scl_pin);
   
    // 时钟配置
    rcu_periph_clock_enable(i2cx_sda_port_rcu);
    // 设置复用功能
    gpio_af_set(i2cx_sda_port, i2cx_sda_af, i2cx_sda_pin);
                // 设置输出模式
    gpio_mode_set(i2cx_sda_port, GPIO_MODE_AF, GPIO_PUPD_NONE, i2cx_sda_pin);
    gpio_output_options_set(i2cx_sda_port, GPIO_OTYPE_OD, GPIO_OSPEED_50MHZ, i2cx_sda_pin);
   
    /****************** I2C config  **********************/
    i2c_deinit(i2cx);
    // 时钟配置
    rcu_periph_clock_enable(i2cx_rcu);
    // I2C速率配置
    i2c_clock_config(i2cx, i2cx_speed, I2C_DTCY_2);

    // 使能i2c
    i2c_mode_addr_config(i2cx, I2C_I2CMODE_ENABLE, I2C_ADDFORMAT_7BITS, 0x00);
    i2c_enable(i2cx);

    // i2c ack enable
                i2c_ack_config(i2cx, I2C_ACK_ENABLE);
    //i2c_ackpos_config(i2cx, I2C_ACKPOS_CURRENT);
        
}

static uint8_t I2C_wait(uint32_t i2cx, uint32_t flag) {
    uint16_t TIMEOUT = 50000;
    uint16_t cnt = 0;

    while(!i2c_flag_get(i2cx, flag)) {
        cnt++;
        if(cnt > TIMEOUT) return 1;
    }
    return 0;
}

static uint8_t I2C_waitn(uint32_t i2cx, uint32_t flag) {
    uint16_t TIMEOUT = 50000;
    uint16_t cnt = 0;

    while(i2c_flag_get(i2cx, flag)) {
        cnt++;
        if(cnt > TIMEOUT) return 1;
    }
                return 0;
}


uint8_t I2C0_write(uint8_t addr, uint8_t reg, uint8_t* data, uint32_t data_len) {
                uint32_t i2cx = I2C0;
    uint8_t address = addr << 1;
               
                /************* start ***********************/
                // 等待I2C闲置
    if(I2C_waitn(i2cx, I2C_FLAG_I2CBSY)) return 1;
        
    // start
    i2c_start_on_bus(i2cx);
               
                 // 等待I2C主设备成功发送起始信号
    if(I2C_wait(i2cx, I2C_FLAG_SBSEND)) return 2;
        
                /************* device address **************/
    // 发送设备地址
    i2c_master_addressing(i2cx, address, I2C_TRANSMITTER);
                 // 等待地址发送完成
    if(I2C_wait(i2cx, I2C_FLAG_ADDSEND)) return 3;
    i2c_flag_clear(i2cx, I2C_FLAG_ADDSEND);
        
                /************ register address ************/
    // 寄存器地址
    // 等待发送数据缓冲区为空
    if(I2C_wait(i2cx, I2C_FLAG_TBE)) return 4;
               
                // 发送数据
    i2c_data_transmit(i2cx, reg);

    // 等待数据发送完成
    if(I2C_wait(i2cx, I2C_FLAG_BTC)) return 5;
               
                /***************** data ******************/
    // 发送数据
    uint32_t i;
    for(i = 0; i < data_len; i++) {
        uint32_t d = data[i];

        // 等待发送数据缓冲区为空
        if(I2C_wait(i2cx, I2C_FLAG_TBE)) return 6;

        // 发送数据
        i2c_data_transmit(i2cx, d);

        // 等待数据发送完成
        if(I2C_wait(i2cx, I2C_FLAG_BTC)) return 7;
    }
               
                /***************** stop ********************/
    // stop
    i2c_stop_on_bus(i2cx);
    if(I2C_waitn(i2cx, I2C_CTL0(I2C0)&I2C_CTL0_STOP)) return 8;
        
                return 0;
}

uint8_t I2C0_write2(uint8_t addr, uint8_t reg, uint8_t* data, uint32_t offset, uint32_t len) {
    uint32_t i2cx = I2C0;
    uint8_t address = addr << 1;
               
                /************* start ***********************/
                // 等待I2C闲置
    if(I2C_waitn(i2cx, I2C_FLAG_I2CBSY)) return 1;
        
    // start
    i2c_start_on_bus(i2cx);
               
                 // 等待I2C主设备成功发送起始信号
    if(I2C_wait(i2cx, I2C_FLAG_SBSEND)) return 2;
        
                /************* device address **************/
    // 发送设备地址
    i2c_master_addressing(i2cx, address, I2C_TRANSMITTER);
                 // 等待地址发送完成
    if(I2C_wait(i2cx, I2C_FLAG_ADDSEND)) return 3;
    i2c_flag_clear(i2cx, I2C_FLAG_ADDSEND);
        
                /************ register address ************/
    // 寄存器地址
    // 等待发送数据缓冲区为空
    if(I2C_wait(i2cx, I2C_FLAG_TBE)) return 4;
               
                // 发送数据
    i2c_data_transmit(i2cx, reg);

    // 等待数据发送完成
    if(I2C_wait(i2cx, I2C_FLAG_BTC)) return 5;
               
                /***************** data ******************/
    // 发送数据
                do {
        // 等待发送数据缓冲区为空
        if(I2C_wait(i2cx, I2C_FLAG_TBE)) return 6;

        // 发送数据
        i2c_data_transmit(i2cx, *data);
                                data += offset;

        // 等待数据发送完成
        if(I2C_wait(i2cx, I2C_FLAG_BTC)) return 7;
    } while(--len);
               
                /***************** stop ********************/
    // stop
    i2c_stop_on_bus(i2cx);
    if(I2C_waitn(i2cx, I2C_CTL0(I2C0)&I2C_CTL0_STOP)) return 8;
        
                return 0;
}


void I2C0_deinit() {
        
}


uint8_t I2C0_read(uint8_t addr, uint8_t reg, uint8_t* data, uint32_t len) {
                uint32_t i2cx = I2C0;
                uint8_t address = addr << 1;
               
                /************* start ***********************/
    // 等待I2C空闲
                if(I2C_waitn(i2cx, I2C_FLAG_I2CBSY)) return 1;

    // 发送启动信号
    i2c_start_on_bus(i2cx);
                if(I2C_wait(i2cx, I2C_FLAG_SBSEND)) return 2;

                /************* device address **************/
    // 发送从设备地址
    i2c_master_addressing(i2cx, address, I2C_TRANSMITTER);
               
//                //ack
//                i2c_ack_config(i2cx, I2C_ACK_ENABLE);
//                i2c_ackpos_config(i2cx, I2C_ACKPOS_CURRENT);
//                if(I2C_wait(i2cx, (I2C_CTL0(i2cx) & I2C_CTL0_ACKEN))) return 11;
//                // i2c_ack_config(i2cx, I2C_ACK_DISABLE);
               
                if(I2C_wait(i2cx, I2C_FLAG_ADDSEND)) return 3;
                i2c_flag_clear(i2cx, I2C_FLAG_ADDSEND);

                /********** register address **************/
                // 等待发送缓冲区        
    if(I2C_wait(i2cx, I2C_FLAG_TBE)) return 4;
   
                // 发送寄存器地址
    i2c_data_transmit(i2cx, reg);
               
                // 等待发送数据完成        
    if(I2C_wait(i2cx, I2C_FLAG_BTC)) return 5;        
                if(I2C_wait(i2cx, I2C_FLAG_TBE)) return 6;

                /************* start ***********************/
    // 发送再启动信号
    i2c_start_on_bus(i2cx);
               
               
                if(I2C_wait(i2cx, I2C_FLAG_SBSEND)) return 7;

                /************* device address **************/
    // 发送从设备地址
    i2c_master_addressing(i2cx, address, I2C_RECEIVER);
                if(I2C_wait(i2cx, I2C_FLAG_ADDSEND)) return 8;
                i2c_flag_clear(i2cx, I2C_FLAG_ADDSEND);


                /************* data **************/
                //ack
                i2c_ack_config(i2cx, I2C_ACK_ENABLE);
                i2c_ackpos_config(i2cx, I2C_ACKPOS_CURRENT);
                if(I2C_wait(i2cx, (I2C_CTL0(i2cx) & I2C_CTL0_ACKEN))) return 23;
               
    // 读取数据
                uint8_t i;
    for (i = 0; i < len; i++) {
                                if(i != len - 1) {
                                                // 等待ACK发送完成        
                                                if(I2C_wait(i2cx, I2C_FLAG_BTC)) return 9;
                                }
                        
                                // 等待ACK数据发送完成
                                // 等待接收缓冲区        
                                if(I2C_wait(i2cx, I2C_FLAG_RBNE)) return 10;
        data[i] = i2c_data_receive(i2cx);
                        
        if (i == len - 1) {
            // 在读取最后一个字节之前,禁用ACK,并发送停止信号
                                                // 配置自动NACK
                                                //i2c_ackpos_config(i2cx, I2C_ACKPOS_NEXT);
                                                //if(I2C_wait(i2cx, (I2C_CTL0(i2cx) & I2C_CTL0_ACKEN))) return 9;
                                                i2c_ack_config(i2cx, I2C_ACK_DISABLE);
        }
    }
               
                /***************** stop ********************/
                i2c_stop_on_bus(i2cx);
                if(I2C_waitn(i2cx, I2C_CTL0(I2C0) & I2C_CTL0_STOP)) return 11;
    return 0;
}













使用特权

评论回复
评论
21小跑堂 2024-10-16 13:53 回复TA
字数未满800字不予审核 

相关帖子

沙发
呐咯密密| | 2024-10-30 10:12 | 只看该作者
请教一下,这个时序图和流程图是用什么软件做的

使用特权

评论回复
板凳
yangjiaxu| | 2024-10-31 21:21 | 只看该作者
话说,I2C的挂载数量跟什么有关系?巡检的时候也是点名的方式吗?

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

14

主题

115

帖子

1

粉丝