STM32F4 UART1 DMA sends and receives indeterminate length data

Source: Internet
Author: User

STM32F4 Serial transceiver Using DMA is still very convenient. However, configuring the DMA requires the configuration of the data length, which can be used to pre-estimate the length of the Send to configure the DMA send data length, but for the reception is not a good solution, because if the use of DMA receive interrupt is to configure the length of the data to be configured to 0 to start the outage. However, it is not possible to determine the length of the accepted data, resulting in the inability to determine data reception. The solution proposed on the Internet is to determine whether the reception is completed with the length of the read DMA received by the timer fixed period, and also to handle the idle interrupt using the UART. Here I use the UART's idle interrupt to handle the receiving of indefinite long data. Of course also to turn on DMA receive complete interrupt, processing the data received over the length of the DMA configuration caused by the DMA receive interrupt.

1. When using DMA to send data before each send the data length needs to be configured, it should be noted that the DMA should be closed first, then configure the data length, finally turn on the DMA send, while in the DMA send interrupt do not forget to clear the corresponding interrupt flag bit.

When the 2.DMA receive length reaches the configured length, it causes the receive interrupt, at which time the DMA is closed in the interrupt handler, then the data length is read out, the corresponding interrupt flag bit is cleared, the DMA receive length is reconfigured and the DMA receive is turned on. Here the DMA interrupt is indicated in order to protect the disposable receive data over the DMA configuration length.

3.UART Idle Interrupt, the use of idle interrupt can be good to determine whether the DMA receives an indefinite length of data is complete. Open idle interrupt when initializing UART. The UART idle interrupt is triggered when the data reception is complete. In the interrupt, first turn off the DMA, read the DMA received data length, clear the DMA flag, reconfigure the DMA receive length, clear the idle interrupt flag idle. Note here to clear idle to be purged by software sequence and read usart1->sr; and usart1->dr; sequentially

Post the code below for easy viewing later

