Continue to Site

Welcome to our site!

Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

  • Welcome to our site! Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

UART code litle improvement

Status
Not open for further replies.

PIC2PIC

New Member
Hi !

This program is for UART connection between 16f877 and 16f877. Its working OK as long as connection is Ok. As soon as i break connection TX-RX and make it again all freezes .
How Can I improve program so theese two PICs can restore communication after connection breakes. This is very important to my circuit.


Transmiter code:


;---------------------------------------------------------------------------
list p=16f877A ; list directive to define processor
#include <p16f877A.inc> ; processor specific variable definitions
errorlevel -302, -207
;---------------------------------------------------------------------------


;---------------------------------------------------------------------------
banksel TRISB

movlw 0ffh
movwf TRISB
movwf TRISC
movlw 00h
movwf TRISA

movlw b'00000110' ; all analog pins = digital
movwf ADCON1

;---------------------------------------------------------------------------


;---------------------------------------------------------------------------

banksel SPBRG
movlw 0x0C
movwf SPBRG

movlw b'00100100'
movwf TXSTA


bcf PIE1,TXIE
bcf PIE1,RCIE

banksel RCSTA
movlw b'10010000'
movwf RCSTA

;---------------------------------------------------------------------------





Main
call Trans
call Receive

goto Main

Receive
banksel PIR1
btfss PIR1,RCIF
goto Receive
movf RCREG,W
movwf PORTA
return

Trans
banksel PORTB
movf PORTB,W
movwf TXREG

banksel TXSTA

WtHere btfss TXSTA,TRMT
goto WtHere
return

;---------------------------------------------------------------------------





end

Receiver code:

;---------------------------------------------------------------------------
list p=16f877A ; list directive to define processor
#include <p16f877A.inc> ; processor specific variable definitions
errorlevel -302, -207
;---------------------------------------------------------------------------


;---------------------------------------------------------------------------
banksel TRISB

movlw 0ffh
movwf TRISA
movwf TRISC
movlw 00h
movwf TRISB

movlw b'00000110' ; all analog pins = digital
movwf ADCON1
;---------------------------------------------------------------------------


;---------------------------------------------------------------------------

banksel SPBRG
movlw 0x0C
movwf SPBRG

movlw b'00100100'
movwf TXSTA


bcf PIE1,TXIE
bcf PIE1,RCIE

banksel RCSTA
movlw b'10010000'
movwf RCSTA

;---------------------------------------------------------------------------





Main

call Receive
call Trans

goto Main

Receive
banksel PIR1
btfss PIR1,RCIF
goto Receive
movf RCREG,W
movwf PORTB
return

Trans
banksel PORTB
movf PORTA,W
movwf TXREG

banksel TXSTA

WtHere btfss TXSTA,TRMT
goto WtHere
return

;---------------------------------------------------------------------------





end
 
You can start sending a leading character to determine the connections are all ok.

For ex:
In your main program you send character “A” to the other PIC. When other PIC receives this character send character “a” back to the 1st PIC. If character “a” received then connections are all ok & you can send your actual data.

You wait after sending "A" & wait it receives "a" & send the actual data.
 
Last edited:
Both ends of your link are waiting for a transmission. If nothing arrives, both ends will sit there waiting for transmission forever.

You should:-

1) Get both ends to transmit regularly, whether or not they receive anything.
2) Get both ends to deal with data if it is received, but not loop forever if they don't
3) Get both ends to look for USART errors and clear them if they happen.
 
Thank you people!

That is easy to say. I am trying that for days. It's just not working.

Its working when I set one PIC as trasmitter and the other one as receiver. But If I try to make each PIC both transmitter and receiver it freezes.

I know the problem is in these waitings for answer from other PIC.

I made two codes. One named "Transmitter" and the other one "Receiver" . Almost same code. Here is my new code and I don't know what is wrong :

TRANSMITER


;---------------------------------------------------------------------------
list p=16f877A ; list directive to define processor
#include <p16f877A.inc> ; processor specific variable definitions
errorlevel -302, -207
;---------------------------------------------------------------------------


