进阶篇 IV [DMA]

项目&教程仓库-STM32-RoboMaster-


1.0 什么是DMA

1.1 DMA的定义

Direct Memory Access:直接存储器访问 是所有现代计算设备的重要特色,它允许不同速度的硬件装置来沟通,而不需要依赖于CPU的大量中断负载。否则,CPU需要从来源把每一片段的资料复制到暂存器,然后把它们再次写回到新的地方。在这个时间中,CPU对于其他的工作来说就无法使用。DMA传输将数据从一个地址空间复制到另外一个地址空间。当CPU初始化这个传输动作,传输动作本身是由DMA控制器来实行和完成。典型的例子就是移动一个外部内存的区块到芯片内部更快的内存区。像是这样的操作并没有让处理器工作拖延,反而可以被重新排程去处理其他的工作。DMA传输是高效能嵌入式系统算法和网络最关键的部分。

DMA and CPU.png

从上图可以看出,DMA和CPU是同等地位的,CPU能进行的数据转移操作,DMA都能做,或者说,DMA就是只能做数据转移操作的迷你CPU。

如果要简单理解的话,DMA就是CPU小弟,当CPU觉得把一大串数据转移到另一个地方这种任务太麻烦,还有更重要的事情需要做的时候,就可以把这个任务丢给DMA去干,DMA干完或者出问题了跟CPU说一声就行了。

1.2 DMA的内部结构

DMA detail.png

  • STM32 –> DMA –> Stream –> Channel
    • STM32F4家族拥有两个DMA,其中只有DMA2能够进行M2M操作(稍后会讲)。
    • 每个DMA一般拥有8个Stream。
    • 每个Stream有多个Channel选项,但是一次只能进行一个Channel的传输,具体的配置与选项请参考芯片对应的数据手册。

Stream and Channel.png

2.0 什么情况下使用DMA?

2.1 UART

  • 这是最常见的使用情况,当有大量的数据从UART读入或者写入的时候,DMA将CPU解放出来,然后自己单干,让CPU处理更重要的事情。

2.2 ADC

  • 一般在需要ADC时的通道扫描模式下,需要DMA来处理,本章不讲解这部分,放到后面专门讲ADC的篇章。

2.3 SD

  • 需要大量往SD里面读写数据的时候一般也用DMA来处理,本章不讲解这部分。

3.0 DMA的使用方法

3.1 传输方向

  • P2P
    • Peripheral to Peripheral:从外设到外设 在RM中暂时用不上,不讲解
  • P2M
    • Peripheral to Memory:从外设到内存 当传感器从UART传来数据的时候用
  • M2P
    • Memory to Peripheral:从内存到外设 从UART传出数据控制执行器的时候用
  • M2M
    • Memory to Memory:从内存到内存 MCU内部的数据转移,常见于Buffer之间互相转移数据,或者从Buffer读写数据
    • 只有DMA2能够执行M2M操作。

3.2 特殊选项

  • First In First Out是STM32里面的DMA的特殊功能,但是一般来说,RM就算不用FIFO,DMA也能完美处理数据,所以暂时不需要,也同样不讲解。

3.3 传输模式

3.3.1 Normal Mode

  • 常用的默认模式,在该模式下,任务完成后就停止DMA,如果还需要用到DMA,需要再次手动启动。

3.3.2 Circular Mode / Continuous Mode

  • 可选模式,在该模式下,任务完成后,DMA的Buffer清零,再次执行任务。也就是说,永远重复执行下去,除非手动停止。

3.4 传输方式

3.4.1 DMA泛用方法(需要用到寄存器)

3.4.1.1 Polling

需要注意的是,DMA的Polling其实根本毫无意义,因为在这个过程中,CPU还是全程参与了,并没有解放CPU,所以,虽然这种方法我还是列出来了,但是除了Debug时可能会用到,其他情况下建议不要用。

1
HAL_StatusTypeDef HAL_DMA_Start(DMA_HandleTypeDef *hdma, uint32_t SrcAddress, uint32_t	DstAddress, uint32_t DataLength);
  • 参数
    • hdma:指向DMA Stream配置结构体
    • SrcAddress:需要传输的数据的地址
    • DstAddress:数据传输到的目标地址
    • DataLength:传输的数据大小
  • 返回值
    • HAL_StatusTypeDef:如果传输配置成功,返回HAL_OK;如果该DMA Stream正在被占用,返回HAL_BUSY

1
huart.Instance->CR3|=USART_CR3_DMAT;
  • 通过修改CR3寄存器对应的bit,开启DMA传输

1
HAL_StatusTypeDef HAL_DMA_PollForTransfer(DMA_HandleTypeDef *hdma, HAL_DMA_LevelCompleteTypeDef CompleteLevel, uint32_t Timeout);
  • 参数
    • hdma:指向DMA Stream配置结构体
    • CompleteLevel:指定DMA的完成程度
    • Timeout:传输的最大时限
  • 返回值
    • HAL_StatusTypeDef:如果传输成功,返回HAL_OK;如果传输出错,返回HAL_ERROR;如果传输超过最大时限,返回HAL_TIMEOUT

1
huart.Instance->CR3&=~USART_CR3_DMAT;
  • 通过修改CR3寄存器对应的bit,结束DMA传输
3.4.1.2 Interrupt
1
HAL_StatusTypeDef HAL_DMA_Start_IT(DMA_HandleTypeDef *hdma, uint32_t SrcAddress, uint32_t	DstAddress, uint32_t DataLength);
  • 参数
    • hdma:指向DMA Stream配置结构体
    • SrcAddress:需要传输的数据的地址
    • DstAddress:数据传输到的目标地址
    • DataLength:传输的数据大小
  • 返回值
    • HAL_StatusTypeDef:如果传输配置成功,返回HAL_OK;如果该DMA Stream正在被占用,则返回HAL_BUSY

