Forum: Mikrocontroller und Digitale Elektronik Anfängerfrage , 8x8 matrix von common cathode auf anode ?


von ernst u. (Firma: nono) (circat)


Lesenswert?

Hallo , erstmal vorneweg : super forum :-)

Ich beschäftige mich erst seit einigen wochen mit µC , bißher habe ich 
eher kleine analoge schaltungen und tonerzeuger gelötet.
Daher kommen von mir gleich bestimmt einige doofe Fragen oder 
Denkfehler.

Mein Setup :

Attiny2313
WIN-AVR
AVR Studio
Diamex-AVR USB

Ich versuche eine einfache Animation von einem ATtiny2313 auf einer 
LED-Matrix anzuzeigen.Das klappt bei dem Common Anode Display auch schon 
ganz gut,aber den code so umzuschreiben das er auch einer Common Cathode 
display läuft schaffe ich irgendwie nicht.Muss er aber.

ich habe grob fahrlässig alles Gutti gemacht ( Copy&Paste aus 
verschiedenen Scripts und die Animation selber erstellt. ) :-)

aber hier scheitere ich seit tagen :

 * if you have a common cathode matrix rotate your pin layout 90 Degree
 * switch row with column
 */
also per kabel oder per script switchen ?
nur WO und WAS ?

kann mir jemand n hinweis geben wo ich ansetzen soll?

vielen dank,eric

