STM32 serial port uses DMA to receive data

Publisher:糖果龙猫Latest update time:2018-06-08 Source: eefocusKeywords:STM32 Reading articles on mobile phones Scan QR code
Read articles on your mobile phone anytime, anywhere

environment:

Host: WINXP

Development environment: MDK4.23

MCU:STM32F103CBT6


illustrate:

The serial port can be configured to receive data using DMA, but DMA requires a fixed length to generate a receive interrupt. How can we receive data of variable length?

There are three methods:

1. Connect the RX pin to an external clock pin. When a frame is sent by the serial port, this timer can be used to generate a timeout interrupt. This has high real-time performance and can achieve real-time monitoring of 1 byte.

2. Without changing the hardware, start a timer to monitor DMA reception, and generate an interrupt if it times out. This is not very real-time, because the timeout must be greater than the time required to receive the frame, and the accuracy is difficult to control.

3. Some serial ports of STM32 microcontrollers can monitor whether the bus is idle, and generate an interrupt if it is idle. It can be used to monitor whether DMA reception is completed. This method has high real-time performance.

This article adopts the third method. The impact of large data packets at a baud rate of 576000 proves to be feasible.


source code:


  1. //Serial port receive DMA buffer  

  2. #define UART_RX_LEN 128  

  3. extern uint8_t Uart_Rx[UART_RX_LEN];  



  1. //Serial port receive DMA buffer  

  2. uint8_t Uart_Rx[UART_RX_LEN] = {0};  



  1. //---------------------Serial port function configuration---------------------  

  2.     //Open the peripheral clock corresponding to the serial port    

  3.     RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);   

  4.     //Serial port DMA configuration    

  5.     //Start DMA clock  

  6.     RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);  

  7.     //DMA send interrupt setting  

  8.     NVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel4_IRQn;  

  9.     NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 3;  

  10.     NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;  

  11.     NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;  

  12.     NVIC_Init(&NVIC_InitStructure);  

  13.     //DMA1 channel 4 configuration  

  14.     DMA_DeInit(DMA1_Channel4);  

  15.     //Peripheral address  

  16.     DMA_InitStructure.DMA_PeripheralBaseAddr = (u32)(&USART1->DR);  

  17.     //Memory address  

  18.     DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)Uart_Send_Buffer;  

  19.     //dma transmission direction is one-way  

  20.     DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;  

  21.     //Set the length of the DMA buffer during transmission  

  22.     DMA_InitStructure.DMA_BufferSize = 100;  

  23.     //Set the DMA peripheral increment mode, a peripheral  

  24.     DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;  

  25.     //Set DMA memory increment mode  

  26.     DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;  

  27.     //Peripheral data word length  

  28.     DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;  

  29.     //Memory data word length  

  30.     DMA_InitStructure.DMA_MemoryDataSize = DMA_PeripheralDataSize_Byte;  

  31.     //Set DMA transfer mode  

  32.     DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;  

  33.     //Set the DMA priority level  

  34.     DMA_InitStructure.DMA_Priority = DMA_Priority_High;  

  35.     //Set the variables in the two DMA memories to access each other  

  36.     DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;  

  37.     DMA_Init(DMA1_Channel4,&DMA_InitStructure);  

  38.     DMA_ITConfig(DMA1_Channel4,DMA_IT_TC,ENABLE);  

  39.       

  40.     // Enable channel 4  

  41.     //DMA_Cmd(DMA1_Channel4, ENABLE);  

  42.   

  43.     //Serial port receiving DMA configuration    

  44.     //Start DMA clock  

  45.     RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);  

  46.     //DMA1 channel 5 configuration  

  47.     DMA_DeInit(DMA1_Channel5);  

  48.     //Peripheral address  

  49.     DMA_InitStructure.DMA_PeripheralBaseAddr = (u32)(&USART1->DR);  

  50.     //Memory address  

  51.     DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)Uart_Rx;  

  52.     //dma transmission direction is one-way  

  53.     DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;  

  54.     //Set the length of the DMA buffer during transmission  

  55.     DMA_InitStructure.DMA_BufferSize = UART_RX_LEN;  

  56.     //Set the DMA peripheral increment mode, a peripheral  

  57.     DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;  

  58.     //Set DMA memory increment mode  

  59.     DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;  

  60.     //Peripheral data word length  

  61.     DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;  

  62.     //Memory data word length  

  63.     DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;  

  64.     //Set DMA transfer mode  

  65.     DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;  

  66.     //Set the DMA priority level  

  67.     DMA_InitStructure.DMA_Priority = DMA_Priority_VeryHigh;  

  68.     //Set the variables in the two DMA memories to access each other  

  69.     DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;  

  70.     DMA_Init(DMA1_Channel5,&DMA_InitStructure);  

  71.   

  72.     // Enable channel 5  

  73.     DMA_Cmd(DMA1_Channel5,ENABLE);  

  74.       

  75.         

  76.     //Initialization parameters    

  77.     //USART_InitStructure.USART_BaudRate = DEFAULT_BAUD;    

  78.     USART_InitStructure.USART_WordLength = USART_WordLength_8b;    

  79.     USART_InitStructure.USART_StopBits = USART_StopBits_1;    

  80.     USART_InitStructure.USART_Parity = USART_Parity_No;    

  81.     USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;    

  82.     USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;      

  83.     USART_InitStructure.USART_BaudRate = DEFAULT_BAUD;   

  84.     // Initialize the serial port   

  85.     USART_Init(USART1,&USART_InitStructure);    

  86.     //TXE send interrupt, TC transmission completion interrupt, RXNE receive interrupt, PE parity error interrupt, can be multiple     

  87.     //USART_ITConfig(USART1,USART_IT_RXNE,ENABLE);  

  88.       

  89.     //Interrupt configuration  

  90.     USART_ITConfig(USART1,USART_IT_TC,DISABLE);  

  91.     USART_ITConfig(USART1,USART_IT_RXNE,DISABLE);  

  92.     USART_ITConfig(USART1,USART_IT_IDLE,ENABLE);    

  93.   

  94.     //Configure UART1 interrupt    

  95.     NVIC_PriorityGroupConfig(NVIC_PriorityGroup_3);  

  96.     NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn; //Channel is set to serial port 1 interrupt    

  97.     NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2; //Interrupt preemption level 0    

  98.     NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; //Interrupt response priority 0    

  99.     NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //Enable interrupt    

  100.     NVIC_Init(&NVIC_InitStructure);     

  101.           

  102.     //Send using DMA  

  103.     USART_DMACmd(USART1,USART_DMAReq_Tx,ENABLE);  

  104.     //Receive using DMA  

  105.     USART_DMACmd(USART1,USART_DMAReq_Rx,ENABLE);  

  106.     //Start the serial port    

  107.     USART_Cmd(USART1, ENABLE);   



  1. //Serial port 1 receive interrupt     

  2. void USART1_IRQHandler(void)                                 

  3. {     

  4.     uint32_t temp = 0;  

  5.     uint16_t i = 0;  

  6.       

  7.     if(USART_GetITStatus(USART1, USART_IT_IDLE) != RESET)  

  8.     {  

  9.         //USART_ClearFlag(USART1,USART_IT_IDLE);  

  10.         temp = USART1->SR;  

  11.         temp = USART1->DR; // Clear USART_IT_IDLE flag  

  12.         DMA_Cmd(DMA1_Channel5,DISABLE);  

  13.   

  14.         temp = UART_RX_LEN - DMA_GetCurrDataCounter(DMA1_Channel5);  

  15.         for (i = 0;i < temp;i++)  

  16.         {  

  17.             Data_Receive_Usart = Uart_Rx[i];  

  18.             //Start the serial port state machine  

  19.             usart_state_run();   

  20.         }  

  21.   

  22.         //Set the transmission data length  

  23.         DMA_SetCurrDataCounter(DMA1_Channel5,UART_RX_LEN);  

  24.         //Open DMA  

  25.         DMA_Cmd(DMA1_Channel5,ENABLE);  

  26.     }   

  27.       

  28.     __nop();   

  29. }   


