I=92m trying to get some PIC to PC communication going using the 16F688, but I am not having much luck.
Hardware setup is just a PIC16F688 with power, and RC4/RC5 connected to an RS232 ShifterBoard Kit from Sparkfun.
I grabbed the code below off the internet somewhere. Nothing hooked up to the ADC but that=92s fine, I don=92t mind it spitting out random data, as long as it=92s the values in the registers. The code below compiles fine, load the chip, and start up hyperterminal. At 9600 baud 8 bits, no parity, no flow control I get nothing. If I lower the speed to 2400bps I get gobbledygook periodically at timed intervals corresponding to the RCV light on the serial shifter, so it looks like data is being transmitted. I assume I must just have the baud rate wrong.
In looking at the datasheet, for 9600baud, SYNC =3D 0, BRG16=3D1, BRGH=3D0 = I keep coming up with an SPBRG value of 8,000,000 / [16 (n + 1)] =3D
51.08 =3D [51]The code I pulled used 25. I have had no luck with either setting. Anyone know what I am missing?
list p=3D16f688 ; list directive to define processor
#include ; processor specific variable definitions
__CONFIG _CP_OFF & _CPD_OFF & _BOD_OFF & _PWRTE_ON & _WDT_OFF & _INTRC_OSC_NOCLKOUT & _MCLRE_OFF & _FCMEN_OFF & _IESO_OFF
; '__CONFIG' directive is used to embed configuration data within .asm file.
; The labels following the directive are located in the respective .inc file.
; See respective data sheet for additional information on configuration word.
;***** VARIABLE DEFINITIONS
w_temp EQU 0x71 ; variable used for context saving
status_temp EQU 0x72 ; variable used for context saving
pclath_temp EQU 0x73 ; variable used for context saving
ADCH0 EQU B'00000001' ;setup ch 0, Vdd for Vref, and left justified result
ADCH1 EQU B'00000101' ;set to Ch1 same settings as above
ADCH2 EQU B'00001001' ;set to Ch2 same settings as above
ADCH3 EQU B'00001101' ;set to Ch3 same settings as above
COUNTER EQU 0x60 ;counter variable
TXPREBUF EQU 0x61 ;A buffer for the serial transmit buffer (a prebuf)
OCTTOVERT EQU 0x20 ;stores the a/d value when it's being converted to octal
;**********************************************************************
ORG 0x0 ; processor reset vector
goto main ; go to beginning of program
main
;***********************************************************
;Setup For 9600 bps tx serial interface
;***********************************************************
bsf STATUS, RP0 ;bank 1
movlw B'00111111' ;setup RC0-5 as inputs for serial i/ o and A/D
movwf TRISC
bcf STATUS, RP0 ;bank 0
bsf RCSTA, SPEN ;serial port enable
bsf BAUDCTL, BRG16 ;use 16 bit baudrate generator
bcf TXSTA, BRGH ;use low baudrate speed
movlw d'25'
movwf SPBRG ;setup baudrate generator
bcf TXSTA, SYNC ;asynchronous serial i/o
bsf TXSTA, TXEN ;enable transmission
;***********************************************************
;Setup A/D converter
;***********************************************************
bsf STATUS, RP0 ;bank 1
movlw B'00011111' ;Setup all of port A as inputs for A/ D
movwf TRISA
movlw 0xFF
movwf ANSEL ;Enable all available Analog channels
movlw B'01010000'
movwf ADCON1 ;Set 4uS conversion time w/ 4MHz internal clk
bcf STATUS, RP0 ;bank 0
movlw ADCH0
movwf ADCON0 ;AD: right justified result, ch 0, VDD ref. voltage
call WaitForAD
;***********************************************************
;Setup Timer1 for 1/10 second wait period
;***********************************************************
movlw B'00110001'
movwf T1CON ;load timer1 config register
GoAgain:
movlw 0x01 ;set to max for approx 1 sec delay
movwf TMR1L
movlw 0x00
movwf TMR1H
;bsf T1CON, TMR1ON ;start timer
bcf PIR1, TMR1IF ;clear overflow flag
;This is the delay between sample periods from the analog inputs
Wait:
btfss PIR1, TMR1IF ;check if timer has overflowed
goto Wait
call GetADValues
; loop through 4 values here and print them out
movlw 0x4 ;loop 4 times
movwf COUNTER
movlw 0x21 ;point to first a/d value
movwf FSR ;data pointer
OutLoop:
movf INDF, W ;getting indirect data
movwf OCTTOVERT ;store a/d value we need to convert
call TO_OCTAL ;convert currently selected A/D Channel to octal
movf 0x30, W ;output all bytes
movwf TXPREBUF
call SENDBYTE
movf 0x31, W
movwf TXPREBUF
call SENDBYTE
movf 0x32, W
movwf TXPREBUF
call SENDBYTE
movlw ',' ;do checking on this one to see if we're at the last byte
movwf TXPREBUF
call SENDBYTE
incf FSR ;goto next a/d value
decfsz COUNTER ;is counter zero yet? if so skip goto
goto OutLoop
; end of above loop
movlw 0x0A ;Line Feed (newline, hopefully)
movwf TXPREBUF
call SENDBYTE
;movlw 0x0D ;carridge return
;movwf TXPREBUF
;call SENDBYTE
goto GoAgain ;Reset the timer for another go around
;***********************************************************
;Subroutines
;***********************************************************
WaitForAD: ;wait 44us to init, 176 instruction cycles
movlw D'176' ;really only need 1/2 this many cycles due to test and set
movwf COUNTER
FourFourWait:
decf COUNTER
bnz FourFourWait ;keep decrementing until we reach 0
return
;get a/d values for 4 ch
GetADValues:
movlw 0x21 ;start of free ram
movwf FSR ;setup indirect addressing register
movlw ADCH0 ;goto channel 0
movwf ADCON0
bsf ADCON0, GO ;start conversion
btfsc ADCON0, GO ;conversion done?
goto $-1 ;keep looping
movf ADRESH, W ;get high byte into acc W
movwf INDF ;store adresh to 21h
incf FSR ;move ptr to 22h
call WaitForAD
movlw ADCH1 ;goto channel 1
movwf ADCON0
bsf ADCON0, GO ;start conversion
btfsc ADCON0, GO ;conversion done?
goto $-1 ;keep looping
movf ADRESH, W ;get high byte into acc W
movwf INDF ;store adresh to 22h
incf FSR ;move ptr to 23h
call WaitForAD
movlw ADCH2 ;goto channel 2
movwf ADCON0
bsf ADCON0, GO ;start conversion
btfsc ADCON0, GO ;conversion done?
goto $-1 ;keep looping
movf ADRESH, W ;get high byte into acc W
movwf INDF ;store adresh to 23h
incf FSR ;move ptr to 24h
call WaitForAD
movlw ADCH3 ;goto channel 3
movwf ADCON0
bsf ADCON0, GO ;start conversion
btfsc ADCON0, GO ;conversion done?
goto $-1 ;keep looping
movf ADRESH, W ;get high byte into acc W
movwf INDF ;store adresh to 24h
return
;convert to 3 octal bytes in ASCII
;stores bytes in 0x30 to 0x32, w/ lsb in 0x32 msb in 0x30
;input value stored in 0x20, ie OCTTOVERT
TO_OCTAL:
clrc ;clear carry
movlw B'00000111' ;bit mask field
andwf OCTTOVERT, W ;and with ADRESH
addlw 0x30 ;make this into an ASCII number
movwf 0x32 ;store result away
;octal byte 2
movlw B'00111000' ;bit mask field
andwf OCTTOVERT, W ;get 2nd set of 3 bits
movwf 0x31 ;place back into file
rrf 0x31 ;rotate to LSB, need 3x
rrf 0x31
rrf 0x31
movf 0x31, W ;now get it back
addlw 0x30 ;and add 30h to make a ascii number
movwf 0x31 ;store again
;octal byte 3
clrc ;clear carry
movlw B'11000000' ;bit mask field
andwf OCTTOVERT, W ;get last 2 bits
movwf 0x30
rrf 0x30
rrf 0x30
rrf 0x30
rrf 0x30
rrf 0x30
rrf 0x30
;btfsc 0x21, 0 ;check the LSB value from the last byte
;bsf 0x31, 2
movf 0x30, W ;get value back
addlw 0x30 ;convert to ASCII
movwf 0x30 ;store it
return
;transmit data on serial port
SENDBYTE:
btfss TXSTA, TRMT ;check tx buffer ready bit
goto SENDBYTE ;try again, keep polling
movf TXPREBUF, W ;get data from pre-buffer
movwf TXREG ;move data to tx register and start transmission
return
ORG 0x2100 ; data EEPROM location
DE 1,2,3,4 ; define first four EEPROM locations as 1, 2, 3, and 4
END ; directive 'end of program'