Pick a USART DMA data (variable length)

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 }

 

 

Guess you like

Origin www.cnblogs.com/better-day/p/12600351.html