Forum: Mikrocontroller und Digitale Elektronik TLC5940 mit Xmega


von Highii H. (highii)


Lesenswert?

Hallo,

ich möchte den TLC5940 in Betrieb nehmen und habe dazu das Datenblatt 
und Demistifying gewältzt und versucht den Code mit einem Xmega 
umzusetzen. In Demisitifying wird der Code in verschiedenen 
Optimierungsstufen erstellt. Den ersten habe ich bei mir umgesetzt. Er 
funktioniert auch. Wenn ich diesen jedoch durch Interrupts erweitere, 
funktioniert er nicht. Die LEDs leuchten nicht.
Könnt ihr mir weiterhelfen? Was habe ich vergessen?

Meine Unterschiede zum Original:
- Xmega anstatt Atmega
- 32Mhz interner Takt anstatt 16Mhz

Code 1, der funktioniert:
1
#define F_CPU 2e6
2
3
#include <asf.h>
4
#include <avr/io.h>
5
#include <stdint.h>
6
#include <util/delay.h>
7
8
#define GSCLK_PORT PORTC
9
#define GSCLK_PIN 4
10
#define SIN_PORT PORTC
11
#define SIN_PIN 5
12
#define SCLK_PORT PORTC
13
#define SCLK_PIN 3
14
#define BLANK_PORT PORTC
15
#define BLANK_PIN 2
16
#define DCPRG_PORT PORTC
17
#define DCPRG_PIN 6
18
#define VPRG_PORT PORTC
19
#define VPRG_PIN 7
20
#define XLAT_PORT PORTC
21
#define XLAT_PIN 1
22
23
#define TLC5940_N 1
24
25
uint8_t dcData[96*TLC5940_N] = {
26
  //MSB      LSB
27
  1, 1, 1, 1, 1, 1,  // Channel 15
28
  1, 1, 1, 1, 1, 1,  // Channel 14
29
  1, 1, 1, 1, 1, 1,  // Channel 13
30
  1, 1, 1, 1, 1, 1,  // Channel 12
31
  1, 1, 1, 1, 1, 1,  // Channel 11
32
  1, 1, 1, 1, 1, 1,  // Channel 10
33
  1, 1, 1, 1, 1, 1,  // Channel 9
34
  1, 1, 1, 1, 1, 1,  // Channel 8
35
  1, 1, 1, 1, 1, 1,  // Channel 7
36
  1, 1, 1, 1, 1, 1,  // Channel 6
37
  1, 1, 1, 1, 1, 1,  // Channel 5
38
  1, 1, 1, 1, 1, 1,  // Channel 4
39
  1, 1, 1, 1, 1, 1,  // Channel 3
40
  1, 1, 1, 1, 1, 1,  // Channel 2
41
  1, 1, 1, 1, 1, 1,  // Channel 1
42
  1, 1, 1, 1, 1, 1,  // Channel 0
43
};
44
45
uint8_t gsData[192*TLC5940_N] = {
46
  //MSB      LSB
47
  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,    // Channel 15
48
  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,    // Channel 14
49
  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,    // Channel 13
50
  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,    // Channel 12
51
  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0,    // Channel 11
52
  0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0,    // Channel 10
53
  0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0,    // Channel 9
54
  0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0,    // Channel 8
55
  0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0,    // Channel 7
56
  0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0,    // Channel 6
57
  0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,    // Channel 5
58
  0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0,    // Channel 4
59
  0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0,    // Channel 3
60
  0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,    // Channel 2
61
  1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,    // Channel 1
62
  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,    // Channel 0
63
};
64
65
#define setOutput(ddr,pin) (ddr |= (1<<pin))
66
#define setHigh(port,pin)  (port |= (1<<pin))
67
#define setLow(port,pin) (port &= ~(1<<pin))
68
#define outputState(port,pin) ((port) & (1<<(pin)))
69
70
#define pulse(port,pin) do { \
71
  setHigh((port),(pin)); \
72
  setLow((port),(pin)); \
