STM32 HAL库 模拟I²C

发布者:SereneSpirit最新更新时间:2025-10-31 来源: bilibili关键字:STM32  HAL库  模拟I²C 手机看文章 扫描二维码
随时随地手机看文章

在使用单片机的过程中,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


关键字:STM32  HAL库  模拟I²C 引用地址:STM32 HAL库 模拟I²C

上一篇:入门STM32F103-GPIO输入
下一篇:STM32 IAP实验

推荐阅读最新更新时间:2026-03-22 21:51

STM32单片机的ADS1115通过模拟I2C驱动
注意:本部分代码需要只是ADS1115的部分程序(一些用到的数组在此没有写),模拟II2C的各程序并未给出,大家根据需要进行裁剪,代码完全开源,希望能帮到大家,也希望大家乐于分享。 调试时需特别注意I2C的通信问题,特别是应答信号的使用需要特别关注,本人的程序之前出错全是因为从机的应答信号的未使用造成。 收获:对于I2C通信协议的理解更加深刻,对ADS1115也能进行单通道的使用。I2C的开始、发送/读写、应答、结束等一定要严格按照时序操作,ADS的操作还有所欠缺,仅仅会配置单通道,对于其他配置并没有关注,最近要把多通道的和阈值的配置也写好,到时再更新 附录代码: #define CMD_Write 0x90 ////写
[单片机]
<font color='red'>STM32</font>单片机的ADS1115通过<font color='red'>模拟</font><font color='red'>I</font>2<font color='red'>C</font>驱动
关于stm32通信协议:软件模拟SPI、软件模拟I2C的总结
趁着帮老师代上嵌入式实验课的机会,又重新熟悉了一遍stm32的通信协议:串口协议、SPI协议、I2C协议、RS485协议。大概半年前,是过了一遍的,但也只停留于读了遍代码,跑了下例程,最近又过了一遍(自己仔细的看了一遍,老师还给我们讲了一遍,自己又讲了一遍),然后还写了一遍软件模拟SPI、软件模拟I2C的代码,才彻底的懂了个皮毛 ,:)。稍微总结下吧,总结的不好,都是自己的理解,仅供参考,主要说软件模拟SPI、I2C,硬件SPI和硬件I2C就不说了。 串口协议 串口协议没什么可说的,现在常用的串口协议,是基于以前的RS232的协议,因为RS232的引脚太多而改进过来的。 物理层只用三根引脚:TXD、RXD、GND(最好接,不然
[单片机]
STM32快速读写AT24C16 代码 模拟I2C
本帖只适用AT24C16及以下的芯片,AT24C32及以上的芯片读写方式不一样,故不适用!!! 如果你的代码可以正常读写24C01/02,直接拿来读取24C16是可以的,但是只能读取256字节。 AT24C16与AT24C01/02/04/08 不同,它引脚的A2,A1,A0是无效的,也就是它没有自己独立的地址,总线上只能挂一个AT24C16设备。 AT24C16总共2048字节,分为128页,每页16字节,地址范围是0~2047。 128页只需要7位地址,分为高3位和低4位,高3位在设备地址中,低4位在字节地址中。 设备地址:1010+页地址高3位+读写方向(1:读 0:写) 字节地址:页地址高4位+4位
[单片机]
<font color='red'>STM32</font>快速读写AT24<font color='red'>C</font>16 代码 <font color='red'>模拟</font><font color='red'>I</font>2<font color='red'>C</font>
stm32模拟i2c驱动ht16c22
iic.h文件如下: #ifndef _stm32f103_myi2c_h_ #define _stm32f103_myi2c_h_ //IO方向设置 #define SDA_IN() {GPIOB- CRH&=0XFFFF0FFF;GPIOB- CRH|=8 12;} #define SDA_OUT() {GPIOB- CRH&=0XFFFF0FFF;GPIOB- CRH|=3 12;} //IO操作函数 #define IIC_SCL PBout(10) //SCL #define IIC_SDA PBout(11) //SDA #define READ_SDA PBin(11) //输入SDA //ht16c22
[单片机]
单片机模拟I2C总线及24C02读写实例
单片机模拟I2C总线及24C02(I2C EEP ROM )读写实例(c源代码) /* 51系列单片机在使用时,有时需要模拟I2C总线, */ /* 这里举出一个实例(读写串行EEPROM 芯片 at2402) */ /************************************************************************/ /* Name:AT24C02存储器的读写程序,用到I2C总线,含相对独立的I2C总线读写函数 */ /* Language: C 51单片机 编程 语言 */ /* Platf or m: Win98, Intel Celeron 433 Processor,伟
[单片机]
STM32F2系列驱动开发——模拟I2C通信
简介:一、概述 通过STM32的PC14和PC15管脚来模拟I2C通信,读写I2C接口的器件内部寄存器...... 一、概述 通过STM32的PC14和PC15管脚来模拟I2C通信,读写I2C接口的器件内部寄存器,具体定义如下: #define PIN_SCL GPIO_Pin_14 #define PIN_SDA GPIO_Pin_15 延时函数为μs延时,例如Delay(4)表示延时4μs。 二、Static型函数定义 static __inline void TWI_SCL_0(void) { GPIOC- BSRRH = PIN_SCL; } static __inline void
[单片机]
MSP430学习的第一个模拟I2C程序
#include msp430.h unsigned char I2CBUF; unsigned char checkbit; #define SCL_H (P10OUT |= BIT2) // P10.2为SCL #define SCL_L (P10OUT &= ~BIT2) #define SDA_H (P10OUT |= BIT1) //p10.1为SDA #define SDA_L (P10OUT &= ~BIT1) #define SDA_OUT (P10DIR |= BIT1) #define SDA_IN (P10DIR &= ~ BIT1) void I2C_Start(void) //I2C开
[单片机]
STM8 I/O口模拟I2C
STM8I/O口模拟I2C所读数据不正确 STM8 I/O口模拟I2C #define I2C_ERR 0 #define I2C_CRR 1 #define I2CDataIn 1 #define I2CDataOut 0 #define I2C_PORT (GPIOC) #define I2CSCL (GPIO_PIN_7) #define I2CSDA (GPIO_PIN_6) //*************************************************************** // I2C Data input/outpu
[单片机]
小广播
最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

厂商技术中心

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

 
机器人开发圈

电子工程世界版权所有 京ICP证060456号 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2026 EEWORLD.com.cn, Inc. All rights reserved