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;    

    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;
}

发布了124 篇原创文章 · 获赞 51 · 访问量 32万+

猜你喜欢

转载自blog.csdn.net/zoosenpin/article/details/73321178