目录
GPIO输入模式下的硬件和电路
按键原理
传感器原理
什么是上下拉电阻?
运算放大器当做比较器
按键的硬件电路
传感器的硬件电路
STM32用到的C语言知识
STM32中的C语言数据类型
C语言中的宏定义
typedef和define的区别是什么?
C语言的枚举
声明:本专栏是本人跟着B站江科大的视频的学习过程中记录下来的笔记,我之所以记录下来是为了方便自己日后复习。如果你也是跟着江科大的视频学习的,可以配套本专栏食用,如有问题可以QQ交流群:963138186
本节我们来学习GPIO的输入部分。
GPIO输入模式下的硬件和电路
我们先来看一下GPIO输入模式下的硬件和电路。
按键原理
首先是按键,这个按键是最常见的输入设备了。按键里面的电路逻辑和按键抖动现象之前的51单片机专栏有详细解释过,这里不再赘述。
下面这个图就是我们套件里的按键实物图,上面白色的是按钮,下面有两个引脚。
传感器原理
接着我们再来看一下传感器模块的介绍:
我们套件里提供了四种传感器模块,分别是光敏电阻传感器、热敏电阻传感器、对射式红外传感器,反射式红外传感器。
传感器模块:传感器元件(光敏电阻/热敏电阻/红外接收管等)的电阻会随外界模拟量的变化而变化,比如光线越强,光敏电阻的阻值就越小,温度越高,热敏电阻的阻值就越小。红外光线越强,红外接收管的阻值就越小,但是电阻的变化不容易直接被观察,所以我们通常将传感器元件与定值电阻进行串联分压,这样就可以得到模拟电压的输出了,对电路来说,检测电压就非常容易了。另外这个模块还可以通过电压比较器进行二值化即可得到数字电压输出。
它们的电路结构和工作原理都差不多,我们来具体看一下传感器模块的电路:
我们先看这部分:
N1就是传感器元件所代表的可变电阻,它的阻值可以根据环境的光线温度等模拟量进行变化。
上面的R1是和N1进行分压的定值电阻,R1和N1串联,一端接在VCC正极一端接在GND负极,这就构成了基本的分压电路。
左边这个C2是一个滤波电容,它是为了给中间的电压输出进行滤波的,用来滤除一些干扰,保证输出电压波形的平滑。
一般我们在电路里遇到这种一端接在电路中,另一端接地的电容都可以考虑一下这个是不是滤波电容的作用。如果是滤波电容的作用,这个电容就是用来保证电路稳定的,并不是电路的主要框架。这时候我们在分析电路的时候,就可以先把这个电容给抹掉。这样就可以使我们的电路分析更加简单。
我们把这个电容抹掉,整个电路的主要框架,就是定值电阻和传感器电阻的分压电路了。
在这里可以用分压定理来分析一下传感器电阻的阻值变化,对输出电压的影响。当然我们还可以用上下拉电阻的思维来分析。当这个N1阻值变小时,下拉作用就会增强,中间的AO端的电压就会拉低,极端情况下,N1阻值为零,AO输出被完全下拉输出0V。
当N1阻值变大下拉作用就会减弱,中间的引脚,由于R1的上拉作用,电压就会升高,极端情况下,N1阻值无穷大,相当于断路输出。电压被R1拉高至VCC。
这是用上下拉电阻来分析电路的。
什么是上下拉电阻?
上下拉电阻的工作逻辑
我们可以举个例子来说明上下拉电阻的工作逻辑:
AO这个输出端可以把它想象成一个放在屋里的水平杆子R1上拉电阻相当于栓在屋顶的弹簧,将杆子往上拉。N1下拉电阻相当于拴在地面的弹簧,将杆子往下拉,这个电阻的阻值越小,弹簧的拉力就越强。这个杆子的高度就相当于电路中的电压。如果只有上拉弹簧或者下拉弹簧,杆子肯定被拉到了屋顶,或者地面,在电路中就相当于中间点的电压为VCC或者GND。
当两个弹簧相互拉扯的时候,中间的输出端就会向拉力强的一端偏移。至于偏移多少,就取决于两个弹簧的弹力之差了。如果上下拉弹簧的弹力一致,则杆子会处于居中的位置,也就是电路输出VCC/2的电压。如果上面的阻值小拉力强,输出电压就会变高。反之,下面的阻值小输出电压就会变低。如果阻值为零,在电路中就是短接的状态,就相当于拉力无穷大了。
如果上下拉电阻的阻值都为0,就是两个无穷大的力在对抗,在电路中呈现的状态就是电源短路。所以这种情况应该避免。这个上拉电阻和下拉电阻在单片机电路中会经常出现。比如弱上拉,弱下拉强,上拉强下拉等,这里强和弱,就指电阻阻值的大小,也就是这个弹簧弹力的大小。上拉和下拉就指接到VCC还是GND,也就是这个杆子是拉向屋顶还是拉向地面。最终的输出电压就是在弹簧拉扯下最终杆子的高低。
大家以后再遇到上拉电阻和下拉电阻的分析就可以尝试一下用这个杆子和弹簧的模型来分析一下。
我们回到这个电路继续来看,在这两个电阻的分压下,AO就是我们想要的模拟电压输出了。
所以这里可以看到这个AO电压,就直接通过这个排针输出了。
这就是AO电压的由来仅需两个电阻,分压即可得到。
这个模块还支持有数字输出,这个数字输出就是对AO进行二值化的输出。这里二值化是通过这个芯片LM393来完成的。
这个LM393是一个电压比较器芯片,里面有两个独立的电压比较器电路,
然后剩下的是VCC和GND供电
我们VCC就接到电路的VCC,GND也接到了电路的GND。
这里有个电容是一个电源供电的滤波电容。
这个电压比较器其实就是一个运算放大器,有关运算放大器的知识。我在51单片机专栏已经详细讲过,大家不会的可以去看一下。
单片机学习笔记---AD/DA工作原理(含运算放大器的工作原理)_简述da和ad转换的原理-CSDN博客
运算放大器当做比较器
这里讲一下运算放大器当做比较器的情况:
当这个同向输入端的电压大于反向输入端的电压时,输出就会瞬间升为最大值,也就是输出接VCC。
反之,当同向输入端的电压小于反向输入端的电压时,输出就会瞬间降为最小值,也就是输出接GND
这样就可以对一个模拟电压进行二极化了。
实际的应用中,这里同相输入端IN+接到了AO这里,就是模拟电压端,
IN-接了一个电位器
这个定位器的接法也是分压电阻的原理。拧动电位器IN-就会生成一个可调的阈值电压,
两个电压进行比较,最终输出结果就是DO数字电压输出。
DO最终就接到了引脚的输出端,
这就是数字电压的由来。
然后右边这里还有两个指示灯,电路左边的是电源指示灯,通电就亮。
右边的是DO输出指示灯,它可以指示DO的输出电平,低电平点亮高电平熄灭
右边DO这里还多了个R5上拉电阻,这个是为了保证默认输出为高电平的。
然后就是P1的排针,分别是VCC、GND、DO和AO。
对于光敏电阻传感器来说,
这个N1就是光敏电阻
对于热敏电阻传感器来说,
这个N1就是热敏电阻,
对于这个红外传感器来说,
这个N1就是一个红外接收管。
当然对应还会多一个点亮红外发射管的电路在这里。发射管发射红外光,接收管接收红外光,模拟电压就表示的是接收光的强度。
这个模块的这里
电位器是直接换成了两个电阻进行分压。这样数字输出就是固定阈值的二极化了。这个模块通常用来检测通断。所以阈值也不需要过多的调整。
最后一个模块也是一个红外发射管和接收管。
只不过它是向下发射红外光,然后检测反射光的,这个可以用来做寻迹小车。
按键的硬件电路
接下来我们就来看一下按键和传感器模块的硬件电路。
按键这里给了4种接法,上面两个是下接按键的方式,
下面两个是上接按键的方式
一般来说,我们的按键都是用上两种方式,也就是下接的方式。这个原因跟LED的接法类似,是电路设计的习惯和规范。
我们先来看一下第一个图,这种接法是按键的最常用的接法。
在这里随便选取一个GPIO口,比如PA0,然后通过K1接到地
当按键按下时,PA0被直接下拉到GND,此时读取PA0口的电压就是低电平。
当按键松手时,PA0被悬空,悬空会出现引脚的电压不确定,所以在这种接法下,必须要求PA0是上拉输入的模式,否则就会出现引脚电压不确定的错误现象。
如果PA0是上拉输入的模式,引脚再悬空PA0就是高电平。所以这种方式下,按下按键引脚为低电平,松手引脚为高电平。
接着再看一下第二个图,相比较第一个图在这里外部接了一个上拉电阻,
大家可以把它想象成一个弹簧,把这个端口往屋顶上拉,当按键松手时,引脚由于上拉作用自然保持为高电平。当按键按下时,引脚直接接到GND,也就是一股无穷大的力,把这个引脚往下拉,弹簧肯定对抗不了无穷大的力,所以引脚就为低电平。
这种电路连接的情况下引脚不会出现悬空状态,所以此时PA0引脚可以配置为浮空输入或者上拉输入。如果是上拉输入,就是内外两个上拉电阻共同作用。
这时高电平就会更强一些,对应高电平就更加稳定,当然这样的话,当引脚被强行拉到低时,损耗也就会大一些。
接着第三个图PA0通过按键接到3.3V,这样要求PA0必须要配置成下拉输入的模式。当按键按下时,引脚为高电平。
松手时,引脚回到默认值低电平。
这要求单片机的引脚可以配置为下拉输入的模式,一般单片机可能不一定有下拉输入的模式,所以最好还是用第一张图的接法。这种接法大家了解一下即可。
最后一种接法就是在刚才的这种接法下面再外接一个下达电阻,这个接法PA0需要配置为下拉输入模式或者浮空输入模式。
总结一下,就是上面这两种接法,按键按下时引脚是低电平,松手是高电平。
下面这两种接法按键按下时是高电平,松手是低电平。
左边两种接法必须要求引脚是上拉或者下拉输入的模式。
右边两种接法可以允许引脚是浮空输入的模式,因为已经外置了上拉电阻和下拉电阻。
一般我们都用上面两种接法,下面两种接法用的比较少,到这里按键的硬件电路就介绍完了。
传感器的硬件电路
再看一下右边的传感器模块的电路:
因为是使用模块的方案,所以电路还是非常简单的。VCC接3.3V,GND接GND用于供电。
DO数字输出,随便接一个端口,比如PA0,用于读取数字量。
AO模拟输出,我们之后学ADC模数转换器的时候再讲,现在不用接。
STM32用到的C语言知识
C语言的基础知识这里就不再赘述,今后我们在STM32的学习过程中将会结构体、枚举等相关知识,不懂的可以去一下我在“嵌入式全栈开发”专栏中写的C语言知识
嵌入式全栈开发学习笔记---C语言笔试复习大全索引-CSDN博客
接下来这里还是提一点要注意的C语言相关知识
STM32中的C语言数据类型
了解一下STM32中的C语言数据类型
注意:在51单片机中int是占16位,而在stm32中int是占32位,如果要用16位的数据要用short来表示。这是和51单片机的不同之处,不要混淆了。
然后下面还有long和unsigned long占用的也是32位,跟int是一样的。如果想用64位的,需要用到long long和unsigned long long,不过这个数据类型实在是太大了,我们用的比较少。
float和double都是带符号的数,没有无符号的float和double。
然后我们看一下右边这两列:
这两列写的是C语言stdint.h文件和ST对这些变量的重命名,因为左边这些名字比较长,而且这个int的位数根据系统的不同,还有可能不一样。还有个就是这些名字有时候会名不对题。比如这个char本意是字符型数据的意思,按名字来说,它就应该存放字符的,但是我们单片机通常用它来存放整数,而不是字符。
所以综上各种原因,C语言和ST就给这些变量换了个名字。C语言提供的有stdint这个头文件,使用了新的名字,比如int8_t就是char的新名字,表示的意思就是八位整形数据,右边加个_t表示这是用typedef重新命名的变量类型。我们通过名字就知道意思了。
我们以后在写程序的时候,就会按照他的推荐使用这些新的名字。
另外还有ST定义的名字,这是ST库函数以前用的名字。在新版库函数这里已经换成了这些
不过这个新版本库函数仍然支持旧的写法。
推荐大家使用新的数据类型定义。
C语言中的宏定义
接下来我们再来看一下C语言中的宏定义
在单片机开发程序中的第一个用途是:
我们经常用一个字符串代替一个数字,便于理解,防止出错。比如我们在程序中1代表上拉输入,2代表下拉输入,3代表浮空输入等等,这时直接用数字来表示,就非常麻烦了,我们就可以用宏定义将数据参数映射到一个字符串上。这样就比较好理解。
然后第二个用途是提取程序中经常出现的参数,便于快速修改。比如我们程序里面出现了10个GPIO_Pin_0,这个Pin_0是需要经常修改的,如果一个个修改就太不方便了,这时我们就可以用一个字符串来代替GPIO_Pin_0,然后需要修改的时候,只需要修改一下定义即可。
宏定义的时候是将后面的重命名成前面的,比如#define ABC 12345,即将12345重命名为ABC。
这些就是库函数中宏定义的用法,当然宏定义还有其他的很多用法以后遇到再说。
typedef和define一样可以重定义名字
typedef和define的区别是什么?
区别就是宏定义的新名字在左边,typedef的新名字在右边,然后是宏定义不需要分号,typedef后面必须加分号。
宏定义任何名字都可以换,而typedef只能专门给变量类型换名字。所以,宏定义的改名范围要更宽一些,只不过对于变量类型重命名而言,使用typedef更加安全。
注:重命名后旧名字在在程序中也还是可以用的。
C语言的枚举
接下来复习一下C语言的枚举
枚举用途:定义一个取值受限制的整型变量,用于限制变量取值范围;(关于枚举的定义我在我的嵌入式全栈开发专栏中写过,不懂的可以去看看):
嵌入式全栈开发学习笔记---C语言笔试复习大全23-CSDN博客
这里补充一下枚举的引用:
比如:
typedef enum{
MONDAY=1,
TUESDAY,
WEDSDAY,
}Week_t; //定义枚举并重命名
Week_t week; //定义枚举变量名
week=MONDAY; //引用枚举,将1赋值给week
这个赋值只能按枚举中的定义来。如果你写week=8,编译器就会报警告说枚举中混入了其他变量。如果你写week=1,编译器也会报警告,这种情况要做一下强制类型转换成枚举类型:比如week=(Week_t)1;
另外,这个枚举值也不是必须赋值给枚举变量的,我们可以随意定一个变量,把枚举值赋给它都行。
比如我这里写int a=MONDAY;
如果到现在还对C语言的一些语法和关键字还不熟悉的话,可以去看看我的’“嵌入式全栈开发”专栏中的C语言复习部分:嵌入式全栈开发学习笔记---C语言笔试复习大全索引-CSDN博客
在我们之后的stm32编程中也会不断的和他们打交道。
本节就到这里,我们下一小节继续来学习GPIO输入的代码部分。
QQ交流群:963138186
本篇就到这里,下篇继续!欢迎点击下方订阅本专栏↓↓↓