Forum: Mikrocontroller und Digitale Elektronik STM32: Seriell senden via DMA funktioniert zwar, aber wo wird´s gestartet?


von Fun R. (funnyrice)


Lesenswert?

Hallo Leute,

habe hier einen erweiterten Beispielcode in dem nach dem Einschalten 
seriell via DMA gesendet wird. Soweit funktioniert es.
Nun wollte ich einfach den gleichen String, nach Joystickbetätigung 
(Primer2), nochmal senden. Die Joysick-Funktion funktioniert auch und 
habe dort den Code eingefügt.
1
          /* USARTz TX DMA1 Channel (triggered by USARTz Tx event) Config */
2
        DMA_DeInit(USARTz_Tx_DMA_Channel);  
3
        DMA_InitStructure.DMA_PeripheralBaseAddr = USARTz_DR_Base;
4
        DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)TxBuffer2;
5
        DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;
6
        DMA_InitStructure.DMA_BufferSize = TxBufferSize2;  
7
        DMA_Init(USARTz_Tx_DMA_Channel, &DMA_InitStructure);

Leider wird nach Aufrufen der Funktion der String kein zweites Mal 
gesendet?!?

Wo ist denn mein Denkfehler?
Hab die ganze Code mal angehangen.

MfG
FunRice

1
/* Includes ------------------------------------------------------------------*/
2
#include "stm32f10x.h"
3
#include "platform_config.h"
4
#include "stm32f10x_dma.h"
5
#include "stm32f10x_rcc.h"
6
#include "misc.h"
7
#include "stm32f10x_usart.h"
8
#include "stm32f10x_tim.h"
9
#include "stm32f10x_it.h"
10
#include "stm32f10x_flash.h"
11
#include "stm32f10x_tim.h"
12
#include "lib_dbg.h"
13
14
/** @addtogroup STM32F10x_StdPeriph_Examples
15
  * @{
16
  */
17
18
/** @addtogroup USART_DMA_Polling
19
  * @{
20
  */ 
21
22
/* Private typedef -----------------------------------------------------------*/
23
typedef enum { FAILED = 0, PASSED = !FAILED} TestStatus;
24
25
/* Private define ------------------------------------------------------------*/
26
#define DEBUG
27
28
#define TxBufferSize1   (countof(TxBuffer1) - 1)
29
#define TxBufferSize2   (countof(TxBuffer2) - 1)
30
31
//LEDs port and pins
32
#define LEDS_GPIO       (GPIOE)
33
#define LEDS_RCC_GPIO   (RCC_APB2Periph_GPIOE)
34
#define LED0_PIN        (GPIO_Pin_0)
35
#define LED1_PIN        (GPIO_Pin_1)
36
#define LEDS_BOTH_PINS  (LED0_PIN|LED1_PIN)
37
38
//joystick port and pins
39
#define JSTK_GPIO       (GPIOE)
40
#define JSTK_RCC_GPIO   (RCC_APB2Periph_GPIOE)
41
#define JSTK_LEFT_PIN   (GPIO_Pin_3)
42
#define JSTK_RIGHT_PIN  (GPIO_Pin_4)
43
#define JSTK_UP_PIN     (GPIO_Pin_5)
44
#define JSTK_DOWN_PIN   (GPIO_Pin_6)
45
#define JSTK_ALL_PINS   (JSTK_LEFT_PIN|JSTK_RIGHT_PIN|JSTK_UP_PIN|JSTK_DOWN_PIN)
46
47
//push button port and pin
48
#define BP_GPIO         (GPIOA)
49
#define BP_RCC_GPIO     (RCC_APB2Periph_GPIOA)
50
#define BP_PIN          (GPIO_Pin_8)
51
52
53
//LCD backlight enable port and pin
54
#define LCDBLEN_GPIO         (GPIOB)
55
#define LCDBLEN_RCC_GPIO     (RCC_APB2Periph_GPIOB)
56
#define LCDBLEN_PIN          (GPIO_Pin_8)
57
58
59
60
61
62
/* Private macro -------------------------------------------------------------*/
63
#define countof(a)   (sizeof(a) / sizeof(*(a)))
64
65
/* Private variables ---------------------------------------------------------*/
66
USART_InitTypeDef USART_InitStructure;
67
uint8_t TxBuffer1[] = "1 USART DMA Polling: USARTy -> USARTz using DMA";
68
uint8_t TxBuffer2[] = "2 USART DMA Polling: USARTz -> USARTy using DMA";
69
uint8_t RxBuffer1[TxBufferSize2];
70
uint8_t RxBuffer2[TxBufferSize1];
71
volatile TestStatus TransferStatus1 = FAILED;
72
volatile TestStatus TransferStatus2 = FAILED; 
73
ErrorStatus HSEStartUpStatus; 
74
75
vu16 CCR1_Val = 480;
76
vu16 CCR2_Val = 32768;
77
vu16 CCR3_Val = 16384;
78
vu16 CCR4_Val = 8192; 
79
80
u16     u16ActInputGPIOE = 0;
81
u16     u16PreInputGPIOE = 0;
82
u16     u16DeboInputGPIOE = 0;
83
u16     u16InvertRegGPIOE = 0;
84
u16     u16FallInputGPIOE = 0;
85
u16     u16RiseInputGPIOE = 0;
86
87
volatile bool bTimer2Ch1Int = 0; 
88
89
90
91
/* Private function prototypes -----------------------------------------------*/
92
void RCC_Configuration(void);
93
void GPIO_Configuration(void);
94
void USART_Configuration(void);
95
void DMA_Configuration(void);
96
void NVIC_Configuration(void);
97
void TIM2_Configuration(void);
98
void GetGPIOE(void);
99
void PinChangeGPIOE(void);
100
101
void MainLoop(void);
102
void MainFunction(void);
103
104
TestStatus Buffercmp(uint8_t* pBuffer1, uint8_t* pBuffer2, uint16_t BufferLength);
105
106
/* Private functions ---------------------------------------------------------*/
107
108
/**
109
  * @brief   Main program
110
  * @param  None
111
  * @retval None
112
  */
