//****************************************************************** //* L6208 MOTOR DRIVER BOARD //* LAST UPDATED 01/24/2008 //* FIRMWARE BY FRED EADY FOR SERVO MAGAZINE //* CHANGES/ADDITIONS //****************************************************************** #include #include #include #include #include #include // Settings for PIC18F2620 __CONFIG(1,IESODIS & FCMDIS & RCIO); __CONFIG(2,BORDIS & PWRTDIS & WDTDIS); __CONFIG(3,MCLREN & LPT1DIS & PBDIGITAL); __CONFIG(4,DEBUGEN & LVPDIS & XINSTDIS & STVREN); __CONFIG(5,UNPROTECT); __CONFIG(6,WRTEN); __IDLOC(0124); //45 //90 unsigned int const sinetable1[] = {723,790,850,902,945,978,1002,1018,1023,1018,1002,978,945,902,850,790, //135 //0 723,648,568,482,391,296,199,100,0,100,199,296,391,482,568,648}; //135 //0 unsigned int const sinetable2[] = {723,648,568,482,391,296,199,100,0,100,199,296,391,482,568,648, //45 //+90 723,790,850,902,945,978,1002,1018,1023,1018,1002,978,945,902,850,790}; #define esc 0x1B //****************************************************************** //* FUNCTION PROTOTYPES //****************************************************************** void interrupt TIMERS(void); void putch(char c); unsigned int recvchar(void); unsigned int sendchar(unsigned int data); char CharInQueue(void); void cls(void); void init(void); void step_HALT(void); //****************************************************************** //* PIC18F2620 RAM Definitions //****************************************************************** unsigned int temp16,scratch16; char temp8,scratch8,bytein; char hundreds, tens, ones; //t = optional timer value //i = interrupt counter value unsigned int tmsecs1,tmsecs2,tmsecs3; char tsecs1,tsecs2,tsecs3,tmins1,tmins2,tmins3,thours1,thours2,thours3; unsigned int imsecs1,imsecs2,imsecs3; char isecs1,isecs2,isecs3,imins1,imins2,imins3,ihours1,ihours2,ihours3; char hours, mins, secs; char sinetable_index,direction,stepstate,pwm_lsbs; //****************************************************************** // MACROS AND PORT/PIN DEFINITIONS //****************************************************************** #define bitset(var, bitno) ((var) |= 1 << (bitno)) #define bitclr(var, bitno) ((var) &= ~(1 << (bitno))) #define make8(var,offset) ((unsigned int)var >> (offset * 8)) & 0x00FF #define make16(varhigh,varlow) (((unsigned int)varhigh & 0xFF)* 0x100) + ((unsigned int)varlow & 0x00FF) #define make32(var1,var2,var3,var4) \ ((unsigned long)var1<<24)+((unsigned long)var2<<16)+ \ ((unsigned long)var3<<8)+((unsigned long)var4) #define make32i(var1,var2) ((unsigned long)var1<<16)+((unsigned long)var2) //****************************************************************** //* GENERAL DEFINITONS //****************************************************************** #define act_led LATA7 //****************************************************************** //* STEPPER MOTOR DEFINITONS //****************************************************************** #define control LATC0 #define half_full LATC3 #define clock LATC4 #define ccw_cw LATC5 #define reset LATA3 #define enable LATA5 #define CW 1 #define CCW 0 #define step_CW ccw_cw = CW; \ direction = CW; #define step_CCW ccw_cw = CCW; \ direction = CCW; void step_HALT(void) { pwm_lsbs = (sinetable1[17] & 0x0003) << 4; CCP2CON = 0x0F; CCP2CON &= 0b11001111; CCP2CON |= pwm_lsbs; CCPR2L = sinetable1[17] >> 2; pwm_lsbs = (sinetable2[17] & 0x0003) << 4; CCP1CON = 0x0F; CCP1CON &= 0b11001111; CCP1CON |= pwm_lsbs; CCPR1L = sinetable2[17] >> 2; T2CON = 0x07; PR2 = 255; } //****************************************************************** //* INTERRUPT DEFINITIONS //****************************************************************** #define disable_RXint RCIE = 0 #define enable_RXint RCIE = 1 #define disable_TMR2int TMR2IE = 0 #define enable_TMR2int TMR2IE = 1 #define disable_TMR3int TMR3IE = 0 #define enable_TMR3int TMR3IE = 1 #define disable_TMR1int TMR1IE = 0 #define enable_TMR1int TMR1IE = 1 #define enable_GLOBALint IPEN = 0; \ GIE = 1; \ PEIE = 1; #define disable_GLOBALint IPEN = 0; \ GIE = 0; \ PEIE = 0; #define TIMER0ON TMR0ON = 1 #define TIMER0OFF TMR0ON = 0 #define TIMER1ON TMR1ON = 1 #define TIMER1OFF TMR1ON = 0 #define TIMER2ON TMR2ON = 1 #define TIMER2OFF TMR2ON = 0 #define TIMER3ON TMR3ON = 1 #define TIMER3OFF TMR3ON = 0 #define mdelay1(msecdelay) TIMER1OFF; \ TMR1IF = 0; \ imsecs1 = 0; \ tmsecs1 = 0; \ TIMER1ON; \ while(tmsecs1 < msecdelay); #define sdelay1(secdelay) TIMER1OFF; \ TMR1IF = 0; \ imsecs1 = 0; \ tmsecs1 = 0; \ isecs1 = 0; \ tsecs1 = 0; \ TIMER1ON; \ while(tsecs1 < secdelay); //****************************************************************** //* USART BUFFER DEFINITIONS //****************************************************************** #define BAUD 57600 //desired baud rate #define FOSC 32000000 //oscillator frequency #define DIVIDER ((unsigned int)(FOSC/(16 * BAUD) - 1)) //1,2,4,8,16,32,64,128 or 256 bytes #define USART_RX_BUFFER_SIZE 256 #define USART_RX_BUFFER_MASK ( USART_RX_BUFFER_SIZE - 1 ) // 1,2,4,8,16,32,64,128 or 256 bytes #define USART_TX_BUFFER_SIZE 256 #define USART_TX_BUFFER_MASK ( USART_TX_BUFFER_SIZE - 1 ) unsigned char USART_RxBuf[USART_RX_BUFFER_SIZE],USART_TxBuf[USART_TX_BUFFER_SIZE]; unsigned char USART_TxHead,USART_TxTail,USART_RxHead,USART_RxTail; void putch(char c) { while(!TRMT) // TRMT is set when TSR is empty continue; TXREG = c; // load the register } unsigned int recvchar(void) { unsigned char tmptail; // wait for incomming usart_data while ( USART_RxHead == USART_RxTail ); // calculate buffer index tmptail = ( USART_RxTail + 1 ) & USART_RX_BUFFER_MASK; USART_RxTail = tmptail; // store new index return USART_RxBuf[tmptail]; // return usart_data } unsigned int sendchar(unsigned int usart_data) { unsigned char tmphead; // calculate buffer index tmphead = ( USART_TxHead + 1 ) & USART_TX_BUFFER_MASK; // wait for free space in buffer while ( tmphead == USART_TxTail ); // store usart_data in buffer USART_TxBuf[tmphead] = (unsigned char)usart_data; USART_TxHead = tmphead; // store new index TXIE = 1; // enable TX interrupt return usart_data; } unsigned char CharInQueue(void) { return(USART_RxHead != USART_RxTail); } //****************************************************************** //* Init USART Function //****************************************************************** void init_EUSART(void) { SPBRG = DIVIDER; //load baud rate divisor-calc didn't work here TRISC7 = 1; //receive pin TRISC6 = 0; //transmit pin TXSTA = 0x04; //high speed baud rate RCSTA = 0x80; //enable serial port and serial port pins USART_RxTail = 0x00; //flush receive buffer USART_RxHead = 0x00; USART_TxTail = 0x00; //flush transmit buffer USART_TxHead = 0x00; RCIP = 1; //receive interrupt = high priority TXIP = 1; //transmit interrupt = high priority RCIE = 1; //enable receive interrupt PEIE = 1; //enable all unmasked peripheral interrupts GIE = 1; //enable all unmasked interrupts CREN = 1; //enable USART1 receiver TXIE = 0; //disable USART1 transmit interrupt TXEN = 1; //transmitter enabled } //****************************************************************** //* INTERRUPT HANDLER ROUTINE //****************************************************************** void interrupt TIMERS(void) { unsigned char usart_data,tmphead,tmptail; if((TMR3IF && TMR3IE)) { TMR3IF = 0; TMR3H = 0xE0; TMR3L = 0xC1; ++tmsecs3; if(++imsecs3 == 1000) { imsecs3 = 0; ++isecs3; ++tsecs3; act_led ^= 1; } if(isecs3 == 60) { isecs3 = 0; ++imins3; ++tmins3; } if(imins3 == 60) { imins3 = 0; ++ihours3; } } if((TMR1IF && TMR1IE)) { TMR1IF = 0; TMR1H = 0xE0; TMR1L = 0xC1; ++tmsecs1; if(++imsecs1 == 1000) { imsecs1 = 0; ++isecs1; ++tsecs1; } if(isecs1 == 60) { isecs1 = 0; ++imins1; ++tmins1; } if(imins1 == 60) { imins1 = 0; ++ihours1; } } //SERVICE THE EUSART if(RCIF) { usart_data = RCREG; // read the received usart_data // calculate buffer index tmphead = ( USART_RxHead + 1 ) & USART_RX_BUFFER_MASK; USART_RxHead = tmphead; // store new index if ( tmphead == USART_RxTail ) { // ERROR! Receive buffer overflow } USART_RxBuf[tmphead] = usart_data; // store received usart_data in buffer } if(TRMT) { // check if all usart_data is transmitted if ( USART_TxHead != USART_TxTail ) { // calculate buffer index tmptail = ( USART_TxTail + 1 ) & USART_TX_BUFFER_MASK; USART_TxTail = tmptail; // store new index TXREG = USART_TxBuf[tmptail]; // start transmitiON } else { TXIE = 0; // disable TX interrupt } } } //**************************************************************************** //* INITIALIZE ROUTINE //**************************************************************************** void init() { //**************************************************************************** //* INITIALIZE CLOCK AND IO PORTS //**************************************************************************** OSCCON = 0x70; PLLEN = 1; TRISA = 0b01010111; TRISB = 0b11111111; TRISC = 0b10000000; //****************************************************************** //* CONFIGURE A2D AND COMPARATORS //****************************************************************** ADCON1 = 0b00001111; ADON = 0; CMCON = 0x07; //****************************************************************** //* INITIALIZE L6208 //****************************************************************** reset = 0; clock = 0; half_full = 1; control = 1; step_CW; TIMER2OFF; pwm_lsbs = (sinetable1[0] & 0x0003) << 4; CCP2CON = 0x0F; CCP2CON &= 0b11001111; CCP2CON |= pwm_lsbs; CCPR2L = sinetable1[0] >> 2; pwm_lsbs = (sinetable2[0] & 0x0003) << 4; CCP1CON = 0x0F; CCP1CON &= 0b11001111; CCP1CON |= pwm_lsbs; CCPR1L = sinetable2[0] >> 2; T2CON = 0x07; PR2 = 255; TIMER2ON; reset = 1; //****************************************************************** //* INITIALIZE EUSART //****************************************************************** init_EUSART(); //****************************************************************** //* CONFIGURE AND START TIMER1 //* SET TO OVERFLOW EVERY 1mS //****************************************************************** //F831 = 8MHz //E0C1 = 32MHz TIMER1OFF; T1CON = 0b00000000; TMR1H = 0xF8; TMR1L = 0x31; TIMER1ON; //****************************************************************** //* CONFIGURE AND START TIMER3 //* SET TO OVERFLOW EVERY 1mS //****************************************************************** TIMER3OFF; ihours3 = 12; imins3 = 0; isecs3 = 0; imsecs3 = 0; T3CON = 0x00; TMR3H = 0xE0; TMR3L = 0xC1; //TIMER3ON ; //****************************************************************** //* CONFIGURE EXTERNAL INTERRUPTS //****************************************************************** enable_TMR1int; //enable_TMR3int; enable_GLOBALint; //****************************************************************** //* INITIALIZE STEPPER STATE COUNTER //****************************************************************** stepstate = 0xE0; } void main(void) { //****************************************************************** //* INITIALIZE //****************************************************************** init(); enable = 1; /* while(1) { step_CW; for(temp16=0;temp16<1000;++temp16) { clock = 0; mdelay1(1); clock = 1; mdelay1(1); } step_CCW; for(temp16=0;temp16<1000;++temp16) { clock = 0; mdelay1(1); clock = 1; mdelay1(1); } } */ //****************************************************************** //* MAIN SERVICE LOOP //****************************************************************** do{ clock = 0; reset = 1; mdelay1(1); switch(direction) { case CW: if(++stepstate == 0x0000) { reset = 0; stepstate = 0xE0; } sinetable_index = stepstate & 0b00011111; if((sinetable_index & 0b00001110) == 8) { clock = 1; } pwm_lsbs = (sinetable1[sinetable_index] & 0x0003) << 4; CCP2CON &= 0b11001111; CCP2CON |= pwm_lsbs; CCPR2L = sinetable1[sinetable_index] >> 2; pwm_lsbs = (sinetable2[sinetable_index] & 0x0003) << 4; CCP1CON &= 0b11001111; CCP1CON |= pwm_lsbs; CCPR1L = sinetable2[sinetable_index] >> 2; mdelay1(1); break; case CCW: if(--stepstate == 0x0000) { reset = 0; stepstate = 0xE0; } sinetable_index = stepstate & 0b00011111; if(((sinetable_index + 1) & 0b00001110) == 8) { clock = 1; } pwm_lsbs = (sinetable1[sinetable_index] & 0x0003) << 4; CCP2CON &= 0b11001111; CCP2CON |= pwm_lsbs; CCPR2L = sinetable1[sinetable_index] >> 2; pwm_lsbs = (sinetable2[sinetable_index] & 0x0003) << 4; CCP1CON &= 0b11001111; CCP1CON |= pwm_lsbs; CCPR1L = sinetable2[sinetable_index] >> 2; break; } }while(1); }