ps:ja,ich sollte mit was einfacherem anfangen,aber s geht ja schon fast 
!
1
//#include <inttypes.h>
2
//#include <stdlib.h>
3
//#include <string.h>
4
#include <avr/io.h>
5
#include <avr/interrupt.h>
6
//#include <avr/eeprom.h>
7
//#include <util/delay.h>
8
#include <avr/pgmspace.h>
9
#include "font.h"
10
11
// Change these values to adjust scroll speeds and animation iterations
12
#define ANIMATION_SCROLL_SPEED 200  // how fast to scroll the animations
13
#define ANIMATION_SPEED 140      // how fast to change to next picture
14
#define TEXT_SCROLL_SPEED 120      // how fast to scrill the text (wait)
15
#define REPEAT_ANIMATION 2        // how often to repeat the animation if in cycling mode
16
#define REPEAT_TEXT 1              // how often to repeat the text if in cycling mode
17
18
// How to add a new message:
19
// * add the new message (only upper case, see font.h)
20
// * adjust MAX_MESSAGES
21
// * add the new message to messages
22
// NOTE: messages may not be longer than 255 chars.
23
const prog_char message_00[] = " ! MERRY CHRISTMAS AND A HAPPY NEW YEAR ! ";
24
const prog_char message_01[] = " COUNTDOWN...";
25
const prog_char message_02[] = " 5  4  3  2  1 ... BOOM!! ";
26
27
#define MAX_MESSAGES 3
28
PGM_P PROGMEM messages[] = {
29
  message_00
30
  ,message_01
31
  ,message_02
32
}; 
33
34
//#define MAX_ANIMATIONS 1
35
36
const uint8_t dancer1[][8] PROGMEM = {
37
{ 0x00, 0x01, 0x03, 0x01, 0x00, 0x00, 0x00, 0x00}, // fight
38
{ 0x00, 0x01, 0x03, 0x01, 0x00, 0x00, 0x00, 0x00}, // fight
39
{ 0x00, 0x01, 0x0B, 0x01, 0x00, 0x00, 0x00, 0x00}, // fight
40
{ 0x00, 0x01, 0x13, 0x01, 0x00, 0x00, 0x00, 0x00}, // fight
41
{ 0x00, 0x01, 0x23, 0x01, 0x00, 0x00, 0x00, 0x00}, // fight
42
{ 0x00, 0x00, 0x41, 0x03, 0x01, 0x00, 0x00, 0x00}, // fight
43
{ 0x00, 0x00, 0x81, 0x03, 0x01, 0x00, 0x00, 0x00}, // fight
44
{ 0x00, 0x00, 0x00, 0x01, 0x0B, 0x01, 0x00, 0x00}, // fight
45
{ 0x00, 0x00, 0x00, 0x01, 0x13, 0x01, 0x00, 0x00}, // fight
46
{ 0x00, 0x00, 0x00, 0x01, 0x23, 0x01, 0x00, 0x00}, // fight
47
{ 0x00, 0x00, 0x00, 0x01, 0x43, 0x01, 0x00, 0x00}, // fight
48
{ 0x00, 0x00, 0x00, 0x01, 0x83, 0x01, 0x00, 0x00}, // fight
49
{ 0x40, 0x00, 0x00, 0x01, 0x03, 0x01, 0x00, 0x00}, // fight
50
{ 0xE0, 0x40, 0x01, 0x03, 0x01, 0x00, 0x00, 0x00}, // fight
51
{ 0xE0, 0xE0, 0x41, 0x03, 0x01, 0x00, 0x00, 0x00}, // fight
52
{ 0x40, 0xE1, 0xE3, 0x41, 0x00, 0x00, 0x00, 0x00}, // fight
53
{ 0x00, 0x41, 0xEB, 0xE1, 0x40, 0x00, 0x00, 0x00}, // fight
54
{ 0x00, 0x41, 0xF3, 0xE1, 0x40, 0x00, 0x00, 0x00}, // fight
55
{ 0x00, 0x41, 0xC3, 0xE1, 0x40, 0x00, 0x00, 0x00}, // fight
56
{ 0x00, 0x41, 0xC3, 0x81, 0x50, 0x00, 0x00, 0x00}, // fight
57
{ 0x40, 0x01, 0x83, 0x81, 0x10, 0x40, 0x00, 0x00}, // fight
58
{ 0x00, 0x81, 0x03, 0x01, 0x00, 0x08, 0x80, 0x00}, // fight
59
{ 0x00, 0x01, 0x03, 0x01, 0x00, 0x00, 0x00, 0x00}, // fight
60
61
62
};
63
64
65
//uint8_t mode_ee EEMEM = 0;                      // stores the mode in eeprom
66
uint8_t screen_mem[8];      // screen memory
67
uint8_t active_row=1;      // active row
68
uint8_t message_ptr = 0;                 // points to the active char in the message
69
uint8_t message_displayed = 0;           // how often has the message been displayed?
70
uint8_t active_char = 0;                 // stores the active char
71
uint8_t message_length = 0;              // stores the length of the active message
72
uint8_t char_ptr = 0;                    // points to the active col in the char
73
uint8_t char_length = 0;                 // stores the length of the active char
74
static volatile uint16_t counter = 0;    // used for delay function
75
76
77
// prototypes
78
void delay_ms(uint16_t delay);
79
void copy_to_display(int8_t x, int8_t y, uint8_t sprite[]);
80
void display_active_row(void);
81
void show_char();
82
//void clear_screen(void);
83
void copy_to_buffer(const prog_uint8_t sprite[8]);
84
//void scroll_animation(const prog_uint8_t sprite_1[], const prog_uint8_t sprite_2[], uint8_t flash, uint16_t flash);
85
86
/*
87
 * ISR TIMER0_OVF_vect
88
 * Handles overflow interrupts of timer 0.
89
 *
90
 * 4MHz
91
 * ----
92
 * Prescaler 8 ==> 1953.1 Hz
93
 * Complete display = 244 Hz
94
 *
95
 */