113
int main(void)
114
{
115
#ifdef DEBUG
116
  debug();
117
#endif 
118
119
  /* System Clocks Configuration */
120
  RCC_Configuration();
121
  NVIC_Configuration();
122
  /* Configure the GPIO ports */
123
  GPIO_Configuration();
124
125
  /* Configure the DMA */
126
  DMA_Configuration();
127
  USART_Configuration();
128
  TIM2_Configuration(); 
129
130
    MainLoop();
131
132
 while(1){};
133
  }
134
135
void MainLoop(void)
136
{
137
while(1)
138
    {
139
     if(bTimer2Ch1Int)
140
        {
141
         bTimer2Ch1Int = 0;
142
        
143
144
  
145
        //MainFunction();
146
         GetGPIOE();
147
        }
148
    }
149
}
150
void MainFunction(void)
151
{
152
 GetGPIOE();
153
  /* Wait until USARTy TX DMA1 Channel Transfer Complete */
154
  while (DMA_GetFlagStatus(USARTy_Tx_DMA_FLAG) == RESET)
155
  {
156
  }
157
158
  /* Wait until USARTy RX DMA1 Channel Transfer Complete */
159
  while (DMA_GetFlagStatus(USARTy_Rx_DMA_FLAG) == RESET)
160
  {
161
  }
162
163
  /* Wait until USARTz TX DMA1 Channel Transfer Complete */
164
  while (DMA_GetFlagStatus(USARTz_Tx_DMA_FLAG) == RESET)
165
  {
166
  }
167
//GPIO_WriteBit(GPIOB, GPIO_Pin_6, (BitAction)(1 - GPIO_ReadOutputDataBit(GPIOB, GPIO_Pin_6)));
168
169
  /* Wait until USARTz RX DMA1 Channel Transfer Complete */
170
  while (DMA_GetFlagStatus(USARTz_Rx_DMA_FLAG) == RESET)
171
  {
172
  }
173
GPIO_WriteBit(GPIOB, GPIO_Pin_6, (BitAction)(1 - GPIO_ReadOutputDataBit(GPIOB, GPIO_Pin_6)));
174
175
  /* Check the received data with the send ones */
176
  TransferStatus1 = Buffercmp(TxBuffer2, RxBuffer1, TxBufferSize2);
177
  /* TransferStatus1 = PASSED, if the data transmitted from USARTz and  
178
     received by USARTy are the same */
179
  /* TransferStatus1 = FAILED, if the data transmitted from USARTz and 
180
     received by USARTy are different */
181
  TransferStatus2 = Buffercmp(TxBuffer1, RxBuffer2, TxBufferSize1);
182
  /* TransferStatus2 = PASSED, if the data transmitted from USARTy and  
183
     received by USARTz are the same */
184
  /* TransferStatus2 = FAILED, if the data transmitted from USARTy and 
185
     received by USARTz are different */
186
187
  while (1)
188
  {
189
  }
190
}
191
192
/**
193
  * @brief  Configures the different system clocks.
194
  * @param  None
195
  * @retval None
196
  */
197
198
void GetGPIOE()
199
{
200
 u16FallInputGPIOE = 0;
201
 u16RiseInputGPIOE = 0;
202
203
 u16PreInputGPIOE = u16ActInputGPIOE;
204
 u16ActInputGPIOE = ((u16)JSTK_GPIO->IDR) & ( JSTK_ALL_PINS );
205
 //u16ActInputGPIOE = ( (GPIO_ReadInputData(JSTK_GPIO))  );
206
 u16ActInputGPIOE ^= u16InvertRegGPIOE;
207
208
 if(u16ActInputGPIOE == u16PreInputGPIOE)
209
    {    
210
     if(u16DeboInputGPIOE != u16PreInputGPIOE)
211
        {
212
         u16FallInputGPIOE = u16DeboInputGPIOE;
213
         u16FallInputGPIOE ^= u16ActInputGPIOE;
214
         u16RiseInputGPIOE = u16FallInputGPIOE;
215
         u16FallInputGPIOE &= u16DeboInputGPIOE;
216
         u16RiseInputGPIOE &= u16ActInputGPIOE;
217
         u16DeboInputGPIOE = u16PreInputGPIOE;
218
     
219
         PinChangeGPIOE();
220
     
221
        }
222
    }
223
}
224
225
void PinChangeGPIOE()
226
{
227
DMA_InitTypeDef DMA_InitStructure;
228
229
    if(u16RiseInputGPIOE& JSTK_UP_PIN) 
230
        {
231
          /* USARTz TX DMA1 Channel (triggered by USARTz Tx event) Config */
232
        DMA_DeInit(USARTz_Tx_DMA_Channel);  
233
        DMA_InitStructure.DMA_PeripheralBaseAddr = USARTz_DR_Base;
234
        DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)TxBuffer2;
235
        DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;
236
        DMA_InitStructure.DMA_BufferSize = TxBufferSize2;  
237
        DMA_Init(USARTz_Tx_DMA_Channel, &DMA_InitStructure);
238
        
239
        // Nur als Funktionstest
240
        GPIO_SetBits(GPIOE, GPIO_Pin_0);
241
    }
