Forum: Mikrocontroller und Digitale Elektronik Hardware SPI Problem


von cler :) (Gast)


Lesenswert?

Hi ich habe ein Problem mit meinen SPI Funktionen und weiß nicht was ich 
falsch mache, denn den Code habe ich eingentlich aus dem entsprechenden 
Datenblatt entnommen.

Es geht hierbei um den ATmega44a mit dem ich den CC1100 von TI 
ansprechen will.

Ich habe vorher noch nicht mit Hardware SPI geareitet, daher bin ich 
erstmal dabei in dem CC1100 in die Register zu schreiben und dann wieder 
auszulesen.

Hier ist mein Programm:

main.c
1
#include <avr/io.h>
2
//#include <avr/sleep.h>
3
#include "uart.h"
4
#include "cc1101.h"
5
#include "ioconf.h"
6
#include "register.h"
7
8
int main(void)
9
{  
10
  char input = 0xff;
11
  
12
  //initialization functions
13
  io_init();
14
  spi_init();
15
  uart_init();  
16
  
17
  cc_power(1);
18
  uart_puts("cc1100 eingeschaltet\n");
19
  cc_config();
20
  uart_puts("cc1100 configuriert");
21
  
22
  //program started go into while loop
23
  uart_puts("start\n");
24
  
25
    while(1){                
26
  }
27
  
28
  return 0;
29
}

cc1101.c:
1
/************************************************************************/
2
/* cc1101.c - functions for cc1101 and spi functions                    */
3
/************************************************************************/
4
#include "cc1101.h"
5
#include "ioconf.h"
6
#include <avr/io.h>
7
#include "register.h"
8
#include "uart.h";
9
10
/*************************************************************************
11
void spi_init():
12
  SPI configuration as master                                                                   
13
************************************************************************/
14
void spi_init(){
15
  SPCR = (1 << SPE) | (1 << MSTR) | (1 << SPR0);
16
}
17
18
/************************************************************************
19
void spi_send(char data)
20
  data = address or input on the SPI bus
21
************************************************************************/
22
void spi_send(char data){    
23
  SPDR = data;
24
  uart_puts("SPDR has received data content\n");
25
  while(!(SPSR & (1 << SPIF)));  
26
  uart_puts("end of while and spi_send()\n");
27
}
28
29
/************************************************************************
30
char spi_read(char addr):
31
  addr = address of spi register of cc1101
32
  
33
  addr will be manipulated that the msb shows that the master is
34
  reading from the bus
35
************************************************************************/
36
char spi_read(char addr){
37
  SPDR = (addr);
38
  while(!(SPSR & (1 << SPIF)));
39
  return SPDR;
40
}
41
42
/************************************************************************
43
cc_writeRegister(char addr, char data)
44
  addr = register address
45
  data = data written to registers address  
46
************************************************************************/
47
void cc_writeRegister(char addr, char data){
48
  uart_puts("cc_writeRegister start\n");
49
  cc_select(1);
50
  
51
  spi_send(addr);
52
  spi_send(data);
53
  
54
  cc_select(0);
55
  uart_puts("cc_writeRegister end\n");
56
}
57
58
/************************************************************************
59
cc_readRegister(char addr)
60
  addr = address of register
61
************************************************************************/
62
char cc_readRegister(char addr){
63
  char data = 0xff;
64
  
65
  uart_puts("cc_readRegister start\n");
66
  cc_select(1);
67
  
68
  data = spi_read(addr | 0x80);
69
  
70
  cc_select(0);
71
  uart_puts("cc_readRegister end\n");
72
  
73
  return data;
74
}
75
76
/************************************************************************
77
void cc_config():
78
  configures the cc1101 with the necessary settings:
79
************************************************************************/
80
void cc_config(){
81
  uart_puts("write 1\n");
82
  cc_writeRegister(CC1100_FSCTRL1, 0x08);
83
  uart_puts("write 2\n");
84
  cc_writeRegister(CC1100_FSCTRL0, 0x00);
85
  uart_puts("write 3\n");
86
  cc_writeRegister(CC1100_FIFOTHR, 0x04);
87
  uart_puts("write 4\n");
88
  cc_writeRegister(CC1100_FREQ2, 0x21);
89
  uart_puts("write 5\n");
90
  cc_writeRegister(CC1100_FREQ1, 0x76);
91
  uart_puts("write 6\n");
92
  cc_writeRegister(CC1100_FREQ0, 0x27);      
93
}