1
huart.Instance->CR3|=USART_CR3_DMAT;
  • 通过修改CR3寄存器对应的bit,开启DMA传输

1
2
3
void XferCpltCallback(DMA_HandleTypeDef *hdma){
......
}
  • 在写代码的时候,在main.c中创建XferCpltCallback函数
  • 在该函数中填写DMA传输结束后,需要执行的代码

1
huart.Instance->CR3&=~USART_CR3_DMAT;
  • 通过修改CR3寄存器对应的bit,结束DMA传输

3.4.2 UART特化方法(全HAL库实现)

1
HAL_StatusTypeDef HAL_UART_Transmit_DMA(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size);
  • 参数
    • huart:指向UART引脚配置结构体
    • pData:指向需要传输的数据
    • Size:传输数据的大小
  • 返回值
    • HAL_StatusTypeDef:如果传输配置成功,返回HAL_OK;如果传输出错,返回HAL_ERROR;如果该DMA Stream正在被占用,则返回HAL_BUSY

1
HAL_StatusTypeDef HAL_UART_Receive_DMA(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size);
  • 参数
    • huart:指向UART引脚配置结构体
    • pData:指向需要传输的数据
    • Size:传输数据的大小
  • 返回值
    • HAL_StatusTypeDef:如果传输配置成功,返回HAL_OK;如果传输出错,返回HAL_ERROR;如果该DMA Stream正在被占用,则返回HAL_BUSY

1
2
3
void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart){
......
}
  • 在写代码的时候,在main.c中创建HAL_UART_TxCpltCallback函数
  • 在该函数中填写UART发送结束后,需要执行的代码

1
2
3
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart){
......
}
  • 在写代码的时候,在main.c中创建HAL_UART_RxCpltCallback函数
  • 在该函数中填写UART接收结束后,需要执行的代码

4.0 练习项目

4.1 项目简介

  • 一键发送信息:按下用户自定义按钮,就从UART发送出预先设定好的信息,完成后在板子上亮红灯0.2s。
  • 键盘回响:按下键盘,从STM32返回对应的字符,完成后在板子上亮绿灯0.2s。然后,再加上上面一键发送信息的功能。

4.2 项目代码

完整的工程文件可以在这里找到!

4.2.1 一键发送信息

  • DMA泛用方法 Polling
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
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
/* USER CODE BEGIN Header */
/**
******************************************************************************
* @file : main.c
* @brief : Main program body
******************************************************************************
* @attention
*
* <h2><center>&copy; Copyright (c) 2020 STMicroelectronics.
* All rights reserved.</center></h2>
*
* This software component is licensed by ST under BSD 3-Clause license,
* the "License"; You may not use this file except in compliance with the
* License. You may obtain a copy of the License at:
* opensource.org/licenses/BSD-3-Clause
*
******************************************************************************
*/
/* USER CODE END Header */

/* Includes ------------------------------------------------------------------*/
#include "main.h"

/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "string.h"
/* USER CODE END Includes */

/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */

/* USER CODE END PTD */

/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
/* USER CODE END PD */

/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */

/* USER CODE END PM */

/* Private variables ---------------------------------------------------------*/
UART_HandleTypeDef huart7;
DMA_HandleTypeDef hdma_uart7_tx;

/* USER CODE BEGIN PV */

/* USER CODE END PV */

/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_DMA_Init(void);
static void MX_UART7_Init(void);
/* USER CODE BEGIN PFP */

/* USER CODE END PFP */

/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
char msg[]="\r\n"
" %@@@@@@@#\r\n"
" .(&@&, &@@@@@@@% *@@&(\r\n"
" %@@@@@@@@%%&@@@@@@@@@@@@@@@@@@@&%&@@@@@@@@#\r\n"
" &@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@%\r\n"
" #@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@/\r\n"
" ,. .&@@@@@@@@@@@@@&(. ,(&@@@@@@@@@@@@@&. .,\r\n"
" &@@@@&@@@@@@@@@@@&, ###%#%%%%#%%%#### *&@@@@@@@@@@@&@@@@%\r\n"
" /@@@@@@@@@@@@@@@& ,@@@@@@@@&. .&@@@@@@@@@@@@@@@,\r\n"
" (&@@@@@@@@@@@@@# (@@@@@@@/ %@@@@@@@@@@@@@&*\r\n"
" &@@@@@@@@&. ,%@@@@&@@@@@@@&@@@&%, ,&@@@@@@@@%\r\n"
" /@@@@@@@@% #@@@@@( *@@@@@@&, %@@@@&( &@@@@@@@@/\r\n"
" .&@@@@@@@% #@@@@@% *@@@@@@&, &@@@@@# &@@@@@@@&. # \"There is no truth in flesh, only betrayal.\"\r\n"
" ,%%%%&@@@@@@@@* &@@@@@% *@@@@@@&, %@@@@@% ,@@@@@@@@&%%%% # \"There is no strength in flesh, only weakness.\"\r\n"
" /@@@@@@@@@@@@&. #@@@@@@, *@@@@@@&, ,@@@@@@( .&@@@@@@@@@@@&, # \"There is no constancy in flesh, only decay .\"\r\n"
" /@@@@@@@@@@@@& %@@@@@@, *@@@@@@&, ,@@@@@@# .&@@@@@@@@@@@&, # \"There is no certainty in flesh, but death .\"\r\n"
" *&@@@@@@@@@@@&, .@@@@@@# *@@@@@@&, %@@@@@& ,@@@@@@@@@@@@&. # — Credo Omnissiah\r\n"
" .&@@@@@@@# .&@@@@@( *@@@@@@&, %@@@@@& %@@@@@@@&.\r\n"
" (@@@@@@@@( ,&@@@@&. *@@@@@@&, *&@@@@%. #@@@@@@@@( Welcome back to Adeptus Mechanicus, Alchemic Ronin!\r\n"
" %@@@@@@@@% .%@@@@&%@@@@@@@%&@@@@#. %@@@@@@@@%\r\n"
" .(&@@@@@@@@@@@@, *%@@@@@@@%* (@@@@@@@@@@@@&/\r\n"
" %@@@@@@@@@@@@@@@/ .(@@@@@@@@@(. #@@@@@@@@@@@@@@@#\r\n"
" .&@@@@@@@@@@@@@@@@( ,***************, #&@@@@@@@@@@@@@@@&.\r\n"
" %( #@@@@@@@@@@@@@%*. ./&@@@@@@@@@@@@@/ .##\r\n"
" .&@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@%.\r\n"
" #@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@(\r\n"
" &@@@@@@@@@&@@@@@@@@@@@@@@@@@@@@@&@@@@@@@@@%\r\n"
" /&@@@/ .*&@@@@@@@&,. (@@@&/\r\n"
" %@@@@@@@#\r\n"
" .,,,,,,,.\r\n"
"\r\n";
/* 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_DMA_Init();
MX_UART7_Init();
/* USER CODE BEGIN 2 */
HAL_GPIO_WritePin(LD_RED_GPIO_Port,LD_RED_Pin,GPIO_PIN_SET);
/* USER CODE END 2 */

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

