STM32-cubeMX + DMA + USART receives data of an arbitrary length

Foreword

Original: https://blog.csdn.net/u014470361/article/details/79206352

My previous article for any length USART receive data can be achieved, for HAL library has been modified, can be achieved at the receiving end of arbitrary length data 0x0a, that is considered received when receiving end 0x0a, see link: HAL USART receiving any length .
  However, this method is not suitable for the above, the general principle not modified HAL library, others not easy migration program, the program reduces the applicability of the library, which is very bad habit, so this method is not desirable .
  After receiving data of any length that STM32 check the information may also be implemented by DMA serial manner, so the learning data + the start serial receive DMA arbitrary length in this manner.

cubeMX software configuration process

First, the first step is to configure the clock tree, the clock system configured, different configuration of the chip clock frequency, as shown in FIG.
Write pictures described here
Next, the USART1 configuration, select Asynchronous asynchronous, the software automatically configured PA9 and PA10 pins.
Write pictures described here
Then, continue to add to send and receive DMA USART1 the rest default.
Write pictures described here
Then, check the USART1 interrupt enable.
Write pictures described here
Finally, a program MDK-ARM V5 version environment.
Write pictures described here

UASRT serial program

//添加变量,为什么用关键字volatile见链接:[链接](http://blog.csdn.net/u014470361/article/details/78830147)
volatile uint8_t rx_len=0;
volatile uint8_t recv_end_flag=0;
uint8_t rx_buffer[200];
static void MX_USART1_UART_Init(void)
{

  huart1.Instance = USART1;
  huart1.Init.BaudRate = 115200;
  huart1.Init.WordLength = UART_WORDLENGTH_8B;
  huart1.Init.StopBits = UART_STOPBITS_1;
  huart1.Init.Parity = UART_PARITY_NONE;
  huart1.Init.Mode = UART_MODE_TX_RX;
  huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;
  huart1.Init.OverSampling = UART_OVERSAMPLING_16;
  if (HAL_UART_Init(&huart1) != HAL_OK)
  {
    _Error_Handler(__FILE__, __LINE__);
  }
  //上面的usart配置代码为cubemx自动生成的,在下方添加使能idle中断和打开串口DMA接收语句
	__HAL_UART_ENABLE_IT(&huart1, UART_IT_IDLE);//使能idle中断
	HAL_UART_Receive_DMA(&huart1,rx_buffer,BUFFER_SIZE);//打开DMA接收,数据存入rx_buffer数组中。	
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23

Then modify the serial port interrupt function.

void USART1_IRQHandler(void)
{
	uint32_t tmp_flag = 0;
	uint32_t temp;
	tmp_flag =__HAL_UART_GET_FLAG(&huart1,UART_FLAG_IDLE); //获取IDLE标志位
	if((tmp_flag != RESET))//idle标志被置位
	{ 
		__HAL_UART_CLEAR_IDLEFLAG(&huart1);//清除标志位
		temp = huart1.Instance->SR;  //清除状态寄存器SR,读取SR寄存器可以实现清除SR寄存器的功能
		temp = huart1.Instance->DR; //读取数据寄存器中的数据
		HAL_UART_DMAStop(&huart1); //
		temp  = hdma_usart1_rx.Instance->NDTR;// 获取DMA中未传输的数据个数,NDTR寄存器分析见下面
		rx_len =  BUFFER_SIZE - temp; //总计数减去未传输的数据个数,得到已经接收的数据个数
		recv_end_flag = 1;	// 接受完成标志位置1	
	 }
  HAL_UART_IRQHandler(&huart1);

}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18

DMA channel structure defined NDTR register, number data is why it is not transmitted, the STM32 Chinese manual gives detailed description of the register.

typedef struct
{
  __IO uint32_t CR;     /*!< DMA stream x configuration register      */
  __IO uint32_t NDTR;   /*!< DMA stream x **number of data register**     */
  __IO uint32_t PAR;    /*!< DMA stream x peripheral address register */
  __IO uint32_t M0AR;   /*!< DMA stream x memory 0 address register   */
  __IO uint32_t M1AR;   /*!< DMA stream x memory 1 address register   */
  __IO uint32_t FCR;    /*!< DMA stream x FIFO control register       */
} DMA_Stream_TypeDef;
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

Write pictures described here
Then, write handlers main function of the serial port interrupt.

int main(void)
{
  HAL_Init();
  SystemClock_Config();
  MX_GPIO_Init();
  MX_DMA_Init();
  MX_USART1_UART_Init();
  while (1)
  {
		if(recv_end_flag ==1)
		{
			printf("rx_len=%d\r\n",rx_len);//打印接收长度
			HAL_UART_Transmit(&huart1,rx_buffer, rx_len,200);接收数据打印出来
			for(uint8_t i=0;i<rx_len;i++)
				{
					rx_buffer[i]=0;//清接收缓存
				}
			rx_len=0;//清除计数
			recv_end_flag=0;//清除接收结束标志位
		}
		HAL_UART_Receive_DMA(&huart1,rx_buffer,BUFFER_SIZE);//重新打开DMA接收		
  }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23

Running effect program shown in the following figure, the input data of arbitrary length, the length of the serial print data and prints out the received data is received. Receiving the maximum length is set by the program of the present BUFFER_SIZE 200, For longer data received, may change the length of the array and BUFFER_SIZE large.
Write pictures described here
### DMA function parameters and analytical
rationale DMA, parameters and analytical functions to analyze the next article (link) .

Download the source code of this article: https://download.csdn.net/download/u014470361/10234803

 

Guess you like

Origin www.cnblogs.com/pacexdong/p/12118193.html