Menu

SerReceive only capturing one digit

Help
2014-01-29
2014-02-07
  • Jack Hoffnung

    Jack Hoffnung - 2014-01-29

    Have written a simple program using SerReceive to capture output from my PC keyboard. It works with digits 0-9, but only captures the first digit with 10 or larger. I have dimensioned the captured variable as a byte, and have tried using two different terminal programs with the same result. I'm thinking I'm missing something simple; any help appreciated.

     
  • Anobium

    Anobium - 2014-01-29

    Post your code, or a subset of your code, to help understanding.

    Thank you.

     
  • Jack Hoffnung

    Jack Hoffnung - 2014-01-29

    Thank you for responding to this query. Below is the code, and attached is a picture of what I see on my terminal following several responses.
    There are actually 2 things I don’t understand; first why the “Type number to convert “ always shows up twice when I first run the program, and second, why SerReceive appears to only capture the first digit of my keyboard response.

    ~~~~~
    ;This program takes num <=255, "converts" it to binary
    ;by showing result via serial transmission.

    ;Chip Settings
    #chip 12F683,8

    #config OSC=INT
    ;Defines (Constants)
    #define SerInPort GPIO.3
    #define SerOutPort GPIO.5

    #define SendAHigh Set SerOutPort on
    #define SendALow Set SerOutPort off
    #define RecAHigh SerInPort on
    #define RecALow SerInPort off
    #define cr 13
    #define lf 10

    ;Variables
    Dim num, divby, bid, rm As byte

    dir GPIO out
    dir SerInPort in
    InitSer 1, r4800, 1+WaitForStart, 8, 1, none, invert

    do

    divby = 128
    SerPrint 1, "Type number to convert (<= 255) "
    SerSend 1, cr :SerSend 1, lf
    SerReceive 1, num
    SerPrint 1, "You typed " : SerSend 1, num : SerSend 1, cr :SerSend 1, lf

    num = num - 48

    Repeat 8
    If divby > num Then
    bid = 0
    rm = num
    Else
    bid = 1
    rm = num % divby
    End If
    SerPrint 1, bid
    num = rm
    divby = divby/2
    End Repeat
    SerSend 1, cr :SerSend 1, lf
    loop

    NB: Edit by Anobium only to sorted the layout.... Please use indents and 5 tilders before posting code.

     

    Last edit: Anobium 2014-01-29
  • Anobium

    Anobium - 2014-01-29

    This is not something I have come across. I can build your setup at the weekend.

    Try this.
    - Remove the REPEAT and change to a FOR/NEXT as there is a known issue with REPEAT.
    - Check your circuit. Is the chip resetting to cause the two lines to be serialised?

     

    Last edit: Anobium 2014-01-29
  • Chuck Hellebuyck

    I'm not sure I understand your setup.
    You say you are getting values from your keyboard but it looks like you are receiving data from a serial port.
    When you type a value and the PC sends it out the serial port it is broken into ASCII bytes.
    So 37 is broken into a byte containing 3 and a second containing 7.
    Your program only is receiving one byte so it gets the first digit only and misses the second.

    Add a second SerReceive to get the second byte.
    Add a third for the third byte(255).

    I don't know the SerReceive command well enough but according to the manual I don't see a timeout option so you may need to put the SerReceive lines in a timed loop otherwise a single byte could hang it up. Or just always send three bytes i.e. 002 or 010.

     
  • Jack Hoffnung

    Jack Hoffnung - 2014-01-30

    I really appreciate the efforts in helping me figure this out.
    To clarify my setup, I have a serial cable connecting my PC and the 12F683, I am running Free Serial Port Terminal (although the results are the same with
    other terminal programs I have tried), and I am typing decimal number to be processed on my PC keyboard. Serial input is onto pin 4, and Serial output from pin 2 of the PIC.

    • I changed Repeat to a For/Next loop, but that did not change anything.
    • If a chip reset is occurring to cause the first SerPrint command to execute twice, I don’t know how to check for that. I did recheck my wiring and found nothing loose or otherwise iffy. Could that problem be related to the contents of my gbasic.ini file?
    • Thank you for helping me understand that even a “single digit” being received on the serial port is a byte; I changed my code to reflect that, and except for the double line at the beginning, it works now.
    • There is one more wrinkle to this; after the double line is seen on the terminal, the program halts until I check and then uncheck the /MCLR box under VDD target on the PICkit2 software software. Is this a clue?

    Below find my revised code:

    ~~~~
    ;This program takes num <=255, "converts" it to binary
    ;by showing result via serial transmission.

    ;Chip Settings
    #chip 12F683,8

    #config OSC=INT
    ;Defines (Constants)
    #define SerInPort GPIO.3
    #define SerOutPort GPIO.5

    #define SendAHigh Set SerOutPort on
    #define SendALow Set SerOutPort off
    #define RecAHigh SerInPort on
    #define RecALow SerInPort off
    #define cr 13
    #define lf 10

    ;Variables
    Dim numhunds, numtens, numones, count, divby, bid, rm As byte

    dir GPIO out
    dir SerInPort in
    InitSer 1, r4800, 1+WaitForStart, 8, 1, none, invert

    do
    divby = 128
    SerPrint 1, "Type 3 digit number"
    SerPrint 1, " to convert (<= 255) "
    SerSend 1, cr : SerSend 1, lf
    SerReceive 1, numhunds : SerReceive 1, numtens : SerReceive 1, numones
    SerPrint 1, "You typed "
    SerSend 1, numhunds : SerSend 1, numtens : SerSend 1, numones
    SerSend 1, cr : SerSend 1, lf
    numhunds = numhunds - 48
    numtens = numtens - 48
    numones = numones - 48
    num = (numhunds * 100) + (numtens * 10) + numones
    SerPrint 1, num
    SerSend 1, cr : SerSend 1, lf
    For count = 0 to 7
    If divby > num Then
    bid = 0
    rm = num
    Else
    bid = 1
    rm = num % divby
    End If
    SerPrint 1, bid
    num = rm
    divby = divby/2
    Next
    SerSend 1, cr :SerSend 1, lf
    loop

    Anobium, please please use five tilders before posting your code. Edited to revise formatting only.

     

    Last edit: Anobium 2014-02-01
  • Jack Hoffnung

    Jack Hoffnung - 2014-01-30

    I just discovered that if I use a different pin (not the MCLR pin) for SerInPort, no double line, but still have to check and uncheck /MCLR for the program to run.

     
  • Chuck Hellebuyck

    Are you sending 3 digit numbers?
    If not, the program will sit and wait for the third byte that will never come.

    Clicking Mclr on and off just resets the pic and it starts working again.

     
  • Anobium

    Anobium - 2014-02-01

    Try this. I changed the method but it works for me. You will to revert the chip, serial etc. etc.

    I essentially create and manage a string, when 3 numbers or the return key is pressed the numeric value is returned.

    You can add handlers to key the number below 256 by changing the sub to a WORD and then handle in your main code. You have lots of options. :-)

    Post your working code when you have got it all working, please.

    ~~~~
    ;This program takes num <=255, "converts" it to binary
    ;by showing result via serial transmission.

    ' [todo] Ensure this location of this include file is correct
    #include "D:\Others\GCB@Syn\GreatCowBasic\include\outputserial.h"
    

    ;Chip Settings
    #chip 16F1937,32
    #config Osc = intOSC, MCLRE_OFF, PLLEN_ON, VCAPEN_OFF

    ;Defines (Constants)
    ' [todo] This is the config for a serial terminal
    ' turn on the RS232 and terminal port.
    ' Define the USART port
    #define USART_BAUD_RATE 9600
    #define USART_BLOCKING
    ' [todo] Ensure these port addresses are correct
    #define SerInPort PORTc.7
    #define SerOutPort PORTc.6
    'Set pin directions
    Dir SerOutPort Out
    Dir SerInPort In

    ' [todo] This assumes you are using an ANSI compatible terminal.  Use PUTTY.EXE it is very easy.
    
        wait 1 s
        ANSIERASECREEN
        ANSI ( 0, 2)
        HSerPrint "Started: "
        ANSI ( 0, 6)
    

    #define cr 13
    #define lf 10

    ;Variables
    Dim numhunds, numtens, numones, count, divby, bid, rm As byte

    ' InitSer 1, r4800, 1+WaitForStart, 8, 1, none, invert

    do
    divby = 128
    HserPrint "Type 3 digit number"
    HserPrint " to convert (<= 255) "
    HSerSend cr : hSerSend lf

    GetNum ( num )
    HSerSend cr : hSerSend lf

    For count = 0 to 7
    If divby > num Then
    bid = 0
    rm = num
    Else
    bid = 1
    rm = num % divby
    End If
    HserPrint bid
    num = rm
    divby = divby/2
    Next
    HSerSend cr :hSerSend lf
    loop

    ' get the serial character, create a string of up to 3 chars, then take the value of that string and return a numeric value.

    Sub GetNum ( Out InputVal ) as byte
    dim inputstring as string * 3
    Dim inputstringpointer as byte
    inputstringpointer = 1

      ' init SNum of you will create an endless on the second call this this sub.
      SNum = 255
    
           ' stay in loop Until CR is pressed or 3 chars entered
           Do while SNum <> 13 and  inputstringpointer < 4
              HSerReceive SNum
    
              ' limit string handlers to NUMBERS only
              IF SNum > 0x2f AND  SNum < 0x3A Then
                          HSerSend SNum
                          ' add the char to the string
                          inputstring ( inputstringpointer ) = SNum
                          inputstring ( 0) = inputstringpointer
                          inputstringpointer++
              END IF
    
              'the delete Key
              IF SNum = 0x7f then
                  HSerSend SNum
                  ' remove the last char from the string
                  if inputstringpointer > 1 then
                     inputstringpointer--
                     inputstring ( 0) = inputstringpointer
                  end if
              End iF
    
           Loop
           ' get the value
           InputVal = val ( inputstring )
    

    End Sub

     
  • Anobium

    Anobium - 2014-02-04

    A revised version. This version works. :-)

    ~~~~
    ;This program takes num <=255, "converts" it to binary
    ;by showing result via serial transmission.

    ' [todo] Ensure this location of this include file is correct
    #include "D:\Others\GCB@Syn\GreatCowBasic\include\outputserial.h"
    

    ;Chip Settings
    #chip 16F1937,32
    #config Osc = intOSC, MCLRE_OFF, PLLEN_ON, VCAPEN_OFF

    ;Defines (Constants)
    #define CLEARCARRY set STATUS.C OFF
    #define CARRYOVERFLOW STATUS.C

    ' [todo] This is the config for a serial terminal
        ' turn on the RS232 and terminal port.
        ' Define the USART port
        #define USART_BAUD_RATE 9600
        #define USART_BLOCKING
    ' [todo] Ensure these port addresses are correct
        #define SerInPort PORTc.7
        #define SerOutPort PORTc.6
        'Set pin directions
        Dir SerOutPort Out
        Dir SerInPort In
    
    ' [todo] This assumes you are using an ANSI compatible terminal.  Use PUTTY.EXE it is very easy.
    
        wait 1 s
        ANSIERASECREEN
        ANSI ( 0, 2)
        HSerPrint "Started: "
        ANSI ( 0, 6)
    

    #define cr 13
    #define lf 10

    ;Variables
    Dim numhunds, numtens, numones, count, divby, bid, rm As byte
    dim num as word

    ' InitSer 1, r4800, 1+WaitForStart, 8, 1, none, invert

    do
    HserPrint "Type 3 digit number"
    HserPrint " to convert (<= 255) "
    HSerSend cr : hSerSend lf
    num = 0
    GetNum ( num )
    HSerSend cr : hSerSend lf

            if num > 255 then
               HserPrint "Error! Number larger than 255"
               HSerSend  cr : hSerSend  lf
            ELSE
    
              divby = 128
              For lcount = 0 to 7                           
                If divby > num Then                 
                          bid = 0                           
                          rm = num                      
                Else
                          bid = 1                           
                          rm = num % divby          
                End If
                HserPrint  bid                  
                num = rm                            
                divby = divby/2                     
              Next
              HSerSend  cr :hSerSend  lf
            END IF
    

    loop

    ' get the serial character, create a string of up to 3 chars, then take the value of that string and return a numeric value.

    Sub GetNum ( Out InputVal as word )
    dim inputstring as string * 3
    Dim inputstringpointer as byte
    inputstringpointer = 1
    ' init SNum of you will create an endless on the second call this this sub.
    SNum = 255

           ' stay in loop Until CR is pressed or 3 chars entered
           Do while SNum <> 13 and  inputstringpointer < 4
              HSerReceive SNum
    
              ' limit string handlers to NUMBERS only
              IF SNum > 0x2f AND  SNum < 0x3A Then
                          HSerSend SNum
                          ' add the char to the string
                          inputstring ( inputstringpointer ) = SNum
                          inputstring ( 0) = inputstringpointer
                          inputstringpointer++
              END IF
    
              'the delete Key
              IF SNum = 0x7f then
                  HSerSend SNum
                  ' remove the last char from the string
                  if inputstringpointer > 1 then
                     inputstringpointer--
                     inputstring ( 0) = inputstringpointer
                  end if
              End iF
    
           Loop
           ' get the value
    
           InputVal = val ( inputstring )
    

    End Sub

     
  • Jack Hoffnung

    Jack Hoffnung - 2014-02-04

    Thanks so much for your interest in this; I'm sure I'll learn much from studying your code.

     
  • Anobium

    Anobium - 2014-02-07

    Pleasure.

    A few interesting pieces in this code.

    Use of string array to capture the input, then, using VAL to change to a WORD variable.
    Addressing the string as an array (which is fully supported).
    Use of a WORD variable to capture numbers bigger then 255.

    I did try to use STATUS.C... ignore that! :-)

     

Log in to post a comment.

Want the latest updates on software, tech news, and AI?
Get latest updates about software, tech news, and AI from SourceForge directly in your inbox once a month.