Forum: Compiler & IDEs Probleme mit AT90CAN64 SPI Übertragung


von Florian (Gast)


Lesenswert?

Hallo!

Für meine Arbeit muss ich einen AT90CAN64 programmieren. Habe leider 
damit keinerlei Erfahrung...

Das Programm soll den MAX1148 ADC auslesen. Da dieser nur 8 Kanäle hat, 
ich aber insgesamt 64 auslesen möchte, werden zudem über Port A 
Multiplexer gesteuert. Ich benutze die von Atmel für diesen MC zur 
Verfügung gestellt CAN software Libraries 
([[http://www.atmel.com/dyn/products/product_card.asp?PN=AT90CAN64]])

Mein Problem ist, dass ich mit dem Scope keinerlei Signale am SPI sehe.
Hier mein Code
1
//_____ I N C L U D E S ________________________________________________________
2
#include <avr/io.h>
3
#include <avr/interrupt.h>
4
#include <avr/iocan64.h>
5
#include "compiler.h"
6
#include "at90can_drv.h"
7
#include "spi_lib.h"
8
#include "can_lib.h"
9
10
//_____ D E F I N I T I O N S __________________________________________________
11
    // -------------- MCU LIB CONFIGURATION
12
#define FOSC           8000                      // 8.000 MHz External cristal
13
#define F_CPU          (FOSC*1000)               // Need for AVR GCC
14
15
    // -------------- CAN LIB CONFIGURATION
16
#define CAN_BAUDRATE   250                       // in kBit
17
18
    // -------------- MISCELLANEOUS
19
#define ADCSTART       0x8e                      // c.f. MAX1146-1149 datasheet
20
#define ADCSSTRB       PINB4
21
#define NUM_CHANNELS   64
22
#define NUM_DATA       (NUM_CHANNELS*2)
23
24
volatile U8 channelSelect[8] = {0,4,1,5,2,6,3,7}; // c.f. MAX1146-1149 datasheet
25
26
U8 init(void)
27
{ 
28
  // --- enable interrupts
29
  Enable_interrupt();                         
30
31
  // --- init SPI; c.f. "spi_lib.c"
32
  U8 spi_config = (SPI_MASTER|SPI_MSB_FIRST|SPI_DATA_MODE_0|SPI_CLKIO_BY_64);
33
  if( spi_init(spi_config) ){
34
    Spi_init_ss();                              
35
    Spi_disable_ss();
36
  }
37
  else return (0);
38
                           
39
  // --- configure port A
40
  DDRA = (1<<DDA2)|(1<<DDA1)|(1<<DDA0);
41
  PORTA = 0x00;
42
43
  return (1);
44
}
45
46
void readAdc(unsigned int channel, U8 *result)
47
{
48
  U8 buffer[3];
49
50
  buffer[0] = ADCSTART | (channelSelect[channel%8] << 4);
51
  buffer[1] = 0; buffer[2] = 0;
52
53
  Spi_enable_ss();
54
55
  // --- Send control byte
56
  spi_transmit_master(buffer[0]);
57
58
  // --- Wait for conversion complete
59
  while(ADCSSTRB == 0);
60
61
  buffer[1] = spi_getchar();
62
  buffer[2] = spi_getchar();
63
64
  Spi_disable_ss();
65
66
  result[2*channel] = buffer[1];
67
  result[2*channel+1] = buffer[2];
68
69
  return;
70
}
71
72
int main(void)
73
{
74
  U8 meanValues[NUM_DATA];
75
  int channel;
76
77
  if(init()==0) return (0);
78
79
  while(1){
80
    for(channel=0; channel<NUM_CHANNELS; channel++){
81
      int value = channel/8;
82
      if((value != PORTA) && (value <= 7))
83
        PORTA = value;
84
      readAdc(channel,meanValues);
85
    } // for channel
86
    
87
  } // while(1)
88
89
}

Hat jemand eine Idee, woran es liegen könnte? Wenn ich die 3 Zeilen, in 
der ich Daten auf dem SPI hin und her schicke, auskommentiere, läuft 
alles so wie es soll...

Gruss
Florian

von holger (Gast)


Lesenswert?

>Mein Problem ist, dass ich mit dem Scope keinerlei Signale am SPI sehe.

Der wichtigste Teil des Programmes fehlt mal wieder :(
Nutzt du auch den SS Pin für das Slaveselect?

von Florian (Gast)


Lesenswert?

Lies dir doch meinen Code durch!
Da kommen Kommandos vor die heißen
1
    Spi_init_ss();                              
2
    Spi_disable_ss();
3
Spi_enable_ss();

Auch ohne die "CAN Software Libraries" zu kennen, könnte man doch 
annehmen, dass das es sich um den SlaveSelect handelt, oder etwa nicht?!
(Sorry wenns ned eindeutig war)

von codesuchender (Gast)


Lesenswert?

wo ist deine spi_lib.c ? Wo sind deine SPI-Makros definiert? Gibts nen 
Schaltplan? Glaskugel ist leider kaputt sorry ;-)

von holger (Gast)


Lesenswert?

>Lies dir doch meinen Code durch!

Habe ich getan.

>Da kommen Kommandos vor die heißen
>
>    Spi_init_ss();
>    Spi_disable_ss();
>Spi_enable_ss();

Benutzt du nun den SS Pin vom ATMega64 oder nicht?
Das kann ich dort nicht sehen.

>Auch ohne die "CAN Software Libraries" zu kennen, könnte man doch
>annehmen, dass das es sich um den SlaveSelect handelt, oder etwa nicht?!

Annehmen heisst nicht wissen.

von Florian (Gast)


Angehängte Dateien:

Lesenswert?

Sorry für meine Faulheit. Die spi_lib.c ist in den atmel libraries. der 
link ist oben...

von holger (Gast)


Lesenswert?

>Benutzt du nun den SS Pin vom ATMega64 oder nicht?

Sorry, vom AT90CAN..

von Florian (Gast)


Angehängte Dateien:

Lesenswert?

>Benutzt du nun den SS Pin vom ATMega64 oder nicht?
>Das kann ich dort nicht sehen.

es ist der at90can64, nicht der atmega....aber die o.g. Macros verwenden 
den SlaveSelect Pin...

So. Nun hab ich auch mal die Files aus den Atmel Libs mit angehangen

von Florian (Gast)


Angehängte Dateien:

Lesenswert?

Auf die Frage nach dem Schaltplan, ist angehängt.
(Das Value des Crystals ist allerdings falsch. Der hat 8 und nicht 16 
MHz)
Mal ne Frage, kann man auch mehr als eine Datei an nen Post anhängen, 
oder muss man die dazu in nen Archiv parken?!

von holger (Gast)


Lesenswert?

Ich seh nix, außer das

Bool spi_init (U8 config)

so aussehen müsste wegen der Clock Macros

Bool spi_init (U16 config)

von Florian (Gast)


Lesenswert?

>Ich seh nix, außer das
>
>Bool spi_init (U8 config)
>
>so aussehen müsste wegen der Clock Macros
>
>Bool spi_init (U16 config)

Ne! Wenn man mal durchzählt:
SPI_MASTER      1 Bit
SPI_MSB_FIRST   1 Bit
SPI_DATA_MODE_0 2 Bit
SPI_CLKIO_BY_64 3 Bit
SPI_enable      1 Bit
Macht insgesamt 8 Bit...
demnach ist U8 richtig

von Florian (Gast)


Lesenswert?

Ups! Hab mich vertan! spi_enable gehört ja gar ned zur variable 
config...
Aber dann passt U8 immernoch

von holger (Gast)


Lesenswert?

>Aber dann passt U8 immernoch
1
    // ---------- Pre-definitions for relationship between SCK and CLKIO (16-bit)
2
    // ---------- (The 9th is the Double SPI Speed Bit: SPI2X of SPSR)
3
#define SPI_CLKIO_BY_2            ((1<<(SPI2X+8))|(0<<SPR1)|(0<<SPR0)) // -- 0x100

Und was sagt dir das?
Aber hast recht, bei seiner Clockeinstellung reicht U8.

von Florian (Gast)


Lesenswert?

>>Aber dann passt U8 immernoch
1
    // ---------- Pre-definitions for relationship between SCK and CLKIO (16-bit)
2
    // ---------- (The 9th is the Double SPI Speed Bit: SPI2X of SPSR)
3
#define SPI_CLKIO_BY_2            ((1<<(SPI2X+8))|(0<<SPR1)|(0<<SPR0)) // -- 0x100
>Und was sagt dir das?
>Aber hast recht, bei seiner Clockeinstellung reicht U8.

Mkay! Vom MC und seinen Registern her sind es 16 Bit. Das stimmt.

Aber ich denke mal, dass Atmel das schon richtig macht, da die diese 
Libs selber zum Programmieren verwenden...

von holger (Gast)


Lesenswert?

>Aber ich denke mal, dass Atmel das schon richtig macht, da die diese
>Libs selber zum Programmieren verwenden...

Dann hat von denen aber noch niemand versucht
SPI_CLKIO_BY_2 einzustellen ;)

Hier ist auch noch ein Tippfehler (macht aber nix)
1
#define Spi_enable_ss()           (PORTB &= ~(1<<DDB0))  // -- Can be user re-defined

Und da sind die Kommentare falsch
1
#define SPI_CLKIO_BY_64           ((0<<(SPI2X+8))|(1<<SPR1)|(0<<SPR0)) // -- 0x102
2
#define SPI_CLKIO_BY_128          ((0<<(SPI2X+8))|(1<<SPR1)|(1<<SPR0)) // -- 0x103

von Florian (Gast)


Lesenswert?

>Hier ist auch noch ein Tippfehler (macht aber nix)
1
#define Spi_enable_ss()           (PORTB &= ~(1<<DDB0))  // -- Can be user re-defined
Was denn?! Habe diese Variante beim Googlen schon des öfteren gesehen, 
nicht nur von Atmel...

von holger (Gast)


Lesenswert?

>Was denn?! Habe diese Variante beim Googlen schon des öfteren gesehen,
>nicht nur von Atmel...

Ist ja auch nur ein Schönheitsfehler ;)

Hier ist das Problem
1
  buffer[1] = spi_getchar();
2
  buffer[2] = spi_getchar();

Vor jedem spi_getchar(); muß ein Dummybyte gesendet werden.
spi_getchar(); macht das nicht.

von Florian (Gast)


Lesenswert?

>Hier ist das Problem

>  buffer[1] = spi_getchar();
>  buffer[2] = spi_getchar();

>Vor jedem spi_getchar(); muß ein Dummybyte gesendet werden.
>spi_getchar(); macht das nicht.

Ok! Hab ich eingebaut!
Und auch den Fehler mit dem U16 bei der Funktion spi_init hab ich 
behoben!
(Hab das nochmal nachgeguckt, und du hattest recht mit dem 16 bit...)

Allerdings funktioniert es immernoch ned...So wie es aussieht (habe zum 
debuggen nach jedem Schritt den Wert von Port c erhöht) kommt er nicht 
mal über das
1
  // --- Send control byte
2
  spi_transmit_master(buffer[0]);
von oben hinaus...

Jemand ne Idee wo der Fehler liegen könnte?!

Gruss
Florian

von holger (Gast)


Lesenswert?

1
void  spi_transmit_master(U8 ch)
2
{
3
    //-- Wait for transmission complete
4
    Spi_wait_eot();
5
//An dieser Stelle wird es vermutlich klemmen
6
//Einfach mal auskommentieren zum probieren
7
    
8
    //-- Start new transmission
9
    Spi_send_byte(ch);
10
}

von Florian (Gast)


Lesenswert?

Danke Holger!!!
Es funktioniert!!

von Martin J. (bluematrix) Benutzerseite


Lesenswert?

Hallo euch allen,

ich bin schon seit einiger Zeit auf der Suche nach einem CAN-Bootlader
für den AT90CAN. Leider konnte ich dazu aber kein fertiges Projekt
finden.
Genauere Informationen gibt es unter fogendem Link:

Titel - Beitrag "CAN BUS Bootloader AT90CAN"

Ich hoffe es finden sich einige um dieses Projekt zu realisieren oder
die dabei helfen können.

Grüße martin

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.