PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : CAN - Controller Area Network



Kaiser-F
03.08.2005, 11:31
Hallo Ihr! O:)

Wie man dem Titel schon antnehmen kann, geht es um den CAN-BUS.

Ich möchte gerne mehrere Controller über den CAN-BUS verbinden.
Zur Übermittlung von Temperaturen, Drehzahlen, Stellungswerten usw.

Ich habe den CAN-BUS gewählt, weil:
- er sicher ist
- das Protokoll Identifier "besitzt", welche die gesendeten daten "identifizieren"
- es ein bewährter Industriestandard ist.
- er flexibel ist
usw.

Um dies zu realisieren habe ich mir kleine CAN-Module gebaut:

https://www.roboternetz.de/phpBB2/files/img_1370.jpg

Der Versuchsaufbau ist einfach:

ATMEGA8535 ----- CAN-Modul ====CAN BUS ==== CAN-Modul ----- ATMEGA8535

Ich hatte zuerst vorgehabt Kjion's Version einfach nachzubauen.
https://www.roboternetz.de/phpBB2/viewtopic.php?t=8325&postdays=0&postorder=asc&start=0

Aber dann würde ich die Sache wohl nie verstehen, und auch andere lassen die Finer davon, weil es zu aufwendig erscheint.

Ich denke dass es nicht verkehrt ist, das Thema CAN mal von 0auf aufzuziehen, da es in den meisten Foren nie so richtig besprochen wird ( nur unter den Profis, für die das ein Klacks ist :-), respekt an Kjion! ), und weil CAN eigentlich ne coole Sache ist! :Ostern


Es wäre echt super, wenn sich dieses Thema in eine Schritt-für-Schritt - Anleitung für CAN über den MCP2515 entwickeln würde.


===============================================

Ich denke der erste Schritt ist zunächst einmal eine Headerdatei zu erstellen, welche alle Register des MCP2515 beschreibt.

Das war ursprünglich Kjion's Code!

==== Code wurde Aktualisiert, Siehe weiter unten ====

Bitte verbessert mich!
Was Fehlt,
Was braucht man nicht,
Was könnte man verbessern

Ich bedanke mich!

Kaiser-F
03.08.2005, 14:28
So, nun gut,

So wie ich das verstanden habe, muss man nun folgendes tun.

Den MCP2515 Initialisieren...

Um Daten zu senden:
In einem Transmit-Buffer den Identifier und die Daten schreiben,
und dann den Sendebefehl senden....

Um Daten zu empfangen.
Wenn eingestellt, dann löst der MCP2515 einen interrupt aus ( über den INT pin ) wenn daten empfangen wurden.
Diese kann man dann aus den Reciever-Buffer auslesen.

Eigentlich einfach....
Jetzt fehlt mir nur noch der Code!

fortsetzung folgt.!

Stromi
07.08.2005, 23:41
Ich habe interessiert mitgelesen, da ich auch mit CAN anfangen will. Ist der Code so in Ordnung? Hast du was getestet?

Kaiser-F
13.08.2005, 15:07
dauert noch ne weile, bin noch im urlaub... Fortsetzung folgt ;-)

Kaiser-F
24.08.2005, 14:22
Hallo,

Wollte nur mal eben melden dass ich daran weiterarbeite!

Leider habe ich schwierigkeiten das BIT-TIMING zu verstehen, evtl kann jemand Hilfestellung geben.

Danke!

Kaiser-F
25.08.2005, 08:43
So, Nun mal wieder Zwischenergebnisse.

Hier ist die neue mcp2515.h
und auch schon die mcp2515.c



/************************************************** ****************************/
/********************** M C P 2 5 1 5 C O N T R O L ***********************/
/******************************* Kaiser Franz *********************************/
/************************************************** ****************************/


//|======================== MCP2515 Includes & Defines ========================|
#include "mcp2515.h"

//+================================================= ===========================+
//|=========================== Funktionen Übersicht ===========================|
//================================================== ==========================+
void mcp2515_init(void); // MCP2515 Initialisation
void spi_init(void); // SPI Initialisation
uint8_t spi_putc( uint8_t data ); // SPI Transmission
uint8_t mcp2515_read_register(uint8_t adress); // Ein Register lesen
void mcp2515_write_register( uint8_t adress, uint8_t data ); // In ein Register schreiben
void mcp2515_bit_modify(uint8_t adress, uint8_t mask, uint8_t data); // In einem Register ein Bit schreiben


//+================================================= ===========================+
//|=========================== F U N K T I O N E N ============================|
//+================================================= ===========================+


//|========================== MCP2515 Initialisation ==========================|
void mcp2515_init(void)
{
//|------------------ SPI Interface initialisieren ------------------|
spi_init();


//|------------- MCP2515 per Software Reset zurücksetzten -----------|
PORTB &= ~(1<<SPI_CS);
spi_putc( SPI_RESET );
PORTB |= (1<<SPI_CS);


//|---------- Device in den Konfigurations Modus versetzten ---------|
//|-------------------- CLKOUT Pin deaktivieren ---------------------|
mcp2515_bit_modify( CANCTRL, 0xE0, (1<<REQOP2) );


//|------------------- Einstellen des Bit Timings -------------------|

// +------------------- Hilfe für das Bit Timing -----------------+
// | Fosc = 16MHz |
// | BRP = 7 ( teilen durch 8 ) |
// | TQ = 2 * (BRP + 1) / Fosc ( => 1 ns ) |
// | |
// | Sync Seg = 1 TQ |
// | Prop Seg = ( PRSEG + 1 ) * TQ = 1 TQ |
// | Phase Seg1 = ( PHSEG1 + 1 ) * TQ = 3 TQ |
// | Phase Seg2 = ( PHSEG2 + 1 ) * TQ = 3 TQ |
// | |
// | Bus speed = 1 / (Total # of TQ) * TQ |
// | = 1 / 8 * TQ = 125 kHz |
// +--------------------------------------------------------------+

// BRP = 7
mcp2515_write_register( CNF1, (1<<BRP0)|(1<<BRP1)|(1<<BRP2) );

// Prop Seg und Phase Seg1 einstellen
mcp2515_write_register( CNF2, (1<<BTLMODE)|(1<<PHSEG11) );

// Phase Seg2 einstelen
mcp2515_write_register( CNF3, (1<<PHSEG21) );


//|-------------- Einstellen der Rx Buffer Interrupts ---------------|
//mcp2515_write_register( CANINTE, (1<<RX1IE)|(1<<RX0IE) );


//|--------------------- Buffer Operating Mode ----------------------|
// Buffer 0 : Empfangen aller Nachrichten, Infos Datasheet S.27
mcp2515_write_register( RXB0CTRL, (1<<RXM1)|(1<<RXM0) );

// Buffer 1 : Empfangen aller Nachrichten, Infos Datasheet S.28
mcp2515_write_register( RXB1CTRL, (1<<RXM1)|(1<<RXM0) );


//|--------- Device zurück in den normalen Modus versetzten ---------|
mcp2515_bit_modify( CANCTRL, 0xE0, 0);


}



