文章创作目的是梳理STM32的学习过程。本文旨在用最言简意骇的方式,主张用到哪里的代码就讲到哪里知识点。
一.STM32与51单片机——io口的区别;
STM32:需要进行io口初始化
因为stm32芯片拥有独特的时钟节能系统,如果要使用外设,必须先打开时钟,了解时钟如何打开与io口如何初始化成了第一课
五一单片机:直接对io口进行输出高低电平的操作
二.STM32芯片硬件基本知识:
1,io口介绍
STM32F103VET6的单片机,io端口数量非常多所以按组分类,每组含有16个引脚。有GPIOA,GPIOB,GPIOC,GPIOD,GPIOE,GPIOF,GPIOG,每组端口下有分有GPIO_Pin0到GPIO_Pin15一共16个引脚,所以总共有7*16=112个io口;
2,io口输出模式(led和蜂鸣器只用到推挽输出1种故不全提)
推挽输出:可以输出高电平和低电平
开漏输出:只能驱动输出低电平或浮动输出,高电平需要靠外部电阻拉高
3,时钟总线
STM32有APB1和APB2两种时钟线,具体哪组口使用哪个总线,看下图绿框部分,GPIOA-GPIOG都是APB2的时钟线
三.io口初始化固定思路
1.开启端口时钟。
2.设置引脚
3.引脚初始化
LED引脚连接如图
蜂鸣器引脚连接如图
四.代码思路:
1.创建对应文件,目的是实现代码模块化;
为两个外设,分别创建对应的.C与.H文件,在.C文件中初始化端口,.H文件作用与五一相同。
2.在.C文件中,创建一个使用时钟使能函数:RCC_APB2PeriphClockCmd,使能(打开)时钟;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE)
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); //使能函数
其中 APB2 可以替换为 APB1
GPIOB 可以替换为 GPIOA-GPIOG
ENABLE(使能) 可以替换为 DISABLE (失能)
参数(RCC_APB2Periph_GPIOB) 还可以写成
(RCC_APB2Periph_GPIOB|RCC_APB2Periph_GPIOE )//可以同时使能多组io口,一直添加"或"即可。
3.配置引脚+模式+速率函数
引脚配置
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
补充:可以试着双击代码右键选择GO To.....,可以跳转到到参数所在位置。
GPIO_Mode_Out_OD //开漏输出
GPIO_Mode_Out_PP //推挽输出
补充:若是更改为其他端口的初始化时,更改下面几个初始化函数的标红的参数即可。
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB|RCC_APB2Periph_GPIOE, ENABLE); //使能PB,PE端口时钟
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5; // 端口配置
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //IO口速度为
GPIO_Init(GPIOB, &GPIO_InitStructure); //根据设定参数初始化GPIO口
4.使用输出高低电平的函数
该函数可以直接控制端口高低电平,但还有另外一种可以输出高低电平的方式
GPIO_SetBits(GPIOB,GPIO_Pin_5); //PB.5 输出高
GPIO_SetBits(GPIOE,GPIO_Pin_5); //PE.5 输出高
GPIO_ResetBits(GPIOE,GPIO_Pin_5); //PE.5 输出低
GPIO_ResetBits(GPIOB,GPIO_Pin_5); //PB.5 输出低
4.1另一种输出高低电平的方式
1.在硬件的.h与main所在文件中引用 #include "sys.h"
2.在硬件.h中宏定义 #define BEEP PBout(8)
#ifndef __BEEP_H
#define __BEEP_H
#include "sys.h" //在相应外设的.h文件中引用该函数库,
可以实现使用0或者1控制端口输出高低电平
//蜂鸣器端口定义
#define BEEP PBout(8) // BEEP,蜂鸣器接口 #define 名字 P(组)out(端口号)
// 如 #define led PEout(5)
void BEEP_Init(void); //初始化
#endif
3.便可以在main中使用: BEEP=0; //BEEP 输出低电平
BEEP=1; //BEEP 输出高电平
int main(void)
{
delay_init(); //延时函数初始化
LED_Init(); //初始化与LED连接的硬件接口
BEEP_Init(); //初始化蜂鸣器端口
while(1)
{
LED0=0;
BEEP=0;
delay_ms(300);//延时300ms
LED0=1;
BEEP=1;
delay_ms(300);//延时300ms
}
}
五.代码实现如下:
led闪烁+蜂鸣器响
led.c
#include "led.h"
//初始化PB5和PE5为输出口.并使能这两个口的时钟
//LED IO初始化
void LED_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;//GPIO_InitTypeDef是一个结构体类型,其功能是定义一个结构体,该结构体有三个成员分别是u16类型的GPIO_Pin、GPIOSpeed_TypeDef 类型的GPIO_Speed和GPIOMode_TypeDef 类型的GPIO_Mode
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);
GPIO_SetBits(GPIOE,GPIO_Pin_5); //PE.5 输出高
}
led.h
#include "beep.h"
//初始化PB8为输出口.并使能这个口的时钟
//蜂鸣器初始化
void BEEP_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); //使能GPIOB端口时钟
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8; //BEEP-->PB.8 端口配置
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //速度为50MHz
GPIO_Init(GPIOB, &GPIO_InitStructure); //根据参数初始化GPIOB.8
GPIO_ResetBits(GPIOB,GPIO_Pin_8);//输出0,关闭蜂鸣器输出
}
beep.c
#ifndef __LED_H
#define __LED_H
#include "sys.h"
#define LED0 PBout(5)// PB5
#define LED1 PEout(5)// PE5 //本次未用上,仅用于理解#define LED1 PEout(5)
void LED_Init(void);//初始化
#endif
beep.h
#ifndef __BEEP_H
#define __BEEP_H
#include "sys.h"
//蜂鸣器端口定义
#define BEEP PBout(8) // BEEP,蜂鸣器接口
void BEEP_Init(void); //初始化
#endif
main.c
#include "sys.h"
#include "delay.h"
#include "led.h"
#include "beep.h"
int main(void)
{
delay_init(); //延时函数初始化
LED_Init(); //初始化与LED连接的硬件接口
BEEP_Init(); //初始化蜂鸣器端口
while(1)
{
LED0=0;
BEEP=0;
Delay_ms(300);//延时300ms
LED0=1;
BEEP=1;
Delay_ms(300);//延时300ms
}
}
delay.c (套用即可)
#include "stm32f10x.h"
/**
* @brief 微秒级延时
* @param xus 延时时长,范围:0~233015
* @retval 无
*/
void Delay_us(uint32_t xus)
{
SysTick->LOAD = 72 * xus; //设置定时器重装值
SysTick->VAL = 0x00; //清空当前计数值
SysTick->CTRL = 0x00000005; //设置时钟源为HCLK,启动定时器
while(!(SysTick->CTRL & 0x00010000)); //等待计数到0
SysTick->CTRL = 0x00000004; //关闭定时器
}
/**
* @brief 毫秒级延时
* @param xms 延时时长,范围:0~4294967295
* @retval 无
*/
void Delay_ms(uint32_t xms)
{
while(xms--)
{
Delay_us(1000);
}
}
/**
* @brief 秒级延时
* @param xs 延时时长,范围:0~4294967295
* @retval 无
*/
void Delay_s(uint32_t xs)
{
while(xs--)
{
Delay_ms(1000);
}
}
delay.h
#ifndef __DELAY_H
#define __DELAY_H
void Delay_us(uint32_t us);
void Delay_ms(uint32_t ms);
void Delay_s(uint32_t s);
#endif