Home
News
Design Info
Code
Links
|
RS-232 communications between PC and 16F73/74/76/77/873/874/876/877
The links to the following two webpages were the basis for getting
RS-232 serial communication working between the pic16F73 and a PC. In
fact, the code below was taking 95% from examples on those websites.
This code is for a mid-range pic microcontroller with a built in USART.
The 16f73, 16f74, 16f76, 16f77, 16f873, 16f874, 16f876, 16f877 all have
a built in USART, so this code should apply to all of them, although
some tweaking may be needed. For example, the f73/f76/f873/f876 are all
28-pin devices, the others are 40-pin devices and have 2 more ports (D
and E). Bente Petersen's 9600baud 16F628 UART test circuit and program
Tony Nixon's UART test program
A
key element to interfacing a PIC to a PC is adjusting the voltage
levels correctly. RS-232, which is what a PC serial port uses, uses +3V
to +25V to indicate a logic 0 and -3V to -25V to indicate a logic 1.
However a PIC uses TTL/CMOS level signaling where a logic 0 is about 0V
to .8V and a logic 1 about 2V to Vdd. In order to make this work, a
Texas Instruments MAX232 RS-232 transceiver was used. It will convert
between the two signal levels and includes a capacitive generator to
supply the RS-232 voltage levels from a single 5V supply. It does
require several external capacitors. See the schematic at the bottom of
this page. RS-232 defines several signals, but only three are
required for our simple asynchronous serial communication: the TXD, RXD
and GND signal. To communicate with the PIC, the Hyperterminal program
in Windows was used. For the example code listed, Hyperterminal was
configured for 19200 baud, 8 data bits, no parity, 1 stop bit and no
flow control.
echo2.asm - This just echos characters from a PC terminal program back to the screen via the PIC (this is the same as the code below).
int_echo_876.asm - Here is a program that functions almost identically to echo2.asm, but it is interrupt driven (it's also for the 16F876 and uses a 20MHz clock, but that's irrelevant)
bb_echo.asm - This program is a bit more complex than the other two above. It does rs-232 communications without using the internal UART. It's all done through bit-banging (ie software). It performs the same function as the two pieces of code above; prints a hello message and then echos everything that is sent to it. It is hardcoded for 9600 8-N-1 using a 20MHz oscillator. As is, the code just loops, waiting for a start bit, reading a byte and then sending the byte back. The problem with this is that if the bytes it receives are too close together, it will miss some because when it calls the transmit routine, that takes time where we could be missing an incoming byte. This problem can be seen if carriage return & line feeds are sent by the enter key in Hyperterminal. Because they are sent back to back, only the carriage return is actually read and echoed back. The line feed is missed. This program is setup to easily be interrupt driven as well, by uncommenting the "ENABLE_IRQ" line and commenting out the "call BBRX" and "call BBTX" lines in the main loop. In either case, the program is setup to transmit on RB1 and receive on RB0, otherwise it is connected exactly the same as the diagram below.
Title "Your Program"
;
list P = 16F73
;
include "P16f73.inc"
;
; ------------------
; CONFIGURATION FUSE
; ------------------
; Code protection/watchdog timer off, enable power up timer and brown out detection
; Using a 4MHz ceramic resonator, so set to XT mode
__CONFIG _CP_OFF & _XT_OSC & _WDT_OFF & _PWRTE_ON & _BODEN_ON
;
; CRYSTAL SPEED = 4000000Hz
;
; Define user registers in this block
CBLOCK 0x20
dataL
ENDC
;
; -------------
; PROGRAM START
; -------------
;
org 0x0000 ; startup = 0000h
;
Start movlw 0x00 ; setup ports
movwf PORTA
movlw 0x00
movwf PORTB
movlw 0x40
movwf PORTC
bsf STATUS,RP0 ; RAM Page 1
movlw 0x00
movwf TRISA
movlw 0x00
movwf TRISB
movlw 0x80
movwf TRISC
;
; -------------------------
; SET ANALOG/DIGITAL INPUTS
; -------------------------
;
movlw 0x06 ; all digital
movwf ADCON1
;
; ------------------------------------
; SET BAUD RATE TO COMMUNICATE WITH PC
; ------------------------------------
; Boot Baud Rate = 19200, No Parity, 1 Stop Bit
;
movlw 0x0C ; 19200 baud
movwf SPBRG
movlw b'00100100' ; brgh = high (2)
movwf TXSTA ; enable Async Transmission, set brgh
movlw b'10010000' ; enable Async Reception
bcf STATUS,RP0 ; RAM Page 0
movwf RCSTA
;
; ------------------------------------
; PROVIDE A SETTLING TIME FOR START UP
; ------------------------------------
;
clrf dataL
settle decfsz dataL,F
goto settle
;
movf RCREG,W
movf RCREG,W
movf RCREG,W ; flush receive buffer
call message
Loop call Receive ; wait for a char
movwf TXREG ; echo data back to sender
goto Loop
;
; ----------------------------
; RECEIVE CHARACTER FROM RS232
; ----------------------------
; This routine does not return until a character is received.
;
Receive btfss PIR1,RCIF ; (5) check for received data
goto Receive
;
movf RCREG,W
return
;
; -------------------------------------------------------------
; SEND CHARACTER IN W VIA RS232 AND WAIT UNTIL FINISHED SENDING
; -------------------------------------------------------------
;
send movwf TXREG ; send data in W
TransWt bsf STATUS,RP0 ; RAM PAGE 1
WtHere btfss TXSTA,TRMT ; (1) transmission is complete if hi
goto WtHere
bcf STATUS,RP0 ; RAM PAGE 0
return
;
; -------
; MESSAGE
; -------
;
message movlw '1'
call send
movlw '6'
call send
movlw 'F'
call send
movlw '7'
call send
movlw '3'
call send
movlw ' '
call send
movlw 'a'
call send
movlw 'l'
call send
movlw 'i'
call send
movlw 'v'
call send
movlw 'e'
call send
movlw 0x0D ; CR
call send
movlw 0x0A ; LF
call send
return
end
|