Forum - MCS Electronics

 

FAQFAQ SearchSearch RegisterRegister Log inLog in

Baudrate 9600 problem
Goto page 1, 2  Next
 
Post new topic   Reply to topic    www.mcselec.com Forum Index -> BASCOM-AVR
View previous topic :: View next topic  
Author Message
atmega64

Bascom Member



Joined: 23 Feb 2005
Posts: 298
Location: ITALY

italy.gif
PostPosted: Tue Oct 22, 2019 3:10 pm    Post subject: Baudrate 9600 problem Reply with quote

Hi,
I use an atmega1284 with a 16Mhz oscillator ..
if I use a baud rate of 9600, I have problems receiving the first character sent ... why?

Code:
$regfile = "m1284def.dat"
$crystal = 16000000
$baud = 9600

'**************
Config Lcdpin = Pin , Db4 = Porta.3 , Db5 = Porta.2 , Db6 = Porta.1 , Db7 = Porta.0 , E = Portc.5 , Rs = Portc.6
Config Lcd = 16 * 2
'**************

Config Com1 = Dummy , Synchrone = 0 , Parity = None , Stopbits = 1 , Databits = 8 , Clockpol = 0

Config Serialin = Buffered , Size = 254

Config Portd.6 = Output                                     'BUZZER
Buzzer Alias Portd.6

Declare Sub Bip

Dim Rx_cmd , Ric As Byte
Dim Command As String * 254

Enable Interrupts

Waitms 30

Initlcd
Cls
locate 1,1
lcd "HELLO"

bip

Command = ""
Ric = 0
Rx_cmd = 0

do
   Rx_cmd = Ischarwaiting()                                 'CONTROLLA SE E' STATO RICEVUTO UN CARATTERE

   If Rx_cmd = 1 Then
      Rx_cmd = Waitkey()                                    'RITORNA IL VALORE DECIMALE RICEVUTO
      Ric = 1
      Command = Command + Chr(rx_cmd)                       'INSERISCE I CARATTERI IN UNA STRINGA FINO A QUANDO LA TRASMISSIONE NON TERMINA
      Waitms 1
   Else
      If Ric = 1 Then
         Bip
         Ric = 0
         Cls
         Locate 2 , 1
         Lcd Command
         Command = ""
      End If
   End If
loop

Sub Bip
   Buzzer = 0
   Waitms 20
   Buzzer = 1
End Sub

end


(BASCOM-AVR version : 2.0.8.1 , Latest : 2.0.8.2 )
Back to top
View user's profile Visit poster's website
AdrianJ

Bascom Expert



Joined: 16 Jan 2006
Posts: 2483
Location: Queensland

australia.gif
PostPosted: Tue Oct 22, 2019 11:21 pm    Post subject: Reply with quote

I would suspect that using ischarwaiting together with waitkey is the problem, at the least, one of them is redundant.

You do bufferend input, so IsCharWaiting tells you at least one character is in the buffer. Then just read it with inkey, you dont need to use waitkey, you already know there is a character there.

Depending on what you want to do, I find its usually better to put ischarwaiting in a loop, so it keeps adding characters to your output string untill the buffer is empty. At some point you get an end of line character, or carriage return, use that to determine when to output the completed string to the display.

Code:

do
   while Ischarwaiting()  > 0                               'CONTROLLA SE E' STATO RICEVUTO UN CARATTERE

 
      Rx_cmd = inkey()                                    'RITORNA IL VALORE DECIMALE RICEVUTO
      Ric = 1
      if Rx_cmd = 13 ' pick whatever end of line character your string has
'a Select...Case statment works better here to pick out various characters
          Bip
     
         Cls
         Locate 2 , 1
         Lcd Command
         Command = ""
      else
Command = Command + Chr(rx_cmd)                       'INSERISCE I CARATTERI IN UNA STRINGA FINO A QUANDO LA TRASMISSIONE NON TERMINA
      Waitms 1 'you dont need this - just wastes valuable processor cycles
   end if
     
   wend
loop
 

_________________
Adrian Jansen
Computer language is a framework for creativity
Back to top
View user's profile Visit poster's website
atmega64