Test Results:

Conditions: The microcontroller runs at 72M and communicates with the PC at a rate of 460800. The PC sends a 9-byte packet every 100ms: c5 5c 6 0 6F 10 5 4e f7.

Test: Each time the MCU receives this packet, an IO jumps to a level, and then processes and returns a packet.

Oscilloscope display:


Zoom in to show:


Keywords:STM32 Reference address:STM32 serial port uses DMA to receive data

Previous article:STM32 serial port 1 send and receive DMA mode function configuration
Next article:STM32F407ZET6 USART DMA mode to send and receive data

Recommended ReadingLatest update time:2024-11-16 15:20

stm32 prints data to PC serial port
1. Generally speaking, many people use printf function redirection to achieve this, but it is not very clear. Therefore, the sprintf function is used here to implement it. Second, the whole idea is to put the data to be printed into the serial port send buffer of MCU to PC. 3. The sprintf function is in the stdio.h he
[Microcontroller]
STM32 RTC real-time clock
Introduction to RTC real-time clock:  The RTC peripheral of STM32 is actually a timer that continues to run after power failure. From the perspective of the timer, compared with the general timer TIM peripheral, its function is very simple, with only the timing function (it can also trigger an interrupt). However, fro
[Microcontroller]
STM32 SPI Notes
        I thought SPI was very simple, so I used it directly without looking at it carefully. This time, when I was debugging a chip, a strange problem occurred. I thought it was a problem with the program logic, and I wasted several days without finding the cause. Today, I obediently checked some manuals and finally f