Die Register (Tabelle mit CC1100 Registern) und die IO Sachen sind 
ausgiebig getestet das stimmt soweit aber wenn ich das Programm laufen 
lasse bricht er in cc_config() ab und zwar wenn ich den ersten Register 
beschreibe. Ich habe zum debuggen kommentare über die serielle 
Schnittstelle ausgeben lassen.

Abbruch bzw Endlosschleife laut aufgabe bei:

cc_config() -> cc_writeRegister() -> spi_send(data) -> dort in der While 
Schleife


Ausgabe auf dem Terminal:

cc1100 eingeschaltet
write 1
cc_writeRegister start
SPDR has received data content
end of while and spi_send()
SPDR has received data content

Sind meine SPI Funktionen richtig? Denn das auslesen Funktioniert auch 
nicht. Das habe ich auch schon getestet um die Intertialwerte 
auszulesen.
Den Programmteil habe ich aber verworfen um es simpler zu gestalten.

Wäre cool wenn ihr mir da helfen würdet.

Gruß cler

von spess53 (Gast)


Lesenswert?

Hi

>char spi_read(char addr){
>  SPDR = (addr);
>  while(!(SPSR & (1 << SPIF)));
>  return SPDR;

Um etwas vom Slave zu lesen muss man ein Dummy-Byte senden.

MfG Spess

von cler :) (Gast)


Lesenswert?

Danke, aber wo muss ich die denn einbauen?

cler

von cler :) (Gast)


Lesenswert?

Aber ich sende doch die Addresse an den Chip reicht das nicht als 
Dummybyte? Beim SoftSPI kenne ich das noch so:

Adresse schicken :
   SPDR = (addr);
   while(!(SPSR & (1 << SPIF)));
dann warten und Register lesen:
   return SPDR;

Allerdings muss ich beim HardwareSPI doch nicht warten oder?

von spess53 (Gast)


Lesenswert?

Hi

>Aber ich sende doch die Addresse an den Chip reicht das nicht als
>Dummybyte?

Dann muss dein CC1100 hellseherische Fähigkeiten haben. Ein SPI-Slave 
(dein CC1100) bekommt zu Senden und Empfangen den Takt vom Master 
(ATMega). Und ein Takt wird nur erzeugt, wenn der ATMega etwas sendet 
(und dabei gleichzeitig empfängt). So wie du es willst muss der CC1100 
schon beim ersten Bit der Adresse wissen, welche Bits er mit dem Takt 
rausschieben muss.

MfG Spess

von Karl H. (kbuchegg)


Lesenswert?

SPI musst du dir wie das gleichzeitige Austauschen von Bytes vorstellen.

Wenn der Master etwas zum Slave sendet, überträgt gleichzeitig der Slave 
1 Byte zum Master.

So wie wenn du und dein Kumpel euch am Tisch gegenüber sitzt.
Jeder hat ein Kuvert in der Hand, in dem die Nachricht steckt.
Du schiebst mit der rechten Hand dein Kuvert über den Tisch und dein 
Kumpel macht genau dasselbe. D.h. mit der rechten Hand schiebst du dein 
Kuvert rüber und mit der linken Hand nimmst du das Kuvert, welches dein 
Kumpel dir zeitgleich rüberschickt.

So. Wenn du jetzt von deinem Kumpel etwas wissen willst, dann kann 
logischerweise die Antwort auf deine Anfrage NICHT im ersten Kuvert 
sein, welches dein Kumpel dir rüberschiebt. Denn der kann ja zu diesem 
Zeitpunk noch gar nicht wissen, was du von ihm willst.

Du musst ihm also mal deine Anfrage in einem Kuvert rüberschieben. Das 
Kuvert welches du von deinem Kumpel kriegst, enthält für dich nichts 
wesentliches. D.h. das kannst du ignorieren.

Dann sieht dein Kumpel in des gerade gekriegte Kuvert rein, besorgt die 
Information, die du angefragt hast, und schreibt sie in das Kuvert das 
er hat.
Damit du dann diese Information wieder kriegen kannst, müsst ihr nochmal 
die Kuverts tauschen.

Und erst dann hast du die Antwort auf deine Anfrage.

