STM32 I2C

1、有四种模式
● 从发送器模式
● 从接收器模式
● 主发送器模式
● 主接收器模式

默认是在从模式,接口在生成起始条件后自动切换到主模式;当仲裁丢失或产生停止信号后,又回到从模式

从模式时,能识别自己的地址(7位或10位) 和广播呼叫地址。

数据和地址按8位传输,高位在前。SCL时钟为高电平期间数据要维持稳定, 否则会被认为是起始 或 停止条件

在第9个时钟脉冲,从机回复0 表示应答 ACK
在这里插入图片描述
这里主要介绍主模式
● 主模式
CR2设置I2C模块的时钟-----时钟控制寄存器CCR,配置快速还是慢速,时钟分频率----------上升时间寄存器TRISE,配置上升沿最大时间----配置CR2-----配置CR1的START位为1,用于产生开始条件。
起始:
对START位置1, SR1. SB位会自动置1表示已发出开始信号,然后读SR1。如果CR2.ITEVFEN位设置了允许中断,则会产生中断。程序在中断中把地址写入 DR寄存器等待发送。(读SR1,然后写DR,将会清除SB)

地址发送:
在地址发送完后,并收到从机应答时,SR1.ADDR会被置1,如果允许了中断,则会产生中断。然后读SR1,跟着读SR2则会清除ADDR。根据地址的最后一位,主设备将决定进入发送模式 还是 接收模式

发送模式
当发送完地址收到应答后,TxE 被置1,(如果设置为中断允许INEVFEN和ITBUFEN,则产生中断),将要发送的数据写入到DR,则清除该位。在TxE被置1表示发送寄存器空,并且在上一次发送结束之前没有写数据到DR,则SR1.BTF会被置1.
关闭发送
CR1.STOP置1,产生停止条件。
在这里插入图片描述

接收模式
当发送完地址收到应答后,进入接收模式,接收完一个字节后,发出一个应答(CR1.ACK置1才会发送应答),SR.RxNE置1表示收到数据,(如果INEVFEN和ITBUFEN置1,则表示允许中断,这里会产生中断)

关闭通信
在收到最后一个字节后发送一个NACK,从设置将释放总线。
为了在最后一个字节产生NACK,在读倒数第二个字节后必须清除ACK位;为了产生停止条件,在读倒数第二个字节后,设置STOP位。

hal库函数:
初始化:
HAL_I2C_Init(I2C_HandleTypeDef *hi2c),流程如下:

开时钟,配置引脚
判断最小时钟是否达到,100K要求大于2M时钟,400k要求大于4M
计数有多少M时钟,然后写入CR2
根据时钟和设定的速度配置RISE
设置速率SPEED
设置CR1,时钟是否延长
设置自己地址

判断最小时钟是否达到,

  /* Check the minimum allowed PCLK1 frequency */
  if (I2C_MIN_PCLK_FREQ(pclk1, hi2c->Init.ClockSpeed) == 1U)
  {
    return HAL_ERROR;
  }
  
#define I2C_MIN_PCLK_FREQ(__PCLK__, __SPEED__)             (((__SPEED__) <= 100000U) ? ((__PCLK__) < I2C_MIN_PCLK_FREQ_STANDARD) : ((__PCLK__) < I2C_MIN_PCLK_FREQ_FAST))
// 如如初始化的时钟小于100K, 则宏定义返回的是((__PCLK__) < I2C_MIN_PCLK_FREQ_STANDARD)的比较结果,外设时钟小于2M吗,如果小于则返回1,返回1则上面的调用就会进入HAL_ERROR,表示模块时钟不够。

轮询模式,有4个函数:

 HAL_I2C_Master_Transmit()
HAL_I2C_Master_Receive()
HAL_I2C_Slave_Transmit()
HAL_I2C_Slave_Receive()

HAL_I2C_Master_Transmit():
主发送式:限时等待BUSY=0-----确认PE位等于0----清除CR1的POS位-----------发送从机地址-----#产生START------#限时等待SB set---------#写从机地址DR,并把最后1位读写标志清0------#等待ADDR set-------##如果等待期间AF set-----##产生STOP----##清除AF------------------清除ADDR-----等待TXE set-----写数据入DR-----如果BTF is set-----再写数据到DR----等待BTF set----循环直到数据发送完----产生STOP

另外HAL_I2C_Mem_Write()函数与上面HAL_I2C_Master_Transmit()的区别是:
HAL_I2C_Mem_Write()发送从机地址是调用I2C_RequestMemoryWrite() 发送从机地址,同时发送寄存器地址。

发送从机地址-----#产生START------#限时等待SB set---------#写从机地址到DR,并把最后1位读写标志清0------#等待ADDR set-------#清除ADDR-----#等待TXE set-------#把寄存器地址写到DR ------写数据到DR

HAL_I2C_Master_Receive():
**主接收:**限时等待BUSY=0-----确认PE位等于0----清除CR1的POS位-----发送从机地址-----#设置应答ACK-----#产生START------#限时等待SB set-----#发送从机地址,并把最后1位读写标志置1------#等待ADDR set-------##如果等待期间AF set-----##产生STOP----##清除AF------如果接收数据为0,清除ADDR并生产STOP----如果接收数据为1字节,清除应答ACK,清除ADDR,并产生STOP------如果接收为2字节,置1 POS,并清除ADDR,清除ACK------否则清除ACK,清作ADDR------------------------------------接收数据分几种情况----如果还剩大于3字节-----等待RXNE set-----把数据从DR读走----如果BTF is set,说明还有1字节没读走,再从DR读走1字节-------如果还剩3字节,等待BTF is set, BTF set以后说明已经收到2字节了,只剩1字节,设置非应答,从DR读走一字节,等待BTF再次set,说明已经接收完,产生STOP,从DR读走1字节,再次从DR读走1字节------如果还剩2字节,等待BTF set,产生STOP信号,读两次DR,读走2字节。--------如果还剩1字节,等待RXNE set, 然后从DR读走1字节。

可见主接收时有点复杂,接收到1个字节时,RXNE会置1,如果数据没有读走,再接收到1个字节时,BTF会置1。这时表示已经有2个字节待读走。

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
STM32I2C调试过程中,有两种实现I2C协议的方式。一种是通过GPIO口来模拟I2C协议,另一种是使用STM32自带的I2C模块。其中,使用GPIO口模拟I2C协议需要详细了解I2C协议的内容,并修改对应的源码实现功能。而使用STM32自带的I2C模块,可能会遇到一些问题,一些网上的声音指出该模块存在bug且难以调试。然而,这些问题在我自己的实践中尚未遇到,可能需要进一步验证。在调试过程中,需要注意以下几点: 1. 首先,要确保I2C1时钟已经使能。可以使用RCC_APB1PeriphClockCmd函数来使能I2C1时钟。 2. 其次,需要配置I2C参数。例如,设置I2C_Mode、I2C_DutyCycle、I2C_ClockSpeed等参数。 3. 进一步,需要初始化I2C模块。可以使用I2C_Init函数进行初始化,并通过I2C_Cmd函数使能I2C模块。 4. 在主机中断发送数据时,可以使用I2C_INT_Write函数进行发送。该函数会检查总线是否繁忙,然后进行传输处理,并使能I2C_IT_TXI中断。这样可以实现主机中断发送功能。 以上是关于STM32I2C调试过程的一些注意事项和示例代码。具体调试过程还需要根据实际情况进行。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* [STM32I2C模块调试总结](https://blog.csdn.net/u010847928/article/details/83445346)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *3* [STM32 I2C调试过程心得记录](https://blog.csdn.net/yhl_sophia/article/details/88718448)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值