Bascom Member



Joined: 23 Feb 2005
Posts: 298
Location: ITALY

italy.gif
PostPosted: Wed Oct 23, 2019 2:00 pm    Post subject: Reply with quote

ok thanks…

but With "waitms 2" it works

Code:
Command = Command + Chr (rx_cmd)
       Waitms 2
Back to top
View user's profile Visit poster's website
albertsm

Administrator



Joined: 09 Apr 2004
Posts: 5921
Location: Holland

blank.gif
PostPosted: Wed Oct 23, 2019 2:36 pm    Post subject: Reply with quote

both inkey and waitkey can be used in combination with ischarwaiting.
The waitms is indeed not needed.

The provided info given is not complete : we have no idea when the data is sent. Is the code running before the data is sent? And exactly what data is sent? En how much, etc.

_________________
Mark
Back to top
View user's profile Visit poster's website
AdrianJ

Bascom Expert



Joined: 16 Jan 2006
Posts: 2483
Location: Queensland

australia.gif
PostPosted: Wed Oct 23, 2019 11:03 pm    Post subject: Reply with quote

Thanks for the clarification Mark. I thought that waitkey might be waiting for the next character, after the one which set the ischarwaiting flag. In which case that one would be missed.
_________________
Adrian Jansen
Computer language is a framework for creativity
Back to top
View user's profile Visit poster's website
atmega64

Bascom Member



Joined: 23 Feb 2005
Posts: 298
Location: ITALY

italy.gif
PostPosted: Thu Oct 24, 2019 7:22 am    Post subject: Reply with quote

albertsm wrote:
both inkey and waitkey can be used in combination with ischarwaiting.
The waitms is indeed not needed.

The provided info given is not complete : we have no idea when the data is sent. Is the code running before the data is sent? And exactly what data is sent? En how much, etc.


Hi Mark,

- The code is running before the data is transmitted ...

- The transmitted data are strings of few characters, for example "HELLO" ...

putting waitms 2, it works ... what do you think?

this is the code: (can it be optimized?)

Code:

$regfile = "m1284def.dat"
$crystal = 16000000
$baud = 9600

'**************
Config Lcdpin = Pin , Db4 = Porta.3 , Db5 = Porta.2 , Db6 = Porta.1 , Db7 = Porta.0 , E = Portc.5 , Rs = Portc.6
Config Lcd = 16 * 2
'**************

Config Com1 = Dummy , Synchrone = 0 , Parity = None , Stopbits = 1 , Databits = 8 , Clockpol = 0

Config Serialin = Buffered , Size = 254

Config Portd.6 = Output                                     'BUZZER
Buzzer Alias Portd.6

Declare Sub Bip

Dim Rx_cmd , Ric As Byte
Dim Command As String * 254

Enable Interrupts

Waitms 30

Initlcd
Cls
locate 1,1
lcd "HELLO"

bip

Command = ""
Ric = 0
Rx_cmd = 0

do
   Rx_cmd = Ischarwaiting()                                 'CONTROLLA SE E' STATO RICEVUTO UN CARATTERE

   If Rx_cmd = 1 Then
      Rx_cmd = Waitkey()                                    'RITORNA IL VALORE DECIMALE RICEVUTO
      Ric = 1
      Command = Command + Chr(rx_cmd)                       'INSERISCE I CARATTERI IN UNA STRINGA FINO A QUANDO LA TRASMISSIONE NON TERMINA
      Waitms 2 '<<<<<<<<<<<<<<<<<<<
   Else
      If Ric = 1 Then
         Bip
         Ric = 0
         Cls
         Locate 2 , 1
         Lcd Command
         Command = ""
      End If
   End If
loop

Sub Bip
   Buzzer = 0
   Waitms 20
   Buzzer = 1
End Sub

end
Back to top
View user's profile Visit poster's website
albertsm

Administrator



Joined: 09 Apr 2004
Posts: 5921
Location: Holland

blank.gif
PostPosted: Thu Oct 24, 2019 8:58 am    Post subject: Reply with quote

I do not know what the goal of the code is?
It looks odd. There is no trailing character to check? Like a CR or LF ?
Usually you signal the end of a data stream with a trailing character like CR + LF or one of them.

