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

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

1. STM32L151C8T6 硬件IIC 控制OLED 屏,OLED 驱动IC CH1116G, 查阅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_PPGPIO_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 - PB11GPIO_ResetBits(GPIOB, GPIO_Pin_11);delay_xms(20);GPIO_PinAFConfig(GPIOB, GPIO_PinSource10, GPIO_AF_I2C2); // set PB10 as IIC2 SCLGPIO_PinAFConfig(GPIOB, GPIO_PinSource11, GPIO_AF_I2C2); // set PB11 as IIC2 SDAI2C_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 KhzI2C_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 addressI2C_Init(I2C2, &I2C_InitStruct);I2C_Cmd(I2C2, ENABLE);I2C_AcknowledgeConfig(I2C2, ENABLE);
}

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

在这里插入图片描述

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

在这里插入图片描述

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 signalIIC_SendStartSignal_CheckEvent();I2C_Send7bitAddress(I2C2, OLED_ADDRESS, I2C_Direction_Transmitter); // send device addr and write bitI2C_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_CmdI2C_SendByteDataWaitAck();IIC_Delay(IIC_TIMEOUT_COUNTER);I2C_SendData(I2C2, mode); // 0x00, low 8-bits, cmd codeI2C_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 stm32l151c8t6INFO_LOG("[OLED_Init] init start\r\n");OLED_SendCmd(0xAE); // display offOLED_SendCmd(0x02); // set colum start addressOLED_SendCmd(0x10); // set colum end addressOLED_SendCmd(0x40); // set start line (first row)OLED_SendCmd(0xB0); // set page addressOLED_SendCmd(0x81); // set contrast ratioOLED_SendCmd(0xCF); // 128OLED_SendCmd(0xA1); // set segment remapping, from right to leftOLED_SendCmd(0xA6); // forward display, normal or reverseOLED_SendCmd(0xA8); // multiple reuse rate, multiple ratioOLED_SendCmd(0x3F); // duty = 1 / 64OLED_SendCmd(0xAD); // set charge pump enableOLED_SendCmd(0x8B); // enable DC-DCOLED_SendCmd(0x33); // set VPP = 10VOLED_SendCmd(0xC8); // set output scan direction, COM[N - 1] to COM[0], COM scan directionOLED_SendCmd(0xD3); // set display offsetOLED_SendCmd(0x00); // 0x00OLED_SendCmd(0xD5); // set internal clock frequence, set osc frequencyOLED_SendCmd(0xC0);OLED_SendCmd(0xD9); // set pre-charge periodOLED_SendCmd(0x1F); // 0x22OLED_SendCmd(0xDA); // set COM pins, pin layoutOLED_SendCmd(0x12);OLED_SendCmd(0xDB); // set electrical level, set VCOMHOLED_SendCmd(0x40);OLED_SendCmd(0xAF); // enable display, display onINFO_LOG("[OLED_Init] init complete\r\n");
}

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

