• 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.

Serial routine problem

Status
Not open for further replies.

scomi

New Member
I am trying to have serial communication in 16F88 over hardware UART. However when i tried the code below, it just halt there and nothing happened.

I declared the temp1 as follows:
Code:
    cblock            0x20
    tmp1
    endc
And the serial communication as follows:
Code:
store_Ah:
    mov16    dd+2,AmpHours
    call     Serial_sent

Serial_sent:
   banksel      SPBRG
   movlw      .25                  ; 9.6kbps
   movwf      SPBRG
   movlw      b'00100100'      ; brgh = high (2)
   movwf      TXSTA            ; enable Async Transmission, set brgh

   ; Provide a settling time for startup
   banksel      tmp1
   clrf       tmp1
   settle
   decfsz       tmp1, f
   goto       settle


   ; Send a character through the UART
loop
   movf AmpHours, w
   call Send
   movf AmpHours+1, w
   call Send
   goto      $

;----------------------
; SEND function
;----------------------
Send
   banksel      TXREG
   movwf       TXREG            ; Send data which has been stored in W

trans_wt
   banksel      TXSTA
   btfss       TXSTA, TRMT         ; Loop until data is sent
   goto      trans_wt      
   return
with baud rate 9600. AmpHours as a 16 bits words.
 

scomi

New Member
The way my tutorial does it is

Code:
XMIT_RS232  	btfss   PIR1,	TXIF 	      ;xmit buffer empty?
     		GOTO	XMIT_RS232            ;no, wait
     		MOVWF   TXREG		      ;now send
                RETURN

Using RS 232 interface for hardware UART?
I am just using serial UART with HUART compatible with pin B5. :)
 

scomi

New Member
Yes, using the hardware UART for RS232, you simply check if the TX buffer is empty before you load the data to it.
Well, how about setting the baud rate? Is it not necessary for that?
Sorry to ask, how to check for the empty buffer? I am beginner on this..
P/S: The variable to be transmit is a 16 bit words, each time only 8 bits are allowed. So, how the variable is transmitted twice using XMIT_RS232? Thanks.
 
Last edited:

Nigel Goodwin

Super Moderator
Most Helpful Member
Well, how about setting the baud rate? Is it not necessary for that?
Of course it is, check my tutorial for the full code, I just posted the part where your code looked to be wrong.

Sorry to ask, how to check for the empty buffer?
As the comments in the code I posted show.

I am beginner on this..
P/S: The variable to be transmit is a 16 bit words, each time only 8 bits are allowed. So, how the variable is transmitted twice using XMIT_RS232?
It isn't, you need to call it twice, just as you do with your faulty 'send' subroutine.
 

scomi

New Member
Of course it is, check my tutorial for the full code, I just posted the part where your code looked to be wrong.
I'd looked through the code in the tutorial:
Code:
;Serial routines
            Xmit_Byte    Equ  0x20        ;holds byte to xmit
            Rcv_Byte     Equ  0x21        ;holds received byte 
            Bit_Cntr     Equ  0x22        ;bit counter for RS232
            Delay_Count  Equ  0x23        ;delay loop counter
SER_INIT
            BSF     STATUS, RP0           ;select bank 1
            BCF     TRISB, 5              ;set B5 as an output
            ;BSF     TRISB, 7              ;set B7 as an input
            BCF     STATUS, RP0           ;select bank 0
            BSF     PORTB, 5              ;set B5 high
            RETURN

XMIT_RS232  MOVWF   Xmit_Byte             ;move W to Xmit_Byte
            MOVLW   0x08                  ;set 8 bits out
            MOVWF   Bit_Cntr
            BCF     PORTB, 5
            CALL    Bit_Delay
Ser_Loop    RRF     Xmit_Byte , f         ;send one bit
            BTFSS   STATUS    , C
            BCF     PORTB, 5
            BTFSC   STATUS    , C
            BSF     PORTB, 5
            CALL    Bit_Delay
            DECFSZ  Bit_Cntr  , f         ;test if all done
            GOTO    Ser_Loop
            BSF     PORTB, 5
            CALL    Bit_Delay
            RETURN

;Rcv_RS232   BTFSC   PORTB, 7              ;wait for start bit
;            GOTO    Rcv_RS232
;            CALL    Start_Delay	          ;do half bit time delay
;            BTFSC   PORTB, 7              ;check still in start bit
;            GOTO    Rcv_RS232
;            MOVLW   0x08                  ;set up to read 8 bits
;            MOVWF   Bit_Cntr
;            CLRF    Rcv_Byte