your code seems to grab some data and when no data is available it resets.

so this is how it usually works :

Code:

do
   Rx_cmd = Ischarwaiting()                                 'CONTROLLA SE E' STATO RICEVUTO UN CARATTERE
   If Rx_cmd = 1 Then
      Rx_cmd = Waitkey()                                    'RITORNA IL VALORE DECIMALE RICEVUTO
      if rx_cmd=13 then
         Cls: Locate 2 , 1 :
         Lcd Command        'show
         Command = "" 'clear
      else
        Command = Command + Chr(rx_cmd)                       'INSERISCE I CARATTERI IN UNA STRINGA FINO A QUANDO LA TRASMISSIONE NON TERMINA
      end if
   End If
loop
 


what you do is adding data, then set a flag. and once there is no data in the buffer, you show the data.
with waitms gives the sender more time to send data.
make 100% sure the code is running before you send data.
you can also simulate it and it will show that all data is captured.
it is also not clear if you mean from the first time you send data, or for each time you send data.

i would perform a simple test :
Code:

Config Com1 = Dummy , Synchrone = 0 , Parity = None , Stopbits = 1 , Databits = 8 , Clockpol = 0
Config Serialin = Buffered , Size = 254
Config Portd.6 = Output                                     'BUZZER
Buzzer Alias Portd.6
Declare Sub Bip
Dim Rx_cmd , Ric As Byte
Dim Command As String * 254
Enable Interrupts


do
     Rx_cmd = Waitkey()                                    'RITORNA IL VALORE DECIMALE RICEVUTO
     print rx_cmd  ' print ASCII value
loop


that way you can see which data you receive.

and also important : do not forget to include $hwstack setting.the interrupt requires stack space.

_________________
Mark
Back to top
View user's profile Visit poster's website
MWS

Bascom Member



Joined: 22 Aug 2009
Posts: 2262

blank.gif
PostPosted: Fri Oct 25, 2019 8:11 am    Post subject: Reply with quote

atmega64 wrote:
this is the code: (can it be optimized?)

Yes, by much, simply put your code in the trash bin, aka copy file to NUL.
Quote:
putting waitms 2, it works

For this botchery you kept two forums busy.
Back to top
View user's profile
atmega64

Bascom Member



Joined: 23 Feb 2005
Posts: 298
Location: ITALY

italy.gif
PostPosted: Fri Oct 25, 2019 2:48 pm    Post subject: Reply with quote

albertsm wrote:
I do not know what the goal of the code is?
It looks odd. There is no trailing character to check? Like a CR or LF ?
Usually you signal the end of a data stream with a trailing character like CR + LF or one of them.


Thanks Mark, I have been following this forum for years, and your advice has always been very valuable for me ... (the forum was born for this to give and receive help not for anything else … Very Happy )

I explain it better:

I'm realizing a CCTALK communication between a micro and CCTALK devices (when I'm done I'll post the project on the forum … Wink )

I already have a project I made on VB.net, which works fine, now I'm converting it to bascom.

The CCTALK protocol does not include the end of a data stream with a trailing character like CR + LF or one of them, but only the cheksum.

I managed to convert the VB.net code to transmit data, in bascom code, now I have to convert the code to receive the data.

The code for receiving data in VB.net is this:

Code:

Do
   If SerialPort1.BytesToRead > 0 Then      'there are bytes to read
         
              'I read one byte at a time

              LenRx += 1

              ReDim Preserve RxByte(LenRx)

              RxByte(LenRx) = SerialPort1.ReadByte

              RxHex = HexConv(RxByte(LenRx), 2)
             
              Buffer += RxHex       'the buffer contains transformed data in 2-digit hex
             
              If LenRx = (MyCommand.Length / 2 + 1) Then     'the value of this byte identifies how many characters I will have in reception
                 
                  AttLenRx = RxByte(LenRx) + 4 + LenCommand     'in this variable I insert the number of the data that I must receive in the serial port.
                 
                  ReDim RxData(RxByte(LenRx - 1) - 1)      'in this matrix of bytes I insert only the data answered, as long as there is' -1 because it has a zero base.

              End If

              If AttLenRx > 0 Then

                  If LenRx >= AttLenRx Then 'IF ALL DATA HAVE BEEN RECEIVED, GET OUT OF THE RECEIVE CONTROL LOOP

                      Exit Do

                  End If
              End If              
      End If