Stell es dir einfach bildlich vor, wie das abläuft. Dann ist es ganz 
einfach.

> Danke, aber wo muss ich die denn einbauen?
Die Frage solltest du dir jetzt eigentlich selbst beantworten können.
Die Sequenz
1
  ...
2
  SPDR = Bytewert;
3
  while(!(SPSR & (1 << SPIF)))
4
    ;
5
  ...
entspricht EINEM Kuverttausch.
Mit der Zuweisung stösst du ihn an, und die while-Schleife wartet 
darauf, dass der Austausch fertig vollzogen ist.
Danach kannst du durch Auslesen von SPDR in das gerade erhaltene Kuvert 
reinschauen. Du kannst, aber du musst natürlich nicht.

von Karl H. (kbuchegg)


Lesenswert?

Mir fehlt deine
1
  io_init();

Hast du den SS Pin der SPI auf Ausgang gestellt?

von cler :) (Gast)


Lesenswert?

Super Erklärung vielen Dank :)

Also ich habe dann die lesefunktion so umgeschrieben:
Von der Logik her muss ich dem Chip die Adresse mitteilen, dabei bekomme 
ich Müll dafür bietet sich die Funktion spi_send() an. Dann muss ich 
noch ein Dummybyte senden damit ich in der Antwort daraufhin die Info 
bekomme.

Aber im /**/ habe ich makiert wo mein Programm nicht mehr funktioniert. 
Ich bekomme keine Meldung über das Terminal

Was mache ich noch falsch?

Danke euch schonmal
1
in der main aufgerufen:
2
3
uart_puts("\nread FREQ2\n");
4
uart_putc(cc_readRegister(CC1100_FREQ2));
5
6
char cc_readRegister(char addr){
7
  char data = 0xff;
8
  
9
  uart_puts("cc_readRegister(");
10
  uart_putc(addr);
11
  uart_puts(") start\n");
12
  cc_select(1);
13
  
14
  spi_send(addr | 0x80);  //anfrage nach inhalt der addresse
15
16
  data = spi_read(addr);  //addresse mit dummy byte zB addr
17
  
18
  cc_select(0);
19
  uart_puts("cc_readRegister end\n");
20
  
21
  return data;
22
}
23
24
char spi_read(char addr){
25
  uart_puts("spi_read() start\n");
26
  
27
  SPDR = (addr);
28
  uart_puts("spi_send() SPDR received data content\n");
29
30
        /**/
31
32
  while(!(SPSR & (1 << SPIF)));
33
  uart_puts("spi_read() end returning data\n");
34
  return SPDR;
35
}
36
37
void spi_send(char data){    
38
  SPDR = data;
39
  uart_puts("spi_send() SPDR has received data content\n");
40
  while(!(SPSR & (1 << SPIF)));  
41
  uart_puts("end of while and spi_send()\n");
42
}

Debug Ausgabe auf dem Terminal:

cc1100 eingeschaltet<\n>
start<\n>
<\n>
read FREQ2<\n>
cc_readRegister(<\r>) start<\n>
spi_send() SPDR has received data content<\n>
end of while and spi_send()<\n>
spi_read() start<\n>
spi_send() SPDR received data content<\n>

von Karl H. (kbuchegg)


Lesenswert?

cler :) schrieb:

> Aber im /**/ habe ich makiert wo mein Programm nicht mehr funktioniert.
> Ich bekomme keine Meldung über das Terminal
>
> Was mache ich noch falsch?

Nochmal.
Hast du den SS Pin der SPI auf Ausgang gestellt!

Das ist wichtig. Denn sonst fungiert dein µC nicht als Master. Selbst 
dann nicht wenn du es im Konfigurationsregister angefordert hast!

(OK, die Wahrheit ist ein wenig komplizierter, aber in a Nutshell kann 
man das vereinfacht so sagen: Wenn µC als Master fungieren soll, dann 
MUSS der SS Pin der SPI auf Ausgang gestellt werden. Sonst generiert der 
AVR keinen Clock und die Übertragung findet nicht statt)

von Karl H. (kbuchegg)


Lesenswert?

Fass die beiden hier
1
char spi_read(char addr){
2
  uart_puts("spi_read() start\n");
3
  
4
  SPDR = (addr);
5
  uart_puts("spi_send() SPDR received data content\n");
6
7
        /**/
8
9
  while(!(SPSR & (1 << SPIF)));
10
  uart_puts("spi_read() end returning data\n");
11
  return SPDR;
12
}
13
14
void spi_send(char data){    
15
  SPDR = data;
16
  uart_puts("spi_send() SPDR has received data content\n");
17
  while(!(SPSR & (1 << SPIF)));  
18
  uart_puts("end of while and spi_send()\n");
19
}
zu einer einzigen Funktion zusammen. Du brauchst da keine 2 getrennte 
Funktionen, das verwirrt doch nur. Die machen sowieso dasselbe.
1
char spi_transfer(char byte)
2
{
3
  uart_puts("spi_transfer() start\n");
4
  
5
  SPDR = byte;
6
  uart_puts("spi_transfer() SPDR received data content\n");
7
8
  while(!(SPSR & (1 << SPIF)))
9
    ;
10
  uart_puts("spi_transfer() end returning data\n");
11
  return SPDR;
12
}

und mit der baust du dann deine
void cc_writeRegister(char addr, char data)
char cc_readRegister(char addr)
Funktionen auf.

von cler :) (Gast)


Lesenswert?

Also ich bleibe jetzt nicht mehr in der Schleife hängen und das lag doch 
tatsächlich an einem IO Pin der falsch gesetzt war.. der ss pin muss 
beim atmega gesetzt sein, damit das ganze mit der spi funktioniert

Allerdings habe ich jetzt ein paar Register mit werten Beschrieben und 
anschließend wollte ich die wieder auslesen aber ich bekomme mit der 
Funktion spi() nur \0 zurück
1
char spi(char data){
2
  SPDR = data;
3
  while(!(SPSR & (1 << SPIF)));
4
  return SPDR;
5
}

was läuft da immernoch falsch?

funktion um in die Register zu schreiben:
1
void cc_writeRegister(char addr, char data){
2
  char tmp = 0xff;
3
  
4
  cc_select(1);
5
  
6
  tmp = spi(addr);
7
  uart_puts("tmp = ");
8
  uart_putc(tmp);
9
  uart_putc('\n');
10
  
11
  tmp = spi(data);
12
  uart_puts("tmp = ");
13
  uart_putc(tmp);
14
  uart_putc('\n');
15
  
16
  cc_select(0);
17
}

tmp ist immer \0 was ich auch nicht verwunderlich finde, aber ich dachte 
mir wenn ich die Info habe kann ich sie auch rausrücken.

cler

von Karl H. (kbuchegg)


Lesenswert?

Na was erwartest du?
Beim schreiben von Registern wird dir der IC nichts sinnvolles 
zurückschicken. Der nimmt die Adresse, nimmt den Wert und beschreibt 
sein internes Register. Mehr wird der nicht tun.
Irgendwas muss er zurückgeben, ob er will oder nicht - weil das ja immer 
ein Bytetausch ist. Also wird der halt immer 0 zurückgeben. Ist ja 
schliesslich auch eine Information. Nämlich: 'HuHu, ich bin da!'

Anders sieht es beim Lesen aus!

von Karl H. (kbuchegg)


Lesenswert?

cler :) schrieb:

> tmp ist immer \0 was ich auch nicht verwunderlich finde, aber ich dachte
> mir wenn ich die Info habe kann ich sie auch rausrücken.

Ja, schon.
Aber warum gibst du sie nicht als Zahlenwert aus, sondern über 
usart_putc?
Schreib dir halt ein usart_puth, welches die ein Byte als Hexzahl 
ausgibt. Ist doch keine Hexerei, sich die Hilfsunktionen zu bauen, die 
man braucht. Und gerade Zahlenausgabe braucht man immer wieder.


PS: wenn wir schon dabei sind.
Der angebrachte Datentyp für alles was im weitesten Sinne ein Byte ist, 
ist ein unsigned char, oder ein uint8_t. Aber einen char willst du da 
eigentlich nicht nehmen. Du willst an dieser Stelle es nicht dem 
Compiler überlassen, ob er ein char als mit oder ohne Vorzeichen 
ansieht.

Gewöhn dir an, dass es 3(!) Datentypen gibt
1
  signed char        kleine Zahlen mit Vorzeichen
2
  unsigned char      kleine Zahlen ohne Vorzeichen, also Bytes
3
  char               für alles, was mit Texten oder Textverarbeitung
4
                     zu tun hat.