242
243
        if(u16RiseInputGPIOE& JSTK_DOWN_PIN)
244
        GPIO_ResetBits(GPIOE, GPIO_Pin_0);
245
    
246
    GPIO_WriteBit(GPIOE, GPIO_Pin_1, (BitAction)(1 - GPIO_ReadOutputDataBit(GPIOE, GPIO_Pin_1)));
247
248
}
249
250
void RCC_Configuration(void)
251
{
252
253
  /* SYSCLK, HCLK, PCLK2 and PCLK1 configuration -----------------------------*/   
254
  /* RCC system reset(for debug purpose) */
255
  RCC_DeInit();
256
257
  /* DMA clock enable */
258
  RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);
259
260
  /* Enable HSE */
261
  RCC_HSEConfig(RCC_HSE_ON);
262
263
  /* Wait till HSE is ready */
264
  HSEStartUpStatus = RCC_WaitForHSEStartUp();
265
266
  if (HSEStartUpStatus == SUCCESS)
267
  {
268
    /* Enable Prefetch Buffer */
269
    FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable);
270
271
    /* Flash 2 wait state */
272
    FLASH_SetLatency(FLASH_Latency_2);
273
 
274
    /* HCLK = SYSCLK */
275
    RCC_HCLKConfig(RCC_SYSCLK_Div1); 
276
  
277
    /* PCLK2 = HCLK */
278
    RCC_PCLK2Config(RCC_HCLK_Div1); 
279
280
    /* PCLK1 = HCLK/2 */
281
    RCC_PCLK1Config(RCC_HCLK_Div2);
282
283
    /* PLLCLK = 12MHz * 6 = 72 MHz */
284
    RCC_PLLConfig(RCC_PLLSource_HSE_Div1, RCC_PLLMul_6);
285
286
    /* Enable PLL */ 
287
    RCC_PLLCmd(ENABLE);
288
289
    /* Wait till PLL is ready */
290
    while (RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET)
291
    {
292
    }
293
294
    /* Select PLL as system clock source */
295
    RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);
296
297
    /* Wait till PLL is used as system clock source */
298
    while(RCC_GetSYSCLKSource() != 0x08)
299
    {
300
    }
301
  }
302
  else
303
  { /* If HSE fails to start-up, the application will have wrong clock configuration.
304
       User can add here some code to deal with this error */    
305
306
    /* Go to infinite loop */
307
    while (1)
308
    {
309
    }
310
311
312
313
  }
314
315
  /* TIM2 clock enable */
316
  RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
317
318
  /* GPIOC clock enable */
319
//  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);    
320
321
  /* Enable USART1, GPIOA, GPIOD and AFIO clocks */
322
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1 |
323
                         RCC_APB2Periph_GPIOA |
324
                         RCC_APB2Periph_GPIOB |
325
                         RCC_APB2Periph_AFIO, ENABLE);
326
  /* Enable USART2 clock */
327
  RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);
328
} 
329
/*******************************************************************************
330
* Function Name  : NVIC_Configuration
331
* Description    : Configures Vector Table base location.
332
* Input          : None
333
* Output         : None
334
* Return         : None
335
*******************************************************************************/
336
void NVIC_Configuration(void)
337
{  
338
 NVIC_InitTypeDef NVIC_InitStructure;
339
340
#ifdef  VECT_TAB_RAM  
341
  /* Set the Vector Table base location at 0x20000000 */ 
342
  NVIC_SetVectorTable(NVIC_VectTab_RAM, 0x0); 
343
#else  /* VECT_TAB_FLASH  */
344
  /* Set the Vector Table base location at 0x08000000 */ 
345
  NVIC_SetVectorTable(NVIC_VectTab_FLASH, 0x0);   
346
#endif
347
348
349
  /* Enable the TIM2 gloabal Interrupt */
350
  NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;
351
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
352
  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
353
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
354
355
  NVIC_Init(&NVIC_InitStructure);
356
357
}
358
359
/**
360
  * @brief  Configures the different GPIO ports.
361
  * @param  None
362
  * @retval None
363
  */
