Myke's Home Page
|
"BasicRS" ExperimentThe second RS-232 interface application uses a PICmicro device which does not have a built in RS-232 port and does not use a negative voltage generator (the MAX232 in TrueRS). This experiment is really more typical of the kind of PICmicro applications you will be working with.
This experiment uses the circuit shown below:
The parts needed for this experiment are listed in the table:
Using a breadboard, the experiment is wired using the guide:
The circuit can also be built on a YAP-II using the guide:
The source code listed below can be accessed from the CD-ROM by clicking Here. Note that the code uses the "Macro Calculator" to find constant values instead of having the application author doing the work.
title "BasicRS - Simple 3-Wire RS-232 Application"
;
; This Application Implements a simple "3 Wire" RS-232 Link
; to another Computer. A Interrupt Based Bit Banging
; Routine is used instead of a USART.
;
;
; Hardware Notes:
; PIC16F84 Running at 4 MHz
; _MCLR is Pulled Up
; RC7 - Serial Receive Pin
; RC6 - Serial Transmit Pin
;
; Myke Predko
; 99.12.31
;
LIST R=DEC
ifdef __16F84
INCLUDE "p16f84.inc"
else
ifdef __16F877
INCLUDE "p16f877.inc"
endif
; Registers
CBLOCK 0x020
Dlay:2
_w, _status
TXCount, TXByte
RXCount, RXByte
ENDC
#define TX PORTB, 4
#define RX PORTB, 3
PAGE
ifdef __16F84
__CONFIG _CP_OFF & _WDT_OFF & _XT_OSC & _PWRTE_ON
else
__CONFIG _CP_OFF & _WDT_OFF & _XT_OSC & _PWRTE_ON & _DEBUG_OFF & _LVP_OFF & _BODEN_OFF
endif
; Mainline of TrueRS
org 0
nop
variable TMRDlay, TMRReset, PreScaler, PreScalerDlay, TMRActual, RTCActual, TMRError
TMRDlay = 4000000 / (1200 * 3 * 4)
TMRDlay = TMRDlay - 8
PreScalerDlay = 0
PreScaler = 2
TMRReset = TMRDlay / PreScaler
TMRActual = TMRReset * PreScaler
TMRError = ((TMRDlay - TMRActual) * 100) / TMRDlay
RTCActual = TMRActual + 9
RTCActual = ((RTCActual * 100000) / (4000000 / 4)) * 10
goto Mainline ; Jump Past the Interrupt Handler
org 4
Int ; PICmicro Interrupt Handler
movwf _w ; Save the Context Registers
movf STATUS, w
movwf _status
bcf INTCON, T0IF ; Reset the Timer Overflow Interrupt
movlw 256 - TMRReset ; Reset the Timer
movwf TMR0
movf TXCount, f ; If Transmitting, Can't Receive
btfsc STATUS, Z
goto _DoRX
movlw 0x004 ; Interrupt Transmit Increment Value
addwf TXCount, f
btfss STATUS, DC ; Send the Next Byte?
goto _TXSendDlayCheck
bsf TXCount, 2 ; Want to Increment 3x not Four for each byte
bsf STATUS, C
rrf TXByte, f
movf PORTB, w ; Send Next Bit
andlw 0x0FF ^ (1 << 4)
btfsc STATUS, C
iorlw 1 << 4
movwf PORTB ; Cycle 12 is the Bit Send
goto _IntEnd
_TXSendDlayCheck ; Don't Send Bit, Check for Start Bit
btfss TXCount, 0 ; Bit Zero Set (Byte to Send)?
goto _TXNothingtoCheck
goto $ + 1 ; Send Bit at Start of Cycle 12
movlw 0x004 ; Setup the Timer to Increment 3x
movwf TXCount
bcf TX ; Output the Start Bit
goto _IntEnd
_TXNothingtoCheck ; Nothing Being Sent?
movf TXCount, w
xorlw 0x004 ; Zero (Originally) TXCount?
btfsc STATUS, Z
clrf TXCount
movf TXCount, w ; Sent 10 Bits?
xorlw 0x09C
btfsc STATUS, Z
clrf TXCount ; Yes, Clear "TXCount" for Next Byte
goto _IntEnd
_DoRX
; #### - Put in Receive Interrupt Code
;
; RXCount Bit 1 Bit 0
; 0 0 - Waiting for Character to Come In
; 0 1 - Receiving Character
; 1 0 - Have Received Valid Character
; 1 1 - Error Receiving, Clear Buffer/RXCount
;
movlw 0x004 ; Check for Bit?
addwf RXCount, f
btfss STATUS, DC
goto _RXNo ; Nothing to Check for (Yet)
movf RXCount, w ; At the End?
xorlw 0x091
btfsc STATUS, Z
goto _RXNo
bcf STATUS, C ; Read the Current Bit
btfsc RX
bsf STATUS, C
rrf RXByte, f
bsf RXCount, 2 ; Start Counting from 4
goto _IntEnd ; Finished Receiving Byte
_RXAtEnd ; Check Last Bit
btfss RX
goto _RXOverrun ; Not Valid - Error
movlw 2 ; Valid - Save Value
movwf RXCount
goto _IntEnd
_RXNo ; No Bit to Receive
movf RXCount, w
xorlw 0x09D ; Read with Stop Bit?
btfsc STATUS, Z
goto _RXAtEnd
btfsc RXCount, 0 ; Something Running?
goto _IntEnd ; - Yes, Skip Over
btfss RXCount, 3 ; Checking Start Bits?
goto _RXStart
btfsc PORTB, 3
bcf RXCount, 3 ; Nothing - Keep Waiting
bsf RXCount, 0 ; Mark it has Started
btfss RXCount, 1 ; Something Already Saved?
goto _IntEnd
_RXOverrun ; Error - Mark the Overrun
movlw 0x003
movwf RXCount
goto _IntEnd
_RXStart ; Check for Low
btfsc PORTB, 3
bcf RXCount, 2 ; Don't Have a "Start" Bit
; #### - Finished with the Receive Interrupt Code
_IntEnd
movf _status, w ; Restore the Context Registers
movwf STATUS
swapf _w, f
swapf _w, w
retfie
Mainline
bsf TX ; Initialize the Output Port
bsf STATUS, RP0
bcf TX
movlw 0x0D0 + PreScalerDlay ; Set up the Timer
movwf OPTION_REG ^ 0x080
bcf STATUS, RP0
call Delay ; Delay 200 msecs before Sending
clrf TXCount ; Make Sure Nothing is Happening
clrf RXCount ; On Boot
bsf INTCON, T0IE ; Initialize the Interrupt Handler
bsf INTCON, GIE
movlw 256 - TMRReset ; Start the Timer Going
movwf TMR0
movlw "*" ; Send out a Start Character
call NRZSend
Loop
call NRZReceive ; Wait for a Serial Byte to be Received
addlw 255 - 'z' ; Get the High limit
addlw 'z' - 'a' + 1 ; Add Lower Limit to Set Carry
btfss STATUS, C ; If Carry Set, then Lower Case
addlw h'20' ; Carry NOT Set, Restore Character
addlw 'A' ; Add 'A' to restore the Character
call NRZSend
goto Loop
NRZSend ; Send the Value in "w" Serially
movf TXCount, f ; Wait for Previous Data Sent
btfss STATUS, Z
goto $ - 2 ; Counter = 0 when Sent
movwf TXByte
bsf TXCount, 0 ; Indicate there is Data to Send
return
NRZReceive ; Wait for a New Character to be Received
btfss RXCount, 1 ; Bit 0 Set when Data Received
goto $ - 1
movf RXByte, w ; Get the Received Byte
clrf RXCount
bcf STATUS, C ; Carry Reset - No Error
return
Delay
clrf Dlay
clrf Dlay + 1
decfsz Dlay, f
goto $ - 1
decfsz Dlay + 1, f
goto $ - 3
return
end
|