STOpen IO子系统(二)-IO的模式设置和数据输入输出路径详细剖析

在上一章,我们把IO系统的时钟源进行了一个梳理和详细分析,在正确的配置了相关的系统时钟源和IO模块的时钟源后,接下来还要做一件重要的事情,就是配置IO的输出模式。
既然是IO,就有输出也有输入,所以需要配置来选择正确的方向。
在这里插入图片描述
上图是STM32F103的IO基本结构图。
我们把这张图分两部分来解读:

第一部分: 输入input,如图中红色部分所示

在这里插入图片描述
当I/O端口配置为输入时,如上图简化后的图,注意红色圆圈的几个地方:
1.输出缓冲器被禁止,如图A点,被断开,所以你的输出数据无法反应到IO端口上,此路不通。
2. 施密特触发输入被激活,如图B点
这两步动作是把端口模式配置为输入后自动进行的,无需额外配置
3. 根据输入配置(上拉,下拉或浮动)的不同,弱上拉和下拉电阻被连接
4. 出现在I/O脚上的数据在每个APB2时钟被采样到输入数据寄存器,这就是IO能捕捉到数据的最大的频率,如果你的输入数的频率高于这个频率,将不会正确的捕捉到。
5. 对输入数据寄存器的读访问可得到I/O状态。

输入的三条路径如下

第一条路径是模拟信号输入路径,它是直达系统的模拟输入器件端口的,比如ADC,比较器等模拟电路,所以它要绕过输入部分的数字电路(施密特触发器)。如下图ADC的输入路径所示,它从IO口进来后会进入一个MUX(多路复用器,算是一个模拟开关),然后到达ADC转换单元完成模拟到数字的转换后,才送到后端进行进一步的处理。
在这里插入图片描述
特别留意一下模拟输入的时候示意图如下:
在这里插入图片描述
如上图所示,当I/O端口被配置为模拟输入时:

  1. 输出缓冲器被禁止;
  2. 禁止施密特触发输入,实现了每个模拟I/O引脚上的零消耗。施密特触发输出值被强置
    为’0’;所以,此时输入阻抗很高,容易吸收干扰信号。
  3. 弱上拉和下拉电阻被禁止;
  4. 读取输入数据寄存器时数值为’0’

第二条路径是特殊功能输入,但是它输入的是数字信号,典型的应用比如UART的接收,PWM的捕获等数字信号。这个数字信号还会送到后面的数字电路进行进一步的处理,比如UART。下图中红色代表UART的接收数据RX,它会经过一个移位寄存器,按照我们设定的参数(数据位数,奇偶校验位,停止位数等)把数据组合成一个字节后,才送入RDR寄存器。
在这里插入图片描述
对于特殊功能的路径,简化后如下:
在这里插入图片描述
当I/O端口被配置为复用功能时:

  1. 在开漏或推挽式配置中,输出缓冲器被打开
  2. 内置外设的信号驱动输出缓冲器(复用功能输出),路径是图中A点,此时IO输出数据的路径被断开,所以你无法写数据到IO引脚
  3. 施密特触发输入被激活。
  4. 弱上拉和下拉电阻被禁止,如图C,上下拉电阻被disable掉了。
    5.在每个APB2时钟周期,出现在I/O脚上的数据被采样到输入数据寄存器,此采样频率决定了外设的工作速度
  5. 开漏模式时,读输入数据寄存器时可得到I/O口状态
  6. 在推挽模式时,读输出数据寄存器时可得到最后一次写的值

第三条路径是最简单的一条路径。它把IO引脚的电平经过可选的施密特触发器整型后(所以你的输入电平要达到一定的电压才能被认识为高电平),就直接把结果放入到输入寄存器了,你读到的IO电平就是这个寄存器的数值。

第二部分 输出output,如第一张图的蓝色部分所示

在这里插入图片描述
当I/O端口被配置为输出时,IO的结构如上图所示:
1.输出缓冲器被激活
─ 开漏模式:输出寄存器上的’0’激活N-MOS,而输出寄存器上的’1’将端口置于高阻状态(PMOS从不被激活,相当于已经被从系统断开)。
─ 推挽模式:输出寄存器上的’0’激活N-MOS,而输出寄存器上的’1’将激活P-MOS。
2. 施密特触发输入被激活,如图C点
3. 弱上拉和下拉电阻被禁止
4.出现在I/O脚上的数据在每个APB2时钟被采样到输入数据寄存器,这样才可以读到输出的数据
5.在开漏模式时,对输入数据寄存器的读访问可得到I/O状态
6. 在推挽式模式时,对输出数据寄存器的读访问得到最后一次写的值。

对应的输出也会有三条路径

从图上可以看出来,三路输出的路径最后都要经过一个输出控制单元的控制,所以输出路径的特殊之处在于没有模拟信号输出。
第一条路径是特殊功能输出,比如UART的TX,DAC的输出等。
第二条路径,就是直接写端口的寄存器来输出数据,如下图所示,STM32F103的输出数据一般都是16bit(32bit的MCU最高是可以到32bit的)。

GPIOA->ODR = 0x0012;	 //将0x0012送到A端口,输出完毕后,端口的bit1,bit5变1

在这里插入图片描述
第三条路径就是arm的一个特殊操作,bit操作。这个操作的目的就是加速单个IO的数据输出速度。
IO的数据输入输出寄存器是32bit,我们读的时候就是一次性读入的,写也是一次性输出的,比如向GPIOA输出数据:

GPIOA->ODR = PortVal; //这样输出是一次性输出16bit,同时改变16位的数据。
如果我们只需要输出bit0的数据,就需要这样来操作才可以:
PortVal  = GPIOx->ODR;//先读入整个端口的输出寄存器值。
PortVal &= 0xFFFFFFFE//mask掉bit0
If(要输出bit0==1)
	PortVal |= 0x00000001;
GPIOA->ODR = PortVal; //输出数据

以上操作相当的繁琐,效率低下,如果用ARM的位操作来做,非常简单:

GPIOA->BSRR = GPIO_Pin1;// GPIO_Pin1 == 1

只需要向这个特殊的寄存器的对应位写1就一步完成了操作,效率提高若干倍。
要注意的是复位对应的位也是写1而不是0,只是所用的寄存器不一样,

GPIOA->BRR = GPIO_Pin1;// GPIO_Pin1 ==0

在这里插入图片描述
在这里插入图片描述
最后通过两个特殊的寄存器,来选择我们需要的输出和输入路径:
在这里插入图片描述
在这里插入图片描述
根据你的输入输出功能,选择正确的输出路径后,基本通道就打通了。
别高兴太早了,还要一步需要我们去完成,看到图一中的ABCD几个地方的设置了吗?
欲知后事如何,且听下回分解!
原创文章,欢迎转载,请注明来源,未经书面允许,请勿用于商业用途。
在这里插入图片描述

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值