;---------------------------------------------------------------------------
banksel TRISB

movlw 0ffh
movwf TRISB
movwf TRISC
movlw 00h
movwf TRISA

movlw b'00000110' ; all analog pins = digital
movwf ADCON1

;---------------------------------------------------------------------------


;---------------------------------------------------------------------------

banksel SPBRG
movlw 0x0C
movwf SPBRG

movlw b'00100100'
movwf TXSTA


bcf PIE1,TXIE
bcf PIE1,RCIE

banksel RCSTA
movlw b'10010000'
movwf RCSTA

bcf STATUS,5
bcf STATUS,6


izbor equ 22h

;---------------------------------------------------------------------------


movlw 0ffh
movwf izbor


Main
banksel izbor
movf izbor,w
sublw 0ffh
btfsc STATUS,2
call Trans

banksel izbor
movf izbor,w
btfsc STATUS,2
call Receive

goto Main


;---------------------------------------------------------------------------


Trans
banksel TXREG
movlw 0ffh
movwf TXREG

banksel TXSTA

WtHere_t btfss TXSTA,TRMT
goto WtHere_t

banksel RCREG

btfss PIR1,RCIF
goto Trans

movf RCREG,w
sublw 0ffh
btfss STATUS,2
goto Trans

banksel PORTB
movf PORTB,W
movwf TXREG

banksel TXSTA

WtHere_t_1 btfss TXSTA,TRMT
goto WtHere_t_1

banksel izbor
movlw 00h
movwf izbor

return

;---------------------------------------------------------------------------

Receive

banksel RCREG

WtHere_r btfss PIR1,RCIF
goto WtHere_r


movf RCREG,w
sublw 0ffh
btfss STATUS,2
goto Receive

transmisija

banksel TXREG
movlw 0ffh
movwf TXREG

banksel TXSTA

WtHere btfss TXSTA,TRMT
goto WtHere


prijem
banksel PIR1
btfss PIR1,RCIF
goto prijem
movf RCREG,W
movwf PORTA

banksel izbor
movlw 0ffh
movwf izbor

return




;---------------------------------------------------------------------------





end



RECEIVER



;---------------------------------------------------------------------------
list p=16f877A ; list directive to define processor
#include <p16f877A.inc> ; processor specific variable definitions
errorlevel -302, -207
;---------------------------------------------------------------------------


;---------------------------------------------------------------------------
banksel TRISB

movlw 0ffh
movwf TRISA
movwf TRISC
movlw 00h
movwf TRISB

movlw b'00000110' ; all analog pins = digital
movwf ADCON1


;---------------------------------------------------------------------------


;---------------------------------------------------------------------------

banksel SPBRG
movlw 0x0C
movwf SPBRG

movlw b'00100100'
movwf TXSTA


bcf PIE1,TXIE
bcf PIE1,RCIE

banksel RCSTA
movlw b'10010000'
movwf RCSTA

bcf STATUS,5
bcf STATUS,6


izbor equ 22h

;---------------------------------------------------------------------------




movlw 00h
movwf izbor

Main
banksel izbor
movf izbor,w
btfsc STATUS,2
call Receive

banksel izbor
movf izbor,w
sublw 0ffh
btfsc STATUS,2
call Trans


goto Main

;---------------------------------------------------------------------------

Receive

banksel RCREG

WtHere_r btfss PIR1,RCIF
goto WtHere_r


movf RCREG,w
sublw 0ffh
btfss STATUS,2
goto Receive

transmisija

banksel TXREG
movlw 0ffh
movwf TXREG

banksel TXSTA

WtHere btfss TXSTA,TRMT
goto WtHere


prijem
banksel PIR1
btfss PIR1,RCIF
goto prijem
movf RCREG,W
movwf PORTB

banksel izbor
movlw 0ffh
movwf izbor

return


;---------------------------------------------------------------------------

Trans
banksel TXREG
movlw 0ffh
movwf TXREG

