一 概述
很多人都知道stm32的硬件I2C存在BUG,现在我们通过软件模拟时序的办法来实现I2C。
使用软件模拟I2C主要是方便程序的移植,只需要更改一下相应的IO端口即可。
二 软件模拟实现
1 起始信号
void i2c_Start(void)
{
macI2C_SDA_1(); //首先确保SDA和SCL都是高电平
macI2C_SCL_1();
i2c_Delay();
macI2C_SDA_0(); //先拉低SDA
i2c_Delay();
macI2C_SCL_0(); //在拉低SCL
i2c_Delay();
}
2 总线产生停止信号
void i2c_Stop(void)
{
macI2C_SDA_0(); //首先确保SDA是低电平
macI2C_SCL_1(); //先拉高SCL
i2c_Delay();
macI2C_SDA_1(); //在拉高SDA
}
3 CPU向I2C总线设备发送8bits的数据
void i2c_SendByte(uint8_t _ucByte)
{
uint8_t i;
for (i = 0; i < 8; i++)
{
if (_ucByte & 0x80)
{
macI2C_SDA_1();
}
else
{
macI2C_SDA_0();
}
i2c_Delay();
macI2C_SCL_1();
i2c_Delay();
macI2C_SCL_0();
if (i == 7)
{
macI2C_SDA_1(); // 8位数据发送完毕后,主机释放SDA,以检测从机应答
}
_ucByte <<= 1; //左移1个bit
i2c_Delay();
}
}
4 CPU从I2C总线读取8个bits的数据
uint8_t i2c_ReadByte(void)
{
uint8_t i;
uint8_t value;
/*读取到的第一个bit为bit7*/
value = 0;
for (i = 0; i < 8; i++)
{
value <<= 1;
macI2C_SCL_1();
i2c_Delay();
if (macI2C_SDA_READ())
{
value++;
}
macI2C_SCL_0();
i2c_Delay();
}
return value;
}
5 CPU产生一个时钟,并且读取器件的ACK应答信号
uint8_t i2c_WaitAck(void)
{
uint8_t re;
macI2C_SDA_1(); //CPU释放SDA总线
i2c_Delay();
macI2C_SCL_1(); //CPU驱动SCL=1,此时器件会返回ACK应答
i2c_Delay();
if (macI2C_SDA_READ()) //CPU读取SDA口线状态
{
re = 1;
}
else
{
re = 0;
}
macI2C_SCL_0();
i2c_Delay();
return re;
}
6 CPU产生一个ACK信号
void i2c_Ack(void)
{
macI2C_SDA_0();
i2c_Delay();
macI2C_SCL_1();
i2c_Delay();
macI2C_SCL_0();
i2c_Delay();
macI2C_SDA_1();
}
7 CPU产生一个NACK信号(NACK即无应答信号)
void i2c_NAck(void)
{
macI2C_SDA_1(); //CPU驱动SDA产生1
i2c_Delay();
macI2C_SCL_1(); //CPU驱动SCL产生1
i2c_Delay();
macI2C_SCL_0();
i2c_Delay();
}
8 I2C总线位延时
static void i2c_Delay(void)
{
uint8_t i;
for (i = 0; i < 10; i++);
}
对于I2C总线延时来说,不同的单片机写法是不相同的,参考野火的程序,当CPU主频为72MHz时,在内部Flash运行,同时MDK不做优化的情况下
循环次数为10时,SCL频率为205KHz
循环次数为7时,SCL频率为347KHz,SCL高电平时间为1.5us,SCL低电平时间为2.87us
后记:关于I2C通信,我还是有几处地方没有搞明白,这里的程序只是写好了具体的底层封装,对于不同的外设,如AT24C02,MPU6050,应用起来肯定是不相同的,等搞明白其他的一些问题后,我会继续补充这篇文章。
参考资料
1 http://blog.csdn.net/subkiller/article/details/6854910 《I2C总线协议》
2 《手把手教你学51单片机》
3 野火stm32指南者开发板程序
关键字:stm32 模拟I2C
引用地址:
stm32软件模拟I2C
推荐阅读最新更新时间:2024-03-16 15:36
STM32开放式开发环境:释放创造力的利器
市场上涌现各种价格亲民的经济型微控制器,助力新一代开发者创造令人兴奋的新型嵌入式应用。如今的开发工具非常好用,软硬件均呈现模块化趋势,插接安装简单容易,使得产品设计评估和原型开发周期大幅缩短。STM32开放式开发环境是业内独一无二的软硬件开发平台,堆叠式插接电路板集成各种模块化硬件,同时模块化软件覆盖从驱动程序到应用层的全部软件,帮助设计人员将创意快速变成产品原型,顺利转化成最终设计。 STM32开放式开发环境是什么? STM32开放式开发环境 是意法半导体开发的嵌入式系统原型设计开发环境,以简化嵌入式项目设计为目标,通过开源形式提供全部重要功能模块,组件包括: - 价格极低的STM32 Nucleo开发板(STM32微控
[嵌入式]
STM32 HAL库学习系列第11篇---定时器TIM---看门狗基本配置及使用
基本配置 使用cube配置溢出时间 记住准时喂狗 独立看门狗: /* IWDG 1s 超时溢出 */ MX_IWDG_Init(IWDG_PRESCALER_64,625); /* 启动独立看门狗 */ HAL_IWDG_Start(&hiwdg); LED1_ON; /* while部分是我们在项目中具体需要写的代码,这部分的程序可以用独立看门狗来监控 * 如果我们知道这部 分代码的执行时间,比如是50ms,那么我们可以设置独立看门狗的 * 溢出时间是60ms,比50ms多一点, 如果要被监控的程序没有跑飞正常执行的话,那么 * 执行完毕之后就会执行喂狗的程序,如果程序跑飞
[单片机]
Stm32浮点运算死机解决方案
需要在SOC中的软核部分(PS)构建一些浮点运算,结果发现仿真6次就死机 咋仿真咋死! 修改代码如下 好了!
[单片机]
STM32 外部计数ETR计算频率
STM32 外部计数ETR计算频率,测量100K频率,用定时器2定时250ms,定时器3PD2(TIM3_ETR)计数,计算公式f=n*t; void Tim3_Configuration(void) { TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; TIM_TimeBaseStructure.TIM_Prescaler = 0x00; TIM_TimeBaseStructure.TIM_Period = 0xFFFF; TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; TIM_TimeBaseStr
[单片机]
STM32+FreeRTOS+CUBEMX_学习笔记(七 )输入捕获
前言 我们可以利用输入捕获模式来测量脉冲宽度或者测量频率。 1、cube设置 2、函数详解: /** * @brief Read the captured value from Capture Compare unit 读取通道捕获值 * @param htim TIM handle. * @param Channel TIM Channels to be enabled * This parameter can be one of the following values: * @arg TIM_CHANNEL_1: TIM Channel 1 selected * @arg T
[单片机]
STM32关于USART的问题集锦
1、STM32103USART1死机 问:voidUSART_Receive(USART_TypeDef*USARTx) { if(USART_GetFlagStatus(USARTx,USART_FLAG_RXNE)==SET) { USART_ClearFlag(USARTx,USART_FLAG_RXNE); s =USART_ReceiveData(USART1); delay(1000); s =USART_ReceiveData(USART1); delay(1000); s =USART_ReceiveData(USART1); delay(1000); write_c
[单片机]
stm32的学习之存储器和总线架构
四个驱动单元:context-M3内核的D-bus总线和S-bus总线、通用DMA1和通用DMA2。 四个被驱动的单元:内部FLASH(内部山村存储器)、内部SRAM、FSMC、AHB到APB的桥AHP2APBx。 ICode总线是context-M3与内部闪存FLASH指令接口之间的连接的总线,实现指令的预取功能。 DCode总线是将context-M3与内部闪存存储器(FLASH)的数据接口连接起来的总线,实现数据读取。 系统总线(system bus)连接context-M3和总线矩阵,总线矩阵协调着context-M3和DMA间的访问。 DMA总线实现DMA的AHB主控接口道总线接口的连接。 总线矩阵 此总线矩阵协调内
[单片机]
怎样在Linux上开发STM32程序
步骤1:下载所需的一切 您需要下载三个部分才能正常工作: 用于ARM的GCC编译器 STM32固件文件 St-link实用程序 Sample Project 编译器是将我们的C代码和所有其他库文件编译成stm32控制器可以理解的机器语言的主要软件。下载此编译器的最新预编译版本。 包含STM32固件的文件夹是保存主处理器运行所需的所有启动文件和核心文件的文件夹。我们将使用HAL已超越的标准外围设备库。我更喜欢StPeriphLibrary,因为使用该处理器的公司都在使用它们,因为它功能强大,更老旧并且受支持。它也更坚固。它不会减少初始化外围设备或打开LED所需的工作,但是会迫使您学习这些处理器的工作方式。这样一来,您将对内部工作
[单片机]