STM32 Bit-Bang I2C

#include <stdio.h>
#include <stdlib.h>
#include "stm32l0xx_hal.h"

/**I2C1 GPIO Configuration    
    PB6     ------> I2C1_SCL
    PB7     ------> I2C1_SDA
*/

#define SCL_0         HAL_GPIO_WritePin(GPIOB, GPIO_PIN_6, GPIO_PIN_RESET)
#define SCL_1         HAL_GPIO_WritePin(GPIOB, GPIO_PIN_6, GPIO_PIN_SET)
#define SDA_0         HAL_GPIO_WritePin(GPIOB, GPIO_PIN_7, GPIO_PIN_RESET)
#define SDA_1         HAL_GPIO_WritePin(GPIOB, GPIO_PIN_7, GPIO_PIN_SET)
#define IICport         GPIOB
#define SCL             GPIO_PIN_6
#define SDA             GPIO_PIN_7

static void  i2c_start(void);
static void  i2c_stop(void);
static void  wait_ack(void);
static void  i2c_writebyte(unsigned char a);
static unsigned char  i2c_readbyte(void);
static void SDAIN(void);
static void SDAOUT(void);
static void sendack(void);
static void sendnack(void);
static void i2c_writebit(unsigned char a);

void  i2c1_sw_acc_init(void);
void  i2c1_sw_acc_write(unsigned char sadd, unsigned char reg, unsigned char val);
unsigned char i2c1_sw_acc_read(unsigned char sadd, unsigned char reg);

/**
* @brief send ack signal at i2c bus
*/
static void sendack(void)
{
    i2c_writebit(0);
}
/**
* @brief send nack signal at i2c bus
*/
static void sendnack(void)
{
    i2c_writebit(1);
}

/**
* @brief realese the SDA
*/
static void SDAIN(void)
{
    GPIO_InitTypeDef  GPIO_InitStructure;

    GPIO_InitStructure.Pin = GPIO_PIN_7;
    GPIO_InitStructure.Mode = GPIO_MODE_INPUT;    
    HAL_GPIO_Init(GPIOB, &GPIO_InitStructure);
}

/**
* @brief get the control of SDA
*/
static void SDAOUT(void)
{
    GPIO_InitTypeDef  GPIO_InitStructure;

    GPIO_InitStructure.Pin = GPIO_PIN_7;
    GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_OD;
    HAL_GPIO_Init(GPIOB, &GPIO_InitStructure);
}

/**
* @brief delay
*/
static void delay5us(void)
{
    unsigned short i;
    i = 50;
    
    while(i--);
}

/**
* @brief send start signal at i2c bus
*/
static void i2c_start(void)
{
    SDAOUT();  
    SDA_1;
    delay5us();
    SCL_1;
    delay5us();
    SDA_0;
    delay5us();
    SCL_0;
    delay5us();
}

/**
* @brief send stop signal at i2c bus
*/
static void i2c_stop(void)
{
    SDAOUT();
    SDA_0;
    delay5us();
    SCL_1;
    delay5us();
    SDA_1;
    delay5us();
    SCL_0;
    delay5us();
}
/**
* @brief recieve ack signal at i2c bus
*/
static void  wait_ack(void)
{  
    int i = 0;    

    SCL_0;
    delay5us;
    SDAIN();
    delay5us;
    SCL_1;
    delay5us();
    while (HAL_GPIO_ReadPin(IICport, SDA) && (i < 0x2b0)) {
        i++;
    }

    SCL_0;
    delay5us();
}

/**
* @brief write a byte at i2c bus
*
* @param the data to write
*/
static void  i2c_writebyte(unsigned char a)
{
    unsigned short i;

    SDAOUT();
    for (i = 0; i < 8; i++) {
        SCL_0;
        delay5us();
        if (a & 0x80) {
            SDA_1;
        } else {
            SDA_0;
        }
        a = a << 1;
        delay5us();
        SCL_1;
        delay5us();
    }
}

/**
* @brief write a bit at i2c bus
*
* @param the data to write
*/
static void i2c_writebit(unsigned char a)
{
    SDAOUT();
    SCL_0;
    delay5us();
    if (a == 0) {
        SDA_0;
    } else {
        SDA_1;
    }
    delay5us();
    SCL_1;
    delay5us();
    SCL_0;
    delay5us();
}

/**
* @brief read a byte at i2c bus
*
* @retval the data read
*/
static unsigned char i2c_readbyte()
{
    unsigned char i, temp;
    temp = 0;
    
    SDAIN();
    SCL_0;      
    delay5us();
    for (i = 0; i < 8; i++) {
        SCL_1;  
        delay5us();
        temp = (temp << 1) | HAL_GPIO_ReadPin(IICport, SDA);
        delay5us();
        SCL_0;  
        delay5us();
    }
    return temp;
}

/**
* @brief initial the i2c related gpios
*/
void i2c1_sw_acc_init(void)
{       
    GPIO_InitTypeDef  GPIO_InitStructure;

    __GPIOB_CLK_ENABLE();
    GPIO_InitStructure.Pin = GPIO_PIN_6|GPIO_PIN_7;
    GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_OD;
    GPIO_InitStructure.Pull = GPIO_NOPULL;
    GPIO_InitStructure.Speed = GPIO_SPEED_FAST; //GPIO_SPEED_HIGH;
    HAL_GPIO_Init(GPIOB, &GPIO_InitStructure);

    SDA_1;
    SCL_1;
}

/**
* @brief write data at certain address on MPU6050
*
* @param add the in-chip address of the data
* @param Achar the data to write
*/
void  i2c1_sw_acc_write(unsigned char sadd, unsigned char reg, unsigned char val)
{
    i2c_start();
    i2c_writebyte(sadd);
    wait_ack();
    i2c_writebyte(reg);
    wait_ack();
    i2c_writebyte(val);
    wait_ack();
    i2c_stop();
}
/**
* @brief read data from certain address of MPU6050
*
* @param add the in-chip address of the data
* @retval the data read
*/
unsigned char  i2c1_sw_acc_read(unsigned char sadd, unsigned char reg)
{
    unsigned char temp;
    
    i2c_start();
    i2c_writebyte(sadd);
    wait_ack();
    delay5us();
    i2c_writebyte(reg);
    wait_ack();
    i2c_start();
    i2c_writebyte(sadd + 1);
    wait_ack();
    temp = i2c_readbyte();
    sendnack();
    i2c_stop();
    
    return temp;
}

  • 10
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值