//|============================ SPI Initialisation ============================|
void spi_init(void)
{
//|----------- Aktivieren der Pins für das SPI Interface ------------|
DDRB |= (1<<SPI_CS)|(1<<SPI_SCK)|(1<<SPI_MOSI);
PORTB |= (1<<SPI_CS);
PORTB &= ~(1<<SPI_SCK)|(1<<SPI_MOSI)|(1<<SPI_MISO);

//|--- Aktivieren des SPI Master Interfaces, fosc = fclk / 4 --------|
SPCR = (1<<SPE)|(1<<MSTR)/*|(1<<SPIE)*/;
//SPSR = (1<<SPI2X);
}



//|============================= SPI Transmission =============================|
uint8_t spi_putc( uint8_t data )
{
// Sende ein Byte
SPDR = data;

// Warten bis Byte gesendet wurde
while( !( SPSR & (1<<SPIF) ) );

return SPDR;
}



//|============================ Ein Register lesen ============================|
uint8_t mcp2515_read_register(uint8_t adress)
{
uint8_t data;

PORTB &= ~(1<<SPI_CS); // CS low

spi_putc(SPI_READ);

spi_putc(adress);

data = spi_putc(0xff);

PORTB |= (1<<SPI_CS); // CS high

return data;
}



//|========================= In ein Register schreiben ========================|
void mcp2515_write_register( uint8_t adress, uint8_t data )
{
PORTB &= ~(1<<SPI_CS); // CS low

spi_putc(SPI_WRITE);

spi_putc(adress);

spi_putc(data);

PORTB |= (1<<SPI_CS); // CS high
}



//|======= Mehrere hintereinanderliegende Register auf einmal schreiben =======|
//Note: Das ist nur bei bestimmten stellen zu empfehlen,
// zB dem Transmit-Daten-Puffer
//Infos Datasheet S.63
void mcp2515_write_register_f( uint8_t adress, uint8_t data, uint8_t length)
{
uint8_t i;

PORTB &= ~(1<<SPI_CS); // CS low

spi_putc(SPI_WRITE);

spi_putc(adress);

for (i=0; i<length ;i++ )
spi_putc(*data++);

PORTB |= (1<<SPI_CS); // CS high
}



//|================ In einem Register einzelne Bits schreiben =================|
// Note: Bit-Modify funktionjiert nicht bei allen Registern!
// Nur die Bits, die mit der Maske "selektiert" wurden, können geändert werden,
// Infos Datasheet S.64
void mcp2515_bit_modify(uint8_t adress, uint8_t mask, uint8_t data)
{
PORTB &= ~(1<<SPI_CS); // CS low

spi_putc(SPI_BIT_MODIFY);

spi_putc(adress);

spi_putc(mask);

spi_putc(data);

PORTB |= (1<<SPI_CS); // CS high
}





/************************************************** ****************************/
/********************** M C P 2 5 1 5 D E F I N E S ***********************/
/******************************* Kaiser Franz *********************************/
/************************************************** ****************************/


//|================================= SPI-Pins =================================|
// ( Eingestellt für ATmega8535 ):
#define SPI_CS 4
#define SPI_MOSI 5
#define SPI_MISO 6
#define SPI_SCK 7

//|============================== SPI Kommandos ===============================|
#define SPI_RESET 0xC0
#define SPI_READ 0x03
#define SPI_READ_RX 0x90
#define SPI_WRITE 0x02
#define SPI_WRITE_TX 0x40
#define SPI_RTS 0x80
#define SPI_READ_STATUS 0xA0
#define SPI_RX_STATUS 0xB0
#define SPI_BIT_MODIFY 0x05

//|========================== Alle Register-Adressen ==========================|
// Nicht aufgelistet: CANSTAT ( 0x1E, 0x2E, 0x3E, 0x4E, 0x5E, 0x6E, 0x7E)
// CANCTRL ( 0x1F, 0x2F, 0x3F, 0x4F, 0x5F, 0x6F, 0x7F)
// Siehe MCP2515 Datenblatt S.61

#define RXF0SIDH 0x00
#define RXF0SIDL 0x01
#define RXF0EID8 0x02
#define RXF0EID0 0x03
#define RXF1SIDH 0x04
#define RXF1SIDL 0x05
#define RXF1EID8 0x06
#define RXF1EID0 0x07
#define RXF2SIDH 0x08
#define RXF2SIDL 0x09
#define RXF2EID8 0x0A
#define RXF2EID0 0x0B
#define BFPCTRL 0x0C
#define TXRTSCTRL 0x0D
#define CANSTAT 0x0E
#define CANCTRL 0x0F

#define RXF3SIDH 0x10
#define RXF3SIDL 0x11
#define RXF3EID8 0x12
#define RXF3EID0 0x13
#define RXF4SIDH 0x14
#define RXF4SIDL 0x15
#define RXF4EID8 0x16
#define RXF4EID0 0x17
#define RXF5SIDH 0x18
#define RXF5SIDL 0x19
#define RXF5EID8 0x1A
#define RXF5EID0 0x1B
#define TEC 0x1C
#define REC 0x1D

#define RXM0SIDH 0x20
#define RXM0SIDL 0x21
#define RXM0EID8 0x22
#define RXM0EID0 0x23
#define RXM1SIDH 0x24
#define RXM1SIDL 0x25
#define RXM1EID8 0x26
#define RXM1EID0 0x27
#define CNF3 0x28
#define CNF2 0x29
#define CNF1 0x2A
#define CANINTE 0x2B
#define CANINTF 0x2C
#define EFLG 0x2D

#define TXB0CTRL 0x30
#define TXB0SIDH 0x31
#define TXB0SIDL 0x32
#define TXB0EID8 0x33
#define TXB0EID0 0x34
#define TXB0DLC 0x35
#define TXB0D0 0x36
#define TXB0D1 0x37
#define TXB0D2 0x38
#define TXB0D3 0x39
#define TXB0D4 0x3A
#define TXB0D5 0x3B
#define TXB0D6 0x3C
#define TXB0D7 0x3D

#define TXB1CTRL 0x40
#define TXB1SIDH 0x41
#define TXB1SIDL 0x42
#define TXB1EID8 0x43
#define TXB1EID0 0x44
#define TXB1DLC 0x45
#define TXB1D0 0x46
#define TXB1D1 0x47
#define TXB1D2 0x48
#define TXB1D3 0x49
#define TXB1D4 0x4A
#define TXB1D5 0x4B
#define TXB1D6 0x4C
#define TXB1D7 0x4D

#define TXB2CTRL 0x50
#define TXB2SIDH 0x51
#define TXB2SIDL 0x52
#define TXB2EID8 0x53
#define TXB2EID0 0x54
#define TXB2DLC 0x55
#define TXB2D0 0x56
#define TXB2D1 0x57
#define TXB2D2 0x58
#define TXB2D3 0x59
#define TXB2D4 0x5A
#define TXB2D5 0x5B
#define TXB2D6 0x5C
#define TXB2D7 0x5D