Loop
 


Any suggestions on what code I can use in BASCOM for:

If SerialPort1.BytesToRead > 0 Then
...
RxByte(LenRx) = SerialPort1.ReadByte
...

thank you all for your patience ... Laughing
Back to top
View user's profile Visit poster's website
EDC

Bascom Expert



Joined: 26 Mar 2014
Posts: 971

poland.gif
PostPosted: Fri Oct 25, 2019 4:55 pm    Post subject: Reply with quote

I never saw CCTALK protocol so I read Wikipedia https://en.wikipedia.org/wiki/CcTalk

I make quick test on the simulator

Code:
$regfile = "m1284def.dat"
$crystal = 16000000
$baud = 9600
$hwstack = 64
$swstack = 16
$framesize = 256
$sim

'CCTALK RECEIVER SIMULATION in BASCOM for checksum and overlay test

'TX data = 2 0 1 245 8

'    2 = destination address
'    0 = zero data bytes
'    1 = source address
'    245 = command header ‘Request equipment category id’
'    8 = checksum ( 2 + 0 + 1 + 245 + 8 = 256 = 0 mod 256 )

'This is a message from address 1 ( the host ) to peripheral address 2 to find out what it is.

'RX data = 1 13 2 0 67 111 105 110 32 65 99 99 101 112 116 111 114 22

'    1 = destination address
'    13 = 13 data bytes
'    2 = source address
'    0 = reply header
'    67…114 = ASCII for ‘Coin Acceptor’
'    22 = checksum ( sum of all packet bytes is zero )

'The Reply From Address 2 Back To Address 1 Identifies It As A Coin Acceptor.

Dim Rxbyte(255) As Byte
Dim Rxstring As String * 200 At Rxbyte(5) Overlay

'RX data = 1 13 2 0 67 111 105 110 32 65 99 99 101 112 116 111 114 22
Rxbyte(1) = 1
Rxbyte(2) = 13
Rxbyte(3) = 2
Rxbyte(4) = 0
Rxbyte(5) = 67
Rxbyte(6) = 111
Rxbyte(7) = 105
Rxbyte(8) = 110
Rxbyte(9) = 32
Rxbyte(10) = 65
Rxbyte(11) = 99
Rxbyte(12) = 99
Rxbyte(13) = 101
Rxbyte(14) = 112
Rxbyte(15) = 116
Rxbyte(16) = 111
Rxbyte(17) = 114
Rxbyte(18) = 22

Dim Helpb As Byte , N As Byte

For N = 1 To 18
 Helpb = Helpb + Rxbyte(n)
Next

 If Helpb = 0 Then
  Rxbyte(18) = 0                                            'string terminator
  Print Rxstring
 End If

End

Result was promissing Wink


So I end up with this not tested code but you can try it Wink
Probably it needs some tweaks because i work on both only half hour.

Code:
$regfile = "m1284def.dat"
$crystal = 16000000
$hwstack = 64
$swstack = 16
$framesize = 256
$baud = 9600

'CCTALK RECEIVER PART by EDC Smile

Config Serialin = Buffered , Size = 100                     'dont forget to enable interrupts!

Const Max_buff_len = 201
Const Max_cmd_len = Max_buff_len - 1

Dim Rxbyte(max_buff_len) As Byte
Dim Rxstring As String * Max_cmd_len At Rxbyte(5) Overlay
Dim Mycrc As Byte , N As Byte
Dim Lenrx As Byte , Rxend As Byte

Enable Interrupts

