Menu

Low speed communication between two pic16f's

Help
fisyon
2017-03-16
2017-03-18
  • fisyon

    fisyon - 2017-03-16

    hi,
    i want to send 3 bytes from pic16f628a to pic16f877a (by hardware serial if possible)
    628a running on 32768hz crystal and 877a is on 20Mhz.

    my code for 628a:

    #chip 16F628a, 0.032768
    #config Osc=LP, BODEN=off, WDT=off
    #define UART_BAUD_RATE 150
    #define TestLed Portb.6
    
    dim Ticks as bit
    dim Hours as byte
    dim Mins as Byte
    dim Secs as Byte
    
    
    
    InitTimer0 osc, PS0_32
    on interrupt timer0overflow call t0ov
    StartTimer 0
    
    'main
      do
        if ticks=1 then
          if Secs<59 Then
              Secs+=1
            Else
              Secs=0
              if Mins<59 Then
                Mins+=1
              Else
                Mins=0
                if Hours<23 Then
                  Hours+=1
                Else
                  Hours=0
                end if
              end if
            end if
    
          ticks=0
          set TestLed on
          wait 100 ms
          set TestLed off
          wait 100 ms
    
    
            HSerPrint Hours
            HSerPrint Mins
            HSerPrint Secs
    
          HSerPrintCRLF
    
        end if
    
    
       loop
    'end main
    
    sub t0ov
        Ticks=1
    end sub
    

    and here for 877a:

    #chip 16F877a, 20
    #config Osc=HS, BODEN = off, WDT = off
    
    '**********LCD config********
    #define LCD_IO 4
    #define LCD_DB4 PORTD.4 'LCD pin 11, sematik pin 13, chip pin 27
    #define LCD_DB5 PORTD.5 'LCD pin 12, sematik pin 14, chip pin 28
    #define LCD_DB6 PORTD.6 'LCD pin 13, sematik pin 15, chip pin 29
    #define LCD_DB7 PORTD.7 'LCD pin 14, sematik pin 16, chip pin 30
    #define LCD_NO_RW
    #define LCD_Enable PORTD.2
    #define LCD_RS PORTD.3
    #define LCD_BL PORTD.1 'pin 20 LCDBacklight
    
    #define UART_BAUD_RATE 150
    
    Dim Hours as Byte
    Dim Mins as Byte
    Dim Secs as Byte
    
    'LCD test and startup
    cls
    set LCD_BL on
    print "Test"
    wait 1 s
    set LCD_BL off
    cls
    '*******************
    On Interrupt UsartRX1Ready call Getting
    
    'Main loop
    Do
      Locate 0,0
        Print Hours
      Locate 0, 2
        print ":"
      Locate 0,5
        print Mins
      Locate 0,6
        Print ":"
      Locate 0,7
        Print Secs
    wait 100 ms
    set LCD_BL off
    Loop
    'End Main
    
    Sub Getting
    
    cls
        set LCD_BL on
        HSerReceive (Hours)
        HSerReceive (Mins)
        HSerReceive (Secs)
    end sub
    

    i got this result on the LCD and it is not changing
    0: 0:4

    so, is it possible communication by using these speeds over hardware serial? or what can i use for sending and receiving minimum 3 bytes per second?

     
  • William Roth

    William Roth - 2017-03-16

    Hi,

    HerPrint sends a string of ASCII data , Example: < HserPrint 44 > will send 2 bytes, each with a value of 52 since 52 is the value for the character "4" .

    Try using "Hsersend" instead of HserPrint for sending byte data.

     
  • fisyon

    fisyon - 2017-03-17

    Thanks for the correction. still not working...
    i figured out i got this result from 877a without connecting the other.
    how can i test if it is senders fault or receivers fault?
    Edit:
    seems "on interrupt UsartRX1Ready call ..." is not triggered...

     

    Last edit: fisyon 2017-03-17
  • William Roth

    William Roth - 2017-03-17

    Seems you have misspelled "USART" With UART

    And you need to enable USART blocking. Should look like this:

    #define USART_BAUD_RATE 150
    #define USART_BLOCKING
    #define USART_TX_BLOCKING
    
     
  • viscomjim

    viscomjim - 2017-03-17

    I've been trying to figure this out too and for some reason I can wrap my head around the difference between hsersend and hserprint. From the manual...

    HSerPrint is used to send a value over the serial connection. user_value can be a string, integer, long, word or byte.

    HSerSend - This command will send a byte given by user_byte using the hardware RS232 module.

    Can someone with a better understanding spell out when to use one over the other? Maybe it's just me, but can't a byte be a string value, or integer too? Not getting it yet, sorry. Is HSerPrint better for certain things when trying serial communication? Again, sorry for not getting it...

    Thanks in advance!!!!

    I have to Edit this post real quick, I have to say that GCB is incredible. Even though I am still learning, I can't believe how much you can do using this awesome FREE piece of work. I am truly thankful to all of the contributors for this. It is hard to believe that so much effort is given away for free for others to accomplish things that would not be done if it were not for others selfless efforts. I am not a wordsmith, thats for sure... but you get the point.

     

    Last edit: viscomjim 2017-03-17
  • fisyon

    fisyon - 2017-03-17

    @William Roth
    it was not misspelling.
    i tried "USART" before but i got this error:

    Error: USART baud rate is too low

    edit: just tested for the minimum value: 1221...

     

    Last edit: fisyon 2017-03-17
  • fisyon

    fisyon - 2017-03-17

    yet, can't figure out how to send and receive 3 bytes over serial. i think i need to create a buffer or something like that which i don't know "how" either...

    so, i thought to send these three bytes by converting and joining into a string variable.
    then i tried to write something like this:
    ...
    dim mystring as string
    ...
    mystring = Str(Hours) + ":" + Str(mins) + ":"............

    SynWrite crashed before writing that line...
    i thought that is just a coincidence. but next time at this line SynWrite crashed again...
    please, can someone confirm this? (bug?)

    i think this is not a success even if i can send and receive this 3 bytes in a string form, because this will be unneccesary long way for a simple(!) task.

    ps: maximum baud rate setting without getting compiler error for 32768hz crystall is 2048.

     
  • William Roth

    William Roth - 2017-03-17

    You do NOT Need a buffer. You just need to get code set up properly and then do methodical testing/troubleshooting if things do not work as expected. Test one code section at a time instead of the entire program. When a section is working move to the next. When that is working add both together and retest. Then move to the next ... and so on.

    I think you have several issues. I can get it your code working here just fine at 150 Baud with a 32KHz Crystal, using a PIC16F886. The 886 has the same USART and oscillator block as your 16F628a. I DO NOT get "baud too low" messages when I change the PIC to 16F628a and compile.

    With my setup the external Oscillator works. The interrupt works. And the three data byte are sent correctly at the correct baud as confirmed with a logic analyzer. So why does yours not work ?

    First, confirm that the 628A is actually operating on the crystal and not falling back to the internal oscillator. If it falls back to the internal oscillator then nothing will work becasue all timing will be incorrect. Do this with a simple program that flashes the LED ON/OFF every second. Does it work as expected or does the LED come on and stay on? If not as expected then the crystal is not operating.

    Use this exact code. Do not change it in any way.

    #chip 16F628a, 0.032768
    #config OSC=LP, BOREN=off, WDT=off, FCMEN = OFF
    #define TestLed Portb.6
    DIR PORTB.6 OUT
    
    Do
     Set TestLED ON
     Wait 1 s
     Set TestLED OFF
     Wait 1 S
    Loop
    

    If this does not flash the LED on 1 sec, and off 1 sec then the external crystal is not working. did you use loading capacitors ? What values? .

    If this code works as expected then let me know and I will provide you more working code.

     

    Last edit: William Roth 2017-03-17
  • William Roth

    William Roth - 2017-03-17

    I do not get baud rate too low messages. So I need to see the exact code that produces this message and I need to know what version of the GCB compiler you are currently using.

    If you are not using the latest version of GCB .(97.01) then the first thing you need to do is update.
    .

     
  • fisyon

    fisyon - 2017-03-17

    hello William,
    it is a bit difficult to test step by step both circuits.
    however i am sure the external oscillator of 628a (32768hz) working as expected. if you look again at first post you can see my TestLed setup. it blinks...

    for the baud rate setup; i think i confused you:

    for 32khz (628a) i can not compile higher than 2048.
    here is the full message when i try to compile with 2049 baud:

    14:15:52 G+Stool-COMPILE/ASSEMBLE, processing E:\PIC\GCB@Syn\G+Stools\makeHEX.bat
    Source-File = E:\PIC\pic16f628aSerialOSCtest.gcb
    5.3 Sec. <<< WARNINGs / ERRORs while compiling!
    Doubleclick on errormessage below to go to sourcecode-line:
    usart.h (363): Error: Cannot store -1 in the byte variable SPBRG

    for 20mhz (877a) i can not compile lower than 1221.
    here is the full message when i try to compile with 1220 baud:
    14:13:46 G+Stool-COMPILE/ASSEMBLE, processing E:\PIC\GCB@Syn\G+Stools\makeHEX.bat
    Source-File = E:\PIC\pic16f877ALCDPortDSerialReceiver.gcb
    6.7 Sec. <<< WARNINGs / ERRORs while compiling!
    Doubleclick on errormessage below to go to sourcecode-line:
    Error: USART baud rate is too low

    so i decided to make it 2048 for both chips.
    it seems somewhat works. but i got some strange output like:
    5: 0 :6
    then a few seconds later:
    10 : 0 :11
    17: 0 :18
    22: 0 :23
    ...

    then a few minutes later it stays on this:
    00

    my gcbasic version is 0.97.1. it is the last version as far as i know.

    ok, let me add my latest codes for both chips:

    #chip 16F628a, 0.032768
    #config Osc=LP, BODEN=off, WDT=off
    #define USART_BAUD_RATE 2048
    #define TestLed Portb.6
    
    dim Ticks as bit
    dim Hours as byte
    dim Mins as Byte
    dim Secs as Byte
    
    InitTimer0 osc, PS0_32
    on interrupt timer0overflow call t0ov
    StartTimer 0
    
    'main
      do
        if ticks=1 then
          if Secs<59 Then
              Secs+=1
            Else
              Secs=0
              if Mins<59 Then
                Mins+=1
              Else
                Mins=0
                if Hours<23 Then
                  Hours+=1
                Else
                  Hours=0
                end if
              end if
            end if
    
          ticks=0
        set TestLed on
          wait 100 ms
        set TestLed off
          wait 100 ms
    
    
            HSerSend Hours
            HSerSend Mins
            HSerSend Secs
    
        end if
    
    
       loop
    
    sub t0ov
        Ticks=1
    end sub
    

    and for the "receiver" side:

    #chip 16F877a, 20
    #config Osc=HS, BODEN = off, WDT = off
    
    '**********LCD config********
    #define LCD_IO 4
    #define LCD_DB4 PORTD.4 'LCD pin 11, sematik pin 13, chip pin 27
    #define LCD_DB5 PORTD.5 'LCD pin 12, sematik pin 14, chip pin 28
    #define LCD_DB6 PORTD.6 'LCD pin 13, sematik pin 15, chip pin 29
    #define LCD_DB7 PORTD.7 'LCD pin 14, sematik pin 16, chip pin 30
    #define LCD_NO_RW
    #define LCD_Enable PORTD.2
    #define LCD_RS PORTD.3
    #define LCD_BL PORTD.1 'pin 20 LCDBacklight
    
    #define USART_BAUD_RATE 2048
    #define USART_BLOCKING
    #define USART_TX_BLOCKING
    
    Dim Hours as Byte
    Dim Mins as Byte
    Dim Secs as Byte
    
    'LCD test and startup
    cls
    set LCD_BL on
    print "USART saat okuma"
    wait 1 s
    set LCD_BL off
    cls
    '*******************
    On Interrupt UsartRX1Ready call Getting
    
    'Main loop
    Do
      Locate 0,0
        Print Hours
      Locate 0, 2
        print ":"
      Locate 0,5
        print Mins
      Locate 0,6
        Print ":"
      Locate 0,7
        Print Secs
    wait 100 ms
    set LCD_BL off
    Loop
    
    
    Sub Getting
    
        set LCD_BL on
        HSerReceive (Hours)
        HSerReceive (Mins)
        HSerReceive (Secs)
        cls
    end sub
    

    There is no compiler error for both at 2048 baud.
    the TestLED on 628a (portB.6) and backlight of 877a's LCD, both blinks (not synchronised)

     
  • mmotte

    mmotte - 2017-03-17

    Greetings fisyon,

    If you look on the PIC16F877a datasheet table 10-3 the lowest baud is 1200 but the SPBRG is at 255 which must be the limit. i can't get your code to compile at 1200 but it does at 2400.

    If I change the chip to PIC16F887 at 20mhz then you code compiles down to 300 baud. Must be some difference in the microcontroller. I'll llook further to see what the difference is.

    Your implementing a clock on the second chip '628a. Why don't you implement it on the '877a using timer 1 and a external 32728 crystal on RC0 and RC1? This would eliminate the comm problem and a chip.

    BR
    M

     
  • mmotte

    mmotte - 2017-03-17

    Greetings viscomjim,

    Serial communication is a byte at a time.
    HSerSend takes the byte that your are sending and sends it to the correct USART transmit register. HSerSend doesn't care if your byte is a number or an ascii character. On some PICs or AVRs there can be more than one USART.

    HSerPrint converts a byte, word, long or string to the ascii represenation and sends it using the HSerSend command. HSerPrint's ability to accept different varaible types is called "overloading" which is programming jargon.This conversion is a multistepped process.

    For numbers, the number is taken apart and converted to to the ascii characters.
    248 / 100 = 2 , 2+48 = 50 , 50 is sent using HserSend
    48/10 =4 , 4 +48 =52 , 52 is sent using HSerSend
    8 is left , 8 + 48 = 56 , 56 is sent

    For Strings, The chars are already assumed to be ascii.
    MyString(0) has the length of the string in.
    So a simple For loop is set up from 1 to the print length which is MyString(0) .

    MyString(1) is sent to HSerSend
    MyString(2) is sent to HSerSend
    ....
    until Print Length is achieved.

    BR
    M

     
  • fisyon

    fisyon - 2017-03-17

    @mmotte

    Why don't you implement it on the '877a using timer 1 and a external 32728 crystal on RC0 and RC1?

    my goals are:

    to build a modular design. (i can attach / detach both of them easily right now)
    low power, battery backed RTC.
    to learn serial communication.
    plus, i can use 877a for faster jobs (for example: driving six digits of 7 segment display)

    PS:

    so, i thought to send these three bytes by converting and joining into a string variable.
    then i tried to write something like this:
    ...
    dim mystring as string
    ...
    mystring = Str(Hours) + ":" + Str(mins) + ":"............
    SynWrite crashed before finishing this line...
    i thought that is just a coincidence. but next time at this line SynWrite crashed again...
    please, can someone confirm this? (bug?)

    i am using GCBasic 0.9.0.1 and SynWrite 6.22.2290 on windows 8.1.
    may you try to duplicate that crash?

     
  • William Roth

    William Roth - 2017-03-18

    This is not supported/allowed and will return a compiler error ..

     mystring = Str(Hours) + ":" + Str(mins) + ":"
    

    .
    .
    .
    This works Ok

      MyString = Str(hours)
      MyString = MyString + ":" + Str(mins)
    

    The IDE did not "crash" on the error with my systems (Win7/Win10) so I am guessing the crash is specific to Win8.1 or to your system.

    When you say Synwrite crashes, what specifically do you mean ? Does the entire IDE crash? Is there an error message? If so what does it say ? Can you provide a screenshot ?

     

    Last edit: William Roth 2017-03-18
  • fisyon

    fisyon - 2017-03-18

    The message is ~:
    SynWrite for Great Cow Basic has stopped working
    A problem caused the program to stop working bla bla...

    to click the button on the message box will close SynWrite.

    You can see my crasher line in the background.

    may you try to write this line without spaces? mystring = Str(Hours)+":"+Str(mins)+":"+Str(secs)+":"
    i know, this is not a good style even if compiled successfuly...

    btw: i have "windows8.1 single language" (turkish) on my laptop...

     
  • Anobium

    Anobium - 2017-03-18

    This is a Synwrite issue. Edit your source file in Notepad, remove any odd characters and save. I have seen this myself and I was unable to determine the root cause of the issue.

    So, open in Notepad, remove any odd characters, save, and reopen in IDE.

     

    Last edit: Anobium 2017-03-18
  • fisyon

    fisyon - 2017-03-19

    finally i have some progress:
    256 baud looks like working for sender (628a) side.
    i tested it by an arduino with a software serial example.

    now, i think i need a software serial for the receiver (877a) side because 20Mhz is too fast for 256 baud.

    is there a low baud rate limit for software serial?

    @Anobium, i know it is SynWrite's bug, not the GCBasic's.

     
  • fisyon

    fisyon - 2017-03-22

    my chips are communicating successfuly with each other, thank you all.

    however, when i am trying to display time on a 6x 7 segment CC display i can get and show the bytes but the code waits at the "Ser1Receive" line. the display goes off for ~half a second at that line.

    defining "SER1_RXNOWAIT off" reduces/eliminates that pause but it causes corrupted or no data.

    i know, my baud rate is too low and i can't increase because of low crystall speed.

    is there a trick or should i give up ?

     
  • William Roth

    William Roth - 2017-03-22

    Perhaps you should consder using a higher clock speed and higher baud rate on the 628a. There are other ways to get an accurate 1 sec time base than using a 32.768 KHz clock crystal.

    You could also implement a non blocking backround serial receive on the 877.

    Why does the 628a even need to calculate the time and send serial data? You could have the 628a simplysend a short pulse every1sec to the 877 and then let the 877 do the rest.

     

    Last edit: William Roth 2017-03-22
  • fisyon

    fisyon - 2017-03-22

    i want to build 628a as a RTC. i am planning to operate it by batteries. i thought that kind (low speed) of operation will consume less power. i also want to keep time against power loss. that is why i am stuck with this setup.
    anyway, i think i have to give up with the smooth display idea with this design.

     

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.