/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
}

/**
* @brief System Clock Configuration
* @retval None
*/
void SystemClock_Config(void)
{
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};

/** Configure the main internal regulator output voltage
*/
__HAL_RCC_PWR_CLK_ENABLE();
__HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE3);
/** Initializes the CPU, AHB and APB busses clocks
*/
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
RCC_OscInitStruct.HSIState = RCC_HSI_ON;
RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE;
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
{
Error_Handler();
}
/** Initializes the CPU, AHB and APB busses clocks
*/
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
|RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_HSI;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;

if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_0) != HAL_OK)
{
Error_Handler();
}
}

/**
* @brief UART7 Initialization Function
* @param None
* @retval None
*/
static void MX_UART7_Init(void)
{

/* USER CODE BEGIN UART7_Init 0 */

/* USER CODE END UART7_Init 0 */

/* USER CODE BEGIN UART7_Init 1 */

/* USER CODE END UART7_Init 1 */
huart7.Instance = UART7;
huart7.Init.BaudRate = 115200;
huart7.Init.WordLength = UART_WORDLENGTH_8B;
huart7.Init.StopBits = UART_STOPBITS_1;
huart7.Init.Parity = UART_PARITY_NONE;
huart7.Init.Mode = UART_MODE_TX_RX;
huart7.Init.HwFlowCtl = UART_HWCONTROL_NONE;
huart7.Init.OverSampling = UART_OVERSAMPLING_16;
if (HAL_UART_Init(&huart7) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN UART7_Init 2 */

/* USER CODE END UART7_Init 2 */

}

/**
* Enable DMA controller clock
*/
static void MX_DMA_Init(void)
{

/* DMA controller clock enable */
__HAL_RCC_DMA1_CLK_ENABLE();

/* DMA interrupt init */
/* DMA1_Stream1_IRQn interrupt configuration */
HAL_NVIC_SetPriority(DMA1_Stream1_IRQn, 1, 0);
HAL_NVIC_EnableIRQ(DMA1_Stream1_IRQn);

}

/**
* @brief GPIO Initialization Function
* @param None
* @retval None
*/
static void MX_GPIO_Init(void)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};

/* GPIO Ports Clock Enable */
__HAL_RCC_GPIOB_CLK_ENABLE();
__HAL_RCC_GPIOE_CLK_ENABLE();

/*Configure GPIO pin Output Level */
HAL_GPIO_WritePin(LD_RED_GPIO_Port, LD_RED_Pin, GPIO_PIN_RESET);

/*Configure GPIO pin : Button_Pin */
GPIO_InitStruct.Pin = Button_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_IT_RISING;
GPIO_InitStruct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(Button_GPIO_Port, &GPIO_InitStruct);

/*Configure GPIO pin : LD_RED_Pin */
GPIO_InitStruct.Pin = LD_RED_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(LD_RED_GPIO_Port, &GPIO_InitStruct);

/* EXTI interrupt init*/
HAL_NVIC_SetPriority(EXTI2_IRQn, 1, 0);
HAL_NVIC_EnableIRQ(EXTI2_IRQn);

}

/* USER CODE BEGIN 4 */
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin){
if(GPIO_Pin == Button_Pin){
HAL_Delay(500);
HAL_DMA_Start(&hdma_uart7_tx,(uint32_t)msg,(uint32_t)&huart7.Instance->DR,strlen(msg));
huart7.Instance->CR3|=USART_CR3_DMAT;
HAL_DMA_PollForTransfer(&hdma_uart7_tx,HAL_DMA_FULL_TRANSFER,HAL_MAX_DELAY);
huart7.Instance->CR3&=~USART_CR3_DMAT;
HAL_GPIO_TogglePin(LD_RED_GPIO_Port,LD_RED_Pin);
HAL_Delay(200);
HAL_GPIO_TogglePin(LD_RED_GPIO_Port,LD_RED_Pin);
}
}
/* USER CODE END 4 */

/**
* @brief This function is executed in case of error occurrence.
* @retval None
*/
void Error_Handler(void)
{
/* USER CODE BEGIN Error_Handler_Debug */
/* User can add his own implementation to report the HAL error return state */

/* USER CODE END Error_Handler_Debug */
}

