资讯详情

【RTOS训练营】I2C和UART知识和预习安排 + 晚课提问

一、I2C

对于I2C,芯片内部有I2C控制器。

他的结构如下图所示:

请添加图片描述

我们配置好I2C控制器之后,去读写寄存器就可以了。

但是在我们的视频中,我们使用它GPIO引脚来模拟I2C。

让我们先 I2C本协议为硬件连接图:

一个主芯片,多个从芯片。

假设我们的arm这是一个主芯片,他必须访问这个i2c他该怎么办?

我讲i2c在协议中,体育育老师发球的例子:

让我们看看i2c如何传输总线上的数据:

(S为Start,开始信号)

如何规定S信号?

你看,通常这两个引脚都是高电平的,然后SDAS信号从高到低。

我们使用i2c如果控制器写程序,就是写一个寄存器,他会自动帮你发S信号。

我们用gpio来模拟I2C怎么办?

对于这个代码,让我们画一张图片:

在i2c协议里面, S没有规定信号低电平维持多久,

这位体育老师想发球给一个学生,他必须点名,这就是地址。

老师想把球送给他,而不是让学生传回球,所以还有一个方向。

S主设备发出信号后,应发出信号,并发出数据

设备地址为7位,数据传输方向为1位,加起来为8位。

主要设备就像老师一样,老师点名学生回答:到。

主设备发布设备地址和数据的读写方向。如果有这个设备,他想。如何回应?

主设备发出7位地址和1位方向后,立即释放SDA,也就是说,这个时候SDA是高电平。

如果对方存在,他会把它放在一边SDA拉下。将检测到主要设备sda,他发现:哦,有人把这个拿走了SDA如果你把它拉低,那么这个设备一定存在。

说到这里,这就涉及到了I2C精致的传输。

您可以看到,在这个传输过程中,发送方控制SDA由接收方控制的时间为8个时钟。

也就是说SDA他由发送方和接收方控制。

如果每个人的时间都管理得很准确,你可以控制这个时间;另一次,我控制。

每个人的时间都没有交叉,这不会有问题。

但如果每个人的时间都有交叉呢?

例如,发送方将引脚设置为高电平, 同时,我时将引脚设置为低电平, 同一个引脚,一方写高,另一方写低,不是冲突吗?也许它会烧坏引脚。

怎么办呢?

这就引入了开漏电路,我来画一张图:

如何避免冲突?

也就是说,如果有人想把引脚设置成高电平,他什么都不做,把决定权交给别人。

什么意思?

当发送方希望引脚发出低电平时,在发送方内部,它相当于将引脚接地。

当发送者想要引脚发出高电平时,他该怎么办?

再看这张图,我在发送方,我想让这个引脚发出高电平。

我有两种方法:

1.让这个引脚在内部接收电源

但是这种方法我们刚才说过了,有可能会跟别人发生冲突。

2.使用第二种方法,就像上图一样, 如果他想发出高电平,他会断开引脚和芯片内部的模块。

他说:我想发高电平,你怕我和别人冲突,那我就不在乎了,爱怎么滴就怎么滴

他不在乎,那么这个电平是高还是低?

决定。

发送方想发高电平,又怕他和别人冲突, 所以他什么都不在乎,电平由上拉电阻决定。

发送方想发高电平,接收方突然想发低电平。会发生什么?

我们画一幅图:

图中的蓝色是接收方,他想发出低电平, 在芯片内部,它就相当于把这个引脚接到地。

这个引脚,一边发1,另一边发0,最终结果是什么?

是低电平。

有冲突吗?你什么都不在乎发送方。 引脚电平:上拉电阻 和 另一方决定。

在这种操作下,不会烧坏电路。

在图中,我们用红色叉号表示断开引脚。

使用三极管实现芯片内部,我们再画一幅图:

看图中左边。 当他想发出高电平时,他通过反向器进入三极管。三极管的截止日期相当于此SDA断开左芯片。

当主芯片想要发出低电平时,通过反向器进入三极管,三极管导通,相当于SDA接地。

主机发出S信号,发出设备地址和方向,得到回应:可以发送或读取数据。

每个芯片的含义不同于发送和读取的数据。

让我们选择一个存储芯片来看看:

既然是存储芯片,就可以写数据,也可以从中读数据。

我要写数据时,写存储空间的哪个地址?写什么数据?

所以在图片中,你可以看到红色1是存储地址,红色2是数据。

对于写作操作,主设备将地址值和数据值发送给存储设备。

读取操作怎么样?您想读哪个存储地址?该地址应由主设备从设备发送。

读取的数据应从设备返回到主设备。

