//****************************************************************** //* MAXBOTIX DRIVER //* LAST UPDATED 04/14/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(0414); //****************************************************************** //* FUNCTION PROTOTYPES //****************************************************************** void interrupt MEASURE(void); void init(void); void reset_TIMER1(void); void putch(char c); unsigned int recvchar(void); unsigned int sendchar(unsigned int data); char CharInQueue(void); void initEUSART(void); //****************************************************************** //* PIC18F2620 RAM Definitions //****************************************************************** unsigned int temp16,pulsewidth,pulsestart,pulseend,distance; unsigned int analogdistance; char usart_data,tmphead,tmptail; //****************************************************************** // 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 LATA5 #define RX LATB0 #define BW LATB1 //****************************************************************** //* 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 disable_TMR0int TMR0IE = 0 #define enable_TMR0int TMR0IE = 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 typedef struct { char rising_edge:1; char captured:1; } FFlags; FFlags flags; FFlags pwbits; //just for fun //****************************************************************** //* EUSART BUFFER DEFINITIONS //****************************************************************** #define BAUD 9600 //desired baud rate #define FOSC 4000000 //oscillator frequency #define DIVIDER ((unsigned int)(FOSC/(16 * BAUD) - 1)) //1,2,4,8,16,32,64,128 or 256 bytes #define EUSART_RX_BUFFER_SIZE 256 #define EUSART_RX_BUFFER_MASK ( EUSART_RX_BUFFER_SIZE - 1 ) // 1,2,4,8,16,32,64,128 or 256 bytes #define EUSART_TX_BUFFER_SIZE 256 #define EUSART_TX_BUFFER_MASK ( EUSART_TX_BUFFER_SIZE - 1 ) unsigned char EUSART_RxBuf[EUSART_RX_BUFFER_SIZE],EUSART_TxBuf[EUSART_TX_BUFFER_SIZE]; unsigned char EUSART_TxHead,EUSART_TxTail,EUSART_RxHead,EUSART_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 ( EUSART_RxHead == EUSART_RxTail ); // calculate buffer index tmptail = ( EUSART_RxTail + 1 ) & EUSART_RX_BUFFER_MASK; EUSART_RxTail = tmptail; // store new index return EUSART_RxBuf[tmptail]; // return usart_data } unsigned int sendchar(unsigned int usart_data) { unsigned char tmphead; // calculate buffer index tmphead = ( EUSART_TxHead + 1 ) & EUSART_TX_BUFFER_MASK; // wait for free space in buffer while ( tmphead == EUSART_TxTail ); // store usart_data in buffer EUSART_TxBuf[tmphead] = (unsigned char)usart_data; EUSART_TxHead = tmphead; // store new index TXIE = 1; // enable TX interrupt return usart_data; } unsigned char CharInQueue(void) { return(EUSART_RxHead != EUSART_RxTail); } //****************************************************************** //* Init EUSART Function //****************************************************************** void init_EUSART(void) { SPBRG = 25; //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 EUSART_RxTail = 0x00; //flush receive buffer EUSART_RxHead = 0x00; EUSART_TxTail = 0x00; //flush transmit buffer EUSART_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 EUSART1 receiver TXIE = 0; //disable EUSART1 transmit interrupt TXEN = 1; //transmitter enabled } //**************************************************************************** //* INITIALIZE ROUTINE //**************************************************************************** void init() { //**************************************************************************** //* INITIALIZE CLOCK AND IO PORTS //**************************************************************************** OSCCON = 0x60; PLLEN = 0; TRISA = 0b11011111; TRISB = 0b11111100; TRISC = 0b10111111; RX = 0; BW = 0; flags.rising_edge = 1; flags.captured = 0; //**************************************************************************** //* INITIALIZE TIMER1 //**************************************************************************** T1CON = 0b00000000; //1:1 prescale //****************************************************************** //* CONFIGURE A2D AND COMPARATORS //****************************************************************** ADCON0 = 0b00000000; ADCON1 = 0b00001110; ADCON2 = 0b10111111; ADON = 1; CMCON = 0x07; //**************************************************************************** //* INITIALIZE USART //**************************************************************************** init_EUSART(); //****************************************************************** //* CONFIGURE INTERRUPTS //****************************************************************** disable_GLOBALint; } void interrupt MEASURE(void) { if(CCP1IE && CCP1IF) { //interrupt caused by rising edge of PW if(flags.rising_edge) { pulsestart = make16(CCPR1H,CCPR1L); CCP1CON = 0b00000100; //capture falling edge flags.rising_edge = 0; } else //interrupt caused by falling edge of PW { pulseend = make16(CCPR1H,CCPR1L); CCP1CON = 0b00000101; //capture rising edge flags.rising_edge = 1; flags.captured = 1; } CCP1IF = 0; //clear the CCP1 interrupt flag } //SERVICE THE EEUSART if(RCIF) { usart_data = RCREG; // read the received usart_data // calculate buffer index tmphead = ( EUSART_RxHead + 1 ) & EUSART_RX_BUFFER_MASK; EUSART_RxHead = tmphead; // store new index if ( tmphead == EUSART_RxTail ) { // ERROR! Receive buffer overflow } EUSART_RxBuf[tmphead] = usart_data; // store received usart_data in buffer } if(TRMT) { // check if all usart_data is transmitted if ( EUSART_TxHead != EUSART_TxTail ) { // calculate buffer index tmptail = ( EUSART_TxTail + 1 ) & EUSART_TX_BUFFER_MASK; EUSART_TxTail = tmptail; // store new index TXREG = EUSART_TxBuf[tmptail]; // start transmitiON } else { TXIE = 0; // disable TX interrupt } } } void reset_TIMER1(void) { TMR1H = 0; TMR1L = 0; TIMER1ON; } //****************************************************************** //* MAIN SERVICE LOOP //****************************************************************** void main(void) { init(); //allow ultrasonic rangefinder to calibrate RX = 1; for(temp16=0;temp16<0xFF;++temp16){NOP();} RX = 0; CCP1CON = 0b00000101; //capture rising edge CCP1IE = 1; //enable capture interrupt CCP1IF = 0; //clear capture interrupt flag reset_TIMER1(); //initialize TIMER1 and start it do{ enable_GLOBALint; //enable interrupts RX = 1; //kick off a ranging cycle //while(1); //uncomment this to run continuous RS232 cycle do{ GODONE = 1; while(GODONE); //wait for a2d conversion to end }while(!flags.captured); disable_GLOBALint; //disable interrupts RX = 0; //cease ranging //compute pulsewidth and distance in inches pulsewidth = pulseend - pulsestart; // in microseconds distance = pulsewidth / 147; //147uS = 1 inch analogdistance = make16(ADRESH,ADRESL); flags.captured = 1; //do it all again reset_TIMER1(); }while(1); }