Anstelle von signed char kannst du auch einen int8_t nehmen.
Anstelle von unsigned char kannst du auch einen uint8_t nehmen.

Aber akzeptiere, dass es einen Character in 3(!) unterschiedlichen 
Ausprägungen gibt, orientier dich an der 'Tabelle', unter welchen 
Umständen du welchen nimmst, und du hast auf lange Sicht weniger Ärger.

von cler :) (Gast)


Lesenswert?

Danke für den Tipp werde mir das mit den 8 Bit Datentypen mal zu Herzen 
nehmen. Ich habe das so auf den 8051ern gelernt. Aber mein Problem liegt 
ja auch beim auslesen.. Das ich da immer \0 zurück bekomme.

Hier schreibe ich in die Frequenzregister:
1
uart_puts("write 4\n");
2
cc_writeRegister(CC1100_FREQ2, 0x21);
3
uart_puts("write 5\n");
4
cc_writeRegister(CC1100_FREQ1, 0x76);
5
uart_puts("write 6\n");
6
cc_writeRegister(CC1100_FREQ0, 0x27);

Hier zB: lese ich die zuvor eingestellten Frequenzen aus:
1
uart_puts("\nread FREQ2\n");
2
uart_putc(cc_readRegister(CC1100_FREQ2));
3
uart_puts("\nread FREQ1\n");
4
uart_putc(cc_readRegister(CC1100_FREQ1));
5
uart_puts("\nread FREQ0\n");
6
uart_putc(cc_readRegister(CC1100_FREQ0));


Warum gibt der mir dann beim Lesen immer nur \0 aus obwohl da jetzt 0x21 
0x76 und 0x27 zurückkommen müsste.

Hier nochmal die Funktion cc_readRegister:
1
char cc_readRegister(char addr){
2
  char data = 0xff;
3
  
4
  cc_select(1);
5
  
6
  data = spi((addr |0x80));
7
  
8
  uart_puts("data = ");
9
  uart_putc(data);
10
  uart_putc('\n');
11
  
12
  data = spi(addr | 0x80);
13
  
14
  uart_puts("data = ");
15
  uart_putc(data);
16
  uart_putc('\n');
17
  
18
  cc_select(0);
19
  
20
  return data;
21
}

Vielen Dank für eure Mühe

Gruß cler :)

von holger (Gast)


Lesenswert?

Versuchs mal so:
1
char cc_readRegister(char addr){
2
  char data = 0xff;
3
  
4
  cc_select(0);
5
  
6
  data = spi((addr |0x80));
7
  
8
  uart_puts("data = ");
9
  uart_putc(data);
10
  uart_putc('\n');
11
  
12
  data = spi(addr | 0x80);
13
  
14
  uart_puts("data = ");
15
  uart_putc(data);
16
  uart_putc('\n');
17
  
18
  cc_select(1);
19
  
20
  return data;
21
}

von Scheri (Gast)


Lesenswert?

>Warum gibt der mir dann beim Lesen immer nur \0 aus obwohl da jetzt 0x21
>0x76 und 0x27 zurückkommen müsste.

Stimmt der SPI Mode?

von Karl H. (kbuchegg)


Lesenswert?

holger schrieb:
> Versuchs mal so:

:-)
oder zeig zumindest die Funktion cc_select her, zusammen mit der 
Information, ob der angehängte IC eine 1 oder eine 0 an seinem 
Select-Eingang sehen will um sich angesprochen zu fühlen.

von cler :) (Gast)


Lesenswert?

Hier ist die Funktion mit dem select also wie schon im Datenblatt steht 
CS muss low sein also wenn ich cc_select(1) hab aktiviere ich den Chip 
und schalte demnach auf low:
1
void cc_select(unsigned char p){
2
  if(p == 1){
3
    PORTB &= ~(1 << PB1);  
4
  }else{
5
    PORTB |= (1 << PB1);  
6
  }  
7
}

Habe das sowohl mit der Polarität und der Phase ausprobiert. Und beides 
nochmal mit vertauschtem cc_select() ich bin langsam mit meinem Latein 
am Ende.

von Felix P. (fixxl)


Lesenswert?

Hast du irgendwo in deinem Initialisierungscode die Zeile
1
DDRB |= 1<<PB1;
drin?

