STM32 硬件IIC 控制OLED I2C卡死问题

这篇具有很好参考价值的文章主要介绍了STM32 硬件IIC 控制OLED I2C卡死问题。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

#更新通知:2023-09-06 STM32L151 固件库 使用I2C 太难了,又宕机了,建议不要在固件库版本上尝试硬件IIC 了,一般人真用不了,直接使用软件模拟的,或者不要使用固件库了,用HAL 库吧,据说HAL 库没这么多问题,不死心的我还是死心了,等有空再研究吧

1. STM32L151C8T6 硬件IIC 控制OLED 屏,OLED 驱动IC CH1116G, 查阅OLED 数据手册

STM32 硬件IIC 控制OLED I2C卡死问题,stm32,单片机,嵌入式硬件,OLED

2. STM32 硬件IIC 初始化,用的标准库,固件库

// stm32l151c8t6 as master, oled control ic (CH1116G) as slave, and communicate by master iic2
void STM32L151C8T6_IIC_Init(void)
{
    GPIO_InitTypeDef GPIO_InitStruct;
    I2C_InitTypeDef I2C_InitStruct;

    RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOB, ENABLE);
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C2, ENABLE);

    GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF;
    GPIO_InitStruct.GPIO_OType = GPIO_OType_PP; // GPIO_OType_OD, GPIO_OType_PP
    GPIO_InitStruct.GPIO_Pin = GPIO_Pin_10 | GPIO_Pin_11;
    GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_UP;
    GPIO_InitStruct.GPIO_Speed = GPIO_Speed_400KHz;
    GPIO_Init(GPIOB, &GPIO_InitStruct); // IIC2 SCL - PB10, SDA - PB11

    GPIO_ResetBits(GPIOB, GPIO_Pin_11);
    delay_xms(20);

    GPIO_PinAFConfig(GPIOB, GPIO_PinSource10, GPIO_AF_I2C2); // set PB10 as IIC2 SCL
    GPIO_PinAFConfig(GPIOB, GPIO_PinSource11, GPIO_AF_I2C2); // set PB11 as IIC2 SDA

    I2C_InitStruct.I2C_Ack = I2C_Ack_Enable;
    I2C_InitStruct.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;
    I2C_InitStruct.I2C_ClockSpeed = iic_clockSpeed_400Khz; // must be less than 100 Khz
    I2C_InitStruct.I2C_DutyCycle = I2C_DutyCycle_2;
    I2C_InitStruct.I2C_Mode = I2C_Mode_SMBusHost; // 这里很重要
    I2C_InitStruct.I2C_OwnAddress1 = IIC2_NOT_USE_OWN_ADDR; // do not use own address

    I2C_Init(I2C2, &I2C_InitStruct);

    I2C_Cmd(I2C2, ENABLE);

    I2C_AcknowledgeConfig(I2C2, ENABLE);
}

3. GPIO 引脚速率要和 I2C 速率匹配,这很重要

STM32 硬件IIC 控制OLED I2C卡死问题,stm32,单片机,嵌入式硬件,OLED

3.1 I2C模式,我这里选的是主机模式,选其它模式就会出问题

STM32 硬件IIC 控制OLED I2C卡死问题,stm32,单片机,嵌入式硬件,OLED

4. OLED 硬件I2C 发送函数封装,给OLED发送的东西分两种:①发的是数据,②发的是命令

// master (STM32L151C8T6) send cmd instruction to oled screen control ic (CH1116G)
void OLED_SendCmd(uint8_t cmd)
{
    WaitFor_IIC_ReadyToWorking();

    I2C_GenerateSTART(I2C2, ENABLE); // iic start signal

    IIC_SendStartSignal_CheckEvent();

    I2C_Send7bitAddress(I2C2, OLED_ADDRESS, I2C_Direction_Transmitter); // send device addr and write bit

    I2C_SendDeviceAddrWaitAck();

    IIC_SendByteToOLED(iic_transmitType_Cmd);

    IIC_Delay(IIC_TIMEOUT_COUNTER);
    I2C_SendData(I2C2, cmd);
    I2C_SendByteDataWaitAck();

    I2C_GenerateSTOP(I2C2, ENABLE);
    IIC_Delay(IIC_TIMEOUT_COUNTER);
}

5. IIC 发送数据之前先检查I2C 是否有空,STM32 为了规避飞利浦的发明专利,把硬件I2C 搞的很复杂,导致固件库会有卡死的问题,据说HAL 库解决了这问题,本人没用过HAL库

static void WaitFor_IIC_ReadyToWorking(void)
{
    while (I2C2->SR2 & 0x02)
    {
        INFO_LOG("[WaitFor_IIC_ReadyToWorking] i2c2 is busy\r\n");
    }
}

6. 发送完起始信号后,要检查起始信号事件, 不要用固件库检查事件函数,会卡死的

static void IIC_SendStartSignal_CheckEvent(void)
{
    while (!((uint16_t)(I2C2->SR1) & (uint16_t)(0x0001)))
    {
        printf("[IIC_SendStartSignal_CheckEvent][] I2C_SR1=0x%04x, I2C2_SR2=0x%04x\r\n", I2C2->SR1, I2C2->SR2);
    }
    while (!((uint16_t)(I2C2->SR2) & (uint16_t)(0x0003)) == 0x0003)
    {
        printf("[IIC_SendStartSignal_CheckEvent][] I2C_SR1=0x%04x, I2C2_SR2=0x%04x\r\n", I2C2->SR1, I2C2->SR2);
    }
}

7. 发送完设备地址也要检查发送设备地址这个事件,同样不能用固件库函数

static void I2C_SendDeviceAddrWaitAck(void)
{
    while (!((uint16_t)(I2C2->SR1) & (uint16_t)(0x0082)) == 0x0082)
    {
    }
    while (!((uint16_t)(I2C2->SR2) & (uint16_t)(0x0007)) == 0x0007)
    {
    }
}

8. 发送命令给OLED 屏,这里要发两次,我也暂时没弄明白为什么,这个地方搞死我了,好惨

static void IIC_SendByteToOLED(uint8_t mode)
{
    IIC_Delay(IIC_TIMEOUT_COUNTER);
    I2C_SendData(I2C2, mode); // 0x00, high 8-bits, cmd code, iic_transmitType_Cmd
    I2C_SendByteDataWaitAck();

    IIC_Delay(IIC_TIMEOUT_COUNTER);
    I2C_SendData(I2C2, mode); // 0x00, low 8-bits, cmd code
    I2C_SendByteDataWaitAck();
}

9. 发送完命令后要检查标志位, while 里面可以啥都不写,空转,死等,也可以加一个超时退出,但是超时退出只能解决卡死的问题,并不能解决I2C busy 卡死导致发不出去数据的问题,治标不治本,这一点被别人说的坑死了,网上有人说超时退出可以解决卡死问题,但仅仅只解决了卡死问题,I2C 还是没有工作起来,我们的最终目的是让I2C 工作起来

static void I2C_SendByteDataWaitAck(void)
{
    while (!((uint16_t)(I2C2->SR1) & (uint16_t)(0x0080)) == 0x0080)
    {
    }
    while (!((uint16_t)(I2C2->SR2) & (uint16_t)(0x0007)) == 0x0007)
    {
    }
}

10. OLED 初始化,不同的驱动IC 会有所区别,但是可以先用我这个套用一下试试,我是在STM32L151C8T6 芯片上还跑了FreeRTOS 实时操作系统的

void OLED_Init(void)
{
    delay_xms(20); // oled startup slowly than stm32l151c8t6
    INFO_LOG("[OLED_Init] init start\r\n");

    OLED_SendCmd(0xAE); // display off

    OLED_SendCmd(0x02); // set colum start address
    OLED_SendCmd(0x10); // set colum end address

    OLED_SendCmd(0x40); // set start line (first row)

    OLED_SendCmd(0xB0); // set page address

    OLED_SendCmd(0x81); // set contrast ratio
    OLED_SendCmd(0xCF); // 128

    OLED_SendCmd(0xA1); // set segment remapping, from right to left

    OLED_SendCmd(0xA6); // forward display, normal or reverse

    OLED_SendCmd(0xA8); // multiple reuse rate, multiple ratio
    OLED_SendCmd(0x3F); // duty = 1 / 64

    OLED_SendCmd(0xAD); // set charge pump enable
    OLED_SendCmd(0x8B); // enable DC-DC

    OLED_SendCmd(0x33); // set VPP = 10V

    OLED_SendCmd(0xC8); // set output scan direction, COM[N - 1] to COM[0], COM scan direction

    OLED_SendCmd(0xD3); // set display offset
    OLED_SendCmd(0x00); // 0x00

    OLED_SendCmd(0xD5); // set internal clock frequence, set osc frequency
    OLED_SendCmd(0xC0);

    OLED_SendCmd(0xD9); // set pre-charge period
    OLED_SendCmd(0x1F); // 0x22

    OLED_SendCmd(0xDA); // set COM pins, pin layout
    OLED_SendCmd(0x12);

    OLED_SendCmd(0xDB); // set electrical level, set VCOMH
    OLED_SendCmd(0x40);

    OLED_SendCmd(0xAF); // enable display, display on

    INFO_LOG("[OLED_Init] init complete\r\n");
}

11. OLED 测试函数封装,B 站博主keysking

void OLED_Test(void)
{
    OLED_SendCmd(0xB0); // page 0
    OLED_SendCmd(0x00); // colume 0 low 4-bits
    OLED_SendCmd(0x10); // colume 0 high 8-bits

    OLED_SendCmd(0x40);
    OLED_SendCmd(0xAA);
}

12. 主函数调用OLED 初始化函数和测试函数,先延时一会再初始化,因为STM32 比OLED的控制IC 起来的快很多,CH1116G

int main(void)
{
	delay_xms(1000);
    OLED_Init();
    OLED_Test();
}

13. IIC_Delay 函数

#define IIC_TIMEOUT_COUNTER    0x1000 // iic transmit timeout

static void IIC_Delay(uint32_t delay_time)
{
    uint32_t delayTime;
    for (delayTime = 0; delayTime < delay_time; delayTime++)
    {
    }
}

14. 用逻分仪抓的数据看不出来细节,可以用示波器抓一下波形,看细节,这个波形都变形了,查看原理图,上面接了两个电容,把SCL 和SDA 当成高频信号,给我滤掉了,导致这波形乱七八糟的,直接把原理图上的两个对地电容去掉,或者更好其它容量的电容,我这里是直接去掉了

STM32 硬件IIC 控制OLED I2C卡死问题,stm32,单片机,嵌入式硬件,OLED

15. 接了两个对地电容,把正常信号当成高频滤掉了

STM32 硬件IIC 控制OLED I2C卡死问题,stm32,单片机,嵌入式硬件,OLED

16. 正常波形,应该是这样的,方波才对,正弦波是有问题的,这里还有一个小台阶,待处理

STM32 硬件IIC 控制OLED I2C卡死问题,stm32,单片机,嵌入式硬件,OLED文章来源地址https://www.toymoban.com/news/detail-696297.html