#ifdef USE_FULL_ASSERT
/**
* @brief Reports the name of the source file and the source line number
* where the assert_param error has occurred.
* @param file: pointer to the source file name
* @param line: assert_param error line source number
* @retval None
*/
void assert_failed(uint8_t *file, uint32_t line)
{
/* USER CODE BEGIN 6 */
/* User can add his own implementation to report the file name and line number,
tex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
/* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT */

/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

  • DMA泛用方法 Interrupt
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
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
/* USER CODE BEGIN Header */
/**
******************************************************************************
* @file : main.c
* @brief : Main program body
******************************************************************************
* @attention
*
* <h2><center>&copy; Copyright (c) 2020 STMicroelectronics.
* All rights reserved.</center></h2>
*
* This software component is licensed by ST under BSD 3-Clause license,
* the "License"; You may not use this file except in compliance with the
* License. You may obtain a copy of the License at:
* opensource.org/licenses/BSD-3-Clause
*
******************************************************************************
*/
/* USER CODE END Header */

/* Includes ------------------------------------------------------------------*/
#include "main.h"

/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "string.h"
/* USER CODE END Includes */

/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */

/* USER CODE END PTD */

/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
/* USER CODE END PD */

/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */

/* USER CODE END PM */

/* Private variables ---------------------------------------------------------*/
UART_HandleTypeDef huart7;
DMA_HandleTypeDef hdma_uart7_tx;

/* USER CODE BEGIN PV */

/* USER CODE END PV */

/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_DMA_Init(void);
static void MX_UART7_Init(void);
/* USER CODE BEGIN PFP */

/* USER CODE END PFP */

/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
char msg[]="\r\n"
" %@@@@@@@#\r\n"
" .(&@&, &@@@@@@@% *@@&(\r\n"
" %@@@@@@@@%%&@@@@@@@@@@@@@@@@@@@&%&@@@@@@@@#\r\n"
" &@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@%\r\n"
" #@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@/\r\n"
" ,. .&@@@@@@@@@@@@@&(. ,(&@@@@@@@@@@@@@&. .,\r\n"
" &@@@@&@@@@@@@@@@@&, ###%#%%%%#%%%#### *&@@@@@@@@@@@&@@@@%\r\n"
" /@@@@@@@@@@@@@@@& ,@@@@@@@@&. .&@@@@@@@@@@@@@@@,\r\n"
" (&@@@@@@@@@@@@@# (@@@@@@@/ %@@@@@@@@@@@@@&*\r\n"
" &@@@@@@@@&. ,%@@@@&@@@@@@@&@@@&%, ,&@@@@@@@@%\r\n"
" /@@@@@@@@% #@@@@@( *@@@@@@&, %@@@@&( &@@@@@@@@/\r\n"
" .&@@@@@@@% #@@@@@% *@@@@@@&, &@@@@@# &@@@@@@@&. # \"There is no truth in flesh, only betrayal.\"\r\n"
" ,%%%%&@@@@@@@@* &@@@@@% *@@@@@@&, %@@@@@% ,@@@@@@@@&%%%% # \"There is no strength in flesh, only weakness.\"\r\n"
" /@@@@@@@@@@@@&. #@@@@@@, *@@@@@@&, ,@@@@@@( .&@@@@@@@@@@@&, # \"There is no constancy in flesh, only decay .\"\r\n"
" /@@@@@@@@@@@@& %@@@@@@, *@@@@@@&, ,@@@@@@# .&@@@@@@@@@@@&, # \"There is no certainty in flesh, but death .\"\r\n"
" *&@@@@@@@@@@@&, .@@@@@@# *@@@@@@&, %@@@@@& ,@@@@@@@@@@@@&. # — Credo Omnissiah\r\n"
" .&@@@@@@@# .&@@@@@( *@@@@@@&, %@@@@@& %@@@@@@@&.\r\n"
" (@@@@@@@@( ,&@@@@&. *@@@@@@&, *&@@@@%. #@@@@@@@@( Welcome back to Adeptus Mechanicus, Alchemic Ronin!\r\n"
" %@@@@@@@@% .%@@@@&%@@@@@@@%&@@@@#. %@@@@@@@@%\r\n"
" .(&@@@@@@@@@@@@, *%@@@@@@@%* (@@@@@@@@@@@@&/\r\n"
" %@@@@@@@@@@@@@@@/ .(@@@@@@@@@(. #@@@@@@@@@@@@@@@#\r\n"
" .&@@@@@@@@@@@@@@@@( ,***************, #&@@@@@@@@@@@@@@@&.\r\n"
" %( #@@@@@@@@@@@@@%*. ./&@@@@@@@@@@@@@/ .##\r\n"
" .&@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@%.\r\n"
" #@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@(\r\n"
" &@@@@@@@@@&@@@@@@@@@@@@@@@@@@@@@&@@@@@@@@@%\r\n"
" /&@@@/ .*&@@@@@@@&,. (@@@&/\r\n"
" %@@@@@@@#\r\n"
" .,,,,,,,.\r\n"
"\r\n";
/* 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_DMA_Init();
MX_UART7_Init();
/* USER CODE BEGIN 2 */
HAL_GPIO_WritePin(LD_RED_GPIO_Port,LD_RED_Pin,GPIO_PIN_SET);
/* USER CODE END 2 */

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

/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
}

/**
* @brief System Clock Configuration
* @retval None
*/
void SystemClock_Config(void)
{
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};

/** Configure the main internal regulator output voltage
*/
__HAL_RCC_PWR_CLK_ENABLE();
__HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE3);
/** Initializes the CPU, AHB and APB busses clocks
*/
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
RCC_OscInitStruct.HSIState = RCC_HSI_ON;
RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE;
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
{
Error_Handler();
}
/** Initializes the CPU, AHB and APB busses clocks
*/
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
|RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_HSI;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;

if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_0) != HAL_OK)
{
Error_Handler();
}
}