void OLED_Test(void)
{OLED_SendCmd(0xB0); // page 0OLED_SendCmd(0x00); // colume 0 low 4-bitsOLED_SendCmd(0x10); // colume 0 high 8-bitsOLED_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 timeoutstatic void IIC_Delay(uint32_t delay_time)
{uint32_t delayTime;for (delayTime = 0; delayTime < delay_time; delayTime++){}
}

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

在这里插入图片描述

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

在这里插入图片描述

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

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/69607.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

既要炫酷好看,又要出图快?可视化大屏模板了解下!

可视化大屏模板可以在很大程度上满足炫酷好看和出图快的需求。使用模板可以节约制作时间&#xff0c;像奥威BI系统就上线了大量的可视化大屏模板。这些模板实际上都是一张张完整的可视化大屏报表&#xff0c;从数据源到数据分析模型&#xff0c;再到数据可视化图表和智能分析功…

《vue3实战》运用push()方法实现电影评价系统的添加功能

目录 前言 电影评价系统的添加功能是什么&#xff1f; 电影评价系统的添加功能有什么作用&#xff1f; 一、push&#xff08;&#xff09;方法是什么&#xff1f;它有什么作用&#xff1f; 含义&#xff1a; 作用&#xff1a; 二、功能实现 这段是添加开始时点击按钮使…

支持CAN FD的Kvaser PCIEcan 4xCAN v2编码: 73-30130-01414-5如何应用?

这里是引用 Kvaser PCIEcan 4xCAN v2&#xff08;编码: 73-30130-01414-5&#xff09;是一款小巧而先进的多通道实时CAN接口&#xff0c;可发送和接收CAN总线上的标准和扩展CAN消息&#xff0c;时间戳精度高。其与所有使用Kvaser CANlib的应用程序兼容。 主要特性 PCI Express…

spring boot项目上传头像

应用还是验证码使用的原理&#xff1b;但是代码逻辑却有所不同。 逻辑前端传给后端&#xff0c;然后写入本机磁盘去&#xff0c;文件名用uuid避免重复。写完就可以顺带把文件名保存到数据库里。上传就这样子。 怎么取用的&#xff1b;还是通过配置映射的方式&#xff1b;通过sr…

vue3升级了些什么

Vue 3 升级了以下几个方面的内容&#xff1a; 响应式系统&#xff1a;Vue 3 使用了 Proxy 对象来替代 Vue 2 中的 Object.defineProperty&#xff0c;这使得响应式系统更加高效和灵活。Vue 3 的响应式系统可以追踪更细粒度的依赖关系&#xff0c;提供了更好的性能和更细致的响应…

Bootstrap的行、列布局设计(网络系统设计)

目录 00-基础知识01-等宽列布局02-指定某一列的宽度03-根据内容自动改变列的宽度04-五种预定义列宽度 .col、.col-sm-*、.col-md-*、.col-lg-*、.col-xl-*05-不同视口宽度按不同的分列方案划分06-删除列内容的盒模型的外边距07-超过12列怎么办&#xff1f;08-重新排列各列的顺序…

继承(个人学习笔记黑马学习)

1、基本语法 #include <iostream> using namespace std; #include <string>//普通实现页面//Java页面 //class Java { //public: // void header() { // cout << "首页、公开课、登录、注册...(公共头部)" << endl; // } // void footer() …

【精品】NLP自然语言处理学习路线(知识体系)

当前&#xff0c;大规模预训练语言模型的强大对话问答、文本生成能力&#xff0c;将自然语言处理&#xff08;NLP&#xff09;的研究和应用推向了新一轮的热潮。NLP是计算机科学、人工智能和语言学等学科交叉的前沿领域。NLP的应用和研究范围非常的广泛&#xff0c;个人是没有找…

利用GitHub实现域名跳转

利用GitHub实现域名跳转 一、注册一个 github账号 你需要注册一个 github账号,最好取一个有意义的名字&#xff0c;比如姓名全拼&#xff0c;昵称全拼&#xff0c;如果被占用&#xff0c;可以加上有意义的数字. 本文中假设用户名为 UNIT-wuji(也是我的博客名) 地址: https:/…

Git常用命令用法

参考视频&#xff1a;真的是全能保姆 git、github 保姆级教程入门&#xff0c;工作和协作必备技术&#xff0c;github提交pr - pull request_哔哩哔哩_bilibili 1.Git初始化 首先设置名称和邮箱。然后初始化一下&#xff0c;然后就创建了一个空的Git仓库。 PS D:\golang\oth…

node socket.io

装包&#xff1a; yarn add socket.io node后台&#xff1a; const express require(express) const http require(http) const socket require(socket.io) const { getUserInfoByToken } require(../../utils/light/tools)let app express() const server http.createS…

【C++漂流记】结构体的定义和使用、结构体数组、结构体指针、结构体做函数参数以及结构体中const的使用

结构体&#xff08;struct&#xff09;是C语言中一种重要的数据类型&#xff0c;它由一组不同类型的成员组成。结构体可以用来表示一个复杂的数据结构&#xff0c;比如一个学生的信息、一个员工记录或者一个矩形的尺寸等。 结构体定义后&#xff0c;可以声明结构体变量&#xf…

NCCoE发布“向后量子密码学迁移”项目进展情况说明书

近日&#xff0c;NIST下属的国家网络安全中心&#xff08;NCCoE&#xff09;发布了一份向后量子密码学迁移&#xff08;Migration to Post-Quantum Cryptography&#xff09;项目情况说明书。该文档简要概述了向后量子密码学迁移项目的背景、目标、挑战、好处和工作流程&#x…

【HTML5高级第二篇】WebWorker多线程、EventSource事件推送、History历史操作

文章目录 一、多线程1.1 概述1.2 体会多线程1.3 多线程中数据传递和接收 二、事件推送2.1 概述2.2 onmessage 事件 三、history 一、多线程 1.1 概述 前端JS默认按照单线程去执行&#xff0c;一段时间内只能执行一件事情。举个栗子&#xff1a;比方说古代攻城游戏&#xff0c…

Jenkins自动构建(Gitee)

Gitee简介安装JenkinsCLI https://blog.csdn.net/tongxin_tongmeng/article/details/132632743 安装Gitee jenkins-cli install-plugin gitee:1.2.7 # https://plugins.jenkins.io/gitee/releases获取安装命令(稍作变更) JenkinsURL Dashboard-->配置-->Jenkins Locatio…

鸿蒙系列-如何使用好 ArkUI 的 @Reusable?

如何使用好 ArkUI 的 Reusable&#xff1f; OpenHarmony 组件复用机制 在ArkUI中&#xff0c;UI显示的内容均为组件&#xff0c;由框架直接提供的称为 系统组件&#xff0c;由开发者定义的称为 自定义组件。 在进行 UI 界面开发时&#xff0c;通常不是简单的将系统组件进行组合…

NIO原理浅析(三)

epoll 首先认识一下epoll的几个基础函数 int s socket(AF_INET, SOCK_STREAM, 0); bind(s, ...); listen(s, ...);int epfd epoll_create(...) epoll_ctl(epfd, ...); //将所有需要监听的socket添加到epfd中while(1) {int n epoll_wait(...);for(接受到数据的socket) {//处…

Kotlin 环境下解决属性初始化问题

&#x1f337;&#x1f341; 博主猫头虎&#xff08;&#x1f405;&#x1f43e;&#xff09;带您 Go to New World✨&#x1f341; &#x1f984; 博客首页——&#x1f405;&#x1f43e;猫头虎的博客&#x1f390; &#x1f433; 《面试题大全专栏》 &#x1f995; 文章图文…

react使用hook封装一个tab组件

目录 react使用hook封装一个tab组件Tabbar.jsx使用组件效果 react使用hook封装一个tab组件 Tabbar.jsx import PropsTypes from "prop-types"; import React, { useEffect, useState } from react; export default function Tabbar(props) {const { tabData , cur…

使用pip下载第三方软件包报错超时处理方法

报错如下&#xff1a; WARNING: Retrying (Retry(total4, connectNone, readNone, redirectNone, statusNone)) after connection broken by ‘ReadTimeoutEr ror(“HTTPSConnectionPool(host‘files.pythonhosted.org’, port443): Read timed out. (read timeout15)”)’: /p…