364
void GPIO_Configuration(void)
365
{
366
  GPIO_InitTypeDef GPIO_InitStructure;
367
368
#ifdef USE_STM3210C_EVAL
369
  /* Enable the USART3 Pins Software Remapping */
370
  GPIO_PinRemapConfig(GPIO_PartialRemap_USART3, ENABLE);
371
  
372
  /* Enable the USART2 Pins Software Remapping */
373
  GPIO_PinRemapConfig(GPIO_Remap_USART2, ENABLE);  
374
#elif defined USE_STM3210B_EVAL
375
  /* Enable the USART2 Pins Software Remapping */
376
  GPIO_PinRemapConfig(GPIO_Remap_USART2, ENABLE);
377
#endif
378
379
  /* Configure USARTy Rx as input floating */
380
  GPIO_InitStructure.GPIO_Pin = USARTy_RxPin;
381
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
382
  GPIO_Init(USARTy_GPIO, &GPIO_InitStructure);
383
  
384
  /* Configure USARTz Rx as input floating */
385
  GPIO_InitStructure.GPIO_Pin = USARTz_RxPin;
386
  GPIO_Init(USARTz_GPIO, &GPIO_InitStructure);  
387
  
388
  /* Configure USARTy Tx as alternate function push-pull */
389
  GPIO_InitStructure.GPIO_Pin = USARTy_TxPin;
390
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
391
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
392
  GPIO_Init(USARTy_GPIO, &GPIO_InitStructure);
393
394
  /* Configure USARTz Tx as alternate function push-pull */
395
  GPIO_InitStructure.GPIO_Pin = USARTz_TxPin;
396
  GPIO_Init(USARTz_GPIO, &GPIO_InitStructure); 
397
  
398
  /* Configure (PB.06) as output push-pull */
399
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7;
400
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
401
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
402
  GPIO_Init(GPIOB, &GPIO_InitStructure);  
403
  
404
    // Enable LEDs GPIO clock 
405
    if(LEDS_RCC_GPIO!=LCDBLEN_RCC_GPIO)
406
        RCC_APB2PeriphClockCmd(LEDS_RCC_GPIO, ENABLE);
407
408
    // Configure PE.00 and PE.01 as output push-pull 
409
    GPIO_InitStructure.GPIO_Pin =  LEDS_BOTH_PINS;
410
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
411
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
412
    GPIO_Init(LEDS_GPIO, &GPIO_InitStructure);  
413
  
414
415
   // Enable joystick GPIO clock 
416
    if( (JSTK_RCC_GPIO!=LCDBLEN_RCC_GPIO) && (JSTK_RCC_GPIO!=LEDS_RCC_GPIO) )
417
        RCC_APB2PeriphClockCmd(JSTK_RCC_GPIO, ENABLE);
418
419
    // Configure PE.03 to PE.06 as input 
420
    GPIO_InitStructure.GPIO_Pin = JSTK_ALL_PINS;
421
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD;
422
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
423
    GPIO_Init(JSTK_GPIO, &GPIO_InitStructure); 
424
}
425
/* USARTy and USARTz configuration ------------------------------------------------------*/
426
  /* USARTy and USARTz configured as follow:
427
        - BaudRate = 230400 baud  
428
        - Word Length = 8 Bits
429
        - One Stop Bit
430
        - No parity
431
        - Hardware flow control disabled (RTS and CTS signals)
432
        - Receive and transmit enabled
433
  */
434
void USART_Configuration(void)
435
{
436
  USART_InitStructure.USART_BaudRate = 115200;
437
  USART_InitStructure.USART_WordLength = USART_WordLength_8b;
438
  USART_InitStructure.USART_StopBits = USART_StopBits_1;
439
  USART_InitStructure.USART_Parity = USART_Parity_No;
440
  USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
441
  USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
442
  
443
  /* Configure USARTy */
444
  USART_Init(USARTy, &USART_InitStructure);
445
  /* Configure USARTz */
446
  USART_Init(USARTz, &USART_InitStructure);
447
448
  /* Enable USARTy DMA Rx and TX request */
449
  USART_DMACmd(USARTy, USART_DMAReq_Rx | USART_DMAReq_Tx, ENABLE);
450
  /* Enable USARTz DMA Rx and TX request */
451
  USART_DMACmd(USARTz, USART_DMAReq_Rx | USART_DMAReq_Tx, ENABLE);
452
453
454
  
455
  /* Enable the USARTy */
456
  USART_Cmd(USARTy, ENABLE);
457
  /* Enable the USARTz */
458
  USART_Cmd(USARTz, ENABLE);
459
460
}
461
/**
462
  * @brief  Configures the DMA.
463
  * @param  None
464
  * @retval None
465
  */
466
void DMA_Configuration(void)
467
{
468
  DMA_InitTypeDef DMA_InitStructure;
469
470
  /* USARTy TX DMA1 Channel (triggered by USARTy Tx event) Config */
471
  DMA_DeInit(USARTy_Tx_DMA_Channel); 
472
  DMA_InitStructure.DMA_PeripheralBaseAddr = USARTy_DR_Base;
473
  DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)TxBuffer1;
474
  DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;
475
  DMA_InitStructure.DMA_BufferSize = TxBufferSize1;
476
  DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
477
  DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
478
  DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
479
  DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
