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(); Stm32_Clock_Init(360,25,2,8); delay_init(180); RCC->AHB1ENR |= 1<<1; GPIOB->MODER= 0x00000005; GPIOB->OTYPER= 0x00000000; GPIOB->OSPEEDR=0x0000000F; GPIOB->PUPDR= 0x00000005; while(1) { GPIOB->BSRR=0x00000003 ; delay_ms(500); GPIOB->BSRR=0x00030000; 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; 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);
|
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(); Stm32_Clock_Init(360,25,2,8); delay_init(180); __HAL_RCC_GPIOB_CLK_ENABLE(); GPIO_InitStructure.Mode=GPIO_MODE_OUTPUT_PP; GPIO_InitStructure.Pin=GPIO_PIN_0 | GPIO_PIN_1; 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); HAL_GPIO_WritePin(GPIOB,GPIO_PIN_1,GPIO_PIN_RESET); delay_ms(500); HAL_GPIO_WritePin(GPIOB,GPIO_PIN_0,GPIO_PIN_SET); HAL_GPIO_WritePin(GPIOB,GPIO_PIN_1,GPIO_PIN_SET); 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(); Stm32_Clock_Init(360,25,2,8); delay_init(180); __HAL_RCC_GPIOB_CLK_ENABLE(); GPIO_InitStructure.Mode=GPIO_MODE_OUTPUT_PP; GPIO_InitStructure.Pin=GPIO_PIN_0 | GPIO_PIN_1; 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(); __HAL_RCC_GPIOC_CLK_ENABLE(); __HAL_RCC_GPIOH_CLK_ENABLE(); GPIO_Initure.Pin=GPIO_PIN_0; 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; 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; HAL_GPIO_Init(GPIOH,&GPIO_Initure); }
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); HAL_GPIO_WritePin(GPIOB,GPIO_PIN_1,GPIO_PIN_SET); }
|
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(); KEY_Init(); while(1) { key=KEY_Scan(0); switch(key) { case WKUP_PRES: LED1=!LED1; LED0=!LED1; break; case KEY2_PRES: LED0=!LED0; break; case KEY1_PRES: LED1=!LED1; break; case KEY0_PRES: LED0=!LED0; LED1=!LED1; break; } delay_ms(10); } }
|