发新帖本帖赏金 50.00元(功能说明)我要提问
123下一页
返回列表
打印
[PIC®/AVR®/dsPIC®产品]

如何解决PIC单片机的硬件I2C在驱动OLED显示屏时候的不好用问题

[复制链接]
5754|55
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
#申请原创# @21小跑堂

网友反应在硬件时钟设置较高的时候驱动SSD1306控制器的OLED模块时候无法工作,同样在设置I2C时钟为高速模式时候(1MHz,实际配置为800KHz)也无法工作。
那么这是什么情况呢?
经过我的实验总结如下:
SSD1306通常仅支持100Khz的低速模式和400KHz的中速模式。
查询相关资料内容:SSD1306 i2c的最大速度取决于具体的硬件和软件实现。 一般来说,它支持标准模式(100 kHz)和快速模式(400 kHz)的I2C通信。
所以设置为高速模式无法正常工作。
这是第一个解决的问题,即使用OLED模块时候,硬件I2C的速度推荐设置为400KHz。

接下面分析为何MCU系统时钟设置为高速的时候无法正常工作。
经过阅读MCC的源代码,I2C的通信为非阻塞通信,即不会卡顿在某处等待,如果不满足条件就会跳过去。所以如果系统时钟速度设置过高,导致在I2C从机还没来得及反应的时候就执行完毕了,这个时候总线繁忙,会自动跳过。相关库函数代码如下:
bool I2C1_Write(uint16_t address, uint8_t *data, size_t dataLength)
{
    bool retStatus = false;
    if (!I2C1_IsBusy())
    {
        i2c1Status.busy = true;
        i2c1Status.address = address;
        i2c1Status.switchToRead = false;
        i2c1Status.writePtr = data;
        i2c1Status.writeLength = dataLength;
        i2c1Status.readPtr = NULL;
        i2c1Status.readLength = 0;
        i2c1Status.errorState = I2C_ERROR_NONE;
        I2C1_WriteStart();
        retStatus = true;
    }
    return retStatus;
}
如何解决这个不同步问题呢?修改库函数?NO,我是不主张修改的,因为非阻塞可以防止整个系统卡死在某处。
经过尝试可以在每次调用完该函数后进行一定时间的延时。
经过测试,在系统时钟设置为最高速度64MHz的情况下,每次调用I2C写函数后延时50个系统周期可以正常通信,当低于49后开始不稳定。
void OLED_Write_cmd(uint8_t cmd)
{
    uint8_t cmd2[2];
    cmd2[0] = 0x00;
    cmd2[1] = cmd;
    I2C1_Write(0x3C, cmd2, 2);
    DELAY_microseconds(50);
}
void OLED_Write_data(uint8_t data)
{
    uint8_t data2[2];
    data2[0] = 0x40;
    data2[1] = data;
    I2C1_Write(0x3C, data2, 2);
    DELAY_microseconds(50);
}

这里推荐在64Mhz时钟下延时50,该函数并非是50us经过测试该函数参数对应位System Clock的时钟周期数。
8MHz系统时钟下,设置延时参数为1
16MHz系统时钟下,设置延时参数为6
其他时钟下,请参考以上范围调整到最小合适值即可。
总结:很多人说硬件I2C不好用,其实不是不好用,是很多时候没有能严格按照通信协议规范设置相关参数,比如常用的这个OLED模块,经常用于一些显示,比如文中提到的这个单片机,如果你没能很好的设置相关参数,并对时钟进行同步的延时操作,就无法正常高速点亮屏幕,你会以为是硬件的I2C不好用,其实不是。该文相信可以为很多用I2C硬件不好用的朋友提供一份参考,相信以后的项目中硬件I2C越来越流行。


使用特权

评论回复

打赏榜单

21小跑堂 打赏了 50.00 元 2024-01-11
理由:恭喜通过原创审核!期待您更多的原创作品~