480
  DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;
481
  DMA_InitStructure.DMA_Priority = DMA_Priority_VeryHigh;
482
  DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
483
  DMA_Init(USARTy_Tx_DMA_Channel, &DMA_InitStructure);
484
485
  /* USARTy RX DMA1 Channel (triggered by USARTy Rx event) Config */
486
  DMA_DeInit(USARTy_Rx_DMA_Channel);  
487
  DMA_InitStructure.DMA_PeripheralBaseAddr = USARTy_DR_Base;
488
  DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)RxBuffer1;
489
  DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;
490
  DMA_InitStructure.DMA_BufferSize = TxBufferSize2;
491
  DMA_Init(USARTy_Rx_DMA_Channel, &DMA_InitStructure);
492
  
493
  /* USARTz TX DMA1 Channel (triggered by USARTz Tx event) Config */
494
  DMA_DeInit(USARTz_Tx_DMA_Channel);  
495
  DMA_InitStructure.DMA_PeripheralBaseAddr = USARTz_DR_Base;
496
  DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)TxBuffer2;
497
  DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;
498
  DMA_InitStructure.DMA_BufferSize = TxBufferSize2;  
499
  DMA_Init(USARTz_Tx_DMA_Channel, &DMA_InitStructure);
500
  
501
  /* USARTz RX DMA1 Channel (triggered by USARTz Rx event) Config */
502
  DMA_DeInit(USARTz_Rx_DMA_Channel);  
503
  DMA_InitStructure.DMA_PeripheralBaseAddr = USARTz_DR_Base;
504
  DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)RxBuffer2;
505
  DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;
506
  DMA_InitStructure.DMA_BufferSize = TxBufferSize1;
507
  DMA_Init(USARTz_Rx_DMA_Channel, &DMA_InitStructure);  
508
  
509
    /* Enable USARTy TX DMA1 Channel */
510
  DMA_Cmd(USARTy_Tx_DMA_Channel, ENABLE);
511
  /* Enable USARTy RX DMA1 Channel */
512
  DMA_Cmd(USARTy_Rx_DMA_Channel, ENABLE);
513
514
  /* Enable USARTz TX DMA1 Channel */
515
  DMA_Cmd(USARTz_Tx_DMA_Channel, ENABLE);
516
  /* Enable USARTz RX DMA1 Channel */
517
  DMA_Cmd(USARTz_Rx_DMA_Channel, ENABLE);
518
}
519
void TIM2_Configuration(void)
520
{
521
/* ---------------------------------------------------------------
522
    TIM2 Configuration: Output Compare Timing Mode:
523
    TIM2CLK = 36 MHz, Prescaler = 4, TIM2 counter clock = 7.2 MHz
524
    CC1 update rate = TIM2 counter clock / CCR1_Val = 146.48 Hz
525
    CC2 update rate = TIM2 counter clock / CCR2_Val = 219.7 Hz
526
    CC3 update rate = TIM2 counter clock / CCR3_Val = 439.4 Hz
527
    CC4 update rate = TIM2 counter clock / CCR4_Val =  878.9 Hz
528
  --------------------------------------------------------------- */
529
TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
530
TIM_OCInitTypeDef  TIM_OCInitStructure;
531
532
  /* Time base configuration */
533
  TIM_TimeBaseStructure.TIM_Period = 65535;
534
  TIM_TimeBaseStructure.TIM_Prescaler = 0;
535
  TIM_TimeBaseStructure.TIM_ClockDivision = 0;
536
  TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
537
538
  TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);
539
540
  /* Prescaler configuration */
541
  TIM_PrescalerConfig(TIM2, 4, TIM_PSCReloadMode_Immediate);
542
543
  /* Output Compare Timing Mode configuration: Channel1 */
544
  TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_Timing;
545
  TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
546
  TIM_OCInitStructure.TIM_Pulse = CCR1_Val;
547
  TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; 
548
549
  TIM_OC1Init(TIM2, &TIM_OCInitStructure);
550
  TIM_OC1PreloadConfig(TIM2, TIM_OCPreload_Disable);
551
  
552
  /* Output Compare Timing Mode configuration: Channel2 */
553
  TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
554
  TIM_OCInitStructure.TIM_Pulse = CCR2_Val;
555
556
  TIM_OC2Init(TIM2, &TIM_OCInitStructure);
557
558
  TIM_OC2PreloadConfig(TIM2, TIM_OCPreload_Disable);
559
560
  /* Output Compare Timing Mode configuration: Channel3 */
561
  TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
562
  TIM_OCInitStructure.TIM_Pulse = CCR3_Val;
563
564
  TIM_OC3Init(TIM2, &TIM_OCInitStructure);
565
566
  TIM_OC3PreloadConfig(TIM2, TIM_OCPreload_Disable);
567
568
  /* Output Compare Timing Mode configuration: Channel4 */
569
  TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
570
  TIM_OCInitStructure.TIM_Pulse = CCR4_Val;
571
572
  TIM_OC4Init(TIM2, &TIM_OCInitStructure);
573
574
  TIM_OC4PreloadConfig(TIM2, TIM_OCPreload_Disable);
575
576
  /* TIM IT enable */
