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;

}

相关推荐
LCG米8 小时前
STM32串口接收卡死根因排查:ORE溢出标志陷阱、错误标志清除顺序与中断恢复实测
stm32·单片机·嵌入式硬件·串口·嵌入式
_Ningye15 小时前
STM32 — 11.5 硬件SPI读写W25Q64
stm32·单片机·嵌入式硬件
inrichtt15 小时前
第九课时:STM32 SPI实战:按键消抖与FLASH断电保护
stm32·单片机·嵌入式硬件
zhangzhangkeji17 小时前
stm32, HAL 库,WDG,复位分类,硬件看门狗相关,
stm32
新晨单片机设计19 小时前
S023E-基于STM32单片机WIFI智能插座(温度、定时)【Proteus仿真+Keil程序+原理图】
stm32·单片机·proteus·wifi智能电表
硅基手札19 小时前
SPI技术系列 08 · SPI 控制器寄存器与 IP 架构
驱动开发·stm32·单片机·嵌入式硬件·mcu·架构·计算机外设
元器件BOM超人20 小时前
STM32F103和GD32F103怎么选?
stm32·单片机·gd32
‎ദ്ദിᵔ.˛.ᵔ₎21 小时前
STM32 时钟树与 RCC
stm32
笨笨饿1 天前
#142_VS Code.map文件插件的用法
git·python·stm32·单片机·嵌入式硬件·物联网·vim
Zw-awa1 天前
让小车沿线转得顺:循迹位置环 PID
stm32