因此,读取存储芯片的数据将涉及两个I2C操作,一个是写地址,一个是读数据。

在上面的图里你可以看到读操作,会涉及两个S信号。

第一个S信号后写操作,第二个S信号后读操作。

再来看看oled:

S然后是设备地址,然后是控制字节,然后是数据。

这个在视频中讲得很清楚,简单举几个例子:

对oled,我们可以给他发命令,比如启动它,关闭它: 上面这个函数发送的0x00说我要给你发命令。什么是命令?cmd参数。

如何发送数据?在下面的函数中,它必须先发送0x40这个值,然后是数据本身data。

这些设备的i2c数据含义, 查看这些设备的芯片手册。

二、UART

现在我们来谈谈UART,UART常用。

图中只有一条线:

左边怎么给右边,怎么通过一条线发数据?

关键在于

一开始,引脚是高电平的。他想发送数据。他引脚设置为低电平一段时间。这是通知对方说:嘿,我要发送数据了

发送方这边,就接下来在每一段时间里发出一位数据。

在接收方这边,每次都要读取引脚,得到数据

UART协议比较简单,因为双方都要约定非常准确的时间。

所以一般来说,不可能用引脚来模拟串口。

假设你用引脚模拟串口,你可能会被中断程序打断,所以时间不会混乱。

因此,芯片中的串口模块将用于串口。

配置串口模块后,如果要发送数据,可以将数据写入寄存器。

串口模块将逐个发送这些数据。

串口模块将从接收引脚上检测信号,逐个读取这些数据,并将其组合成8位数据。

对于串口章节,环形缓冲区更有趣

三、预习安排

安排预览的视频和文档:

就像今天一个同学提出的建议一样,预习的时候不仅要有视频,还要有文档。

这里有文档和源码:

对于项目1, 主要是给大家打基础,前面有C语言基础,有HAL开发的基础, 接下来,我将讨论如何设计一个更好的程序。如何做这个程序的框架更容易扩展和移植。

星期天,让我们全天制作视频!

直播, 彻底掌握C语言。

关注微信官方账号,微信官方账号写不好,然后会有一些转发奖励。

因为我们的直播将持续近6个小时,你最好来现场参加,否则当你想在第二天看的时候,你不能看6个小时

四、 晚班学生提问

1. 问: I2C开始信号中,SCL低电平时间最短多少?

最短多长没看过资料,但是肯定不能太短,太短的话对方都检测不到这个信号。低电平最长多长,具体数值我也没去看,只要对方芯片不会自动进入休眠状态就可以。在I2C协议里面,这个时钟它并不需要很准确,根本就不需要准确。通信的双方,只要有一个说我还没准备好,他就可以把SCL拉低让对方等他一会。

在使用GPIO模拟I2C中,延时会不会受到其他中断任务的影响?

肯定会受到影响,delay时间容易被其他任务、容易被中断 延长。如果对方的设备,对于时序要求非常高的话,那就不能够用gpio来模拟。我们使用gpio模拟的时候,主要是因为没有I2C控制器,或者不够用。

在使用GPIO模拟I2C中, 不要delay可以吗?

不加delay也可以的原因在于:

在使用GPIO模拟I2C中,上拉电阻多大合适?

10K左右。你要问我原因,我也说不上准确的原因,100K我也试过,1K、2K,10K、100K都行。只要是上拉就可以,这主要跟内部的晶体管,那个三极管或者MOS管有关系: 能让他导通就可以。

GPIO模拟和芯片内部控制哪个好?实际工作中用哪种?

有I2C控制器,就使用I2C控制器;没有的话才使用GPIO来模拟。

为什么现在好多芯片都有硬件iic 大家都不用 ,说不稳定,非要用gpio模拟?

实际上有硬件就用硬件,没硬件才用gpio来模拟,以前说是难用,应该是某一款芯片的I2C硬件有BUG。然后大家以讹传讹,一直以为有bug。我们去访问某些I2C设备时,如果不追求效率的话,用引脚来模拟,主要是因为懒,懒得去看I2C的寄存器操作。就比如我移植rt-smart到IMX6ULL的时候,要去操作触摸屏,一开始我们也懒得去看那些寄存器,直接用GPIO模拟好了。

I2C中,主机发完S信号,要回检吗? 如果有设备没有准备好,是不是还不能立即发送地址?

这个问题我暂时没法回答,在时序图里面,他并没有监测SDA。但是I2C,它有总线冲突的检测机制,现在我也没有办法去查资料,他肯定有回检的功能的。

如果2个进行IIC通讯,怎么确定设备的地址?

