Hello,
I have some Can driver routine for my at90can128. I have tested them and so fare this seems good, but want to verify that this is a stable setup.
I want a interrupt driven RX and a polled TX in my system.
I use Mob 0 as reception mob and Mob 1 as tx mob. I also need a 29bit id mask and this is tested ok against external equipment. I use can_tx for sending on 1 sec and 500ms interval. The bus is by the way crowded with packets from many different can components.
Below I have added my code.
Any suggestions for changes and better performance
Regards ellile
void can_init (void) { uint8_t mob; CANGCON = (1 << SWRES); // Reset the CAN cntr hw for (mob = 0; mob < AT90CAN_MOBS; mob++) { CANPAGE = (mob << MOBNB0); // Set the MOb page CANCDMOB = MOB_DIS_CMD; // Set each MOb CANSTMOB = 0; // Clear all the MOb } // This will enable all the MObs for interrupt usage. Only the MObs you write CANCDMOB // commands to will ever be used, all other MObs will remain disabled and this setting will not // matter for disabled MObs. CANIE2 = 1; //Enable interrupt on Mob 0 CANPAGE = (0 << MOBNB0); // Set the MOb page CANSTMOB = 0; // Clear all the MOb CANIDM1 = 0; //get all messages CANIDM2 = 0; //1 = check bit CANIDM3 = 0; //0 = ignore bit CANIDM4 = (1<<IDEMSK); CANCDMOB = (1<<CONMOB1) | (1<<IDE); // Set MOb to extended format and as reception mob. CANBT1 = 0x02; // Timing - Baud Rate CANBT2 = 0x0C; // Timing - Re- CANBT3 = 0x1B; // Timing - Phase Segment 2, Phase Segment 1 and Sample Point. PS2=001, PS1=101 // This is the minimum Rx/Tx interrupt enable. It does not include MOb errors, General errors, // the BXOK, BOFFI or the OVR IT interrupt. CANGIE = (1 << ENIT) | (1 << ENRX) | (1 << ENTX); CANGCON = (1 << ENASTB); // Enable the CAN. } volatile MOb can_msg[RxCanSize]; volatile uint8_t can_tail; volatile uint8_t can_head; /* Looptime approx 36,7uS */ char can_tx (MOb msg) { unsigned char i; uint8_t temp = CANPAGE; //save CANPAGE //enable MOb1, auto increment index, start with index = 0 CANPAGE = (1<<MOBNB0); if(( CANCDMOB & 0b11000000) && ( (CANSTMOB & 0x40) ==0)) { CANPAGE = temp; //restore CANPAGE return false; } msg.id <<= 3; //write 29 Bit identifier CANIDT4 = (unsigned char) (msg.id&0xF8); CANIDT3 = (unsigned char) (msg.id>>8); CANIDT2 = (unsigned char) (msg.id>>16); CANIDT1 = (unsigned char) (msg.id>>24); for (i=0; i<8; i++) //put data in mailbox CANMSG = msg.data [i]; CANSTMOB = 0x00; // cancel pending operation CANCDMOB = (1<<CONMOB0) | (1<<IDE) | (8<<DLC0); //enable transmission //set IDE bit, length = 8 CANPAGE = temp; //restore CANPAGE return true; } ISR(CANIT_vect) //receive interrupt { uint8_t temp = CANPAGE; //save CANPAGE unsigned char i; uint8_t head; MOb msg; CANPAGE = (0 << MOBNB0); //select MOb0 msg.len = CANCDMOB & 0x08; for (i=0; i<8; i++) //get data msg.data [i] = CANMSG; msg.id = 0; msg.id |= ((unsigned long) CANIDT1<<24); //get identifier msg.id |= ((unsigned long) CANIDT2<<16); msg.id |= ((unsigned long) CANIDT3<<8); msg.id |= (CANIDT4 & 0xF8); msg.id >>= 3; head = ((can_head + 1) & RxCanMask); can_msg[can_head] = msg; if ( head != can_tail) can_head = head; CANSTMOB = 0; //clear interrupt flag CANCDMOB = (1<<CONMOB1) | (1<<IDE); //reconfig mailbox CANPAGE = temp; //restore CANPAGE CANSTMOB = 0; //clear interrupt flag }