/**
* @brief UART7 Initialization Function
* @param None
* @retval None
*/
static void MX_UART7_Init(void)
{

/* USER CODE BEGIN UART7_Init 0 */

/* USER CODE END UART7_Init 0 */

/* USER CODE BEGIN UART7_Init 1 */

/* USER CODE END UART7_Init 1 */
huart7.Instance = UART7;
huart7.Init.BaudRate = 115200;
huart7.Init.WordLength = UART_WORDLENGTH_8B;
huart7.Init.StopBits = UART_STOPBITS_1;
huart7.Init.Parity = UART_PARITY_NONE;
huart7.Init.Mode = UART_MODE_TX_RX;
huart7.Init.HwFlowCtl = UART_HWCONTROL_NONE;
huart7.Init.OverSampling = UART_OVERSAMPLING_16;
if (HAL_UART_Init(&huart7) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN UART7_Init 2 */

/* USER CODE END UART7_Init 2 */

}

/**
* Enable DMA controller clock
*/
static void MX_DMA_Init(void)
{

/* DMA controller clock enable */
__HAL_RCC_DMA1_CLK_ENABLE();

/* DMA interrupt init */
/* DMA1_Stream1_IRQn interrupt configuration */
HAL_NVIC_SetPriority(DMA1_Stream1_IRQn, 1, 0);
HAL_NVIC_EnableIRQ(DMA1_Stream1_IRQn);

}

/**
* @brief GPIO Initialization Function
* @param None
* @retval None
*/
static void MX_GPIO_Init(void)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};

/* GPIO Ports Clock Enable */
__HAL_RCC_GPIOB_CLK_ENABLE();
__HAL_RCC_GPIOE_CLK_ENABLE();

/*Configure GPIO pin Output Level */
HAL_GPIO_WritePin(LD_RED_GPIO_Port, LD_RED_Pin, GPIO_PIN_RESET);

/*Configure GPIO pin : Button_Pin */
GPIO_InitStruct.Pin = Button_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_IT_RISING;
GPIO_InitStruct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(Button_GPIO_Port, &GPIO_InitStruct);

/*Configure GPIO pin : LD_RED_Pin */
GPIO_InitStruct.Pin = LD_RED_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(LD_RED_GPIO_Port, &GPIO_InitStruct);

/* EXTI interrupt init*/
HAL_NVIC_SetPriority(EXTI2_IRQn, 1, 0);
HAL_NVIC_EnableIRQ(EXTI2_IRQn);

}

/* USER CODE BEGIN 4 */
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin){
if(GPIO_Pin == Button_Pin){
HAL_Delay(500);
HAL_DMA_Start_IT(&hdma_uart7_tx,(uint32_t)msg,(uint32_t)&huart7.Instance->DR,strlen(msg));
huart7.Instance->CR3|=USART_CR3_DMAT;
}
}

void XferCpltCallback(DMA_HandleTypeDef *hdma){
if(hdma->Instance == DMA1_Stream1){
huart7.Instance->CR3&=~USART_CR3_DMAT;
HAL_GPIO_TogglePin(LD_RED_GPIO_Port,LD_RED_Pin);
HAL_Delay(200);
HAL_GPIO_TogglePin(LD_RED_GPIO_Port,LD_RED_Pin);
}
}
/* USER CODE END 4 */

/**
* @brief This function is executed in case of error occurrence.
* @retval None
*/
void Error_Handler(void)
{
/* USER CODE BEGIN Error_Handler_Debug */
/* User can add his own implementation to report the HAL error return state */

/* USER CODE END Error_Handler_Debug */
}

#ifdef USE_FULL_ASSERT
/**
* @brief Reports the name of the source file and the source line number
* where the assert_param error has occurred.
* @param file: pointer to the source file name
* @param line: assert_param error line source number
* @retval None
*/
void assert_failed(uint8_t *file, uint32_t line)
{
/* USER CODE BEGIN 6 */
/* User can add his own implementation to report the file name and line number,
tex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
/* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT */

/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

  • UART特化方法
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
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
/* USER CODE BEGIN Header */
/**
******************************************************************************
* @file : main.c
* @brief : Main program body
******************************************************************************
* @attention
*
* <h2><center>&copy; Copyright (c) 2020 STMicroelectronics.
* All rights reserved.</center></h2>
*
* This software component is licensed by ST under BSD 3-Clause license,
* the "License"; You may not use this file except in compliance with the
* License. You may obtain a copy of the License at:
* opensource.org/licenses/BSD-3-Clause
*
******************************************************************************
*/
/* USER CODE END Header */

/* Includes ------------------------------------------------------------------*/
#include "main.h"

/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "string.h"
/* USER CODE END Includes */

/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */

/* USER CODE END PTD */

/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
/* USER CODE END PD */

/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */

/* USER CODE END PM */

/* Private variables ---------------------------------------------------------*/
UART_HandleTypeDef huart7;
DMA_HandleTypeDef hdma_uart7_tx;

/* USER CODE BEGIN PV */

/* USER CODE END PV */

/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_DMA_Init(void);
static void MX_UART7_Init(void);
/* USER CODE BEGIN PFP */

/* USER CODE END PFP */

/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
char msg[]="\r\n"
" %@@@@@@@#\r\n"
" .(&@&, &@@@@@@@% *@@&(\r\n"
" %@@@@@@@@%%&@@@@@@@@@@@@@@@@@@@&%&@@@@@@@@#\r\n"
" &@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@%\r\n"
" #@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@/\r\n"
" ,. .&@@@@@@@@@@@@@&(. ,(&@@@@@@@@@@@@@&. .,\r\n"
" &@@@@&@@@@@@@@@@@&, ###%#%%%%#%%%#### *&@@@@@@@@@@@&@@@@%\r\n"
" /@@@@@@@@@@@@@@@& ,@@@@@@@@&. .&@@@@@@@@@@@@@@@,\r\n"
" (&@@@@@@@@@@@@@# (@@@@@@@/ %@@@@@@@@@@@@@&*\r\n"
" &@@@@@@@@&. ,%@@@@&@@@@@@@&@@@&%, ,&@@@@@@@@%\r\n"
" /@@@@@@@@% #@@@@@( *@@@@@@&, %@@@@&( &@@@@@@@@/\r\n"
" .&@@@@@@@% #@@@@@% *@@@@@@&, &@@@@@# &@@@@@@@&. # \"There is no truth in flesh, only betrayal.\"\r\n"
" ,%%%%&@@@@@@@@* &@@@@@% *@@@@@@&, %@@@@@% ,@@@@@@@@&%%%% # \"There is no strength in flesh, only weakness.\"\r\n"
" /@@@@@@@@@@@@&. #@@@@@@, *@@@@@@&, ,@@@@@@( .&@@@@@@@@@@@&, # \"There is no constancy in flesh, only decay .\"\r\n"
" /@@@@@@@@@@@@& %@@@@@@, *@@@@@@&, ,@@@@@@# .&@@@@@@@@@@@&, # \"There is no certainty in flesh, but death .\"\r\n"
" *&@@@@@@@@@@@&, .@@@@@@# *@@@@@@&, %@@@@@& ,@@@@@@@@@@@@&. # — Credo Omnissiah\r\n"
" .&@@@@@@@# .&@@@@@( *@@@@@@&, %@@@@@& %@@@@@@@&.\r\n"
" (@@@@@@@@( ,&@@@@&. *@@@@@@&, *&@@@@%. #@@@@@@@@( Welcome back to Adeptus Mechanicus, Alchemic Ronin!\r\n"
" %@@@@@@@@% .%@@@@&%@@@@@@@%&@@@@#. %@@@@@@@@%\r\n"
" .(&@@@@@@@@@@@@, *%@@@@@@@%* (@@@@@@@@@@@@&/\r\n"
" %@@@@@@@@@@@@@@@/ .(@@@@@@@@@(. #@@@@@@@@@@@@@@@#\r\n"
" .&@@@@@@@@@@@@@@@@( ,***************, #&@@@@@@@@@@@@@@@&.\r\n"
" %( #@@@@@@@@@@@@@%*. ./&@@@@@@@@@@@@@/ .##\r\n"
" .&@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@%.\r\n"
" #@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@(\r\n"
" &@@@@@@@@@&@@@@@@@@@@@@@@@@@@@@@&@@@@@@@@@%\r\n"
" /&@@@/ .*&@@@@@@@&,. (@@@&/\r\n"
" %@@@@@@@#\r\n"
" .,,,,,,,.\r\n"
"\r\n";
/* 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_DMA_Init();
MX_UART7_Init();
/* USER CODE BEGIN 2 */
HAL_GPIO_WritePin(LD_RED_GPIO_Port,LD_RED_Pin,GPIO_PIN_SET);
/* USER CODE END 2 */

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

/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
}