这个地址由程序来决定。温湿度传感器芯片内部那个程序,不是我们写的,是厂家写的,他也会去判断SDA线上传输的地址值是不是他的

硬件I2C是不是限制管脚的?

是的, I2C模块能够使用外部引脚,就几个,这要看芯片手册确认。

为什么有的需要NACK 有的需要 ACK?

NACK 就是不回应。 就比如说你要写数据给从设备,从设备每收到一个数据都会给你回应。 但从机有时可能不会回应,比如回应时刚好发生了中断,此时主设备设计程序就需要考虑不理会ACK信号。

如果最后一位发的是0,确认也是0,那么主设备怎么判断从设备到底有没有确认?

送完第8位数据的时候,主机方一定要设置SDA为1,然后在第9个时钟读取引脚。

怎么确定有没有开漏?

看芯片手册。

Pushpull会讲到吗?

看我同事录制的视频里面讲的很清楚:

图里的Clock line held low by receiver and/or transmitter是什么意思?

意思是:Scl为低电平的时候,大家都暂停i2c操作。

也就是说我发送着发送着,唉,发现我有些忙不过来,我可以把scl拉低:让对方的从设备等待一会。

也可以反过来:接收方得到数据之后,发现,唉,这个数据比较难处理,我得花很长时间。他就可以把scl拉低让发送方等待一会。

Input是用的什么电路不影响sda的?

一个引脚被配置成输入时,他就是高阻状态 ,不会影响到外面的电路

老师,第九个时钟设成高阻态可以吗?

可以在第9个时钟,发送方不要去影响到别人,设置成高阻状态是可以的。

有没有讲解串口接收字符串的?

你可以用环形缓冲区来接收字符串,这字符串要有一个分隔符。一般就是回车换行,用回车换行来区分:上一个字符串、下一个字符串。

串口通信和IIC通信的距离一般多长?

I2C使用TTL电平时,就是在电路板上传输,也就厘米量级吧(比如10cm),TTL电平也是厘米量级的。将串口转化成RS232电平,则是米量级比如5米。

环行缓冲区定义的不是指针,为什么视频里按地址算,更像计数器。

在视频里面说指针只是一个习惯性的说法,应该就像你说的就是一个计数器。

老师,讲解下FIFO和回调函数?

UART是一个很慢的设备。

我们使用窗口时,很多时候是突发地要传很多数据,比如:printf("hello, world");

为了提高效率,串口模块内部有一个FIFO缓冲区。

你可以一次性的写入多个字节的数据,然后就不管了,串口模块会从FIFO缓冲区里面把那些数据一个一个的取出来发送出去。

接收缓冲区也是类似的,别人可能一次性的给你发来很多个串口数据,串口模块把这些数据收起来之后,也放入FIFO缓冲区。

我们应用程序去读串口的时候,就可以一次性的读出多个数据。

回调函数,在串口中断里面用到:

你不想去修改中断的处理函数,但是你又想在发生中断时去做一些事情,

就可以提供一个回调函数,在串口的中断服务程序里面,它会去调用你提供的这个函数。

串口里面,双发约定时间,例如传输1个位的时间是200ns,波特率是多少,硬件串口波特率最大支持多大?

串口的波特率最大也就是兆级别的。传出一个位需要200纳秒,波特率就是:1/200ns = 1000,000,000/200 = 5,000,000 波特率。一秒钟可以传输500万位。

问一个问题,波特率设置为115200,起始位是一位,数据位是8位,停止位是一位,没有校验位。115200的波特率,1秒钟可以传多少字节?

传输一个字节。一个字节是8位,但是需要一个起始位,一个停止位,也就是说传输一个字节需要10位。所以就是:115200/10 = 11520。

老师,两个假期想好好学习单片机裸机程序,用103那款开发板 1、预告下国庆前的课程安排 2、AT 、HAL库智能家居,Freeros入门大概各讲解多少课时?

At指令很快,纯操作而已,没有问题的话10分钟就过了。

HAL库智能家居,主要是锻炼大家编程的习惯,怎么抽象出一个结构体,怎么让程序更容易移植、扩展。 可能大家会反馈的问题比较多,所以这个我暂且认为是4次课

Freeros入门大概各讲解多少课时? 写的参考书有11、12章,估计要讲7、8次课

老师,环形缓冲区可以用来协议解析吗?

当然可以,环形缓冲区只是用来接收数据而已,防止数据丢失,你当然可以用来解析协议了。

能讲讲你IIC和串口调试过程中常遇到的问题吗?这些问题的调试思路是什么?遇到问题了怎么划分是硬件问题还是软件问题??

I2C最大问题就是总线被占用, 就是scl老是为低电平。