Ansonsten würdest du mit deiner Funktion cc_select(1) nur den 
Pullup-Widerstand deaktivieren bzw. ihn mit cc_select(0) aktivieren.

von Karl H. (kbuchegg)


Lesenswert?

Oder mal alles zusammengenommen:

Zeig doch bitte endlich mal den kompletten Code!
Die UART Funktionen brauchen wir nicht. Aber alle Funktionen, egal ob du 
sie für wichtig hältst oder nicht, die im Zusammenhang mit SPI stehen. 
Und ja, die Datenrichtungen gehören da genauso dazu! Im Idealfall 
versetzt du uns in die Lage, deinen Code zu nehmen, zu compilieren und 
auf einen M44 zu brennen.

Du hast doch selber schon gesehen, dass dein erster Fehler (SS Pin) 
nicht in dem aufgetaucht ist, was du präsentiert hast! Gefunden wurde er 
nur, weil das ein Standardfehler ist und korrekt erraten wurde. Lass uns 
nicht raten! Lass uns am Problem arbeiten. Dazu brauchen wir aber 
vollständige Informationen.

von cler :) (Gast)


Lesenswert?

IO Initialisierung:
1
void io_init(){
2
  // I/O-Ports initialisieren
3
4
  /* Port B Initialisierung
5
  // Port B1  -  CS  ->   output default high
6
  // Port B2  -  GD0 ->  input with pullup
7
*/
8
  PORTB = 0x06;
9
  DDRB = 0x06;
10
11
  /* Port C Initialisierung
12
  // Port C1  -  SO  -> output default high
13
  // Port C2  -  SI -> input without pullup
14
  // Port C3  -  SCLK -> output default low
15
*/
16
  PORTC = 0x02;
17
  DDRC = 0x0A;
18
19
  /* Port D Initialisierung
20
  // Port D0  -  powersupply CC1100 -> output default low
21
22
  // Port D7  -  LED -> output default low*/
23
  PORTD = 0x00;
24
  DDRD = 0x81;
25
}
26
27
/************************************************************************
28
void cc_select(unsigned char p):
29
  p = 1 select cc1101
30
  p = 0 deselect cc1101
31
  
32
  selects the cc1101 on active low     
33
  PB1 selection pin                                
34
************************************************************************/
35
void cc_select(unsigned char p){
36
  if(p == 1){
37
    PORTB &= ~(1 << PB1);  
38
  }else{
39
    PORTB |= (1 << PB1);  
40
  }  
41
}
42
43
/************************************************************************
44
void cc_power(unsigned char p)
45
  p = 1 power on
46
  p = 0 power off
47
  
48
  turn on the cc1101 on PD0 high
49
************************************************************************/
50
void cc_power(unsigned char p){
51
  if(p == 1){
52
    PORTD |= (1 << PD0); 
53
  }else{
54
    PORTD &= ~(1 << PD0);
55
  }
56
}

SPI Funktionen:
1
/*************************************************************************
2
void spi_init():
3
  SPI configuration as master                                                                   
4
************************************************************************/
5
void spi_init(){
6
  SPCR = (1 << SPE) | (1 << MSTR) | (1 << SPR0);
7
}
8
9
/************************************************************************
10
char spi(char data):
11
  data = data to or address of spi register of cc1101
12
  
13
  addr will be manipulated that the msb shows that the master is
14
  reading from the bus
15
************************************************************************/
16
char spi(char data){
17
  SPDR = data;
18
  while(!(SPSR & (1 << SPIF)));
19
  return SPDR;
20
}
21
22
/************************************************************************
23
cc_writeRegister(char addr, char data)
24
  addr = register address
25
  data = data written to registers address  
26
************************************************************************/
27
void cc_writeRegister(char addr, char data){  
28
  cc_select(1);
29
  
30
  spi(addr);
31
  spi(data);
32
  
33
  cc_select(0);
34
}
35
36
/************************************************************************
37
cc_readRegister(char addr)
38
  addr = address of register
39
************************************************************************/
40
char cc_readRegister(char addr){
41
  char data = 0xff;
42
  
43
  cc_select(1);
44
  
45
  data = spi((addr |0x80));
46
  
47
  uart_puts("data = ");
48
  uart_putc(data);
49
  uart_putc('\n');
50
  
51
  data = spi(addr | 0x80);
52
  
53
  uart_puts("data = ");
54
  uart_putc(data);
55
  uart_putc('\n');
56
  
57
  cc_select(0);
58
  
59
  return data;
60
}
61
62
/************************************************************************
63
void cc_config():
64
  configures the cc1101 with the necessary settings:
65
************************************************************************/
66
void cc_config(){
67
  uart_puts("write 1\n");
68
  cc_writeRegister(CC1100_FSCTRL1, 0x08);
69
  uart_puts("write 2\n");
70
  cc_writeRegister(CC1100_FSCTRL0, 0x00);
71
  uart_puts("write 3\n");
72
  cc_writeRegister(CC1100_FIFOTHR, 0x04);
73
  uart_puts("write 4\n");
74
  cc_writeRegister(CC1100_FREQ2, 0x21);
75
  uart_puts("write 5\n");
76
  cc_writeRegister(CC1100_FREQ1, 0x76);
77
  uart_puts("write 6\n");
78
  cc_writeRegister(CC1100_FREQ0, 0x27);      
79
}

