实验器材:STM32 F411RET6开发版
任务目标:利用空闲中断和DMA实现不定长数据的接收
任务内容:PC发送任意唱的数据到Nucleo开发板,开发板将数据原样回传到PC
一、CubeMX配置
关于CubeMX配置参考http://t.csdn.cn/gGp3x,相同设置部分不再赘述
3.3 Connectivity 配置
在NVIC Settings下勾选“USART2 global interrupt”
在DMA Settings下设置如下
二 Cube IDE程序编写
关于Cube IDE中添加头文件及串口重定向同http://t.csdn.cn/gGp3x中1/6完全一致
1. 进行宏定义
/* USER CODE BEGIN PD */
#ifdef __GNUC__
#define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
#define GETCHAR_PROTOTYPE int __io_getchar(FILE *f)
#else
#define PUTCHAR_PROTOTYPE int fputc(int ch,FILE *f)
#define GETCHAR_PROTOTYPE int fgetc(FILE *f)
#endif
#define LENGTH 100 //数据缓冲区大小,该数据一定要大于一帧数据的总字符数
/* USER CODE END PD */
2.定义自变量
/* USER CODE BEGIN PV */
extern DMA_HandleTypeDef hdma_usart2_rx;
extern DMA_HandleTypeDef hdma_usart2_tx;
extern UART_HandleTypeDef huart2;
uint8_t RxBuffer[LENGTH]; //数据缓冲区
uint8_t RxCount=0; //实际接受的数据项数
volatile uint8_t RxFlag=0; //数据接受标志
/* USER CODE END PV */
3.用户代码2
/* USER CODE BEGIN 2 */
//发送提示信息
printf ("/*******UART Communication LL using IDLE IT + DMA *******\r\n");
printf ("Please enter arbitrary length characters:\r\n");
__HAL_UART_ENABLE_IT(&huart2,UART_IT_IDLE); //使能IDLE中断
HAL_UART_Receive_DMA(&huart2, (uint8_t *)RxBuffer, LENGTH);//启动DMA接受
/* USER CODE END 2 */
4.用户代码3
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
if( RxFlag==1 ) //判断接收是否完成
{
RxFlag=0; //清除数据接收标志
RxCount = LENGTH - __HAL_DMA_GET_COUNTER(&hdma_usart2_rx);
HAL_UART_Transmit_DMA(&huart2,(uint8_t *)RxBuffer,RxCount);
__HAL_DMA_DISABLE(&hdma_usart2_rx);
}
}
/* USER CODE END 3 */
}
5.用户代码4
/* USER CODE BEGIN 4 */
PUTCHAR_PROTOTYPE
{
HAL_UART_Transmit(&huart2, (uint8_t*)&ch, 1, HAL_MAX_DELAY);
return ch;
}
GETCHAR_PROTOTYPE
{
uint8_t ch;
HAL_UART_Receive(&huart2,(uint8_t *)&ch, 1, HAL_MAX_DELAY);
return ch;
}
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
if(huart->Instance==USART2)
{
HAL_UART_Receive_DMA(&huart2, (uint8_t *)RxBuffer, LENGTH);
}
}
void HAL_UART_IdleCpltCallback(UART_HandleTypeDef *huart)
{
RxFlag =1 ;
}
/* USER CODE END 4 */
6. 在stm32f4xx_it.c中添加的函数
6.1引用变量
/* USER CODE BEGIN EV */
extern volatile uint8_t RxFlag;
/* USER CODE END EV */
6.2撰写 void USART2_IRQHandler(void)
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 */
if (__HAL_UART_GET_FLAG(&huart2,UART_FLAG_IDLE)!=RESET)
{
__HAL_UART_CLEAR_IDLEFLAG(&huart2);
HAL_UART_IdleCpltCallback(&huart2);
RxFlag=1;
}
/* USER CODE END USART2_IRQn 1 */
}
7.在main.h中添加代码
/* USER CODE BEGIN EFP */
void HAL_UART_IdleCpltCallback(UART_HandleTypeDef *huart);
/* USER CODE END EFP */
8. 实验结果