Forum: Mikrocontroller und Digitale Elektronik STM32F4 STM32L152: DAC Ausgabe DDS Spannungseinbruch


von Curby23523 N. (Gast)


Lesenswert?

Hallo,

ich benutze ein STM32F4 und STM32L152 Discovery Board. Ich lasse auf 
beiden nahezu 1:1 die selbe Software laufen.

Ich lasse mit 60kSps einen Sinus ausgeben. Ich messe direkt am Port Pin 
GPIO A:4 mit meinem Oszilloskop. Der STM32F4 hat absolut keine Probleme, 
alles sauber. Beim STM32L152 hingegen bricht die Spannung ab einer 
Frequenz von 500Hz langsam ein, bis ich irgendwann nur noch einn 
winziges Dreieck Signal sehe.

Ich denke nicht, dass es ein prinzipielles Software Problem, eher ein 
Konfigurationsproblem. Oder überlese ich eine Spzifikation bzgl. der 
maximalen Frequenz des DACs? Brauche ich eine Last? Wie kann ich mir das 
erklären? Die Frequenz der DDS stimmt, aber die Spannung bricht immer 
mehr ein.

Danke für Ideen.

Mein Code mit ausgeblendeter Look-Up Table:
1
#include "stm32l1xx.h"
2
#include "timer.h"
3
4
#define SZ 1024
5
#define ML (4294967296 / SZ)
6
#define BS 200
7
#define SPS 60000
8
9
short sample[SZ] ={
10
    [...]
11
};
12
13
unsigned short DMAB0[BS];
14
unsigned short DMAB1[BS];
15
unsigned long long dwFreq = 55;
16
17
struct sTon{
18
  unsigned long wPos;
19
  unsigned long wVol;
20
  unsigned long wStepsize;
21
};
22
23
volatile struct sTon aoToene[10];
24
25
#define CALC(a) (sample[aoToene[(a)].wPos/ML]) * aoToene[(a)].wVol / 0x100
26
void calcbuffer(unsigned short * buffer){
27
  for(int x = 0; x < BS; x++){
28
29
    aoToene[0].wPos += aoToene[0].wStepsize;
30
31
    *buffer++ = CALC(0);
32
  }
33
}
34
35
void DMA1_Channel2_IRQHandler(void){
36
  DMA1->IFCR |= (1<<5);
37
  g_dwTime++;
38
  DMA1_Channel2->CCR &= ~1;
39
40
  if(DMA1_Channel2->CMAR == (unsigned long)&DMAB0[0]){
41
    DMA1_Channel2->CNDTR = BS;
42
    DMA1_Channel2->CMAR = (unsigned long)&DMAB1[0];
43
    DMA1_Channel2->CCR |= 1;
44
45
    calcbuffer(DMAB0);
46
  }else{
47
    DMA1_Channel2->CNDTR = BS;
48
    DMA1_Channel2->CMAR = (unsigned long)&DMAB0[0];
49
    DMA1_Channel2->CCR |= 1;
50
51
    calcbuffer(DMAB1);
52
  }
53
}
54
55
56
57
int main(void)
58
{
59
60
  RCC->CR |= 1;
61
  while(!(RCC->CR & 0b10));
62
  RCC->CFGR |= 0b01;
63
  while(!(RCC->CFGR & 0b0100));
64
  RCC->CFGR |= (0b000 << 11);      //APB2 Prescaler = 0
65
  RCC->CFGR |= (0b000 << 8);      //APB1 Prescaler = 0
66
  RCC->CFGR |= (0b0000 << 4);      //AHB Prescaler = 0
67
68
  RCC->AHBENR |= 1UL;            //GPIOA CLK
69
  RCC->AHBENR |= (1<<25);          //DMA1  CLK
70
  RCC->APB1ENR |= (1<<4);          //TIM6 CLK
71
  RCC->APB1ENR |= (1UL << 29);      //DAC CLK
72
73
  //GPIOA->OSPEEDR |= (0b11 << 2*4);
74
  GPIOA->MODER |= (0b11 << 2*4);      //PA4 analog
75
76
  TIM6->PSC   = 0;
77
  TIM6->ARR   = 16000000 / SPS - 1;
78
  TIM6->CR2 |= (1<<5);
79
  TIM6->CR1  |= 0x01;
80
81
  DAC->CR |= (1<<12);            //DMA enable
82
  DAC->CR |= 0b000100;          //TIM2 trigger
83
  DAC->CR |= 1;              //DAC ON
84
85
  DMA1_Channel2->CCR |= (0b11<<12);    //high priority
86
  DMA1_Channel2->CCR |= (0b01<<10);    //16 Bit peripherie
87
  DMA1_Channel2->CCR |= (0b01<<8);    //16 Bit memory
88
  DMA1_Channel2->CCR |= (1<<7);      //inc memory adress
89
  DMA1_Channel2->CCR |= (1<<4);      //mem to peripherie
90
  DMA1_Channel2->CCR |= (1<<1);      //TCIE enable
91
  DMA1_Channel2->CNDTR = BS;
92
  DMA1_Channel2->CMAR = (unsigned long)&DMAB0[0];
93
  DMA1_Channel2->CPAR = (unsigned long)&DAC->DHR12R1;
94
  DMA1_Channel2->CCR |= 1;
95
96
  NVIC->ICPR[DMA1_Channel2_IRQn/32] |= (1<<DMA1_Channel2_IRQn%32);
97
  NVIC->ISER[DMA1_Channel2_IRQn/32] |= (1<<DMA1_Channel2_IRQn%32);
98
99
  aoToene[0].wStepsize = dwFreq * SZ * ML / SPS;
100
  aoToene[0].wVol = 0xff;
101
102
  while(1){
103
  }
104
}

von STM Apprentice (Gast)


Lesenswert?

Nils H. schrieb:
> Danke für Ideen.

Vorschlag: auf dem STM32L152 ist der benutze Pin (den du
nicht genannt hast) zusätzlich mit irgendeiner externen
Hardware verbunden.

von Curby23523 N. (Gast)


Lesenswert?

Auf die Idee bin ich wirklich nicht gekommen, das war es tatsächlich! 
Danke.

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.