;Next_RcvBit CALL    Bit_Delay
;            BTFSS   PORTB, 7
;            BCF     STATUS    , C
;            BTFSC   PORTB, 7
;            BSF     STATUS    , C
;            RRF     Rcv_Byte  , f
;            DECFSZ  Bit_Cntr  , f         ;test if all done
 ;           GOTO    Next_RcvBit
 ;           CALL    Bit_Delay
;            MOVF    Rcv_Byte, W
;            RETURN

Start_Delay MOVLW   0x0C
            MOVWF   Delay_Count
Start_Wait  NOP
            DECFSZ  Delay_Count , f
            GOTO    Start_Wait
            RETURN

Bit_Delay   MOVLW   0x18
            MOVWF   Delay_Count
Bit_Wait    NOP
            DECFSZ  Delay_Count , f
            GOTO    Bit_Wait
            RETURN
How if the pin I use already hardware UART compatible? I'd modified the code to suit my needs. All I need to do is just sending 16 bits wide variables out via B5 without receiving anything. Kindly comment on the coding if i made it wrong. Thanks.
 

Nigel Goodwin

Super Moderator
Most Helpful Member
How if the pin I use already hardware UART compatible? I'd modified the code to suit my needs. All I need to do is just sending 16 bits wide variables out via B5 without receiving anything. Kindly comment on the coding if i made it wrong. Thanks.
Check the last tutorial on that page, it shows how to use the hardware UART, the earlier ones use a software UART.
 

scomi

New Member
OK, i'd looked through the code.

So right now, I am having a variable called AmpereHour (16 bits words.).

Code:
store_Ah:
	mov16	dd+2,AmpHours
This is where the variable is manipulated. After this I starts my serial routine like this:

Code:
store_Ah:
	mov16	dd+2,AmpHours
        mov16   TXREG, AmpHours
        call SER_INIT

SER_INIT
            	BSF     STATUS, RP0           ;select bank 1
     		MOVLW   d'129'                ;9600 baud @ 20 Mhz Fosc +0.16 err
     		MOVWF   SPBRG
     		MOVLW   b'00100100'           ;brgh = 1
     		MOVWF   TXSTA                 ;enable Async Transmission, set brgh
            	BCF     STATUS, RP0           ;select bank 0
     		MOVLW   b'10010000'
     		MOVWF   RCSTA                 ;enable Async Reception
            	RETURN

XMIT_RS232  	btfss   PIR1,	TXIF 	      ;xmit buffer empty?
     		GOTO	XMIT_RS232            ;no, wait
     		MOVWF   TXREG		      ;now send
                RETURN
 

Nigel Goodwin

Super Moderator
Most Helpful Member
OK, i'd looked through the code.

So right now, I am having a variable called AmpereHour (16 bits words.).

Code:
store_Ah:
	mov16	dd+2,AmpHours
This is where the variable is manipulated. After this I starts my serial routine like this:

Code:
store_Ah:
	mov16	dd+2,AmpHours
        mov16   TXREG, AmpHours
        call SER_INIT          [COLOR="Red"];after it returns HERE, it then falls back in the SER_INIT subroutine below[/COLOR]
SER_INIT
            	BSF     STATUS, RP0           ;select bank 1
     		MOVLW   d'129'                ;9600 baud @ 20 Mhz Fosc +0.16 err
     		MOVWF   SPBRG
     		MOVLW   b'00100100'           ;brgh = 1
     		MOVWF   TXSTA                 ;enable Async Transmission, set brgh
            	BCF     STATUS, RP0           ;select bank 0
     		MOVLW   b'10010000'
     		MOVWF   RCSTA                 ;enable Async Reception
            	RETURN   [COLOR="red"] ;at this point it does a RETURN without a valid adress to return to and crashes[/COLOR]
XMIT_RS232  	btfss   PIR1,	TXIF 	      ;xmit buffer empty?
     		GOTO	XMIT_RS232            ;no, wait
     		MOVWF   TXREG		      ;now send
                RETURN
Please see comments in red
 

scomi

New Member
Please see comments in red
OK, i think i should call XMIT_RS232 after SER_INT is performed, right goodwin?
Something like this:
Code:
store_Ah:
	mov16	dd+2,AmpHours
        mov16   TXREG, AmpHours
        call SER_INIT   
        call XMIT_RS232
while no RETURN after the transmission.
 

mister_e

New Member
Yes but still... what will happen once XMIT_RS232? You should use another goto to avoid jumping in SER_INIT once again.
 
Status
Not open for further replies.

EE World Online Articles

Loading
Top