//=========================================================================== // Local Function Prototypes //=========================================================================== void outbyte(UINT8 reg, UINT8 value); UINT8 inbyte(UINT8 reg); void sleep(UINT16 nanosecondsX100); //************************************************************************************************************************ // ************************************************************************************************ // sja1000.C // // ************************************************************************************************ volatile UINT8 check; UINT8 testvector[13]=0; int i_SJA1000CANMode = 0; UINT8 delay = 5; unsigned int ui_IHandler = 0; unsigned int ui_SHandler = 0; ///////////////////////// unsigned int ui_CANActive = 0; ////////////////////////////////////////////////////////////////////////////// // Global variables ////////////////////////////////////////////////////////////////////////////// unsigned int CANBASISADR = 0 ; unsigned int ui_Sendepuffer[10]; unsigned char empfangspuffer[10]; unsigned char i; unsigned int ui_recvbuf[16]; // buffer for received messages unsigned long ul_msgcount = 0; // received message counter int i_recvret = 0; int j = 0; t_CMSG t_recvbuf; static int i_LastSJAMode = 0; static int i_LastACR = 0; static int i_LastAMR = 0; static int i_LastBTR0 = 0; static int i_LastBTR1 = 0; int i_Busoffctr = 0; unsigned int ui_SJAStatus = 0; /*************************** Funktionen *************************************/ /////////////////////////////////////////////////////////////////////////////// // CAN_FN_INITCAN /////////////////////////////////////////////////////////////////////////////// // // description: initialisiert den CAN controller SJA1000 // // input : int i_sjamode: 1 = BasicCAN, 2 = PeliCAN // int i_acr: ACR-Register of SJA1000 (filter) // int i_amr: AMR-Register of SJA1000 (filter) // int i_btr0: BTR0-Register of SJA1000 (baudrate) // int i_btr1: BTR1-Register of SJA1000 (baudrate) // // // output : none // // return : int 1 -> successful // -1 -> wrong mode, 1 = BasicCAN, 2 = PeliCAN // -2 -> controller does not enter reset mode // // 08.06.04 BAP first release /////////////////////////////////////////////////////////////////////////////// int CAN_fn_InitCAN ( int i_sjamode, long i_acr, long i_amr, int i_btr0, int i_btr1 ) { unsigned char cancontrolreg; unsigned char by_test = 0; unsigned int ui_timeout = 0; // timeout variable unsigned char by_acr0 = 0; unsigned char by_acr1 = 0; unsigned char by_acr2 = 0; unsigned char by_acr3 = 0; unsigned char by_amr0 = 0; unsigned char by_amr1 = 0; unsigned char by_amr2 = 0; unsigned char by_amr3 = 0; // save the settings // if an error comes from SJA1000, the function CAN_fn_InitCAN // will be called within CAN_fn_ClearError with this saved parameter values i_LastSJAMode = i_sjamode; i_LastACR = i_acr; i_LastAMR = i_amr; i_LastBTR0 = i_btr0; i_LastBTR1 = i_btr1; // Reset the ring buffer fn_ResetRXRingbuffer ( 0 ); // check mode setting if ( ( i_sjamode < 1 ) || ( i_sjamode > 2 ) ) { // wrong mode // 1 = Basic CAN // 2 = PeliCAN #ifdef DEVELOP //printf ( "*** mboxcan: error CAN_fn_InitCAN, wrong mode selected!\n"); #endif //********************************************************************************************* //******************* PELICAN MODE ************************************************************ if ( i_SJA1000CANMode == cPELICAN ) { #ifdef DEVELOP //printf ( "*** mboxcan: CAN_fn_InitCAN, PELICAN selected\n"); #endif by_test = (CANBASISADR>>8) & 0xFF; #ifdef DEVELOP //printf ( "*** mboxcan: CAN_fn_InitCAN baseadr: %04X\n", by_test); #endif outbyte (CANBASISREG,(CANBASISADR>>8) & 0xFF ) ; ui_CANActive = 0; // set CAN not active (used in receivertask or receiver interrupt) //CAN-Controller in den RESET-Mode setzten cancontrolreg = inbyte (CANBASISADR+cCANPELIMOD) ; cancontrolreg = cancontrolreg | 0x01 ; outbyte (CANBASISADR+cCANPELIMOD,cancontrolreg) ; ui_timeout = 0; while ((inbyte (CANBASISADR+cCANPELIMOD) & 0x01) != 0x01) { //Warten bis CAN-Controller im Reset-Mode sleep ( 10000 ); ui_timeout++; if ( ui_timeout >= 10 ) { // controller does not enter Reset Mode return -2; } } //***zu testzwecken testvector[0] = inbyte(cCANPELIMOD); ///////////////////////////////////////////////////////////////////////////////////////////// // WICHTIG: // fuer PeliCAN-Modus muss hier!! gleich mal in den PeliCAN-Mode geschaltet werden (Bit7 = 1) // sonst bleibt der SJA1000 im BasicCAN cancontrolreg = inbyte (CANBASISADR+CANCDR) ; cancontrolreg |= 0x80; //Mode: PELICAN outbyte (CANBASISADR+CANCDR,cancontrolreg); ///////////////////////////////////////////////////////////////////////////////////////////// // disable all interrupts CAN_fn_DisableIRQ(); /* // MOD register adr 0 // 0x08 = 0 0 0 0 1 0 0 0 // | | | | | | | |______ Reset Mode 0 normal, 1 = reset mode // | | | | | | |________ Listen only mode 0 = aus, 1 = an // | | | | | |__________ Self Test Mode 0 = aus, 1 = an // | | | | |____________ Acceptance Filter Mode 0 = dual, 1 = single // | | | |_________________ Sleep Mode 0 = aus, 1 = an // | | |___________________ reserved // | |_____________________ reserved // |_______________________ reserved cancontrolreg = inbyte (CANBASISADR+cCANPELIMOD) ; cancontrolreg |= 0x08; cancontrolreg &= 0x08; // outbyte (CANBASISADR+cCANPELIMOD, 0x08); outbyte (CANBASISADR+cCANPELIMOD, cancontrolreg); */ //Clock-Divider-Register setzen // 0x18 = 10001000 // ||||||___ fosc/2 (Wert unwichtig, da Ausgang abgeschaltet // |||||____ Taktausgang abschalten // ||||_____ reserviert, mit 0 beschreiben // |||______ Tx1-Ausgang nicht als Interrupt genutzt // ||_______ Eingangskomparator einschalten // | vorhanden // |________ PeliCAN Mode outbyte (CANBASISADR+CANCDR,0x88); //PELICAN MODE / CLOCKOUT PIN DISABLE // ACR(Acceptance code Register) - and AMR(Acceptance Mask Register) setzen outbyte (CANBASISADR + cCANPELIACR0, i_acr & 0xFF); //check = (i_acr >> 8) & 0xFF; //zum Test eingefügt outbyte (CANBASISADR + cCANPELIACR1, (i_acr >> 8) & 0xFF); //check = (i_acr >> 16) & 0xFF; //zum Test eingefügt outbyte (CANBASISADR + cCANPELIACR2, (i_acr >> 16) & 0xFF); //check = (i_acr >> 24) & 0xFF; //zum Test eingefügt outbyte (CANBASISADR + cCANPELIACR3, (i_acr >> 24) & 0xFF); outbyte (CANBASISADR + cCANPELIAMR0, i_amr & 0xFF); outbyte (CANBASISADR + cCANPELIAMR1, (i_amr >> 8) & 0xFF); outbyte (CANBASISADR + cCANPELIAMR2, (i_amr >> 16) & 0xFF); outbyte (CANBASISADR + cCANPELIAMR3, (i_amr >> 24) & 0xFF); #ifdef DEVELOP //printf ( "*** mboxcan: CAN_fn_InitCAN BTR0: %08X BTR1: %08X\n", i_btr0, i_btr1); #endif outbyte (CANBASISADR+CANBTR0,(i_btr0 & 0xFF)); outbyte (CANBASISADR+CANBTR1,(i_btr1 & 0xFF)); //Output Control Register einstellen // 0x1A = 00011010 // | | |__ Normal Output Mode // | |_____ Ausgang TX0 nichtinvertierend und Push-Pull // |________ Ausgang TX1 float, da nicht genutzt outbyte(CANOCR,0x00); //zu Testzwecken check = inbyte(CANOCR); //zu Testzwecken outbyte(CANOCR,0x21); //zu Testzwecken check = inbyte(CANOCR); //zu Testzwecken outbyte(CANOCR,0x00); //zu Testzwecken check = inbyte(CANOCR); //zu Testzwecken outbyte (CANBASISADR+CANOCR,0x1A); check = inbyte(CANOCR); //zu Testzwecken eingefügt // MOD register adr 0 // 0x08 = 0 0 0 0 1 0 0 0 // | | | | | | | |______ Reset Mode 0 normal, 1 = reset mode // | | | | | | |________ Listen only mode 0 = aus, 1 = an // | | | | | |__________ Self Test Mode 0 = aus, 1 = an // | | | | |____________ Acceptance Filter Mode 0 = dual, 1 = single // | | | |_________________ Sleep Mode 0 = aus, 1 = an // | | |___________________ reserved // | |_____________________ reserved // |_______________________ reserved outbyte (CANBASISADR+cCANPELIMOD,0x08) ; // enable receive interrupt CAN_fn_EnableIRQ(); ui_timeout = 0; //Warten bis CAN-Controller Reset-Mode verlässt while ((inbyte (CANBASISADR+cCANPELIMOD) & 0x01) != 0x00) { sleep ( 10000 ); ui_timeout++; if ( ui_timeout >= 10 ) { // controller does not leave Reset Mode return -2; } } // set CAN active (used in receivertask or receiver interrupt) ui_CANActive = 1; return 1; } return -99; // we should never get here ! //MG:2004-07-23 } /////////////////////////////////////////////////////////////////////////////// // CAN_FN_TRANSMIT /////////////////////////////////////////////////////////////////////////////// // // description: transmits the given can data // // input : unsigned int *ui_data : array of 16 unsigned int elements // Array-index [0] = Identifier // [1] = DLC // [2] = remote ( 0 = no remote, 1 = remote) // [3]..[10] = DB0..DB7 // [11] = extended ( 0 = standard, 1 = extended) // [12]..[15] = reserved // // output : none // // return : int 1 -> successful // -1 -> no space left in the transmit register of SJA1000 // -2 -> controller does not enter reset mode // // 08.06.04 BAP first release /////////////////////////////////////////////////////////////////////////////// int CAN_fn_Transmit ( unsigned long *ui_data ) { unsigned int i; unsigned char by_dlc = 0; unsigned char by_id0 = 0; unsigned char by_id1 = 0; unsigned char by_id2 = 0; unsigned char by_id3 = 0; unsigned char by_FrameInfo = 0; unsigned int ui_extended = 0; //*********************************************PELICAN TRANSMIT if ( i_SJA1000CANMode == cPELICAN ) { // Sendepuffer frei? if ( (inbyte(CANBASISADR+CANSR) & 0x04 ) != 0x04 ) { return -1; } by_dlc = ui_data[1] & 0x0F; by_FrameInfo = by_dlc; if ( ui_data[2] == 1 ) { // remote? by_FrameInfo |= 0x40; // Bit 6 setzen } else { by_FrameInfo &= 0xBF; // Bit 6 loeschen } if ( ui_data[11] == 1 ) { // ext? by_FrameInfo |= 0x80; // Bit 7 setzen ui_extended = 1; } else { by_FrameInfo &= 0x7F; // Bit 7 loeschen ui_extended = 0; } outbyte ( CANBASISADR + 16, by_FrameInfo ); // if ( ui_extended == 0 ) { by_id0 = ((ui_data[0]>>3)&0xFF); outbyte ( CANBASISADR + 17, by_id0); //identifier Bits 28..21 = 10..3 by_id1 = (ui_data[0] & 0x07); by_id1 <<= 5; outbyte ( CANBASISADR + 18, by_id1 ); //Sendedaten uebergeben belegen for ( i = 0; i < by_dlc; i++ ) { outbyte ( CANBASISADR + 19 + i, ui_data[3+i]) ; } } if ( ui_extended == 1 ) { by_id3 = (ui_data[0] >> 21) & 0xFF; outbyte ( CANBASISADR + 17, by_id3); by_id2 = (ui_data[0] >> 13) & 0xFF; outbyte ( CANBASISADR + 18, by_id2); by_id1 = (ui_data[0] >> 5) & 0xFF; outbyte ( CANBASISADR + 19, by_id1); by_id0 = (ui_data[0] ) & 0xFF; by_id0 <<= 3; outbyte ( CANBASISADR + 20, by_id0); //Sendedaten uebergeben belegen for ( i = 0; i < by_dlc; i++ ) { outbyte ( CANBASISADR + 21 + i, ui_data[3+i]) ; } } //Uebertragung starten outbyte (CANBASISADR+CANCMR,0x01) ; return 1; } // end of if ( i_SJA1000CANMode == cPELICAN ) { return -99; // we should never get here ! //MG:2004-07-23 } //========================================================================== // Definition of local Functions //========================================================================== void outbyte(UINT8 reg, UINT8 value) { DDRP = 0xFF; // data direction control port as output sleep(delay); DDRQ = 0xFF; // data direction data port as output sleep(delay); PTP = 0x07; // signals set as followed: AS, No CS, No E, WR, No RST sleep(delay); PTQ = reg ; // write register adress to sja1000 sleep(delay); PTP = 0x06; // Control Data: No AS, No CS, No E, WR, No RST sleep(delay); PTP = 0x0C; sleep(delay); // signals set as followed: No AS, WR, E, CS PTQ = value; sleep(delay); // write value in selected register of sja1000 PTP = 0x06; // Control Data: No AS, No CS, No E, WR, No RST } UINT8 inbyte(UINT8 reg) { volatile UINT8 regcontent = 0; DDRP = 0xFF; // Control Port As Output sleep(delay); DDRQ = 0xFF; // Data Port As Output sleep(delay); PTP = 0x07; // Control Data: AS, No CS, No E, WR, No RST sleep(delay); PTQ = reg; // write register adress you want to read from to sja1000 sleep(delay); PTP = 0x06; // Control Data: No AS, No CS, No E, WR, No RST sleep(delay); DDRQ = 0x00; // Data Port As Input sleep(delay); PTP = 0x1C; // Control Data: No AS, CS, E, No WR, No RST sleep(delay); regcontent = PTQ; sleep(delay); PTP = 0x06; // Control Data: No AS, No CS, No E, WR, No RST return(regcontent); } void sleep(UINT16 nanosecondsX100) { UINT16 cnt; UINT16 oldcnt; TSCR1 = 0xA0; TSCR2 = 0x03; //Prescaler 3 100ns pro clock oldcnt = TCNT; cnt = nanosecondsX100; while(TCNT < (oldcnt + cnt)){ } }