解决这个问题的方法就是:我先用gpio来模拟,我就看看谁把这个引脚拉低了。

对于串口一般来说不会有什么问题,主要就是处理不过来导致数据丢失。

请教老师一个问题,如果进入串口中断后,进入中断服务函数的话,然后在中断服务函数中加入接收数据处理函数的话,会不会影响其他的函数,或者跑飞。

中断程序里面要尽可能快地退出,所以我们一般来说就在串口中断程序里面,把数据放入环形缓冲区。

ESP8266本来是一个MCU,用AT固件方便开发。那这样我能自己写一个类似AT固件一样的程序,然后处理指令吗,一般数据是怎么处理的呢,因为串口是一个个位这样收发数据的?

一条指令它以回车换行结束,所以你接收到一个一个字符之后,判断一下是回车换行的话就表明接收到了完整的指令。

C语言malloc创建的只能在堆么?C++中new出来的对象能通过重载new的技巧使对象创建在静态区或者栈区,C语言有什么技巧可以这样做么? 如果有的话,可以在周日直播讲讲技巧?

在上一次课里面我们讲了,你可以去定义一个很大的数组, 然后去管理这个数组,你看这个堆不就在数据段里了吗。

老师,printf重定向那个是什么原理?

别被“重定向”给唬住了,就是:printf里调用到fputc函数。

这个函数你写串口的话就是打印到串口。

这个函数你写屏幕的话,就是打印到屏幕。

这个fputc哪里指定的?C库吗?换一个平台之后还一样是fputc吗??

自己写的:

老师,我想问下变量和函数命名的规范,驼峰式和下划线式哪个好?是不是针对不同的场景会采用不同的方式??

看个人喜欢,驼峰式 好看一点。

fputc 是不是类似于HAL库里的回调,自己写同名的就会用自己写的?

应该是weak属性,你提供自己的代码的话,就用你自己的。

老师,如果智能家居显示不使用OLED,而是电容触摸屏使用LVGL来管理,实时性更强了,那工程是怎么管理,项目是怎么实现的 我能裸机移植LVGL使用,但是我不知道怎么结合FreeRTOS,一堆东西脑子乱成一团了

我同事对LVGL了解比较深,我还没有去看LVGL。 我大概的看了一下,lvgl里面,他已经实现了"事件"驱动

能不能这样:lvgl本身作为一个任务,其他不涉及界面操作的,也拆分为任务。

另外,教学视频里面,环形缓冲区extern 了结构体test_buffer,这个变量很多地方都被调用了哦,如果我要改点东西,直接牵一发而动全身了,有什么好办法吗?

不应该这么做的,不建议直接去访问全局变量,而是放到一个函数里面去访问。

如果裸机层面的底层驱动没有弄的很清楚的话。比如can,网口等。直接学操作系统会不会有点更不上产品级的项目?

在一个项目里面,底层驱动的占比不会很大的,所以你不用担心。

老师,视频hal库的i2c和oled驱动程序看的很吃力怎么办,看是能看懂但是建立不起体系?

这种你要去多练习,故意找一个不一样的模块来写程序,多写几个就明白。

老师,对于ESP的wifi/bt二合一产品,是用AT开发比较多还是IDF?另外使用IDF开发是不是很难?

如果要在ESP上开发程序,用IDF。

老师,如何真正做到模块化,每个模块化功能移植下就能用,每次移植的时候会有很多的其他变量都要屏蔽掉,是不是要少用extern?

一般来说都不要暴露出变量,除非说这个变量很重要,是只读的 。就比如linux中的jiffies。

老师,有一个基本概念不懂,用ttl转usb模块接电脑的时候,为什么单片机的地要和ttl转usb模块接一起。

双方要有一个参考的电位,就是共地。

老师,如何真正做到模块化,每个模块化功能移植下就能用,每次移植的时候会有很多的其他变量都要屏蔽掉,是不是要少用extern?

这模块要尽可能独立,不要去引用别人的东西。

想请问一下,网页控制单片机怎们实现的,是HTTP转串口吗? 纯小白,想先去学习一下

单片机是一个web服务器,通过浏览器来访问单片机。

如何 提高 数据结构 算法 设计模式 操作系统原理 编译原理 软件架构 这些内功?

操作系统原理、编译原理 ,学的话是有帮助,但是停下来去学习他的话代价太大。

标签: 电位器2k2k电容传感器布置结构四线电阻触摸屏控制器usb01usb型温湿度传感器变送器

锐单商城拥有海量元器件数据手册IC替代型号,打造 电子元器件IC百科大全!

锐单商城 - 一站式电子元器件采购平台