/**
* @brief System Clock Configuration
* @retval None
*/
void SystemClock_Config(void)
{
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};

/** Configure the main internal regulator output voltage
*/
__HAL_RCC_PWR_CLK_ENABLE();
__HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE3);
/** Initializes the CPU, AHB and APB busses clocks
*/
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
RCC_OscInitStruct.HSIState = RCC_HSI_ON;
RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE;
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
{
Error_Handler();
}
/** Initializes the CPU, AHB and APB busses clocks
*/
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
|RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_HSI;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;

if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_0) != HAL_OK)
{
Error_Handler();
}
}

/**
* @brief UART7 Initialization Function
* @param None
* @retval None
*/
static void MX_UART7_Init(void)
{

/* USER CODE BEGIN UART7_Init 0 */

/* USER CODE END UART7_Init 0 */

/* USER CODE BEGIN UART7_Init 1 */

/* USER CODE END UART7_Init 1 */
huart7.Instance = UART7;
huart7.Init.BaudRate = 115200;
huart7.Init.WordLength = UART_WORDLENGTH_8B;
huart7.Init.StopBits = UART_STOPBITS_1;
huart7.Init.Parity = UART_PARITY_NONE;
huart7.Init.Mode = UART_MODE_TX_RX;
huart7.Init.HwFlowCtl = UART_HWCONTROL_NONE;
huart7.Init.OverSampling = UART_OVERSAMPLING_16;
if (HAL_UART_Init(&huart7) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN UART7_Init 2 */

/* USER CODE END UART7_Init 2 */

}

/**
* Enable DMA controller clock
*/
static void MX_DMA_Init(void)
{

/* DMA controller clock enable */
__HAL_RCC_DMA1_CLK_ENABLE();

/* DMA interrupt init */
/* DMA1_Stream1_IRQn interrupt configuration */
HAL_NVIC_SetPriority(DMA1_Stream1_IRQn, 1, 0);
HAL_NVIC_EnableIRQ(DMA1_Stream1_IRQn);

}

/**
* @brief GPIO Initialization Function
* @param None
* @retval None
*/
static void MX_GPIO_Init(void)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};

/* GPIO Ports Clock Enable */
__HAL_RCC_GPIOB_CLK_ENABLE();
__HAL_RCC_GPIOE_CLK_ENABLE();

/*Configure GPIO pin Output Level */
HAL_GPIO_WritePin(LD_RED_GPIO_Port, LD_RED_Pin, GPIO_PIN_RESET);

/*Configure GPIO pin : Button_Pin */
GPIO_InitStruct.Pin = Button_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_IT_RISING;
GPIO_InitStruct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(Button_GPIO_Port, &GPIO_InitStruct);

/*Configure GPIO pin : LD_RED_Pin */
GPIO_InitStruct.Pin = LD_RED_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(LD_RED_GPIO_Port, &GPIO_InitStruct);

/* EXTI interrupt init*/
HAL_NVIC_SetPriority(EXTI2_IRQn, 1, 0);
HAL_NVIC_EnableIRQ(EXTI2_IRQn);

}

/* USER CODE BEGIN 4 */
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin){
if(GPIO_Pin == Button_Pin){
HAL_Delay(500);
HAL_UART_Transmit_DMA(&huart7,(uint8_t*)msg,strlen(msg));
}
}

void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart){
HAL_GPIO_TogglePin(LD_RED_GPIO_Port,LD_RED_Pin);
HAL_Delay(200);
HAL_GPIO_TogglePin(LD_RED_GPIO_Port,LD_RED_Pin);
}
/* USER CODE END 4 */

/**
* @brief This function is executed in case of error occurrence.
* @retval None
*/
void Error_Handler(void)
{
/* USER CODE BEGIN Error_Handler_Debug */
/* User can add his own implementation to report the HAL error return state */

/* USER CODE END Error_Handler_Debug */
}

#ifdef USE_FULL_ASSERT
/**
* @brief Reports the name of the source file and the source line number
* where the assert_param error has occurred.
* @param file: pointer to the source file name
* @param line: assert_param error line source number
* @retval None
*/
void assert_failed(uint8_t *file, uint32_t line)
{
/* USER CODE BEGIN 6 */
/* User can add his own implementation to report the file name and line number,
tex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
/* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT */

/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

4.2.2 键盘回响

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
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
/* USER CODE BEGIN Header */
/**
******************************************************************************
* @file : main.c
* @brief : Main program body
******************************************************************************
* @attention
*
* <h2><center>&copy; Copyright (c) 2020 STMicroelectronics.
* All rights reserved.</center></h2>
*
* This software component is licensed by ST under BSD 3-Clause license,
* the "License"; You may not use this file except in compliance with the
* License. You may obtain a copy of the License at:
* opensource.org/licenses/BSD-3-Clause
*
******************************************************************************
*/
/* USER CODE END Header */

/* Includes ------------------------------------------------------------------*/
#include "main.h"

/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "string.h"
#include "stdbool.h"
/* USER CODE END Includes */

/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */

/* USER CODE END PTD */

/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
/* USER CODE END PD */

/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */

/* USER CODE END PM */

/* Private variables ---------------------------------------------------------*/
UART_HandleTypeDef huart7;
DMA_HandleTypeDef hdma_uart7_rx;
DMA_HandleTypeDef hdma_uart7_tx;

/* USER CODE BEGIN PV */

/* USER CODE END PV */

/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_DMA_Init(void);
static void MX_UART7_Init(void);
/* USER CODE BEGIN PFP */

/* USER CODE END PFP */

/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
char msg[]="\r\n"
" %@@@@@@@#\r\n"
" .(&@&, &@@@@@@@% *@@&(\r\n"
" %@@@@@@@@%%&@@@@@@@@@@@@@@@@@@@&%&@@@@@@@@#\r\n"
" &@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@%\r\n"
" #@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@/\r\n"
" ,. .&@@@@@@@@@@@@@&(. ,(&@@@@@@@@@@@@@&. .,\r\n"
" &@@@@&@@@@@@@@@@@&, ###%#%%%%#%%%#### *&@@@@@@@@@@@&@@@@%\r\n"
" /@@@@@@@@@@@@@@@& ,@@@@@@@@&. .&@@@@@@@@@@@@@@@,\r\n"
" (&@@@@@@@@@@@@@# (@@@@@@@/ %@@@@@@@@@@@@@&*\r\n"
" &@@@@@@@@&. ,%@@@@&@@@@@@@&@@@&%, ,&@@@@@@@@%\r\n"
" /@@@@@@@@% #@@@@@( *@@@@@@&, %@@@@&( &@@@@@@@@/\r\n"
" .&@@@@@@@% #@@@@@% *@@@@@@&, &@@@@@# &@@@@@@@&. # \"There is no truth in flesh, only betrayal.\"\r\n"
" ,%%%%&@@@@@@@@* &@@@@@% *@@@@@@&, %@@@@@% ,@@@@@@@@&%%%% # \"There is no strength in flesh, only weakness.\"\r\n"
" /@@@@@@@@@@@@&. #@@@@@@, *@@@@@@&, ,@@@@@@( .&@@@@@@@@@@@&, # \"There is no constancy in flesh, only decay .\"\r\n"
" /@@@@@@@@@@@@& %@@@@@@, *@@@@@@&, ,@@@@@@# .&@@@@@@@@@@@&, # \"There is no certainty in flesh, but death .\"\r\n"
" *&@@@@@@@@@@@&, .@@@@@@# *@@@@@@&, %@@@@@& ,@@@@@@@@@@@@&. # — Credo Omnissiah\r\n"
" .&@@@@@@@# .&@@@@@( *@@@@@@&, %@@@@@& %@@@@@@@&.\r\n"
" (@@@@@@@@( ,&@@@@&. *@@@@@@&, *&@@@@%. #@@@@@@@@( Welcome back to Adeptus Mechanicus, Alchemic Ronin!\r\n"
" %@@@@@@@@% .%@@@@&%@@@@@@@%&@@@@#. %@@@@@@@@%\r\n"
" .(&@@@@@@@@@@@@, *%@@@@@@@%* (@@@@@@@@@@@@&/\r\n"
" %@@@@@@@@@@@@@@@/ .(@@@@@@@@@(. #@@@@@@@@@@@@@@@#\r\n"
" .&@@@@@@@@@@@@@@@@( ,***************, #&@@@@@@@@@@@@@@@&.\r\n"
" %( #@@@@@@@@@@@@@%*. ./&@@@@@@@@@@@@@/ .##\r\n"
" .&@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@%.\r\n"
" #@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@(\r\n"
" &@@@@@@@@@&@@@@@@@@@@@@@@@@@@@@@&@@@@@@@@@%\r\n"
" /&@@@/ .*&@@@@@@@&,. (@@@&/\r\n"
" %@@@@@@@#\r\n"
" .,,,,,,,.\r\n"
"\r\n";
uint8_t data[1];
bool flag=false;
/* 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_DMA_Init();
MX_UART7_Init();
/* USER CODE BEGIN 2 */
HAL_GPIO_WritePin(LD_RED_GPIO_Port,LD_RED_Pin,GPIO_PIN_SET);
HAL_GPIO_WritePin(LD_GREEN_GPIO_Port,LD_GREEN_Pin,GPIO_PIN_SET);
HAL_UART_Receive_DMA(&huart7,data,1);
/* USER CODE END 2 */

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

/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
}