73
} while (0);
74
75
void TLC5940_Init(void);
76
void TLC5940_ClockInDC(void);
77
void TLC5940_SetGS_And_GS_PWM(void);
78
79
80
int main(void)
81
{
82
  
83
//Oszillator auf 32Mhz stellen
84
OSC.CTRL |= OSC_RC32MEN_bm;
85
// Warten bis der Oszillator bereit ist
86
while(!(OSC.STATUS & OSC_RC32MRDY_bm));
87
//Schützt I/O Register, Interrupts werden ignoriert
88
CCP = CCP_IOREG_gc;
89
//aktiviert den internen Oszillator
90
CLK.CTRL = CLK_SCLKSEL_RC32M_gc;
91
    
92
  TLC5940_Init();
93
  TLC5940_ClockInDC();
94
  
95
  for (;;) {
96
    TLC5940_SetGS_And_GS_PWM();      
97
  }
98
  
99
  return 0;
100
}
101
102
void TLC5940_Init(void)
103
{
104
  setOutput(GSCLK_PORT.DIR,GSCLK_PIN);
105
  setOutput(SCLK_PORT.DIR,SCLK_PIN);
106
  setOutput(DCPRG_PORT.DIR,DCPRG_PIN);
107
  setOutput(VPRG_PORT.DIR,VPRG_PIN);
108
  setOutput(XLAT_PORT.DIR,XLAT_PIN);
109
  setOutput(BLANK_PORT.DIR,BLANK_PIN);
110
  setOutput(SIN_PORT.DIR,SIN_PIN);
111
  
112
  setLow(GSCLK_PORT.OUT, GSCLK_PIN);
113
  setLow(SCLK_PORT.OUT, SCLK_PIN);
114
  setLow(DCPRG_PORT.OUT, DCPRG_PIN);
115
  setHigh(VPRG_PORT.OUT, VPRG_PIN);
116
  setLow(XLAT_PORT.OUT, XLAT_PIN);
117
  setHigh(BLANK_PORT.OUT, BLANK_PIN);
118
  
119
}
120
121
void TLC5940_ClockInDC(void) {
122
  setHigh(DCPRG_PORT.OUT, DCPRG_PIN);
123
  setHigh(VPRG_PORT.OUT, VPRG_PIN);
124
  
125
  uint8_t Counter = 0;
126
  
127
  for (;;) {
128
    if (Counter > TLC5940_N*96-1) {
129
      pulse(XLAT_PORT.OUT, XLAT_PIN);
130
      break;
131
    } else {
132
      if (dcData[Counter])
133
        setHigh(SIN_PORT.OUT, SIN_PIN);
134
      else
135
        setLow(SIN_PORT.OUT, SIN_PIN);
136
      pulse(SCLK_PORT.OUT,SCLK_PIN);
137
      Counter++;
138
    }
139
  }
140
}
141
142
void TLC5940_SetGS_And_GS_PWM(void) {
143
  uint8_t firstCycleFlag = 0;
144
  
145
  if (outputState(VPRG_PORT.OUT,VPRG_PIN)) {
146
    setLow(VPRG_PORT.OUT,VPRG_PIN);
147
    firstCycleFlag = 1;
148
  }
149
  
150
  uint16_t GSCLK_Counter = 0;
151
  uint8_t Data_Counter = 0;
152
  
153
  setLow(BLANK_PORT.OUT, BLANK_PIN);
154
  for (;;) {
155
    if (GSCLK_Counter > 4095) {
156
      setHigh(BLANK_PORT.OUT, BLANK_PIN);
157
      pulse(XLAT_PORT.OUT, XLAT_PIN);
158
      if (firstCycleFlag) {
159
        pulse(SCLK_PORT.OUT, SCLK_PIN);
160
        firstCycleFlag = 0;
161
      }
162
      break;
163
    } else {
164
      if (!(Data_Counter > TLC5940_N * 192 - 1)) {
165
        if (gsData[Data_Counter])
166
          setHigh(SIN_PORT.OUT, SIN_PIN);
167
        else
168
          setLow(SIN_PORT.OUT, SIN_PIN);
169
        pulse(SCLK_PORT.OUT,SCLK_PIN);
170
        Data_Counter++;
171
      }
172
    }
173
    pulse(GSCLK_PORT.OUT, GSCLK_PIN);
174
    GSCLK_Counter++;
175
  }
176
}

