?? chap8.c
字號:
// Chapter 8 6811 C programs// Jonathan W. Valvano// This software accompanies the book,// Embedded Microcomputer Systems: Real Time Interfacing// published by Brooks Cole, 1999// Program 8.1. The MC68HC812A4 Port J initialization.// MC68HC812A4 only// Program 8.3. Switch debouncing using C software.// MC68HC11A8void WaitPress(void){ while (PORTA&0x01); // Loop here until switch is pressed TOC5=TCNT+20000; // 10ms delay TFLG1=0x08; // Clear OC5F while((TFLG1&0x08)==0);} // wait for switch to stop bouncingvoid WaitRelease(void){ while ((PORTA&0x01)==0); // Loop here until switch is released TOC5=TCNT+20000; // 10ms delay TFLG1=0x08; // Clear OC5F while((TFLG1&0x08)==0); } // wait for switch to stop bouncing// no ritual required// Program 8.5. Another example of switch debouncing using C software.// MC68HC11A8unsigned char ReadPA0(void){unsigned char old; old=PORTA&0x01; // Current value TOC5=TCNT+20000; // 10ms delay TFLG1=0x08; // Clear OC5F while((TFLG1&0x08)==0){ // unchanged for 10ms? if(old<>(PORTA&0x01)){ // changed? old=PORTA&0x01; // New value TOC5=TCNT+20000; // restart delay TFLG1=0x08; } // Clear OC5F } return(old);}// no ritual required//Program 8.6. Switch debouncing using interrupts in C software.// MC68HC11A8// counts the number of button pushes// signal connected to IC3=PA0unsigned int count; // times pushed#define wait 20000 // bounce wait (cyc) #pragma interrupt_handler TOC5handler()void TOC5handler(void){ TMSK1=0x01; // Arm IC3, disarm OC5 TFLG1=0x01; // clear IC3F if(PORTA&0x01==0) count++;} // new count if PA0=0 #pragma interrupt_handler TIC3handler()void TIC3handler(void){ TMSK1=0x08; // Disarm IC3, Arm OC5 TOC5=TCNT+wait; TFLG1=0x08;} // clear OC5F void Ritual(void){ asm(" sei"); // make atomic TMSK1=0x01; // Arm IC3, disarm OC5 TFLG1=0x01; // clear IC3F TCTL2 = 0x01; // IC3F set on rising count=0; asm(" cli"); }// Program 8.7. Another example of switch debouncing using interrupts in C software.// MC68HC11A8// counts the number of button pushes// signal connected to IC3=PA0unsigned int count; // times pushedchar LastState; // looking for touch?// true means open, looking for a touch// false means closed, looking for release #define wait 20000 // bounce wait (cyc) #pragma interrupt_handler TOC5handler()void TOC5handler(void){ TMSK1=0x01; // Arm IC3, disarm OC5 TFLG1=0x01;} // clear IC3F #pragma interrupt_handler TIC3handler()void TIC3handler(void){ if(LastState){ count++; // a touch has occurred LastState=0;} else LastState=1; // release occurred TMSK1=0x08; // Disarm IC3, Arm OC5 TOC5=TCNT+wait; TFLG1=0x08;} // clear OC5F void Ritual(void){ asm(" sei"); // make atomic TMSK1=0x01; // Arm IC3, disarm OC5 TFLG1=0x01; // clear IC3F TCTL2 = 0x01; // IC3F set on rising count=0; LastState=PORTA&0x01; asm(" cli"); }// Program 8.9. C software interface of a direct connection keyboard.// MC68HC11A8unsigned int KEY; // current pattern #define wait 20000 // bounce time (cyc)void Ritual(void){ asm(" sei"); // make atomic TMSK1=0x00; // Disarm OC5 DDRC=0; // PortC are inputs from the keyboard PIOC=0x54; // Input hndshk, fall, arm, STRB neg pulse KeyBoard(); // Initially read asm(" cli"); }void KeyBoard(void){ dummyRead=PIOC; // read status KEY=(PORTE<<8)+PORTCL;} // Set global, clear STAF#pragma interrupt_handler IRQhandler()void IRQhandler(void){ PIOC=0x14; // Disarm STAF TMSK1=0x08; // Arm OC5 TOC5=TCNT+wait; TFLG1=0x08;} // clear OC5F#pragma interrupt_handler TOC5handler()void TOC5handler(void){ TMSK1=0x00; // Disarm OC5 PIOC=0x54; // Rearm STAF KeyBoard();} // Read keys, set LS374's// Program 8.10. C software interface of a direct connection keyboard using periodic polling.// MC68HC11A8unsigned int Key; // current pattern #define period 20000 // 10ms pollingunsigned int KeyBoard(void){ return((PORTE<<8)+PORTC);} // patternvoid Ritual(void){ asm(" sei"); // make atomic DDRC=0; // inputs from keyboard Key=KeyBoard(); // read 16 keys TMSK1=0x08; // Arm OC5 TOC5=TCNT+period; TFLG1=0x08; // clear OC5F asm(" cli"); }#pragma interrupt_handler TOC5handler()void TOC5handler(void){ Key=KeyBoard(); // Current pattern TOC5=TOC5+period; TFLG1=0x08;} // ack OC5F // Program 8.12. C software interface of a matrix scanned keyboard.// MC68HC11A8const struct Row{ unsigned char out; unsigned char keycode[4];}#typedef const struct Row RowType;RowType ScanTab[5]={{ 0x70, "abcd" },{ 0xB0, "efgh" },{ 0xD0, "ijkl" },{ 0xE0, "mnop" },{ 0x00, " " }};void Ritual(void){ // PC3-PC0 are inputs PIOC=0x40; // CWOM=1 DDRC=0xF0;} // PC7-PC4 are outputs/* Returns ASCII code for key pressed, Num is the number of keys pressed both equal zero if no key pressed */unsigned char Scan(unsigned int *Num){ RowType *pt; unsigned char column,key; int j; (*Num)=0; key=0; // default values pt=&ScanTab[0]; while(pt->out){ PORTC=pt->out; // select row column=PORTC; // read columns for(j=3; j>=0; j--){ if((column&0x01)==0){ key=pt->keycode[j]; (*Num)++;} column>>=1;} // shift into position pt++; } return key;}// Program 8.14. C software interface of a multiplexed keyboard.// MC68HC11A8// PC7-PC4 row output // PC3-PC0 column inputs unsigned char Key; // current pattern unsigned char PreviousKey; // 10ms ago #define period 20000 // 10 ms unsigned char KeyScan(void){ unsigned char key,row; key=0; // means no key pressed for(row=0;row<16;row++){ PORTC=row<<4; // Select row if((PORTC&0x0F)!=0x0F){ key=PORTC^0x0F; }} return(key);}void Ritual(void){ asm(" sei"); // make ritual atomic DDRC=$F0; PreviousKey=Key=KeyScan(); // read TMSK1|=0x08; // Arm OC5 TOC5=TCNT+wait; TFLG1=0x08; // clear OC5F asm(" cli"); }#pragma interrupt_handler TOC5handler()void TOC5handler(void){ unsigned char NewKey; NewKey=KeyScan(); // Current pattern if(NewKey==PreviousKey) Key=NewKey; PreviousKey=NewKey; TOC5=TOC5+period; TFLG1=0x08;} // ack OC5F// Program 8.15. C software interface of a scanned LED display.// MC68HC11A8// PB7-PB0 output, 7 bit pattern // PC2-PC0 output, selects LED digit unsigned char code[3]; // binary codesstatic unsigned char select[3]={4,2,1};unsigned int index; // 0,1,2#define OC5F 0x08#pragma interrupt_handler TOC5handler()void TOC5handler(void){ TFLG1=OC5F; // Acknowledge TOC5=TOC5+10000; // every 5 ms PORTC=select[index]; // which LED? PORTB=code[index]; // enable if(++index==3) index=0;}void ritual(void) { asm(" sei"); // make atomic index=0; DDRC=0xFF; // outputs TMSK1|=OC5F; // Arm OC5 TFLG1=OC5F; // clear OC5F TOC5=TCNT+10000; asm(" cli"); }// Program 8.16. C software interface of a multiplexed LED display.// MC68HC11A8unsigned int global; // 12 bit packed BCDconst struct LED{ unsigned char enable; // select unsigned char shift; // bits to shift const struct LED *Next; }; // Link#typedef const struct LED LEDType;#typedef LEDType * LEDPtr;LEDType LEDTab[3]={{ 0x04, 8, &LEDTab[1] }, // Most sig{ 0x02, 4, &LEDTab[2] },{ 0x01, 0, &LEDTab[0] }}; // least sigLEDPtr Pt; // Points to current digit#define OC5F 0x08#pragma interrupt_handler TOC5handler()void TOC5handler(void){ TFLG1=OC5F; // Acknowledge TOC5=TOC5+10000; // every 5 ms PORTB=(Pt->enable) +(global>>(pt->shift))<<4); Pt=Pt->Next; }void ritual(void) { asm(" sei"); // make atomic global=0; TMSK1=OC5F; // Arm OC5 Pt=&LEDTab[0]; TFLG1=OC5F; // clear OC5F */ TOC5=TCNT+10000; asm(" cli"); }// Program 8.17. C software interface of an integrated LED display.// MC68HC11A8// PD3/MOSI = MC14489 DATA IN// PD4/SCLK = MC14489 CLOCK IN// PD5 (simple output) = MC14489 ENABLEvoid ritual(void) { DDRD |= 0x38; // outputs to MC14489 SPCR=0x50; // bit meaning// 7 SPIE=0 no interrupts// 6 SPE=1 SPI enable// 5 DWOM=0 regular outputs// 4 MSTR=1 master// 3 CPOL=0 match timing with MC14489// 2 CPHA=0// 1 SPR1=0 E/2 is 1Mhz SCLK// 0 SPR0=0 PORTD|= 0x20; // ENABLE=1 PORTD&= 0xDF; // ENABLE=0 SPDR=0x01; // hex format while(SPSR&0x80)==0){}; PORTD|=0x20;} // ENABLE=1void LEDout(unsigned char data[3]){// 24 bit packed BCD PORTD &= 0xDF; // ENABLE=0 SPDR = data[2]; // send MSbyte while(SPSR&0x80)==0){}; SPDR = data[1]; // send middle byte while(SPSR&0x80)==0){}; SPDR = data[0]; // send LSbyte while(SPSR&0x80)==0){}; PORTD |= 0x20;} // ENABLE=1// Program 8.18. Helper function for a simple LCD display.void LCDOutDigit(unsigned char position, unsigned char data) { // position is 0x80, 0x40, 0x20, or 0x10 and data is the BCD digit PORTB=0x0F&data; // set BCD digit on the A-D inputs of the MC14543B PORTB|=position; // toggle one of the LD inputs high PORTB=0x0F&data;} // LD=0, latch digit into MC14543B// Program 8.19. C software interface of a simple LCD display.void LCDOutNum(unsigned int data){ unsigned int digit,num,i; unsigned char pos; num=min(data,9999); // data should be unsigned from 0 to 9999 pos=0x10; // position of first digit (ones) for(i=0;i<4;i++){ digit=num%10; num=num/10; // next BCD digit 0 to 9 LCDOutDigit(pos,digit); pos=pos<<1;}}// Program 8.20. Bit-banged interface to a scanned LCD display.void LCDOut (unsigned char *pt) {unsigned int i; unsigned char mask; for(i=0;i<6;i++){ for(mask=0x80;mask;mask=mask>>1){ // look at bits 7,6,5,4,3,2,1,0 if((*pt)&mask) PORTB=1; else PORTB=0; // Serial data of the MC145000 PORTB|=2; // toggle the serial clock first high PORTB&=0xFD;} // then low pt++; }}// Program 8.21. SPI interface to a scanned LCD display using a MC145000.// MC68HC11A8// PD3/MOSI = MC145000 DATA IN// PD4/SCLK = MC145000 CLOCK INvoid ritual(void) { DDRD |= 0x18; // outputs to MC145000 SPCR=0x50; }// bit meaning// 7 SPIE=0 no interrupts// 6 SPE=1 SPI enable// 5 DWOM=0 regular outputs// 4 MSTR=1 master// 3 CPOL=0 match timing with MC14489// 2 CPHA=0// 1 SPR1=0 E/2 is 1Mhz SCLK// 0 SPR0=0 void LCDout(unsigned char data[6]){ unsigned int j; for(j=5; j>=0 ; j--){ SPDR = data[j]; // Msbyte first while(SPSR&0x80)==0){};}}// Program 8.22. Private functions for an HD44780 controlled LCD display.// MC68HC11A8// 1 by 16 char LCD Display (HD44780)// ground = pin 1 Vss// power = pin 2 Vdd +5v// 10Kpot = pin 3 Vlc contrast adjust// PB2 = pin 6 E enable// PB1 = pin 5 R/W 1=read, 0=write// PB0 = pin 4 RS 1=data, 0=control// PC0-7 = pins7-14 DB0-7 8 bit data#define LCDdata 1 // PB0=RS=1#define LCDcsr 0 // PB0=RS=0#define LCDread 2 // PB1=R/W=1#define LCDwrite 0 // PB1=R/W=0#define LCDenable 4 // PB2=E=1#define LCDdisable 0 // PB2=E=0void LCDcycwait(unsigned short cycles){ TOC5=TCNT+cycles; // 500ns cycles TFLG1 = 0x08; // clear C5F while((TFLG1&0x08)==0){};}// Program 8.23. Public functions for an HD44780 controlled LCD display.// MC68HC11A8void LCDputchar(unsigned short letter){// letter is ASCII code PORTC=letter; PORTB=LCDdisable+LCDwrite+LCDdata; PORTB=LCDenable+LCDwrite+LCDdata; // E goes 0,1 PORTB=LCDdisable+LCDwrite+LCDdata; // E goes 1,0 LCDcycwait(80);} // 40 us waitvoid LCDputcsr(unsigned short command){ PORTC=command; PORTB=LCDdisable+LCDwrite+LCDcsr; PORTB=LCDenable+LCDwrite+LCDcsr; // E goes 0,1 PORTB=LCDdisable+LCDwrite+LCDcsr; // E goes 1,0 LCDcycwait(80);} // 40 us waitvoid LCDclear(void){ LCDputcsr(0x01); // Clear Display LCDcycwait(3280); // 1.64ms wait LCDputcsr(0x02); // Cursor to home LCDcycwait(3280);} // 1.64ms waitvoid LCDinit(void){ DDRC=0xFF; LCDputcsr(0x06); // I/D=1 Increment, S=0 nodisplayshift LCDputcsr(0x0C); // D=1 displayon, // C=0 cursoroff, B=0 blinkoff LCDputcsr(0x14); // S/C=0 cursormove, R/L=0 shiftright LCDputcsr(0x30); // DL=1 8bit, N=0 1 line, F=0 5by7dots LCDclear();} // clear display// Program 8.27. C linked list and helper functions used to control the stepper motor.const struct State{ unsigned char Out; /* Output for this state */ const struct State *Next[2]; /* Next state CW or CCW motion */};#typedef struct State StateType;#typedef StateType * StatePtr;unsigned char POS; /* between 0 and 199 representing shaft angle */#define clockwise 0 /* Next index*/#define counterclockwise 1 /* Next index*/StateType fsm[4]={ {10,{&fsm[1],&fsm[3]}}, { 9,{&fsm[2],&fsm[0]}}, { 5,{&fsm[3],&fsm[1]}}, { 6,{&fsm[0],&fsm[2]}}};StatePtr Pt; /* Current State */void CW(void){ Pt=Pt->Next[clockwise]; /* circulates around linked list */ PORTB=Pt->Out; /* step motor */ if(POS++==200) POS=0;} /* maintain shaft angle */ void CCW(void){ Pt=Pt->Next[counterclockwise]; /* circulates around linked list*/ PORTB=Pt->Out; /* step motor */ if(POS==0)POS=199; else POS--; } /* maintain shaft angle */void Init(void){ POS=0; Pt=&fsm[0];}// Program 8.28. High-level C function to control the stepper motor.void SEEK(unsigned char New){ int CWsteps,i; if((CWsteps=New-POS)<0) CWsteps+=200; if(CWsteps>100) for(i=CWsteps;i<200;i++) CCW(); else for(i=0;i<CWsteps;i++) CW(); }
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -