欢迎光临散文网 会员登陆 & 注册

STM32F103的硬件I2C调试记录

2020-09-14 17:17 作者:奥大梨呀  | 我要投稿

    提到I2C协议,搞嵌入式的朋友肯定不陌生,它是一种半双工的串行同步通信协议。通信速率通常分为标准模式(100Kbit/S)和快速模式(400Kbits/S)。笔者在学习51单片机操作AT24C02这个EEPROM的时候第一次接触到I2C协议,因为传统的89C51并不带有I2C控制器,因此只能使用IO模拟的方式来驱动I2C器件。

    笔者后来学习STM32的时候,因老师说STM32F1的硬件I2C不好用,因此在以后很长一段时间笔者在驱动I2C器件时都是采用IO模拟的方式。网络上也有很多朋友采用IO模拟的方式,理由大多是因为IO模拟的方式稳定、便于移植等。最近,笔者突然打算研究一下STM32F1的硬件I2C,毕竟对于CM3内核的单片机,甚至是CM4、CM7内核的单片机,这样的高性能单片机使用IO模拟的方式来驱动I2C器件太浪费CPU的性能了。

    这次笔者的实验平台是STM32F103RCT6这块MCU,其中驱动的I2C器件是NXP的一款I2C接口的RTC芯片——PCF8563,连接到STM32F103RCT6的PB11(I2C2_SDA)和PB10(I2C2_SCL),板子是笔者团队自己画的,就是先前视频(BV1PA411i7Sx)里驱动数码管的那块板子。

    由于笔者是第一次使用STM32的硬件I2C,因此就暂时采用轮询的方式,并没有采用中断或者DMA的方式了。

    要使用STM32的硬件I2C,首先需要对I2C控制器进行初始化,这里笔者为了提高代码的可重用性,提前构思好了一个框架,将I2C驱动进行了一个封装:

1.首先是I2C初始化结构体,包含了一个I2C控制器初始化参数的一些信息。

    

        然后编写一个函数根据这个结构体的信息对I2C控制器进行初始化:

2.然后是I2C的数据传输,也使用结构体进行了一个封装。

这个封装的思路其实是笔者从Linux的I2C驱动的I2C数据传输中模仿而来的。所有的数据传输函数的形式参数只有一个,就是这个I2C_TransferType结构体指针类型。

至此I2C主机控制器层就搭建完毕了。

然后是PCF8563的驱动,为了方便操作时间,同样也构建了一个用来表示时间的结构体:

而PCF8563层就是调用I2C层的读写API对其寄存器进行操作了。

比如,往PCF8563写入时间的API:

最终则是在uCOS-III操作系统创建的一个线程中每隔500ms读取一次时间在数码管上显示出来(数码管驱动就是先前视频中的那个DMA+定时器的驱动)。

    以上是笔者在进行程序开发时的思路,但是STM32F103的硬件I2C不是那么好掌控的,笔者在调试过程中也是遇到了很多问题。

    程序刚刚编译通过第一次运行时,上电运行直接死机。注意,笔者使用了RTOS,如果只是因为RTC线程中I2C读取某个标志位时卡在了while中,并不会影响其他线程,LED还是会闪。但是LED也灭了,在线debug的时候发现程序最终是进入了HardFault_Handler,说明I2C里某些操作导致STM32硬件错误。

    最终在ST的官方手册中找到了原因,在I2C读取最后1字节数据前,应该先设置非应答和停止信号,然后再去读数据,笔者一开始是将这两步按正常的I2C协议放在了最后。

    之后又修改了一些笔者拷贝相同代码时,粗心导致的一些变量忘记修改,比如txlen在接收函数中忘记改成了rxlen。

    经过了两三天的搭建和调试,总算是把STM32的硬件I2C搞定了,采用的是轮询的方式,日后看找个时间试试中断或者DMA的方式吧。这个I2C和PCF8563的代码我会在文末贴出来供大家参考,写的不好的地方也请批评指正。

    最后总结一下STM32F1的硬件I2C,据网友说,ST为了规避专利问题,将I2C控制器复杂化了,而且STD库貌似也有些许BUG,但还是可以用的(不然ST就不会发布这款芯片了)。对于F1的硬件I2C,貌似还有其他毛病,比如通信速率不能过快、不能被打断等。笔者在PCF8563驱动中使用的400KHz的通信速率,目前并没有发现异常,但长期来看也不好说,指不定什么时候卡死了呢。至于不能被打断,笔者在驱动中使用RTOS提供的关中断的方式来确保I2C读写过程连续不被打断。如果采用STM32F1的方案且使用到I2C器件的话,为了稳定性,推荐还是使用IO模拟的方式吧,至少容错率高。


代码链接:

https://pan.baidu.com/s/155xub7hBSiYXG7fi-tB--A 

提取码:u8ng


STM32F103的硬件I2C调试记录的评论 (共 条)

分享到微博请遵守国家法律