目录
  1. 1. STM32实验教程
    1. 1.1. 1.跑马灯实验——寄存器版本
    2. 1.2. 2.跑马灯实验——库函数版本
    3. 1.3. 3.跑马灯实验——位带操作
    4. 1.4. 4.按键输入实验——GPIO口作输入
跑马灯实验和GPIO口按键输入实验

STM32实验教程

1.跑马灯实验——寄存器版本

硬件连接

硬件连接

配置寄存器操作IO口步骤:

①初始化HAL库:HAL_Init();

②初始化系统时钟

STM32F429: Stm32_Clock_Init(360,25,2,8);

③ 使能IO口时钟。配置IO口时钟使能寄存器: RCC->AHB1ENR

④ 初始化IO口模式。配置四个配置寄存器

​ GPIOx_MODER GPIOx_OTYPER

​ GPIOx_OSPEEDR GPIOx_PUPDR

⑤ 操作IO口,输出高低电平。

配置寄存器GPIOX_ODR或者GPIOx_BSRR 。

程序源码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
#include "sys.h"
#include "delay.h"
#include "usart.h"

int main(void)
{
HAL_Init(); //初始化HAL库
Stm32_Clock_Init(360,25,2,8); //初始化系统时钟
delay_init(180); //延时函数初始化


RCC->AHB1ENR |= 1<<1; //使能IO口时钟(PB)

GPIOB->MODER= 0x00000005; //设置PB0和PB1为通用输出模式
GPIOB->OTYPER= 0x00000000; //设置PB0和PB1为推挽输出
GPIOB->OSPEEDR=0x0000000F; //设置PB0和PB1为高速
GPIOB->PUPDR= 0x00000005; //设置PB0和PB1为上拉

while(1)
{

GPIOB->BSRR=0x00000003 ;//1 置位

delay_ms(500);

GPIOB->BSRR=0x00030000; //0 复位

delay_ms(500);
}
}

2.跑马灯实验——库函数版本

硬件连接同上节。LED1-PB0,LED0-PB1。

八个重要函数:

1个初始化函数:

void HAL_GPIO_Init(GPIO_TypeDef *GPIOx, GPIO_InitTypeDef *GPIO_Init);

作用:初始化一个或者多个IO口(同一组)的工作模式,输出类型,速度以及上下拉方式。也就是一组IO口的4个配置寄存器。

​ (GPIOx->MODER, GPIOx->OSPEEDR,GPIOx->OTYPER,GPIOx->PUPDR)

GPIO_Init函数初始化样例:

1
2
3
4
5
6
7
GPIO_InitTypeDef GPIO_Initure;

GPIO_Initure.Pin=GPIO_PIN_0|GPIO_PIN_1; //PB1,0
GPIO_Initure.Mode=GPIO_MODE_OUTPUT_PP; //推挽输出
GPIO_Initure.Pull=GPIO_PULLUP; //上拉
GPIO_Initure.Speed=GPIO_SPEED_HIGH; //高速
HAL_GPIO_Init(GPIOB,&GPIO_Initure);

1个读取输入电平函数:

GPIO_PinState HAL_GPIO_ReadPin(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);

作用:读取某个GPIO的输入电平。实际操作的是GPIOx_IDR寄存器。

例如:

1
GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_5);//读取GPIOA PA5的输入电平

1个设置输出电平函数:

void HAL_GPIO_WritePin(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin, GPIO_PinState PinState);


1个电平翻转函数:

void HAL_GPIO_TogglePin(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);


1个引脚电平锁定函数:

HAL_StatusTypeDef HAL_GPIO_LockPin(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);


2个外部中断相关函数。

配置HAL库操作IO口步骤:

①初始化HAL库:HAL_Init();

②初始化系统时钟 :Stm32_Clock_Init( );

③ 使能IO口时钟。

​ 操作寄存器:配置IO口时钟使能寄存器: RCC->AHB1ENR

​ HAL库方法:__HAL_RCC_GPIOB_CLK_ENABLE();

④ 初始化IO口模式。

​ 操作寄存器:GPIOx_MODER OTYPER OSPEEDR PUPDR

​ HAL库方法:HAL_GPIO_Init();

⑤ 操作IO口,输出高低电平。

​ 操作寄存器:配置寄存器GPIOX_ODR或者GPIOx_BSRR 。

​ HAL库方法:HAL_GPIO_WritePin();

程序源码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
#include "sys.h"
#include "delay.h"
#include "usart.h"



int main(void)
{
GPIO_InitTypeDef GPIO_InitStructure;

HAL_Init(); //初始化HAL库
Stm32_Clock_Init(360,25,2,8); //系统时钟初始化
delay_init(180);

__HAL_RCC_GPIOB_CLK_ENABLE(); //使能IO口时钟


GPIO_InitStructure.Mode=GPIO_MODE_OUTPUT_PP;//推挽
GPIO_InitStructure.Pin=GPIO_PIN_0 | GPIO_PIN_1; //PB0和PB1
GPIO_InitStructure.Pull=GPIO_PULLUP;//上拉
GPIO_InitStructure.Speed=GPIO_SPEED_FREQ_VERY_HIGH;//高速

HAL_GPIO_Init(GPIOB,&GPIO_InitStructure);

while(1)
{
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_0,GPIO_PIN_RESET); //PB0=0
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_1,GPIO_PIN_RESET); //PB1=0
delay_ms(500);
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_0,GPIO_PIN_SET);//PB0=1
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_1,GPIO_PIN_SET);//PB0=1
delay_ms(500);
}

}

3.跑马灯实验——位带操作

