Content comes from: http: //blog.sina.com.cn/s/blog_777668c30102x4hz.html
1, DMA is well known that this is to do a good thing for developers to run bare metal is a boon. However, many engineers still under the previous approach to the design serial port, I saw a really anxious not. What good things like this storm sent heavenly! Many developers would probably say that I send and receive data DMA is fixed length are variable length what is the use? If you hear these words I guarantee that my colleagues have not properly studied DMA. Today his own transmitting and receiving variable length DMA program Tieshanglai. I hope you suffer less in the process of development.
2, in the process we have to start learning, says a secret STM32 serial interrupt. In previous designs with 51 MODBUS friends, many are known, MODBUS protocol stack, there is a frame interval judgment. Many people in order to design the frame head judge are blown up, but also add a timer, that this flag that marks a word vomit blood, I have eaten cry. In fact, just a MODBUS frame interval to determine his agreement, in fact, there is a byte judgment, what is the byte judge? Interval is transmitted byte by byte over. While we are all Cock wire, but we are also very brain, frame judgment are so much trouble, do not you dare call us bytes judge! Our group quit Cock wire directly to the standard protocol of this byte judge omitted for! No wrong is a living omitted! Program up and running OK. Oh, happy. Who can not tell. Oh, engaged MODBUS friends know. In addition to first see what the novice MODBUS protocol design their own protocol stack, he will go to the design of this byte interval, and then design does not come out, they begin to doubt their own abilities. Not really, you dare to design very much, just to avoid the veteran.
Having said that there is a ghost of what use? Of course, it is designed to allow us to understand what is the frame interval of the current global popular STM32 microcontroller actually have a frame interval judge interrupted, how good this thing! Since then designed this way MODBUS friends you can casually write a MODBUS protocol stack, and in do not worry, what a mess the frame interval.
Well, now we say STM32 frame interval. STM32 frame interval is when the serial data we receive a hardware will automatically determine whether the frame to the end, if the end will have free judgment IDLE. We just set a flag in the interrupt, our application will know, oh, an ending, well I can to deal with the data.
3, 1 serial port driver DMA driver IDLE interrupts.
The following is a .c file
1 void Usart1RccEnable ( void ) 2 { . 3 RCC_APB2PeriphClockCmd (RCC_APB2Periph_GPIOA, the ENABLE); // enable serial clock . 4 RCC_APB2PeriphClockCmd (RCC_APB2Periph_USART1, the ENABLE); // enable serial clock . 5 RCC_AHBPeriphClockCmd (RCC_AHBPeriph_DMA1, the ENABLE); // open DMA clock . 6 } . 7 . 8 void Usart1GpioConfig ( void ) . 9 { 10 GPIO_InitTypeDef GPIO_InitStructure; . 11 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; //The TX the USART1 12 is GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; 13 is GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; // multiplexing push-pull output 14 GPIO_Init (with GPIOA, & GPIO_InitStructure); // A port 15 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10; // the USART1 the RX 16 GPIO_InitStructure.GPIO_Mode GPIO_Mode_IN_FLOATING =; // multiplexing open drain input . 17 GPIO_Init (with GPIOA, & GPIO_InitStructure); // A port 18 is } . 19 20 is void Usart1DmaConfig ( void ) 21 is { 22 is DMA_InitTypeDef DMA_InitStructure; 23 is DMA_DeInit (DMA1_Channel5); 24 DMA_InitStructure.DMA_PeripheralBaseAddr = (U32) & USART1-> the DR; 25 DMA_InitStructure.DMA_MemoryBaseAddr = (U32) Usart1_Module_Struct.S_usart_dma_rx_buffer; // this is an initialization time to configure, re-run according to the procedure settings. 26 is DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC; 27 DMA_InitStructure.DMA_BufferSize = UART1_TX_RX_MAX_SIZE; 28 DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; 29 DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; 30 DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte; 31 DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte; 32 DMA_InitStructure.DMA_Mode = DMA_Mode_Normal; 33 DMA_InitStructure.DMA_Priority = DMA_Priority_Medium; 34 DMA_InitStructure.DMA_M2M = DMA_M2M_Disable; 35 DMA_Init(DMA1_Channel5, &DMA_InitStructure); 36 DMA_Cmd(DMA1_Channel5, ENABLE); 37 USART_DMACmd(USART1, USART_DMAReq_Rx, ENABLE); 38 } 39 40 voidUsart1Config ( void ) 41 { 42 USART_InitTypeDef USART_InitStructure; 43 USART_InitStructure.USART_BaudRate = BAUD_RATE; // 速率115200bps 44 USART_InitStructure.USART_WordLength = USART_WordLength_8b; // 数据位位8 45 USART_InitStructure.USART_StopBits = USART_StopBits_1; // 停止位1位 46 USART_InitStructure.USART_Parity = USART_Parity_No; // 无校验位 47 USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None; // 无硬件流控 48 = USART_Mode_Rx USART_InitStructure.USART_Mode | USART_Mode_Tx; // transceiver mode 49 USART_Init (the USART1, & USART_InitStructure); // serial configuration parameters function 50 USART_ITConfig (the USART1, USART_IT_TC, the DISABLE); // Serial Port Interrupt Enable 51 is USART_ITConfig (the USART1, USART_IT_RXNE, the DISABLE ); // serial port Receive interrupt enable 52 is USART_ITConfig (the USART1, USART_IT_IDLE, the eNABLE); // serial port interrupt enable idle 53 is USART_Cmd (the USART1, the eNABLE); 54 is USART_ClearFlag (the USART1, USART_FLAG_TC); 55 } 56 is 57 is void Usart1NvicConfig ( void ) 58 { 59 NVIC_InitTypeDef NVIC_InitStructure; 60 NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1); 61 NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn; // 串口中断配置 62 NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; 63 NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; 64 NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; 65 NVIC_Init(&NVIC_InitStructure); 66 NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1); 67 = DMA1_Channel4_IRQn NVIC_InitStructure.NVIC_IRQChannel; // serial interrupt configuration 68 NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0 ; 69 NVIC_InitStructure.NVIC_IRQChannelSubPriority = . 1 ; 70 NVIC_InitStructure.NVIC_IRQChannelCmd = the ENABLE; 71 is NVIC_Init (& NVIC_InitStructure); 72 } 73 is 74 void Usart1DmaStructInit ( void ) 75 { 76 Usart1_Module_Struct.S_rx_idle_flag the DISABLE =; // initializes to 0 IDLE, no data is sent 77 The ENABLE = Usart1_Module_Struct.S_dma_send_usart_flag; // initializes the DMA status bit 1 is set to start the first transmission. 78 } 79 80 void Usart1Init ( void ) 81 { 82 Usart1RccEnable (); 83 Usart1GpioConfig (); 84 Usart1Config (); 85 Usart1NvicConfig (); 86 Usart1DmaConfig (); 87 Usart1DmaStructInit (); 88 } 89 90 void Usart1SendData (uint8_t * Usart_TxBuffer, the Length uint32_t) 91 is { 92 DMA_InitTypeDef DMA_InitStructure; 93 while(Usart1_Module_Struct.S_dma_send_usart_flag == DISABLE); 94 Usart1_Module_Struct.S_dma_send_usart_flag = DISABLE; 95 DMA_DeInit(DMA1_Channel4); 96 RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE); 97 DMA_InitStructure.DMA_PeripheralBaseAddr = (u32)&USART1->DR; 98 DMA_InitStructure.DMA_MemoryBaseAddr = (u32)Usart_TxBuffer; 99 DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST; 100 DMA_InitStructure.DMA_BufferSize = Length; 101 DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; 102 DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; 103 DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte; 104 DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte; 105 DMA_InitStructure.DMA_Mode = DMA_Mode_Normal; 106 DMA_InitStructure.DMA_Priority = DMA_Priority_Medium; 107 DMA_InitStructure.DMA_M2M = DMA_M2M_Disable; 108 DMA_Init(DMA1_Channel4, &DMA_InitStructure); 109 DMA_ITConfig(DMA1_Channel4, DMA_IT_TC, ENABLE); 110 DMA_Cmd(DMA1_Channel4, ENABLE); 111 USART_DMACmd(USART1, USART_DMAReq_Tx, ENABLE); 112 } 113 114 void USART1_IRQHandler(void) 115 { 116 if(USART_GetITStatus(USART1, USART_IT_IDLE) != RESET) 117 { 118 Usart1_Module_Struct.S_dma_rx_usart_size = USART1->SR; 119 Usart1_Module_Struct.S_dma_rx_usart_size = USART1->DR; 120 DMA_Cmd(DMA1_Channel5,DISABLE); 121 Usart1_Module_Struct.S_dma_rx_usart_size = UART1_TX_RX_MAX_SIZE - DMA_GetCurrDataCounter(DMA1_Channel5); 122 DMA_SetCurrDataCounter(DMA1_Channel5,UART1_TX_RX_MAX_SIZE); 123 DMA_Cmd(DMA1_Channel5,ENABLE); 124 Usart1_Module_Struct.S_rx_idle_flag = 1; 125 } 126 } 127 128 129 130 131 void DMA1_Channel4_IRQHandler(void) 132 { 133 if(DMA_GetFlagStatus(DMA1_FLAG_TC4)==SET) 134 { 135 DMA_ClearFlag(DMA1_FLAG_TC4); 136 DMA_Cmd(DMA1_Channel4,DISABLE); 137 Usart1_Module_Struct.S_dma_send_usart_flag = ENABLE; 138 } 139 } 140 141 unsigned char GetUsart1DmaTxFlag( void ) 142 { 143 return Usart1_Module_Struct.S_dma_send_usart_flag; 144 } 145 146 unsigned char GetUsart1DmaRxFlag( void ) 147 { 148 return Usart1_Module_Struct.S_rx_idle_flag; 149 } 150 151 void SetUsart1DmaTxFlag( unsigned char status ) 152 { 153 Usart1_Module_Struct.S_dma_send_usart_flag = status; 154 } 155 156 void SetUsart1DmaRxFlag( unsigned char status ) 157 { 158 Usart1_Module_Struct.S_rx_idle_flag = status; 159 } 160 161 unsigned int GetUsart1DmaRxSize( void ) 162 { 163 return Usart1_Module_Struct.S_dma_rx_usart_size; 164 } 165 166 void SetUsart1DmaRxSize( void ) 167 { 168 Usart1_Module_Struct.S_dma_rx_usart_size = 0; 169 }
The following is a .h file
. 1 #ifndef _usart1_h 2 #define _usart1_h . 3 #include " public.h " . 4 #ifdef _usart1_C . 5 #define _usart1_ext . 6 #else . 7 #define _usart1_ext extern . 8 #endif . 9 10 #define BAUD_RATE 115200 . 11 #define UART1_TX_RX_MAX_SIZE 1460 12 is 13 is typedef struct 14 { 15 unsigned char __IO S_dma_send_usart_flag; // the status flag indicates the end of the DMA transfer, if the flag is NO Do not use DMA with resource consumption. 16 unsigned int __IO S_dma_rx_usart_size; // receives an end of data, acquires the frame length . 17 unsigned char __IO S_rx_idle_flag; // receiving an end flag 18 is unsigned char S_usart_dma_tx_buffer [UART1_TX_RX_MAX_SIZE]; // Transmit Buffer Buffer . 19 unsigned char S_usart_dma_rx_buffer [UART1_TX_RX_MAX_SIZE]; // receive buffer buffer 20 is } Usart_p; 21 is 22 is _usart1_ext Usart_p Usart1_Module_Struct; 23 is 24 _usart1_ext void Usart1Init ( void ); 25 _usart1_ext void Usart1SendData(uint8_t *Usart_TxBuffer, uint32_t Length); 26 _usart1_ext unsigned char GetUsart1DmaTxFlag( void ); 27 _usart1_ext unsigned char GetUsart1DmaRxFlag( void ); 28 _usart1_ext void SetUsart1DmaTxFlag( unsigned char status ); 29 _usart1_ext void SetUsart1DmaRxFlag( unsigned char status ); 30 _usart1_ext unsigned int GetUsart1DmaRxSize( void ); 31 _usart1_ext void SetUsart1DmaRxSize( void ); 32 33 #endif 34 35 36 //用户应用: 37 int main( void ) 38 { 39 SystemInit(); 40 Usart1Init(); 41 while(1) 42 { 43 if(GetUsart1DmaRxFlag()==TRUE) 44 { 45 SetUsart1DmaRxFlag(FALSE); 46 Usart1SendData(Usart1_Module_Struct.S_usart_dma_rx_buffer,GetUsart1DmaRxSize()); 47 } 48 } 49 }