banksel TXSTA

WtHere_t btfss TXSTA,TRMT
goto WtHere_t

banksel RCREG

btfss PIR1,RCIF
goto Trans

movf RCREG,w
sublw 0ffh
btfss STATUS,2
goto Trans

banksel PORTB
movf PORTA,W
movwf TXREG

banksel TXSTA

WtHere_t_1 btfss TXSTA,TRMT
goto WtHere_t_1

banksel izbor
movlw 00h
movwf izbor

return
;---------------------------------------------------------------------------





end
 
You are making stuff way too complicated.

I guess that you have Port B on the transmitter as inputs, and you want whatever is on that to appear on Port B on the receiver. Also, you want whatever is on Port A of the receiver to appear on Port A of the transmitter.

You should not have code with stuff like this:-

WtHere_t btfss TXSTA,TRMT
goto WtHere_t

There are 3 things wrong with it.

1) You didn't post it in code tags
2) There are no comments anywhere
3) It waits for something to arrive from the serial port and crashes the processor if nothing ever arrives.

Also, it is a real pain for us if you write
btfss STATUS, 2

when you could write STATUS, Z because more of us know that Z stands for "zero" than know that bit 2 of the status register happens to be the zero flag.

The transmit and receive can go ahead at the same time. There is no need to wait for reception. You can just transmit as often as you want.

What you need is something like:-

Code:
Main
  call transmit
  call receive
  goto Main

transmit
;this transmits the contents of port B if it can.
  banksel TXSTA
  btfss TXSTA,TRMT 
  return                   ;Return if there isn't space to transmit.
  
  banksel PortB
  movf  PortB, w        ;collect the contents of Port B
  banksel TXREG        ;(I don't know if this is needed)
  movwf  TXREG        ;and send contents of Port B
  return

receive
;This looks for anything received and puts it on Port A
  btfss PIR1,RCIF
  return                   ;Return if nothing has been recieved

  banksel RCREG
  movf    RCREG, w    ;collect what has been recieved
  banksel PortA
  movwf  PortA         ;and send to PortA
  return

The real shortcoming of this code is that it transmits as back to back bytes. With many values the some of the data bits could be interpreted as the start and stop bits.

It would be better to have timer and only send data when the timer rolls. The gaps between the data bytes ensure that the start bit is seen correctly by the receiver.
 
Are you talking about physically disconnecting or software wise? For both its simply the same i guess. Do what Gayan Soyza said but have it set a flag. And only test the flag.

Here is my view:

Create a variable like
char con1;
Have it setup like ...

0x00 nothing
0x01 request acknowledged
0x02 request complete

Now you can have it check the con1 variable and if its a 0x00 send a request
use a timer to check in about 50ms to see if the flag changed
(in your recieve code it can check for anything like 2 characters like |~ this way its less likely false start)

If its a 0x00 still send another request. if you recieved the 2 characters then set the flag to 0x01 meaning we are ready to send data. Once data is sent send out the same characters to the other pic which in turn will send the data back in reverse like ~| this way we know its done and can clear the flag.

So to sum it up..

Let me draw it out for you in paint lol
 
Here you go:
pic-jpg.33088
 

Attachments

  • PIC.jpg
    PIC.jpg
    46.7 KB · Views: 538
Last edited:
I'm sorry, but that is far too complicated.

You are not doing anything different if the data is received correctly or not. Either way, new data is sent afterwards. Therefore there is no need to work out if the data was received OK
 
This isnt a data check its a connection check heh It will ensure there is a connection before sending the data out hence it wont get stuck when a connection is made. It will get stuck if you break the link mid way tho. But a easy fix is a timer or watchdog clone heh.

Like time it for double your connection speed. A simple definition would help. And use the timer to count. If data hasnt been received for a complete interrupt or 2 of the timer then its a error and can reset the connection by clearing the flag and restarting it.
 
Status
Not open for further replies.

Latest threads

New Articles From Microcontroller Tips

Back
Top