U8 Receivebuff[receive_buf_size]; Receive buffer U8 sendbuff[send_buf_size];//send data buffer u16 uart1_receivesize = 0;//Initialize IO serial 1//bound: baud rate void Uart_init (u32 bound) {/ /gpio port Settings Gpio_inittypedef gpio_initstructure; Usart_inittypedef usart_initstructure; Nvic_inittypedef Nvic_initstructure;dma_inittypedef dma_initstructure; Rcc_ahb1periphclockcmd (rcc_ahb1periph_gpioa,enable); Enable Gpioa clock Rcc_apb2periphclockcmd (rcc_apb2periph_usart1,enable),//Enable USART1 clock Rcc_ahb1periphclockcmd (RCC_ ahb1periph_dma2,enable);//dma2 clock enable//serial 1 corresponds to the pin multiplexing mapping Gpio_pinafconfig (GPIOA,GPIO_PINSOURCE9,GPIO_AF_USART1); GPIOA9 Multiplexing is usart1gpio_pinafconfig (GPIOA,GPIO_PINSOURCE10,GPIO_AF_USART1); GPIOA10 multiplexing for usart1//usart1 port configuration Gpio_initstructure.gpio_pin = Gpio_pin_9 | gpio_pin_10; GPIOA9 and Gpioa10gpio_initstructure.gpio_mode = gpio_mode_af;//multiplexing function gpio_initstructure.gpio_speed = GPIO_Speed_50MHz ;//Speed 50mhzgpio_initstructure.gpio_otype = gpio_otype_pp; Push-pull multiplexing output gpio_initstructure.gpio_pupd = gpio_pupd_up; Pull-up gpio_init (gpioa,&gpio_initstructure);Initialize PA9,PA10//USART1 initialization Setting Usart_initstructure.usart_baudrate = bound;//baud rate setting usart_initstructure.usart_wordlength = usart_wordlength_8b;//Word length is 8-bit data format usart_initstructure.usart_stopbits = usart_stopbits_1;//a stop bit usart_ initstructure.usart_parity = usart_parity_no;//no parity bit usart_initstructure.usart_hardwareflowcontrol = USART_ hardwareflowcontrol_none;//No hardware data flow control Usart_initstructure.usart_mode = Usart_mode_rx | usart_mode_tx;//Transceiver Mode Usart_init (USART1, &usart_initstructure);  Initialize the serial port 1usart_cmd (USART1, ENABLE); Enable serial port 1//usart_clearflag (USART1, USART_FLAG_TC); Usart_itconfig (USART1, Usart_it_idle, enable);//Turn on related interrupts//usart1 NVIC configuration Nvic_initstructure.nvic_irqchannel = usart1_ irqn;//Serial 1 Interrupt channel nvic_initstructure.nvic_irqchannelpreemptionpriority=3;//preemption priority 3nvic_initstructure.nvic_ Irqchannelsubpriority =3;//Sub-priority 3nvic_initstructure.nvic_irqchannelcmd = ENABLE;//IRQ Channel Enable Nvic_init (&NVIC_  initstructure);//Initialize the VIC Register, Usart_dmacmd (usart1,usart_dmareq_tx,enable) According to the specified parameters; Enable DMA for serial port 1 to send Usart_dmacmd (usart1,usart_dmareq_rx,enable); Enable DMA for serial port 1 to receive//**************************** configuration UART1 send Dma_deinit (DMA2_STREAM7); while (Dma_getcmdstatus (dma2_  STREAM7)! = DISABLE);//wait for DMA configurable/* To configure DMA Stream */dma_initstructure.dma_channel = dma_channel_4; Channel selection dma_initstructure.dma_peripheralbaseaddr = (u32) &AMP;USART1-&GT;DR;//DMA Peripheral Address Dma_initstructure.dma_ Memory0baseaddr = (u32) SENDBUFF;//DMA memory 0 Address Dma_initstructure.dma_dir = dma_dir_memorytoperipheral;//memory to peripheral mode Dma_ initstructure.dma_buffersize = send_buf_size;//data transfer amount Dma_initstructure.dma_peripheralinc = DMA_PeripheralInc_ disable;//Peripheral Non-incremental mode dma_initstructure.dma_memoryinc = dma_memoryinc_enable;//memory Increment mode Dma_initstructure.dma_ Peripheraldatasize = dma_peripheraldatasize_byte;//Peripheral Data Length: 8-bit dma_initstructure.dma_memorydatasize = DMA_ memorydatasize_byte;//Memory Data length: 8 bit dma_initstructure.dma_mode = dma_mode_normal;//using normal mode Dma_initstructure.dma_         Priority = dma_priority_medium;//Medium Precedence dma_initstructure.dma_fifomode = dma_fifomode_disable; Dma_initstructure.dma_fifothreshOld = Dma_fifothreshold_full;dma_initstructure.dma_memoryburst = dma_memoryburst_single;//Memory Burst single transmission Dma_ Initstructure.dma_peripheralburst = dma_peripheralburst_single;//Peripheral Burst single transmission dma_init (DMA2_STREAM7, &DMA_  initstructure);//Initialize DMA STREAM//DMA NVIC nvic_initstructure.nvic_irqchannel = dma2_stream7_irqn;  nvic_initstructure.nvic_irqchannelpreemptionpriority = 0;  nvic_initstructure.nvic_irqchannelsubpriority = 0;  Nvic_initstructure.nvic_irqchannelcmd = ENABLE;  Nvic_init (&nvic_initstructure); Dma_itconfig (dma2_stream7,dma_it_tc,enable);//**************************** configuration UART1 receive Dma_deinit (DMA2_STREAM5); while (Dma_getcmdstatus (DMA2_STREAM5)! = DISABLE);//wait for DMA configurable/* To configure DMA Stream */dma_initstructure.dma_channel = Dma_  Channel_4; Channel selection dma_initstructure.dma_peripheralbaseaddr = (u32) &AMP;USART1-&GT;DR;//DMA Peripheral Address Dma_initstructure.dma_ Memory0baseaddr = (u32) RECEIVEBUFF;//DMA memory 0 Address dma_initstructure.dma_dir = dma_dir_peripheraltomemory;//peripheral to Memory mode DMA _initstructure.dma_buffersize = Receive_buf_size;//data transfer Amount Dma_initstructure.dma_peripheralinc = dma_peripheralinc_disable;//peripheral non-incremental mode Dma_initstructure.dma_ Memoryinc = dma_memoryinc_enable;//Memory increment mode dma_initstructure.dma_peripheraldatasize = dma_peripheraldatasize_byte;/ /Peripheral Data Length: 8-bit dma_initstructure.dma_memorydatasize = dma_memorydatasize_byte;//Memory Data length: 8-bit dma_initstructure.dma_mode = dma_mode_normal;//using normal mode dma_initstructure.dma_priority = dma_priority_medium;//Medium-Priority Dma_initstructure.dma_         Fifomode = dma_fifomode_disable; Dma_initstructure.dma_fifothreshold = Dma_fifothreshold_full;dma_initstructure.dma_memoryburst = DMA_MemoryBurst_ single;//Memory Burst single transmission Dma_initstructure.dma_peripheralburst = dma_peripheralburst_single;//Peripheral Burst single transmission dma_init (DMA2_  STREAM5, &dma_initstructure);//Initialize DMA STREAM//DMA NVIC nvic_initstructure.nvic_irqchannel = dma2_stream5_irqn;  nvic_initstructure.nvic_irqchannelpreemptionpriority = 0;  nvic_initstructure.nvic_irqchannelsubpriority = 1;  Nvic_initstructure.nvic_irqchannelcmd = ENABLE; Nvic_init (&Amp  Nvic_initstructure);  Dma_cmd (DMA2_STREAM5, ENABLE); Turn on DMA transfer dma_itconfig (dma2_stream5,dma_it_tc,enable);} Turn on DMA transfer//DMA_STREAMX:DMA data stream, dma1_stream0~7/dma2_stream0~7//NDTR: Data transfer volume void Dmasenddataproc (DMA_STREAM_                      TypeDef *dma_streamx,u16 ndtr) {dma_cmd (DMA_STREAMX, DISABLE);          Turn off the DMA transfer while (Dma_getcmdstatus (DMA_STREAMX)! = DISABLE) {}//Ensure that the DMA can be set Dma_setcurrdatacounter (DMA_STREAMX,NDTR);                      Data transmission Volume Dma_cmd (DMA_STREAMX, ENABLE); Enable DMA transfer}/////////////////////////////////////////////////////////////////////////////serial 1//send single byte void Sendbyteinfoproc (U8 nsendinfo) {U8 *pbuf = null;//points to send buffer pBuf = sendbuff;*pbuf++ = Nsendinfo;dmasenddataproc (DMA2_ stream7,1);  Start a DMA transfer!  }//sends multibyte void Sendbytesinfoproc (u8* psendinfo, U16 Nsendcount) {u16 i = 0;u8 *pbuf = null;//points to send buffer PBuf = sendbuff;for (i=0; i<nsendcount; i++) {*pbuf++ = Psendinfo[i];} DMA send mode Dmasenddataproc (Dma2_stream7,nsendcount);  Start a DMA transfer! }//send complete interrupt void DMA2_STREAM7_IRQHAndler (void) {//Clear flag if (Dma_getflagstatus (DMA2_STREAM7,DMA_FLAG_TCIF7)!=reset)//wait for DMA2_STEAM7 transfer to complete {Dma_clearflag ( DMA2_STREAM7,DMA_FLAG_TCIF7)//Clear DMA2_STEAM7 transfer Complete flag}}//receive complete interrupt void Dma2_stream5_irqhandler (void) {//Clear flag if (Dma_ Getflagstatus (DMA2_STREAM5,DMA_FLAG_TCIF5)!=reset)//wait for DMA2_STEAM7 transfer to complete {dma_cmd (DMA2_STREAM5, DISABLE);//Turn off DMA, Prevent the processing of data uart1_receivesize =receive_buf_size-dma_getcurrdatacounter (DMA2_STREAM5); if (Uart1_receivesize!=0) { Ossempost (Dmareceivesize_sem);} Dma_clearflag (Dma2_stream5,dma_flag_tcif5 | Dma_flag_feif5 | Dma_flag_dmeif5 | Dma_flag_teif5 | DMA_FLAG_HTIF5);//clear DMA2_STEAM7 Transfer complete flag dma_setcurrdatacounter (DMA2_STREAM5, receive_buf_size);D Ma_cmd (DMA2_     STREAM5, ENABLE); Open dma,}}//idle interrupt void Usart1_irqhandler (void) {U16 data;if (Usart_getitstatus (usart1,usart_it_idle)! = RESET) {Dma_cmd (DMA2_STREAM5, DISABLE); Turn off DMA to prevent data = Usart1->sr;data = usart1->dr; during processing Uart1_receivesize =receive_buf_size-dma_getcurrdatacounter (DMA2_STREAM5); if (Uart1_receivesize!=0) {OSSemPoSt (DMARECEIVESIZE_SEM);} Dma_clearflag (Dma2_stream5,dma_flag_tcif5 | Dma_flag_feif5 | Dma_flag_dmeif5 | Dma_flag_teif5 | DMA_FLAG_HTIF5);//clear DMA2_STEAM7 Transfer complete flag dma_setcurrdatacounter (DMA2_STREAM5, receive_buf_size);D Ma_cmd (DMA2_     STREAM5, ENABLE);  Open DMA,}}


STM32F4 UART1 DMA sends and receives indeterminate length data

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.