#define RXB0CTRL 0x60
#define RXB0SIDH 0x61
#define RXB0SIDL 0x62
#define RXB0EID8 0x63
#define RXB0EID0 0x64
#define RXB0DLC 0x65
#define RXB0D0 0x66
#define RXB0D1 0x67
#define RXB0D2 0x68
#define RXB0D3 0x69
#define RXB0D4 0x6A
#define RXB0D5 0x6B
#define RXB0D6 0x6C
#define RXB0D7 0x6D

#define RXB1CTRL 0x70
#define RXB1SIDH 0x71
#define RXB1SIDL 0x72
#define RXB1EID8 0x73
#define RXB1EID0 0x74
#define RXB1DLC 0x75
#define RXB1D0 0x76
#define RXB1D1 0x77
#define RXB1D2 0x78
#define RXB1D3 0x79
#define RXB1D4 0x7A
#define RXB1D5 0x7B
#define RXB1D6 0x7C
#define RXB1D7 0x7D

//|============================= Bitdefinitionen ==============================|
// Bitdefinition der verschiedenen Register

//|------------------- Bitdefinition von BFPCTRL --------------------|
#define B1BFS 5
#define B0BFS 4
#define B1BFE 3
#define B0BFE 2
#define B1BFM 1
#define B0BFM 0

//|------------------- Bitdefinition von TXRTSCTRL ------------------|
#define B2RTS 5
#define B1RTS 4
#define B0RTS 3
#define B2RTSM 2
#define B1RTSM 1
#define B0RTSM 0

//|------------------- Bitdefinition von CANSTAT --------------------|
#define OPMOD2 7
#define OPMOD1 6
#define OPMOD0 5
#define ICOD2 3
#define ICOD1 2
#define ICOD0 1

//|------------------- Bitdefinition von CANCTRL --------------------|
#define REQOP2 7
#define REQOP1 6
#define REQOP0 5
#define ABAT 4
#define CLKEN 2
#define CLKPRE1 1
#define CLKPRE0 0

//|------------------- Bitdefinition von CNF3 -----------------------|
#define WAKFIL 6
#define PHSEG22 2
#define PHSEG21 1
#define PHSEG20 0

//|------------------- Bitdefinition von CNF2 -----------------------|
#define BTLMODE 7
#define SAM 6
#define PHSEG12 5
#define PHSEG11 4
#define PHSEG10 3
#define PHSEG2 2
#define PHSEG1 1
#define PHSEG0 0

//|------------------- Bitdefinition von CNF1 -----------------------|
#define SJW1 7
#define SJW0 6
#define BRP5 5
#define BRP4 4
#define BRP3 3
#define BRP2 2
#define BRP1 1
#define BRP0 0

//|------------------- Bitdefinition von CANINTE --------------------|
#define MERRE 7
#define WAKIE 6
#define ERRIE 5
#define TX2IE 4
#define TX1IE 3
#define TX0IE 2
#define RX1IE 1
#define RX0IE 0

//|------------------- Bitdefinition von CANINTF --------------------|
#define MERRF 7
#define WAKIF 6
#define ERRIF 5
#define TX2IF 4
#define TX1IF 3
#define TX0IF 2
#define RX1IF 1
#define RX0IF 0

//|------------------- Bitdefinition von EFLG -----------------------|
#define RX1OVR 7
#define RX0OVR 6
#define TXB0 5
#define TXEP 4
#define RXEP 3
#define TXWAR 2
#define RXWAR 1
#define EWARN 0


//|------------------- Bitdefinition von TXBnCTRL -------------------|
// ( n = 0, 1, 2 )
#define ABTF 6
#define MLOA 5
#define TXERR 4
#define TXREQ 3
#define TXP1 1
#define TXP0 0

//|------------------- Bitdefinition von RXB0CTRL -------------------|
#define RXM1 6
#define RXM0 5
#define RXRTR 3
#define BUKT 2
#define BUKT1 1
#define FILHIT0 0

//|------------------- Bitdefinition von TXBnSIDL -------------------|
// ( n = 0, 1 )
#define EXIDE 3

//|------------------- Bitdefinition von RXB1CTRL -------------------|
//RXM1, RXM0, RXRTR und FILHIT0 sind schon für RXB0CTRL definiert
#define FILHIT2 2
#define FILHIT1 1

//|------------------- Bitdefinition von RXBnSIDL -------------------|
// ( n = 0, 1 )
#define SRR 4
#define IDE 3

//|------------------- Bitdefinition von RXBnDLC BZW. TXBnDLC -------|
// ( n = 0, 1 ) BZW. ( n = 0, 1, 2 )
#define RTR 6
#define DLC3 3
#define DLC2 2
#define DLC1 1
#define DLC0 0



Damit kann man schon was anfangen.
Arbeite heute daran mal endlich was zu versenden :-)

Bitte beachtet, dass ich die Alten Codes immer rauslösche wenn ich neue Poste, welche dieselbe Datei betreffen

Kaiser-F
25.08.2005, 12:12
Hallo,

Was haltet Ihr von dieser Transmit-Funktion?
Mit Autosuche nach einem freien Transmit-Puffer,
Priorität einstellbar,
Remotetransmit einschaltbar,
11Bit Standart Identifyer,
16Bit Extended identifyer, ( wer hier die 18 Bit haben will, muss sich halt das nötige daruproggen, aber ich denke kaum dass von uns jemand überhaupt einen Extended identifyer braucht ;-) )
8-DatenBytes

Bitte Verbessert mich!



