stm32-base-01-基础

本系列须知:

  1. 本博客中stm32入门系列是一些基础外设的使用,所用为正点原子stm32f103zet6精英版
  2. 使用的是hal库和cubemx

本实验内容如下

  • led的点亮

  • 独立按键检测(通过read_pin的方式),按key1,按一下灯的状态调转

  • 独立按键检测(通过外部中断的方式),KEY0,长按LED0亮,短按LED1灭,松手都灭

  • 定时器的使用,LED0亮一秒,熄一秒

  • 定时器的使用,pwm灯。通过KEY1来增强led灯的亮度

  • 定时器的使用,通过定时器来判断key1单击、双击、长按。单击亮LED0,双击亮LED1,长按所有灯关闭

ps.本系列不讲cubemx配置,但会放相关博客连接

pps.非完全原创,这其实也算我个人的学习笔记

LED的点亮

这个无需多说

一、【STM32 HAL库开发】点亮led灯_stm32cubeide的hal库编程呼吸灯编码-CSDN博客

总结一下

  1. 通过cubemx配置gpio口(PE3定义为LED0)
  2. 通过HAL_GPIO_WritePin(LED0_GPIO_Port,LED0_Pin,GPIO_PIN_RESET);置gpio口低电平,从而点亮LED
  3. HAL_GPIO_WritePin(LED0_GPIO_Port,LED0_Pin,GPIO_PIN_SET)置高电平,从而熄灭LED灯

led.c

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#include "LED.h"

void LED0_ON(void)
{
HAL_GPIO_WritePin(LED0_GPIO_Port,LED0_Pin,GPIO_PIN_RESET);
}

void LED0_OFF(void)
{
HAL_GPIO_WritePin(LED0_GPIO_Port,LED0_Pin,GPIO_PIN_SET);
}


void LED1_ON(void)
{
HAL_GPIO_WritePin(LED1_GPIO_Port,LED1_Pin,GPIO_PIN_RESET);
}

void LED1_OFF(void)
{
HAL_GPIO_WritePin(LED1_GPIO_Port,LED1_Pin,GPIO_PIN_SET);
}

led.h

1
2
3
4
5
6
7
8
9
10
11
#ifndef __LED_H
#define __LED_H
#include "stm32f1xx_hal.h"
#include "main.h"

void LED0_ON(void);
void LED0_OFF(void);
void LED1_ON(void);
void LED1_OFF(void);

#endif

main

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
int main(void)
{
/* USER CODE BEGIN 1 */

/* USER CODE END 1 */

/* MCU Configuration--------------------------------------------------------*/

/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();

/* USER CODE BEGIN Init */

/* USER CODE END Init */

/* Configure the system clock */
SystemClock_Config();

/* USER CODE BEGIN SysInit */

/* USER CODE END SysInit */

/* Initialize all configured peripherals */
MX_GPIO_Init();
/* USER CODE BEGIN 2 */
//
/* USER CODE END 2 */

/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
/* USER CODE END WHILE */

/* USER CODE BEGIN 3 */

LED1_OFF();
LED0_ON();
HAL_Delay(1000);
LED0_OFF();
LED1_ON();
HAL_Delay(1000);


}
/* USER CODE END 3 */
}

独立按键检测read_pin

STM32 HAL库实战基础篇(一)——跑马灯与按键输入_stm32按键输入低电平代码怎么写-CSDN博客

key.c

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include "key.h"

uint8_t key_scan(void)
{
uint8_t key_value = 0;//未被按下
if(HAL_GPIO_ReadPin(KEY1_GPIO_Port,KEY1_Pin) == GPIO_PIN_RESET)
{
while(HAL_GPIO_ReadPin(KEY1_GPIO_Port,KEY1_Pin) == GPIO_PIN_RESET)
{
key_value = 1;
}
}
return key_value;

}

key.h

1
2
3
4
5
6
7
8
9
10
11
#ifndef __KEY_
#define __KEY_
#include "stm32f1xx_hal.h"
#include "main.h"

uint8_t key_scan(void);



#endif

