serial coms - again


Closed Thread
Results 1 to 40 of 58

Hybrid View

  1. #1
    Join Date
    Oct 2005
    Location
    Sweden
    Posts
    3,612


    Did you find this post helpful? Yes | No

    Default

    Hi,
    Try running it a slower baud rate, just as a test - say 2400 baud.

    One thing I have noticed, When I simplify the code to simply read the variable and send say S789 from the serial communicator the LCD changes but displays 007 as if it's picked up the 1st byte and then ignored the rest.
    It is because you just say HSERIN [DEC Normtemp[0]] so PBP grabs the first character which is 7 - change that to DEC3 to grab three digits and properly convert it to 789.
    If I change the HSERIN line by removing DEC statement the LCD displays 055 ???? - I was expecting at least 078 ???
    And this is because you removed the DEC modifier so PBP again grabs one character and 55 is the ASCII code for "7".

    You have to remember that the PC (in this case) doesn't send the "value" 789 it sends the the individual digits representing the number as text "S", "7", "8", "9" if you look at that transmision with your serial port monitor you'll see that what is sent is 83 55 56 57 which are the ASCII codes for S789.

    The DEC modifier converts the text representation of the value into an actual value. If you remove it the value stored in the variable will be the value received - which is 55 when you send "7".

    /Henrik.

  2. #2
    malc-c's Avatar
    malc-c Guest


    Did you find this post helpful? Yes | No

    Thumbs up Now we're getting somewhere

    Full Code:

    Code:
    ASM 
      __CONFIG    _CONFIG1H, _OSC_HSPLL_1H
      __CONFIG    _CONFIG2L, _PWRT_ON_2L  
      __CONFIG    _CONFIG2H, _WDT_ON_2H & _WDTPS_512_2H
      __CONFIG    _CONFIG3H, _PBADEN_OFF_3H
      __CONFIG    _CONFIG4L, _LVP_OFF_4L & _XINST_OFF_4L
    ENDASM
    
    
    DEFINE OSC 48                     ; uses 12Mhz xtal
    
    ADCON1 = $0F
    clear
    
    DEFINE LCD_DREG  PORTB           ' LCD Data port
    DEFINE LCD_DBIT  0               ' starting Data bit (0 or 4)
    DEFINE LCD_EREG  PORTB           ' LCD Enable port
    DEFINE LCD_EBIT  5               '     Enable bit  (on EasyPIC 5 LCD)
    DEFINE LCD_RSREG PORTB           ' LCD Register Select port
    DEFINE LCD_RSBIT 4               '     Register Select bit   (on EasyPIC 5 LCD)
    DEFINE LCD_BITS  4               ' LCD bus size (4 or 8 bits)
    DEFINE LCD_LINES 4               ' number of lines on LCD
    DEFINE LCD_COMMANDUS 2000        ' Command delay time in us 
    DEFINE LCD_DATAUS 50             ' Data delay time in us 
    
    
    ;----[Port settings]----------------------------------------------------
    
    TRISA = %11001111
    TRISB = %00000000
    TRISD = %00001111
    CMCON = 7                                       ' disable Comparators
    
    ;----[USART defines]--------------------------------------------------------
    
    
    DEFINE HSER_RCSTA 90h                           ' Enable serial port & continuous receive
    DEFINE HSER_TXSTA 20h                           ' Enable transmit, BRGH = 0
    DEFINE HSER_CLROERR 1                           ' Clear overflow automatically
    DEFINE HSER_SPBRG 25                            ' 115200 Baud @ 48MHz, 0.16%
    SPBRGH = 0
    BAUDCON.3 = 1                                   ' Enable 16 bit baudrate generator
    ColumnWidth CON 10
    
    
    TempWD            VAR WORD
    RCIF              VAR PIR1.5                    ' USART receive flag
    GIE               VAR INTCON.7
    
    tr var byte
    
    
      
    normtemp          VAR WORD[4]                   ' used to store the desired temperature setting
      normtemp1       VAR normtemp[0]
      normtemp2       VAR normtemp[1]
      normtemp3       VAR normtemp[2]
      normtemp4       VAR normtemp[3]  
    
    nTest var byte
    temphold var byte
    temp var byte
    
    TimeoutCount var byte
    ;---------------------------------------------------------------------
     
    ;set test values
    
      
    normtemp[0]=240
    normtemp[1]=250
    normtemp[2]=260
    normtemp[3]=270
    
    
    
      ;______________________________________________________________
    
    
    gosub FlushBuffer
    
    main:
    
    FOR TempWD = 0 TO 1000
            IF RCIF=1 THEN GOsub Term_RX
            PAUSE 1
    NEXT TempWD
    
    pause 200
    goto main
    
    
    
    Term_RX:
    HSERIN[nTest]
        SELECT CASE nTest
        CASE "S"
           TempWD = 0
        HSERIN 1000,RX_Bombed,[DEC3 TempWD]
        normtemp[0] = TempWD
        gosub send    
        Goto Term_Rx
    RX_Bombed:
        TimeoutCount = TimeOutCount + 1
     lcdOUT $FE,1,"all we got was", dec TempWD,", ", DEC TimeOutCount 
     
        end select 
     
        Goto Term_Rx
     
    Send:
        HSEROUT [DEC normtemp[0],10]
        setpoints(0)=normtemp[0]
        LCDOut $FE,$D4,#setpoints(0)dig 2,#setpoints(0)dig 1,#setpoints(0)dig 0
    RETURN
    
    
    FlushBuffer:
    While PIR1.5
    HSERIN [TempWd]
    WEND
    TempWd=0
    LCDOUT $FE,1,"Buffer flushed"
    RETURN

    I tried this at 2400 baud (having use PIC multicalc to get the Uart setting) and it gave one error and then echoed all the subsequent entry's correctly. I then changed it back to 115200 and it works a treat - even with my friends application.

    Henrick thanks for taking the time out to assist me with this, and for explaining the serial function in laymens terms, I have learnt a lot from your posts.

    Now just got to amend the code so that it does the same for all the other variables

    I think Charles was going to have his application send one long string of all the variables, maybe I should ask him if he can make it user selected so it updates just the one ?

  3. #3
    malc-c's Avatar
    malc-c Guest


    Did you find this post helpful? Yes | No

    Default

    Uhmmm strange things.. I spoke too soon.

    If I follow your example code
    Code:
    Term_RX:
    HSERIN[nTest]
        SELECT CASE nTest
        CASE "S"
           TempWD = 0
        HSERIN 1000,RX_Bombed,[DEC3 TempWD]
        normtemp[0] = TempWD
        gosub send    
        Goto Term_Rx
    RX_Bombed:
        TimeoutCount = TimeOutCount + 1
     lcdOUT $FE,1,"all we got was", dec TempWD,", ", DEC TimeOutCount 
     
        end select 
     
       Goto Term_Rx
    
    FlushBuffer:
    While PIR1.5
    HSERIN [TempWd]
    WEND
    TempWd=0
    LCDOUT $FE,1,"Buffer flushed"
    RETURN
    when the program 1st runs and detects somthing in the buffer it gosubs to Term_RX, but with the goto hi-lighted above the program then never returns to the main program... If I change this to go to main I'm back where I started from...

    I guess I should ask Charles to design his application so that it opens a second window to do the updates, and when it opens that window it sends a Q or P or something which makes the PIC jump to the Term_RX section, and then sends another character when the updating window is closed (sort of click APPLY )

  4. #4
    Join Date
    Oct 2005
    Location
    Sweden
    Posts
    3,612


    Did you find this post helpful? Yes | No

    Default

    Hi,
    That goto was needed in order to test it at my end (I said I modified it), it was never my intention for you to copy/paste that code back into your application - sorry about that.

    With this code:
    Code:
    main:
    FOR TempWD = 0 TO 1000
            IF RCIF=1 THEN GOsub Term_RX
            PAUSE 1
    NEXT TempWD
    pause 200
    goto main
    You are looping around polling the RCIF flag 1000 times in one second (basically). But at 115200 baud you're sending ~11500 bytes or characters per second (one startbit, 8 databots, one stopbot = 10bits per character).

    This means you're sending ~11.5 characters every millisecond. The PICs hardware buffer is only 2 levels deep so you're very likely to overrun the buffer before the HSERIN command is able to grab the data.

    At 2400baud you're only sending 240 characters per second so your polling loop will have no problem catching the RCIF flag and jump to the Term_Rx routine before the buffer overruns.

    Does that make sense?

    /Henrik.

  5. #5
    malc-c's Avatar
    malc-c Guest


    Did you find this post helpful? Yes | No

    Default

    Quote Originally Posted by HenrikOlsson View Post
    Hi,

    You are looping around polling the RCIF flag 1000 times in one second (basically). But at 115200 baud you're sending ~11500 bytes or characters per second (one startbit, 8 databots, one stopbot = 10bits per character).

    This means you're sending ~11.5 characters every millisecond. The PICs hardware buffer is only 2 levels deep so you're very likely to overrun the buffer before the HSERIN command is able to grab the data.

    At 2400baud you're only sending 240 characters per second so your polling loop will have no problem catching the RCIF flag and jump to the Term_Rx routine before the buffer overruns.

    Does that make sense?

    /Henrik.
    Yes, somewhat - no wonder why I was having problems missing the data... so is it better to reduce the baud rate for the port or reduce the for next loop steps ?

  6. #6
    Join Date
    Oct 2005
    Location
    Sweden
    Posts
    3,612


    Did you find this post helpful? Yes | No

    Default

    Hi Malcolm,
    If the PC starts to send S789 right at the beginning of the Pause 1 statment all four bytes will have been sent before the PIC checks the RCIFlag and your data will be messed up. So, as you say, either check the flag more often or reduce the baudrate so that you are sure that a maximum of two characters can arrive while you are not watching - so to speak.

    Actually, there can be two bytes in the buffer and a third on its way in without messing it up. But as soon as the last bit of that third byte is shifted in you're in trouble if there's no room in the two byte buffer.

    Let me see if I've got the overall scheme correct.
    ** The PIC does its thing, running the PID and everything. Each time thru its main loop it checks the RCIFlag.
    ** The PC, when it needs attention sends a single character "Q" to the PIC and waits.
    ** The PIC sees the RCIFlag and gets the character (there's no problem here since a single character will sit in the buffer untill you get around to read it)
    ** The PIC compares the received character to "Q" and sends something back to say "OK, hit me" - it then goes to the loop we've been discussing.

    That should work..... At 115200 baud two characters takes roughly 175us so you need to check the RCIF flag at least that often. I'd probably go with something like:
    Code:
    WaitHere:
    For I = 0 to 10000
      If RCIF = 1 then GOSUB Term_Rx
      PauseUs 100
    Next
    Keep it up!
    /Henrik.

  7. #7
    malc-c's Avatar
    malc-c Guest


    Did you find this post helpful? Yes | No

    Default

    Quote Originally Posted by HenrikOlsson View Post
    Hi Malcolm,


    Let me see if I've got the overall scheme correct.
    ** The PIC does its thing, running the PID and everything. Each time thru its main loop it checks the RCIFlag.
    ** The PC, when it needs attention sends a single character "Q" to the PIC and waits.
    ** The PIC sees the RCIFlag and gets the character (there's no problem here since a single character will sit in the buffer untill you get around to read it)
    ** The PIC compares the received character to "Q" and sends something back to say "OK, hit me" - it then goes to the loop we've been discussing.


    /Henrik.
    Pretty much it. As far as I understand Charles has programmed his code to send Q when the program is first launched, this was so that we could use Q as a trigger to jump to a subroutine and have the PIC send the data string.... then the user over types the value in the target temperature box and then when the Update button is clicked it sends Snnn to the PIC, followed by Q to refresh the PC application.

    I've tried migrating the test code over to the main code that you were involved in and have discovered one issue. On launching the application the LCD stops running, but I can set the temperature set point via the application on the PC, which upon pressing the Update button the value on the LCD changes to match. However whilst the application is still open the LCD is still not updated. If I then close the application it still locks up and I have to restart the PIC.

    At the moment I've reduced the
    Code:
    FOR TempWD = 0 TO 1000
    to
    Code:
    FOR TempWD = 0 TO 10
    so at 115200 baud rate that should equate to 115 bytes as second (? yes)

    If RCIF=1 it gosubs to the TERM_RX

    Code:
    Term_RX:
    HSERIN [nTest]
        SELECT CASE nTest
        CASE "S"
           TempWD = 0
        HSERIN 1000,RX_Bombed,[DEC3 TempWD]
        normtemp[0] = TempWD   
        SetPoints(0)=normtemp[0]
        goto Term_TX
      
    return
    
    RX_Bombed:
        TimeoutCount = TimeOutCount + 1 
        end select 
        Goto Term_Rx
    Term_TX is simply

    Code:
    Term_TX:
    
    Hserout [DEC3 Temperatures(0)]
    Hserout [DEC3 Temperatures(1)]
    Hserout [DEC3 Temperatures(2)]
    Hserout [DEC3 Temperatures(3)]
    
    HSEROUT [dec3 normtemp[0]]
    HSEROUT [dec3 normtemp[1]]
    ....
    ...
    ...... etc etc 
    
    gosub flushBuffer 
    goto main
    If I close the down the application and even disconnect the cable from the EasyPIC board the PIC is still frozen....

    Any idea ?

Members who have read this thread : 0

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