// CAN-Sendefunktion: Priorität| Remote| SID| EID| Daten| Datenlänge|
// 0-3| 0-1| 11 Bits| 16 Bits| 1-8Stück| =Anz. Daten|
void mcp2515_can_transmit(uint8_t prioritiy, uint8_t rtr, uint16_t sid, uint16_t eid, uint8_t data, uint8_t length)
{

//|========================= Freien Sendepuffer suchen ========================|
uint8_t buffer[4];

buffer[0] = mcp2515_read_register(0x30);
buffer[1] = mcp2515_read_register(0x40);
buffer[2] = mcp2515_read_register(0x50);

if ( buffer[2] !& (1<<TXREQ) ){ buffer[3] = 0x50; }
if ( buffer[1] !& (1<<TXREQ) ){ buffer[3] = 0x40; }
if ( buffer[0] !& (1<<TXREQ) ){ buffer[3] = 0x30; }


//|============================= Bytes vorbereiten ============================|
uint8_t x[6];

// Byte für TXBnCTRL vorbereiten, Datasheet S.18, TRANSMIT BUFFER n CONTROL REGISTER
if(priority > 3){ priority = 3; }
x[0] = ( priority );

// Byte für TXBnSIDH vorbereiten, Datasheet S.19, TRANSMIT BUFFER n STANDARD IDENTIFIER HIGH
x[1] = ( sid >> 3 );

// Byte für TXBnSIDL vorbereiten, Datasheet S.20, TRANSMIT BUFFER n STANDARD IDENTIFIER LOW
if(eid){ x[2] = ( 5 << sid ) + 0b00001000; }
else{ x[2] = ( 5 << sid ); }

// Byte für TXBnEID8 vorbereiten, Datasheet S.20, TRANSMIT BUFFER n EXTENDED IDENTIFIER HIGH
x[3] = ( eid >> 8 );

// Byte für TXBnEID0 vorbereiten, Datasheet S.20, TRANSMIT BUFFER n EXTENDED IDENTIFIER LOW
x[4] = ( eid );

// Byte für TXBnDLC vorbereiten, Datasheet S.21, TRANSMIT BUFFER n DATA LENGTH CODE
if(length > 8){ length = 8; }
if(RTR){ x[5] = length + 0b01000000; }
else{ x[5] = length; }


//|============================= Bytes übertragen =============================|

PORTB &= ~(1<<SPI_CS); // CS low

spi_putc(SPI_WRITE); // Write condition

spi_putc(buffer[3]); // TXBnCTRL von Puffer n adressieren

spi_putc(x[0]); // in TXBnCTRL schreiben, Datasheet S.18, TRANSMIT BUFFER n CONTROL REGISTER

spi_putc(x[1]); // in TXBnSIDH schreiben, Datasheet S.19, TRANSMIT BUFFER n STANDARD IDENTIFIER HIGH

spi_putc(x[2]); // in TXBnSIDL schreiben, Datasheet S.20, TRANSMIT BUFFER n STANDARD IDENTIFIER LOW

spi_putc(x[3]); // in TXBnEID8 schreiben, Datasheet S.20, TRANSMIT BUFFER n EXTENDED IDENTIFIER HIGH

spi_putc(x[4]); // in TXBnEID0 schreiben, Datasheet S.20, TRANSMIT BUFFER n EXTENDED IDENTIFIER LOW

spi_putc(x[5]); // in TXBnDLC schreiben, Datasheet S.21, TRANSMIT BUFFER n DATA LENGTH CODE

while(length > 1){ // in TXBnDm schreiben, Datasheet S.21, TRANSMIT BUFFER n DATA BYTE m
spi_putc(*data++);
length--;
}

PORTB |= (1<<SPI_CS); // CS high


//|=========================== Übertragung Starten ============================|

// TXREQ setzen, um Transmission zu starten
mcp2515_bit_modify(buffer[3], TXREQ, TXREQ);

}

Stromi
28.08.2005, 17:59
Für das Bittiming:

http://ww1.microchip.com/downloads/en/AppNotes/00754.pdf

Kaiser-F
05.09.2005, 06:31
Hallo CANer,

Kjion hat sich entschieden ein Tutorial über den MCP2515 zu schreiben.

Ich bin mir sicher dass hier bald der Link auftauchen wird, sobald er fertig ist.

Soll aber kein Grund sein, hier nicht weiter über dieses Thema zu plaudern.

Ich bedanke mich bei Kjion, dass er diese Aufgabe in die Hand genommen hat.

Kjion
18.09.2005, 14:47
Ich bin mir sicher dass hier bald der Link auftauchen wird, sobald er fertig ist.

... und hier ist auch der versprochene Link :-)
http://www.kreatives-chaos.com/index.php?seite=mcp2515

MfG Kjion

Kaiser-F
20.12.2005, 00:49
Ich hätte an dieser Stelle noch eine Frage.

Sind die Leitungen vom CAN-BUS eigendlich Kurzschlusssicher?

Also dass das Senden nicht mehr möglichist ist klar, aber ist der Transciever dann auch hinüber?

Konnte im DBL nichts finden bezüglich CANL und CANH.

askazo
20.12.2005, 05:28
Die Leitungen sind Kurzschlusssicher, sowohl gegeneinander als auch gegen +12V und GND (ist zumindest mit PCA82C250 ausprobiert).
Wenn man fehlertolerante Transceiver wie z.B. den TJA1053 nimmt, funktioniert der Bus bei einem Kurzschluss sogar noch.

askazo

Kaiser-F
20.12.2005, 12:37
Das ist ja nicht schlecht, ehrlich wahr!

Danke für den Tipp!

askazo
20.12.2005, 14:31
Aber Vorsicht: Der TJA1053 ist ein Low-Speed-Transceiver, der geht also nur bis max. 125kb/s

askazo

Kaiser-F
04.01.2006, 08:49
Hallo,

Ich hab mich ja ziemlich mit dem CAN-BUS nun beschäftigt und hab wieder ein Codeschnipsel für euch.

Mit diesem gelingt es ganz schnell einen freien TX-Buffer automatisch suchen zu lassen.

Lasst euch aber von "sender" und "befehl" nicht verwirren. Aus diesen beiden setzt sich in meinen CAN-Systemen der Identifyer zusammen...




uint8_t MCP2515_status( void ){
uint8_t status;
SPI_cs_low();
SPI_master_transmit( 0b10100000 ); // Read Status ( S.64 bzw. S.67 )
status = SPI_master_transmit( 0xFF );
SPI_cs_high();
return status;
}


void CAN_transmit( uint8_t sender, uint8_t befehl, uint8_t rtr, uint8_t dlc, uint8_t *data ){

uint8_t status = MCP2515_status();
uint8_t buffer;

if( !(status & (1<<6)) ){ buffer = 0b01000100; } // TXB2CTRL.TXREQ
if( !(status & (1<<4)) ){ buffer = 0b01000010; } // TXB1CTRL.TXREQ
if( !(status & (1<<2)) ){ buffer = 0b01000000; } // TXB0CTRL.TXREQ

uint8_t i = 0;

SPI_cs_low();
SPI_master_transmit( buffer );
SPI_master_transmit( (sender<<3) + (befehl>>3) );
SPI_master_transmit( (befehl<<5) );
SPI_master_transmit( 0x00 );
SPI_master_transmit( 0x00 );
SPI_master_transmit( (rtr<<6) + (dlc) );

while( i<dlc ){
SPI_master_transmit( data[i] );
i++;
}

SPI_cs_high();

switch (buffer){
case 0b01000000: MCP2515_bit_modify( TXB0CTRL, (1<<TXREQ), 0xFF ); break;
case 0b01000010: MCP2515_bit_modify( TXB1CTRL, (1<<TXREQ), 0xFF ); break;
case 0b01000100: MCP2515_bit_modify( TXB2CTRL, (1<<TXREQ), 0xFF ); break;
}

}

Kaiser-F
06.04.2006, 19:33
!Wichtiger Bericht!

Falls Ihr vorhaben solltet, wie ich, beispielsweise alle 0,5 Sekunden eine Nachricht über den CAN-BUS zu versenden, und das per Timer-Interrupt steuern wollt, müsst ihr folgendes beachten...

Ihr dürft die Nachricht nicht direkt im Interrupt versenden!!!

Man sollte statt dessen im Interrupt eine Variable setzen, und diese dann in der normalen Operation abfragen, mit if() oder so...

WEIL:

Sollte der Zufall eintreten, dass genau dann der Interrupt ausgeführt wird, wenn der ATMEL gerade seine Daten an den CAN-Controller schickt, so wird diese Aktion unterbrochen, und die neue Information wird gesendet. Das führt unter umständen dazu, dass das Programm ( aber nicht die Interruptroitinen ) da hängen bleibt, wo er auf beendung der SPI-Transmission wartet.

Sollte man beachten! Ich hab stundenlang gesucht! ](*,)

LC-HC
18.04.2006, 15:28
HI, ich hab ein problem mit den SPI Funktionen, wieso leist man den Bus, indem man 0xff schreibt ?

