// Chapter 11 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 // Program 11.1. Software used to test how many bits are really needed. void DACout8(unsigned short code){ DACout(code&0xFFF0); // ignore bottom 4 bits } void DACout10(unsigned short code){ DACout(code&0xFFFC); // ignore bottom 2 bits } // Program 11.2. Periodic interrupt used to create the analog output waveform. unsigned short wave(unsigned short t){ float result,time; time = 2*pi*((float)t)/1000.0; // integer t in msec into floating point time in seconds result =2 048.0+1000.0*cos(31.25*time)-500.0*sin(125.0*time); return (unsigned short) result; } // Program 11.3. Periodic interrupt used to create the analog output waveform. #define RATE 2000 #define OC5 0x20 unsigned short Time; // Inc every 1ms void interrrupt 13 TOC5handler(void){ TFLG1 = OC5; // ack C5F TC5 = TC5+RATE; // Executed every 1 ms Time++; DACout(wave(Time)); } // Program 11.4. Simple data structure for the waveform. unsigned short I; // incremented every 1ms const unsigned short wave[32]= { 3048,2675,2472,2526,2755,2957,2931,2597, 2048,1499,1165,1139,1341,1570,1624,1421, 1048,714,624,863,1341,1846,2165,2206,2048, 1890,1931,2250,2755,3233,3472,3382}; // Program 11.5. Periodic interrupt used to create the analog output waveform. #define RATE 2000 #define OC5 0x20 void interrupt 13 TOC5handler(void){ TFLG1 = OC5; // ack C5F TC5 = TC5+RATE; // Executed every 1 ms if((++I)==32) I = 0; DACout(wave[I]); } // Program 11.6. Data structure with time and value for the waveform. short I; // incremented every 1ms short J; // index into these two tables const short t[10]= {0,2,6,10,14,18,22,25,30,32}; // time in msec const short wave[10]={3048,2472,2931,1165,1624,624,2165,1890,3472,3048}; //last=first // Program 11.7. Periodic interrupt used to create the analog output waveform. #define RATE 2000 #define OC5 0x20 void interrupt 13 TOC5handler(void){ TFLG1 = OC5; // ack C5F TC5 = TC5+RATE; // Executed every 1 ms if((++I)==32) {I=0; J=0;} if(I==t[J]) DACout(wave[J]); else if (I==t[J+1]){ J++; DACout(wave[J]); } else DACout(wave[J]+((wave[J+1]-wave[J])*(I-t[J]))/(t[J+1]-t[J])); } // Program 11.8. Data structure with delta time and value for the waveform. unsigned short I; // incremented every sample const unsigned short wave[32]= { 3048,2675,2472,2526,2817,2981,2800,2337,1901,1499,1165,1341,1570,1597,1337, 952, 662, 654, 863,1210,1605,1950,2202,2141,1955,1876,2057,2366,2755,3129,3442,3382}; const unsigned short dt[32]= { // time increment in 500 ns cycles 2000,2000,2000,2500,2500,2000,2000,1500,1500,2000,4000,2000,2500,2000,2000,2000, 2000,1500,1500,1500,1500,2000,2500,2000,2000,2000,1500,1500,1500,2000,2500,2000}; // Program 11.9. Periodic interrupt used to create the analog output waveform. #define OC5 0x20 void interrupt 13 TOC5handler(void){ TFLG1 = OC5; // ack C5F if((++I)==32) I=0; TC5 = TC5+dt[I]; // variable rate DACout(wave[I]); } // Figure 11.54 Software implementation of a 12-bit successive approximation A/D. unsigned int SuccAproxAD(void){ unsigned short DOUT,bit; DOUT = 0; for(bit=2048;bit;bit>>1){ DOUT |= bit; // try to turn on this bit DACout(DOUT); // set D/A output, V0 if(Z()) DOUT ^= bit; // too big, so remove this bit } return(DOUT); } // Program 11.10. Software implementation of a sigma-delta A/D. unsigned char DOUT; // 8-bit sample unsigned char SUM; // number of times Z=0 and V0=1 unsigned char CNT; // 8-bit counter void interrupt 13 TOC5handler(void){ TFLG1 = OC5; // ack C5F TC5 = TC5+rate; // interrupt 256 times faster than the A/D output rate if(Z()) // check input DACout(0); // too high, set D/A output, V0=0 else { DACout(1); // too low, set D/A output, V0=+5v SUM++; } if(++CNT==0){ // end of 256 loops? DOUT = SUM; // new sample SUM = 0; // get ready for the next } } // Program 11.11. Software implementation of first derivative using a multiple access circular queue. #define RATE 2000 #define OC5 0x20 unsigned short x[4]; // MACQ (mV) unsigned short d; // derivative (V/s) void interrupt 13 TOC5handler(void){ TC5 = TC5+RATE; // Executed every 1 ms TFLG1 = 0x20; // ack OC5F x[3] = x[2]; // shift MACQ data x[2] = x[1]; // units of mV x[1] = x[0]; x[0] = ADC_In(0x85); // current data, from Channel 5 d = x[0]+3*x[1]-3*x[2]-x[3]; // mV/ms } // Program 11.13. C-language software to sample data using the ADC . // MC9S12C32 void ADC_Init(void){ ATDCTL2 = 0x80; // enable ADC // bit 7 ADPU=1 enable // bit 6 AFFC=0 ATD Fast Flag Clear All // bit 5 AWAI=0 ATD Power Down in Wait Mode // bit 4 ETRIGLE=0 External Trigger Level/Edge Control // bit 3 ETRIGP=0 External Trigger Polarity // bit 2 ETRIGE=0 External Trigger Mode Enable // bit 1 ASCIE=0 ATD Sequence Complete Interrupt Enable // bit 0 ASCIF=0 ATD Sequence Complete Interrupt Flag ATDCTL3 = 0x08; // bit 6 S8C =0 Sequence length = 1 // bit 5 S4C =0 // bit 4 S2C =0 // bit 3 S1C =1 // bit 2 FIFO=0 no FIFO mode // bit 1 FRZ1=0 no freeze // bit 0 FRZ0=0 ATDCTL4 = 0x05; // enable ADC // bit 7 SRES8=0 A/D Resolution Select // 1 => n=8 bit resolution // 0 => n=10 bit resolution // bit 6 SMP1=0 Sample Time Select // bit 5 SMP0=0 s=4 // bit 4 PRS4=0 ATD Clock Prescaler m=5 // bit 3 PRS3=0 ATD Clock Prescaler // bit 2 PRS2=1 ATD Clock Prescaler // bit 1 PRS1=0 ATD Clock Prescaler // bit 0 PRS0=1 ATD Clock Prescaler // Prescale = 2(m+1) = 12 cycles // ADC clock period = 2(m+1)/24MHz = 0.5us // choose m so 2(m+1)/Eperiod is between 0.5 to 2us // Sample time s=4 // SMP1 SMP0 s sample time // 0 0 4 ADC clock periods // 0 1 6 ADC clock periods // 1 0 10 ADC clock periods // 1 1 18 ADC clock periods // ADC conversion time 2(m+1)(s+n)/24MHz = 7us // if multiple samples are selected, then each requires 7us } //******** ADC_In *************** // perform 10-bit analog to digital conversion // input: chan is 0 to 7 specifying analog channel to sample // output: 10-bit ADC sample (left justified) // analog input left justified right justified // 0.000 0 0 // 0.005 0040 1 // 0.010 0080 2 // 1.250 4000 100 // 2.500 8000 200 // 5.000 FFC0 3FF // uses busy-wait synchronization // bit 7 DJM Result Register Data Justification // 1=right justified, 0=left justified // bit 6 DSGN Result Register Data Signed or Unsigned Representation // 1=signed, 0=unsigned // bit 5 SCAN Continuous Conversion Sequence Mode // 1=continuous, 0=single // bit 4 MULT Multi-Channel Sample Mode // 1=multiple channel, 0=single channel // bit 3 0 // bit 2-0 CC,CB,CA channel number 0 to 7 // example data = ADC_In(0x82); // samples right-justified channel 2 unsigned short ADC_In(unsigned short chan){ ATDCTL5 = (unsigned char)chan; // start sequence while((ATDSTAT1&0x01)==0){}; // wait for CCF0 return ATDDR0; } //**********************************from old edition***************// Program 11.10. Software implementation of a ramp A/D. unsigned short rampAD(void){ unsigned short DOUT; // guess DOUT = 0; // start at minimum, V0=-5.00 (offset binary) do { DACout(DOUT); // set D/A output, V0 DOUT++; // ramp } while((!Z())&&(DOUT<4096)); // stop when V0>Vin or DOUT=4096 return(DOUT); } // Program 11.11. Software implementation of a tracking A/D. int DOUT; // guess void main(void){ DOUT = 2048; // start in the middle, V0=0.00 (offset binary) while(1) { DACout(DOUT); // set D/A output, V0 if(Z()) { // check input if(DOUT>0) // don't go below 0 DOUT--; // V0>Vin so decrement } else { if(DOUT<4095) DOUT++; // V00) // don't go below 0 DOUT--; // V0>Vin so decrement } else { if(DOUT<4095) DOUT++; // V0