GD32F303学习记录(一)I2C GPIO 软件模拟

3 篇文章 0 订阅
2 篇文章 0 订阅

项目中遇到MCU通过I2C访问从机寄存器,对其进行读写操作的任务时,可以使用GPIO软件模拟I2C和硬件I2C两种方式进行。下面介绍软件模拟I2C的驱动代码。

一、创建a_sw_i2c.c源文件用于编辑软件模拟i2c通信协议和读\写操作函数

(1)GPIO端口配置。

#include "a_sw_i2c.h"

void a_i2c_gpio_config(void)
{
    // enable GPIO clock
    rcu_periph_clock_enable(RCU_GPIOB);
    // connect PB6 to I2C0_SCL  connect PB7 to I2C0_SDA
    gpio_init(GPIOB, GPIO_MODE_OUT_OD, GPIO_OSPEED_50MHZ, GPIO_PIN_6);
    gpio_init(GPIOB, GPIO_MODE_OUT_OD, GPIO_OSPEED_50MHZ, GPIO_PIN_7);
}

(2)起始信号、停止信号、应答信号、不应答信号、应答信号检测。

/* start signal */
void a_sw_i2c_start(void)
{
    SCL_HIGH;
    SDA_HIGH;
    a_delay_5us;
    SDA_LOW;
    a_delay_5us;
    SCL_LOW;
    a_delay_5us;
}
/* stop signal */
void a_sw_i2c_stop(void)
{
    SDA_LOW;
    SCL_HIGH;
    a_delay_5us;
    SDA_HIGH;
}
/* ack signal */
void a_ack(void)
{
    SDA_LOW;
    a_delay_5us;
    SCL_HIGH;
    a_delay_5us;
    SCL_LOW;
    a_delay_5us;
    SDA_HIGH;
}
/* nack signal */
void a_nack(void)
{
    SDA_HIGH;
    a_delay_5us;
    SCL_HIGH;
    a_delay_5us;
    SCL_LOW;
    a_delay_5us;
}
/* wait ack signal */
uint8_t a_wait_ack(void)
{
    AW_U32 ack_state;
    SDA_HIGH;
    a_delay_5us;
    SCL_HIGH;
    a_delay_5us;
    // read sda state:1 nack,0 ack
    if (SDA_READ) {
        ack_state = 1;
    } else {
        ack_state = 0;
    }
    SCL_LOW;
    a_delay_5us;
    return ack_state;
}

(3)总线数据接收与发送。        

/* send 8bit to i2c bus */
void aw_send_byte(uint8_t byte)
{
    uint8_t i;
    for (i = 0; i < 8; i++) {
        if (byte & HIGH_BIT) {
            SDA_HIGH;
        } else {
            SDA_LOW;
        }
        a_delay_5us;
        SCL_HIGH;
        a_delay_5us;
        SCL_LOW;
		// send complete release bus
        if (i == 7) {
            SDA_HIGH;
        }
        byte <<= 1;
        a_delay_5us;
    }
}
/* receive 8bit from i2c bus */
uint8_t a_receive_byte(void)
{
    uint8_t i;
    uint8_t value = 0;
    for (i = 0; i < 8; i++) {
        value <<= 1;
        SCL_HIGH;
        a_delay_5us;
        if (SDA_READ) {
            value |= 1;
        }
        SCL_LOW;
        a_delay_5us;
    }
    return value;
}

(4)单字节读\写接口函数。     

/* read one byte data*/
uint8_t a_sw_i2c_read_byte(uint8_t slave_addr, uint8_t register_addr, uint8_t data)
{
    // send start signal
    a_sw_i2c_start();
    // send slave address write
    a_send_byte(slave_addr << LEFT_SHIFT);
    // wait ack
    a_wait_ack();
    // slave register address
    a_send_byte(register_addr);
    // wait ack
    a_wait_ack();
    // send start signal
    a_sw_i2c_start();
    // send slave address read
    a_send_byte(slave_addr << LEFT_SHIFT + READ_BIT);
    // wait ack
    a_wait_ack();
    // read one byte data
    data = a_receive_byte();
    // read completed send nack signal
    a_nack();
    // send stop signal
    a_sw_i2c_stop();
    return data;
}
/* write one byte data*/
uint8_t a_sw_i2c_write_byte(uint8_t slave_addr, uint8_t register_addr, uint8_t data)
{
    // send start signal
    a_sw_i2c_start();
    // send slave address
    a_send_byte(slave_addr << LEFT_SHIFT);
    // wait ack
    a_wait_ack();
    // slave register address
    a_send_byte(register_addr);
    // wait ack
    a_wait_ack();
    // read data
    a_send_byte(data);
    // wait ack
    a_wait_ack();
    // send stop signal
    a_sw_i2c_stop();
}

(5)多字节读\写接口函数。

/* read multiple bytes data*/
uint8_t a_sw_i2c_read_bytes(uint8_t slave_addr, uint8_t register_addr, uint8_t *data, uint8_t data_size)
{
    uint8_t i;
    //uint8_t register_data[i];
    // send start signal
    a_sw_i2c_start();
    // send slave address write
    a_send_byte(slave_addr << LEFT_SHIFT);
    // wait ack
    a_wait_ack();
    // slave register address
    a_send_byte(register_addr);
    // wait ack
    a_wait_ack();
    // send start signal
    a_sw_i2c_start();
    // send slave address read
    a_send_byte(slave_addr << LEFT_SHIFT + READ_BIT);
    // wait ack
    a_wait_ack();
    // read multiple bytes
    for (i = 0; i < data_size; i++) {
        data[i] = a_receive_byte();
        if (i < data_size - 1) {
            a_ack();
        }
    }
    // read completed send nack signal
    a_nack();
    // send stop signal
    a_sw_i2c_stop();
}
/* write multiple bytes data*/
uint8_t a_sw_i2c_write_bytes(uint8_t slave_addr, uint8_t register_addr, uint8_t *data, uint8_t data_size)
{
    uint8_t i;
    // send start signal
    a_sw_i2c_start();
    // send slave address write
    a_send_byte(slave_addr << LEFT_SHIFT);
    // wait ack
    a_wait_ack();
    // slave register address
    a_send_byte(register_addr);
    // wait ack
    a_wait_ack();
    // write multiple bytes
    for (i = 0; i < data_size; i++) {
        a_send_byte(data[i]);
        if (i < data_size - 1) {
            aw_ack();
        }
    }
    // send stop signal
    a_sw_i2c_stop();
}

二、创建a_sw_i2c.h头文件

#ifndef __IIC_H
#define __IIC_H

#include "systick.h"

// define sw_i2c gpio
#define SCL_HIGH        (GPIO_BOP(GPIOB) = BIT(6))
#define SCL_LOW         (GPIO_BC(GPIOB) = BIT(6))

#define SDA_HIGH        (GPIO_BOP(GPIOB) = BIT(7))
#define SDA_LOW         (GPIO_BC(GPIOB) = BIT(7))
#define SDA_READ        (GPIO_ISTAT(GPIOB) & BIT(7))

#define SLAVE_ADDR      (0x45)
#define LEFT_SHIFT      (1)
#define READ_BIT        (1)
#define HIGH_BIT        (0x80)
#define ONE_BYTE        (1)
#define TWO_BYTE        (2)
#define THREE_BYTE      (3)
#define FOUR_BYTE       (4)

//sw
void a_i2c_gpio_config(void);
void a_sw_i2c_start(void);
void a_sw_i2c_stop(void);
void a_ack(void);
void a_nack(void);
uint8_t a_wait_ack(void);
void a_send_byte(uint8_t byte);
uint8_t a_receive_byte(void);
/* read one byte data */
uint8_t a_sw_i2c_read_byte(uint8_t slave_addr, uint8_t register_addr, uint8_t data);
/* write one byte data */
uint8_t a_sw_i2c_write_byte(uint8_t slave_addr, uint8_t register_addr, uint8_t data);
/* read multiple bytes data */
uint8_t a_sw_i2c_read_bytes(uint8_t slave_addr, uint8_t register_addr, uint8_t *data, uint8_t data_size);
/* write multiple bytes data */
uint8_t a_sw_i2c_write_bytes(uint8_t slave_addr, uint8_t register_addr, uint8_t *data, uint8_t data_size);

#endif

