' PIC_IO_BAS.bas PIC serial IO interface by Mark Phythian ' Uses Microchip PIC16F88 processor running at 4MHz internal RC Osc. ' define variables Dim adtable(4) As Word ' table to hold adc results Dim chan As Byte ' channel number Dim val As Word ' word size adc result variable Dim oldb As Byte ' last portb value Dim char As Byte ' single character commend Dim command As Byte ' upper 4 bits of command Dim n As Byte ' lower 4 bits of command Dim m As Byte ' byte size temporary variable Dim wrd As Word ' word size temporary variable ' setup PIC OSCCON = 0x72 ' set internal RC select to 8MHz TRISB = %11000000 ' set PORTB 0-5 pins as outputs, 6 & 7 inputs Gosub initad ' initialise adc PIE1.RCIE = 1 ' enable UART RX interrupt OPTION_REG = 0x7f ' enable PORTB weak pullups for inputs 6 & 7 Hseropen 57600 ' set UART BAUD rate INTCON = 0xc8 ' enable GIE, PEIE and RBIE ' initialise variables PORTB = 0x00 oldb = PORTB And 0xc0 ' last value of PORTB bits 6 & 7 for change of state WaitMs 1000 Hserout "OK" ' startup ok WaitMs 100 ' endless loop converting as fast as possible main: While 1 ADCON0 = 0xc1 ' select channel 0 in bits 5,4,3 of ADCON0 For chan = 0 To 3 Gosub adconv ' go to conversion routine val.HB = ADRESH ' save high byte (upper 2 bits only) val.LB = ADRESL ' save low byte adtable(chan) = val ADCON0 = ADCON0 + 0x08 ' increment selected channel Next chan Wend 'repeat forever End ' Initialise ADC initad: TRISA = %11111111 ' set portA as input ANSEL = %00001111 ' set PORTA pins 0-3 as analog inputs ADCON1 = 0x80 ' set 10 bit A/D result format right justify ADRESH/L ADCON0 = 0xc1 ' set A/D conversion clock to internal source, turn on adc Return ' Adc conversion routine adconv: High ADCON0.GO_DONE ' start the conversion While ADCON0.GO_DONE ' wait until conversion is completed Wend Return On Interrupt Save System ' check for PORTB change of state on bits 6 & 7 If INTCON.RBIF = 1 Then ' test if portb change flag is on n = PORTB And 0xc0 INTCON.RBIF = 0 ' reset RBI flag n = oldb Xor n If n.7 = 1 Then ' if bit 7 changed If oldb.7 = 1 Then ' if bit 7 changed to 0 Hserout 0x22 ' send a " for INT2 input trigger WaitMs 10 Endif Else If n.6 = 1 Then ' if bit 6 changed If oldb.6 = 1 Then ' if bit 6 7 changed to 0 Hserout 0x21 ' send a ! for INT1 input trigger WaitMs 10 Endif Endif Endif oldb = PORTB And 0xc0 ' set oldb to new PORTB value Else ' test for serial command received If PIR1.RCIF = 1 Then ' test if RXer flag is on PIR1.RCIF = 0 ' reset RCI flag Hserget char ' get the received character command = char And 0xf0 ' command is upper 4 bits n = char And 0x0f ' number is lower 4 bits ' fetch 10 bit adc values, returns 2 bytes each, command letter 0 (zero) If command = 0x30 Then Hserout char ' echo command WaitMs 10 For n = 0 To 3 Hserout adtable(n) ' send 10 bit value in 2 bytes WaitMs 10 Next n Else ' fetch 8 bit adc values, returns 1 byte each, command letter @ If command = 0x40 Then Hserout char ' echo command WaitMs 10 For n = 0 To 3 ' D command requests all 4 wrd = adtable(n) m = ShiftRight(wrd, 2) Hserout m ' send 8 bit value as 1 byte WaitMs 10 Next n Else ' read inputs bits PA4-7, returns 1 byte, command letter P If command = 0x50 Then Hserout char ' echo command WaitMs 10 n = PORTA And 0xf0 n = ShiftRight(n, 4) Hserout n ' send 4 bits in low part of byte WaitMs 10 Else ' set outputs, command letters (from $60-$6F) ',a,b,c,d ... o If command = 0x60 Then Hserout char ' echo command WaitMs 10 m = n And 0x03 ' arrange bits to Port B bits 4,3,1,0 n = n And 0x0c n = ShiftLeft(n, 1) PORTB = m Or n ' set output bits from number n Endif Endif Endif Endif Endif Endif exit: Resume