Do

 If 0 < Ischarwaiting() Then
  Lenrx = 0 : Mycrc = 0                                     'we starting

  Do
   If 0 < Ischarwaiting() Then
    Incr Lenrx
    If Lenrx > Max_cmd_len Then                             'buffor cant acomodate more data, error
     Lenrx = 0 : Exit Do
    End If

    Rxbyte(lenrx) = Waitkey()

    If Lenrx = 2 Then Rxend = Rxbyte(lenrx) + 5             'in second byte we get payload len
                                                             'but we must add 4B header and last byte for CRC

    If Lenrx = Rxend Then                                   'ALL DATA WAS RECEIVED
     For N = 1 To Rxend
      Mycrc = Mycrc + Rxbyte(n)
     Next

     If Mycrc = 0 Then
      Rxbyte(rxend) = 0                                     'string terminator
      Print Rxstring                                        'you can show this on LCD
     Else
      Print "CRC dont match"
     End If

     Exit Do                                                'exit because we dont aspect another byte
    End If

    'end Ischarwaiting
   End If
  Loop

 End If

Loop
End


Good luck Wink
Back to top
View user's profile Visit poster's website
atmega64

Bascom Member



Joined: 23 Feb 2005
Posts: 298
Location: ITALY

italy.gif
PostPosted: Fri Oct 25, 2019 5:16 pm    Post subject: Reply with quote

thanks! of people like you need this forum ...

I will make tests and update you.
Back to top
View user's profile Visit poster's website
albertsm

Administrator



Joined: 09 Apr 2004
Posts: 5921
Location: Holland

blank.gif
PostPosted: Fri Oct 25, 2019 6:50 pm    Post subject: Reply with quote

Well done EDC. It is a good starting point.

I have done some commercial CCTALK apps. It is used in vending machines used on events.

One thing i like to warn for in general when i see serial reception code.
Thus not about your code but what i see in support : code that assumes that there will come data.
It is best never to assume that further data will arrive. There are different ways to deal with that.

first you can first count how much data is received. that way you know if you can read/process all data.
Another way is to use a simple state machine where you advance through states .
first you wait for data, when you have data you go to a next state. it is also important to consider timing. if for some time no data arrives you can reset your state.
because when you activate your code, you need to know what the data is. that what you think is the first byte is actually the first byte and not some data in the middle. of course you can check this with crc.
And you can use a WD timeout which is a rather cruel way.

_________________
Mark
Back to top
View user's profile Visit poster's website
EDC

Bascom Expert



Joined: 26 Mar 2014
Posts: 971

poland.gif
PostPosted: Fri Oct 25, 2019 7:19 pm    Post subject: Reply with quote

In my aplications I set Timeout if I receive first byte, then renev it every next one.
If message is complite I set Timeout = 0 and parse but if message is for example without end mark for too long then I clear state machine, reset index or force to parse. It depend of application.

Yeah. This is important notice. I was affected by that VB.Net code above Very Happy

[EDIT] Should be better Wink
Code:
$regfile = "m1284def.dat"
$crystal = 16000000
$hwstack = 64
$swstack = 16
$framesize = 256
$baud = 9600

Config Serialin = Buffered , Size = 100                     'dont forget to enable interrupts!

Const Max_buff_len = 201
Const Max_cmd_len = Max_buff_len - 1

Dim Rxbyte(max_buff_len) As Byte
Dim Rxstring As String * Max_cmd_len At Rxbyte(5) Overlay
Dim Mycrc As Byte , N As Byte
Dim Lenrx As Byte , Rxend As Byte , Timeout As Byte

Config Timer2 = Timer , Prescale = 1024 , Clear_timer = 1
Compare2a = 155                                             '10ms @16MHz/1024

Enable Interrupts

Do

 If Tifr2.ocf2a = 1 Then                                    '10ms
  If Timeout > 0 Then
   Decr Timeout
   If Timeout = 0 Then Lenrx = 0
  End If

 End If

 If 0 < Ischarwaiting() Then

   Timeout = 50
    Incr Lenrx : If Lenrx > Max_cmd_len Then Lenrx = 1      'buffer protection

    Rxbyte(lenrx) = Waitkey()
                                                            'in second byte we get payload len
    If Lenrx = 2 Then Rxend = Rxbyte(lenrx) + 5             'but we must add 4B header and last byte for CRC

    If Lenrx = Rxend Then                                   'ALL DATA WAS RECEIVED
     For N = 1 To Rxend
      Mycrc = Mycrc + Rxbyte(n)
     Next

     If Mycrc = 0 Then
      Rxbyte(rxend) = 0                                     'string terminator
      Print Rxstring                                        'you can show this on LCD
     Else
      Print "CRC dont match"
     End If

     Lenrx = 0                                              'for next msg
     Timeout = 0                                            'disable Timeout
    End If

 'end Ischarwaiting
 End If

Loop
End
Back to top
View user's profile Visit poster's website
atmega64

Bascom Member



Joined: 23 Feb 2005
Posts: 298
Location: ITALY

italy.gif
PostPosted: Tue Oct 29, 2019 8:40 pm    Post subject: Reply with quote

I obtained the BASCOM code from the VB.net code, which I had written ... and it works (obviously the timeout has to be managed etc ..)

a question ... there is a way in BASCOM to convert these commands to arrays ?

ReDim Preserve RxData (LenRx)
ReDim RxData (0)

CCTALK protocol reception code:

Code:
   
Do
    If Ischarwaiting(#2) = 1 Then                            'If Serialport1.bytestoread > 0 Then 'ci sono byte da leggere
         Ric = 1

           'leggo un byte alla volta
           Incr Lenrx

           Rxbyte(lenrx) = Waitkey(#2)

           Rxhex = Hexconv(rxbyte(lenrx) , 2)

           Buffer = Buffer + Rxhex                          'il buffer contiene dei dati trasformati in hex a 2 cifre

           Mylen = Len(mycommand)

           Xlen = Mylen / 2

           Incr Xlen

           If Lenrx = Xlen Then                             'il valore di questo byte identifica quanti caratteri avrò in ricezione

               Attlenrx = Rxbyte(lenrx) + 4

               Attlenrx = Attlenrx + Lencommand             'in questa variabile inserisco il nuumero dei dati che devo ricevere nella porta seriale.

           End If

           Waitms 2

   Else
      If Ric = 1 Then                                       'Or Attlenrx > 0 And Lenrx >= Attlenrx Then

         Ric = 0

         Exit Do

      End If

   End If

  Loop

  Locate 2 , 1
  Lcd Buffer

' Estrairisposta

  Lenrx = 0

  Rispostaascii = ""

  For A = Lencommand + 4 To Attlenrx - 1

        Rxdata(lenrx) = Rxbyte(a)

        Incr Lenrx

        If Rxbyte(a) = 0 Then

            Rispostaascii = Rispostaascii + Chr(1)          ' sostituisco il carattere zero perchè è un terminatore di stringa

        Else

            Rispostaascii = Rispostaascii + Chr(rxbyte(a))

        End If
  Next A

  Locate 1 , 1
  Lcd Rispostaascii
[/code]
Back to top
View user's profile Visit poster's website
EDC

Bascom Expert



Joined: 26 Mar 2014
Posts: 971

poland.gif
PostPosted: Tue Oct 29, 2019 9:04 pm    Post subject: Reply with quote

I think that VB.Net code was not yours if you dont understand how ReDim works Very Happy
Read this for a moment https://www.dotnetperls.com/redim-vbnet

..then read this short explanation what Preserve means LINK

Above means that simple ReDim will resize Array but also zeroes it (fill it with zeros) while ReDim Preserve will leave original content and resize array (in your case create another next memory cell).

So in PC that Array can grow dinamically. In uC like AVR you must declare/guarantee array with some reasonably length, then operate on the index.

So code should look like this, I think:
Code:
Dim RxData(255) As Byte , LenRx As Byte

'if new byte arrive
  Incr LenRx
'ReDim Preserve RxData (LenRx)
  RxData(LenRx) = Waitkey()         'simply take next cell in the prepared/declared array

'when VB.Net code is  ReDim RxData (0)
 LenRx = 0 'so in first Incr LenRx ->LenRx will be 1 for first cell of our array
 
Back to top
View user's profile Visit poster's website
Display posts from previous:   
Post new topic   Reply to topic    www.mcselec.com Forum Index -> BASCOM-AVR All times are GMT + 1 Hour
Goto page 1, 2  Next
Page 1 of 2

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum
You cannot attach files in this forum
You cannot download files in this forum