mikrocontroller.net

Forum: Compiler & IDEs MAX7221 mit ATMega32 über SPI


Autor: Marius (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Guten Abend zusammen,

ich habe mir einen LED-Cube (4x4x4) zusammengelötet, der per MAX7221 
angesteuert wird. Als µC habe ich einen ATMega32 auf einem 
AVR-Evaluationsboard von Pollin. Programmiert wird über ein USB-AVR-Lab 
von Ullihome mit STK500 Firmware.

Ich hbe den Cube schon mittels Bascom angesteuert und es hat auch alles 
so funktioniert, wie es sollte, also ist die elektronische Schaltung 
richtig.

Nun möchte ich gerne auf C umsteigen, aber es klappt nicht. Manchmal 
leuten alle LEDs und manchmal keine. Ich hab "erweiterte 
Grundkenntnisse" in C, hab aber noch nie einen AVR-Programmiert. Bisher 
immer nur mit Bascom.

Der MAX7221 wartet auf insgesamt 16 bit. Das erste Bit ist das MSB. Nach 
der Initialisierung steht das erste Byte für das Digit und das zweite 
Byte für die 8 Segmente. Damit sollte mit diesem Code bei Digit 1 die 
erste LED leuchten (SPI_write(0x01,0x01)). Tut sie aber nicht.

Code:
#include <avr\io.h>


void SPI_write(unsigned char, unsigned char);
void max7221_init(void);

void main(){
    DDRB = (1<<PB4)|(1<<PB5)|(1<<PB6); // MOSI,SCK, SS als Output, Rest als Input
  SPCR = (1<<SPE)|(1<<MSTR);         // SPI enable, Master Mode
  PORTB |= (1<<PB4);
  max7221_init();
  SPI_write(0x01,0x01);
  while(1){                          //mainloop    
  }
}


void SPI_write(unsigned char addr,unsigned char data)
{
    PORTB &= ~(1<<PB4);           // Set CS pin to 0
  SPDR = addr;                  // Start Address transmission
  while(!(SPSR & (1<<SPIF)));   // Wait for transmission complete
  SPDR = data;                  // Start Data transmission 
  while(!(SPSR & (1<<SPIF)));   // Wait for transmission complete
  PORTB |= (1<<PB4);         // Set tze CS pin to 1
}

void max7221_init(){
  SPI_write(0x0C,0x01); //normal operation
  SPI_write(0x09,0x00); //no decode
  SPI_write(0x0A,0x02); //set intensity
  SPI_write(0x0B,0x07); //display all digits
  SPI_write(0x0C,0x01); //normal operation
  SPI_write(0x0F,0x00); //Displaytest aus
  SPI_write(0x01,0x00); //clear Digit 1
  SPI_write(0x02,0x00); //clear Digit 2
  SPI_write(0x03,0x00); //clear Digit 3
  SPI_write(0x04,0x00); //clear Digit 4
  SPI_write(0x05,0x00); //clear Digit 5
  SPI_write(0x06,0x00); //clear Digit 6
  SPI_write(0x07,0x00); //clear Digit 7
  SPI_write(0x08,0x00); //clear Digit 8
}

Noch ne kurze ergänzende Frage:
SPI nutzt ja die gleichen Pins wie die ISP. Macht es dann etwas aus, 
wenn der Programmer noch am Board hängt?

Ich hoffe ihr könnt mir Helfen!

Viele Grüße
Marius

Autor: Marius F. (marius_f)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich bins nochmal:

Ich hab noch etwas rumgesucht und bin über Google auf folgende Seite 
gestoßen:
http://www.hackchina.com/en/r/19672/Max7221.h__html
Dabei wird nich das Hardware-SPI verwendet, sondern das ganze "per Hand" 
gemacht. Daraufhin hab ich den Code folgendermaßen umgestrickt, und nun 
Läuft es:
#include <avr\io.h>

#define _nop_() asm volatile("nop")

typedef unsigned char byte;

struct test {
  byte b0:1;
  byte b1:1;
  byte b2:1;
  byte b3:1;
  byte b4:1;
  byte b5:1;
  byte b6:1;
  byte b7:1;
} __attribute__((__packed__));

#define BIT(r,n) (((volatile struct test *)&r)->b##n)

#define Max7221DIN     BIT(PORTD,5)


void SPI_write(unsigned char, unsigned char);
void max7221_init(void);

void main(){
    //DDRB |= (1<<PB4)|(1<<PB5)|(1<<PB6); // MOSI,SCK, SS als Output, Rest als Input
  //SPCR |= (1<<SPE)|(1<<MSTR)|(1<<SPR1);         // SPI enable, Master Mode
  //SPSR |= (1<<SPI2X);
  //PORTB |= (1<<PB4);
  DDRD = (1<<PD4)|(1<<PD5)|(1<<PD6); //Als Ausgänge setzen
  PORTD |= (1<<PD4); //CS auf 1
  PORTD |= (1<<PD6); //Clock auf 1

  max7221_init();
  SPI_write(0x01,0x0F);
  //SPI_write(0x02,0x05);
  while(1){                          //mainloop    
  }
}


void SPI_write(unsigned char Address,unsigned char Data) 
{ 
  unsigned char i; 
  PORTD &= ~(1<<PD4); 
  for (i=0;i<8;i++) 
  { 
    PORTD &= ~(1<<PD6); //Clock auf 0
    Max7221DIN = (Address&(0x80>>i)) ? 1:0; 
    _nop_(); 
    _nop_(); 
    PORTD |= (1<<PD6);  //Clock auf 1
    _nop_(); 
    _nop_(); 
  } 
  for (i=0;i<8;i++) 
  { 
    PORTD &= ~(1<<PD6);  //Clock auf 0
    Max7221DIN = (Data&(0x80>>i)) ? 1:0; 
    _nop_(); 
    _nop_(); 
    PORTD |= (1<<PD6);  //Clock auf 1
    _nop_(); 
    _nop_(); 
  } 
  PORTD |= (1<<PD4);
} 
 


/*
void SPI_write(unsigned char addr,unsigned char data)
{
    PORTB &= ~(1<<PB4);           // Set CS pin to 0
  SPDR = addr;                  // Start Address transmission
  while(!(SPSR & (1<<SPIF)));   // Wait for transmission complete
  SPDR = data;                  // Start Data transmission 
  while(!(SPSR & (1<<SPIF)));   // Wait for transmission complete
  PORTB |= (1<<PB4);         // Set tze CS pin to 1
}
*/

void max7221_init(){
  SPI_write(0x0C,0x01); //normal operation
  SPI_write(0x09,0x00); //no decode
  SPI_write(0x0A,0x02); //set intensity
  SPI_write(0x0B,0x07); //display all digits
  SPI_write(0x0C,0x01); //normal operation
  SPI_write(0x0F,0x00); //Displaytest aus
  SPI_write(0x01,0x00); //clear Digit 1
  SPI_write(0x02,0x00); //clear Digit 2
  SPI_write(0x03,0x00); //clear Digit 3
  SPI_write(0x04,0x00); //clear Digit 4
  SPI_write(0x05,0x00); //clear Digit 5
  SPI_write(0x06,0x00); //clear Digit 6
  SPI_write(0x07,0x00); //clear Digit 7
  SPI_write(0x08,0x00); //clear Digit 8
}

Warum funktioniert das ganze dann nicht mit dem Hardware-SPI?
Ich hab nur Clock, MOSI und CS auf andere Pins gelegt, ansonsten ist die 
Hardware identisch.
Hat jemand ne Idee?

Viele Grüße
Marius

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Marius F. schrieb:
> Warum funktioniert das ganze dann nicht mit dem Hardware-SPI?

Ein möglicher Fehler:
Der /SS-Pin muß vor SPI-Init auf Ausgang gesetzt werden.


Peter

Autor: Marius F. (marius_f)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Peter,

das hab ich doch getan.
Zuerst DDRB konfiguriert und dann SPI eingeschaltet
DDRB = (1<<PB4)|(1<<PB5)|(1<<PB6); // MOSI,SCK, SS als Output, Rest als Input
SPCR = (1<<SPE)|(1<<MSTR);         // SPI enable, Master Mode
PORTB |= (1<<PB4);

Oder meinst du was anderes?

Gruß
Marius

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Marius F. schrieb:
> das hab ich doch getan.

Dann wird wohl was anderes falsch sein.
Probier mal alle 4 Modies aus.

Ich benutze meistens auch nur das Bitschubser-SPI in SW.


Peter

Autor: holger (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>Ich benutze meistens auch nur das Bitschubser-SPI in SW.

Mein Gott wie armselig. Kriegst du das SPI Modul nicht zum laufen?
Ich geb dir gerne Nachhilfestunden;)

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
holger schrieb:
> Ich geb dir gerne Nachhilfestunden;)

Nicht nötig.
Ich hab an einem ATmega2560 am SPI ADCs und DACs am Laufen und an einer 
UART im SPI-Modus einige IO-Expander (74HC165/74HC595).

Welcher Modus für den MAX7219 paßt, müßte ich aber erst im Datenblatt 
nachsehen.

Ich benutze auch oft ATtinys und da bevorzuge ich SW-SPI.


Peter

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.