概述
本篇文章主要介紹如何使用STM32CubeMX移植到雅特力AT32F403AVGT7,并通過雙串口輸出打印。
直接存儲器訪問(DMA)用于在外設與存儲器之間以及存儲器與存儲器之間提供高速數據傳輸。可以在無需任何CPU操作的情況下通過DMA快速傳輸傳輸。這樣節省的CPU資源可供其它操作使用。
DMA允許在后臺執行數據傳輸,無需Cortex-M3處理器干預。在此操作過程中,主處理器可以執行其它任務,僅當整個數據塊需要處理時,才會中斷主處理器。這樣即使傳輸大量數據也不會對系統性能造成太大影響。
DMA主要用于為不同的外設模塊實現集中數據緩沖存儲(通常在系統SRAM中)。與分布式解決方案(其中每個外設都需要實現自己的本地數據存儲)相比,DMA解決方案在硅片成本和功耗方面的成本較低。
根據使用的產品型號的不同,有一個或兩個DMA模塊。
本篇文章主要介紹如何使用STM32CubeMX實現串口DMA讀取,并且打印出去。
硬件準備
首先需要準備一個開發板,這里我準備的是雅特力AT32F403AVGT7的開發板:
選擇芯片型號
雅特力AT32F403AVGT7兼容STM32F103系列,故選取STM32f103VG進行開發。
配置時鐘源
HSE與LSE分別為外部高速時鐘和低速時鐘,在本文中使用內置的時鐘源,故都選擇Disable選項,如下所示:
配置時鐘樹
雅特力AT32F403AVGT7最高頻率到240M,但是STM32F1的最高主頻到72M,同時使用不使用外部晶振時候,最高速度只能到64M,所以配置64即可:
串口配置
本次實驗使用的串口2,串口3進行串口通信,波特率配置為115200。
配置DMA
在DMA 設置中,Mode有兩種模式,一種是普通模式(Normal),使用一次發送語句就發一次,另一種是循環模式(Circula),使用一次發送會一直發送。這里接收選擇循環模式。
中斷
在中斷設置里打開串口2,3的中斷。
生成工程設置
注意在生產工程設置中不能出現中文,不然會報錯。
代碼生成設置
最后設置生成獨立的初始化文件
生成代碼
代碼編寫
在main.c中,添加頭文件,若不添加會出現 identifier "FILE" is undefined報錯。
/* USER CODE BEGIN Includes */
#include "stdio.h"
/* USER CODE END Includes */
變量定義 ,在main.c中添加。
/* USER CODE BEGIN PV */
#define BUFFERSIZE_usart2 1000 //可以接收的最大字符個數
uint8_t ReceiveBuff_usart2[BUFFERSIZE_usart2]; //接收緩沖區
uint8_t recv_end_flag_usart2 = 0,Rx_len_usart2;//接收完成中斷標志,接收到字符長度
#define BUFFERSIZE_usart3 1000 //可以接收的最大字符個數
uint8_t ReceiveBuff_usart3[BUFFERSIZE_usart3]; //接收緩沖區
uint8_t recv_end_flag_usart3 = 0,Rx_len_usart3;//接收完成中斷標志,接收到字符長度
int f1_u1 = 0;
/* USER CODE END PV */
函數聲明和串口重定向,這里使用串口3進行打印,在main.c中添加。
/* USER CODE BEGIN PFP */
void uart2_data(void); //接收函數
void uart3_data(void); //接收函數
#ifdef __GNUC__ //串口重定向
#define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
#else
#define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
#endif
PUTCHAR_PROTOTYPE
{
HAL_UART_Transmit(&huart3 , (uint8_t *)&ch, 1, 0xFFFF);
return ch;
}
/* USER CODE END PFP */
開啟串口IDLE中斷,在main.c中添加。
/* USER CODE BEGIN 2 */
__HAL_UART_ENABLE_IT(&huart2, UART_IT_IDLE);//使能串口2 IDLE中斷
__HAL_UART_ENABLE_IT(&huart3, UART_IT_IDLE);//使能串口2 IDLE中斷
printf("雙串口DMA接收例程
");
/* USER CODE END 2 *
串口DMA獲取,在main.c中添加。
void uart2_data(void)
{
if(recv_end_flag_usart2 ==1)//接收完成標志
{
printf("串口2數據長度=%d
",Rx_len_usart2);//打印接收到的數據長度
printf("串口2數據內容:");
for(int i=0;iprintf("%c",ReceiveBuff_usart2[i]);//向串口打印接收到的數據
}
printf("
");
for(int i = 0; i < Rx_len_usart2 ; i++) //清空接收緩存區
ReceiveBuff_usart2[i]=0;//置0
Rx_len_usart2=0;//接收數據長度清零
recv_end_flag_usart2=0;//接收標志位清零
}
//開啟下一次接收
HAL_UART_Receive_DMA(&huart2,(uint8_t*)ReceiveBuff_usart2,BUFFERSIZE_usart2);
}
void uart3_data(void)
{
if(recv_end_flag_usart3 ==1)//接收完成標志
{
printf("串口3數據長度=%d
",Rx_len_usart3);//打印接收到的數據長度
printf("串口3數據內容:");
for(int i=0;iprintf("%c",ReceiveBuff_usart3[i]);//向串口打印接收到的數據
}
printf("
");
for(int i = 0; i < Rx_len_usart3 ; i++) //清空接收緩存區
ReceiveBuff_usart3[i]=0;//置0
Rx_len_usart3=0;//接收數據長度清零
recv_end_flag_usart3=0;//接收標志位清零
}
//開啟下一次接收
HAL_UART_Receive_DMA(&huart3,(uint8_t*)ReceiveBuff_usart3,BUFFERSIZE_usart3);
}
主循環,在main.c中添加。
/* USER CODE BEGIN WHILE */
while (1)
{
/* USER CODE END WHILE */
uart2_data();
uart3_data();
/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 *
中斷外部變量引用,在stm32f0xx_it.c中添加。
/* USER CODE BEGIN 0 */
#define BUFFERSIZE_usart2 255 //可接收的最大數據量
extern uint8_t recv_end_flag_usart2,Rx_len_usart2;
#define BUFFERSIZE_usart3 255 //可接收的最大數據量
extern uint8_t recv_end_flag_usart3,Rx_len_usart3;
/* USER CODE END 0 */
串口2,3中斷函數,在stm32f0xx_it.c中添加。
/**
* @brief This function handles USART2 global interrupt.
*/
void USART2_IRQHandler(void)
{
/* USER CODE BEGIN USART2_IRQn 0 */
/* USER CODE END USART2_IRQn 0 */
HAL_UART_IRQHandler(&huart2);
/* USER CODE BEGIN USART2_IRQn 1 */
uint32_t temp_usart2;
if(USART2 == huart2.Instance)//判斷是否為串口2中斷
{
if(RESET != __HAL_UART_GET_FLAG(&huart2,UART_FLAG_IDLE))//如果為串口2
{
__HAL_UART_CLEAR_IDLEFLAG(&huart2);//清除中斷標志
HAL_UART_DMAStop(&huart2);//停止DMA接收
temp_usart2 = __HAL_DMA_GET_COUNTER(&hdma_usart2_rx);//獲取DMA當前還有多少未填充
Rx_len_usart2 = BUFFERSIZE_usart2 - temp_usart2; //計算串口接收到的數據個數
recv_end_flag_usart2 = 1;
}
}
/* USER CODE END USART2_IRQn 1 */
}
/**
* @brief This function handles USART3 global interrupt.
*/
void USART3_IRQHandler(void)
{
/* USER CODE BEGIN USART3_IRQn 0 */
/* USER CODE END USART3_IRQn 0 */
HAL_UART_IRQHandler(&huart3);
/* USER CODE BEGIN USART3_IRQn 1 */
uint32_t temp_usart3;
if(USART3 == huart3.Instance)//判斷是否為串口3中斷
{
if(RESET != __HAL_UART_GET_FLAG(&huart3,UART_FLAG_IDLE))//如果為串口3
{
__HAL_UART_CLEAR_IDLEFLAG(&huart3);//清除中斷標志
HAL_UART_DMAStop(&huart3);//停止DMA接收
temp_usart3 = __HAL_DMA_GET_COUNTER(&hdma_usart3_rx);//獲取DMA當前還有多少未填充
Rx_len_usart3 = BUFFERSIZE_usart3 - temp_usart3; //計算串口接收到的數據個數
recv_end_flag_usart3 = 1;
}
}
/* USER CODE END USART3_IRQn 1 */
}
結果演示
開機會顯示雙串口DMA接收例程。
串口2發送數據會在串口3中打印,但是會顯示接收的是串口2。
串口3發送數據會在串口3中打印,但是會顯示接收的是串口3。
審核編輯:湯梓紅
-
dma
+關注
關注
3文章
561瀏覽量
100623 -
stm32cubemx
+關注
關注
5文章
283瀏覽量
14824 -
雅特力
+關注
關注
0文章
158瀏覽量
8052
發布評論請先 登錄
相關推薦
評論