评论
21小跑堂 2024-1-11 17:51 回复TA
文章针对PIC单片机的硬件I2C驱动OLED显示出现的问题给出一个解决方案,通过延时的方式等待数据完整通信,当然延时方式二姨也不认为是个好的方式,但是作者通过与评论区的互动,增加了超时检测,在保证通信完整性的同时防止程序卡死。这是比较好的一种方式,现在大多单片机的硬件I2C通信都会采用的方式。作者积极听取意见并给与改进,态度值得肯定。 
54
598330983| | 2024-6-27 17:24 | 只看该作者
楼主说的时钟问题,是不是冲突导致的。比如系统时钟配置低了,又想设置高速的I2C,导致的冲突。

使用特权

评论回复
53
幸福小强| | 2024-6-26 16:35 | 只看该作者
大佬分享一下SPI驱动WS2812B的方法啊。

使用特权

评论回复
52
gejigeji521| | 2024-6-25 23:07 | 只看该作者
对I2C分析的透彻。

使用特权

评论回复
51
LinkMe| | 2024-6-14 19:43 | 只看该作者
不同的屏幕,方法也不同。

使用特权

评论回复
50
Pretext| | 2024-6-4 23:26 | 只看该作者
库函数只实现为写,但不确定是否完成,如果忙,他不写,它已经通过。

使用特权

评论回复
49
软核硬核| | 2024-5-24 22:09 | 只看该作者
这就是 SPI 如何配置为只有发送线路,以便接收线路被用作普通的输入输出。

使用特权

评论回复
48
天天向善| | 2024-5-20 20:12 | 只看该作者
正确把握图书馆功能应用的方法和原则是十分必要的。

使用特权

评论回复
47
鹿鼎计| | 2024-5-14 23:21 | 只看该作者
只有充分理解相关协议,才能判断它是否被正确使用。

使用特权

评论回复
46
AIsignel| | 2024-5-10 20:50 | 只看该作者
这个大家伙已经很久没有更新帖子了,期待着更新 Spi 相关的技术。

使用特权

评论回复
45
朝生| | 2024-5-10 07:00 | 只看该作者
其他微控制器方面的经验也应该有助于收集。

使用特权

评论回复
44
digit0| | 2024-5-9 07:10 | 只看该作者
精通库函数和 i2c 协议。

使用特权

评论回复
43
理想阳| | 2024-5-7 06:47 | 只看该作者
正确把握图书馆职能运用的方法和原则就行了。

使用特权

评论回复
42
21mengnan| | 2024-5-6 20:04 | 只看该作者
这个讲的很好,有没有SPI接口的教程讲讲。

使用特权

评论回复
41
天灵灵地灵灵| | 2024-4-29 22:19 | 只看该作者
能充分了解相关的协议,才能判断是否正确的使用。

使用特权

评论回复
40
天灵灵地灵灵| | 2024-4-29 22:19 | 只看该作者
正确的配置是至关重要的。

使用特权

评论回复
39
yangxiaor520| | 2024-4-27 13:17 | 只看该作者
IIC的速率还是太低了

使用特权

评论回复
38
幸福小强| | 2024-4-26 22:43 | 只看该作者
认真看完了帖子,真心不错,期待出一个SPI的。

使用特权

评论回复
37
稳稳の幸福| | 2024-4-23 23:18 | 只看该作者
比如如何驱动SPI接口的LCD屏幕。

使用特权

评论回复
36
稳稳の幸福| | 2024-4-23 23:17 | 只看该作者
I2C跟着你的贴学的很懂了,SPI还不太明白,期待分享一下相关的技术。

使用特权

评论回复
35
稳稳の幸福| | 2024-4-23 23:17 | 只看该作者
大佬怎么好久没更新帖子了,期待更新一下SPI相关的技术。

使用特权

评论回复
发新帖 本帖赏金 50.00元(功能说明)我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

个人签名:如果你觉得我的分享或者答复还可以,请给我点赞,谢谢。

2011

主题

16159

帖子

215

粉丝