577
  TIM_ITConfig(TIM2, TIM_IT_CC1 | TIM_IT_CC2 | TIM_IT_CC3 | TIM_IT_CC4, ENABLE);
578
579
  /* TIM2 enable counter */
580
  TIM_Cmd(TIM2, ENABLE);
581
582
}
583
584
/**
585
  * @brief  Compares two buffers.
586
  * @param  pBuffer1, pBuffer2: buffers to be compared.
587
  * @param  BufferLength: buffer's length
588
  * @retval PASSED: pBuffer1 identical to pBuffer2
589
  *   FAILED: pBuffer1 differs from pBuffer2
590
  */
591
TestStatus Buffercmp(uint8_t* pBuffer1, uint8_t* pBuffer2, uint16_t BufferLength)
592
{
593
  while(BufferLength--)
594
  {
595
    if(*pBuffer1 != *pBuffer2)
596
    {
597
      return FAILED;
598
    }
599
600
    pBuffer1++;
601
    pBuffer2++;
602
  }
603
604
  return PASSED;
605
}
606
607
#ifdef  USE_FULL_ASSERT
608
609
/**
610
  * @brief  Reports the name of the source file and the source line number
611
  *   where the assert_param error has occurred.
612
  * @param  file: pointer to the source file name
613
  * @param  line: assert_param error line source number
614
  * @retval None
615
  */
616
void assert_failed(uint8_t* file, uint32_t line)
617
{ 
618
  /* User can add his own implementation to report the file name and line number,
619
     ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
620
621
  /* Infinite loop */
622
  while (1)
623
  {
624
  }
625
}
626
#endif

von (prx) A. K. (prx)


Lesenswert?

Langen Code bitte als Anhang!

von Fun R. (funnyrice)


Lesenswert?

OK, mach ich beim nächsten Mal.
Kann´s jetzt leider nicht mehr rückgängig machen.

MfG
FunRice

von Heiko (Gast)


Lesenswert?

Ich hab zwar noch nichts mit DMA gemacht, aber das hier klingt so, als 
müsste man es auch noch setzen...
1
    /* Enable USARTy TX DMA1 Channel */
2
  DMA_Cmd(USARTy_Tx_DMA_Channel, ENABLE);
3
  /* Enable USARTy RX DMA1 Channel */
4
  DMA_Cmd(USARTy_Rx_DMA_Channel, ENABLE);
5
6
  /* Enable USARTz TX DMA1 Channel */
7
  DMA_Cmd(USARTz_Tx_DMA_Channel, ENABLE);
8
  /* Enable USARTz RX DMA1 Channel */
9
  DMA_Cmd(USARTz_Rx_DMA_Channel, ENABLE);

MfG, Heiko

von gsdfgsd (Gast)


Lesenswert?

Du initialisierst ja nur den DMA, du solltest auch den SW-Trigger setzen 
danach.

Geraten, ohne jetzt genau die FW-LIb oder den STM32 zu kennnen...

von Fun R. (funnyrice)


Lesenswert?

Hallo,

genau da ist ja mein Verständnisproblem.

Beim Starten wird der String ja gesendet. aber wo/wie der Trigger 
gesetzt wird, verstehe ich nicht.

MfG
FunRice

von (prx) A. K. (prx)


Lesenswert?

Da der DMA-Kanal mit dem UART-Transmitter verbunden ist, ist ein 
Software-Trigger nicht erforderlich. Das DMA wird ausgelöst, wenn der 
Transmit-Puffer Platz hat. Wenn man den Transmitter nicht explizit 
abschaltet, dann ist das automatisch gegeben.

Allerdings reicht die Neu-Initialisierung des Kanals allein nicht aus, 
wie Heiko schon anmerkte. Er muss auch eingeschaltet werden. DMA_DeInit 
schaltet ihn aus und DMA_Init verhält sich dazu neutral - das halte ich 
übrigens für ziemlich zweifelhaft, denn wenn man diese Funktion bei 
eingeschaltetem DMA aufruft, dann riskiert man einen Amoklauf. Erst 
DMA_Cmd schaltet den Kanal wieder ein.

Freilich reicht es aus, an Stelle des elend langen DMA_DeInit vor dem 
erneuten DMA_Init einfach nur per DMA_Cmd den Kanal auszuschalten.

IMHO kommt man oft nicht darum herum, die Funktion der Hardware anhand 
der Referenz zu verstehen und für die Nutzung der FWlib deren Umsetzung 
auf die Hardware anhand des Quellcodes zu studieren.

von Fun R. (funnyrice)


Lesenswert?

A. K. schrieb:
> IMHO kommt man oft nicht darum herum, die Funktion der Hardware anhand
> der Referenz zu verstehen und für die Nutzung der FWlib deren Umsetzung
> auf die Hardware anhand des Quellcodes zu studieren.

Nun ja, das wäre die optimale Vorgehensweise.

Habe
1
        DMA_DeInit(USARTz_Tx_DMA_Channel);  
2
        DMA_InitStructure.DMA_PeripheralBaseAddr = USARTz_DR_Base;
3
        DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)TxBuffer2;
4
        DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;
