;*************************************************************************** ;Dbt_kybd_echo_mstr ;This program exercises I2C bus in several ways: ; sends an opening message to the hand controller ; on interrupt receives a digit from the Hand Controller, ; stores it, and echoes it back. ;Routines can be embedded into any program to provide user control of AGV. ;TJW 20.7.05 Tested and working 21.7.05 ;*************************************************************************** ;Clock is 4MHz ; list p=16F873A #include p16f873A.inc ; ;Set Configuration Word: crystal oscillator HS, WDT off, ; power-up timer on, code protect off, LV Program off. __CONFIG _HS_OSC & _WDT_OFF & _PWRTE_ON & _LVP_OFF ; ;Specify RAM delcntr1 equ 20 ;used in delay5 & delayADC SRs delcntr2 equ 21 temp equ 22 ;a temp location, to be used only in consecutive instructions I2C_RX_word equ 23 ;holds most recent I2C word recd I2C_add equ 24 ;holds address used in I2C message I2C_TX_word equ 25 ;holds word to be transmitted on I2C pointer equ 26 ;table pointer for strings to lcd ;Specify some port bits ;For Port A mot_en_rt equ 2 mot_en_left equ 5 ;For Port B sounder equ 1 ;piezo electric sounder us_rt equ 6 ;right microswitch us_left equ 7 ;left microswitch ;For PortC mot_left equ 1 ;left motor direction bit, 1=forward mot_rt equ 2 ;right motor direction bit led_rt equ 5 ;diagnostic led led_left equ 6 ;diagnostic led mode equ 7 ;mode switch org 00 goto start ; org 04 goto Interrupt_SR ;Initialise SFRs in Bank 1 start bcf status,rp1 bsf status,rp0 ;select memory bank 1 movlw B'00001011' ;set port A bits according to their function movwf trisa movlw B'11001001' ;also port B bits movwf trisb movlw B'10011000' ;set port C bits, I2C bits are both set as ip movwf trisc movlw B'01011100' movwf adcon1 ;select port A bits 0,1,3 for analog input movlw 07 ;set up 125kHz baud rate movwf sspadd ;Initialise SFRs in Bank 0 bcf status,rp0 movlw B'00101000' ;SSPCON1:MSSP on, I2C Master movwf sspcon ; ;Switch all outputs off movlw 00 movwf porta movwf portb movwf portc ;diagnostic, flash leds bsf portc,6 bsf portc,5 call delay500 bcf portc,6 bcf portc,5 call delay500 ;extra delay ;Send opening string clrf pointer movlw 0a4 ;send slave address, R/W is write movwf I2C_add call I2C_send_add loop_str1 movf pointer,0 call table1 movwf I2C_TX_word sublw 0ff ;test and move on if end marker reached btfsc status,z goto string_end call I2C_send_word incf pointer,1 call delay1 ;give LCD time to write call delay1 call delay1 goto loop_str1 string_end call I2C_send_stop ;Enable interrupts bcf intcon,intf ;clear pending interrupts bsf intcon,inte ;enable external interrupt bsf intcon,gie ;Wait for interrupts from Hand Controller loop goto loop ; ;******************************************************************* ;ISR. On external interrupt, SSP reads byte from Hand Controller, ;and echoes it back, ie two I2C messages. ;Received Byte stored in I2C_word for further action. ;******************************************************************* Interrupt_SR bsf portc,6 ;diagnostic ;Start new I2C message, requesting word from slave. movlw 0a5 ;this is slave address, R/W is read movwf I2C_add call I2C_send_add ;now wait for byte to come in call I2C_rec_word call I2C_send_stop bcf status,rp0 call delay20u ;Now echo byte - start new message movlw 0a4 ;this is slave address, R/W is write movwf I2C_add call I2C_send_add ;send the echoed character movf I2C_RX_word,0 ;move received word to transmit store movwf I2C_TX_word call I2C_send_word call I2C_send_stop bcf status,rp0 bcf portc,6 ;clear diag led bcf intcon,intf retfie ;******************************************************************* ;SUBROUTINES ;******************************************************************* ;initiates I2C message, by sending the word found in I2C_add, which ;must include R/W bit. Waits for all acknowledgement and completion ;states. Leaves RAM in Bank 0. I2C_send_add bsf status,rp0 bsf sspcon2,sen ;force start bit btfsc sspcon2,sen ;check for its completion goto $-1 bcf status,rp0 movf I2C_add,0 ;load address and data dirn bit movwf sspbuf ;and send bcf pir1,sspif ;will test this soon bsf status,rp0 btfsc sspstat,bf ;test for write complete goto $-1 btfsc sspcon2,ackstat ;wait for 0 acknowledge bit goto $-1 bcf status,rp0 btfss pir1,sspif ;test for int flag to show completion goto $-1 bcf pir1,sspif return ; ;Receives (single) word from I2C bus, and stores in I2C_RX_word. Returns Ack of 1, ;signalling this is last byte. Leaves RAM in Bank 0 I2C_rec_word bsf status,rp0 bsf sspcon2,rcen ;set receive enable bit btfss sspstat,bf ;wait for buffer full goto $-1 bcf status,rp0 ;read the data movf sspbuf,0 movwf I2C_RX_word ;store it for use somewhere bcf pir1,sspif ;preclear int flag, as we are about to use it bsf status,rp0 bsf sspcon2,ackdt ;set required acknowledge state, 1 as it's last byte bsf sspcon2,acken ;and enable it bcf status,rp0 btfss pir1,sspif ;use interrupt flag to test for end of ack goto $-1 bcf status,rp0 return ; ;Sends word on I2C bus, and awaits acknowledgement. Leaves RAM in Bank 0. I2C_send_word bcf status,rp0 movf I2C_TX_word,0 ;get the word movwf sspbuf ;this starts the transfer bsf status,rp0 btfsc sspstat,r_w ;test for write complete goto $-1 btfsc sspcon2,ackstat ;wait for 0 acknowledge bit goto $-1 bcf status,rp0 return ; ;Sends I2C stop bit, and awaits completion. Leaves RAM in Bank 0. I2C_send_stop bsf status,rp0 bsf sspcon2,pen ;force stop bit. btfss sspstat,p ;test for stop bit completion goto $-1 bcf status,rp0 return ; ;introduces delay of 20us approx delay20u movlw D'5' ;5 cycles called, ;each taking 3us, plus call, return (2 ea), and 2 move insts ;less one cycle lost when last goto is hopped movwf delcntr1 dela decfsz delcntr1,1 ;3 inst cycles in this loop, ie 3us goto dela return ; ;introduces delay of 1ms approx delay1 movlw D'250' ;250 cycles called, ; each taking 4us movwf delcntr1 del1 nop ;4 inst cycles in this loop, ie 4us decfsz delcntr1,1 goto del1 return ; ;10ms delay (approx) ;10 calls to delay1 delay10 movlw D'10' movwf delcntr2 del10 call delay1 decfsz delcntr2,1 goto del10 return ;200ms delay (approx) ;200 calls to delay1 delay200 movlw D'200' movwf delcntr2 del2 call delay1 decfsz delcntr2,1 goto del2 return ; ;500ms delay (approx) ;500 calls to delay1 delay500 movlw D'250' movwf delcntr2 del5 call delay1 call delay1 decfsz delcntr2,1 goto del5 return ; ;Character String Tables Table1 addwf pcl,1 retlw ' ' retlw 'D' retlw 'e' retlw 'r' retlw 'b' retlw 'o' retlw 't' retlw 0ff ; end