实现:控制小灯亮灭 发送R1亮
一、搬运小助手DMA
cpu每次触发非空中断就要跑回来搬运数据,也会占用cpu的性能,所以可以调用DMA(直接内存访问)来代替cpu进行搬运
开启DMA方法:
1.串口端口中添加DMA TX和RX的通道,然后
2..使用发送HAL_UART_Transmit_DMA(&huart1, receiveDate, 2); 接收:HAL_UART_Receive_DMA(&huart1, receiveDate, 2);
这2个函数就是在串口中断收发IT上改成DMA,就变成了中断DMA收发,但是中断回调函数还是void HAL_UART_RxCpltCallback,这个就不是串口的中断了,DMA会调用自己的传输完成中断。
代码示例:
/* USER CODE BEGIN PV */
uint8\_t receiveDate\[2\];
\* USER CODE END PV *\
/ USER CODE BEGIN 0 /
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart){
HAL_UART_Transmit_DMA(&huart1, receiveDate, 2);
GPIO_PinState state = GPIO_PIN_SET; //定义gpio_pinstate类型的state变量,默认成高电平
if(receiveDate[1] == '0'){
state = GPIO_PIN_RESET;
}
//判断receivedate的第0位数字是不是0,如果是0就设置成低电平,如果不是则保持高电平
if(receiveDate[0] == 'R'){
HAL_GPIO_WritePin(LED_RED_GPIO_Port, LED_RED_Pin, state);
}else if(receiveDate[0] == 'G'){
HAL_GPIO_WritePin(LED_RED_GPIO_Port, LED_RED_Pin, state);
}else if(receiveDate[0] == 'B'){
HAL_GPIO_WritePin(LED_RED_GPIO_Port, LED_RED_Pin, state);
}
//判断第二位是R,G,B,则输出相应端口高电
HAL_UART_Receive_DMA(&huart1, receiveDate, 2);
//继续接收
}
/ USER CODE END 0 /
/* USER CODE BEGIN 2 */
HAL_UART_Receive_DMA(&huart1, receiveDate, 2);
/* USER CODE END 2 */
二、接收不定长数据
1.原理
主要是靠 串口空闲中断(ldle) 来接收不定长数据,只有当串口从忙碌转为空闲时才会触发。空闲中断发生时,就判断数据接收完了,然后进行数据处理。
2.使用方法
2.1接收数据函数:HAL_UARTEx_ReceiveToIdle_DMA(&huart1, receiveDate, sizeof(receiveDate)); 后面长度是判断变量声明时的长度,HAL_UART_Transmit_DMA(huart, receiveDate, sizeof(receiveDate));//把接收的数据发送出去
2.2.这个触发的中断函数是:void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *huart, uint16_t Size) 与上面中断触发的函数唯一区别是传参多了size,
2.3DMA在数据传送过半时也会触发中断,就会导致数据传输不完整,要在每次触发时关闭一下传输过半中断,关闭过半中断代码:__HAL_DMA_DISABLE_IT(&hdma_usart1_rx,DMA_IT_HT);
2.4.
代码示例:
/* USER CODE BEGIN PV */
uint8_t receiveDate[50]; //全局变量长度50
/* USER CODE END PV */
/* USER CODE BEGIN 0 */
void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *huart, uint16_t Size){ //中断处理函数
if(huart == &huart1){//确认是谁触发了回调函数
HAL_UART_Transmit_DMA(huart, receiveDate, sizeof(receiveDate));//把接收的数据发送出去
HAL_UARTEx_ReceiveToIdle_DMA(huart, receiveDate, sizeof(receiveDate));//再次启用接收函数
__HAL_DMA_DISABLE_IT(&hdma_usart1_rx, DMA_IT_HT);
}
}
/* USER CODE END 0 */
/* USER CODE BEGIN 2 */
HAL_UARTEx_ReceiveToIdle_DMA(&huart1, receiveDate, sizeof(receiveDate));
__HAL_DMA_DISABLE_IT(&hdma_usart1_rx,DMA_IT_HT);
/* USER CODE END 2 */
错误提示:hdma_usart2_rx没找到
如果接收过半中断对你的逻辑判断是没有影响的话, 可以不禁用. 2. 按照视频里的讲解,是没有问题的, 但是如果你在CubeMX的Project Manager->Code Generator里勾选了Generate peripheral initialization as a pair of '.c/.h. files per peripheral, hdma_usart2_rx就会定义到usart.c, 并且usart.h中没有声明, 你只需要自己在usart.h中添加extern DMA_HandleTypeDef hdma_usart3_rx; 就好了,或者去MX里取消勾选