hier der entsprechende Codeabschnitt:


//|============================= SPI Transmission =============================|
uint8_t spi_putc( uint8_t data )
{
// Sende ein Byte
SPDR = data;

// Warten bis Byte gesendet wurde
while( !( SPSR & (1<<SPIF) ) );

return SPDR;
}



//|============================ Ein Register lesen ============================|
uint8_t mcp2515_read_register(uint8_t adress)
{
uint8_t data;

PORTB &= ~(1<<SPI_CS); // CS low

spi_putc(SPI_READ);

spi_putc(adress);

data = spi_putc(0xff);

PORTB |= (1<<SPI_CS); // CS high

return data;
}

SprinterSB
18.04.2006, 16:33
Die Adresse muss ja erst übertragen werden. Nachdem die Adresse übertragen ist, wird das gelesene Byte (data) zum Master rotiert. Dafür wird noch eine Transmission gebraucht.

Kaiser-F
18.04.2006, 17:51
Skizze aus dem Datenblatt jedes ATMegas:

http://www.sir-kaiser.de/upload/SPI-READ.JPG

Das sind zwei schieberegister. Wenn du als Master die Daten haben willst, die der Slave gerade im Datenregister hat, musst du auf der MOSI leitung 8 Bits reinstopfen, dass auf der anderen Seite des Registers im Slave die Bits über die MISO Leitung herausfallen und zum Master gelangen....


Ob es zwingend notwendig ist 0xFF zu senden weiß ich jetzt auch nicht. It aber so gesehen das sinnvollste... Was sagst du Sprinter?

SprinterSB
18.04.2006, 18:43
Der Slave kann ja nicht in die Zukunft schauen oder die Adresse erraten, aus der er das Datum lesen soll. Die Adresse ist aber erst im Slave NACH dem spi_putc(adress). Daher muss noch eine Übertragung gemacht werden, um die Nutzinformation zu bekommen.

Wird noch besser klar, wenn man sich deine Skizze anschaut.

Kaiser-F
18.04.2006, 20:10
Hallo Sprinter,

Ist richtig. Ich glaube aber da liegt ein kleines Mißverständnis vor. Oder ich hab mich falsch ausgedrückt.

1. CS nach LOW
2. Man gibt den Slave die entsprechenden Anweisungen.
spi_putc(SPI_READ);
spi_putc(adress);

3. Jetzt kopiert der Slave das ausgewählte Register in SEIN SPI-Data-Register.

Um nun DIESE Daten vom SLAVE zum MASTER zu Transportieren, muss der MASTER nochmal eine Transmission machen:
data = spi_putc(0xff);

An dieser Stelle ist jetzt die Frage, ob es unbedingt 0xFF sein muss, oder ob es auch 0xAB oder 0x00 was auch immer sein kann... Normalerweise ist es ja egal oder? was mann dann hier sendet? Hauptsache man sendet irgendwas.

CS nach HIGH...

Hanni
19.04.2006, 00:57
Um dies zu realisieren habe ich mir kleine CAN-Module gebaut:

Besteht die Möglichkeit ein Schaltbild dieser Module zu veröffentlichen ?

LC-HC
19.04.2006, 08:36
Alles klar, jetzt hab ich das geschnallt, (würde dann aber nicht LSB und MSB vertauscht werden) ich war immer der Meinung es müste auch so gehen:


//def. V
short int data;

while ( SPSR &= ~(SPIF));

data = SPDR

...


Aber trotzdem, viele Dank.
Übrigens versuch ich mich grade an einem AT90CAN128 und im Rahmen
einer Werkstudententätigkeit an der Renesas M16C Serie (hat auch CAN an Bord) wenn sich hier etwas Wissenswertes entwickelt werd ich das hier posten. Hat auch schonmal jemand was mit Flexray gemacht ?

LC-HC
19.04.2006, 08:42
Vielen Dank, jetzt is mir das auch klar. Ich hatt´s immer meiner Logik nach so versucht:

short int data;

while( SPSR &= ~(1<<SPIF));

data = SPDR;

Also Danke nochmal. Übrigens Arbeite ich auch grade privat an eienm AT90CAN128 und als Werkstudent an einem µC aus der Renesas M16C Serie.
Wenn sich da etwas wissenswertes ergibt, lass ich´s wissen.
Hat auch schonmal jemand etwas mit Flexray gemacht ?

Kaiser-F
22.04.2006, 05:57
Hier für die, die das Teil auch bauen möchten:

http://www.sir-kaiser.de/download/001-MCP2515_CAN-MODUL.pdf

Hanni
22.04.2006, 13:32
Dankeschön :D

[fünfzehnzeichen]

rathma
19.10.2006, 10:36
Hallo,
ich bin gerade dabei das Projekt mal zum testen nachzubauen.

Ich suche aber in erster line eine möglichkeit so eine Art CANGateway zu bauen. Das heisst ich habe zwei CAN Netzte die ich miteinander verbinden will(und paar Sachen Filtern und ändern, verschiedene bauds usw.). Gibt es einen preisgünstigen IC der mit zwei CANschnittstellen umgehen kann oder hat jemand einen guten Lösungsvorschlag?

Gruss
Markus

Kaiser-F
19.10.2006, 11:49
Hallo rathma,

Du kannst auch zwei meiner Platinen mit einem Atmel verbinden.

Ansonsten glaube ich dass der "SJA1000" zwei Can-schnittstellen hat.

rathma
19.10.2006, 13:53
Bräuchte ich nicht dann aus zwei SPI Schnittstellen? An das hatte ich auch schon gedacht, das ich zwei mcp2515er verbaue

Kaiser-F
19.10.2006, 13:59
Nein brauchst du nicht. Dazu ist die CS/SS Leitung. Du kannst beliebig viele "SPI-Chips" miteinander verbinden, wie einen Bus.
Nur die CS oder auch SS Leitung bekommt jeder Chip seperat.
CS bedeutet CHIP-SELECT. Der jenige Chip, bei dem CS LOW ist,
wird angesprochen....


Sagen wir du hast im extremfall 2 CAN-Controller und eine SD-Karte.

Willst du nun mit CAN1 plaudern, viehst du CS von CAN1 auf LOW,
alle anderen MÜSSEN HIGH sein! Dann kannst du bequem mit CAN1 plaudern.

Willst du nun mit CAN2 Plaudern, so setzt du NUR CS von CAN2 auf low,
alle anderen MÜSSEN WIEDER HIGH SEIN!
Jetzt kann man bequem mit CAN2 plaudern.
Die anderen interessieren sich nicht dafür, was am SPI passiert.

Hierbei ist immer vorauszusetztn, dass dein ATMEL der SPI-Master ist!

Jetzt fragst du dich bestimmt, wozu dann die INT-Leitung ist.
Naja, versetzt dich mal in den CAN-Chip (machen wir es mal personifiziert).
Der empfängt jetzt was, und der atmel fragt einfach nicht nach über das SPI.
Dann meldet sich der CAN-Chip durch verändern des pegels an der
INT-Leitung, so ungefär: "hey, schau moi her"...
Daraufhin kann man dann was unternehmen...



