USART (轮询 中断 DMA)

DMA不定长接受,printf轮询发送,码云地址https://gitee.com/buffzhou/DMA_try


快速目录

  1. 快速目录
  2. USART三种收发方式简介
  3. 发送(重定义printf中fputc)
  4. 接受

USART三种收发方式简介

接受发送数据就像你去收发快递,发送还好说因为你知道自己什么时候发快递,这样就能很好的安排什么时候发快递,你完全可以控制发快递的时间不会影响你的工作。但是接受数据是个麻烦的事情,因为是别人发送的数据如果你不去收它就没了,而且这完全是不可控的,也就是说无法预料,为了不干扰你当前的工作我们一般用DMA接受。下面我举个栗子。


轮询接受:你在工作的安排中不停的询问有没有你的快递,在程序中就是一段语句看寄存器上有没有信号,缺点使你工作效率低下,而且没询问的时候消息就没有收到。


中断接受:中断像个宿管大爷,他不会帮你保存,一来快递就喊你下来拿,如果你不来就没有了。这样的话你可能在写作业,突然下来拿快递效率也很低。


DMA接受:这就像菜鸟驿站,菜鸟驿站帮你保存,包裹接受的过程都不用你做,你只要快速的在一个包裹接受结束时吧包裹拿走。

下面是喜闻乐见的“shut up and shoe your code”环节 MX配置就是USRAT打开DMA要打开USRAT中断不然空闲中断没法触发


发送(重定义printf中fputc)


#ifdef __GNUC__
	#define PUTCHAR_PROTOTYPE int __io_putchar(int ch)      //判断编译器
#else
	#define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)    //printf输出到串口,需要将fputc里面的输出指向串口(重定向)
#endif

PUTCHAR_PROTOTYPE
{
	HAL_UART_Transmit(&huart1, (uint8_t *)&ch , 1 , 0xFFFF); //轮询输出
	return ch;
}


接受


  • 中断处理函数



void UsartReceive_IDLE(UART_HandleTypeDef *huart)
{
    uint32_t temp;                                              //空闲余量

    if((__HAL_UART_GET_FLAG(huart,UART_FLAG_IDLE) != RESET))    //判断空闲中断有没有触发
    { 
        __HAL_UART_CLEAR_IDLEFLAG(&huart1);                     //清理空闲中断有没有触发
        HAL_UART_DMAStop(&huart1);                              //暂停DMA,因为操作时不能改DMA
        temp = huart1.hdmarx->Instance->CNDTR;                  //获取DMA余量
        UsartType.RX_Size =  RX_LEN - temp;                     //DMA开启空间 - DMA余量 = 收取的实际长度值
        UsartType.RX_flag=1;                                    //接受结构体设置flag,告知有新串口输入
        HAL_UART_Receive_DMA(&huart1,UsartType.RX_pData,RX_LEN);//继续开启DMA为了下一段输入
    }
}


  • 开启中断

位置:main.c /* USER CODE BEGIN 2 */

  __HAL_UART_CLEAR_IDLEFLAG(&huart1);                       //清理空闲中断flag
  __HAL_UART_ENABLE_IT(&huart1,UART_IT_IDLE);               //使能空闲中断
  HAL_UART_Receive_DMA(&huart1, UsartType.RX_pData, 1024);  //开启接受,这样才能有空闲中断触发,一定要加上

  • 中断处理函数加入中断Handle

位置: stm32f1xx_it.c void USART1_IRQHandler(void) /* USER CODE BEGIN USART1_IRQn 0 */

这里是stm103 stm405就在是4xx_it 在这个中断.c里面找到USART1_IRQHandler(void)函数添加 UsartReceive_IDLE(&huart1);执行自己写>的中断处理函数。

void USART1_IRQHandler(void)
{
  /* USER CODE BEGIN USART1_IRQn 0 */
	UsartReceive_IDLE(&huart1);           //执行自己写的中断处理函数。
  /* USER CODE END USART1_IRQn 0 */
  HAL_UART_IRQHandler(&huart1);
  /* USER CODE BEGIN USART1_IRQn 1 */

  /* USER CODE END USART1_IRQn 1 */
}

本站总访问量

BUFF © 2018. All rights reserved.

Powered by Hydejack v8.1.1