Main:
1
int main(void)
2
{  
3
  //initialization functions
4
  io_init();
5
  spi_init();
6
  uart_init();  
7
  
8
  cc_power(1);
9
  uart_puts("cc1100 eingeschaltet\n");
10
  cc_config();
11
  uart_puts("cc1100 configuriert\n");
12
  
13
  //program started go into while loop
14
  uart_puts("start\n");
15
  
16
  uart_puts("\nread FREQ2\n");
17
  uart_putc(cc_readRegister(CC1100_FREQ2));
18
  uart_puts("\nread FREQ1\n");
19
  uart_putc(cc_readRegister(CC1100_FREQ1));
20
  uart_puts("\nread FREQ0\n");
21
  uart_putc(cc_readRegister(CC1100_FREQ0));
22
    
23
    while(1){                
24
  }
25
  
26
  return 0;
27
}

von Felix P. (fixxl)


Lesenswert?

1
  /* Port B Initialisierung
2
  // Port B1  -  CS  ->   output default high
3
  // Port B2  -  GD0 ->  input with pullup
4
*/
5
  PORTB = 0x06;
6
  DDRB = 0x06;
B2 wird durch diese Befehle kein Input mit Pullup sondern ein 5V-Output. 
06h = 00000110b.

von cler :) (Gast)


Lesenswert?

Den musste ich so setzen damit die SPI Verbindung nicht mehr in der 
whileschleife hängen bleibt. Habe noch vergessen die Kommentare zu 
pflegen Danke :)

von Karl H. (kbuchegg)


Lesenswert?

Entweder stell ich mich jetzt dumm an, oder irgendwas anderes stimmt 
nicht. Ich kann vom Mega44 kein Datenblatt finden.

Nichts desto trotz

