在使用单片机的过程中,I²C总线是常用的一种通信方式,然而由于某些原因,STM32CubeMx直接初始化I²C会出现接收不到信息和各种问题,为此我们需要使用IO口来模拟I²C。
I²C的简介:
https://www.bilibili.com/opus/591043733946717098
用STM32CubeMx初始化模拟I²C的引脚:

STM32CubeMx的GPIO的配置可以参考:
https://www.bilibili.com/opus/484177792198506654
所用到的两个IO口分别对应I²C总线的串行数据线和串行时钟线。
SDA:PB7
SCL:PB6
头文件和源文件皆是依据正点原子mini32开发板的标准库文件学习修改得来
user_iic.h
#ifndef __USER_IIC_H
#define __USER_IIC_H
#ifdef __cplusplus
extern "C"
{
#endif
#include "stm32f1xx_hal.h"
#define SCL_H HAL_GPIO_WritePin(GPIOB, GPIO_PIN_6, GPIO_PIN_SET)
#define SCL_L HAL_GPIO_WritePin(GPIOB, GPIO_PIN_6, GPIO_PIN_RESET)
#define SDA_H HAL_GPIO_WritePin(GPIOB, GPIO_PIN_7, GPIO_PIN_SET)
#define SDA_L HAL_GPIO_WritePin(GPIOB, GPIO_PIN_7, GPIO_PIN_RESET)
#define SDA_read HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_7)
void SDA_IN(void);
void SDA_OUT(void);
void IIC_Init(void); //初始化IIC的IO口
void IIC_Start(void); //发送IIC开始信号
void IIC_Stop(void); //发送IIC停止信号
uint8_t IIC_Wait_Ack(void); // IIC等待ACK信号
void IIC_Ack(void); // IIC发送ACK信号
void IIC_NAck(void); // IIC不发送ACK信号
void IIC_Send_Byte(uint8_t txd); // IIC发送一个字节
uint8_t IIC_Read_Byte(uint8_t ack); // IIC读取一个字节
#ifdef __cplusplus
}
#endif
#endif
user_iic.c
/**
* @file
* @brief user_iic.c
* @details Simulate iic source file
* @author wingplane
* @date 2021-11-09
* @version v1.0
*/
#include "user_iic.h"
#include "stdio.h"
/**
* @brief SDA_IN
* @details Change the SDA pin to read
* @param[in] None
* @param[out] None
* @retval None
* @par Modification log
* Created by wingplane on 2021-11-09
*/
void SDA_IN(void)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
GPIO_InitStruct.Pin = GPIO_PIN_7;
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
GPIO_InitStruct.Pull = GPIO_PULLUP;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
}
/**
* @brief user_SDA_OUT
* @details Change the SDA pin to write
* @param[in] None
* @param[out] None
* @retval None
* @par Modification log
* Created by wingplane on 2021-11-09
*/
void SDA_OUT(void)
{
GPIO_InitTypeDef GPIO_InitStruct;
GPIO_InitStruct.Pin = GPIO_PIN_7;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
}
/**
* @brief IIC_Init
* @details IIC initialization
* @param[in] None
* @param[out] None
* @retval None
* @par Modification log
* Created by wingplane on 2021-11-09
*/
void IIC_Init(void)
{
SDA_H;
SCL_H;
}
/**
* @brief IIC_Start
* @details Master Start Simulation IIC Communication
* @param[in] None
* @param[out] None
* @retval None
* @par Modification log
* Created by wingplane on 2021-11-09
*/
void IIC_Start(void)
{
SDA_OUT(); // SDA set output
SDA_H;
SCL_H;
HAL_Delay(4);
SDA_L; // START:when CLK is high,DATA change form high to low
HAL_Delay(4);
SCL_L; // Clamp the I2C bus, ready to send or receive data
}
/**
* @brief IIC_Stop
* @details Master Stop Simulation IIC Communication
* @param[in] None
* @param[out] None
* @retval None
* @par Modification log
* Created by wingplane on 2021-11-09
*/
void IIC_Stop(void)
{
SDA_OUT(); // SDA set output
SCL_L;
SDA_L; // STOP:when CLK is high DATA change form low to high
HAL_Delay(4);
SCL_H;
SDA_H; // Send I2C bus end signal
HAL_Delay(4);
}
/**
* @brief IIC_Wait_Ack
* @details Master Reserive Slave Acknowledge Single
* @param[in] None
* @param[out] None
* @retval 1 Receive Response Fail
* @retval 0 Receive Response Success
* @par Modification log
* Created by wingplane on 2021-11-09
*/
uint8_t IIC_Wait_Ack(void)
{
uint8_t ucErrTime = 0;
SDA_IN(); // SDAset output
SDA_H;
HAL_Delay(1);
SCL_H;
HAL_Delay(1);
while (SDA_read)
{
ucErrTime++;
if (ucErrTime > 250)
{
IIC_Stop();
return 1;
}
}
SCL_L; //clk output0
return 0;
}
/**
* @brief IIC_Ack
* @details Master Send Acknowledge Single
* @param[in] None
* @param[out] None
* @retval None
* @par Modification log
* Created by wingplane on 2021-11-09
*/
void IIC_Ack(void)
{
SCL_L;
SDA_OUT();
SDA_L;
HAL_Delay(2);
SCL_H;
HAL_Delay(2);
SCL_L;
}
/**
* @brief IIC_NAck
* @details Master Send No Acknowledge Single
* @param[in] None
* @param[out] None
* @retval None
* @par Modification log
* Created by wingplane on 2021-11-09
*/
void IIC_NAck(void)
{
SCL_L;
SDA_OUT();
SDA_H;
HAL_Delay(2);
SCL_H;
HAL_Delay(2);
SCL_L;
}
/**
* @brief IIC_Send_Byte
* @details Master Send a Byte to Slave
* @param[in] txd Will Send Date
* @param[out] None
* @retval None
* @par Modification log
* Created by wingplane on 2021-11-09
*/
void IIC_Send_Byte(uint8_t txd)
{
uint8_t t;
SDA_OUT();
SCL_L; //Start data transfer
for (t = 0; t < 8; t++)
{
// IIC_SDA=(txd&0x80)>>7;
if ((txd & 0x80) >> 7)
SDA_H;
else
SDA_L;
txd <<= 1;
HAL_Delay(2);
SCL_H;
HAL_Delay(2);
SCL_L;
HAL_Delay(2);
}
}
/**
* @brief I2C_Rade_Byte
* @details Master Reserive a Byte From Slave
* @param[in] ack If the value is 1,send the ACK.If the value is 0, send the nACK
* @param[out] receive
* @retval Date From Slave
* @par Modification log
* Created by wingplane on 2021-11-09
*/
uint8_t IIC_Read_Byte(unsigned char ack)
{
unsigned char i, receive = 0;
SDA_IN(); // SDAset output
for (i = 0; i < 8; i++)
{
SCL_L;
HAL_Delay(2);
SCL_H;
receive <<= 1;
if (SDA_read)
receive++;
HAL_Delay(1);
}
if (!ack)
IIC_NAck(); //发送nACK
else
IIC_Ack(); //发送ACK
return receive;
}
参考文献:
STM32不完全手册_标准库版本_V3.3
上一篇:入门STM32F103-GPIO输入
下一篇:STM32 IAP实验
推荐阅读最新更新时间:2026-03-22 21:51
- LT3088IDD 宽安全工作区电源的典型应用
- 使用 Analog Devices 的 LT3663IDCB-3.3 的参考设计
- ADR425 可编程 DAC 参考的典型应用
- LT4276BIUFD 25.5W(类型 2)PoE+ 电源在反激模式下的典型应用电路,具有 24V、1A 输出
- 具有浪涌电流限制的低待机损耗功率前端
- LT4275AHMS IEEE 802.3at(类型 2)25.5W 受电设备的典型应用电路
- 采用 MSP430 电容式触控 MCU、触觉元件和 LCD 的 MSP432 MCU 参考设计
- 具有 6uA 反向泄漏电流的 LT1767EMS8E-3.3 双源电源的典型应用电路
- DER-282 - 使用HiperLCSTM LCS700HG设计的100 W超薄 (11 mm) LLC DC-DC转换器
- UART转USB桥接器

STM32模拟串口
dm9000cep网卡通信
STM32 PMSM FOC 简介
非常经典的关于LLC的杨波博士论文
XC6406PP60DL






京公网安备 11010802033920号