// Chapter 14 6812 C programs // Jonathan W. Valvano, 2/26/07 // This software accompanies the book, // Embedded Microcomputer Systems: Real Time Interfacing, Second Edition // published by Thomson Engineering, 2006 void CAN_Open(void){ asm sei // make atomic CANFifo_Init(); // Initialize FIFO data structure CANCTL1 |= 0x80; // CANE=1, Enable CAN CANCTL0 |= 0x02; // SLPRQ=1, go to sleep first while((CANCTL1&0x02)==0){}; // SLPAK signifies Sleep Mode CANCTL0 &= ~0x02; // SLPRQ=0, leave Sleep Mode CANCTL0 |= 0x01; // INITRQ=1, Enter Initialization Mode while((CANCTL1&0x01)==0){}; // INITAK signifies Initialization Mode CANCTL1 &= ~0x10; // LISTEN=0, get out of Listen-only mode CANCTL1 &= ~0x40; // CLKSRC=0, use oscillator clock CANIDAC = 0x10; // four 16-bit filters CANIDMR0 = 0xFF; CANIDMR1 = 0xFF; CANIDMR2 = 0xFF; CANIDMR3 = 0xFF; CANIDMR4 = 0xFF; CANIDMR5 = 0xFF; CANIDMR6 = 0xFF; CANIDMR7 = 0xFF; CANBTR0 = 0x03; // (x+1)=4, assume oscillator is 8 MHz CANBTR1 = 0x23; // (3+y+z)=8, divide by 32 gives 250,000 bits/sec CANCTL0 &= ~0x01; // INITRQ=0, Leave Initialization mode while(CANCTL1&0x01){}; // wait for the end of initialization CANRIER |= 0x01; // Arm RxF, interrupt on receive message asm cli // Enable interrupts } //Program 14.1. Initialization of the 9S12C32 CAN network. void CAN_Send(unsigned short id, char length, char *data, char priority) { char *pt=(char*)&_CANTXDSR0; // points to transmit message buffer while((CANTFLG&0x07)== 0){}; // Wait for transmit buffer available CANTBSEL = CANTFLG; // Request selection of empty transmit buf CANTXIDR0 = id>>3; // Write Identifier into ID registers CANTXIDR1 = id<<5; // with RTR and IDE=0 CANTXDLR = length; // 0 to 8 bytes while(length){ *pt++ = *data++; // copy data into data registers length--; } CANTXTBPR = priority; // set priority of this message CANTFLG = CANTBSEL; // flag buffer as ready for transmission } //Program 14.2. Transmit a message on the 9S12C32 CAN network. void CAN_Receive(char msg[13]) { while (CANFifo_Get(msg) == 0){}; // wait for incoming message } interrupt 38 void CANInterruptHandler(void){ char *msgPtr = (char*)&_CANRXIDR0; if(CANRFLG & RXF){ CANCTL0 |= RXFRM; // clear Received frame flag CANFifo_Put(msgPtr); CANRFLG |= RXF; // clear RXF by writing a 1. } } //Program 14.3. Receive a message from the 9S12C32 CAN network. void main(void){ // example foreground program char msg[13]; // received message unsigned short id; // ID of received message char length; char i; short sum; CAN_Open(); // activate CAN for(;;) { CAN_Receive(msg); // wait for incoming message id = (msg[0]<<3)+(msg[1]>>5); // bytes 0,1 are CANTXIDR0-1 if(id == 50){ length = msg[12]; // byte 12 is CANTXDLR i = 4; sum = 0; while(length){ sum += msg[i++]; // bytes 4-11 are data length--; } CAN_Send(51,2,&sum,0); } } } //Program 14.4. Example main program that sends and receives messages on the 9S12C32 CAN network. void I2C_Open(void){ IBCR = 0x80; // enable, no interrupts, slave mode IBFD = 0x1F; // 100kHz, assuming 24 MHz bus clock IBSR = 0x02; // clear IBIF } //Program 14.5. 9S12C32 I2C initialization in single master mode. void I2C_Send(char slave, unsigned char data1, unsigned char data2){ IBCR |= 0x30; // send START IBDR = slave&0xFE; // send address with D0=0 signifying write while((IBSR&0x02)==0){}; // wait for the address to be sent IBSR = 0x02; // clear IBIF IBDR = data1; // send first byte while((IBSR&0x02)==0){}; // wait for the data to be sent IBSR = 0x02; // clear IBIF IBDR = data2; // send second byte while((IBSR&0x02)==0){}; // wait for the data to be sent IBSR = 0x02; // clear IBIF IBCR &=~0x30; // send STOP } //Program 14.6. 9S12C32 I2C transmission in single master mode. unsigned short I2C_Recv(char slave){ unsigned char data1,data2; IBCR |= 0x30; // send START IBDR = slave|0x01; // send address with D0=1 signifying read while((IBSR&0x02)==0){}; // wait for the address to be sent IBSR = 0x02; // clear IBIF IBCR &= ~0x18; // Tx/Rx=0, and TXAK=0 data1 = IBDR; // dummy read to initiate receiving while((IBSR&0x02)==0){}; // wait for the data to be received IBSR = 0x02; // clear IBIF IBCR |= 0x08; // TXAK=1 data1 = IBDR; // capture first byte, initiate second while((IBSR&0x02)==0){}; // wait for the address to be sent IBSR = 0x02; // clear IBIF IBCR &=~0x38; // send STOP data2 = IBDR; // capture second byte return (data1<<8)+data2; } //Program 14.7. 9S12C32 I2C reception in single master mode. // Program 14.8. Bit fifo routines. unsigned int TxFifo[FifoSize]; // storage for Bit Stream struct BitPointer{ unsigned int Mask; // 0x8000, 0x4000,...,2,1 unsigned int *WPt;}; // Pointer to word containing bit typedef struct BitPointer BitPointerType; BitPointerType PutTxPt; // Pointer of where to put next BitPointerType GetTxPt; // Pointer of where to get next /* BitFIFO is empty if PutTxPt==GetTxPt */ /* BitFIFO is full if PutTxPt+1==GeTxtPt after wrap */ int SameBit(BitPointerType p1, BitPointerType p2){ if((p1.WPt==p2.WPt)&&(p1.Mask==p2.Mask)) return(1); //yes return(0);} // no //******************InitTxBit************************ // initializes the BitFifo to be empty void InitTxBit(void) { PutTxPt.Mask=GetTxPt.Mask=0x8000; PutTxPt.WPt=GetTxPt.WPt=&TxFifo[0];} /* Empty when PutTxPt==GetTxPt */ //********************PutTxBit************************ // returns TRUE=1 if successful, FALSE=0 if full and data not saved // input is boolean FALSE if data==0 int PutTxBit (int data) { BitPointerType TempPutPt; TempPutPt=PutTxPt; TempPutPt.Mask=TempPutPt.Mask>>1; if(TempPutPt.Mask==0) { TempPutPt.Mask=0x8000; ++TempPutPt.WPt; // next word address if((TempPutPt.WPt)==&TxFifo[FifoSize]) TempPutPt.WPt=&TxFifo[0];} // wrap if (SameBit(TempPutPt,GetTxPt)) return(0); /* Failed, fifo was full */ else { if(data) (*PutTxPt.WPt) |= PutTxPt.Mask; // set bit else (*PutTxPt.WPt)&= ~PutTxPt.Mask; // clear bit PutTxPt=TempPutPt; return(1);}} //********************GetTxBit************************ // returns TRUE=1 if successful, FALSE=0 if empty and data not removed // output is boolean 0 means FALSE, nonzero is true int GetTxBit (unsigned int *datapt) { if (SameBit(PutTxPt,GeTxtPt)) return(0); /* Failed, fifo was empty */ else { *datapt=(*GetTxPt.WPt)&GetTxPt.Mask; GetTxPt.Mask=GetTxPt.Mask>>1; if(GetTxPt.Mask==0) { GetTxPt.Mask=0x8000; ++GetTxPt.WPt; // next word if((GetTxPt.WPt)==&TxFifo[FifoSize]) GetTxPt.WPt=&TxFifo[0];} // wrap return(1); }} // Program 14.8. Bit fifo routines.