三、创建a_sw_i2c.h头文件

    while (1) {

        uint8_t buffer_write[1] = {0x02};
        uint8_t buffer_read[2] = {0};
        uint8_t data_read = 0;
        uint8_t data_write = 0x02;

        // hardware i2c write bytes
        a_hw_i2c_write_bytes(SLAVE_ADDR, REGISTER_RSTR, buffer_write, ONE_BYTE);
        // hardware i2c read bytes
        a_hw_i2c_read_bytes(SLAVE_ADDR, REGISTER_RSTR, buffer_read, TWO_BYTE);
        a_delay_1s;

        // sardware i2c read one byte
        a_sw_i2c_read_byte(SLAVE_ADDR, REGISTER_RSTR, data_read);
        // sardware i2c write one byte
        a_sw_i2c_write_byte(SLAVE_ADDR, REGISTER_RSTR, data_write);
        // sardware i2c read multiple bytes
        a_sw_i2c_read_bytes(SLAVE_ADDR, REGISTER_RSTR, buffer_read, TWO_BYTE);
        a_delay_1s;
    }

  • 0
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是 GD32F303 软件模拟 I2C 的示例代码: ``` c #include "gd32f30x.h" #include "i2c_sw.h" #define I2C_SCL_PIN GPIO_PIN_10 #define I2C_SDA_PIN GPIO_PIN_11 #define I2C_GPIO_PORT GPIOB #define I2C_SCL_HIGH() GPIO_SetBits(I2C_GPIO_PORT, I2C_SCL_PIN) #define I2C_SCL_LOW() GPIO_ResetBits(I2C_GPIO_PORT, I2C_SCL_PIN) #define I2C_SDA_HIGH() GPIO_SetBits(I2C_GPIO_PORT, I2C_SDA_PIN) #define I2C_SDA_LOW() GPIO_ResetBits(I2C_GPIO_PORT, I2C_SDA_PIN) #define I2C_SDA_READ() GPIO_ReadInputDataBit(I2C_GPIO_PORT, I2C_SDA_PIN) void i2c_sw_delay(void) { volatile uint32_t i; for(i=0; i<100; i++); } void i2c_sw_init(void) { GPIO_InitPara GPIO_InitStructure; RCC_AHBPeriphClock_Enable(RCC_AHBPERIPH_GPIOB); GPIO_InitStructure.GPIO_Pin = I2C_SCL_PIN | I2C_SDA_PIN; GPIO_InitStructure.GPIO_Mode = GPIO_MODE_OUT; GPIO_InitStructure.GPIO_Speed = GPIO_SPEED_50MHZ; GPIO_InitStructure.GPIO_OType = GPIO_OTYPE_PP; GPIO_InitStructure.GPIO_PuPd = GPIO_PUPD_PULLUP; GPIO_Init(I2C_GPIO_PORT, &GPIO_InitStructure); I2C_SCL_HIGH(); I2C_SDA_HIGH(); } void i2c_sw_start(void) { I2C_SDA_HIGH(); I2C_SCL_HIGH(); i2c_sw_delay(); I2C_SDA_LOW(); i2c_sw_delay(); I2C_SCL_LOW(); } void i2c_sw_stop(void) { I2C_SDA_LOW(); I2C_SCL_HIGH(); i2c_sw_delay(); I2C_SDA_HIGH(); i2c_sw_delay(); } void i2c_sw_write_byte(uint8_t data) { uint8_t i; for(i=0; i<8; i++) { if(data & 0x80) I2C_SDA_HIGH(); else I2C_SDA_LOW(); i2c_sw_delay(); I2C_SCL_HIGH(); i2c_sw_delay(); I2C_SCL_LOW(); i2c_sw_delay(); data <<= 1; } I2C_SDA_HIGH(); i2c_sw_delay(); I2C_SCL_HIGH(); i2c_sw_delay(); I2C_SCL_LOW(); } uint8_t i2c_sw_read_byte(void) { uint8_t i, data = 0; I2C_SDA_HIGH(); for(i=0; i<8; i++) { data <<= 1; I2C_SCL_HIGH(); i2c_sw_delay(); if(I2C_SDA_READ() != RESET) data |= 0x01; I2C_SCL_LOW(); i2c_sw_delay(); } return data; } void i2c_sw_write(uint8_t addr, uint8_t reg, uint8_t data) { i2c_sw_start(); i2c_sw_write_byte(addr << 1); i2c_sw_write_byte(reg); i2c_sw_write_byte(data); i2c_sw_stop(); } uint8_t i2c_sw_read(uint8_t addr, uint8_t reg) { uint8_t data; i2c_sw_start(); i2c_sw_write_byte(addr << 1); i2c_sw_write_byte(reg); i2c_sw_start(); i2c_sw_write_byte((addr << 1) | 0x01); data = i2c_sw_read_byte(); i2c_sw_stop(); return data; } ``` 使用方法: 1. 在主函数中调用 `i2c_sw_init()` 进行初始化。 2. 调用 `i2c_sw_write()` 写入数据,或调用 `i2c_sw_read()` 读取数据。 3. 注意在每次读写之前先调用 `i2c_sw_start()`,读写完成后调用 `i2c_sw_stop()`。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值