Code 2 - funktioniert nicht
1
#define F_CPU 2e6
2
3
#include <asf.h>
4
#include <avr/io.h>
5
#include <stdint.h>
6
#include <util/delay.h>
7
#include <avr/interrupt.h>
8
9
#define GSCLK_PORT PORTC
10
#define GSCLK_PIN 4
11
#define SIN_PORT PORTC
12
#define SIN_PIN 5
13
#define SCLK_PORT PORTC
14
#define SCLK_PIN 3
15
#define BLANK_PORT PORTC
16
#define BLANK_PIN 2
17
#define DCPRG_PORT PORTC
18
#define DCPRG_PIN 6
19
#define VPRG_PORT PORTC
20
#define VPRG_PIN 7
21
#define XLAT_PORT PORTC
22
#define XLAT_PIN 1
23
24
#define TLC5940_N 1
25
26
uint8_t dcData[96*TLC5940_N] = {
27
  //MSB      LSB
28
  1, 1, 1, 1, 1, 1,  // Channel 15
29
  1, 1, 1, 1, 1, 1,  // Channel 14
30
  1, 1, 1, 1, 1, 1,  // Channel 13
31
  1, 1, 1, 1, 1, 1,  // Channel 12
32
  1, 1, 1, 1, 1, 1,  // Channel 11
33
  1, 1, 1, 1, 1, 1,  // Channel 10
34
  1, 1, 1, 1, 1, 1,  // Channel 9
35
  1, 1, 1, 1, 1, 1,  // Channel 8
36
  1, 1, 1, 1, 1, 1,  // Channel 7
37
  1, 1, 1, 1, 1, 1,  // Channel 6
38
  1, 1, 1, 1, 1, 1,  // Channel 5
39
  1, 1, 1, 1, 1, 1,  // Channel 4
40
  1, 1, 1, 1, 1, 1,  // Channel 3
41
  1, 1, 1, 1, 1, 1,  // Channel 2
42
  1, 1, 1, 1, 1, 1,  // Channel 1
43
  1, 1, 1, 1, 1, 1,  // Channel 0
44
};
45
46
uint8_t gsData[192*TLC5940_N] = {
47
  //MSB      LSB
48
  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,    // Channel 15
49
  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,    // Channel 14
50
  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,    // Channel 13
51
  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,    // Channel 12
52
  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0,    // Channel 11
53
  0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0,    // Channel 10
54
  0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0,    // Channel 9
55
  0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0,    // Channel 8
56
  0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0,    // Channel 7
57
  0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0,    // Channel 6
58
  0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,    // Channel 5
59
  0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0,    // Channel 4
60
  0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0,    // Channel 3
61
  0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,    // Channel 2
62
  1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,    // Channel 1
63
  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,    // Channel 0
64
};
65
66
#define setOutput(ddr,pin) (ddr |= (1<<pin))
67
#define setHigh(port,pin)  (port |= (1<<pin))
68
#define setLow(port,pin) (port &= ~(1<<pin))
69
#define outputState(port,pin) ((port) & (1<<(pin)))
70
71
#define pulse(port,pin) do { \
72
  setHigh((port),(pin)); \
73
  setLow((port),(pin)); \
74
} while (0);
75
76
77
78
void TLC5940_Init(void);
79
void TLC5940_ClockInDC(void);
80
81
int main(void)
82
{
83
  //Oszillator auf 32Mhz stellen
84
  OSC.CTRL |= OSC_RC32MEN_bm;
85
  // Warten bis der Oszillator bereit ist
86
  while(!(OSC.STATUS & OSC_RC32MRDY_bm));
87
  //Schützt I/O Register, Interrupts werden ignoriert
88
  CCP = CCP_IOREG_gc;
89
  //aktiviert den internen Oszillator
90
  CLK.CTRL = CLK_SCLKSEL_RC32M_gc;
91
  
92
  TLC5940_Init();
93
  TLC5940_ClockInDC();
94
  
95
  PORTR.DIR = 1; // Nur zum Test
96
  PORTR.OUT = 1; // Nur zum Test
97
  
98
  
99
  PMIC.CTRL |= PMIC_HILVLEN_bm |PMIC_LOLVLEN_bm |PMIC_MEDLVLEN_bm;
100
  
101
  TCD1.CTRLA = TC_CLKSEL_DIV1024_gc; //1024 Vorteiler
102
  TCD1.CTRLB = 0x00;
103
  TCD1.INTCTRLA = 0x03;
104
  TCD1.PER = 6; // Wert zu dem gezählt wird
105
  
106
  sei();
107
  
108
  for (;;) {
109
110
  }
111
  
112
  return 0;
113
}
114
115
ISR(TCD1_OVF_vect) {
116
  PORTR.OUTTGL = 1; // Nur zum Test
117
  
118
  uint8_t firstCycleFlag = 0;
119
  static uint8_t xlatNeedsPulse = 0;
120
  
121
  setHigh(BLANK_PORT.OUT,BLANK_PIN);
122
  
123
  if (outputState(VPRG_PORT.OUT,VPRG_PIN)) {
124
    setLow(VPRG_PORT.OUT,VPRG_PIN);
125
    firstCycleFlag = 1;
126
  }
127
  
128
  if (xlatNeedsPulse) {
129
    pulse(XLAT_PORT.OUT,XLAT_PIN);
130
    xlatNeedsPulse = 0;    
131
  }
132
  
133
  if (firstCycleFlag) 
134
    pulse(SCLK_PORT.OUT, SCLK_PIN);
135
    
136
  setLow(BLANK_PORT.OUT, BLANK_PIN);
137
  
138
  uint8_t Data_Counter = 0;
139
  for (;;) {
140
    if (!(Data_Counter > TLC5940_N * 192 - 1)) {
141
      if (gsData[Data_Counter])
142
        setHigh(SIN_PORT.OUT, SIN_PIN);
143
      else
144
        setLow(SIN_PORT.OUT, SIN_PIN);
145
      pulse(SCLK_PORT.OUT,SCLK_PIN);
146
      Data_Counter++;
147
    } else {
148
      xlatNeedsPulse = 1;
149
      break;
150
    }
151
    }
152
    
153
  }