Ich habe selbst schon ein System aufgebaut, welches genau das
erfüllen soll, was du machen willst. Benutze dabei auch zwei
MCP2515 und es funktioniert perfekt damit!

rathma
19.10.2006, 14:51
Die Interrupt leitung war mir schon klar.

ok eigendlich logisch, hätte da selber auch drauf kommen müßen, hab hier grad noch ein schema offen, hab da nur grad gedanklich mit den i²c bus was vertauscht(da hat jeder teilnehmer ja eine eigen adresse)

weist du ober jemand anderes, wie hoch umgefähr die baud auf den spi bus ist, wenn ich den avr in softmode bei 20 mhz takt habe.

Kaiser-F
19.10.2006, 15:18
Das kannst selber bestimmen...
Schau dazu einfach mal ins datenblatt unter SPI.

Man sollte glaub ich nicht über 1/4 fcpu drüber kommen...
in deinem fall 20/4=5MHz

rathma
06.11.2006, 22:45
Hi,
so ich hab es jetzt geschaft mit den mcp2515 und den attiny2313 daten zu senden(empfangen hab ich noch nicht programmiert, aber immer alles der reihe nach)
aber leider hab ich ein problem und zwar wollte ich bzw hab ich die cnf123 02ba07 codieren(sollten 166 kbit sein), gemessen und auch getested werden aber mit dieser codierung exakt 500kbit. am mcp2515 hängt ein 20mhz quarz. ich hab zur berechnung das tool genommen das vom kreariven caos verlinkt war. was hab ich den falsch gemacht? kann mir das einer mal erkären wie man das berechnet, ich hab mit zwar das datenblatt paar mal durchgelesen aber ich blick da leider nicht durch bzw steh aufm schauch.

gruss
markus

Kaiser-F
07.11.2006, 09:31
Hallo Markus,

oft muss man bei den jeweiligen Komponenten um eins erhöhen oder verringern.
Wenn du dir zB ProgSeg anschaust:
Wenn Probseg im Register 0 ist, ist es in Wirklichkeit 1...
bei so Sachen könnte sich der Fehler eingeschlichen haben...

Welches Tool hast du denn genau hergenommen?
Diesen Hier:
www.intrepidcs.com/website/BitCindex.htm ?

Kaiser-F
07.11.2006, 09:33
Sorry, der angegebene Link funktioniert nicht mehr...

Einfach auf der Hauptseite unter Downloads bei Suchen "Bit timing"
eingeben, dann kann man diesen hier runterladen:

Microchip Controller Area Network (CAN) Bit Timing Calculator

rathma
07.11.2006, 14:17
Ja hab das hier verwender http://www.intrepidcs.com/index.php?name=CmodsDownload&file=index&req=getit&lid=5

also müßte ich aus 02 ba 07 zb 01 b9 06 oder 03 bb 08 machen?

rathma
16.11.2006, 10:17
Hab mir jezt extra noch ein 16 Mhz Quarz besorgt und die werte 1:1 vom kreativen caos verwendet aber leider nichts :/

Kaiser-F
16.11.2006, 10:30
schreib uns mal was Du genau gesetzt hast

rathma
22.11.2006, 21:25
mein laptop ist leider noch gerade beim richten weg(motherboard oder cpu im himmel) und ich habe leider kein backup da. ich hoffe der laptop ist bald wieder da, da wichtige daten drauf sind.

gruss
markus

rathma
09.12.2006, 22:16
heute endlich mal dazu gekommen platinen zu ätzen und mal den quellcode zu säbern.

ich finde meinen fehler auch nicht :( kann mal bitte einer der experten drüber schauen.
Ich werd hier die tage den überarbeiteten code posten, da mich jetzt schon paar leute angemailt haben,das mein code nicht geht :)

rathma
12.12.2006, 22:17
hat keiner einen tipp für mich, ich weiss nichtmehr weieter. ich weiss nichtmehr wo ich weitermachen kann. ich glaub nicht das es am spi liegt, da ich es ja schaffe die led an und auszuschalten. ich hab die chips schon ausgetauscht um einen hardware schaden auszuschließen. das einzigste was unterschiedlich zu deinen grundaufbau ist, ich hab 27pF kondensatoren an den quarz und die resetleitung des mcp2515 nur mit 10k gegen 5V+ ohne kondensator gegen masse. ich kann gerne mal den schaltplan hier posten.

rathma
13.12.2006, 09:51
hier noch der schaltplan. spi bus wird softwaremäßig gemacht deswegen bitte nicht wundern warum in und out vertauscht sind.

Kaiser-F
13.12.2006, 12:29
Hallo rathma,

ich würde dir gerne helfen, leider kann ich Basic nicht so gut....

Mal eine blöde Frage vonmir:
Warum machst du Software SPI, und nicht Hardware-SPI ?
( Rein aus Interesse )

Tipp,
Versuch mal eine Funktion zu bauen, die nach der initialisation
die Register des MCP2515 liest, und sie dir auf die Serielle Schnittstelle
zum PC ausgibt. Dann kannst du überprüfen, ob die Register auch
wirklich so gesetzt sind, wie du es wolltest.


Noch eine Frage,
Dein Problem liegt einzig und allein darin, dss du die 166kbps nicht hinbekommst?

rathma
13.12.2006, 13:12
also mein problem liegt darin das ich nur 500kbit(und das auch nur duch zufall) hinbekomme.
mit 166k wollte ich nur testen weil ich mein laptop gerade auf diese boud eingestellt hatte. für das was ich vor hab brauch ich verschiedene baudraten, aber leider nicht 500kbit

warum verwende ich kein hardware spi: eigendlich ganz einfach, da ich noch alte at90s2313 hatte die kein spi haben und die attiny2313 haben angebich auch kein richtiges. die haben nur die spi um sie selber zu sprogrammieren glaub ich.

gruss
markus

Kaiser-F
13.12.2006, 13:35
Hallo,

Also, ich habe gerade mal im
"Microchip CAN Bit Timing Calculator" nachgeschaut.

Hier mal meine Theorie:
Weder mit 16MHz, noch mit 20Mhz Quarz kommt man auf die 166kbps.
Das geht einfach rechnerrisch nicht auf. Es gibt für diese Quarze
anscheinend keine Lösung für 166kbps, die 0% Error hat...

166,667kb war das Beste glaub ich, wären sogar nur -0,4016% Error.
Mit 20MHz, BRP-1 = 5, 10Tq.
Mit 16MHz, BRP-1 = 1, 24Tq.

Kannst es ja mal versuchen... Einige Pakete werden evtl Fehlerhaft übertragen. Eben 0,4% der Pakete... Also ca. 1 von 250Paketen.
Ich glaube aber, dass der MCP2515 in einem Solchen fall dann den sendevorgang wiederholt!

( Sorry, dass ich dir das erst jetzt sage :-/ )

Das ist vergleibar mit dem UART.
Setzt man für den ATMEL zB 8MHz quarz ein, kann man
keine üblichen Baudraten erzielen, die 0% Error liefern.

