// Chapter 7 9S12C32 C programs // Jonathan W. Valvano, 2/07/07 // This software accompanies the book, // Embedded Microcomputer Systems: Real Time Interfacing, Second Edition // published by Thomson Engineering, 2006 // MC9S12C32, CodeWarrior C void SCI_Init(void){ RxFifo_Init(); // empty FIFOs TxFifo_Init(); SCIBD = 26; // 9600 bits/sec SCICR1 = 0; // M=0, no parity SCICR2 = 0x2C; // enable, arm RDRF asm cli // enable interrupts } // Input ASCII character from SCI // spin if RxFifo is empty char SCI_InChar(void){ char letter; while (RxFifo_Get(&letter) == 0){}; return(letter); } // Output ASCII character to SCI // spin if TxFifo is full void SCI_OutChar(char data){ while (TxFifo_Put(data) == 0){}; SCICR2 = 0xAC; // arm TDRE } // RDRF set on new receive data // TDRE set on empty transmit register interrupt 20 void SciHandler(void){ char data; if(SCISR1 & RDRF){ RxFifo_Put(SCIDRL); // clears RDRF } if((SCICR2&0x80)&&(SCISR1&TDRE)){ if(TxFifo_Get(&data)){ SCIDRL = data; // clears TDRE } else{ SCICR2 = 0x2c; // disarm TDRE } } } //Program 7.2. C language implementation of an interrupting SCI interface. // MC9S12C32, CodeWarrior C void Printer_Init(void){ TxFifo_Init(); // empty FIFOs SCIBD = 26; // 9600 bits/sec SCICR1 = 0; // M=0, no parity SCICR2 = 0x0C; // enable disarm TDRE TIOS &=~0x08; // PT3 input capture DDRT &=~0x08; // PT3 is input TSCR1 = 0x80; // enable TCNT TCTL4 |= 0xC0; // both rise and fall TIE |= 0x08; // Arm IC3 TFLG1 = 0x08; // initially clear asm cli // enable interrupts } void checkIC3(void){ if(PTT&0x08) // PT3=1 if DTR=-12 SCICR2 = 0x0C; // busy, so disarm else SCICR2 = 0x8C; // not busy, so arm } // Output ASCII character to Printer // spin if TxFifo is full void Printer_OutChar(char data){ while (TxFifo_Put(data) == 0){}; checkIC3(); } // TDRE set on empty transmit register interrupt 20 void SciHandler(void){ char data; if((SCICR2&0x80)&&(SCISR1&TDRE)){ if(TxFifo_Get(&data)){ SCIDRL = data; // clears TDRE } else{ SCICR2 = 0x2c; // disarm TDRE } } } // IC3 interrupt on any change of DTR void interrupt 11 IC3Han(void) { TFLG1 = 0x08; // Ack, clear C3F checkIC3(); // Arm SCI if DTR=+12 } // Program 7.3 C language implementation of a printer interface with DTR synchronization. // MC9S12C32 void DAC_Init(void){ // PM3=LD=1 DDRM |= 0x38; // PM5=CLK=SPI clock out PTM |= 0x08; // PM4=SRI=SPI master out /* bit SPICR1 7 SPIE = 0 no interrupts 6 SPE = 1 enable SPI 5 SPTIE= 0 no interrupts 4 MSTR = 1 master 3 CPOL = 0 output changes on fall, 2 CPHA = 0 clock normally low 1 SSOE = 0 PM3 regular output, LD 0 LSBF = 0 most sign bit first */ SPICR1 = 0x50; SPICR2 = 0x00; // normal mode SPIBR = 0x00;} // 2MHz //Program 7.4. C language initialization for a DAC interface using the SPI. // MC9S12C32 #define SPIF 0x80 void DAC_out(unsigned short code){ // better implementation using SPTEF unsigned char dummy; while((SPISR&SPTEF)==0); // wait for transmit empty SPIDR = (code>>8); // msbyte dummy = SPIDR; // clear SPIF while((SPISR&SPTEF)==0); // wait for transmit empty SPIDR = code; // lsbyte dummy = SPIDR; // clear SPIF Timer_Wait(10); // wait for SPI output completion PTM &= ~0x08; // PM3=LD=0 PTM |= 0x08; // PM3=LD=1 } //Program 7.5. C language function for a DAC interface using the SPI. // MC9S12C32 void ADC_Init(void){ // PM3=CS=1 DDRM |=0x38; // PM5=SCLK=SPI clock out DDRM &=~0x04; // PM2=DOUT=SPI master in PTM |= 0x08; // PM4=DIN=SPI master out /* bit SPICR1 7 SPIE = 0 no interrupts 6 SPE = 1 enable SPI 5 SPTIE= 0 no interrupts 4 MSTR = 1 master 3 CPOL = 0 output changes on fall, 2 CPHA = 0 clock normally low 1 SSOE = 0 PM3 regular output, LD 0 LSBF = 0 most sign bit first */ SPICR1 = 0x50; SPICR2 = 0x00; // normal mode SPIBR = 0x00;} // 2MHz //Program 7.6. C language initialization for an ADC interface using the SPI. // MC9S12C32, fixed unsigned short ADC_in(unsigned char code){ unsigned short data; unsigned char dummy; PTM &= ~0x08; // PM3=CS=0 while((SPISR&SPTEF)==0); // wait for transmit empty SPIDR = code; // set channel,mode while((SPISR&0x80)==0); // gadfly wait dummy = SPIDR; // clear SPIF SPIDR = 0; // start SPI while((SPISR&0x80)==0); // gadfly wait data = SPIDR<<8; // msbyte of ADC SPIDR = 0; // start SPI while((SPISR&0x80)==0); // gadfly wait data += SPIDR; // lsbyte of ADC PTM |= 0x08; // PM3=CS=1 return data>>3; // right justify } //Program 7.7. C language function for an ADC interface using the SPI. // Interface between MC9S12C32 and DS1620 using the SPI // bit status Configuration/Status Register meaning // 7 DONE 1=Conversion done, 0=conversion in progress // 6 THF 1=temperature above TH, 0=temperature below TH // 5 TLF 1=temperature below TL, 0=temperature above TL // 1 CPU 1=CPU control, 0=stand alone operation // 0 1SHOT 1=one conversion and stop, 0=continuous conversions // temperature digital value (binary) digital value (hex) // +125.0 C 011111010 $0FA // +64.0 C 010000000 $080 // +1.0 C 000000010 $002 // +0.5 C 000000001 $001 // 0 C 000000000 $000 // -0.5 C 111111111 $1FF // -16.0 C 111100000 $1E0 // -55.0 C 110010010 $192 void DS1620_Init(void){ // PM3=RST=0 DDRM |= 0x38; // PM5=CLK=SPI clock out PTM &=~0x08; // PM4=DQ=SPI bidirectional data /* bit SPICR1 7 SPIE = 0 no interrupts 6 SPE = 1 enable SPI 5 SPTIE= 0 no interrupts 4 MSTR = 1 master 3 CPOL = 1 output changes on fall 2 CPHA = 1 and input clocked in on rise 1 SSOE = 0 PM3 regular output DS1620 RST 0 LSBF = 1 least significant bit first */ SPICR1 = 0x5D; SPICR2 = 0x01; // bidirectional mode SPIBR = 0x01;} // 1MHz could be 2MHz //Program 7.8. C language initialization of a temperature sensor interface using the SPI. #define SPIF 0x80 void out8(char code){ unsigned char dummy; // assumes DDRM bit 4 is 1, output while((SPISR&SPTEF)==0); // wait for transmit empty SPIDR = code; while((SPISR&SPIF)==0); // gadfly wait for SPIF dummy = SPIDR;} // clear SPIF void out9(short code){ unsigned char dummy; while((SPISR&SPTEF)==0); // wait for transmit empty SPIDR = code; // lsbyte while((SPISR&SPIF)==0); // gadfly wait for SPIF dummy = SPIDR; // clear SPIF while((SPISR&SPTEF)==0); // wait for transmit empty SPIDR = (code>>8); // msbyte while((SPISR&SPIF)==0); // gadfly wait for SPIF dummy = SPIDR;} // clear SPIF unsigned char in8(void){ short n; unsigned char result; DDRM &=~0x10; // PM4=DQ input SPIDR = 0; // start shift register while((SPISR&SPIF)==0); // gadfly wait for SPIF result = SPIDR; // get data, clear SPIF DDRM |= 0x10; // PM4=DQ output return result;} short in9(void){ short result; DDRM &=~0x10; // PM4=DQ input while((SPISR&SPTEF)==0); // wait for transmit empty SPIDR = 0; // start shift register while((SPISR&SPIF)==0); // gadfly wait for SPIF result = SPIDR; // get LS data, clear SPIF while((SPISR&SPTEF)==0); // wait for transmit empty SPIDR = 0; // start shift register while((SPISR&SPIF)==0); // gadfly wait for SPIF if(SPIDR&0x01) // get MS data, clear SPIF result |= 0xFF00; // negative else result &=~0xFF00; // positive DDRM |= 0x10; // PM4=DQ output return result;} //Program 7.9. C language helper functions for a temperature sensor interface using the SPI. void DS1620_Start(void){ PTM |= 0x08; // RST=1 out8(0xEE); PTM &=~0x08;} // RST=0 void DS1620_WriteConfig(char data){ PTM |= 0x08; // RST=1 out8(0x0C); out8(data); PTM &=~0x08;} // RST=0 void DS1620_WriteTH(short data){ PTM |= 0x08; // RST=1 out8(0x01); out9(data); PTM &=~0x08;} // RST=0 void DS1620_WriteTL(short data){ PTM |= 0x08; // RST=1 out8(0x02); out9(data); PTM &=~0x08;} // RST=0 unsigned char DS1620_ReadConfig(void){ unsigned char value; PTM |= 0x08; // RST=1 out8(0xAC); value = in8(); PTM &=~0x08; // RST=0 return value;} unsigned short DS1620_ReadT(void){ unsigned short value; PTM |= 0x08; // RST=1 out8(0xAA); value = in9(); PTM &=~0x08; // RST=0 return value;} //Program 7.10. C language functions for a temperature sensor interface using the SPI. // Program 7.4. Three C functions to output a character using the SCI port. // 68HC812A4 SCI routines void init(void) { SC0BD=417; // 1200 baud SC0CR1=0x00; // 8data, 1stop SC0CR2=0x0C;} // enable gadfly #define RDRF 0x20 #define TDRE 0x80 #define TC 0x40 unsigned char insci(void){ while ((SC0SR1 & RDRF) == 0); return(SC0DRL); } void OutChar(unsigned char letter){ /* Wait for TDRE then output */ while ((SC0SR1 & TDRE) == 0); SC0DRL=letter; } void outsci2(unsigned char letter){ /* Output then wait for TDRE y */ SC0DRL=letter; while ((SC0SR1 & TDRE) == 0); } void outsci3(unsigned char letter){ /* Output then wait for TC */ SC0DRL=letter; while ((SC0SR1 & TC) == 0); } // Program 7.9. C language implementation of receiver interrupts. // MC68HC812A4 and MC68HC912B32 #pragma interrupt_handler SCIHAN() #define RDRF 0x20 // Executed on RDRF (not TDRE) void SCIhandler(void){ if((SC0SR1&0x20)!= RDRF) error(); if(SC0SR1&0x0F) error(); if(PutFifo(SC0DRL)) error(); } void RitualSCI(void){ asm(" sei"); SC0BD=104; // 4800 baud SC0CR1=0x00; // 8data, 1stop SC0CR2=0x2C; // Receiver intrpt CLRQ(); // Clear FIFO asm(" cli");} // Program 7.14. C functions for serial output using DTR synchronization. // MC68HC812A4 or MC68HC912B32 // PT3/IC3 is DTR void OutChar(unsigned char data) { while((PORTT&0x08)||((SC0SR1&0x80)==0)); SC0DRL= data; } // Program 7.15. C language helper function for serial output using DTR synchronization. // MC68HC812A4 or MC68HC912B32 // PT3/IC3 is DTR void checkIC3(void) { if(PORTT&0x08) // PT3=1 if DTR=-12 SC0CR2=0x0C; // SCI TxD disarmed else SC0CR2=0x8C;} // SCI TxD armed // Program 7.16. C language output function using DTR synchronization. int OutChar(unsigned char data) { unsigned char flag; flag=PutFifo(data^0x80); /* Bit7=1 is the first stop bit */ checkIC3(); /* Arm SCI if DTR=+12 */ return(flag);} /* error if FIFO is full */ // Program 7.17. C language ISR using DTR synchronization. // MC68HC812A4 or MC68HC912B32 // PT3/IC3 is DTR #pragma interrupt_handler IC3Han() void IC3Han(void) { TFLG1=0x08; // Ack clear C3F checkIC3();} // Arm SCI if DTR=+12 #pragma interrupt_handler SCIHAN() void SCIHan(void) { unsigned char data; if(GetFifo(&data);) SC0CR2=0x0C; // disarmed, empty else SC0DRL=data;} // output, ack // Program 7.18. C language initialization using DTR synchronization. // MC68HC812A4 or MC68HC912B32 // PT3/IC3 is DTR void Ritual(void){ asm(" sei"); InitFifo(); SC0BD=417; // 1200 baud SC0CR1=0x00; // 8 bit, 1 stop SC0CR2=0x0C; TIOS &= 0xF7; // PT3 input capture DDRT &= 0xF7; // PT3 is input TSCR = 0x80; // enable TCNT TMSK2= 0x32; // 500ns clock TCTL4 |= 0xC0; // both rise, fall TMSK1 |= 0x08; // Arm IC3 TFLG1=0x08; // initially clear asm(" cli");} // Program 7.19. C language initialization for a D/A interface using the SPI. // MC68HC812A4 or MC68HC912B32 void DACInit(void){ // PS7=LD=1 DDRS=0xE0; // PS6=CLK=SPI clock out PORTS=0x80; // PS5=SRI=SPI master out /* bit SP0CR1 7 SPIE = 0 no interrupts 6 SPE = 1 enable SPI 5 SWOM = 0 regular outputs 4 MSTR = 1 master 3 CPOL = 0 output changes on fall, 2 CPHA = 0 clock normally low 1 SSOE = 0 PS7 regular output, LD 0 LSBF = 0 most sign bit first */ SP0CR1=0x50; /* bit SP0CR2 3 PUPS = 0 no internal pullups 2 RDS = 0 regular drive 0 SPC0 = 0 normal mode */ SP0CR2=0x00; SP0BR=0x00;} // 4Mhz // Program 7.20. C language function for a D/A interface using the SPI. // MC68HC812A4 or MC68HC912B32 #define SPIF 0x80 void DACout(unsigned int code){ unsigned char dummy; SP0DR=0x00FF &(code>>8); // msbyte while((SP0SR&SPIF)==0); // gadfly wait dummy=SP0DR; // clear SPIF SP0DR=0x00FF& code; // lsbyte while((SP0SR&SPIF)==0); // gadfly wait dummy=SP0DR; // clear SPIF PORTS &= ~0x80; // PS7=LD=0 PORTS |= 0x80; } // PS7=LD=1 // Program 7.21. C language initialization for an A/D interface using the SPI. // MC68HC812A4 or MC68HC912B32 void ADCInit(void){ // PS7=CS=1 DDRS=0xE0; // PS6=SCLK=SPI clock out PORTS=0x80; // PS5=DIN=SPI master out /* bit SP0CR1 PS4=DOUT=SPI master in 7 SPIE = 0 no interrupts 6 SPE = 1 enable SPI 5 SWOM = 0 regular outputs 4 MSTR = 1 master 3 CPOL = 0 output changes on fall, 2 CPHA = 0 clock normally low 1 SSOE = 0 PS7 regular output, LD 0 LSBF = 0 most sign bit first */ SP0CR1=0x50; /* bit SP0CR2 3 PUPS = 0 no internal pullups 2 RDS = 0 regular drive 0 SPC0 = 0 normal mode */ SP0CR2=0x00; SP0BR=0x01;} // 2Mhz #define CH0 0x9F #define CH1 0xDF #define CH2 0xAF #define CH3 0xEF // Program 7.22. C language function for an A/D interface using the SPI. // MC68HC812A4 or MC68HC912B32 unsigned int ADCin(unsigned char code){ unsigned int data; PORTS&= ~0x80; // PS7=CS=0 SP0DR=code; // set channel,mode while((SP0SR&0x80)==0); // gadfly wait data=SP0DR; // clear SPIF SP0DR=0; // start SPI while((SP0SR&0x80)==0); // gadfly wait data=SP0DR<<8; // msbyte of A/D SP0DR=0; // start SPI while((SP0SR&0x80)==0); // gadfly wait data+=SP0DR; // lsbyte of A/D PORTS |= 0x80; // PS7=CS=1 return data>>3;} // right justify // Program 7.23. C language initialization of a temperature sensor interface using the SPI. // Interface between MC68HC812A4/MC68HC912B32 and DS1620 using the SPI // bit status Configuration/Status Register meaning // 7 DONE 1=Conversion done, 0=conversion in progress // 6 THF 1=temperature above TH, 0=temperature below TH // 5 TLF 1=temperature below TL, 0=temperature above TL // 1 CPU 1=CPU control, 0=stand alone operation // 0 1SHOT 1=one conversion and stop, 0=continuous conversions // temperature digital value (binary) digital value (hex) // +125.0 C 011111010 $0FA // +64.0 C 010000000 $080 // +1.0 C 000000010 $002 // +0.5 C 000000001 $001 // 0 C 000000000 $000 // -0.5 C 111111111 $1FF // -16.0 C 111100000 $1E0 // -55.0 C 110010010 $192 void DS1620Init(void){ // PS7=RST=0 DDRS=0xE0; // PS6=CLK=SPI clock out PORTS=0x60; // PS5=DQ=SPI bidirectional data /* bit SP0CR1 7 SPIE = 0 no interrupts 6 SPE = 1 enable SPI 5 SWOM = 0 regular outputs? 4 MSTR = 1 master 3 CPOL = 1 output changes on fall 2 CPHA = 1 and input clocked in on rise 1 SSOE = 0 PS7 regular output DS1620 RST 0 LSBF = 1 least significant bit first */ SP0CR1=0x5D; /* bit SP0CR2 3 PUPS = 0 no internal pullups 2 RDS = 0 regular drive 0 SPC0 = 1 bidirectional mode */ SP0CR2=0x01; SP0BR=0x02;} // 1MHz could be 2Mhz // Program 7.24. C language helper functions for a temperature sensor interface using the SPI. #define SPIF 0x80 void out8(char code){ unsigned char dummy; // assumes DDRS bit 5 is 1, output SP0DR=code; while((SP0SR&SPIF)==0); // gadfly wait for SPIF dummy=SP0DR;} // clear SPIF void out9(int code){ unsigned char dummy; SP0DR=0x00FF & code; // lsbyte while((SP0SR&SPIF)==0); // gadfly wait for SPIF dummy=SP0DR; // clear SPIF SP0DR=0x00FF&(code>>8); // msbyte while((SP0SR&SPIF)==0); // gadfly wait for SPIF dummy=SP0DR;} // clear SPIF unsigned char in8(void){ int n; unsigned char result; DDRS &= 0xDF; // PS5=DQ input SP0DR=0; // start shift register while((SP0SR&SPIF)==0); // gadfly wait for SPIF result=SP0DR; // get data, clear SPIF DDRS |= 0x20; // PS5=DQ output return result;} unsigned int in9(void){ unsigned int result; DDRS &= 0xDF; // PS5=DQ input SP0DR=0; // start shift register while((SP0SR&SPIF)==0); // gadfly wait for SPIF result=SP0DR; // get LS data, clear SPIF SP0DR=0; // start shift register while((SP0SR&SPIF)==0); // gadfly wait for SPIF if(SP0DR&0x01) // get MS data, clear SPIF result |= 0xFF00; // negative else result &= 0x00FF; // positive DDRS |= 0x20; // PS5=DQ output return result;} // Program 7.25. C language functions for a temperature sensor interface using the SPI. #define RST1 PORTS|=0x80; #define RST0 PORTS= 0x7F; void DS1620Start(void){ RST1 // RST=1 out8(0xEE); RST0} // RST=0 void DS1620WriteConfig(char data){ RST1 // RST=1 out8(0x0C); out8(data); RST0} // RST=0 void DS1620WriteTH(int data){ RST1 // RST=1 out8(0x01); out9(data); RST0} // RST=0 void DS1620WriteTL(int data){ RST1 // RST=1 out8(0x02); out9(data); RST0} // RST=0 unsigned char DS1620ReadConfig(void){ unsigned char value; RST1 // RST=1 out8(0xAC); value=in8(); RST0 // RST=0 return value;} unsigned int DS1620ReadT(void){ unsigned int value; RST1 // RST=1 out8(0xAA); value=in9(); RST0 // RST=0 return value;}