MAX7221 mit ATMega32 über SPI

Gast #2078241
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:
1
#include <avr\io.h>
2

3

4
void SPI_write(unsigned char, unsigned char);
5
void max7221_init(void);
6

7
void main(){
8
    DDRB = (1<<PB4)|(1<<PB5)|(1<<PB6); // MOSI,SCK, SS als Output, Rest als Input
9
  SPCR = (1<<SPE)|(1<<MSTR);         // SPI enable, Master Mode
10
  PORTB |= (1<<PB4);
11
  max7221_init();
12
  SPI_write(0x01,0x01);
13
  while(1){                          //mainloop    
14
  }
15
}
16

17

18
void SPI_write(unsigned char addr,unsigned char data)
19
{
20
    PORTB &= ~(1<<PB4);           // Set CS pin to 0
21
  SPDR = addr;                  // Start Address transmission
22
  while(!(SPSR & (1<<SPIF)));   // Wait for transmission complete
23
  SPDR = data;                  // Start Data transmission 
24
  while(!(SPSR & (1<<SPIF)));   // Wait for transmission complete
25
  PORTB |= (1<<PB4);         // Set tze CS pin to 1
26
}
27

28
void max7221_init(){
29
  SPI_write(0x0C,0x01); //normal operation
30
  SPI_write(0x09,0x00); //no decode
31
  SPI_write(0x0A,0x02); //set intensity
32
  SPI_write(0x0B,0x07); //display all digits
33
  SPI_write(0x0C,0x01); //normal operation
34
  SPI_write(0x0F,0x00); //Displaytest aus
35
  SPI_write(0x01,0x00); //clear Digit 1
36
  SPI_write(0x02,0x00); //clear Digit 2
37
  SPI_write(0x03,0x00); //clear Digit 3
38
  SPI_write(0x04,0x00); //clear Digit 4
39
  SPI_write(0x05,0x00); //clear Digit 5
40
  SPI_write(0x06,0x00); //clear Digit 6
41
  SPI_write(0x07,0x00); //clear Digit 7
42
  SPI_write(0x08,0x00); //clear Digit 8
43
}

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
#2078473
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:
1
#include <avr\io.h>
2

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

5
typedef unsigned char byte;
6

7
struct test {
8
  byte b0:1;
9
  byte b1:1;
10
  byte b2:1;
11
  byte b3:1;
12
  byte b4:1;
13
  byte b5:1;
14
  byte b6:1;
15
  byte b7:1;
16
} __attribute__((__packed__));
17

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

20
#define Max7221DIN     BIT(PORTD,5)
21

22

23
void SPI_write(unsigned char, unsigned char);
24
void max7221_init(void);
25

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

35
  max7221_init();
36
  SPI_write(0x01,0x0F);
37
  //SPI_write(0x02,0x05);
38
  while(1){                          //mainloop    
39
  }
40
}
41

42

43
void SPI_write(unsigned char Address,unsigned char Data) 
44
{ 
45
  unsigned char i; 
46
  PORTD &= ~(1<<PD4); 
47
  for (i=0;i<8;i++) 
48
  { 
49
    PORTD &= ~(1<<PD6); //Clock auf 0
50
    Max7221DIN = (Address&(0x80>>i)) ? 1:0; 
51
    _nop_(); 
52
    _nop_(); 
53
    PORTD |= (1<<PD6);  //Clock auf 1
54
    _nop_(); 
55
    _nop_(); 
56
  } 
57
  for (i=0;i<8;i++) 
58
  { 
59
    PORTD &= ~(1<<PD6);  //Clock auf 0
60
    Max7221DIN = (Data&(0x80>>i)) ? 1:0; 
61
    _nop_(); 
62
    _nop_(); 
63
    PORTD |= (1<<PD6);  //Clock auf 1
64
    _nop_(); 
65
    _nop_(); 
66
  } 
67
  PORTD |= (1<<PD4);
68
} 
69
 
70

71

72
/*
73
void SPI_write(unsigned char addr,unsigned char data)
74
{
75
    PORTB &= ~(1<<PB4);           // Set CS pin to 0
76
  SPDR = addr;                  // Start Address transmission
77
  while(!(SPSR & (1<<SPIF)));   // Wait for transmission complete
78
  SPDR = data;                  // Start Data transmission 
79
  while(!(SPSR & (1<<SPIF)));   // Wait for transmission complete
80
  PORTB |= (1<<PB4);         // Set tze CS pin to 1
81
}
82
*/
83

84
void max7221_init(){
85
  SPI_write(0x0C,0x01); //normal operation
86
  SPI_write(0x09,0x00); //no decode
87
  SPI_write(0x0A,0x02); //set intensity
88
  SPI_write(0x0B,0x07); //display all digits
89
  SPI_write(0x0C,0x01); //normal operation
90
  SPI_write(0x0F,0x00); //Displaytest aus
91
  SPI_write(0x01,0x00); //clear Digit 1
92
  SPI_write(0x02,0x00); //clear Digit 2
93
  SPI_write(0x03,0x00); //clear Digit 3
94
  SPI_write(0x04,0x00); //clear Digit 4
95
  SPI_write(0x05,0x00); //clear Digit 5
96
  SPI_write(0x06,0x00); //clear Digit 6
97
  SPI_write(0x07,0x00); //clear Digit 7
98
  SPI_write(0x08,0x00); //clear Digit 8
99
}

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
#2079675
Lesenswert?

Hallo Peter,

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

Oder meinst du was anderes?

Gruß
Marius

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren