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;

}

相关推荐
2401_8541515510 小时前
ARM Cortex-M 体系结构深度解析——寄存器模型、处理器模式、AAPCS 与异常模型
arm开发·stm32·单片机·嵌入式硬件
Deven_Huang11 小时前
STM32 ADC 使用经验总结与常见踩坑点
stm32·adc
巴巴媛6662 天前
STM32学习笔记【32.BKP + RTC】
笔记·stm32·学习
吠品2 天前
Python字典键获取的四种实用方法
stm32·单片机·嵌入式硬件
追兮兮2 天前
MCUQuickStart:一键生成 STM32 / GD32 的 Keil、CMake、RTOS 工程
stm32·单片机·freertos·gd32·gcc·工程模版
小殷学长2 天前
【单片机毕业设计25-基于stm32的导盲眼镜设计】
stm32·单片机·课程设计
辰哥单片机设计2 天前
STM32智能病房呼叫系统
stm32·单片机·嵌入式硬件
水利行业RTU手艺人2 天前
RTU固件中的“数据保险箱”——离线数据补发系统设计
c++·stm32·单片机·物联网
bu_shuo3 天前
STM32-BOOT的三种启动方式
stm32·单片机·嵌入式硬件
梁朝辉3 天前
STM32H750VBT6中ADCINP与INN什么区别
stm32·单片机·嵌入式硬件