96
97
98
/*
99
 * display_active_col
100
 * Deactivates the active column and displays the next one.
101
 * Data is read from screen_mem.
102
 *
103
 *      ATtiny2313
104
 * 16 - PD0    PB7 - 1
105
 * 15 - PD1    PB6 - 2
106
 * 14 - PA1    PB5 - 3
107
 * 13 - PA0    PB4 - 4
108
 * 12 - PD2    PB3 - 5
109
 * 11 - PD3    PB2 - 6
110
 * 10 - PD4    PB1 - 7
111
 *  9 - PD5    PB0 - 8
112
 *
113
 * NFM-12883 common anode          |
114
 *     A0B5B4D4B2D3D1D0      +-----+
115
 * PD5 o o o o o o o o       |     |
116
 * PA1 o o o o o o o o      _+_    |
117
 * PB0 o o o o o o o o      \ /    |
118
 * PD2 o o o o o o o o     __V__   |
119
 * PB7 o o o o o o o o       |     |
120
 * PB1 o o o o o o o o    ---+-----C---
121
 * PB6 o o o o o o o o             |
122
 * PB3 o o o o o o o o
123
 *
124
 * if you have a common cathode matrix rotate your pin layout 90 Degree
125
 * switch row with column
126
 */
127
128
129
ISR(TIMER0_OVF_vect) {
130
131
  uint8_t row=0,i;
132
133
  // timer for delay  
134
  counter++;
135
136
  // shut down all rows and columns
137
  PORTA = (0 << PB3) | (1 << PB5);
138
  PORTB = (0 << PB6) | (0 << PB1) | (0 << PD2) | (1 << PB4) | 
139
          (1 << PB2) | (1 << PD3) | (1 << PD1) | (1 << PD0);
140
  PORTD = (0 << PB7) | (0 << PB0) | (0 << PA1) | (0 << PD5) |
141
          (1 << PA0) | (1 << PD4) | (1 << PD1);
142
143
  // next row (1,2,4,8,16,32..)
144
  active_row = (active_row << 7) | (active_row >> 1);
145
146
  //row = screen_mem[active_row];
147
  for (i=0; i<8; i++) {
148
  row <<= 1;
149
  if (screen_mem[i] & active_row) { 
150
    row++ ;
151
  }
152
   }
153
154
  // output all columns, switch leds on.
155
  // column 1
156
  if ((row & 0x80) == 0x80) {
157
    PORTA |= (1 << PA0);    
158
  }
159
  // column 2
160
  if ((row & 0x40) == 0x40) {
161
    PORTB |= (1 << PB5);    
162
  }
163
  // column 3
164
  if ((row & 0x20) == 0x20) {
165
    PORTB |= (1 << PB4);    
166
  }
167
  // column 4
168
  if ((row & 0x10) == 0x10) {
169
    PORTD |= (1 << PD4);    
170
  }
171
  // column 5
172
  if ((row & 0x08) == 0x08) {
173
    PORTB |= (1 << PB2);    
174
  }
175
  // column 6
176
  if ((row & 0x04) == 0x04) {
177
    PORTD |= (1 << PD3);    
178
  }
179
  // column 7
180
  if ((row & 0x02) == 0x02) {
181
    PORTD |= (1 << PD1);    
182
  }
183
  // column 8
184
  if ((row & 0x01) == 0x01) {
185
    PORTD |= (1 << PD0);    
186
  }
187
188
  //activate row
189
  if (active_row==0x80) PORTD &= ~(1 << PD5);
190
  if (active_row==0x40) PORTA &= ~(1 << PA1);
191
  if (active_row==0x20) PORTB &= ~(1 << PB0);
192
  if (active_row==0x10) PORTD &= ~(1 << PD2);
193
  if (active_row==0x08) PORTB &= ~(1 << PB7);
194
  if (active_row==0x04) PORTB &= ~(1 << PB1);
195
  if (active_row==0x02) PORTB &= ~(1 << PB6); 
196
  if (active_row==0x01) PORTB &= ~(1 << PB3);
197
198
}
199
200
201
202
/*
203
 * delay_ms
204
 * Uses the counter that is incremented by the ISR.
205
 * Max delay is 32767ms.
206
 */
