在stm32系列单片机中,如果我们想要控制一个IO口输出或者输入,我们都需要对这个IO口进行配置,根据我们需要的功能,将其配置成适合的输出方式或者输入方式。
所以当我们想要控制IO的输出时我们先要确定stm32的输出方式:
内部结构
根据数模电的知识我们可以了解到,Vout具有输出高低电平的能力。
当上面的PMOS管导通,下面的NMOS管截止的时候,Vout输出高电平;
当上面的PMOS管截止,下面的NMOS管导通的时候,Vout输出低电平;
优缺点
优点:输出电压基本与电源电压没有压差;
IO口驱动能力强,输出电流最大可达20mA
电平变化快
缺点:
不支持线与(线与指的就是两个IO口连接在一起,输出电平是这两个IO口相与的结果,当这两个IO口都是推挽输出的时候,线与容易烧坏芯片)
内部结构
根据数模电的知识我们知道,Vout具有输出低电平的能力
当NMOS管导通的时候,Vout输出低电平;
当NMOS管关断的时候,Vout为高阻态;
所以我们知道开漏输出本身不具有输出高电平的功能,我们需要外部连接一个上拉电阻,这样其才有输出高电平的能力。
与普通推挽输出口一样,不过这时IO口不在是简单的输出高低电平那么简单,而是可以将其复用成输出PWM等功能。
与普通开漏输出口一样,不过这时IO口不在是简单的输出高低电平那么简单,而是可以将其复用成输出PWM等功能。
根据上面的解释,我们可以根据我们的实际情况选择合适的输出方式,一般IO口都没有上拉电阻,IO口也不需要线与,所以我们一般选择推挽输出。
确定了IO口的输出方式,我们就可以开始写代码了
首先确定我们的IO口,一般是查看原理图
这里我们知道我们需要控制PB5和PE5两个IO口的输出来控制LED。所以我们需要对PB5和PE5两个IO口进行程序配置。代码如下
这里的文件是led.c
void LED_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure; //IO口配置结构体
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB|RCC_APB2Periph_GPIOE, ENABLE); //使能PB,PE端口时钟
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5; //LED0-->PB.5 端口配置
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //IO口速度为50MHz
GPIO_Init(GPIOB, &GPIO_InitStructure); //根据设定参数初始化GPIOB.5
GPIO_SetBits(GPIOB,GPIO_Pin_5); //PB.5 输出高
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5; //LED1-->PE.5 端口配置, 推挽输出
GPIO_Init(GPIOE, &GPIO_InitStructure); //推挽输出 ,IO口速度为50MHz
GPIO_SetBits(GPIOE,GPIO_Pin_5); //PE.5 输出高
}
重点语句程序解释:
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB|RCC_APB2Periph_GPIOE, ENABLE); //使能PB,PE端口时钟
在APB2总线上开启PB,PE端口时钟,只有开启才会工作!!!
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;
需要配置的具体引脚,如果是PBx,这里就是GPIO_Pin_x。
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; 设置为推挽输出
配置好IO口后,我们需要在main函数中进行调用
这里的文件是main.c
#include "delay.h"
#include "sys.h"
#include "led.h"
#include "lcd_init.h"
#include "lcd.h"
#include "pic.h"
#include "pwm.h"
#include "key.h"
int main(void)
{
delay_init();
LED_Init();
//KEY_Init();
//TIM3_PWM_Init(59999,23);//设置频率为50Hz,公式为:溢出时间Tout(单位秒)=(arr+1)(psc+1)/Tclk 20MS = (59999+1)*(23+1)/72000000
//Tclk为通用定时器的时钟,如果APB1没有分频,则就为系统时钟,72MHZ
//PWM时钟频率=72000000/(59999+1)*(23+1) = 50HZ (20ms),设置自动装载值60000,预分频系数24
while(1)
{
// if(GPIO_ReadInputDataBit(KEYPORT,KEY1)==0)
// {
// delay_ms(20);//20ms消除抖动
// if(GPIO_ReadInputDataBit(KEYPORT,KEY1)==0)
// {
// LED0=!LED0;
// }
// while(GPIO_ReadInputDataBit(KEYPORT,KEY1)==0); //等待按键松开
// }
LED1=0;
delay_ms(500);
LED0=!LED0;
delay_ms(500);
}
}
LED0与LED1在led.h中配置
#ifndef __LED_H
#define __LED_H
#include "sys.h"
#define LED0 PBout(5)// PB5
#define LED1 PEout(5)// PE5
void LED_Init(void);
#endif
这里我们的期望是LED1一直亮,LED0闪烁
效果如下
视频地址
VID20220921171305_哔哩哔哩_bilibili