16F88 RB5 UART

Discussion in 'Embedded Systems and Microcontrollers' started by twister, Apr 9, 2009.

  1. twister

    Thread Starter Member

    Mar 31, 2009
    15
    0
    As depicted in the 16F88 data sheet, port B 5 have the built in hardware UART function which made serial transmission easier.

    [​IMG]

    However I am new to assembly language. To have RB5 send serial data, I am trying to modify the code shown as below:

    I declare the variable for settling time for start up:
    Code ( (Unknown Language)):
    1. ;----------------------
    2. ; DECLARE VARIABLES
    3. ;----------------------
    4.  
    5. cblock         [COLOR=Red][B]0x20[/B][/COLOR]
    6. tmp1
    7. endc
    and the serial transmission is called:

    Code ( (Unknown Language)):
    1.  
    2.  
    3. Ser_sent:
    4.    banksel      SPBRG
    5.    movlw      2580            ; 9.6kbps
    6.    movwf      SPBRG
    7.    movlw      b'00100000'         ; brgh = high (2)
    8.    movwf      TXSTA            ; enable Async Transmission, set brgh
    9.  
    10.    ; Provide a settling time for startup
    11.    banksel      tmp1
    12.    clrf       tmp1
    13.    settle
    14.    decfsz       tmp1, f
    15.    goto       settle
    16.  
    17.  
    18.    ; Send a character through the UART
    19. loop
    20.    movlw      AmpHours
    21.    call      send
    22.    goto      $
    23.  
    24. ;----------------------
    25. ; SEND function
    26. ;----------------------
    27. send
    28.    banksel      TXREG
    29.    movwf       TXREG            ; Send data which has been stored in W
    30.  
    31. trans_wt
    32.    banksel      TXSTA
    33.    btfss       TXSTA, TRMT         ; Loop until data is sent
    34.    goto      trans_wt      
    35.    return
    36.  
    37.    end
    The AmpHour is stored previously as:

    Code ( (Unknown Language)):
    1. store_Ah:
    2.     mov16   dd+2,AmpHours
    3.  
    How about the tem1 timing for a baud rate of 9.6kbps suggested? Thanks
     
  2. t_n_k

    AAC Fanatic!

    Mar 6, 2009
    5,448
    782
    Apologies if I have not understood the question ...

    Are you actually asking whether setting SPBRG = 2580 would be correct for a baud rate of 9.6kbps?

    If so you need to know the clock frequency.
     
  3. twister

    Thread Starter Member

    Mar 31, 2009
    15
    0
    Oh yes..u are right. But i am using 4MHZ internal clock, so for 8 bits, I need to use .25 for it.
    However i am much more concern on is the code runable....especially my variable that passing the value...the AmpHour.
     
  4. t_n_k

    AAC Fanatic!

    Mar 6, 2009
    5,448
    782
    Is the command "mov16" in the 16F88 assembly instruction set?
     
  5. twister

    Thread Starter Member

    Mar 31, 2009
    15
    0
    mov16 actually is macro defined as follows:
    Code ( (Unknown Language)):
    1. ;====================================================================
    2. ;               16 bit macros (Big-Endian)
    3. ;
    4. mov16   MACRO   src,dst
    5.     movf    src,w
    6.     movwf   dst
    7.     movf    src+1,w
    8.     movwf   dst+1
    9.     ENDM
    10.  
    I just know how to pass the literal value of AmpHour to the W register... but it is useless as i need my register has the value for AmpHour. Any advice? It is urgent...
     
  6. twister

    Thread Starter Member

    Mar 31, 2009
    15
    0
    I'd stored AmpHour(AH) like this:
    Code ( (Unknown Language)):
    1. store_Ah:
    2.     mov16   dd+2,AmpHours
    3.  
    If I want to move it to the W register for transmission...how am i able to call it? Thanks..
     
  7. t_n_k

    AAC Fanatic!

    Mar 6, 2009
    5,448
    782
    So it looks like AmpHours is a 16bit value. Presumably the first (high or low) byte is stored at a defined register variable AmpHours and the second byte at AmpHours+1....?

    Since you can only send one byte at a time through the serial port you would have to move the AmpHours high and low bytes sequentially into WREG and then call the Send routine to send the current (Hi or Lo) byte value.

    But - Maybe you already know this - Is your problem that you don't know how to transfer AmpHours to the WREG?
     
  8. t_n_k

    AAC Fanatic!

    Mar 6, 2009
    5,448
    782
    Hope this isn't too trivial or blatantly obvious - you can use MOVFF anywhere in the 4096 byte data space to move contents of one register to another.

    Would ...

    MOVFF AmpHours,W

    or

    MOVFF AmpHours+1,W

    be what you intend? Provided AmpHours+1 is allowed in the command.
     
  9. t_n_k

    AAC Fanatic!

    Mar 6, 2009
    5,448
    782
    Sorry that last post was done with PIC18F in mind - no MOVFF for the PIC16F. Obviously disregard that one!
     
  10. t_n_k

    AAC Fanatic!

    Mar 6, 2009
    5,448
    782
    OK - Have you declared AmpHours as a variable somewhere?
     
  11. twister

    Thread Starter Member

    Mar 31, 2009
    15
    0
    yes.. i declared it as WORD:

    Code ( (Unknown Language)):
    1. ; AmpereHours
    2.     WORD    AmpHours ; Amps * Hours
    3.  
    I called AmpHour displayed as this way:
    Code ( (Unknown Language)):
    1. ;--------------------------------------------------------------------
    2. ;                  Display Amperes * Hours on LCD
    3. ;
    4. Show_AmpHours:
    5.     mov16    AmpHours,Number
    6.     call    bin2dec
    7.     movlw    ' '
    8.     call    Print_Char
    9.     call    ShowDec2    ; display "xx.xx"
    10.     movlw    'A'
    11.     call    Print_Char
    12.     movlw    'h'
    13.     call    Print_Char
    14.     return
    And AmpHours is calculated as follows:
    Code ( (Unknown Language)):
    1. calc_Ah:
    2.     add1632    Amps,AmpSum    ; AmpSum = accumulated Amps
    3.     mov32    AmpSum,dd
    4.     movi16    3600*3,aa    ; 3 reads per second, 3600 seconds per hour
    5.     call    Div32        ; AmpHours = AmpSum  / (reads per hour)
    6. store_Ah:
    7.     mov16    dd+2,AmpHours

    Macros to create variables in RAM

    Code ( (Unknown Language)):
    1. ByteAddr    SET 32     ; user RAM starts here
    2.  
    3. BYTE        MACRO   ByteName
    4. ByteName    EQU ByteAddr
    5. ByteAddr    SET ByteAddr+1
    6.         ENDM
    7.  
    8. WORD        MACRO   WordName
    9. WordName    EQU ByteAddr
    10. ByteAddr    SET ByteAddr+2
    11.         ENDM
    12.  
    13. LONG        MACRO   LongName
    14. LongName    EQU ByteAddr
    15. ByteAddr    SET ByteAddr+4
    16.         ENDM
    17.  
     
  12. t_n_k

    AAC Fanatic!

    Mar 6, 2009
    5,448
    782
    Hi twister,

    This is getting more complex - I'm no longer sure I can be of any help. Perhaps I don't have a clear understanding of what your question is.

    Hopefully someone else might be able to better assist you.

    :(
     
  13. twister

    Thread Starter Member

    Mar 31, 2009
    15
    0
    Sorry....what I want to do is:
    Having 16 bits WORDS of AmpHour move to TXREG so that it can transmit serially.
    I really need your help as i juz leaving this minor part which i used to figure out for 1 week ady. Thanks and i appreciate ur help.
     
  14. t_n_k

    AAC Fanatic!

    Mar 6, 2009
    5,448
    782
    Which compiler are you using?
     
  15. twister

    Thread Starter Member

    Mar 31, 2009
    15
    0
    I am using MPLAB IDE as the compiler. It can be run in onhonsoft as well.
     
  16. t_n_k

    AAC Fanatic!

    Mar 6, 2009
    5,448
    782
    I'm not sure whether this will work but try something like ...

    1. Add a user variable

    cblock 0x20
    .
    .
    .
    tx_Bytes ; place of starting byte for 2-byte transmission
    endc

    2. When AmpHours is evaluated add a line of code

    mov16 AmpHours, tx_Bytes ; store the AmpHours value

    3. Then to transmit 2 bytes of data

    movf tx_Bytes,0 ;transmit high byte valuemoved to WREG
    call send
    ;send the high byte via UART

    movf tx_Bytes+1,0
    ;transmit low byte value moved to WREG
    call send ;send the low byte via UART

    what I'm not sure about is whether the AmpHours value is the actual 2-byte value you want to send - you mentioned the literal AmpHours passed value in an earlier post as being a problem for you.

    If so ...for what it's worth....?

    I have found a literal unpacking macro for a 32-bit literal as follows. Here "Var" is the 32 bit literal to be unpacked as four bytes beginning at address location "Address". You could modify the code to a 16-bit unpack macro [Unpack16] with AmpHours assigned to Var and tx_Bytes assigned to Address. Might be useful.

    Unpack32 MACRO Var, Address ;Var = 32 bit literal to be unpacked
    BANKSEL Address ;Address specifies the LSB start
    movlw Address ;Use FSR and INDF for indirect
    movwf FSR ;access to desired address
    movlw Var & H'FF' ;Mask to get LSB
    movwf INDF ;Put in first location
    movlw Var >>D'08' & H'FF';Mask to get next byte of literal
    incf FSR,F ;Point to next byte
    movwf INDF ;Write data to next byte
    movlw Var >>D'16' & H'FF';Mask to get next byte of literal
    incf FSR,F ;Point to next byte
    movwf INDF ;Write data to next byte
    movlw Var >>D'24' & H'FF';Mask to get last byte of literal
    incf FSR,F ;Point to last byte
    movwf INDF ;Write data to last byte
    ENDM ;End of the Macro Definition
     
  17. twister

    Thread Starter Member

    Mar 31, 2009
    15
    0
    OK t_n_k, I am gonna do something like this:

    I am now having a register called AmpHours, it is a 16-bits binary variable. I am planning to send the content of this via serial transmission to another module. Here, I want to use pin B5 as it is hardware UART built, which is simpler. However I tried the my method but in vain. Hereby I attach the code which I'd implemented. I'd highlighted the part where I added for the serial routine. Hopefully I can get help from you guys as soon as possible. Thanks.

    P/S: Until this stage, if i use the code that i attached, it just manage to display the sign on message, and it halts there.
     
Loading...