/**
* @brief System Clock Configuration
* @retval None
*/
void SystemClock_Config(void)
{
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};

/** Configure the main internal regulator output voltage
*/
__HAL_RCC_PWR_CLK_ENABLE();
__HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE3);
/** Initializes the CPU, AHB and APB busses clocks
*/
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
RCC_OscInitStruct.HSIState = RCC_HSI_ON;
RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE;
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
{
Error_Handler();
}
/** Initializes the CPU, AHB and APB busses clocks
*/
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
|RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_HSI;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;

if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_0) != HAL_OK)
{
Error_Handler();
}
}

/**
* @brief UART7 Initialization Function
* @param None
* @retval None
*/
static void MX_UART7_Init(void)
{

/* USER CODE BEGIN UART7_Init 0 */

/* USER CODE END UART7_Init 0 */

/* USER CODE BEGIN UART7_Init 1 */

/* USER CODE END UART7_Init 1 */
huart7.Instance = UART7;
huart7.Init.BaudRate = 115200;
huart7.Init.WordLength = UART_WORDLENGTH_8B;
huart7.Init.StopBits = UART_STOPBITS_1;
huart7.Init.Parity = UART_PARITY_NONE;
huart7.Init.Mode = UART_MODE_TX_RX;
huart7.Init.HwFlowCtl = UART_HWCONTROL_NONE;
huart7.Init.OverSampling = UART_OVERSAMPLING_16;
if (HAL_UART_Init(&huart7) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN UART7_Init 2 */

/* USER CODE END UART7_Init 2 */

}

/**
* Enable DMA controller clock
*/
static void MX_DMA_Init(void)
{

/* DMA controller clock enable */
__HAL_RCC_DMA1_CLK_ENABLE();

/* DMA interrupt init */
/* DMA1_Stream1_IRQn interrupt configuration */
HAL_NVIC_SetPriority(DMA1_Stream1_IRQn, 1, 0);
HAL_NVIC_EnableIRQ(DMA1_Stream1_IRQn);
/* DMA1_Stream3_IRQn interrupt configuration */
HAL_NVIC_SetPriority(DMA1_Stream3_IRQn, 1, 0);
HAL_NVIC_EnableIRQ(DMA1_Stream3_IRQn);

}

/**
* @brief GPIO Initialization Function
* @param None
* @retval None
*/
static void MX_GPIO_Init(void)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};

/* GPIO Ports Clock Enable */
__HAL_RCC_GPIOB_CLK_ENABLE();
__HAL_RCC_GPIOE_CLK_ENABLE();
__HAL_RCC_GPIOF_CLK_ENABLE();

/*Configure GPIO pin Output Level */
HAL_GPIO_WritePin(LD_RED_GPIO_Port, LD_RED_Pin, GPIO_PIN_RESET);

/*Configure GPIO pin Output Level */
HAL_GPIO_WritePin(LD_GREEN_GPIO_Port, LD_GREEN_Pin, GPIO_PIN_RESET);

/*Configure GPIO pin : Button_Pin */
GPIO_InitStruct.Pin = Button_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_IT_RISING;
GPIO_InitStruct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(Button_GPIO_Port, &GPIO_InitStruct);

/*Configure GPIO pin : LD_RED_Pin */
GPIO_InitStruct.Pin = LD_RED_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(LD_RED_GPIO_Port, &GPIO_InitStruct);

/*Configure GPIO pin : LD_GREEN_Pin */
GPIO_InitStruct.Pin = LD_GREEN_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(LD_GREEN_GPIO_Port, &GPIO_InitStruct);

/* EXTI interrupt init*/
HAL_NVIC_SetPriority(EXTI2_IRQn, 1, 0);
HAL_NVIC_EnableIRQ(EXTI2_IRQn);

}

/* USER CODE BEGIN 4 */
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin){
if(GPIO_Pin == Button_Pin){
HAL_Delay(500);
flag=true;
HAL_UART_Transmit_DMA(&huart7,(uint8_t*)msg,strlen(msg));
}
}

void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart){
if(flag==true){
flag=false;
HAL_GPIO_TogglePin(LD_RED_GPIO_Port,LD_RED_Pin);
HAL_Delay(200);
HAL_GPIO_TogglePin(LD_RED_GPIO_Port,LD_RED_Pin);
}else{
HAL_GPIO_TogglePin(LD_GREEN_GPIO_Port, LD_GREEN_Pin);
HAL_Delay(200);
HAL_GPIO_TogglePin(LD_GREEN_GPIO_Port, LD_GREEN_Pin);
}
}

void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart){
HAL_UART_Transmit_DMA(&huart7,data,1);
HAL_UART_Receive_DMA(&huart7,data,1);
}
/* USER CODE END 4 */

/**
* @brief This function is executed in case of error occurrence.
* @retval None
*/
void Error_Handler(void)
{
/* USER CODE BEGIN Error_Handler_Debug */
/* User can add his own implementation to report the HAL error return state */

/* USER CODE END Error_Handler_Debug */
}

#ifdef USE_FULL_ASSERT
/**
* @brief Reports the name of the source file and the source line number
* where the assert_param error has occurred.
* @param file: pointer to the source file name
* @param line: assert_param error line source number
* @retval None
*/
void assert_failed(uint8_t *file, uint32_t line)
{
/* USER CODE BEGIN 6 */
/* User can add his own implementation to report the file name and line number,
tex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
/* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT */

/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

4.3 效果展示

  • 因为按键回响已经包含了一键发送信息的功能,所以视频部分就只录了按键回响的效果

本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!