| Author |
Message |
ece4afe
Joined: 16 Jun 2005 Posts: 16
|
22 Apr 2006 17:31 uart serial communication |
|
|
|
|
hello,
Pls advise me how to implement serial communication tru software programming. il be using a pic16f84a which doesnt have a built in UART. I know the theory of serial communication and I want to implement it thru software programming. Please teach me how to program it or if you have sample code for me to read and understand. This is my first time to program serial communication. my plan is to send ASCII characters from PIC to PC, which will be seen in the hyperterminal. I want to realize and appreciate the theory of serial communication.
Please help me on this.
Tnx,
Chris
|
|
| Back to top |
|
 |
hermin
Joined: 19 Apr 2005 Posts: 135 Helped: 9
|
22 Apr 2006 17:50 m_rs096.asm |
|
|
|
|
| first choose what programming language you would use so that your computer and mcu would communicate, you could use either C, visual basic and even matlab. For the mcu, you could either make one input be a serial input by just creating a program that would make that port receive serial data
|
|
| Back to top |
|
 |
BeeBop
Joined: 19 Feb 2006 Posts: 161 Helped: 15
|
23 Apr 2006 3:46 what is line feed in serial communication |
|
|
|
|
Hi Chris,
I thought I had some of my own examples, but it has been a long time since I did anything with an F84, however, I did find something that is nicely coded, and should serve you well. I think it came from:http://www.electronic-engineering.ch/microchip/index.html
which is a helpful page. (and you may need some other header files from there)
Anyway, here is the example, I hope it works for you.
Best wishes,
Robert
PS, yes you will need to go to his site and get the m_wait, and m_bank files, but should you have any problems, let me know, and I'll help you as much as I can.
regards
| Code: |
;***************************************************************************
;
; RS232 Communication Test for PIC 16XXX
; ======================================
;
; written by Peter Luethi, 26.03.1999, Dietikon, Switzerland
; http://www.electronic-engineering.ch
; last update: 11.04.2004
;
; V1.02: Fixed copy/paste issue of ISR context store/restore
; (nobody is perfect): Erroneously erased INTCON,INTF
; clearing, resulting in endless ISR calling...
; Re-structured entire ISR and RS232 echo sub-routines
; (11.04.2004)
; V1.01: ISR context restore improvements (30.12.2000)
; V1.00: Initial release (26.3.1999)
;
; This code and accompanying files may be distributed freely and
; modified, provided this header with my name and this notice remain
; intact. Ownership rights remain with me.
; You may not sell this software without my approval.
;
; This software comes with no guarantee or warranty except for my
; good intentions. By using this code you agree to indemnify me from
; any liability that might arise from its use.
;
;
; SPECIFICATIONS:
; ===============
; Processor: Microchip PIC 16F84
; Clock Frequency: 4.00 MHz XT
; Throughput: 1 MIPS
; Baud Rate: 9600 baud, 8 bit, no parity, 1 stopbit
; Code Size of entire Program: approx. 570 instruction words
; Required Hardware: MAX 232, dot matrix LCD display
;
;
; DESCRIPTION:
; ============
; Developed and tested on PIC 16F84, executeable on all interrupt
; featured PICs.
; Program handles all aspects of
; Transmission (Register TXD) and
; Reception (Register RXD) through interrupt.
; Display of received ASCII characters sent from RS232 host and
; their decimal representation on the dot matrix LCD display.
; The microcontroller sends feedback of received characters back to
; the terminal window.
;
;***************************************************************************
;***** COMPILATION MESSAGES & WARNINGS *****
ERRORLEVEL -207 ; found label after column 1
ERRORLEVEL -302 ; register in operand not in bank 0
;***** PROCESSOR DECLARATION & CONFIGURATION *****
PROCESSOR 16F84
#include "p16f84.inc"
; embed Configuration Data within .asm File
__CONFIG _CP_OFF & _WDT_OFF & _PWRTE_ON & _XT_OSC
;***** MEMORY STRUCTURE *****
ORG 0x00 ; processor reset vector
goto MAIN ; main program
ORG 0x04 ; interrupt vector
goto ISR ; Interrupt Service Routine (ISR)
;***** PARAMETERIZATION *****
CONSTANT LCDWAIT = 0x02 ; LCD wait for initialization
CONSTANT LCDSPEED = 0x01 ; configure according to PIC clock
;***** PORT DECLARATION *****
#define TXport PORTA,0x00 ; RS232 output port, could be
#define TXtris TRISA,0x00 ; any active push/pull port
LCDtris equ TRISB
LCDport equ PORTB
;***** CONSTANT DECLARATION *****
CONSTANT BASE = 0x0C ; base address of user file registers
;***** REGISTER DECLARATION *****
TEMP1 set BASE+d'0' ; Universal temporary register
TEMP2 set BASE+d'1' ; ATTENTION !!!
TEMP3 set BASE+d'2' ; They are used by various modules.
TEMP4 set BASE+d'3' ; If you use them, make sure not to use
TEMP5 set BASE+d'4' ; them concurrently! No use in ISR!
LO equ BASE+d'5'
LO_TEMP equ BASE+d'6'
FLAGreg equ BASE+d'7'
#define RSflag FLAGreg,0x00 ; RS232 data reception flag
#define LCDbusy FLAGreg,0x01 ; LCD busy flag
#define LCDcflag FLAGreg,0x02 ; LCD command/data flag
#define BCflag FLAGreg,0x04 ; blank checker for preceeding zeros
TXD equ BASE+d'8' ; TX-Data register
RXD equ BASE+d'9' ; RX-Data register
W_TEMP equ BASE+d'10' ; context register (ISR)
STATUS_TEMP equ BASE+d'11' ; context register (ISR)
PCLATH_TEMP equ BASE+d'12' ; context register (ISR)
FSR_TEMP equ BASE+d'13' ; context register (ISR)
;***** INCLUDE FILES *****
#include "..\..\m_bank.asm"
#include "..\..\m_wait.asm"
#include "..\..\m_lcd_bf.asm"
#include "..\..\m_lcdv08.asm"
#include "..\..\m_rs096.asm" ; standard RS232 baud rate
;***** MACROS *****
;***** SUB-ROUTINES *****
RSservice
LCD_DDAdr 0x45
movfw RXD ; get received RS232 data
LCDw ; send to LCD display
LCD_DDAdr 0x4D
movfw RXD
movwf LO
LCDval_08 ; display decimal value
SEND TAB
SEND 'r'
SEND 'e'
SEND 'c'
SEND 'e'
SEND 'i'
SEND 'v'
SEND 'e'
SEND 'd'
SEND ' '
movfw RXD ; get received RS232 data
SENDw ; transmit across RS232
SEND ' '
SEND 'o'
SEND 'n'
SEND ' '
SEND 'M'
SEND 'i'
SEND 'c'
SEND 'r'
SEND 'o'
SEND 'c'
SEND 'h'
SEND 'i'
SEND 'p'
SEND ' '
SEND 'P'
SEND 'I'
SEND 'C'
SEND '1'
SEND '6'
SEND 'F'
SEND '8'
SEND '4'
SEND CR ; Carriage Return
SEND LF ; Line Feed
; end of RS232 service (echo & display)
bcf RSflag ; reset RS232 data reception flag
bsf INTCON,INTE ; re-enable RB0/INT interrupt
RETURN
;***** INTERRUPT SERVICE ROUTINE *****
ISR ;************************
;*** ISR CONTEXT SAVE ***
;************************
bcf INTCON,GIE ; disable all interrupts
btfsc INTCON,GIE ; assure interrupts are disabled
goto ISR
movwf W_TEMP ; context save: W
swapf STATUS,W ; context save: STATUS
movwf STATUS_TEMP ; context save
clrf STATUS ; bank 0, regardless of current bank
movfw PCLATH ; context save: PCLATH
movwf PCLATH_TEMP ; context save
clrf PCLATH ; page zero, regardless of current page
bcf STATUS,IRP ; return to bank 0
movfw FSR ; context save: FSR
movwf FSR_TEMP ; context save
;*** context save done ***
;**************************
;*** ISR MAIN EXECUTION ***
;**************************
;*** determine origin of interrupt ***
btfsc INTCON,INTF ; check for RB0/INT interrupt
goto _ISR_RS232 ; if set, there was a keypad stroke
; catch-all
goto ISRend ; unexpected IRQ, terminate execution of ISR
;******************************
;*** RS232 DATA ACQUISITION ***
;******************************
_ISR_RS232
; first, disable interrupt source
bcf INTCON,INTE ; disable RB0/INT interrupt
; second, acquire RS232 data
RECEIVE ; macro of RS232 software reception
bsf RSflag ; enable RS232 data reception flag
goto _ISR_RS232end ; terminate RS232 ISR properly
;***********************************
;*** CLEARING OF INTERRUPT FLAGS ***
;***********************************
; NOTE: Below, I only clear the interrupt flags! This does not
; necessarily mean, that the interrupts are already re-enabled.
; Basically, interrupt re-enabling is carried out at the end of
; the corresponding service routine in normal operation mode.
; The flag responsible for the current ISR call has to be cleared
; to prevent recursive ISR calls. Other interrupt flags, activated
; during execution of this ISR, will immediately be served upon
; termination of the current ISR run.
_ISR_RS232error
bsf INTCON,INTE ; after error, re-enable IRQ already here
_ISR_RS232end
bcf INTCON,INTF ; clear RB0/INT interrupt flag
;goto ISRend ; terminate execution of ISR
;*****************************************
;*** ISR TERMINATION (CONTEXT RESTORE) ***
;*****************************************
ISRend movfw FSR_TEMP ; context restore
movwf FSR ; context restore
movfw PCLATH_TEMP ; context restore
movwf PCLATH ; context restore
swapf STATUS_TEMP,W ; context restore
movwf STATUS ; context restore
swapf W_TEMP,F ; context restore
swapf W_TEMP,W ; context restore
RETFIE ; enable global interrupt (INTCON,GIE)
;***** END OF INTERRUPT SERVICE ROUTINE *****
;************** MAIN **************
MAIN LCDinit ; LCD Initialization
RS232init ; RS232 Initialization
clrf FLAGreg ; initialize all flags
;*** START-UP MESSAGE of LCD ***
LCDchar 'R'
LCDchar 'S'
LCDchar '2'
LCDchar '3'
LCDchar '2'
LCDchar ' '
LCDchar 'C'
LCDchar 'o'
LCDchar 'm'
LCDchar 'm'
LCDchar 'u'
LCDchar 'n'
LCDchar 'i'
LCDchar 'c'
LCDchar 'a'
LCDchar '-'
LCDline 2
LCDchar 't'
LCDchar 'i'
LCDchar 'o'
LCDchar 'n'
LCDchar ' '
LCDchar 'o'
LCDchar 'n'
LCDchar ' '
LCDchar 'P'
LCDchar 'I'
LCDchar 'C'
LCDchar '1'
LCDchar '6'
LCDchar 'F'
LCDchar '8'
LCDchar '4'
;*** START-UP MESSAGE to RS232 ***
; this is done by reading a look-up table
; define amount of table items for start-up message
#define tab_size4 d'48'
movlw tab_size4 ; store amount of table items in counter
movwf TEMP5
; transmit message
_ILOOP1 movlw HIGH WelcomeTable ; get correct page for PCLATH
movwf PCLATH ; prepare right page bits for table read
movfw TEMP5 ; get actual count-down value
sublw tab_size4 ; table offset: w = tab_size4 - TEMP6
call WelcomeTable ; call lookup table
SENDw ; RS232 output
decfsz TEMP5,f ; decrement counter
goto _ILOOP1
WAITX 0x1A, b'00000111' ; wait some time
; a little bit animation...
SEND 'a'
SEND 'n'
SEND 'i'
SEND 'm'
SEND 'a'
SEND 't'
SEND 'i'
SEND 'n'
SEND 'g'
SEND ' '
SEND 'L'
SEND 'C'
SEND 'D'
SEND '.'
SEND '.'
SEND '.'
SEND CR ; Carriage Return
SEND LF ; Line Feed
movlw d'16'
movwf TEMP5
_SHL1 LCDcmd LCDSL ; shift left LCD display content
WAIT 0xC0
decfsz TEMP5,f
goto _SHL1
; finally, reset/clear LCD
LCDcmd LCDCLR
LCDchar 'R'
LCDchar 'S'
LCDchar '2'
LCDchar '3'
LCDchar '2'
LCDchar ' '
LCDchar 'R'
LCDchar 'e'
LCDchar 'c'
LCDchar 'e'
LCDchar 'p'
LCDchar 't'
LCDchar 'i'
LCDchar 'o'
LCDchar 'n'
LCDchar ':'
LCDline 2
LCDchar 'C'
LCDchar 'h'
LCDchar 'a'
LCDchar 'r'
LCD_DDAdr 0x47
LCDchar 'V'
LCDchar 'a'
LCDchar 'l'
LCDchar 'u'
LCDchar 'e'
SEND 'r'
SEND 'e'
SEND 'a'
SEND 'd'
SEND 'y'
SEND '.'
SEND '.'
SEND '.'
SEND CR ; Carriage Return
SEND LF ; Line Feed
;******************************
LOOP btfsc RSflag ; check RS232 data reception flag
call RSservice ; if set, call RS232 echo & LCD display routine
goto LOOP
;******************************
;ORG 0x230 ; if necessary, move look-up tables
WelcomeTable
addwf PCL,F ; add offset to table base pointer
retlw CR
retlw LF
DT "Microchip PIC16F84 connected and stand-by..." ; create table
retlw CR
WTableEND retlw LF
IF (HIGH (WelcomeTable) != HIGH (WTableEND))
ERROR "WelcomeTable hits page boundary!"
ENDIF
END
|
|
|
| Back to top |
|
 |
