目录
GPIO基础知识
编辑IO八种工作模式
固件库实现LED点灯
蜂鸣器
按键基础知识
编辑继电器
震动传感器
433M无线模块
GPIO基础知识
GPIO(General-Purpose input/output,通用输入/输出接口)
用于感知外部信号(输入模式)和控制外部设备(输出模式)
简单模块:LED,按键,蜂鸣器,温度传感器,使用一个GPIO就可以完成数据的传输/ 控制
复杂一点的模块OLED,FLASH,六轴传感器需要多个引脚组成“协议”传输数据, USART,IIC,SPI等协议
MCU单片机大都采用引脚复用模式也就是一个GPIO,可以直接控制它输出高低电平,也可以设置为某个协议的引脚之一。此外,一些MCU的引脚,还能设置为ADC模式读取模拟信号,或者设置为DAC模式输出模拟信号
系统架构
IO八种工作模式
引脚电平:0V~3.3V(数据1就是高电平就是3.3V,数据0就是低电平就是0V),部分引脚可忍受5V
STM32 IO工作模式
输出模式有四种:推挽输出,开漏输出,复用开漏,复用推挽
输入模式有四种:上拉输入,下拉输入,浮空输入,模拟输入
输出模式:
1.推挽输出(Push-Pull,pp)
让输出控制变成了VDD/VSS输出,使得输出电流增大 提高了输出引脚的驱动能力,提高了电路的负载能力和开关的动作速度
数据寄存器为1时,下管断开,上管导通,输出直接接到VDD,输出高电平
数据寄存器为0时,上管断开,下管导通,输出直接接到VSS,输出低电平
2.开漏输出(Open-Drain,OD)
推挽输出模式可以直接输出高电平,开漏输出需要外接上拉电阻才能输出高电平(5v)
数据寄存器为1时,下管断开,上管断开,高阻模式
数据寄存器为0时,上管断开,下管导通,输出直接接到VSS,输出低电平
这种模式下只有低电平有驱动能力,高电平是没有驱动能力的
可以作为通信协议的驱动方式,在多机通信的情况下,这个模式可以避免各个设备的相互干扰
开漏输出的特性
利用外部电路驱动能力
实现电平转换
方便实现“逻辑与” 功能
3.复用推挽/开漏输出(Alternate Funtion,AF)
GPIO除了作为通用输入输出引脚使用以外,还可以作为片上外设(USART,IIC,SPI) 专用引脚(和其他输出输入的区别),既可以利用片上外设输入也可以用来输出,即一个引脚可以有多种用途,但是同一时刻一个引脚只能使用复用功能中 的一个
当引脚设置为复用功能的时候,可选择推挽复用模式或者复用开漏模式,在设置为复用开 漏模式时,需要外接上拉电阻。
输入模式:
1.上拉输入(Input Pull-up)
如果接入上拉电阻,当引脚悬空时,还有上拉电阻来保证引脚的高电平
VDD经过开关、上拉电阻,连接外部I/O引脚。当开关闭合时,外部I/O输入信号时,默认 输入高电平。
2.下拉输入(Input Pull-down)
VSS经过开关,下拉电阻,连接外部I/O引脚,当开关闭合时,外部I/O无输入信号 时,默认输入低电平
3.浮空输入(Floating Input)
两个上下拉电阻开关均断开,没有上拉也没有下拉,I/O引脚直接连接TTL肖特基触发器(对输入电压进行整形,如果输入电压大于某一阈值,输出就会瞬间升为高电平,如果输入电压小于某一阈值,输出就会瞬间降为低电平 )
此时,I/O引脚浮空,读取的电平是不确定的,外部信号是什么电平,MCU引脚就输 入什么电平
MCU复位上电后,默认为浮空输入模式
4.模拟输入(Analoge mode)
两个上下拉电阻开关均断开,同事TTL肖特基触发器也断开,引脚信号直接连接模拟输入,实现对外部信号的采集。
在输入模式下输出是无效的,在输出模式下输入都是有效的,因为一个端口只能有一个输出,但可以有多个输入
当使用外设配置GPIO时可以参考手册给配置
固件库实现LED点灯
1.LED灯
LED灯,是一种能够将电能转化为可见光的半导体器件
原理:当给P极施加正向电压时,空穴和自由电子在P-N结复合,辐射出光子而发 光。
2.控制LED灯
LED灯的正极接到了3.3V,LED灯的负极接到了PA1,也就是GPIOA1引脚 只需要控制PA1为相对应的低电平,即可点亮对饮的LED灯,输出高电平则熄灭对应的LED 灯。
(在这种电路连接中,当 LED 灯的正极接到 3.3V 电源时,它为 LED 提供了正向的电压偏置,使得 LED 具备了导通发光的条件之一。而 LED 的负极连接到 PA1(GPIOA1 引脚),GPIOA1 引脚可以通过软件编程来控制其输出电平。
当 PA1 引脚输出低电平时,此时 LED 灯的正负极之间形成了足够的电压差(3.3V - 低电平电压,通常低电平电压接近 0V),有电流从 3.3V 电源经过 LED 流向 PA1 引脚,从而使 LED 灯导通发光。
当 PA1 引脚输出高电平时,假设高电平为 3.3V,那么 LED 灯正负极之间的电压差为 0(或非常小),无法满足 LED 导通所需的电压条件,LED 灯中没有电流通过,所以 LED 灯熄灭。
这种通过控制 GPIO 引脚电平来控制 LED 灯亮灭的方式是一种常见的数字逻辑控制方法,方便且易于通过软件进行灵活的控制和管理,广泛应用于各种电子设备和电路设计中。)
软件设计流程
初始化系统
初始化GPIO外设时钟
初始化LED引脚(对于单片机来说是输出)
(首先得定义这个变量才能用这个变量,用函数把它们装起来)
输出电平
首先在User中建立LED文件,LED:中新建led.h和led.c文件
从project中打开keil5,双击User将led.c添加进去,点击魔术棒led.h文件加进去,双击led.c文件输入#include "led.h",因为我们要用库函数要包含库函数头文件#include "stm32f10x.h"
1.初始化LED灯的函数(先将函数写进led.h文件中)命名函数时用驼峰命名发
1.1初始化LED引脚GPIOA1,要用初始化的GPIO结构体,通过配置结构体我们可以初始化引脚
先在FWLIB中找到giop.c文件再找到giop.h库在里面找到GIOP结构体GPIO_InitTypeDef,在led.c中重新定义GIOP结构体,在重新配置引脚,因为LED灯连接到板子上PA1所以引脚配置的是pin_1,要想LED灯点亮需要输出低电平,所以配置的模式是推挽输出
再从giop.c文件再找到giop.h中找到GPIO_Init(GPIO_TypeDef* GPIOx, GPIO_InitTypeDef* GPIO_InitStruct);函数,这个函数的作用是初始化GIOP的结构体,把上面函数真正初始化到结构体里面去,第一个参数是GPIOA,第二个参数是&led_initstruct(右键参数,上面是跳转定义.c,下面是跳转声明.h)
1.2初始化时钟APB2下的GPIOA
FWLIB中找到rcc.c文件再找到rcc.h找到RCC_APB2PeriphClockCmd(uint32_t RCC_APB2Periph, FunctionalState NewState);函数,第一个参数是APB2下的哪一个外设,第二个参数是枚举类型两种状态,失能和使能
最后总代码要做main文件中运行,在main文件中写入#include "led.h"就包含了上面的所有函数
在main函数中首先输入初始化LED灯的函数,然后让LED灯输出低电平
while(1)
{
GPIO_ResetBits(GPIOA,GPIO_Pin_1);//这个函数是输出低电平
//右键查看函数声明,第一个参数是GPIOA,第二个参数引脚1
GPIO_SetBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);//这个函数是输出高电平
}
如何控制LED灯的闪烁? (亮一秒关一秒:延时)
//软件延时主要是让CPU“空转”,通过计算不同指令周期的时间,参考CPU主频大小,大概算出延时时间,这种方法从表面看起来就不精确,但它是比较好实现; void delay(uint16_t time)//延时1ms {uint16_t i = 0;while(time --){i - 12000;while(i --);}}
蜂鸣器
1.蜂鸣器的种类
蜂鸣器是一种常用的电子发声元器件,采用直流电压供电。广泛应用于计算机,打印 机,报警器,电子玩具,汽车电子设备灯等产品中常见的蜂鸣器可分为有源蜂鸣器和 无源蜂鸣器。
2.蜂鸣器的控制方式
有源蜂鸣器:内部有震荡源,只要通电即可自动发出固定频率的声音。(频率固定无 法控制音色)
无源蜂鸣器:内部无震荡源,需要外部脉冲信号驱动发声,声音频率可变。(可改变 频率来改变音色)
3.区分蜂鸣器
从外观上来看两种蜂鸣器形状相似,有源蜂鸣器底部有黑胶密封。
无源蜂鸣器底部可以看到电路板,两种蜂鸣器都标注有正负极。
GPIO控制蜂鸣器
VCC通过杜邦线接到板子3.3V,GND接到板子GND,I/O口接到普通单片机I/O口即可,当I/O口往蜂鸣器输出低电平时,蜂鸣器就会叫,如果输出高电平就会关掉
软件设计流程(和LED灯类似)
初始化系统
初始化GPIO外设时钟GPIOA
初始化蜂鸣器的引脚A3
输出电平控制蜂鸣器
初始化和LED灯一样
输出电平控制蜂鸣器
按键基础知识
GPIO的特点: 具有内部上拉或下拉的功能 可以使用外部下拉或上拉
按键连接示意图:
没按下开关的时候PC13和PA0都是没有连接外部电平的(默认电平),当按键按下的时候会出入GND低电平,所有我们可以判断如果检测PA0是低电平说明按键按下则我们控制灯亮,如果PC13引脚检测到的电平是低电平,我们就可以判断这个按键按下,则就把灯关掉
按键控制LED灯
软件设计流程
初始化系统
初始化GPIO时钟
初始化按键和LED引脚
检测按键输入电平来控制LED灯
SW2控制灯开(PA0)
SW3控制灯关(PC13)
初始化系统
检测按键输入电平来控制LED灯
继电器
1.继电器的工作原理
继电器是一个电控开关,工作原理基于电磁感应,继电器包括一个电磁线圈和一组触点。常用于控制高电流或高电压的电路,例如自动控制原理,电力系统和自动化设备中,由于可靠性和电气隔离的特性可以实现小电流实现大电流,继电器在各种应用中都有广泛的用途。
2.继电器的引脚说明
1.VCC(+):供电正极,连接此引脚到电源,以提供继电器所需的电流
2.GND(-): 地,连接此引脚到电源的负极或者地。
3.IN:控制输入信号,通常用于连接控制信号,当该信号变化,继电器切换状态。
(IN如果接了低电平,这个继电器是连接的状态(闭合)IN如果接了高电平,就是断开的状态)
IN不管是高电平还是低电平,控制的是NO端和NC端
4.COM(common):公共端,通常是中间的触点,与常开或常闭触点相连
5.NO(Normally Open):常开接口,继电器吸合前悬空,吸合后于COM连接
6.NC(Normally Closed):常闭接口,继电器吸合前与COM连接,吸合后悬空
(测试手中继电器是5v还是3.3v:首先用杜邦线连接VCC和GND另一端接到板子上的5V和GND此时红灯亮了,如果IN口接到低电平(3.3v高电平)绿灯会亮,说明继电器不是5V不是他的工作电压,再重新用杜邦线连接VCC和GND另一端接到板子上的3.3V和GND此时红灯亮了,如果IN口接到低电平绿灯会亮,再重新接到3.3v说明继电器是3.3V是他的工作电压,并且是低电平导通)
初始化系统
初始化继电器IN引脚对应的GPIO外设时钟
初始化继电器IN的引脚输出模式(IN获得低电平就打开,IN获得高电平就断开,所以IN连接单片机,单片机要输出引脚高或者低,所以是输出模式)
输出电平控制继电器开和关
输出电平控制继电器开和关
震动传感器
1.震动传感器工作原理
震动传感器黑色震动检测传感器,工作时电源LED灯常量(说明这个模块左右两边都有LED灯,
左边是电源指示灯,另外的信号灯只有在震动的瞬间才会亮),震动信号检测LED灯发生震动的
时候会
保持亮的过程。正常工作模块DO口输出高电平,震动瞬间DO口输出低电平,用于各种震动触发作
用,防盗报警,智能小车,电子积木灯等。
中间有个旋钮是控制震动传感器的灵敏度
2.震动传感器硬件引脚接线
1.VCC:接到板子电源的5V或者3.3V。
2.GND:地,连接到板子电源的负极或者GND.
3.DO: 数字信号输出口,可以与单片机相连检测环境是否发生震动。(如果这个震动传感器震动了,它就会把这个信号通过DO口发生给单片机,对于单片机来说它是输入的,所以再编程是要以输入IO的状态)
3震动传感器软件开发流程
初始化系统
初始化震动传感器DO相连的单片机引脚时钟
初始化震动传感器DO相连的单片机引脚输入配置
检测震动控制LED灯
#include "stm32f10x.h"
#include "shake.h"void Shake_Init()
{GPIO_InitTypeDef GPIOInitstruct;RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);GPIOInitstruct.GPIO_Pin = GPIO_Pin_0;GPIOInitstruct.GPIO_Mode = GPIO_Mode_IPD;
//上拉输入还是下拉输入都不影响,最终还是以输入电平为主
//配置上拉相当于 int a = 1,下拉相反GPIO_Init(GPIOA, &GPIOInitstruct);}
正常没有震动时输出高电平,有震动的时候输出低电平,如果DO口接受到低电平就控制板子上A1这个灯亮
#include "stm32f10x.h"
#include "main.h"
#include "led.h"
#include "bear.h"
#include "key.h"
#include "relay.h"
#include "shake.h"void delay(uint16_t time){uint16_t i = 0;while(time --){i = 12000;while(i--);}}int main()
{Shake_Init();Led_Init();while(1){if(GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_0) == 0)
//如果单片机引脚PA0接受到低电平(震动传感器震动),就会控制A1灯亮一秒灭一秒{ GPIO_ResetBits(GPIOA, GPIO_Pin_1);delay(1000);GPIO_SetBits(GPIOA, GPIO_Pin_1);delay(1000);}else
//如果没有接受到低电平,就会熄灭{GPIO_SetBits(GPIOA, GPIO_Pin_1);}}}
小项目:震动感应灯
继电器的作用是,如果开的情况下就会把COM和NO端连接在一起,就相当于LED灯直接和单片机的VCC相连接的,这时灯就会亮,如果是关的情况下COM和NO就不会连接在一起,LED灯就是灭的状态
如果震动器震动则控制继电器开 ,继电器开就表示COM和NO连接在一起,LED就会亮
#include "relay.h"
#include "stm32f10x.h"void Relay_Init()
{GPIO_InitTypeDef GPIOInitstruct;//初始化引脚的位置取决于IN引脚的接线,这时我们接到板子上PA0引脚
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);GPIOInitstruct.GPIO_Pin = GPIO_Pin_0;GPIOInitstruct.GPIO_Speed = GPIO_Speed_10MHz;GPIOInitstruct.GPIO_Mode = GPIO_Mode_Out_PP;GPIO_Init(GPIOA, &GPIOInitstruct);}
#include "stm32f10x.h"
#include "shake.h"void Shake_Init()
{GPIO_InitTypeDef GPIOInitstruct;RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);GPIOInitstruct.GPIO_Pin = GPIO_Pin_1;GPIOInitstruct.GPIO_Mode = GPIO_Mode_IPD;GPIO_Init(GPIOA, &GPIOInitstruct);}
#include "stm32f10x.h"
#include "main.h"
#include "led.h"
#include "bear.h"
#include "key.h"
#include "relay.h"
#include "shake.h"void delay(uint16_t time){uint16_t i = 0;while(time --){i = 12000;while(i--);}}int main()
{Relay_Init();Shake_Init();GPIO_SetBits(GPIOA, GPIO_Pin_0);
//这个函数的作用是让我们每次上电时继电器先关上while(1){if(GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_1) == 0)//如果单片机从震动器得到低电平{
//则继电器亮一下,说明IN口得到低电平使继电器工作,COM和NO闭合使单片机上的低电平输出小灯,使小灯亮GPIO_ResetBits(GPIOA, GPIO_Pin_0);delay(1000);GPIO_SetBits(GPIOA, GPIO_Pin_0);delay(1000);}else{GPIO_SetBits(GPIOA, GPIO_Pin_0);} }}
433M无线模块
1.433M无线模块工作原理
数据发射模块的工作频率为315M,采用声表谐振器SAW稳频,频率稳定度极高,当环境温度
在-25~+85度之间变化时,频飘仅为3ppm。
接收到信号,接收模块对应针脚输出高电平,有D0 D1 D2 D3,可能对遥控器的A/B/C/D。
2.引脚接线
1.供电正极,连接此引脚到电源,以提供433M无线模块所需的电流
2.GND(-):地,连接此引脚到电源的负极或者地。
3.D0-D4:连接控制输入信号通常用于连接控制信号,当按键变换控制外设信号
3.433M控制灯软件开发流程
初始化系
初始化433M D0-D4引脚对应的GPIO外设时钟
初始化433M D0-D4引脚配置
433M按键控制外设
小项目:433M无线遥控灯 (一个按键控制灯开,一个按键控制灯关)
正常按下A按键,D0会输出高电平发送给A0,B按键按下,D1会输出高电平发送给A2,我们要实现D0按下灯开,D1按下灯关,板子是输入模式
首先要初始化A0和A2两个引脚,同时我们要控制板子上的LED灯 还要初始化A1的引脚
#include "stm32f10x.h"
#include "shake.h"void Shake_Init()
{GPIO_InitTypeDef GPIOInitstruct;RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);GPIOInitstruct.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_2;
//这里同时初始化两个引脚GPIOInitstruct.GPIO_Mode = GPIO_Mode_IPD;
//板子是输入模式GPIO_Init(GPIOA, &GPIOInitstruct);}#include "led.h"
#include "stm32f10x.h"
void Led_Init()
{GPIO_InitTypeDef led_initstruct;led_initstruct.GPIO_Pin = GPIO_Pin_1;led_initstruct.GPIO_Speed = GPIO_Speed_2MHz;led_initstruct.GPIO_Mode = GPIO_Mode_Out_PP;GPIO_Init(GPIOA, &led_initstruct);RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
}
#include "stm32f10x.h"
#include "main.h"
#include "led.h"
#include "bear.h"
#include "key.h"
#include "relay.h"
#include "shake.h"int main()
{Shake_Init();Led_Init();while(1){if(GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_0) == 1)//如果A0引脚检测到了高电平,说明按键A按下,无线模块接受到信号并输出给板子,要控制灯亮{GPIO_ResetBits(GPIOA,GPIO_Pin_1);//就输出低电平让灯亮}else if(GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_2) == 1)//如果A2引脚检测到了高点哦,说明按键B按下,无线模块接受到信号并输出给板子,要控制灯灭{GPIO_SetBits(GPIOA,GPIO_Pin_1);//就输出高电平让灯灭}}}