I am using an S08DZ16CLC and have designed a program to measure the voltage across two potentiometers and output the data on the CAN bus.
The program seems to work until it enters the calibration function when a push button is pressed. Upon entering callibration mode an LED is turned on and then off upon exiting the function. As the program is being run using a 4MHz crystal, the LED should be on for a minimum of approx. 4 seconds, but it is significantly less than this.
More seriously, when in this callibration function, the debugger will often complain of a frequency change and an illegal_BP and halt the running of the program. My code is shown below, any help would be greatly appreciated!
//CALIBRATION RESULTS - GLOBAL VARIABLES
static unsigned int brk_cal_max = 0;
static unsigned int brk_cal_min = 255; //set to max range so all values less than initial
static unsigned int brk_cal_result = 0;
static unsigned int ac_cal_max = 0;
static unsigned int ac_cal_min = 255; //set to max range so all values less than initial
static unsigned int ac_cal_result = 0;
//FUNCTION TO PERFORM PEDAL CALIBRATION
unsigned int calibrate_pedals() {
unsigned long int a,n,m,p;
/*
asm{
NOP
}
*/
PTCD_PTCD5 = 0; //light LED1
//for(p=0;p<0xFFFFFF;p++){
//for(m=0;m<0xFFFFFF;m++){
for(n=0;n<0xFFFFFF;n++){ //loop in cal mode
for(a=0;a<5;a++) {
ADCSC1_ADCH=0x0D; //select rv2
ADCSC1_ADCO=0; //trigger conversion
while (!ADCSC1_COCO); //remain idle until conversion comple
brk_cal_result = (unsigned int)ADCRL;
if(brk_cal_result>brk_cal_max){
brk_cal_max = brk_cal_result;
}
if(brk_cal_result<brk_cal_min){
brk_cal_min = brk_cal_result;
}
}
for(a=0;a<5;a++){
ADCSC1_ADCH=0x0C; //select rv1
ADCSC1_ADCO=0; //trigger conversion
while (!ADCSC1_COCO); //remain idle until conversion complete
ac_cal_result = (unsigned int)ADCRL;
if(ac_cal_result>ac_cal_max){
ac_cal_max = ac_cal_result;
}
if(ac_cal_result<ac_cal_min){
ac_cal_min = ac_cal_result;
}
}
}
//}
//}
PTCD_PTCD5 = 1; //turn off calibration LED
}
//FUNCTION TO SEND ACCELERATOR AND BRAKE POSITION OVER CAN
static void send_can_data(unsigned long accelpos, unsigned long breakpos) {
int n;
while (!CANCTL0_SYNCH); //test if synched to CAN bus
while(!CANTFLG_TXE0); //test to see which buffers are empty
CANTTBPR = 0x00;
CANTIDR0 = 0xD0; //set CAN id.
CANTIDR1 = 0x00;
CANTDSR0 = (unsigned char)accelpos;
CANTDSR1 = (unsigned char)breakpos;
CANTFLG = 0x01; //clear the buffer, transmit
//while(CANTFLG_TXE0); //wait for flag to clear
CANTFLG = 0x00;
PTBD_PTBD3=0; //CAN light on
for(n=0;n<0xFFFF;n++); //delay
PTBD_PTBD3=1; //CAN light off
}
void main(void) {
unsigned int accel_result =0;
unsigned long accel_total = 0;
unsigned long accel_average = 0;
unsigned long accelpos =0;
unsigned int break_result =0;
unsigned long break_total = 0;
unsigned long break_average = 0;
unsigned long breakpos =0;
int n;
int a;
int b;
// MCGC2 = 0x62; /* Set MCGC2 register */
/* MCGC1: CLKS=0,RDIV=7,IREFS=0,IRCLKEN=0,IREFSTEN=0 */
// MCGC1 = 0x38; /* Set MCGC1 register */
/* MCGC3: LOLIE=0,PLLS=0,CME=0,VDIV=1 */
// MCGC3 = 0x01; /* Set MCGC3 register */
// while(MCGSC_IREFST) { /* Wait until external reference is selected */
// }
// while(!MCGSC_LOCK) { /* Wait until FLL is locked */
// }
// while((MCGSC & 0x0C) != 0x00) { /* Wait until FLL clock is selected as a bus clock reference */
// }
MCGC2_RANGE = 1; // High freq clock range selected
MCGC2_EREFS = 1; // External Ref Clock selected to be Internal Osc
MCGC2_ERCLKEN = 1; // Ext Ref Clk Enabled
while(!MCGSC_OSCINIT); //wait for oscillator to initialize
MCGC1 = 0x00; //Multi-purpose Clock Generator config register1
while(MCGSC_CLKST == 3); //wait until output of PLL is selected as clock
//MCGC1=0x80; //external ref clk selected, divided by 1
//MCGC2=0x33;
EnableInterrupts; /* enable interrupts */
/////////////////////////////////////////////////////////////////////////////
//Initialise CAN
CANCTL1_CANE = 1; /* for test: MSCAN enabled, clock = OSC_CLK, listen only disabled, wake-up filter disabled */
CANCTL0_INITRQ = 1; /* init mode */
while(!CANCTL1_INITAK); /* wait for ack of init mode */
CANCTL1 = 0x80; /* enable module with osc clk as source */
CANBTR0 = 0xC1; /* SJW = 1, SJW = 1, 4Tq jmpwdt prescaler = 2 */
CANBTR1 = 0xD8; /* SAMP = 1, 3 samples/bit, TSEG2 = 5, TSEG1 = 8, 15 Tq per bit */
CANIDAC = 0x10; //Initialise for 8bit mask
CANIDMR0 = 0x00; //All accemptance masks to 0x00 (accept nothing)
CANIDMR1 = 0x00;
CANIDMR2 = 0x00;
CANIDMR3 = 0x00;
CANCTL0_INITRQ = 0; /* leave init mode */
while(CANCTL1_INITAK); /* wait for ack of init mode exit */
CANTBSEL = 0x01; //select transmit buffer TX0
CANRFLG = 0x40;
CANRIER = 0;
CANTARQ = 0;
CANTIER = 0x00; /* transmit buffer empty interrupts disabled for TX0*/
//////////////////////////////////////////////////////////////////////////
/*initialise ADC*/
ADCCFG=0x90; //configured for low power, 8 bit, long samples, bus clk src
ADCSC2=0x00; //see log book for value breakdown
ADCSC1=0x21; //AIEN disabled, input channel 1
APCTL1=0x02; //AD1 pin I/O control disabled, all others general I/O
APCTL2=0x10; //all other pins general I/O, except adp12
ADCSC1_ADCH=0x0D; //ensure channel 13, rv2 as input
ADCSC1_ADCH=0x0C;
/////////////////////////////////////////////////////////////////////////////
//PTCPE_PTCPE5 = 1; //PB1 pull up enable
PTCDD_PTCDD5 = 1; //set LED1 as calibration output
PTBDD_PTBDD3 = 1; //set LED2 as CAN output
PTBDD_PTBDD6 = 0; //set PB1 as input
PTCD_PTCD5 = 1; //make sure LED1 is initially off
PTBD_PTBD3 = 1; //make sure LED2 is initially off
//read the ADC
for(; { //infinite loop
//Test button on port B pin 6 for calibration mode
if (!PTBD_PTBD6) {
calibrate_pedals();
}
for(n=0;n<3;n++){
for(a=0;a<5;a++){
ADCSC1_ADCH=0x0C;
ADCSC1_ADCO=0; //trigger conversion
while (!ADCSC1_COCO); //remain idle until conversion complete
break_result = (unsigned int)ADCRL;
break_total = break_total + break_result;
}
for(a=0;a<5;a++) { //loop so 10 adc values read CHANGED FOR TEST
ADCSC1_ADCH=0x0D;
ADCSC1_ADCO=0; //trigger conversion
while (!ADCSC1_COCO); //remain idle until conversion complete
accel_result = (unsigned int)ADCRL;
accel_total = accel_total + accel_result;
}
}
accel_average = accel_total/10;
accelpos =((accel_average*256)/(ac_cal_max - ac_cal_min));
break_average = break_total/10;
breakpos =((break_average*256)/(brk_cal_max - brk_cal_min));
accel_total = 0;
break_total = 0;
//delay loop provide time for CAN to respond
//to ADC
for(n=0;n<0xFFFF;n++);
///////////////////////////////////////////////////////////////////////////
//Send over CAN
send_can_data(accelpos, breakpos);
__RESET_WATCHDOG(); /* feeds the dog */
/* loop forever */
/* please make sure that you never leave main */
}
}
Any help would be greatly appreciated!!
Thank you.