5
        DMA_InitStructure.DMA_BufferSize = TxBufferSize2;  
6
        DMA_Init(USARTz_Tx_DMA_Channel, &DMA_InitStructure)
durch
1
        DMA_Cmd(USARTz_Tx_DMA_Channel,SET);
ersetzt.

Funktioniert leider noch immer nicht.
Ist ja unfassbar, was für ein Aufwand man betreiben muß, um mittels DMA 
zu senden.
Merkwürdig(für mich), daß es beim Starten einmalig funktioniert.

MfG
FunRice

von (prx) A. K. (prx)


Lesenswert?

Fun Rice schrieb:

> Funktioniert leider noch immer nicht.

Wundert mich nicht. Ein paar der DMA-Register ändern im Betrieb ihren 
Wert, nämlich der Zähler und die Speicheradresse. Wenn der Zähler mal 0 
ist, dann kannst du den Kanal einschalten so oft du willst.

Es läuft eher auf
        DMA_Cmd(USARTz_Tx_DMA_Channel,RESET); -- oder so ähnlich
        DMA_InitStructure.DMA_PeripheralBaseAddr = USARTz_DR_Base;
        DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)TxBuffer2;
        DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;
        DMA_InitStructure.DMA_BufferSize = TxBufferSize2;
        DMA_Init(USARTz_Tx_DMA_Channel, &DMA_InitStructure)
        DMA_Cmd(USARTz_Tx_DMA_Channel,SET);
hinaus.

> Ist ja unfassbar, was für ein Aufwand man betreiben muß,
> um mittels DMA zu senden.

Der Aufwand an notwendiger Codierung ist recht gering (*), der Aufwand 
an Verständnis deutlich höher ;-).

*: Jedenfalls wenn man nur das tut, was die Hardware verlangt. Die kann 
nichts dafür, dass es mit der FWlib deutlich komplizierter aussieht. 
Eigentlich muss man nämlich nur: abschalten, Zähler+Adresse setzen, 
einschalten. Das sind 4 Programmzeilen.

von Fun R. (funnyrice)


Lesenswert?

Hmm, ist der Adresszähler gemeint.

Folgendes bleibt dann auch wirkungslos:
1
          /* USARTz TX DMA1 Channel (triggered by USARTz Tx event) Config */
2
        DMA_DeInit(USARTz_Tx_DMA_Channel);  
3
        DMA_InitStructure.DMA_PeripheralBaseAddr = USARTz_DR_Base;
4
        DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)TxBuffer2;
5
        DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;
6
        DMA_InitStructure.DMA_BufferSize = TxBufferSize2;  
7
        DMA_Init(USARTz_Tx_DMA_Channel, &DMA_InitStructure);
8
        
9
        DMA_Cmd(USARTz_Tx_DMA_Channel,SET);

Vielleicht finde ich ja ein "begreifbares" Tutorial über STM32+DMA, wenn 
ich nicht über das Forum auf "´ne schnelle Lösung" komme.

MfG
FunRice

von (prx) A. K. (prx)


Lesenswert?

Nebenbei: USART-Empfang mit DMA ist nicht wirklich der einfachste Weg, 
DMA kennenzulernen. Weil du meistens nicht im Voraus weisst, wieviele 
Bytes demnächst noch eintrudeln werden, der DMA-Kanal aber genau das 
wissen will. Da kriegt man es dann mit dem circular mode, dem half 
transfer interrupt und möglicherweise auch timeouts zu tun, evtl. 
garniert mit race conditions. Senden ist ok, aber empfangen... (es gibt 
deshalb eine Appnote dazu).

von Fun R. (funnyrice)


Lesenswert?

Hab´s mir mit Hilfe der Beispielcodes "DMA_Polling" viel einfacher 
vorgestellt. Daraus geht aber nicht hervor, wie man mehr als ein Mal 
sendet. Ist echt für´n Popo.

MfG
FunRice

von (prx) A. K. (prx)


Lesenswert?

Ich habe das mal ausprobiert. Funktioniert so wie es soll. Jede Sekunde 
ein "Hallo".

Der Code enthält ein paar Funktionen und Bitnamen aus meiner eigenen 
Umgebung, beispielsweise Zeug wie DMA_CCR_DIR_mem2per - aber hier geht 
es um die Demonstration des Prinzips, nicht um eine copy-and-paste 
Vorlage.
1
char hallo[] = "Hallo!\n";
2
3
int
4
main(void)
5
{
6
    rcc_clock();     // Taktinitialisierung
7
    systick_delay(); // Delay-Kalibrierung
8
9
    RCC->AHBENR  |= RCC_AHBENR_DMA1EN;
10
    RCC->APB2ENR |= RCC_APB2ENR_USART1EN | RCC_APB2ENR_IOPAEN | RCC_APB2ENR_IOPBEN | RCC_APB2ENR_AFIOEN;
11
12
    gpio_config(GPIOA, 1<<9, GPIO_Mode_Output2MHz | GPIO_AltOut_PushPull); // UART1 Tx
13
    usart_init(USART1, 9600, 8, USART_ParityNone);
14
    USART1->CR3 |= USART_CR3_DMAT;              // enable UART Tx DMA
15
16
    DMA1_Channel4->CCR = DMA_CCR_DIR_mem2per
17
                       | DMA_CCR_MINC
18
                       | DMA_CCR_PSIZE_8bits
19
                       | DMA_CCR_MSIZE_8bits
20
                       | DMA_CCR_PL_high;
21
    DMA1_Channel4->CPAR = (unsigned)&USART1->DR;
22
23
    printf("Run " __TIME__ "\n");
24
    while (1) {
25
        delay_ms(1000);
26
27
        DMA1_Channel4->CCR &= ~DMA_CCR_EN;      // disable DMA
28
        DMA1_Channel4->CMAR  = (unsigned)hallo;
29
        DMA1_Channel4->CNDTR = strlen(hallo);
30
        DMA1_Channel4->CCR |= DMA_CCR_EN;       // enable DMA
31
    }
32
}
Ich finde nicht, dass diese Form von DMA so kompliziert ist. Weniger 
geht ja nun wirklich nicht. Ist im Grunde nichts Anderes als das was du 
in der letzten hier beschriebenen Version machst, nur ohne FWlib.

