Menu

Help with Serial connection

Help
bridman
2006-10-13
2013-05-30
  • bridman

    bridman - 2006-10-13

    Hi.  Total newbie here.  I'm trying to work out how to do serial communication, and I am bit confused by the help file for the SerSend command.  The example in the online help file is:

        'This program will send a byte using PORTB.2, the value of which
        'depends on whether a button is pressed.

        #define RecAHigh PORTB.2 ON
        #define RecALow PORTB.2 OFF

        InitSer (1, r9600, 1+WaitForStart, 8, 1, none, normal)
        Main:
         if Button pressed then Temp = 0
         if Button released then Temp = 100
         SerSend (1, Temp)
         Wait 1 s
        goto Main

    Should "RecAHigh" and "RecALow" be "SendAHigh" and "SendALow?"  If not do you need separate channels for sending and receiving, and what are "SendAHigh" and "SendALow?" for anyway?

    Also, I assume that the channel referenced in "RecAHigh" corresponds to channel 1 when you make a SerReceive command.  And the same for B = 2, C = 3, etc.  Is that correct?  I'm just puzzled by the use of letters in one context and numbers in another.  Thanks!

     
    • Nobody/Anonymous

      RecAHigh and RecALow are conditions that are true when a high and a low respectively are being received on channel 1. For sending the constants are SendAHigh and SendALow, which specify the command to call in order to send a high and a low. The constants have been set up this way to allow serial to be sent and received using 38 KHz IR and the PWM module of the PIC.

      The example program should read as follows:

      'This program will send a byte using PORTB.2, the value of which
      'depends on whether a button is pressed.

      #define SendAHigh SET PORTB.2 ON
      #define SendALow SET PORTB.2 OFF

      dir PORTB.2 out
      InitSer (1, r9600, 1+WaitForStart, 8, 1, none, normal)

      Main:
      if Button pressed then Temp = 0
      if Button released then Temp = 100
      SerSend (1, Temp)
      Wait 1 s
      goto Main

      It is possible to use the same pin to send and receive - this would require the use of a DIR command to change the port direction.

      The older help articles were written to show the syntax of the command more than an actual working program, so that program is missing a few things (such as #chip). The #defines are something I missed when adapting the receive example to show a send. The older incomplete examples are gradually being replaced by newer ones that are ready to run with only minor changes, or no changes at all.

      The use of letters and numbers is admittedly odd. Rec1High, Send1High etc will be made valid in the next version of GCBASIC.

      There are already a few issues with the serial that need to be dealt with such as the maximum baud rate. If you have any more trouble or confusion please don't hesitate to post.

       
    • bridman

      bridman - 2006-10-15

      Thanks for that--made things much clearer.  Im trying to get an RFID (Radio Frequency Identification) device to send serial data to a pic which should log the data and then output it to a computer on command.  I'd like to get the pic to read in strings, but I'm having trouble with the syntax.  Does anyone have an example of some GCBASIC code that uses the SerPrint and SerRead commands?  Also, do string variables have to have a dollar sign or something in addition to beng defined with DIM?  Sorry for being so clueless.  As I said in the first post, I'm new to this.  If I  have any success I'll post it.  Thanks.

       
    • Hugh Considine

      Hugh Considine - 2006-10-15

      Strings in GCBASIC are just arrays. dim StringName(40) has exactly the same effect as dim StringName as string * 40. The dollar sign works the same way as the () in GCBASIC - it is used when referring to the string/array as a whole.

      SerPrint is completely untested, and there is no SerRead yet. I'd recommend avoiding them both.

      The morse code demo (http://gcbasic.sourceforge.net/morse code.txt) shows how to work with arrays to store strings of characters. lego.h might also be of interest - there are a few routines in there that send out an array using rs232. In particular, have a look at SendOpcode.

      I'm getting some good ideas here for what GCBASIC needs implemented!

       
    • bridman

      bridman - 2006-10-16

      OK.  I've had a bit of luck with the following code.  It lets me send serial data to hyperlink which then interprets the data as a bunch of gobbledeegook.  So I'm not there yet, but at least I have gotten something to compile.  Here's the code (specific to my chip and oscillator of course) for any other newbies who need help with serial commands.  If anyone can help me with getting serial settings correct for communicating with hyperterminal (or any pc component) please post away.  I've messed around with baud rates (2400 seems most reliable) and inverting the data stream.  I know that a MAX232 chip might help, but it seems like I ought to be able to do without one for low baud rates.  The output on hyperterminal makes me think there might be some sort of frameshift error; however, it displays the wrong number of characters as well as the wrong characters.  Any ideas?

      'testing serial communications

      'Chip model 16F874A with a 4MH crystal oscillator
      #chip 16F874A, 4
      #config XT_OSC
      #mem 192

      'Set up sending serial communications for pin B2

      #define SendAHigh SET PORTB.2 ON 
      #define SendALow SET PORTB.2 OFF 

      'Inititalize the serial conncection

      dir PORTB.2 out

      'Set up a pin for an LED indicator
       
      dir PORTD.3 out
      InitSer (1, r2400, 1+WaitForStart, 8, 1, none, invert)

      'Set variable dimensions and define a string variable

      DIM message as string

      message$ = "testing 1 2 3"

      'Send the message out ten times

      FOR var = 1 TO 10 STEP 1
      SET PORTD.3 ON
      WAIT 500 MS
      SET PORTD.3 OFF
      WAIT 500 MS
      SerPrint (1, message$)
      NEXT

      So that sends SOMETHING to hyperterminal using pin 2 of a 9-pin D-connector (pin 5 to ground).  I'm not sure what I'm sending, because I'm not clear about the syntax for string variables (note that the $ is there in some cases but absent in others--this is what I could get to compile). 

       
    • Hugh Considine

      Hugh Considine - 2006-10-16

      The problem is most likely timing related. First, find this section in rs232.h:

      #script
      Sendr19200 = 5-40/ChipMHz
      Sendr9600 = 10-40/ChipMHz
      Sendr4800 = 21-40/ChipMHz
      Sendr2400 = 42-40/ChipMHz
      Sendr1200 = 83-40/ChipMHz
      Sendr600 = 166-40/ChipMHz
      Sendr300 = 33-40/ChipMHz
      #endscript

      Then, try altering the value on the left side of the "-" for the baud rate you are using. For 2400 bps, increase 42 by one at a time until the correct data appears.

      Also, Wait 500 ms will not work yet, as the Wait command has not been altered to handle numbers over 255. "Wait 50 10ms" will work.

       
    • bridman

      bridman - 2006-10-17

      Thanks again, Hugh.  I'll give it a try tomorrow.  I'm not sure about where to find rs232.h.  Is that part of the source code?  I doubt I have the wherewithal to manipulate source code. 

      An important question for me now is whether there is any way to read in a string of bytes.  I'm working with a device that sends 10 ascii characters at 9600 baud, and I need the PIC to read those characters and store them in a variable.  Can GCBASIC do this?  I must have been halucinating about the SerRead command--I hate it when that happens.  Is there any way to read in 10 consecutive bytes with a series of SerSend commands or something like that?  I'll look at the examples you cited tomorrow and see if there are any leads.

      Finally, 500 ms seems to work.  I didn't actually time it though, so maybe it is only giving me 255 ms.

       
    • Hugh Considine

      Hugh Considine - 2006-10-17

      Here is a SerRead subroutine that you can use:

      sub SerRead(Channel, SerReadData(), numbytes)
      for Counter = 1 to numbytes
        SerReceive Channel, SerReadData(Counter)
      next
      end sub

      To read 10 bytes into message$, use SerRead(1, message$, 10). I'll probably add this to the next version of GCBASIC.

      rs232.h is the file that has all of the rs232 subroutines supplied with GCBASIC. It is in C:\Program Files\GCBASIC\include\lowlevel. Don't worry about messing anything up - it's just GCBASIC code, and if anything bad happens the file can be restored by downloading the .zip version and re-extracting the original rs232.h from it.

      For 9600 bps, the delay would be calculated as 0 ms on a 4 MHz chip! Try substituting this section:
      #script
      Sendr19200 = 5
      Sendr9600 = 10
      Sendr4800 = 21
      Sendr2400 = 42
      Sendr1200 = 83
      Sendr600 = 166
      Sendr300 = 33
      #endscript

      The trouble here is limited testing on my part - I've only tested the 9600 and 4800 bps routines on 20 MHz chips. They should work fine on a 4 MHz chip with a few minor adjustments to timing. The receive is less fussy with timing, as it uses the start and stop bits to synchronize itself.

      The wait would be pausing for 244 ms. If you're happy enough with the program as it is, then don't worry about changing it.

       
    • bridman

      bridman - 2006-10-17

      No dice with altering the timing.  I got either nothing at all or more nonsense.  I'm going to order a 20MHz crystal and try again with that alteration.  I have to get the crystal by mail, so it will be a while.  Thanks again, Hugh, and good luck getting this worked out in the next version.   

       
    • bridman

      bridman - 2006-10-23

      Stumped again....So I have been trying some serial communication with a 20MHz oscillator.  I can now get some degree of communication with a computer, but I cannot get 9600 baud to work very well.  Here is the code I have been using:

      'testing serial communications with RS-2 RFID device

      'Chip model 16F874A with a 20MH crystal oscillator
      #chip 16F874A, 20
      #config HS_OSC
      #mem 192

      'Set up sending serial communications for pins B1 and B2

      #define SendAHigh SET PORTB.2 ON 
      #define SendALow SET PORTB.2 OFF
      #define RecBHigh PORTB.1 ON 
      #define RecBLow PORTB.1 OFF

      'Inititalize the serial conncection

      dir PORTB.2 out 
      dir PORTB.1 in

      InitSer (1, r9600, 1+WaitForStart, 8, 1, none, invert)
      InitSer (2, r9600, 1+WaitForStart, 8, 1, none, invert)

      'Set variable dimensions to define string variables
      'DIM message as string

      'Wait a second for power switch bounce
      Wait 1 s

      'Send a test message first
      SerPrint (1, "Ready to read. ")

      'Set up a neverending loop.
      loop:

      'Now wait to recieve string of data
      'To read 10 bytes into message$, use SerRead(2, message$, 10)
      'SerRead(2, message$, 10)

      SerReceive (2, Temp1)
      SerReceive (2, Temp2)
      SerReceive (2, Temp3)
      SerReceive (2, Temp4)
      SerReceive (2, Temp5)
      SerReceive (2, Temp6)

      wait 250 ms

      SerPrint (1, "the number is: ")

      wait 1 s

      'Send message to computer
      SerSend (1, Temp1)
      SerSend (1, Temp2)
      SerSend (1, Temp3)
      SerSend (1, Temp4)
      SerSend (1, Temp5)
      SerSend (1, Temp6) 

      'Do it again forever
      goto loop

      'Subroutine for reading in string
      'sub SerRead(Channel, SerReadData(), numbytes)
      'for Counter = 1 to numbytes
      'SerReceive Channel, SerReadData(Counter)
      'next
      'end sub

      You may notice that I commented out the SerRead subroutine: it didn't work.  I don't know why because what i have running now does the same thing as the subroutine more or less.  At 9600 baud I get unreadable text.  If I change the in and out baud rates to 4800, then all is well.  If I use 9600 and change the low-level rs232 setting as follows:

      Sendr9600 = 11-40/ChipMHz '(changed the 10 to an 11)

      Then send seems to work but not recieve (the text messages in the program come out fine, but the six "Temp" characters appear to be shifted).  Change invert to normal does nothelp.  Unfortunately, it is the receive function that I need to work at 9600.  So are there any other ways I can adjust timing?  I can get my RFID device to read into the computer just fine, but not into the pic.  Thanks.
        

       
    • Hugh Considine

      Hugh Considine - 2006-10-24

      If you look near the bottom of rs232.h, you'll see a line that says:

      if Ser_Rate = 2 then Wait 2 10us: exit sub     '9600 (35 us)

      Try changing the Wait 2 10us to Wait 3 10us, and see if this helps. I used the send code to test the receive code, so if the send was too fast then the receive is probably also too fast.

       
    • bridman

      bridman - 2006-10-25

      Thanks, Hugh.  I have to attend to some other business for the next few days, but I will try this as soon as I can and post results.

       
    • Steve

      Steve - 2007-01-25

      Do the rs232 routines in the latest rs232.h file work now with the timing?  I'm using an 8mhz pic and not having any luck.  I've tried both 2400 and 300 baud.

       

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.