mikrocontroller.net

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


Autor: ernst unfriendlyforum (Firma: nono) (circat)
Datum:

Bewertung
0 lesenswert
nicht 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 
!


//#include <inttypes.h>
//#include <stdlib.h>
//#include <string.h>
#include <avr/io.h>
#include <avr/interrupt.h>
//#include <avr/eeprom.h>
//#include <util/delay.h>
#include <avr/pgmspace.h>
#include "font.h"

// Change these values to adjust scroll speeds and animation iterations
#define ANIMATION_SCROLL_SPEED 200  // how fast to scroll the animations
#define ANIMATION_SPEED 140      // how fast to change to next picture
#define TEXT_SCROLL_SPEED 120      // how fast to scrill the text (wait)
#define REPEAT_ANIMATION 2        // how often to repeat the animation if in cycling mode
#define REPEAT_TEXT 1              // how often to repeat the text if in cycling mode

// How to add a new message:
// * add the new message (only upper case, see font.h)
// * adjust MAX_MESSAGES
// * add the new message to messages
// NOTE: messages may not be longer than 255 chars.
const prog_char message_00[] = " ! MERRY CHRISTMAS AND A HAPPY NEW YEAR ! ";
const prog_char message_01[] = " COUNTDOWN...";
const prog_char message_02[] = " 5  4  3  2  1 ... BOOM!! ";

#define MAX_MESSAGES 3
PGM_P PROGMEM messages[] = {
  message_00
  ,message_01
  ,message_02
}; 

//#define MAX_ANIMATIONS 1

const uint8_t dancer1[][8] PROGMEM = {
{ 0x00, 0x01, 0x03, 0x01, 0x00, 0x00, 0x00, 0x00}, // fight
{ 0x00, 0x01, 0x03, 0x01, 0x00, 0x00, 0x00, 0x00}, // fight
{ 0x00, 0x01, 0x0B, 0x01, 0x00, 0x00, 0x00, 0x00}, // fight
{ 0x00, 0x01, 0x13, 0x01, 0x00, 0x00, 0x00, 0x00}, // fight
{ 0x00, 0x01, 0x23, 0x01, 0x00, 0x00, 0x00, 0x00}, // fight
{ 0x00, 0x00, 0x41, 0x03, 0x01, 0x00, 0x00, 0x00}, // fight
{ 0x00, 0x00, 0x81, 0x03, 0x01, 0x00, 0x00, 0x00}, // fight
{ 0x00, 0x00, 0x00, 0x01, 0x0B, 0x01, 0x00, 0x00}, // fight
{ 0x00, 0x00, 0x00, 0x01, 0x13, 0x01, 0x00, 0x00}, // fight
{ 0x00, 0x00, 0x00, 0x01, 0x23, 0x01, 0x00, 0x00}, // fight
{ 0x00, 0x00, 0x00, 0x01, 0x43, 0x01, 0x00, 0x00}, // fight
{ 0x00, 0x00, 0x00, 0x01, 0x83, 0x01, 0x00, 0x00}, // fight
{ 0x40, 0x00, 0x00, 0x01, 0x03, 0x01, 0x00, 0x00}, // fight
{ 0xE0, 0x40, 0x01, 0x03, 0x01, 0x00, 0x00, 0x00}, // fight
{ 0xE0, 0xE0, 0x41, 0x03, 0x01, 0x00, 0x00, 0x00}, // fight
{ 0x40, 0xE1, 0xE3, 0x41, 0x00, 0x00, 0x00, 0x00}, // fight
{ 0x00, 0x41, 0xEB, 0xE1, 0x40, 0x00, 0x00, 0x00}, // fight
{ 0x00, 0x41, 0xF3, 0xE1, 0x40, 0x00, 0x00, 0x00}, // fight
{ 0x00, 0x41, 0xC3, 0xE1, 0x40, 0x00, 0x00, 0x00}, // fight
{ 0x00, 0x41, 0xC3, 0x81, 0x50, 0x00, 0x00, 0x00}, // fight
{ 0x40, 0x01, 0x83, 0x81, 0x10, 0x40, 0x00, 0x00}, // fight
{ 0x00, 0x81, 0x03, 0x01, 0x00, 0x08, 0x80, 0x00}, // fight
{ 0x00, 0x01, 0x03, 0x01, 0x00, 0x00, 0x00, 0x00}, // fight


};


//uint8_t mode_ee EEMEM = 0;                      // stores the mode in eeprom
uint8_t screen_mem[8];      // screen memory
uint8_t active_row=1;      // active row
uint8_t message_ptr = 0;                 // points to the active char in the message
uint8_t message_displayed = 0;           // how often has the message been displayed?
uint8_t active_char = 0;                 // stores the active char
uint8_t message_length = 0;              // stores the length of the active message
uint8_t char_ptr = 0;                    // points to the active col in the char
uint8_t char_length = 0;                 // stores the length of the active char
static volatile uint16_t counter = 0;    // used for delay function