154
155
156
void TLC5940_Init(void)
157
{
158
  setOutput(GSCLK_PORT.DIR,GSCLK_PIN);
159
  setOutput(SCLK_PORT.DIR,SCLK_PIN);
160
  setOutput(DCPRG_PORT.DIR,DCPRG_PIN);
161
  setOutput(VPRG_PORT.DIR,VPRG_PIN);
162
  setOutput(XLAT_PORT.DIR,XLAT_PIN);
163
  setOutput(BLANK_PORT.DIR,BLANK_PIN);
164
  setOutput(SIN_PORT.DIR,SIN_PIN);
165
  
166
  setLow(GSCLK_PORT.OUT, GSCLK_PIN);
167
  setLow(SCLK_PORT.OUT, SCLK_PIN);
168
  setLow(DCPRG_PORT.OUT, DCPRG_PIN);
169
  setHigh(VPRG_PORT.OUT, VPRG_PIN);
170
  setLow(XLAT_PORT.OUT, XLAT_PIN);
171
  setHigh(BLANK_PORT.OUT, BLANK_PIN);
172
  
173
}
174
175
void TLC5940_ClockInDC(void) {
176
  setHigh(DCPRG_PORT.OUT, DCPRG_PIN);
177
  setHigh(VPRG_PORT.OUT, VPRG_PIN);
178
  
179
  uint8_t Counter = 0;
180
  
181
  for (;;) {
182
    if (Counter > TLC5940_N*96-1) {
183
      pulse(XLAT_PORT.OUT, XLAT_PIN);
184
      break;
185
      } else {
186
      if (dcData[Counter])
187
        setHigh(SIN_PORT.OUT, SIN_PIN);
188
      else
189
        setLow(SIN_PORT.OUT, SIN_PIN);
190
      pulse(SCLK_PORT.OUT,SCLK_PIN);
191
      Counter++;
192
    }
193
  }
194
}

von Highii H. (highii)


Lesenswert?

Ich habe den Fehler gefunden. Er ist im Demistifying drin gewesen.

Im Interrupt hat noch ein
1
pulse(GSCLK_PORT.OUT,GSCLK_PIN)
weiter hinten gefehlt.

Die ISR lautet somit wiefolgt:
1
ISR(TCD1_OVF_vect) {
2
  PORTR.OUTTGL = 1; // Nur zum Test
3
  
4
  uint8_t firstCycleFlag = 0;
5
  static uint8_t xlatNeedsPulse = 0;
6
  
7
  setHigh(BLANK_PORT.OUT,BLANK_PIN);
8
  
9
  if (outputState(VPRG_PORT.OUT,VPRG_PIN)) {
10
    setLow(VPRG_PORT.OUT,VPRG_PIN);
11
    firstCycleFlag = 1;
12
  }
13
  
14
  if (xlatNeedsPulse) {
15
    pulse(XLAT_PORT.OUT,XLAT_PIN);
16
    xlatNeedsPulse = 0;    
17
  }
18
  
19
  if (firstCycleFlag) 
20
    pulse(SCLK_PORT.OUT, SCLK_PIN);
21
    
22
  setLow(BLANK_PORT.OUT, BLANK_PIN);
23
  
24
  uint8_t Data_Counter = 0;
25
  for (;;) {
26
    if (!(Data_Counter > TLC5940_N * 192 - 1)) {
27
      if (gsData[Data_Counter])
28
        setHigh(SIN_PORT.OUT, SIN_PIN);
29
      else
30
        setLow(SIN_PORT.OUT, SIN_PIN);
31
      pulse(SCLK_PORT.OUT,SCLK_PIN);
32
      pulse(GSCLK_PORT.OUT,GSCLK_PIN); // MaWa
33
      Data_Counter++;
34
    } else {
35
      xlatNeedsPulse = 1;
36
      break;
37
    }
38
    }
39
    
40
  }

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.