Du müsstest als mit den Formeln im Datenblatt zurückrechnen,
welches Quarz du einsetztn müsstest, dass 166kbps "als ganze Zahl" rauskommt... Aber mir 0,4% Error dürfte es schon funktionieren!


Probier einfach mal folgendes aus:
Mit 16MHz:
BRP-1 = 1;
Proporgation Delay = 7 Tq;
Phase Segment 1 = 8 Tq;
Phase Segmant 2 = 6 Tq;
Syncro Jump Width = 1 Tq;

Mit 20MHz:
BRP-1 = 2;
Proporgation Delay = 3 Tq;
Phase Segment 1 = 8 Tq;
Phase Segmant 2 = 8 Tq;
Syncro Jump Width = 1 Tq;

Mach auch mal ein Probeprogramm, welches dir die
Register aus dem MCP wieder ausliest, zur Kontrolle.

rathma
13.12.2006, 17:54
hatte schon mit 166,66 kbit probiert. hab auch schon mit 250kbits 125kbit und 62.5kbit getested und ging nichts :/ und bei diesen werten dürfte 0% fehler sein.
von der thorie hab ich her auch schon alles kapiert und der vergleich mit urat ist mir auch bewust, es kommen aber leider keine daten an.(ausser wenn ich meinen pc auf 500k stelle und den mcp2515 auf 166,66kbit)

ich werd mal deinen tipp ausprobieren und die geschriebenen register wieder auslesen.

ich war heute den ganzen tag in der nähe von straubing, da hätte ich eigendlich gleich bei dir vorbeischauen können *duck* :-)

Kaiser-F
13.12.2006, 18:00
Jup,
teste das mal mit den Registern!

Ich versuche mal das basicprogramm zu verstehen
(Nichts gegen Dein Programm, ich kann nur Basic nicht so gut :-) )


Nebenbei:
Wo genau warst denn unterwegs? Hättest leicht vorbeischaun können ;-)
Auf ein, zwei oder drei Bier :-)

Kaiser-F
13.12.2006, 18:49
Okey,

Laut Deinem Programm setzt du Folgendes:
CNF1 = 0x02 = 0b00000010
CNF2 = 0xBA = 0b10111010
CNF3 = 0x07 = 0b00000111


Aus CNF1 = 0b00000010 folgt:

BRP0 = 0
BRP1 = 1
BRP2 = 0
BRP3 = 0
BRP4 = 0
BRP5 = 0
SJW0 = 0
SJW1 = 0

Daraus folgt:
BRP = 3, da BRP1 ist, wenn im Register 0 steht.
SJW entspricht 1 TQ


Aus CNF2 = 0b10111010 folgt:

PRSEG0 = 0
PRSEG1 = 1
PRSEG2 = 0
PHSEG10 = 1
PHSEG11 = 1
PHSEG12 = 1
SAM = 0
BTLMODE = 1


Daraus folgt:
Proporgation Segment Length = 3TQ
PS1 = 8 TQ


Aus CNF3 = 0b00000111 folgt:

PHSEG20 = 1
PHSEG21 = 1
PHSEG22 = 1
-
-
-
WAKFIL = 0
SOF = 0

Daraus folgt:
PS2 = 8,

FAZIT:
Alle TQs zusammen ergeben: 1TQ +3TQ + 8TQ + 8TQ = 20TQ

BRP = 3.

Schauen wir mal in den Calculator:
Ich male mal die Spalte bei 20TQ hin:

[(BRP-1) =0] : 500kb
[(BRP-1) =1] : 250kb
[(BRP-1) =2] : 166,667kb

Müßte tatsächlich 166,667kb sein.
Offenbar stimmt was mit der Übertragung zum CNF1 nicht.
Der haut Dir da ne 0 rein, anstatt ne 2...



Das Problem könnte darin bestehen, dass du vergessen hast,
den MCP2515 in Konfigurationsmodus zu versetzen.

Bei mir sieht der INIT-Vorgang so aus:

1. Den Chip Resetten
2. den Chip in Configurationsmodus versetzen: REQOP2 in CANCTRL auf 1 setzen.
2. CNF1, 2, 3 usw... Filter, Masken usw.. setzen
3. Wieder in Normalmodus versetzen.

rathma
14.12.2006, 09:34
ohh richtig peinlich, ich hab den punkt 2 vergessen. einen reset mache ich noch aber in den config modus schalte ich ihn nicht, nur dann aus. ](*,) ](*,) ](*,) *und noch paar mal mit den kopf gegen die mauer hau*

ich sag jetzt lieber nicht wielange ich schon vor den quellcode war und gekrübelt habe. ich werd das heute abend gleich testen.

schon mal 1000x danke für deine hilfe

gruss
markus

m4444x
14.12.2006, 09:38
Funktioniert das bei dir ohne delay nach dem reset? Bei mir hat's erst gefunzt als ich nach dem reset noch ein _delay_ms( 1 ) eingefügt hab. Dafür spar ich mir den 2. Schritt, da der chip nach einem reset automatisch im config modus ist.

rathma
14.12.2006, 18:26
es geht :-) ich werd jetzt den code noch verschönern und eine empfangsroutine schreiben und dann online stellen, da hier im forum und auch in anderen sehr oft nach mcp2515 und bascom gefragt wird.

danke franz für deine hilfe.

Kaiser-F
14.12.2006, 18:31
Kein Problem, freut mich, dass es funktioniert und dass ich helfen konnte!

rathma
31.12.2006, 16:02
so nachdem der teil mit senden von can ids jetzt klappt :-) hab ich ein problem mit den empfangen, bzw das empfangen an sich klappt theoretisch.

das problem ist eigendlich nicht groß, es geht da nur um 1 bit aber ein bit kann leider viel versauen :/

wenn ich zb 11111111 empfangen sollte kommt 11111110. dh er schneidet das erste bit immer ab und ersetzt logischerweisse das letzte durch 0, da ja da nichts mehr empfangen wird.

ich wünsch euch alle schon mal ein schönes neues jahr

gruss
markus

rathma
31.12.2006, 16:09
noch zur Info(hab meine änderung Fett geschrieben)



Das Problem könnte darin bestehen, dass du vergessen hast,
den MCP2515 in Konfigurationsmodus zu versetzen.

Bei mir sieht der INIT-Vorgang so aus:

1. Den Chip Resetten
WARTEN bis der Chip "gebooted" ist
2. den Chip in Configurationsmodus versetzen: REQOP2 in CANCTRL auf 1 setzen.
2. CNF1, 2, 3 usw... Filter, Masken usw.. setzen
3. Wieder in Normalmodus versetzen.

wenn man nach denn reset nicht warted, wird der nächste befehl(in deinen fall "REQOP2 in CANCTRL auf 1 setzen") verlohren gehen.
dies fällt zwar nicht weiter auf, da nach einen reset der mcp2515 sowieso in den config mode wächselt aber bei mir viel es damals auf, da der cnf1 gleich nach den reset geschrieben wurde.

ich hab bei mir ein waitms 1 (weniger müßte auch problemlos gehen, habs aber noch nicht getested)

gruss
markus

Kaiser-F
01.01.2007, 00:30
Hallo Rathma,