von (prx) A. K. (prx)


Lesenswert?

Hast du mal kontrolliert, ob es die richtige USART erwischt? Anfangs 
sendest du ja auf beiden USARTs, später aber nur auf einer.

von Fun R. (funnyrice)


Lesenswert?

Hallo, A. K.

vielen Dank für Deine Hilfe! Kann es leider erst heute Abend 
ausprobieren.

A. K. schrieb:
> Hast du mal kontrolliert, ob es die richtige USART erwischt? Anfangs
> sendest du ja auf beiden USARTs, später aber nur auf einer.

Ja, das sind noch Codezeilen aus dem Beispielprojekt die sich auf den 
USART1 beziehen. Ich teste aber erst mal den USART2 (USARTz). Der liegt 
auf dem extension-connector.
Wenn es dann mit USART2 inkl Empfang funktioniert, dann soll 
USART1,3,4 und evtl.5 dazukommen.

Mist, würde Deinen Code am liebsten sofort ausprobieren, geht jetzt aber 
leider nicht. Schätze erst ab 20:30 Uhr


MfG
FunRice

von Fun R. (funnyrice)


Lesenswert?

Juhu! Funktioniert!

Habe den Code angepasst und in die Funktion eingetragen.

Nun werde ich mich wohl erst Mal in die Empfangsgeschichte einarbeiten 
müssen.
Es ist in der Tat so, das die empfangenen Strings unterschiedlich lang 
sind. Ist ja unpraktisch, dass der DMA-Kanal "wissen" muss, wie lang der 
empfangene String sein soll. Und circular Mode sagt mir noch nichts.
Kann also nicht garantieren, daß keine Fregen zu Rx kommen ;-)

Danke nochmal A. K. für Dein Democode.


MfG
FunRice

von (prx) A. K. (prx)


Lesenswert?

Fun Rice schrieb:

> Es ist in der Tat so, das die empfangenen Strings unterschiedlich lang
> sind. Ist ja unpraktisch, dass der DMA-Kanal "wissen" muss, wie lang der
> empfangene String sein soll. Und circular Mode sagt mir noch nichts.

War etwas knapp und provokant formuliert, müssen tut er es nicht, es ist 
nur deutlich einfacher, wenn man es vorher weiss. Es ist eben nicht so 
einfach wie das Senden, weil man nicht einfach abwarten kann, bis das 
DMA durch ist, sondern meist schon vorher "live" in die DMA-Register 
spicken muss. Immerhin will man meist nicht abwarten bis der Puffer voll 
ist, bevor man das erste Byte davon in Angriff nimmt.

Ich habe grad mal in die AN3109 reingesehen. Naja. Mit der Timeout-Idee 
kann man vielleicht etwas anfangen, aber im Code zum DMA-FIFO fehlt m.E. 
genau der interessante Teil.

von Fun R. (funnyrice)


Lesenswert?

A. K. schrieb:
> aber im Code zum DMA-FIFO fehlt m.E.
> genau der interessante Teil.

Also, in der AN3109 ist kein Code, was sehr schade ist, weil ich z.Zt. 
nicht so tief in den Registern stecke, um es jetzt einbinden zu können.

MfG
FunRice

von (prx) A. K. (prx)


Lesenswert?

Dass es zu vielen Appnotes ein File mit Code und Projektkram gibt ist 
dir offenbar entgangen.

Allerdings ist nur die Initialisierung vom DMA-Controller drin, was der 
langweiligste Teil davon ist. Was ich dort nicht fand, ist der Teil, der 
daraus einen Bytestrom für die Anwendung macht.

von Fun R. (funnyrice)


Lesenswert?

Ups, OK!

Kann es mir erst heute Abend ansehen.

MfG
FunRice

von rohe (Gast)


Lesenswert?

prx schrieb:
> Dass es zu vielen Appnotes ein File mit Code und Projektkram gibt ist
> dir offenbar entgangen.

Hallo prx,
ich konnte auf www.st.com keinen Beispielcode zur AN3109 finden. Hast Du 
einen Link parat?
Danke und Gruss, Rohe

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.