207
void delay_ms(uint16_t delay) {
208
  //while (!(PIND & (1 << PD6))) {}   // used to stop the animation when PD6 goes LOW
209
  uint16_t t = delay * 2;
210
  counter = 0;
211
  while (counter < t) {}
212
}
213
214
215
 /*
216
void copy_to_display(int8_t x, int8_t y, uint8_t sprite[8]) {
217
  int8_t i, t;
218
  uint8_t column;
219
  clear_screen();
220
  for (i = 0; i < 8; i++) {
221
    t = i-y;
222
    column = ((t >= 0) && (t < 8)) ? sprite[t] : 0x00;
223
    column = (x >= 0) ? (column >> x) : (column << -x);
224
225
  screen_mem[i]=column;
226
  }
227
}
228
*/
229
230
void show_char(const prog_uint8_t string[]) {
231
  uint8_t i;
232
  uint8_t b;
233
234
  // shift the screen to the left
235
  for (i = 0; i < 7; i++) {
236
    screen_mem[i] = screen_mem[i+1]; 
237
  }
238
  // advance a char if needed
239
  if (char_length == 0x80) {
240
241
  char_length =0;  //reset stop bit
242
243
    //read next char from progmem
244
  memcpy_P(&active_char,&string[message_ptr],1);
245
    message_ptr++;
246
  
247
  //string stop byte 0x00 
248
    if (active_char == 0) {
249
      message_ptr = 0;
250
      message_displayed++;
251
    char_length =0x80; // immediately read next char
252
    }
253
254
  active_char -= CHAR_OFFSET;
255
    char_ptr = 0;
256
257
  // this makes the space between two chars
258
  screen_mem[7]=0;
259
    return; 
260
  }
261
262
  // read pixels for current column of char
263
  b = pgm_read_byte(&font[active_char * 5 + char_ptr]);
264
  char_ptr++;
265
  char_length= (b & 0x80);
266
  b = (b & 0x7F);
267
  // write pixels into screen memory
268
  screen_mem[7] =b;
269
}
270
271
272
/*
273
 * copy_to_buffer
274
 * Copies the given sprite from PROGMEM to 8x8 LED RAM.
275
 */
276
void copy_to_buffer(const prog_uint8_t sprite[8]) {
277
  memcpy_P(screen_mem, sprite, 8);
278
}
279
280
281
/*
282
 * scroll_animation
283
 * Uses sprite_1 and sprite_2 to draw a simple animation.
284
 * blink=1 : change sprite_1/2 every step  // blink=0 : blink only in the middle
285
 * scroll_speed: factor time for next step
286
 */
287
void scroll_animation(const prog_uint8_t sprite_1[8], const prog_uint8_t sprite_2[8], uint8_t blink) {
288
  uint8_t i,j;
289
  int8_t x,z;
290
  for (i = 0; i < REPEAT_ANIMATION; i++) {
291
  //you can scroll from right with (x = -8; x < 8; x++)
292
    for (x = 8; x > -9; x--) {
293
      //move sprite 1
294
    for (j = 0; j < 8; j++) {
295
      screen_mem[j] = 0x00;
296
      z = x+j;
297
      if ((z>=0) && (z<8)) {
298
        if (blink & x) {
299
          memcpy_P(&screen_mem[j],&sprite_2[z],1);
300
        }
301
        else {
302
          memcpy_P(&screen_mem[j],&sprite_1[z],1);
303
        }
304
      }
305
    }
306
      delay_ms(ANIMATION_SCROLL_SPEED);
307
308
      if (x==0) {
309
    //in the middle shift betwenn sprite_1 and sprite_2
310
    for (j=0; j<4;j++) {
311
        copy_to_buffer(sprite_2);
312
        delay_ms(ANIMATION_SPEED);
313
        copy_to_buffer(sprite_1);
314
        delay_ms(ANIMATION_SPEED);
315
    }
316
    }
317
  }  
318
  }
319
}
320
321
/*
322
 * step_animation
323
 * Uses sprite_1 to draw a simple animation.
324
 * size of array
325
 */
