Stm32基础
目录
常用功能函数
初始化gpio函数
作用:初始化一个或者多个io口(同一组)的工作方式和速度
该函数主要是操作GPIO CRL(CRH)寄存器,在上拉或者下拉的时候有设置BSRR或者BRR寄存器
void GPIO_Init(GPIO_TypeDef* GPIOx, GPIO_InitTypeDef* GPIO_InitStruct);
注意:外设(包括GPIO)在使用之前,几乎都要先使能对应的时钟
参数
第一个参数:
GPIOA
GPIOB
GPIOC
GPIOD
GPIOE
GPIOF
GPIOG
可选参数
第二个参数为一个结构体,三个变量成员
GPIO_Pin
GPIO_Pin_0
GPIO_Pin_1
GPIO_Pin_2
GPIO_Pin_3
GPIO_Pin_4
GPIO_Pin_5
GPIO_Pin_6
GPIO_Pin_7
GPIO_Pin_8
GPIO_Pin_9
GPIO_Pin_10
GPIO_Pin_11
GPIO_Pin_12
GPIO_Pin_13
GPIO_Pin_14
GPIO_Pin_15
可选参数
GPIO_Speed
GPIO_Speed_10MHz = ,
GPIO_Speed_2MHz,
GPIO_Speed_50MHz
可选参数
GPIO_Mode
GPIO_Mode_AIN = 0x0,//模拟输入
GPIO_Mode_IN_FLOATING = 0x04,//浮空输入
GPIO_Mode_IPD = 0x28,//下拉输入
GPIO_Mode_IPU = 0x48,//上拉输入
GPIO_Mode_Out_OD = 0x14,//开漏输出
GPIO_Mode_Out_PP = 0x10,//通用推挽输出
GPIO_Mode_AF_OD = 0x1C,//复用开漏输出
GPIO_Mode_AF_PP = 0x18//复用推挽
可选参数
示例
读取输入电平函数
作用:读取某个GPIO的输入电平
实际操作的是GPIOx_IDR寄存器
uint8_t GPIO_ReadInputDataBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);
示例
作用:读取某组GPIO的输入电平
实际操作的是GPIOx_IDR寄存器
uint16_t GPIO_ReadInputData(GPIO_TypeDef* GPIOx);
示例
读取输出电平函数
作用:读取某个GPIO的输出电平
实际操作的是GPIO_ODR寄存器
uint8_t GPIO_ReadOutputDataBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);
示例
作用:读取某组GPIO的输出电平
实际操作的是GPIO_ODR寄存器
uint16_t GPIO_ReadOutputData(GPIO_TypeDef* GPIOx);
示例
设置输出电平函数
void GPIO_SetBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);
void GPIO_ResetBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);
void GPIO_WriteBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin, BitAction BitVal);
void GPIO_Write(GPIO_TypeDef* GPIOx, uint16_t PortVal);
跑马灯实验
led.h
#ifndef __LED_H
#define __LED_H
void LED_Init(void); #endif
代码
led.c
#include "led.h"
#include "stm32f10x.h" void LED_Init(void){
GPIO_InitTypeDef GPIO_InitStruct;
//使能对应的时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);//
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOE,ENABLE);////初始化gpioB.5与gpioE.5 GPIO_InitStruct.GPIO_Mode=GPIO_Mode_Out_PP;
GPIO_InitStruct.GPIO_Pin=GPIO_Pin_5;
GPIO_InitStruct.GPIO_Speed=GPIO_Speed_50MHz; GPIO_Init(GPIOB,&GPIO_InitStruct);//初始化gpioB.5
GPIO_Init(GPIOE,&GPIO_InitStruct);//初始化gpioE.5
GPIO_SetBits(GPIOB,GPIO_Pin_5);//设置GPIOB.5输出低电平
GPIO_SetBits(GPIOE,GPIO_Pin_5);//设置GPIOE.5输出低电平
}
代码
main.c
#include "stm32f10x.h"
#include "led.h"
#include "delay.h" int main(void){ //初始延时
delay_init();
LED_Init(); while()
{
GPIO_SetBits(GPIOB,GPIO_Pin_5);
GPIO_SetBits(GPIOE,GPIO_Pin_5);
delay_ms(); GPIO_ResetBits(GPIOB,GPIO_Pin_5);
GPIO_ResetBits(GPIOE,GPIO_Pin_5);
delay_ms();
} }
代码
蜂鸣器实验
原理
beep.h
#ifndef __BEEP_H
#define __BEEP_H
#include "sys.h" //蜂鸣器端口定义
#define BEEP PBout(8) // BEEP,蜂鸣器接口 void BEEP_Init(void); //初始化 #endif
代码
beep.c
#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,关闭蜂鸣器输出 }
代码
main.c
#include "sys.h"
#include "delay.h"
#include "beep.h" int main(void)
{
delay_init(); //延时函数初始化 BEEP_Init(); //初始化蜂鸣器端口
while()
{ //BEEP=0;
GPIO_ResetBits(GPIOB,GPIO_Pin_8);
delay_ms();//延时300ms //BEEP=1;
GPIO_SetBits(GPIOB,GPIO_Pin_8);
delay_ms();//延时300ms
}
}
代码
按键实验
原理图
按键扫描
解决办法
led.h
#ifndef __LED_H
#define __LED_H #define LED0 PBout(5)// PB5
#define LED1 PEout(5)// PE5
void LED_Init(void); #endif
代码
led.c
#include "led.h"
#include "stm32f10x.h" void LED_Init(void){
GPIO_InitTypeDef GPIO_InitStruct;//
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOE,ENABLE);
//RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOE | RCC_APB2Periph_GPIOB,ENABLE); GPIO_InitStruct.GPIO_Mode=GPIO_Mode_Out_PP;
GPIO_InitStruct.GPIO_Pin=GPIO_Pin_5;
GPIO_InitStruct.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_Init(GPIOB,&GPIO_InitStruct);
GPIO_SetBits(GPIOB,GPIO_Pin_5); GPIO_InitStruct.GPIO_Mode=GPIO_Mode_Out_PP;
GPIO_InitStruct.GPIO_Pin=GPIO_Pin_5;
GPIO_InitStruct.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_Init(GPIOE,&GPIO_InitStruct);
GPIO_SetBits(GPIOE,GPIO_Pin_5);
}
代码
key.h
#ifndef __KEY_H
#define __KEY_H
#include "sys.h" //#define KEY0 PEin(4) //PE4
//#define KEY1 PEin(3) //PE3
//#define KEY2 PEin(2) //PE2
//#define WK_UP PAin(0) //PA0 WK_UP #define KEY0 GPIO_ReadInputDataBit(GPIOE,GPIO_Pin_4)//读取按键0
#define KEY1 GPIO_ReadInputDataBit(GPIOE,GPIO_Pin_3)//读取按键1
#define KEY2 GPIO_ReadInputDataBit(GPIOE,GPIO_Pin_2)//读取按键2
#define WK_UP GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_0)//读取按键3(WK_UP) #define KEY0_PRES 1 //KEY0按下
#define KEY1_PRES 2 //KEY1按下
#define KEY2_PRES 3 //KEY2按下
#define WKUP_PRES 4 //KEY_UP按下(即WK_UP/KEY_UP) void KEY_Init(void);//IO初始化
u8 KEY_Scan(u8); //按键扫描函数
#endif
代码
key.c
#include "stm32f10x.h"
#include "key.h"
#include "sys.h"
#include "delay.h" //按键初始化函数
void KEY_Init(void) //IO初始化
{
GPIO_InitTypeDef GPIO_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOE,ENABLE);//使能PORTA,PORTE时钟 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2|GPIO_Pin_3|GPIO_Pin_4;//KEY0-KEY2
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; //设置成上拉输入
GPIO_Init(GPIOE, &GPIO_InitStructure);//初始化GPIOE2,3,4 //初始化WK_UP-->GPIOA.0 下拉输入
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD; //PA0设置成输入,默认下拉
GPIO_Init(GPIOA, &GPIO_InitStructure);//初始哈CPIOA.0 }
//按键处理函数
//返回按键值
//mode:0,不支持连续按;1,支持连续按
//0,没有任何按键按下
//1,key0按下
//2,key1按下
//3,key2按下
//4,key3按下
//注意此函数有响应优先级,KEY0>KEY1>KEY2>KEY3!!
u8 KEY_Scan(u8 mode)
{
static u8 key_up=;//按键按松开标志
if(mode)key_up=; //支持连按
if(key_up&&(KEY0==||KEY1==||KEY2==||WK_UP==))
{
delay_ms();//去抖动
key_up=;
if(KEY0==)return KEY0_PRES;
else if(KEY1==)return KEY1_PRES;
else if(KEY2==)return KEY2_PRES;
else if(WK_UP==)return WKUP_PRES;
}else if(KEY0==&&KEY1==&&KEY2==&&WK_UP==)key_up=;
return ;// 无按键按下
}
代码
beep.h
beep.c
main.c
#include "led.h"
#include "delay.h"
#include "key.h"
#include "sys.h"
#include "beep.h" int main(void)
{
vu8 key=;
delay_init(); //延时函数初始化
LED_Init(); //LED端口初始化
KEY_Init(); //初始化与按键连续的硬件接口
BEEP_Init(); //初始化蜂鸣器端口
LED0=; //先点亮红灯
while()
{
key=KEY_Scan(); //得到键值
if(key)
{
switch(key)
{
case WKUP_PRES: //控制蜂鸣器
BEEP=!BEEP;
break;
case KEY2_PRES: //控制LED0翻转
LED0=!LED0;
break;
case KEY1_PRES: //控制LED1翻转
LED1=!LED1;
break;
case KEY0_PRES: //同时控制LED0,LED1翻转
LED0=!LED0;
LED1=!LED1;
break;
}
}else delay_ms();
}
}
代码
端口复用与重映射
端口复用
简单来说就是一个端口有多种功能选择,复用功能更多请查表。