[Microcontroller]
Pull-up and pull-down resistors for STM32
STM32F10X I/O can enable weak pull-up or pull-down resistors through the configuration register. According to the datasheet, this resistor is: min=20K, typ=30K, max=40K. The input of STM32F10X I/O can be configured as floating/pull up/pull down. For STM32F10X, the state of I/O after system reset is Floating input. S
[Microcontroller]
Summary of STM32 NVIC and interrupts
Preface:  1. To learn STM32 interrupts, you must first understand STM32's definition of priority;  2. Experience in 51 MCU development will make it easier to understand interrupt priorities;  3. This blog post is based on the STM32F103ZET6 chip and 3.5.0 standard library;  4. This blog post starts with registers and e
[Microcontroller]
Summary of STM32 NVIC and interrupts
STM32 CAN filter settings Identifier filter
The shielding filter function of stm32 has requirements for ID. You can write ID directly in mpc2515, but in STM32, ID must be shifted. Refer to the following table:   Extended Id filter settings (verified, only accept data from Receive_ID nodes): /* CAN filter init */ //设置成只能接受主节点 Extended Id:01 的数据   refere
[Microcontroller]
STM32 CAN filter settings Identifier filter
Research on the problem of ORE flag bit appearing in STM32 serial port
Test environment, STM32L476, when the HAL library uses UART, an ORE error occurs in the interrupt flag register, as described below: Cause of code error: 1. Initialize the serial port, uart_USB_init(); this function does not start the interrupt 2. Delay 3000S, during which the computer sends data to the serial port
[Microcontroller]
Research on the problem of ORE flag bit appearing in STM32 serial port
Design of 2μm high-power laser medical instrument controller based on STM32
    The market demand for 2μm high-power laser medical devices is growing, but the current domestic control of such devices lacks consideration of system safety and light output accuracy. At the same time, with the implementation of the YY0505-2012 medical electrical electromagnetic compatibility standard in 2014, it i
[Medical Electronics]
Design of 2μm high-power laser medical instrument controller based on STM32
Latest Microcontroller Articles
  • Download from the Internet--ARM Getting Started Notes
    A brief introduction: From today on, the ARM notebook of the rookie is open, and it can be regarded as a place to store these notes. Why publish it? Maybe you are interested in it. In fact, the reason for these notes is ...
  • Learn ARM development(22)
    Turning off and on interrupts Interrupts are an efficient dialogue mechanism, but sometimes you don't want to interrupt the program while it is running. For example, when you are printing something, the program suddenly interrupts and another ...
  • Learn ARM development(21)
    First, declare the task pointer, because it will be used later. Task pointer volatile TASK_TCB* volatile g_pCurrentTask = NULL;volatile TASK_TCB* vol ...
  • Learn ARM development(20)
    With the previous Tick interrupt, the basic task switching conditions are ready. However, this "easterly" is also difficult to understand. Only through continuous practice can we understand it. ...
  • Learn ARM development(19)
    After many days of hard work, I finally got the interrupt working. But in order to allow RTOS to use timer interrupts, what kind of interrupts can be implemented in S3C44B0? There are two methods in S3C44B0. ...
  • Learn ARM development(14)
  • Learn ARM development(15)
  • Learn ARM development(16)
  • Learn ARM development(17)
Change More Related Popular Components

EEWorld
subscription
account

EEWorld
service
account

Automotive
development
circle

About Us Customer Service Contact Information Datasheet Sitemap LatestNews


Room 1530, 15th Floor, Building B, No.18 Zhongguancun Street, Haidian District, Beijing, Postal Code: 100190 China Telephone: 008610 8235 0740

Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved 京ICP证060456号 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号