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) &USART1->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) &USART1->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