main

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
int main(void)
{
/* USER CODE BEGIN 1 */

/* USER CODE END 1 */

/* MCU Configuration--------------------------------------------------------*/

/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();

/* USER CODE BEGIN Init */

/* USER CODE END Init */

/* Configure the system clock */
SystemClock_Config();

/* USER CODE BEGIN SysInit */

/* USER CODE END SysInit */

/* Initialize all configured peripherals */
MX_GPIO_Init();
/* USER CODE BEGIN 2 */
uint8_t key;
//
/* USER CODE END 2 */

/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
/* USER CODE END WHILE */

/* USER CODE BEGIN 3 */

key = key_scan();
if(key == 1) HAL_GPIO_TogglePin(LED0_GPIO_Port,LED0_Pin);
}
/* USER CODE END 3 */
}

注意:该方式即时性极差,不建议实际工程中使用

独立按键检测(中断方式)

【STM32】HAL库——按键外部中断_hal库按键中断-CSDN博客

中断的方式就非常丝滑了,即时性很强

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
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
if(GPIO_Pin == KEY0_Pin)
{
if(HAL_GPIO_ReadPin(KEY0_GPIO_Port,KEY0_Pin) == GPIO_PIN_RESET)
{
HAL_GPIO_TogglePin(LED0_GPIO_Port,LED0_Pin);
}
}
}
/* USER CODE END PM */

/* Private variables ---------------------------------------------------------*/

/* USER CODE BEGIN PV */

/* USER CODE END PV */

/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
/* USER CODE BEGIN PFP */


/* USER CODE END PFP */

/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */

/* USER CODE END 0 */

/**
* @brief The application entry point.
* @retval int
*/
int main(void)
{
/* USER CODE BEGIN 1 */

/* USER CODE END 1 */

/* MCU Configuration--------------------------------------------------------*/

/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();

/* USER CODE BEGIN Init */

/* USER CODE END Init */

/* Configure the system clock */
SystemClock_Config();

/* USER CODE BEGIN SysInit */

/* USER CODE END SysInit */

/* Initialize all configured peripherals */
MX_GPIO_Init();

/* USER CODE BEGIN 2 */

//
/* USER CODE END 2 */

/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
/* USER CODE END WHILE */

/* USER CODE BEGIN 3 */

//key = key_scan();
//if(key == 1) HAL_GPIO_TogglePin(LED0_GPIO_Port,LED0_Pin);

}
/* USER CODE END 3 */
}

定时器(控制LED)

1s,led灯亮,1s,led灯灭

STM32CubeMX——定时器之定时功能_stm32cubemx 定时器-CSDN博客

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
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
uint8_t count = 0;
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
if(htim->Instance==TIM2)
{
count++;
}
}
int main(void)
{
/* USER CODE BEGIN 1 */

/* USER CODE END 1 */

/* MCU Configuration--------------------------------------------------------*/

/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();

/* USER CODE BEGIN Init */

/* USER CODE END Init */

/* Configure the system clock */
SystemClock_Config();

/* USER CODE BEGIN SysInit */

/* USER CODE END SysInit */

/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_USART1_UART_Init();
MX_TIM2_Init();
HAL_TIM_Base_Start_IT(&htim2);
/* USER CODE BEGIN 2 */
//
/* USER CODE END 2 */

/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
/* USER CODE END WHILE */

/* USER CODE BEGIN 3 */

if(count != 0 && count %2 == 0)
{
HAL_GPIO_TogglePin(LED0_GPIO_Port,LED0_Pin);
}

}
/* USER CODE END 3 */
}

定时器(pwm呼吸灯)

【定时器+HAL库】PWM的输出_哔哩哔哩_bilibili学会如何调节pwm频率

然后配置LED灯的引脚,设置pwm输出

pwm是个占空比的问题,其中占空比,也就是pulse越大,led灯越暗

因为呼吸灯是由暗到亮,由亮到暗

由暗到亮时,pulse需要减

由亮到暗时,pulse需要加

为了区分这两种模式,我们设置标志位flag

flag = 0 时,pulse 加

flag = 1时,pulse 减

当pulse达到最大值时,需要减,则flag = 1

1
2
3
4
5
6
7
8
9
HAL_TIM_PWM_Start(&htim3,TIM_CHANNEL_2);
void pwm_led(void)
{
HAL_Delay(5);
pwm = (flag == 0) ? pwm + 10 : pwm - 10;
if(pwm == 1000) flag = 1;
if(pwm == 0) flag = 0;
__HAL_TIM_SET_COMPARE(&htim3,TIM_CHANNEL_2,pwm);
}

定时器(控制独立按键)

按键的状态有多种:单击,双击,长按等

本实验将通过定时器来判断它的状态

如何判断短按:

key按下,定时器计时,key松开,定时器停止计时

如何判断长按:

key按下,定时器计时,时间超过2s,则停止计时,判断为短按

所以我们设置开启定时器中断的方式如下,即按键按下则开启定时器

1
2
3
4
5
6
7
void keys(void)
{
if(HAL_GPIO_ReadPin(KEY1_GPIO_Port,KEY1_Pin) == 0)
{
HAL_TIM_Base_Start_IT(&htim2);
}
}

中断内容如下

1
2
3
4
5
6
7
8
9
10
11
12
13
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
if(htim->Instance==TIM2)
{
count++; //count+就代表着计时
if(HAL_GPIO_ReadPin(KEY1_GPIO_Port,KEY1_Pin) == 1)//按键松开
{
HAL_TIM_Base_Stop_IT(&htim2);//停止计时
save_count = count;//保存按键时长
count = 0;//准备记录下一次按键
}
}
}

最后再根据时长判断长按和短按

1
2
3
4
5
6
7
8
uint8_t key_judge(void)
{
keys();
uint8_t key_state = 0;
if(50<save_count && save_count<120) key_state = 1;
if(150<save_count && save_count<220) key_state = 2;
return key_state;
}

在最后是变量的命名

1
2
uint8_t count = 0;
uint8_t save_count = 0;

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
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
uint8_t count = 0;
uint8_t save_count = 0;

void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
if(htim->Instance==TIM2)
{
count++;
if(HAL_GPIO_ReadPin(KEY1_GPIO_Port,KEY1_Pin) == 1)
{
HAL_TIM_Base_Stop_IT(&htim2);
save_count = count;
count = 0;
}
}
}

/* USER CODE END PM */

/* Private variables ---------------------------------------------------------*/

/* USER CODE BEGIN PV */
void keys(void);
uint8_t key_judge(void);
/* USER CODE END PV */

/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
/* USER CODE BEGIN PFP */
void set_dac(float v);

/* USER CODE END PFP */

/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */

/* USER CODE END 0 */

/**
* @brief The application entry point.
* @retval int
*/
int main(void)
{
/* USER CODE BEGIN 1 */

/* USER CODE END 1 */

/* MCU Configuration--------------------------------------------------------*/

/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();

/* USER CODE BEGIN Init */

/* USER CODE END Init */

/* Configure the system clock */
SystemClock_Config();

/* USER CODE BEGIN SysInit */

/* USER CODE END SysInit */

/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_USART1_UART_Init();
MX_TIM2_Init();
MX_RTC_Init();
MX_SDIO_SD_Init();
MX_FSMC_Init();
MX_TIM3_Init();
MX_DAC_Init();
/* USER CODE BEGIN 2 */
/* USER CODE BEGIN 1 */
uint8_t key = 0;
/* USER CODE END 1 */
/* USER CODE END 2 */

/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
/* USER CODE END WHILE */

/* USER CODE BEGIN 3 */

key = key_judge();
// printf("save_count = %d \r\n",save_count);
// printf("key_state = %d \r\n",key);
// HAL_Delay(500);
switch(key)
{
case 1:printf("short\r\n");key = 0;break;
case 2:printf("long\r\n");key = 0;break;
}

}
/* USER CODE END 3 */
}

void keys(void)
{
if(HAL_GPIO_ReadPin(KEY1_GPIO_Port,KEY1_Pin) == 0)
{
HAL_TIM_Base_Start_IT(&htim2);
}
}

uint8_t key_judge(void)
{
keys();
uint8_t key_state = 0;
if(50<save_count && save_count<120) key_state = 1;
if(150<save_count && save_count<220) key_state = 2;
return key_state;
}

stm32-base-01-基础
http://three27seven.top/2024/11/02/stm32-base01-基础/
作者
three27seven
发布于
2024年11月2日
许可协议