🚀write in front🚀
🔎大家好,我是黄桃罐头,希望你看完之后,能对你有所帮助,不足请指正!共同学习交流
🎁欢迎各位→点赞👍 + 收藏⭐️ + 留言📝
💬本系列哔哩哔哩江科大STM32的视频为主以及自己的总结梳理📚
🚀Projeet source code🚀
💾工程代码放在了本人的Gitee仓库:iPickCan (iPickCan) - Gitee.com
引用:
STM32入门教程-2023版 细致讲解 中文字幕_哔哩哔哩_bilibili
Keil5 MDK版 下载与安装教程(STM32单片机编程软件)_mdk528-CSDN博客
STM32之Keil5 MDK的安装与下载_keil5下载程序到单片机stm32-CSDN博客
0. 江协科技/江科大-STM32入门教程-各章节详细笔记-查阅传送门-STM32标准库开发_江协科技stm32笔记-CSDN博客
【STM32】江科大STM32学习笔记汇总(已完结)_stm32江科大笔记-CSDN博客
江科大STM32学习笔记(上)_stm32博客-CSDN博客
STM32学习笔记一(基于标准库学习)_电平输出推免-CSDN博客
术语:
|--------------------------------------|---------------------------------------------|
| 英文缩写 | 描述 |
| GPIO:General Purpose Input Onuput | 通用输入输出 |
| AFIO:Alternate Function Input Output | 复用输入输出 |
| AO:Analog Output | 模拟输出 |
| DO:Digital Output | 数字输出 |
| 内部时钟源 CK_INT:Clock Internal | 内部时钟源 |
| 外部时钟源 ETR:External Trigger | 时钟源 External 触发 |
| 外部时钟源 ETR:External Trigger mode 1 | 外部时钟源 External 触发 时钟模式1 |
| 外部时钟源 ETR:External Trigger mode 2 | 外部时钟源 External 触发 时钟模式2 |
| 外部时钟源 ITRx:Internal Trigger inputs | 外部时钟源,ITRx (Internal trigger inputs)内部触发输入 |
| 外部时钟源 TIx:exTernal Input pin | 外部时钟源 TIx (external input pin)外部输入引脚 |
| CCR:Capture/Comapre Register | 捕获/比较寄存器 |
| OC:Output Compare | 输出比较 |
| IC:Input Capture | 输入捕获 |
| TI1FP1:TI1 Filter Polarity 1 | Extern Input 1 Filter Polarity 1,外部输入1滤波极性1 |
| TI1FP2:TI1 Filter Polarity 2 | Extern Input 1 Filter Polarity 2,外部输入1滤波极性2 |
| DMA:Direct Memory Access | 直接存储器存取 |
正文:
0. 概述
从 2024/06/12 定下计划开始学习下江协科技STM32课程,接下来将会按照哔站上江协科技STM32的教学视频来学习入门STM32 开发,本文是视频教程 P2 STM32简介一讲的笔记。
1.🚚I2C硬件
软件实现和硬件实现
- 💎串口通信为异步时序,用软件实现很麻烦,基本上用硬件实现
- 💎而I2C协议通信为同步时序,软件实现简单且灵活,硬件实现比较麻烦,故软件比较常用
- 💎但I2C硬件实现功能比较大,执行效率高,节省软件资源,可以实现完整的多主机通信模型,时序波形归整,通信速率快
- 💎故I2C软件实现用于简单环境,若性能要求高,则硬件实现
1.(软件只需要写入控制寄存器CR和数据寄存器DR ,就可以实现协议,为了实现实时监控时序的状态,软件要读取状态寄存器SR)
2.支持多主机模型(固定多主机和可变多主机(stm32,谁要做主机,主机就得跳出来))
3.本实验依旧是7位、一个主机(一主多从)
4.STM32F103C8T6 硬件 I2C 资源: I2C1 、 I2C2(两个独立I2C,硬件只有俩路I2C总线,而软件I2C只要代码存的下,想开几路就开几路)
I2C的功能图
(1)数据控制部分
- 1 数据收发的核心部分:数据寄存器和数据移位寄存器
- 2 发送数据时,将数据放在数据寄存器,当没有移位时候,数据从数据寄存器转运到移位寄存器,同时,下一个数据送到数据寄存器,然后移位寄存器将数据给SDA,数据寄存器中的数据给移位寄存器,如此往复
- 3 当数据寄存器转到移位寄存器时,就会置状态寄存器的TXE位为1,表示发送寄存器为空
接收数据
- 接收数据 时,从SDA转到移位寄存器,再转到数据寄存器,同时置标志位RXNE,表示接受寄存器非空,这时候可以把数据从数据寄存器读出来
- 比较器和地址寄存器时从机模式使用(即再stm32不进行通信的时候,这个stm32支持同时响应两个从机地址
SCL部分
- 时钟控制:控制SCL线
- 时钟控制寄存器(CCR):写对应的位,电路就会执行对应的功能
- 控制逻辑电路:写入控制寄存器(CR1/CR2),就可以对整个电路进行控制
- 读取状态寄存器,可以得知电路的工作状态
- 中断:当内部有一些标志位置1后,可能事件比较紧急,就可以申请中断
- 如果开启中断,当事件发生后,程序可以跳转到中断函数处理事件
I2C基本结构
- 发送数据(从数据控制器到SDA):因为I2C是高位先行,所以移位寄存器是向左移位,在发送和的时候,最高位先移出去,然后是次高位,一次SCL时钟移位一次,移动8次,就把一个字节由高位到低位,一次放到SDA线上
- 接收数据:数据从SDA经GPIO口,从右边一次移进来,最终移动8次,一个字节就接收完成
- 使用硬件I2C:两个GPIO口,都要配置成复用开漏输出模式
- 复用就是GPIO的状态由片上外设来控制
- 开漏输出:时I2C协议要求的端口配置(GPIO口依旧可以输入)
主机发送
7位主发送的过程
TxE=1表示数据寄存器空 ,BTF字节发送结束标志位
SB=1,表示起始条件已经发送
- 💎(1)初始化之后:总线默认空闲状态,stm32默认是从模式
- 💎(2)stm32需要写入控制寄存器产生起始条件 :
控制寄存器CR1中,有个START位,写1,可以产生起始条件,起始条件发生后,这一位由硬件清除,不需要手动侵清除
之后stm32从从模式转换成主模式- 💎(3)检查标志位
EV5事件:SB(start bit)=1,表示起始条件已经发送- 💎(4)发送从机地址:需要写到数据寄存器DR中,写入后,硬件自动把这个字节转到移位寄存器中,再把这个字节发送到IIC总线上
之后硬件会自动接收应答并判断,若没有应答,硬件会置应答失败的标志位,标志位可以申请中断来提醒我们- 💎(5)寻址完成之后,会发生EV6事件,ADDR=1,代表在主模式下发送结束
- 💎(6)EV8_1事件:TxE=1,移位寄存器和数据寄存器为空,写入数据寄存器DR进行数据发送,一旦写入DR,因为
移位寄存器也是空的,所以DR会立刻转到移位寄存器进行发送- 💎(7)EV8事件:TxE=1,移位寄存器非空,数据寄存器空,这移位寄存器正在发数据的状态,故数据1的时序产生
一旦检测到EV8事件,就可以写入下一个数据- 💎(8)EV8_2事件:写完后,没有数据可以写了
主机接收
这里是当前地址读的模式
- 💎(1)首先写入start位,产生起始条件,等EV5事件,EV5事件代表起始条件已经发送,
- 💎(2)之后是寻址,接收应答,结束后产生EV6事件,代表寻址已经完成
- 💎(3)数据1这块,代表数据正在通过移位寄存器进行输入,EV6-1事件,从上图可以看出,数据正在移位,还没收到,所以事件没有标志位,当这个时序单元完成时,硬件会自动根据我们的配置,把应答位发送出去(ACK应答使能,写1,在接收到一个字节后就返回一个应答,写0不给应答),当时序单元完成后,表示移位寄存器已经成功移入一个字节的数据1,这时,移入的一个字节就整体转移到数据寄存器中,同时置RxNE标志位,表示数据寄存器非空,也就是收到一个字节的数据,这个状态就是EV7事件、
- 💎(4)当把数据读走后,EV7事件就没有了
- 💎(5)EV7_1:结束
- 💎(6)由于设置了ACK=0,所以会给出非应答,最后由于设置STOP位,所以产生终止条件
软件和硬件之间的比较
(1)硬件IIC的波形比较规整,软件IIC由于添加了延时,时钟周期、占空比可能不规整
SCL低电平写,高电平读(默认下降沿写,上升沿读,硬件IIC数据写入,都是紧贴着下降沿,SCL下降沿,SDA立马切换数据)
(2)在硬件中,应答结束后,从机立刻释放SDA,同时主机立刻拉低SDA,故出现尖锋
软件I2C,SDA接在B11,SCL接在B10 ,软件IIC的两个引脚可以任意更改的,因为都是开漏输出,硬件接在哪个引脚上,程序中就对应操作哪个引脚
但是硬件I2C,通信引脚是不可以任意指定的,查表,由于PB6、PB7被OLED应用,所以用PB10、PB11,软件IIC的代码在此处也适用
程序部分
软件IIC改为硬件IIC
第一步:开启I2C外设,对I2C2外设进行初始化,以替换MyI2C_Init
第二步:控制外设电路,实现指定地址写的时序,以替换WriteReg
第三步:控制外设电路,实现指定地址读的时序,以替换ReadReg