evtl hast du dich in folgendem vertan:
die ID ist in zwei Register zu lesen, da kann sich sczhon mal ein Fehler
beim zusmmenfügen einfschleichen..!

Poste mal deinen Code.

Mann hab iczh einen Sitzen :-) Frohes neues!

Richard
01.01.2007, 11:02
es geht :-) ich werd jetzt den code noch verschönern und eine empfangsroutine schreiben und dann online stellen, da hier im forum und auch in anderen sehr oft nach mcp2515 und bascom gefragt wird.
danke franz für deine hilfe.

Moin moin allerseits,

Jetzt lese ich schon ziemlich lange im Forum und entdecke euch b.z.w. diesen Can_Bus Thread erst heute. :-( Ich habe mich damit vor etlichen Jahren etwas beschäftigt, seinerzeit hatte Elecktor damit mal etwas angefangen. Leider bin ich damals nicht weitergekommen, die Teile müßten aber noch im "Elecktronikschrott" zu finden sein. :-) Mal schauen ob ich noch etwas finde. Am Bascom Code währe ich auch interessiert,
"c" raffe ich noch nicht so richtig, Basic und Assembler ist mir noch aus
"alten Zeiten" bekannter.

Frohes Neues, Richard

rathma
01.01.2007, 13:55
Das die ID auf zwei Bytes/Register verteilt ist, ist mir schon klar :-) Es geht hier um alle Register bzw Statussachen, da ist alles um 1 nach links verschoben(1 Bit im Nirvana und letzte durch 0 aufgefüllt)
hier mal ein beispiel:


Sub Mcp2515_read_rx_status()

Dim Rx_status As Byte
Dim Spi_rx_status As Byte
Dim Spi_read As Byte
Spi_rx_status = &HB0
Spi_read = &H03


Reset Cs_line


Spiout Spi_rx_status , 1
Spiin Rx_status , 1


Set Cs_line

Print Bin(rx_status)
Print Hex(rx_status)

End Sub


gruss
markus

rathma
11.02.2007, 20:16
thema mal wieder nach oben.

ich hab leider in den letzten wochen nicht viel zeit gehabt nach fehlern zu suchen und leider auch nicht die technischen möglichkeiten mit einen oszi oder digitalanalysator mitzuloggen ob der attiny vergisst das erste bit einzulesen oder der mcp2515 diesen gar nicht sendet.

hätte jemdand einen vorschlag wie ich das testen könnte oder kommt jemand aus den raum münchen der mir helfen könnte(als bezahlung gibts gutes bier :-) )


gruss
markus

m4444x
12.02.2007, 14:37
Wie initialisierst Du die SPI ?
Da sollte es zwei Möglichkeiten geben die Takt Polarität einzustellen. Eventuell liegt es daran.

pam
16.02.2007, 12:00
Hallo

Hast du schon ein CODE für MCP2515 und Bascom

würde mich sehr freuen

gruß Patrick

rathma
16.02.2007, 12:57
@m4444x
du meinst ob er bei steigender oder fallender flanke schaut was die dataleitung für einen status hat? an das hatte ich auch schon gedacht, aber leider läst sich das irgendwie bei soft spi in bascom nicht konfigurieren(kommt immer ein error beim kompelieren :( )
deswegen meine frage nach speicheroszi oder änliches

oder weiss einer von euch wie man das in bascom macht?

@pam
wenn alles läuft wirds eine fertige api(ich nenns jetzt mal so) geben


gruss
markus

Stromi
16.02.2007, 13:04
Also wenn es dir hilft kannst du mal 'nen usb-Logikanalyser leihen, bin auch an einen fertigen Bascom CAN-Bus interessiert, aber zu blöde es selbst zu machen, bischen Zeitmangel ist auch da :=)
mfg

rathma
17.02.2007, 12:46
@Stromi
schreib mir mal bitte eine E-Mail

Stromi
25.02.2007, 16:59
geschrieben........., nicht bekommen?

rathma
25.02.2007, 17:01
ahh sorry habs grade erst gesehen das du mir eine pn geschickt hast. ich hab auf eine richte mail gewarted. ich werd die pn aber gleich lesen.

gruss
markus

rathma
18.03.2007, 21:00
erstmal danke an Stromi, der mir einen logicanalysator ausgeliehen hat.

hier noch mein leztztes problem, wenn das gelöst ist, hätte ich einen bascom code fertig
https://www.roboternetz.de/phpBB2/viewtopic.php?p=264868#264868

gruss
markus

DO7RH
23.03.2007, 07:46
Moin moin zusammen,

ich hae nun schon so einige Stunden mit dem MCP2515 verbracht und das Ding sendet mir nun auch schon ein paar lustige Bits raus. Mein Versuchsaufbau:
µC Mega 128 - MCP2515 <--> MCP2515 - µC Mega 8
Ans senden bekomme ich beide dank dem Tutorial auf http://www.kreatives-chaos.com/artikel/ansteuerung-eines-mcp2515
Was ich aber bis lang noch nicht hin bekomme ist eine vernünftige Empfangsauswertung.
Beim sende ist das nicht das Problem die Nachricht zu basteln und dann zu senden, nur wie mache ich das mit dem RX? Ich habe den MCP2515 so angeschlossen, das ein Interrupt bei LOW Signal ausgelöst wird. Eingehende Nachrichten werden mit "can_get_message" abgerufen und wenn ich das richtg erkenne spielt da auch "p_message" noch mit rein, aber wie?
Mein 2. Problem ist, das ich den MCP2515 nicht in den Loopback Modus bekomme. Mit "CANCTRL, 0xE0, 0" setzte ich ihn in den normalen Modus und lt. Datenblatt, so denke ich jedenfalls, mit CANCTRL, 0xE0, 010 ind den Loopback, oder baue ich mir hier gerade selber den Fehler weil ich 010 (also 3 Werte) mit 0xE0 in Verbindung bringe?


Ronald

DO7RH
25.03.2007, 14:47
Mahlzeit

ich gebe mir nun selber eine Antwort, für den Fall, das andere hier die gleichen Probleme habe.
Da ja beim Empfangen einer Nachricht ein Interrupt ausgelöst wird, sieht bei mit die Empfangsroutine folgendermaßen aus.

SIGNAL (INT0_vect)
{
CANMessage rx_message;
can_get_message(&rx_message);
}

Jetzt kann man sich die benötigten Informationen aus rx_message raus ziehen.

Natürlich stehe ich jetzt vor dem Nächsten Problem: Ich bekomme infach kein ACK.
Hatte auch schon überlegt das Senden nach einigen Versuchen wieder einzustellen, aber irgendwie ist das noch nicht die saubere Lösung.
Ich verstehe nicht, warum mein 2. Controller ein ACK sendet. Muss ich ihm das noch extra bei bringen? Beide MCP2515 sind im Normal Mode. Ich habe nun am Mega128 4 Taster angeschlossen. Über diese möchte ich 2 LED ein bzw aus schalten. Wenn ich nun einen Taster betätige, reagiert die gewünschte LED auch, nur dadurch, das er nicht mehr mit dem Enden aufhört, muss ich erst den Controller wieder reseten, damit ich weiter machen kann.

Ronald