位操作原理: 把每个比特膨胀为一个32位的字,当访问这些字的时候就达到了访问比特的目的,比如说BSRR寄存器有32个位,那么可以映射到32个地址上,我们去访问(读-改-写)这32个地址就达到访问32个比特的目的。

简而言之就是直接对IO口相对应的地址写值。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
#include "sys.h"
#include "delay.h"
#include "usart.h"
#define LED0 PBout(0)


int main(void)
{
GPIO_InitTypeDef GPIO_InitStructure;

HAL_Init(); //初始化HAL库
Stm32_Clock_Init(360,25,2,8); //系统时钟初始化
delay_init(180);

__HAL_RCC_GPIOB_CLK_ENABLE(); //使能IO口时钟


GPIO_InitStructure.Mode=GPIO_MODE_OUTPUT_PP;//推挽
GPIO_InitStructure.Pin=GPIO_PIN_0 | GPIO_PIN_1; //PB0和PB1
GPIO_InitStructure.Pull=GPIO_PULLUP;//上拉
GPIO_InitStructure.Speed=GPIO_SPEED_FREQ_VERY_HIGH;//高速

HAL_GPIO_Init(GPIOB,&GPIO_InitStructure);

while(1)
{
PBout(0)=1;
PBout(1)=1;
delay_ms(500);
PBout(0)=0;
PBout(1)=0;
delay_ms(500);
}

}

4.按键输入实验——GPIO口作输入

参考资料《STM32Fxxx开发指南-库函数版本》-第7章 按键输入实验

硬件连接:

按键实验硬件连接

KEY0->PH3 上拉输入 KEY1->PH2 上拉输入 KEY2->PC13 上拉输入 WK_UP->PA0 下拉输入

HARDWARE硬件函数

key.c

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
#include "key.h"
#include "delay.h"


void KEY_Init(void)
{
GPIO_InitTypeDef GPIO_Initure;

__HAL_RCC_GPIOA_CLK_ENABLE(); //开启GPIOA时钟
__HAL_RCC_GPIOC_CLK_ENABLE(); //开启GPIOC时钟
__HAL_RCC_GPIOH_CLK_ENABLE(); //开启GPIOH时钟

GPIO_Initure.Pin=GPIO_PIN_0; //PA0
GPIO_Initure.Mode=GPIO_MODE_INPUT; //输入
GPIO_Initure.Pull=GPIO_PULLDOWN; //下拉
GPIO_Initure.Speed=GPIO_SPEED_HIGH; //高速
HAL_GPIO_Init(GPIOA,&GPIO_Initure);

GPIO_Initure.Pin=GPIO_PIN_13; //PC13
GPIO_Initure.Mode=GPIO_MODE_INPUT; //输入
GPIO_Initure.Pull=GPIO_PULLUP; //上拉
GPIO_Initure.Speed=GPIO_SPEED_HIGH; //高速
HAL_GPIO_Init(GPIOC,&GPIO_Initure);

GPIO_Initure.Pin=GPIO_PIN_2|GPIO_PIN_3; //PH2,3
HAL_GPIO_Init(GPIOH,&GPIO_Initure);
}

//按键处理函数
//返回按键值
//mode:0,不支持连续按;1,支持连续按;
//0,没有任何按键按下
//1,wkup按下 wk_up
//注意此函数有响应优先级,KEY0>KEY1>KEY2>WK_UP!!
u8 KEY_Scan(u8 mode)
{
static u8 key_up=1; //按键松开标志
if(mode==1)key_up=1; //支持连按
if(key_up&&(KEY0==0||KEY1==0||KEY2==0||WK_UP==1))
{
delay_ms(10);
key_up=0;
if(KEY0==0) return KEY0_PRES;
else if(KEY1==0) return KEY1_PRES;
else if(KEY2==0) return KEY2_PRES;
else if(WK_UP==1) return WKUP_PRES;
}else if(KEY0==1&&KEY1==1&&KEY2==1&&WK_UP==0)key_up=1;
return 0; //无按键按下
}

led.c

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include "led.h"
void LED_Init(void)
{
GPIO_InitTypeDef GPIO_Initure;
__HAL_RCC_GPIOB_CLK_ENABLE();

GPIO_Initure.Pin=GPIO_PIN_0|GPIO_PIN_1;
GPIO_Initure.Mode=GPIO_MODE_OUTPUT_PP;
GPIO_Initure.Pull=GPIO_PULLUP;
GPIO_Initure.Speed=GPIO_SPEED_HIGH;
HAL_GPIO_Init(GPIOB,&GPIO_Initure);

HAL_GPIO_WritePin(GPIOB,GPIO_PIN_0,GPIO_PIN_SET); //PB0置1
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_1,GPIO_PIN_SET); //PB1置1
}

main.c

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
#include "sys.h"
#include "delay.h"
#include "usart.h"
#include "led.h"
#include "key.h"

int main(void)
{
u8 key;
HAL_Init();
Stm32_Clock_Init(360,25,2,8);
delay_init(180);
uart_init(115200);
LED_Init(); //初始化LED
KEY_Init(); //初始化按键

while(1)
{
key=KEY_Scan(0); //按键扫描
switch(key)
{
case WKUP_PRES: //控制LED0,LED1互斥点亮
LED1=!LED1;
LED0=!LED1;
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;
}
delay_ms(10);
}
}
文章作者: jiangzuojiben
文章链接: http://jiangzuojiben.github.io/2019/11/01/%E8%B7%91%E9%A9%AC%E7%81%AF%E5%AE%9E%E9%AA%8C%E5%92%8CGPIO%E5%8F%A3%E6%8C%89%E9%94%AE%E8%BE%93%E5%85%A5%E5%AE%9E%E9%AA%8C/
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 jiangzuojiben