Best way to use USART/HSERIN


Closed Thread
Results 1 to 18 of 18

Hybrid View

  1. #1


    Did you find this post helpful? Yes | No

    Default Re: Best way to use USART/HSERIN

    Spending a little more time on the Microchip selector site, I think PIC16F687 might do the trick - 20 pin DIP, 18 I/O pins with Rx on RB5 and RC0-7 available.

  2. #2


    Did you find this post helpful? Yes | No

    Default Re: Best way to use USART/HSERIN

    Coming back to this thread after recovering from some encoder/code porting issues from last week, I'm still trying to figure out the best way to send/receive data from 1 Master chip to 3-4 slaves via USART. I've read over many threads here regarding HSEROUT/HSERIN and the permutations & combinations leave me confused.

    As of last night, I've got a PIC12F1840 sending the following on the Tx pin based on a rotary encoder turn (there's an IOC ISR to determine the direction of turn which sets RotEncDir):
    Code:
    DEFINE OSC 16                ' Set oscillator 16Mhz
    
    DEFINE HSER_TXSTA 20h        ; Set transmit status and control register
    DEFINE HSER_BAUD  2400       ; Set baud rate
    DEFINE HSER_RCSTA 90h
    DEFINE HSER_CLROERR 1        ; Clear overrun error upon
                                 ; execution of every HSERIN
                                 ; command
    
    .
    .
    .
    
    Main:
        TOGGLE LED_0
    
        If ValueDirty = 1 THEN
            ' Send RotEncDir to receiving chip
            '    Chip Id,Itm Id,     <modifier>, "~"
            HSEROUT ["2",   "3", SDEC RotEncDir, TxEndChar]  ' use 'SDEC' if RotEncDir can be -1 for CCW
                
            ValueDirty = 0               ' Clear the flag
    
            #IFDEF USE_LCD_FOR_DEBUG
                HSEROUT [LCD_INST, LCD_CLR]
                pause 5
                '    Chip Id,Itm Id,     <modifier>,  "~"
                HSEROUT ["2",   "3", SDEC RotEncDir, TxEndChar]  ' use 'SDEC' if RotEncDir can be -1 for CCW
            #ENDIF
        ENDIF
     
        pause 500
     
        GOTO Main
    The output on my LCD shows this for a CW turn:
    Code:
    231~
    and this for CCW (RotEncDir actually gets set to 0 but I change it to -1 as on the slave I want to just add this value:
    Code:
    23-1~
    The first number represents the slave chip which is the intended target of the serial data (I'll have 2-3 slaves in this project). The second number represents what to change on that chip with the rotary encoder info. The next part is either '1' for CW or '-1' for CCW (I could go back to using '0' for CCW if that makes the overall serial data easier to interpret on the slaves).
    • Should I have a sync character at the start of the serial data so that on the slave I can determine if new serial data is sent before processing the first message (or there's an error)?
    • Should I convert the HSEROUT line to multiple lines?

    For the slaves, I've decided I need to use a Rx interrupt as I have other code running in the Main loop.
    Code:
    DEFINE OSC 16                ' Set oscillator 16Mhz
    
    DEFINE HSER_TXSTA 20h        ; Set transmit status and control register
    DEFINE HSER_BAUD  2400       ; Set baud rate
    DEFINE HSER_RCSTA 90h
    DEFINE HSER_CLROERR 1        ; Clear overrun error upon
                                 ; execution of every HSERIN
                                 ; command
    .
    .
    .
    ' ***************************************************************
    ' ASM Interrupt Definitions
    ' ***************************************************************
    
    ASM
    INT_LIST  macro    ; IntSource,           Label,  Type, ResetFlag?
            INT_Handler     RX_INT,        _UsartRx,   PBP,  yes
        endm
        INT_CREATE     ; Creates the interrupt processor
    ENDASM
    
    ' Enable interrupt
    @ INT_ENABLE   RX_INT      ; USART Rx interrupt
    
    .
    .
    .
    • Do I need to make the RX_INT a low priority interrupt, or is that only important if there are other time-sensitive interrupts (I am using SPWM_INT.bas for one slave)?
    • As Henrik suggests above, should I make the serial data entirely consistent in terms of number of bytes to make the parsing here easier? If that's true, then I probably need to revert to using '0' for CCW rotary encoder changes.
    • The code below is from DT on another thread but I can't see how the whole serial data (e.g. "231~" for slave chip #2 to increment item #3 by 1) will be pieced together.
    • Does the ISR get 1 byte every time? i.e. the first time it goes into the above ISR, 'SerialData' will be "2" and then the next iteration will have "3"?
    • Should the ISR have the ResetFlag set or not? I've seen both.
    Code:
    '*********** 'ISR for RX_INT interrupt *************************************
    Getbytes:       
        HSERIN [Serialdata]                    ' Get the serial data
        IF Serialdata = SyncByte THEN          ' if it's a Sync byte,
            IF Sync THEN ERROR = 1            '  last command was corrupted
            Sync = 1                          '  indicate Sync was rcvd
            ForMe = 0                          '  ID has not been rcvd
        ELSE
            IF Sync THEN
                IF !ForME THEN                ' if we haven't rcvd the ID
                    IF Serialdata = ID THEN    '  and this byte matches the ID
                        ForMe = 1              '    indicate ID rcvd
                    ELSE
                        Sync = 0              ' Not my packet
                        ForMe = 0              '  reset receive state   
                    ENDIF                      '  and wait for next Sync
                ELSE
                    CmdBuf = serialdata        ' store the command
                    IF CmdRcvd THEN LATE = 1  '  last command not finished
                    CmdRcvd = 1                '  indicate a command was rcvd
                    Sync = 0                  '  reset receive state
                    ForMe = 0                 
                ENDIF
            ENDIF
        ENDIF
    @ INT_RETURN
    All slaves Rx pin will be connected to the master's Tx pin so each slave needs to determine if the serial data is for them or not (which the above code does).
    Last edited by RossWaddell; - 18th March 2013 at 19:01.

  3. #3


    Did you find this post helpful? Yes | No

    Default Re: Best way to use USART/HSERIN

    I've modified Darrel's sample code from this thread (switching to use TMR1 - I couldn't get TMR0 to work) and hooked up my LabX1 board with a PIC16F877A chip jumpered to 4Mhz. It would appear to work except for when the SYNC character appears twice and depending on where it yields a different result.

    Code:
    ':::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
                'Based on Hserin with Darrel Taylor's Instant Interrupts
    ':::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
    '    Program to echo incoming serial data.
    '  RX SYNC byte, if good: ChipID byte, if good: COMMAND, if good: ADJUSTMENT
    
    '   MPASM, LabX-1 , PBP2.47, Using PIC 16F877A @ 4mHz, 9600 Baud
    '   Using Hardware USART and MAX232 to MCS Serial Communicator on PC
    
    ' ***************************************************************
    ' >>>>>>>>>>>>>>>>>    Slave IC ID: 1    <<<<<<<<<<<<<<<<<<<<<<<
    ' ***************************************************************
    
    ChipID          CON "1"
    
    DEFINE OSC 4
    
    DEFINE HSER_RCSTA 90h ' enable serial port, 
    DEFINE HSER_TXSTA 24h ' enable transmit, 
    DEFINE HSER_BAUD 9600 ' set baudrate to 9600                   
    DEFINE HSER_CLOERR  1 ' automatic clear overrun error  
    
    TRISD  = %00000000    ' D to outputs for the LEDs
    TRISC  = %10000000    ' PORTC.7 is the RX input, PORTC.6 is the TX output
    ADCON1 = %00001111    ' Set up ADCON1 register no matter what yr doing!!!                      
            
    ':::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
    INCLUDE "DT_INTS-14.bas"     ' Base Interrupt System
    INCLUDE "ReEnterPBP.bas"     ' Include if using PBP interrupts
    
    ;-- Place a copy of these variables in your Main program -------------------
    ;--   The compiler will tell you which lines to un-comment                --
    ;--   Do Not un-comment these lines                                       --
    ;---------------------------------------------------------------------------
    ;wsave   VAR BYTE    $20     SYSTEM      ' location for W if in bank0
    wsave   VAR BYTE    $70     SYSTEM      ' alternate save location for W 
                                             ' if using $70, comment wsave1-3
    
    ' --- IF any of these three lines cause an error ?? ------------------------
    '       Comment them out to fix the problem ----
    ' -- Which variables are needed, depends on the Chip you are using -- 
    wsave1  VAR BYTE    $A0     SYSTEM      ' location for W if in bank1
    wsave2  VAR BYTE    $120    SYSTEM      ' location for W if in bank2
    wsave3  VAR BYTE    $1A0    SYSTEM      ' location for W if in bank3
    ' --------------------------------------------------------------------------
    
    ':::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
        '   Variable definition
    ':::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
            
    led0       var     PORTD.0
    led1       var     PORTD.1
    led2       var     PORTD.2
    led7       var     PORTD.7
    
    ERROR_LED  VAR led7            ' rename the LED's
    LATE_LED   VAR led2
    HEART_LED  VAR led0
    
    LEDonDELAY CON 4
    
    TxEndChar   CON "~"
    SyncByte    CON "S"
    
    CmdBuf      VAR BYTE
    AdjBuf      VAR BYTE
    SerialData  VAR BYTE
    ERRORtime   VAR BYTE
    LATEtime    VAR BYTE
    HEARTtime   VAR BYTE
    
    state       VAR BYTE         
      Sync      VAR state.0      ' sync byte received
      ForMe     VAR state.1      ' packet is for this device
      CmdRcvd   VAR state.2      ' command has been received
      AdjRcvd   VAR state.3      ' adjustment factor has been received
      ERROR     VAR state.4      ' sync received out of order
      LATE      VAR state.5      ' command received before last one was processed
    
    state = 0                    ' Initialize default value
    
    ' ***************************************************************
    ' ASM Interrupt Definitions
    ' ***************************************************************
    
    ASM
    INT_LIST  macro    ; IntSource,           Label,  Type, ResetFlag?
            INT_Handler   TMR1_INT,      ReloadTMR1,   ASM,  no       ; MUST be first
            INT_Handler   TMR1_INT,      _T1handler,   PBP,  yes
            INT_Handler     RX_INT,        _GetBytes,  PBP,  no
        endm
        INT_CREATE     ; Creates the interrupt processor
    ENDASM
    
    ;--- Change these to match the desired interrupt frequency -------------------
    ;--- See http://DarrelTaylor.com/DT_INTS-14/TimerTemplate.html for more Info.
    @Freq       = 10                  ; Frequency of Interrupts in Hz
    @Prescaler  = 2                   ; Timers Prescaler setting
    T1CON = $10                       ; $30 = Prescaler 1:8, TMR1 OFF
    ; $00=1:1, $10=1:2, $20=1:4, $30=1:8 --  Must match @Prescaler value
    
    ' Enable interrupts
    @ INT_ENABLE  RX_INT        ; enable USART RX_INT interrupts
    @ INT_ENABLE  TMR1_INT      ; enable Timer 1 interrupts
    GOSUB StartTimer            ; Start Timer 1 ('MotorRPM' will be saved on every
                                ; interrupt if dirty
    
    Main:
    ;        High HEART_LED    ' Turn on LED connected to PORTD.0
    ;        Pause 500       ' Delay for .5 seconds
    
    ;        Low HEART_LED         ' Turn off LED connected to PORTD.0
    ;        Pause 500       ' Delay for .5 seconds
    
        IF (CmdRcvd AND AdjRcvd) THEN GOSUB ProcessCmdAdj    ' Process any incomming data
    
        IF ERROR THEN                          ' if there's been an Error
            HIGH ERROR_LED                     '   Turn ON ERROR LED
            ERROR = 0                          '   reset the error flag
            ERRORtime = LEDonDELAY             '   start countdown till LED-OFF
            HSEROUT ["Error",13,10]
        ENDIF
        IF LATE THEN                           ' if command took too long
            HIGH LATE_LED                      '   Turn ON LATE LED
            LATE = 0                           '   reset the LATE flag
            LATEtime = LEDonDELAY              '   start countdown till LED-OFF
            HSEROUT ["Late",13,10]
        ENDIF
    GOTO Main
    
    '*********** Process received command **************************************
    ProcessCmdAdj:
        hserout ["Cmd: ",CmdBuf, _ ' send ChipID, Command, Adjustment and CR/LF
                 " [",DEC CmdBuf,"]",", Adj:",AdjBuf,_
                 " [",DEC AdjBuf,"]",13,10] 
    ;    hserout ["Cmd: ",CmdBuf, " [", _
    ;            DEC CmdBuf,"]",13,10]        
        CmdRcvd = 0                            ' indicate CMD & ADJ has been processed
        AdjRcvd = 0
    RETURN
    
    ' ***************************************************************
    ' [TMR1_INT - interrupt handler]
    ' ***************************************************************
    T1handler:
        IF ERRORtime > 0 THEN                  ' if the Error LED is ON
            ERRORtime = ERRORtime - 1          '   decrement the count
            IF ERRORtime = 0 THEN              '   when it reaches 0
                LOW ERROR_LED                  '   turn the Error LED OFF
            ENDIF
        ENDIF        
        IF LATEtime > 0 THEN                   ' if the LATE LED is ON
            LATEtime = LATEtime - 1            '   decrement the count
            IF LATEtime = 0 THEN               '   when it reaches 0
                LOW LATE_LED                   '   turn the LATE LED OFF
            ENDIF
        ENDIF
        HEARTtime = HEARTtime + 1              ' Toggle heartbeat ~.5sec
        IF HEARTtime = 7 THEN
            HEARTtime = 0
            TOGGLE HEART_LED
        ENDIF       
    @ INT_RETURN
    
    ' ***************************************************************
    ' [RX_INT - interrupt handler]
    ' ***************************************************************
    GetBytes: 
    
    ' Henrik's suggestion (http://www.picbasic.co.uk/forum/showthread.php?t=17685)
    ' I'd probably send equally sized packets each time, perhaps something like sync,
    ' ID, 8 bytes of data, checksum. The slave then waits for the sync, grabs x
    ' number of bytes into an array, evaluates the checksum and if OK checks the ID.
    ' If ID matches it acts on the data otherwise it does nothing.
    
    ' Darrel Taylor's code (http://www.picbasic.co.uk/forum/showthread.php?t=9932&p=65066#post65066)
    
        HSERIN [Serialdata]                    ' Get the serial data
    
        IF Serialdata = SyncByte THEN          ' if it's a Sync byte,
            IF Sync THEN ERROR = 1             '   last command was corrupted
            Sync = 1                           '   indicate Sync was rcvd
            ForMe = 0                          '   ID has not been rcvd
        ELSE
            IF Sync THEN
                IF !ForME THEN                 ' if we haven't rcvd the ID
                    IF Serialdata = ChipID THEN'   and this byte matches the ID
                        ForMe = 1              '   indicate ID rcvd
                    ELSE
                        Sync = 0               ' Not my packet
                        ForMe = 0              '   reset receive state    
                    ENDIF                      '   and wait for next Sync
                ELSEIF !CmdRcvd THEN
                    CmdBuf = serialdata        ' store the command
                    IF CmdRcvd THEN LATE = 1   '   last command not finished
                    CmdRcvd = 1                '   indicate a command was rcvd
                    ;Sync = 0                   '   reset receive state
                    ;ForMe = 0  
                ELSE
                    AdjBuf = SerialData        ' store the command
                    IF AdjRcvd THEN LATE = 1   '   last adjustment not finished
                    AdjRcvd = 1                '   indicate an adjustment was rcvd
                    Sync = 0                   '   reset receive state
                    ForMe = 0                
                ENDIF
            ENDIF
        ENDIF
    
    @ INT_RETURN
    
    ;---[TMR1 reload - interrupt handler]-----------------------------------------
    ASM                               ; Calculate Timer Reload Constant
    ReloadInst  = 8                   ; # of Intructions used to reload timer
      if ((Prescaler == 1)||(Prescaler == 2)||(Prescaler == 4)||(Prescaler == 8))
    MaxCount    = 65536 + (ReloadInst / Prescaler)
    TimerReload = MaxCount - (OSC*1000000/4/Prescaler/Freq)
        if ((TimerReload < 0) || (TimerReload > (65535-ReloadInst)))
            error Invalid Timer Values - check "OSC", "Freq" and "Prescaler"
        endif
      else
          error Invalid Prescaler
      endif
    ENDASM
    
    @Timer1 = TMR1L                   ; map timer registers to a word variable
    Timer1       VAR WORD EXT
    TimerReload  CON EXT              ; Get the External Constant
    TMR1ON       VAR T1CON.0          ; Alias the Timers ON/OFF bit
    
    ;---Reload Timer1------
    ASM
    ReloadTMR1
        MOVE?CT  0, T1CON, TMR1ON     ;  1     stop timer
        MOVLW    LOW(TimerReload)     ;  1     Add TimerReload to the 
        ADDWF    TMR1L,F              ;  1     value in Timer1
        BTFSC    STATUS,C             ;  1/2
        INCF     TMR1H,F              ;  1
        MOVLW    HIGH(TimerReload)    ;  1
        ADDWF    TMR1H,F              ;  1
        MOVE?CT  1, T1CON, TMR1ON     ;  1     start timer
      INT_RETURN
    ENDASM
    
    ;---Start/Stop controls -----
    StartTimer:
        Timer1  = TimerReload         ; Load Timer
        TMR1ON = 1                    ; start timer
    RETURN
    
    StopTimer:
        TMR1ON = 0                    ; stop timer
    RETURN
    I need to capture a 3rd byte (the adjustment to the command feature on the indicated chip) but something's not right - I get strange text in the receive window of the MCS serial window.

    Serial window config:
    Name:  Serial_0.png
Views: 4077
Size:  60.9 KB
    Proper sequence yields correct result:
    Name:  Serial_1.png
Views: 4058
Size:  48.4 KB
    Correct error msg:
    Name:  Serial_1b.png
Views: 4056
Size:  52.3 KB
    Weird error msg:
    Name:  Serial_2.png
Views: 4030
Size:  57.2 KB
    Weird error msg 2:
    Name:  Serial_3.png
Views: 4134
Size:  48.6 KB

    On a side note, any idea why some of the LEDs in the bargraph light up when they're not supposed to? Seems like every time I plug in the Lab X1, different ones light up.
    Name:  photo.JPG
Views: 3926
Size:  176.4 KB

  4. #4


    Did you find this post helpful? Yes | No

    Default Re: Best way to use USART/HSERIN

    The 2 LEDs which are on when they shouldn't be are still perplexing me, but this code works now if anyone's interested:
    Code:
    ' :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
    ' Based on Hserin with Darrel Taylor's Instant Interrupts
    ' :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
    
    '  MPASM, LabX-1 , PBP3, Using PIC 16F877A @ 4mHz, 9600 Baud,
    '  USART and MAX232 to MCS Serial Communicator on PC
    
    ' ***************************************************************
    ' >>>>>>>>>>>>>>>>>    Slave IC ID: 1    <<<<<<<<<<<<<<<<<<<<<<<
    ' ***************************************************************
    
    ThisChipID CON "1"
    
    DEFINE OSC 4
    
    DEFINE HSER_RCSTA 90h ' enable serial port, 
    DEFINE HSER_TXSTA 24h ' enable transmit, 
    DEFINE HSER_BAUD 9600 ' set baudrate to 9600                   
    DEFINE HSER_CLOERR  1 ' automatic clear overrun error  
    
    TRISD  = %00000000    ' D to outputs for the LEDs
    TRISC  = %10000000    ' PORTC.7 is the RX input, PORTC.6 is the TX output
    ADCON1 = %00001111    ' Set up ADCON1 register no matter what yr doing!!!                      
            
    ':::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
    INCLUDE "DT_INTS-14.bas"     ' Base Interrupt System
    INCLUDE "ReEnterPBP.bas"     ' Include if using PBP interrupts
    
    ;-- Place a copy of these variables in your Main program -------------------
    ;--   The compiler will tell you which lines to un-comment                --
    ;--   Do Not un-comment these lines                                       --
    ;---------------------------------------------------------------------------
    ;wsave   VAR BYTE    $20     SYSTEM      ' location for W if in bank0
    wsave   VAR BYTE    $70     SYSTEM      ' alternate save location for W 
                                             ' if using $70, comment wsave1-3
    
    ' --- IF any of these three lines cause an error ?? ------------------------
    '       Comment them out to fix the problem ----
    ' -- Which variables are needed, depends on the Chip you are using -- 
    wsave1  VAR BYTE    $A0     SYSTEM      ' location for W if in bank1
    wsave2  VAR BYTE    $120    SYSTEM      ' location for W if in bank2
    wsave3  VAR BYTE    $1A0    SYSTEM      ' location for W if in bank3
    ' --------------------------------------------------------------------------
    
    ' ***************************************************************
    ' ASM Interrupt Definitions
    ' ***************************************************************
    
    ASM
    INT_LIST  macro    ; IntSource,           Label,  Type, ResetFlag?
            INT_Handler   TMR1_INT,      ReloadTMR1,   ASM,  no       ; MUST be first
            INT_Handler   TMR1_INT,      _T1handler,   PBP,  yes
            INT_Handler     RX_INT,        _GetBytes,  PBP,  yes
        endm
        INT_CREATE     ; Creates the interrupt processor
    ENDASM
    
    ':::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
        '   Variable definition
    ':::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
            
    led0       var     PORTD.0
    led1       var     PORTD.1
    led2       var     PORTD.2
    led7       var     PORTD.7
    
    ERROR_LED  VAR led7            ' rename the LED's
    LATE_LED   VAR led2
    HEART_LED  VAR led0
    
    LEDonDELAY CON 4
    
    TxEndChar   CON "~"
    SyncByte    CON "S"
    
    SerialData  VAR BYTE
    CmdVal      VAR BYTE
    AdjVal      VAR BYTE
    ERRORtime   VAR BYTE
    LATEtime    VAR BYTE
    HEARTtime   VAR BYTE
    
    state         VAR BYTE         
      SyncRcvd    VAR state.0      ' sync byte received
      ForMe       VAR state.1      ' packet is for this device
      CmdRcvd     VAR state.2      ' command has been received
      AdjRcvd     VAR state.3      ' adjustment factor has been received
      MsgRcvd     VAR state.4      ' compelte message received
      ERROR       VAR state.5      ' sync received out of order
      LATE        VAR state.6      ' command received before last one was processed
      SyncIndx    VAR state.7      ' index # of incoming byte
    
    state      = 0                 ' Initialize default values
    
    cmdVal     = 0
    AdjVal     = 0
    serialdata = 0                 ' message sample: "S3B1~"
    
    ;--- Change these to match the desired interrupt frequency -------------------
    ;--- See http://DarrelTaylor.com/DT_INTS-14/TimerTemplate.html for more Info.
    @Freq       = 10                  ; Frequency of Interrupts in Hz
    @Prescaler  = 2                   ; Timers Prescaler setting
    T1CON = $10                       ; $30 = Prescaler 1:8, TMR1 OFF
    ; $00=1:1, $10=1:2, $20=1:4, $30=1:8 --  Must match @Prescaler value
    
    ' Enable interrupts
    @ INT_ENABLE  RX_INT        ; enable USART RX_INT interrupts
    @ INT_ENABLE  TMR1_INT      ; enable Timer 1 interrupts
    GOSUB StartTimer            ; Start Timer 1 ('MotorRPM' will be saved on every
                                ; interrupt if dirty
    
    Main:
        IF MsgRcvd THEN GOSUB ProcessCmdAdj    ' Process incomming data
    
        IF ERROR THEN                          ' if there's been an Error
            HIGH ERROR_LED                     '   Turn ON ERROR LED
            ERROR = 0                          '   reset the error flag
            ERRORtime = LEDonDELAY             '   start countdown till LED-OFF
            HSEROUT ["Error",13,10]
            HSEROUT ["SyncRcvd: ", DEC SyncRcvd,", SyncIndx: ",DEC SyncIndx, _
                    ", ForMe: ", DEC ForMe,", CmdRcvd: ",DEC CmdRcvd, _
                    ", AdjRcvd: ",DEC AdjRcvd,", Cmd: ",CmdVal, ", Adj: ",DEC AdjVal,13,10] 
        ENDIF
        IF LATE THEN                           ' if command took too long
            HIGH LATE_LED                      '   Turn ON LATE LED
            LATE = 0                           '   reset the LATE flag
            LATEtime = LEDonDELAY              '   start countdown till LED-OFF
            HSEROUT ["Late",13,10]
        ENDIF
    GOTO Main
    
    '*********** Process received command **************************************
    ProcessCmdAdj:
        HSEROUT ["Cmd: ", CmdVal, _ ' send ThisChipID, Command, Adjustment and CR/LF
                 ", Adj: ",AdjVal,_
                 " [",DEC AdjVal,"]",13,10]       
        
        state      = 0               ' indicate CMD & ADJ has been processed
    
        cmdVal     = 0
        AdjVal     = 0
    RETURN
    
    ' ***************************************************************
    ' [TMR1_INT - interrupt handler]
    ' ***************************************************************
    T1handler:
        IF ERRORtime > 0 THEN                  ' if the Error LED is ON
            ERRORtime = ERRORtime - 1          '   decrement the count
            IF ERRORtime = 0 THEN              '   when it reaches 0
                LOW ERROR_LED                  '   turn the Error LED OFF
            ENDIF
        ENDIF        
        IF LATEtime > 0 THEN                   ' if the LATE LED is ON
            LATEtime = LATEtime - 1            '   decrement the count
            IF LATEtime = 0 THEN               '   when it reaches 0
                LOW LATE_LED                   '   turn the LATE LED OFF
            ENDIF
        ENDIF
        HEARTtime = HEARTtime + 1              ' Toggle heartbeat ~.5sec
        IF HEARTtime = 7 THEN
            HEARTtime = 0
            TOGGLE HEART_LED
        ENDIF       
    @ INT_RETURN
    
    ' ***************************************************************
    ' [RX_INT - interrupt handler]
    ' ***************************************************************
    GetBytes: 
    ' Darrel Taylor's code (http://www.picbasic.co.uk/forum/showthread.php?t=9932&p=65066#post65066)
    
        HSERIN [Serialdata]                    ' Get the serial data (guaranteed here to have at
    
        IF Serialdata = SyncByte THEN          
            IF SyncRcvd THEN                   ' if it's a Sync byte,
                state = 0                      '   last command was corrupted; reset 'state'
                ERROR = 1                      '   and indicate error
            ENDIF
            SyncRcvd = 1                       '   indicate Sync was rcvd
        ELSE
            IF SyncRcvd THEN
                IF !ForMe THEN                 ' if we haven't rcvd the ID
                    IF Serialdata = ThisChipID THEN 'and this byte matches the ID
                        ForMe = 1              '     indicate ID rcvd
                    ELSE
                        state = 0               '   and wait for next Sync
                    ENDIF                      
                ELSEIF !CmdRcvd THEN
                    CmdVal = SerialData
                    CmdRcvd = 1
                ELSEIF !AdjRcvd THEN
                    AdjVal = SerialData
                    AdjRcvd = 1
                ELSEIF !MsgRcvd THEN
                    If SerialData = TxEndChar THEN
                        MsgRcvd = 1
                    ENDIF
                ENDIF
            ENDIF
        ENDIF
    
    @ INT_RETURN
    
    ;---[TMR1 reload - interrupt handler]-----------------------------------------
    ASM                               ; Calculate Timer Reload Constant
    ReloadInst  = 8                   ; # of Intructions used to reload timer
      if ((Prescaler == 1)||(Prescaler == 2)||(Prescaler == 4)||(Prescaler == 8))
    MaxCount    = 65536 + (ReloadInst / Prescaler)
    TimerReload = MaxCount - (OSC*1000000/4/Prescaler/Freq)
        if ((TimerReload < 0) || (TimerReload > (65535-ReloadInst)))
            error Invalid Timer Values - check "OSC", "Freq" and "Prescaler"
        endif
      else
          error Invalid Prescaler
      endif
    ENDASM
    
    @Timer1 = TMR1L                   ; map timer registers to a word variable
    Timer1       VAR WORD EXT
    TimerReload  CON EXT              ; Get the External Constant
    TMR1ON       VAR T1CON.0          ; Alias the Timers ON/OFF bit
    
    ;---Reload Timer1------
    ASM
    ReloadTMR1
        MOVE?CT  0, T1CON, TMR1ON     ;  1     stop timer
        MOVLW    LOW(TimerReload)     ;  1     Add TimerReload to the 
        ADDWF    TMR1L,F              ;  1     value in Timer1
        BTFSC    STATUS,C             ;  1/2
        INCF     TMR1H,F              ;  1
        MOVLW    HIGH(TimerReload)    ;  1
        ADDWF    TMR1H,F              ;  1
        MOVE?CT  1, T1CON, TMR1ON     ;  1     start timer
      INT_RETURN
    ENDASM
    
    ;---Start/Stop controls -----
    StartTimer:
        Timer1  = TimerReload         ; Load Timer
        TMR1ON = 1                    ; start timer
    RETURN
    
    StopTimer:
        TMR1ON = 0                    ; stop timer
    RETURN
    Any suggestions for improvement gratefully appreciated.

  5. #5
    Join Date
    Jan 2005
    Location
    Montreal, Quebec, Canada
    Posts
    3,172


    Did you find this post helpful? Yes | No

    Default Re: Best way to use USART/HSERIN

    Did you set the pull-up/down jumper for the Lab X1 LEDs?

    I remember I had to set "something".

    Robert

  6. #6


    Did you find this post helpful? Yes | No

    Default Re: Best way to use USART/HSERIN

    No, I didn't Robert. Do I need to do that for all of them?

  7. #7
    Join Date
    Jan 2005
    Location
    Montreal, Quebec, Canada
    Posts
    3,172


    Did you find this post helpful? Yes | No

    Default Re: Best way to use USART/HSERIN

    Check the Lab X1 schematic, I'm pretty sure there was a jumper for this. It handled all the LEDs at once.

Similar Threads

  1. USART to PC
    By tonyfelloni in forum mel PIC BASIC Pro
    Replies: 4
    Last Post: - 15th October 2008, 00:09
  2. Usart
    By lew247 in forum mel PIC BASIC Pro
    Replies: 0
    Last Post: - 2nd June 2008, 23:41
  3. Sharing a USART
    By Ron Marcus in forum Serial
    Replies: 1
    Last Post: - 7th September 2005, 14:48
  4. 9 bit addressable USART
    By barkerben in forum General
    Replies: 9
    Last Post: - 4th January 2005, 22:57

Members who have read this thread : 2

You do not have permission to view the list of names.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts