GD32F303 模拟IIC协议的实现

因为博主之前是从stm32过来的,在mdk环境下进行gd32的开发。
一直听说stm32的iic有问题,所以从来也用的模拟iic,这次使用gd32,虽然有硬件iic的例程,但是在使用的过程中,永远卡在了iic的准备过程:

    /* send a start condition to I2C bus */
    i2c_start_on_bus(I2C0);

    /* wait until SBSEND bit is set */
    while (!i2c_flag_get(I2C0, I2C_FLAG_SBSEND))

这个SBSEND按理说应该由硬件置位,但是这里并不行……所以博主决定还是使用模拟iic……

代码如下:

#ifndef __MYIIC_H
#define __MYIIC_H
#include "gd32f30x.h"

//IIC所有操作函数
int iic_init(void);                //初始化IIC的IO口
void iic_start(void);               //发送IIC开始信号
void iic_stop(void);                //发送IIC停止信号
void iic_write_byte(uint8_t txd);   //IIC发送一个字节
uint8_t iic_read_byte(uint8_t ack); //IIC读取一个字节
uint8_t iic_wait_ack(void);         //IIC等待ACK信号

#endif

因为博主使用了rt-thread,所以这里的延时函数直接使用了rt-thread接口的rt_hw_us_delay函数进行实现,因为IO口配置为开漏模式,所以实际也不需要进行输入输出模式的转换。

#include "myiic.h"
#include "rtthread.h"
#include "rthw.h"

#define IIC_SCL_PIN                         GPIO_PIN_6
#define IIC_SCL_GPIO_PORT                   GPIOB
#define IIC_SCL_GPIO_CLK                    RCU_GPIOB

#define IIC_SDA_PIN                         GPIO_PIN_7
#define IIC_SDA_GPIO_PORT                   GPIOB
#define IIC_SDA_GPIO_CLK                    RCU_GPIOB

#define iic_printf                          rt_kprintf

//配置成OD模式不需要进行输入输出模式切换
#define SDA_IN()  {;}
#define SDA_OUT() {;}
//#define SDA_IN()  {GPIO_CTL0(GPIOB)&=0X0FFFFFFF;GPIO_CTL0(GPIOB)|=(uint32_t)8<<28;}
//#define SDA_OUT() {GPIO_CTL0(GPIOB)&=0X0FFFFFFF;GPIO_CTL0(GPIOB)|=(uint32_t)3<<28;}

static void iic_delay_us(int us)
{
    rt_hw_us_delay(10);
}

static void iic_scl_h(void)
{
    GPIO_BOP(IIC_SCL_GPIO_PORT) = IIC_SCL_PIN;
}

static void iic_scl_l(void)
{
    GPIO_BC(IIC_SCL_GPIO_PORT) = IIC_SCL_PIN;
}

static void iic_sda_write(unsigned char bit)
{
    if (bit == 0)
        GPIO_BC(IIC_SDA_GPIO_PORT) = IIC_SDA_PIN;
    else
        GPIO_BOP(IIC_SDA_GPIO_PORT) = IIC_SDA_PIN;
}

static unsigned char iic_sda_read(void)
{
    if (RESET == gpio_input_bit_get(IIC_SDA_GPIO_PORT, IIC_SDA_PIN))
        return 0x00;
    else
        return 0x01;


}



void iic_start(void)
{
    SDA_OUT();
    iic_sda_write(1);
    iic_delay_us(1);

    iic_scl_h();
    iic_delay_us(4);

    iic_sda_write(0);
    iic_delay_us(4);

    iic_scl_l();
    iic_delay_us(1);
}


void iic_stop(void)
{
    SDA_OUT();
    iic_scl_l();
    iic_delay_us(1);

    iic_sda_write(0);
    iic_delay_us(4);

    iic_scl_h();
    iic_delay_us(1);

    iic_sda_write(1);
    iic_delay_us(4);
}

uint8_t iic_wait_ack(void)
{
    uint32_t retry = 0;
    SDA_IN();
    iic_sda_write(0x01);
    iic_delay_us(1);
    iic_scl_h();
    iic_delay_us(1);

    while (iic_sda_read() == 0x01)
    {
        retry++;
        //iic_delay_us(1);
        if (retry > 500)   break;
    }

    if (iic_sda_read() == 0)
    {
        iic_scl_l();
        iic_delay_us(1);
        return 0;
    }
    else
    {
        iic_printf("stop \r\n");
        iic_stop();
        return 1;
    }
}

static void iic_ack(uint8_t ack_nack)
{
    iic_scl_l();
    SDA_OUT();
    iic_sda_write(ack_nack);
    iic_delay_us(1);
    iic_scl_h();
    iic_delay_us(1);
    iic_scl_l();
    iic_delay_us(1);
}


uint8_t iic_read_byte(uint8_t ack)
{
    uint8_t i, data;
    SDA_IN();
    for (i = 0, data = 0; i < 8; i++)
    {
        data <<= 1;
        iic_scl_h();
        iic_delay_us(1);
        data |= iic_sda_read();
        iic_scl_l();
        iic_delay_us(1);
    }
    iic_ack(ack);

    return data;
}

void iic_write_byte(uint8_t data)
{
    int i;
    SDA_OUT();
    iic_scl_l();
    for (i = 0; i < 8; i++)
    {
        iic_sda_write((data & 0x80) >> 7);
        iic_delay_us(1);
        iic_scl_h();
        iic_delay_us(1);
        iic_scl_l();
        iic_delay_us(1);
        data <<= 1;
    }
}

int iic_init(void)
{
    rcu_periph_clock_enable(IIC_SCL_GPIO_CLK);
    rcu_periph_clock_enable(IIC_SDA_GPIO_CLK);


    gpio_init(IIC_SCL_GPIO_PORT, GPIO_MODE_OUT_PP, GPIO_OSPEED_50MHZ, IIC_SCL_PIN);
    gpio_init(IIC_SDA_GPIO_PORT, GPIO_MODE_OUT_OD, GPIO_OSPEED_50MHZ, IIC_SDA_PIN);

    GPIO_BOP(IIC_SCL_GPIO_PORT) = IIC_SCL_PIN;
    GPIO_BOP(IIC_SDA_GPIO_PORT) = IIC_SDA_PIN;
    return 0;
}

INIT_BOARD_EXPORT(iic_init);


  • 2
    点赞
  • 42
    收藏
    觉得还不错? 一键收藏
  • 7
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值