Google AdSense

|
23 Apr 2006 3:46 Ads |
|
|
|
|
|
|
| Back to top |
|
 |
ece4afe
Joined: 16 Jun 2005 Posts: 16
|
24 Apr 2006 9:34 uart theory |
|
|
|
|
hello,
my target is to have a serial communication, which is purely software, no UART since f84 has no built in uart, and no interrupt as well. So therefore the program will look like this manner,
let say if i want to send capital C which is 43hex, to PC, i will send first the start bit which is a logic zero, then delay (9600kbps--->about 104us) then the data which is the letter C(01000011 in binary), where in, MSB first, then delay again, then the next bit, delay...............until I arrive at Last or LSB, delay then the stop bit, which is a logic one.
I am using C in programming.
Could you give me atleast a hint on how to attack this problem
Regards,
Chris
|
|
| Back to top |
|
 |
hermin
Joined: 19 Apr 2005 Posts: 135 Helped: 9
|
24 Apr 2006 13:30 communicate using uart in c |
|
|
|
|
| I believe the best thing you could use will be a constant bit rate, serial communication. and i also recommend to use a null character instead of a start or stop bit,
|
|
| Back to top |
|
 |
BeeBop
Joined: 19 Feb 2006 Posts: 161 Helped: 15
|
24 Apr 2006 15:44 how does software read serial communication |
|
|
|
|
Chris,
If you looked at the assembly I gave you, it is for a 16F84, which I realize has no hardware UART. And if you look at the data sheet for your PIC you will find, on page 3 that it has:
| Quote: |
• Four interrupt sources:
- External RB0/INT pin
- TMR0 timer overflow
- PORTB<7:4> interrupt on change
- Data EEPROM write complete |
You didn't say how you were programming it, but you did say you wanted
| Quote: |
| to realize and appreciate the theory of serial communication |
which led me to believe you wanted something in assembly. While C is closer to the hardware than most high level languages, it is still a high level language, and you will not get as much out of it as you would assembly. That said, which C compiler are you using? They each have thier own ways of producing hex code, and some even include some libraries. In many compilers, to get the right timing, you will have to inline assembly, at least for the delays, for this to work well.
If I remember, too, you send the LSB first, not the MSB.
Basically, you loop through the byte you want to send. Your line is high in idle, you clear it to send a start bit, then call your delay. Read the first bit of the data you wish to send. If it is a one, then set your pin and call your delay. (This is where is gets tricky with C - how many cycles does it take to get into the dely with your compiler?) Then you shift your bite to the right, and check the next bit. If your bit is high, set the pin. If your bit is low, clear the pin. Then call your delay again. Do this until you have shifted your byte out, and when you are done, send the stop bit.
I would recomend sending just one char until you have it working.
If you are just sending from the PIC, not receiving, you should be able to do it without interrupts, unless you choose to use them for timing.
Again, which compiler are you using?
Regards,
Robert
PS here is a tutorial on software serial comms:http://www.sparkfun.com/commerce/present.php?p=The%20Serial%20Biggie%20Page1
|
|
| Back to top |
|
 |