// prototypes
void delay_ms(uint16_t delay);
void copy_to_display(int8_t x, int8_t y, uint8_t sprite[]);
void display_active_row(void);
void show_char();
//void clear_screen(void);
void copy_to_buffer(const prog_uint8_t sprite[8]);
//void scroll_animation(const prog_uint8_t sprite_1[], const prog_uint8_t sprite_2[], uint8_t flash, uint16_t flash);

/*
 * ISR TIMER0_OVF_vect
 * Handles overflow interrupts of timer 0.
 *
 * 4MHz
 * ----
 * Prescaler 8 ==> 1953.1 Hz
 * Complete display = 244 Hz
 *
 */


/*
 * display_active_col
 * Deactivates the active column and displays the next one.
 * Data is read from screen_mem.
 *
 *      ATtiny2313
 * 16 - PD0    PB7 - 1
 * 15 - PD1    PB6 - 2
 * 14 - PA1    PB5 - 3
 * 13 - PA0    PB4 - 4
 * 12 - PD2    PB3 - 5
 * 11 - PD3    PB2 - 6
 * 10 - PD4    PB1 - 7
 *  9 - PD5    PB0 - 8
 *
 * NFM-12883 common anode          |
 *     A0B5B4D4B2D3D1D0      +-----+
 * PD5 o o o o o o o o       |     |
 * PA1 o o o o o o o o      _+_    |
 * PB0 o o o o o o o o      \ /    |
 * PD2 o o o o o o o o     __V__   |
 * PB7 o o o o o o o o       |     |
 * PB1 o o o o o o o o    ---+-----C---
 * PB6 o o o o o o o o             |
 * PB3 o o o o o o o o
 *
 * if you have a common cathode matrix rotate your pin layout 90 Degree
 * switch row with column
 */


ISR(TIMER0_OVF_vect) {

  uint8_t row=0,i;

  // timer for delay  
  counter++;

  // shut down all rows and columns
  PORTA = (0 << PB3) | (1 << PB5);
  PORTB = (0 << PB6) | (0 << PB1) | (0 << PD2) | (1 << PB4) | 
          (1 << PB2) | (1 << PD3) | (1 << PD1) | (1 << PD0);
  PORTD = (0 << PB7) | (0 << PB0) | (0 << PA1) | (0 << PD5) |
          (1 << PA0) | (1 << PD4) | (1 << PD1);

  // next row (1,2,4,8,16,32..)
  active_row = (active_row << 7) | (active_row >> 1);

  //row = screen_mem[active_row];
  for (i=0; i<8; i++) {
  row <<= 1;
  if (screen_mem[i] & active_row) { 
    row++ ;
  }
   }

  // output all columns, switch leds on.
  // column 1
  if ((row & 0x80) == 0x80) {
    PORTA |= (1 << PA0);    
  }
  // column 2
  if ((row & 0x40) == 0x40) {
    PORTB |= (1 << PB5);    
  }
  // column 3
  if ((row & 0x20) == 0x20) {
    PORTB |= (1 << PB4);    
  }
  // column 4
  if ((row & 0x10) == 0x10) {
    PORTD |= (1 << PD4);    
  }
  // column 5
  if ((row & 0x08) == 0x08) {
    PORTB |= (1 << PB2);    
  }
  // column 6
  if ((row & 0x04) == 0x04) {
    PORTD |= (1 << PD3);    
  }
  // column 7
  if ((row & 0x02) == 0x02) {
    PORTD |= (1 << PD1);    
  }
  // column 8
  if ((row & 0x01) == 0x01) {
    PORTD |= (1 << PD0);    
  }

  //activate row
  if (active_row==0x80) PORTD &= ~(1 << PD5);
  if (active_row==0x40) PORTA &= ~(1 << PA1);
  if (active_row==0x20) PORTB &= ~(1 << PB0);
  if (active_row==0x10) PORTD &= ~(1 << PD2);
  if (active_row==0x08) PORTB &= ~(1 << PB7);
  if (active_row==0x04) PORTB &= ~(1 << PB1);
  if (active_row==0x02) PORTB &= ~(1 << PB6); 
  if (active_row==0x01) PORTB &= ~(1 << PB3);

}



/*
 * delay_ms
 * Uses the counter that is incremented by the ISR.
 * Max delay is 32767ms.
 */
void delay_ms(uint16_t delay) {
  //while (!(PIND & (1 << PD6))) {}   // used to stop the animation when PD6 goes LOW
  uint16_t t = delay * 2;
  counter = 0;
  while (counter < t) {}
}


 /*
void copy_to_display(int8_t x, int8_t y, uint8_t sprite[8]) {
  int8_t i, t;
  uint8_t column;
  clear_screen();
  for (i = 0; i < 8; i++) {
    t = i-y;
    column = ((t >= 0) && (t < 8)) ? sprite[t] : 0x00;
    column = (x >= 0) ? (column >> x) : (column << -x);

  screen_mem[i]=column;
  }
}
*/

void show_char(const prog_uint8_t string[]) {
  uint8_t i;
  uint8_t b;

  // shift the screen to the left
  for (i = 0; i < 7; i++) {
    screen_mem[i] = screen_mem[i+1]; 
  }
  // advance a char if needed
  if (char_length == 0x80) {

  char_length =0;  //reset stop bit

    //read next char from progmem
  memcpy_P(&active_char,&string[message_ptr],1);
    message_ptr++;
  
  //string stop byte 0x00 
    if (active_char == 0) {
      message_ptr = 0;
      message_displayed++;
    char_length =0x80; // immediately read next char
    }

  active_char -= CHAR_OFFSET;
    char_ptr = 0;

  // this makes the space between two chars
  screen_mem[7]=0;
    return; 
  }

  // read pixels for current column of char
  b = pgm_read_byte(&font[active_char * 5 + char_ptr]);
  char_ptr++;
  char_length= (b & 0x80);
  b = (b & 0x7F);
  // write pixels into screen memory
  screen_mem[7] =b;
}


/*
 * copy_to_buffer
 * Copies the given sprite from PROGMEM to 8x8 LED RAM.
 */
void copy_to_buffer(const prog_uint8_t sprite[8]) {
  memcpy_P(screen_mem, sprite, 8);
}


/*
 * scroll_animation
 * Uses sprite_1 and sprite_2 to draw a simple animation.
 * blink=1 : change sprite_1/2 every step  // blink=0 : blink only in the middle
 * scroll_speed: factor time for next step
 */
void scroll_animation(const prog_uint8_t sprite_1[8], const prog_uint8_t sprite_2[8], uint8_t blink) {
  uint8_t i,j;
  int8_t x,z;
  for (i = 0; i < REPEAT_ANIMATION; i++) {
  //you can scroll from right with (x = -8; x < 8; x++)
    for (x = 8; x > -9; x--) {
      //move sprite 1
    for (j = 0; j < 8; j++) {
      screen_mem[j] = 0x00;
      z = x+j;
      if ((z>=0) && (z<8)) {
        if (blink & x) {
          memcpy_P(&screen_mem[j],&sprite_2[z],1);
        }
        else {
          memcpy_P(&screen_mem[j],&sprite_1[z],1);
        }
      }
    }
      delay_ms(ANIMATION_SCROLL_SPEED);

      if (x==0) {
    //in the middle shift betwenn sprite_1 and sprite_2
    for (j=0; j<4;j++) {
        copy_to_buffer(sprite_2);
        delay_ms(ANIMATION_SPEED);
        copy_to_buffer(sprite_1);
        delay_ms(ANIMATION_SPEED);
    }
    }
  }  
  }
}

/*
 * step_animation
 * Uses sprite_1 to draw a simple animation.
 * size of array
 */
void step_animation(const prog_uint8_t sprite_1[][8], uint8_t size) {
  uint8_t i;
  for (i = 0; i < size; i++) {
   copy_to_buffer(sprite_1[i]); //array: step pointer by 8
     delay_ms(ANIMATION_SPEED);
  }  
}


int main(void) {

  int8_t i,j,k;

  // timer 0 setup, prescaler 8
  TCCR0B |= (1 << CS01);
 
  // enable timer 0 interrupt
  TIMSK |= (1 << TOIE0);  

  // define outputs
  DDRA |= 0x03;  
  DDRB |= 0xFF;
  DDRD |= 0x3F;
 
/*
  // killed by code size
  // read last mode from eeprom
  // 0 mean cycle through all modes and messages
  mode = eeprom_read_byte(&mode_ee);
  if ((mode == 0) || (mode >= (MAX_ANIMATIONS + MAX_MESSAGES + 1))) {
    mode = 4;
  }
  eeprom_write_byte(&mode_ee, mode + 1);  
*/
  sei();

  while (1) {

   for (i = 0; i < REPEAT_ANIMATION; i++) {
     step_animation(dancer1[0], 23);  
   }  

  }

return 0;

}


Autor: MaWin (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: ernst unfriendlyforum (Firma: nono) (circat)
Datum:

Bewertung
0 lesenswert
nicht 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 !

Autor: Falk Brunner (falk)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: ernst unfriendlyforum (Firma: nono) (circat)
Datum:

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

Autor: Falk Brunner (falk)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: ernst unfriendlyforum (Firma: nono) (circat)
Datum:

Bewertung
0 lesenswert
nicht 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 ?

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.