到了这里,关于STM32 硬件IIC 控制OLED I2C卡死问题的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • STM32 OLED显示汉字及屏幕滚动(I2C协议)

    理解OLED屏显和汉字点阵编码原理,使用STM32F103的SPI或IIC接口实现以下功能: 显示自己的学号和姓名; 显示AHT20的温度和湿度; 上下或左右的滑动显示长字符。 STM32F103C8T6最小板 AHT20温湿度传感器 ST-LINK 仿真器 4针脚使用I2C通信协议的OLED屏 面包板 杜邦线 KEIL 5 字模软件 可以看

    2024年02月03日
    浏览(72)
  • STM32硬件I2C通信外设

    本文主要介绍stm32自带的I2C通信外设,对比与软件模拟I2C,硬件I2C可以自动生成时序,时序的操作更加及时规范,可以实现更加高性能的IIC通信。 本文内容与I2C软件通信有诸多类似之处,I2C软件通信可见:https://blog.csdn.net/qq_53922901/article/details/136662006?spm=1001.2014.3001.5501 在8位指

    2024年04月08日
    浏览(95)
  • 电脑传输数据STM32模拟I2C显示实时画面到OLED

    写的不好,还望大家指正,有的地方引用了一下大佬的代码。 一、所需硬件: STM32F103C8T6 USB转串口模块 OLED 128*64显示屏 STLINK 二、代码部分 1.stm32串口部分代码 2.stm32OLED屏幕部分代码 3.主程序 4.电脑通过opencv库截取电脑当前1080p一帧画面,并对图片二值化处理,通过电脑端编写

    2024年02月13日
    浏览(43)
  • STM32 HAL FreeRTOS 硬件I2C 使用

    因为某个项目想要颜色识别,去识别球的颜色,但是又不想多来个摄像头,所以想尝试一下颜色传感器的方案。但是经过尝试,HAL库生成的 FreeRTOS 硬件 I2C 读写一直在报错。 刚好手头上有九轴陀螺仪的例程代码。最后用FreeRTOS 硬件 I2C 读取数据。 这里提到了阻塞式 HAL 函数(

    2024年02月20日
    浏览(49)
  • STM32 SHT40驱动源码(使用硬件I2C)

    目录 简介: SHT40.c: SHT40.h 测试结果:         SHT40是瑞士Sensirion公司推出的第四代温湿度传感器,内部集成加热器用于去除表面微小液滴。集成I2C接口,典型的相对湿度精度1.8%RH,典型温度精度0.2℃,运行在0-100%RH和-40-125℃的环境中。 主控:STM32H7B0VBT6 平台:STM32CubeIDE SHT4

    2024年03月19日
    浏览(72)
  • STM32F407系列硬件I2C笔记

    STM32F407系列有3个硬件I2C: I2C1:该接口位于GPIOB引脚上,包括PB6(I2C1_SCL)和PB7(I2C1_SDA)。 I2C2:该接口位于GPIOB引脚上,包括PB10(I2C2_SCL)和PB11(I2C2_SDA)。 I2C3:该接口位于GPIOA和GPIOC引脚上,包括PA8(I2C3_SCL)和PC9(I2C3_SDA)。   硬件I2C的速度比软件I2C更快,硬件I2C通常可以

    2024年02月04日
    浏览(45)
  • 【STM32】STM32学习笔记-硬件I2C读写MPU6050(35)

    I2C(Inter-Integrated Circuit)总线是一种由NXP(原PHILIPS)公司开发的两线式串行总线,用于连接微控制器及其外围设备。多用于主控制器和从器件间的主从通信,在小数据量场合使用,传输距离短,任意时刻只能有一个主机等特性。 串行的 8 位双向数据传输位速率在标准模式下可

    2024年01月25日
    浏览(57)
  • STM32F030硬件I2C代码及解析

    刚接触STM32的时候,第一个学习的就是I2C,当时去网上学习别人写得I2C代码,虽然能用,但是当时并不理解为什么要这么配置,特别希望有人把代码掰碎了讲讲看,今天突然想起来,就把以前写的I2C代码拿出来掰碎了捋捋,希望对新手有些帮助。 先说说STM32的I2C: ST的M3系列还

    2024年02月08日
    浏览(45)
  • 【STM32学习】——STM32-I2C外设&硬件读写MPU6050&软硬件读写波形对比

    目录 前言 一、I2C外设 二、硬件I2C操作流程 1.主机发送时序 3.其他时序

    2024年02月10日
    浏览(45)
  • Hi3861 硬件 i2c 驱动 oled

    最近想用 3861 做个有意思的东西,记录一下开发过程。今天使用 3861 的硬件 i2c 驱动 oled。 硬件平台:Bearpi-Nano 软件SDK:润和sdk 我之前写过一篇基于 stm32cubemx 快速使用 iic 接口 oled 的过程,里面有现成的 oled 接口,我们只要直接拿过来替换掉底层接口就行。  STM32CubeMX驱动4脚

    2023年04月23日
    浏览(45)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包