326
void step_animation(const prog_uint8_t sprite_1[][8], uint8_t size) {
327
  uint8_t i;
328
  for (i = 0; i < size; i++) {
329
   copy_to_buffer(sprite_1[i]); //array: step pointer by 8
330
     delay_ms(ANIMATION_SPEED);
331
  }  
332
}
333
334
335
int main(void) {
336
337
  int8_t i,j,k;
338
339
  // timer 0 setup, prescaler 8
340
  TCCR0B |= (1 << CS01);
341
 
342
  // enable timer 0 interrupt
343
  TIMSK |= (1 << TOIE0);  
344
345
  // define outputs
346
  DDRA |= 0x03;  
347
  DDRB |= 0xFF;
348
  DDRD |= 0x3F;
349
 
350
/*
351
  // killed by code size
352
  // read last mode from eeprom
353
  // 0 mean cycle through all modes and messages
354
  mode = eeprom_read_byte(&mode_ee);
355
  if ((mode == 0) || (mode >= (MAX_ANIMATIONS + MAX_MESSAGES + 1))) {
356
    mode = 4;
357
  }
358
  eeprom_write_byte(&mode_ee, mode + 1);  
359
*/
360
  sei();
361
362
  while (1) {
363
364
   for (i = 0; i < REPEAT_ANIMATION; i++) {
365
     step_animation(dancer1[0], 23);  
366
   }  
367
368
  }
369
370
return 0;
371
372
}

von MaWin (Gast)


Lesenswert?

Einfach an die bisherigen Anodenausgänge

      +-- LED bisher Anode nun Kathode
      |
-1k--|< NPN wie BC368 oder NMOSFET wie IRF7331
      |E
     GND

und an die Kathodenausgänge

     +5V
      |E
-1k--|< PNP wie BC369 oder PMOSFET wie IRF7329
      |
      +-- LED bisher Kathode nun Anode

anschliessen, dann klappt's sogar vielleicht mit dem
Strom den der uC liefern kann und das Display wird
ohne Programmänderungen endlich so hell wie vorgesehen.

von ernst u. (Firma: nono) (circat)


Lesenswert?

es sollte ohne weitere bauteile möglich sein.
ich hab auf der CC Matrix auch schon eine animation zum laufen 
bekommen,musste/wollte aber das script wechseln....

und mit dem neuen bekomme ich die umschaltung nicht hin.

anforderung ist auf jeden fall : keine weiteren bauteile :-)

trotzdem danke !

von Falk B. (falk)


Lesenswert?

@  erich lesovsky (Firma: circat) (circat)

>Hallo , erstmal vorneweg : super forum :-)

Schleimer. ;-)

>Daher kommen von mir gleich bestimmt einige doofe Fragen oder
>Denkfehler.

Erster Fehler: Netiquette missachtet. lange Quelltexte gehören in 
den Anhang.

>ganz gut,aber den code so umzuschreiben das er auch einer Common Cathode
>display läuft schaffe ich irgendwie nicht.Muss er aber.

Warum? Schau mal in den Artikel LED-Matrix.

MFG
Falk

von ernst u. (Firma: nono) (circat)


Lesenswert?

den Artikel LED Matrix habe ich gelesen , trotzdem erklärt sich nicht 
mein problem die anode / cathode in der software aus zu vertauschen.

von Falk B. (falk)


Lesenswert?

@  erich lesovsky (Firma: circat) (circat)

>den Artikel LED Matrix habe ich gelesen , trotzdem erklärt sich nicht
>mein problem die anode / cathode in der software aus zu vertauschen.

Dann lies den Artikel noch einmal und denk drüber nach.

von Peter D. (peda)


Lesenswert?

erich lesovsky schrieb:
> * if you have a common cathode matrix rotate your pin layout 90 Degree
>  * switch row with column
>  */

Wenn Dein Programm funktioniert, sollte doch zu erkennen sein, daß die 
Figur gedreht ist.
Du nimmst die Platine in die Hand und drehst sie um 90°.
Alternativ kannst Du aber auch Deinen Kopf drehen.


Peter

von ernst u. (Firma: nono) (circat)


Lesenswert?

hehe,der war gut :-)

aber wenig konstruktiv....nun ja,ich danke euch trotzdem,auch wenn 
ausser dummen antworten nichts rumkommt...

is das hier normal ?

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.