本周学习STM32单片机,由于之前学过51单片机,为了便于切入,先学习了寄存器点亮LED灯的方法,整体思路与51单片机相似。在基本掌握后,尝试自己构建库函数雏形,过程比较困难,后面开始借鉴野火官方库函数。
这里其实建议大家在学会构建库函数后,没必要每个库函数都自己构建,太消耗时间。当然,若果时间充裕的话,自己构建库函数可以使之后的工程的开发、学习都更加方便,毕竟自己写的更加熟悉。
一、GPIO简述、功能及输出过程
GPIO 即 general purpose intput output ,是通用输入输出端的简称,简单来说就是软件可控制 的引脚, STM32芯片的GPIO弓|脚与外部设备连接起来,从而实现与外部通讯、控制以及数据采集的功能。例如输出高低电平控制LED灯的亮灭状态。GPIO是包含在100引脚之内的,包含诸如PE2、PE3……等引脚。
专用器件接到专用的总线,比如I2C, SPI, SDIO, FSMC, DCMI这些总线的器件需要接到专用的I0,普通的元器件接到GPIO,比如蜂鸣器,LED,按键等元器件用普通的GPIO,如果还有剩下的I0,可根据项目需要引出或者不引出。
由于时间限制,本篇文章只讲述DPIO输出,接下来将以下面的功能框架图作为例图进行讲解。
如果电压高于VDD,电流会由I/O引脚流向VDD,如果高出太多,可能会导致芯片烧毁。因此I/O口不能直接接电机,需要通过一个驱动电路进行隔离。从图中我们可以看到推挽输出、开漏输出、关闭三个输出模式。
首先是推挽输出。当输出数据寄存器输出1时,经过1-2管时会反转为0,此时Ug=0<Us,vdd与OUT导通且,两端电压相等,为3.3v,即p管导通,n管截止,out输出3.3v。反之亦然,若输出数据寄存器输出0时,out输出0。
什么叫推挽输出?
1、可以输出高低电平,用于连接数字器件,高电平由VDD(3.3v)决定,低电平由VSS决定。
2、推挽结构指两个三极管受两路互补的信号控制,总是在一个导通的时候另外一个截止,优点开关效率效率高(电流大,驱动能力强。
3、输出高电平时,电流输出到负载,叫灌电流,可以理解成推,输出低电平时,负载电流流向芯片,叫拉电流,即挽。
什么叫开漏输出?
1、只能输出低电平,不能输出高电平。
2、如果要输出高电平,则需要外接上拉。
3、开漏输出具有“线与”功能,一个为低,全部为低,多用于I2C和SMBUS总线。
二、寄存器点亮LED灯
总线共有三个,APB1、APB2、AHB。
BSRR指bit set reset 寄存器,是32位寄存器,输入1为有效,0为无效,低16位为set,设置,高电平,高16位为reset,复位,低电平,即0。
各寄存器之间存在一个地址的偏移,偏移是以4为一个单位,首先找到总线的基地址,然后通过偏移找到外设基地址,再通过偏移找到需要的寄存器基地址,最初外设基地址是总线1,即APB1的基地址。
下面的图是基址的偏移的实例。
我们这里首先开启GPIOB 端口时钟,清空控制PB0的端口位之后,再配置PB0为通用推挽输出,使PB0输出为低电平。编程如下:
#include "stm32f10x.h"
int main(void)
{
// 开启GPIOB 端口时钟
RCC_APB2ENR |= (1<<3);
//清空控制PB0的端口位
GPIOB_CRL &= ~( 0x0F<< (4*0));
// 配置PB0为通用推挽输出,速度为10M
GPIOB_CRL |= (1<<4*0);
// PB0 输出 低电平
GPIOB_ODR &= ~(1<<0);
//GPIOB_ODR |= (1<<0);
while(1);
}
// 函数为空,目的是为了骗过编译器不报错
void SystemInit(void)
{
}
效果图:
三、固件库点亮LED灯
1.下面是自定义头文件的源文件.c
#include "bsp_led.h"
void LED_GPIO_Config(void)
{
/*定义一个GPIO_InitTypeDef类型的结构体*/
GPIO_InitTypeDef GPIO_InitStructure;
/*开启LED相关的GPIO外设时钟*/
RCC_APB2PeriphClockCmd( LED1_GPIO_CLK | LED2_GPIO_CLK | LED3_GPIO_CLK, ENABLE);
/*选择要控制的GPIO引脚*/
GPIO_InitStructure.GPIO_Pin = LED1_GPIO_PIN;
/*设置引脚模式为通用推挽输出*/
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
/*设置引脚速率为50MHz */
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
/*调用库函数,初始化GPIO*/
GPIO_Init(LED1_GPIO_PORT, &GPIO_InitStructure);
/*选择要控制的GPIO引脚*/
GPIO_InitStructure.GPIO_Pin = LED2_GPIO_PIN;
/*调用库函数,初始化GPIO*/
GPIO_Init(LED2_GPIO_PORT, &GPIO_InitStructure);
/*选择要控制的GPIO引脚*/
GPIO_InitStructure.GPIO_Pin = LED3_GPIO_PIN;
/*调用库函数,初始化GPIOF*/
GPIO_Init(LED3_GPIO_PORT, &GPIO_InitStructure);
/* 关闭所有led灯 */
GPIO_SetBits(LED1_GPIO_PORT, LED1_GPIO_PIN);
/* 关闭所有led灯 */
GPIO_SetBits(LED2_GPIO_PORT, LED2_GPIO_PIN);
/* 关闭所有led灯 */
GPIO_SetBits(LED3_GPIO_PORT, LED3_GPIO_PIN);
}
2.下面是主函数源文件.c
#include "stm32f10x.h"
#include "bsp_led.h"
#define SOFT_DELAY Delay(0x0FFFFF);
void Delay(__IO u32 nCount);
int main(void)
{
/* LED 端口初始化 */
LED_GPIO_Config();
while (1)
{
LED1_ON; // 亮
SOFT_DELAY;
LED1_OFF; // 灭
LED2_ON; // 亮
SOFT_DELAY;
LED2_OFF; // 灭
LED3_ON; // 亮
SOFT_DELAY;
LED3_OFF; // 灭
/*轮流显示 红绿蓝黄紫青白 颜色*/
LED_RED;
SOFT_DELAY;
LED_GREEN;
SOFT_DELAY;
LED_BLUE;
SOFT_DELAY;
LED_YELLOW;
SOFT_DELAY;
LED_PURPLE;
SOFT_DELAY;
LED_CYAN;
SOFT_DELAY;
LED_WHITE;
SOFT_DELAY;
LED_RGBOFF;
SOFT_DELAY;
}
}
void Delay(__IO uint32_t nCount) //简单的延时函数
{
for(; nCount != 0; nCount--);
}
/*********************************************END OF FILE**********************/
下面是效果图:
下载链接:
http://products.embedfire.com文章来源:https://www.toymoban.com/news/detail-840921.html
注:来自于野火官方文章来源地址https://www.toymoban.com/news/detail-840921.html
到了这里,关于STM32萌新学习日志——用GPIO外设寄存器输出点亮LED对比库函数点亮LED——谈学习感悟的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!