> void io_init(){
>   // I/O-Ports initialisieren
>
>   /* Port B Initialisierung
>   // Port B1  -  CS  ->   output default high
>   // Port B2  -  GD0 ->  input with pullup
> */
>   PORTB = 0x06;
>   DDRB = 0x06;
>
>   /* Port C Initialisierung
>   // Port C1  -  SO  -> output default high
>   // Port C2  -  SI -> input without pullup
>   // Port C3  -  SCLK -> output default low
> */
>   PORTC = 0x02;
>   DDRC = 0x0A;


mir fehlt da immer noch das Setzen des SS Pins auf Ausgang

Warum schreibst du das eigentlich alles mit Hex-Zahlen

So...
1
   /* Port B Initialisierung
2
   // Port B1  -  CS  ->   output default high
3
   // Port B2  -  GD0 ->  input with pullup
4
   */
5
  PORTB = (1 << PB1) | (1 << PB2);
6
  DDRB = (1 << PB1) | (1 << PB2);
7
8
  /* Port C Initialisierung
9
  // Port C1  -  SO  -> output default high
10
  // Port C2  -  SI -> input without pullup
11
  // Port C3  -  SCLK -> output default low
12
  */
13
  PORTC = (1 << C1);
14
  DDRC = (1 << C1) | (1 << C3);
... wäre das alles viel einfacher zu kontrollieren, ob du auch wirklich 
die richtigen Pins auf Output gesetzt hast.

Mit ein paar define davor
1
   /* Port B Initialisierung
2
   // Port B1  -  CS  ->   output default high
3
   // Port B2  -  GD0 ->  input with pullup
4
   */
5
#define CS  PB1
6
#define GD0 PB2
7
8
  PORTB = (1 << CS) | (1 << GD0);
9
  DDRB = (1 << CS) | (1 << GD0);
10
11
  /* Port C Initialisierung
12
  // Port C1  -  SO  -> output default high
13
  // Port C2  -  SI -> input without pullup
14
  // Port C3  -  SCLK -> output default low
15
  */
16
#define SO   PC1
17
#define SI   PC2
18
#define SCLK PC3
19
20
  PORTC = (1 << SO);
21
  DDRC = (1 << SO) | (1 << SCLK);
... wirds dann gleich noch eine Spur leichter zu durchschauen. Vor allen 
Dingen im Code danach, bei dem dann ein ...
1
/************************************************************************
2
void cc_select(unsigned char p):
3
  p = 1 select cc1101
4
  p = 0 deselect cc1101
5
  
6
  selects the cc1101 on active low     
7
************************************************************************/
8
void cc_select(unsigned char p){
9
  if(p == 1){
10
    PORTB &= ~(1 << CS);  
11
  }else{
12
    PORTB |= (1 << CS);  
13
  }  
14
}
... mir schon Codemässig erzählt, dass es hier um den CS (also Chip 
Select) geht. Das der am PB1 hängt muss mich dann eigentlich nicht mehr 
weiter interessieren. OK, das PORTB schränkt mich an dieser Stelle noch 
ein wenig ein, aber gut, könnte man auch noch ändern.


Nichts desto trotz. Ich vermisse den Pin SS der SPI Schnittstelle. Der 
wird nirgends auf Output gesetzt.

von Karl H. (kbuchegg)


Lesenswert?

cler :) schrieb:
> Den musste ich so setzen damit die SPI Verbindung nicht mehr in der
> whileschleife hängen bleibt. Habe noch vergessen die Kommentare zu
> pflegen Danke :)

Was sagt uns das?
Kommentare sind Scheisse. Wenn du eine Möglichkeit hast, einen Kommentar 
dadurch wegzubringen, indem du direkt im Code genau dasselbe aussagen 
kannst, DANN TU DAS UND LASS DEN KOMMENTAR WEG!

von spess53 (Gast)


Lesenswert?

Hi

>Ich kann vom Mega44 kein Datenblatt finden.

Den gibt es auch nicht. Entweder meint er einen ATMega644A oder einen 
ATMega48A.

MfG Spess

von Karl H. (kbuchegg)


Lesenswert?

Karl Heinz Buchegger schrieb:
> Entweder stell ich mich jetzt dumm an, oder irgendwas anderes stimmt
> nicht. Ich kann vom Mega44 kein Datenblatt finden.

? Kann wer näheres dazu beitragen
Es gibt einen Tiny44
und einen Mega48

aber einen Mega44 kann ich nicht finden?

von Karl H. (kbuchegg)


Lesenswert?

spess53 schrieb:
> Hi
>
>>Ich kann vom Mega44 kein Datenblatt finden.
>
> Den gibt es auch nicht. Entweder meint er einen ATMega644A oder einen
> ATMega48A.

Hab ich mir auch schon gedacht.
Aber die Pinbelegung des Hardware-SPI am Port C passt zu keinem von 
beiden.

von cler :) (Gast)


Lesenswert?

Habe mich was den Controller angeht vertippt tut mir Leid.

Ich habe den Fehler gelöst. Der CC1100 auf der Platine scheint defekt zu 
sein zumindest macht es den Eindruck mit der Lupe das würde einiges 
erklären, denke ich.

Gruß cler

von Karl H. (kbuchegg)


Lesenswert?

cler :) schrieb:
> Habe mich was den Controller angeht vertippt tut mir Leid.

Und? Welcher ist es?

von cler :) (Gast)


Lesenswert?

Der Atmega48a

von Spess53 (Gast)


Lesenswert?

Hi

>Der Atmega48a

Der hat aber kein SPI an PortC:

PC3 (ADC3/PCINT11)
PC2 (ADC2/PCINT10)
PC1 (ADC1/PCINT9)

sondern an PortB

PB5 (SCK/PCINT5)
PB4 (MISO/PCINT4)
PB3 (MOSI/OC2A/PCINT3
PB2 (SS/OC1B/PCINT2)

MfG Spess

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.