Forum - MCS Electronics

 

FAQFAQ SearchSearch RegisterRegister Log inLog in

BAUD RATE
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
njepsen

Bascom Member



Joined: 13 Aug 2007
Posts: 469

newzealand.gif
PostPosted: Wed Jun 08, 2022 3:58 am    Post subject: BAUD RATE Reply with quote

I have a serial device connected to a HW uart on the ATMEGA1284p. I routinely use 38400 baud, but when i buy the meters they are set to 115200, and sometimes ( v v rarely like x1 in 5yrs) a lightning storm or some-such can change the BR to another standard but unknown value. I want to try talking to the meter at all the standard baud rates and automatically set the rate to 38400. ( with the command BR2). The code below does that but I'm trying to get away from the clumsy case statement. Why can I not replace the whole case statement with
Code:
 baud = testbaudrate


The test code snippet below does achieve what I am trying to do.
Code:

$regfile = "m1284pdef.dat"
$crystal = 9830400
$framesize = 500
$swstack = 500
$PROG &HFF , &HC7 , &HD0 , &HFD



config watchdog = 8192
stop watchdog



                                                ' Pullup On

' '-------------------------------------------------------------------------------
'Open a software UART TRANSMIT channel for debug dB9
'-------------------------------------------------------------------------------
'Open a software UART TRANSMIT channel for debug dB9
Open "comc.3:38400,8,n,1" For Output As #1                   '
Open "comc.2:38400,8,n,1" For Input As #5
'---------------------------------------------------------
'Nor 140
'---------------------------------------------------------
' Open Hardware uart on pins 14 & 15 for NOR140

$baud = 38400                                       '
Open "com1:" For Binary As #3

Config Serialin = Buffered , Size = 200 , Cts = Pind.4 , Rts = Pind.7 , Threshold_full = 30 , Threshold_empty = 30

Config Serialout = Buffered , Size = 250

enable interrupts

Declare Function Getmeterresponse(byval metercommandstr As String*10) As String
declare sub change_meter_baudrate()
declare function confirm_meter_id() as byte

Dim Tempstr1 As String * 100
dim tempstr2 as string * 100
dim msg_id as byte
dim retries as byte
dim m as byte
dim testbaudrate as long
dim tempstr9 as string * 255
dim bArray(200) as byte at tempstr9 overlay
dim n As word
dim rxbyte as byte

  '*************
   'MAIN LOOP
  '*************

  do
   wait 1
   Do

      Print #1 , ">> send IT "           'IT to the instrument ellicits a response "Nor140"
      Tempstr1 = Getmeterresponse( "it;")
      wait 1
      If Instr(tempstr1 , "Nor140") <> 0  Then
         print #1,">. we got correct response "
      else
         print #1,">> we got incorrect or no  response"
         call change_meter_baudrate
      End If


   Loop Until Retries >= 200  or msg_id = 0


  loop


  '***********************
  'SUBROUTINES  START HERE
  '***********************
    function confirm_meter_id() as byte

       baud = 38400
       tempstr1 = getmeterresponse("it;")
       if instr(tempstr1,"Nor140")<>0 then
          msg_id = 0
        else
          msg_id = 99
       end if

       confirm_meter_id = msg_id

    end function

'*********************************************************************************
Sub Change_meter_baudrate()
  ' This sub checks the meter at all baud rate from 9600 to 115200 and exits when the correct response is seen

   n = 0
   do
       incr n
       for m = 0 to 4
         testbaudrate = lookup(m,BR_data)

        select case testbaudrate     'i want to replace this complete case statement with baud = testbaudrate
          case 9600
            baud = 9600
          case 19200
            baud = 19200
          case 38400
            baud = 38400
          case 57600
            baud = 57600
          case 115200
            baud = 115200
          case else
            print #1,">> rubbish"
        end select


        ' baud = testbaudrate

         'Now we try to set the meter baud rate to 38400 using the 'test' baudrate
         print #1,">> try "; str(testbaudrate)
         print #3,"BR2"    'command BR2 sets the meter baud rate to 38400
         waitms 1250
         msg_id = confirm_meter_id()
         if msg_id = 0 then exit sub:
       next m


   loop until n >= 25
   print #1,">> no success"
   wait 2
   exit sub
   BR_data:
   data 9600&,19200&,38400&,57600&,115200&


End Sub




 '*************************************************************************************
Function Getmeterresponse(byval metercommandstr As String*10) As String

'meter response looks like      E<space>57.9<cr><lf>

   Local Timedelay As Long
   local Index as byte
   local loopcount as byte
   Index = 1                                               'arrays are 1 based
   Clear Serialin                                           'clear ser buffer
   Print #3 , ""                                            'clear meter buffer
   Print #3 , metercommandstr                               'CRLF is added automatically
   rxbyte = 0                                                'essential
   tempstr9 = ""
   tempstr1 = ""
   Do

      incr loopcount
      While Ischarwaiting(#3) <> 0
         rxbyte = waitkey(#3)
        select case rxbyte
            case 10     'LF
                 exit while
            case 13     'CR
                  exit while
            case 32      'space do nothing
            case Else
              if index<250 then
                bArray(Index) = rxbyte      'overlay byte onto string
                incr index
              else
                exit while
              end if
         end select
      Wend
      waitms 1
   Loop Until  loopcount >= 100
      bArray(index) = &H0                   'string terminator

    print #1,">> meter said ";tempstr9
    loopcount = 0

   Getmeterresponse = tempstr9

End Function
 '*********************************************************************************
 


(BASCOM-AVR version : 2.0.8.5 )

_________________
Neil
Back to top
View user's profile
EDC

Bascom Expert



Joined: 26 Mar 2014
Posts: 971

poland.gif
PostPosted: Wed Jun 08, 2022 7:26 am    Post subject: Reply with quote

Baudrate is determined by UBRR register and U2X (double speed) bit.
Values for BAUD (UBRR) are precalculated by compiler but this is easy task to do it by micro.
You simply open the datasheet of your Mega1284 and find the formula...



So this is simple to write your own Sub or Function to do so but because of your weird crystal you should stick to U2X = 1 because of large error that should not exeed 2%.

Look how calculated UBRR and Error looks like for your clock :



So for calculating any BAUD you simply do math (9830400 / 8 / Desired BAUD) - 1 and thats it.

UBRR = ((9830400 / 8 / 9600) - 1) = 127 (compare it with calculator Very Happy )

Code:
Const U2X1 = _Xtal / 8

Function Calc_UBRR(byval NewBaud As Dword) As Word
 Local HelpD As Dword
 Helpd = U2X1 / NewBaud
 Calc_UBRR = HelpD - 1
End Function

HelpW = Calc_UBRR : UBRR = HelpW

 


I dont test if you can write to register directly from the function like : UBRR = Calc_UBRR(9600) You must try
If not then maybe better option is write a Sub "Set_UBRR(Byval NewBaud As Dword)" and set UBRR in it.

This is how it works for ANY baud but in your case you can precalculate those four values and simply insert it in DATA then UBRR = Lookup(IndexM , MyData)
Back to top
View user's profile Visit poster's website
njepsen

Bascom Member



Joined: 13 Aug 2007
Posts: 469

newzealand.gif
PostPosted: Wed Jun 08, 2022 8:03 am    Post subject: Reply with quote

Nice EDC. Elegant.
I chose the "weird" xtal freq 10 yrs ago because it gave me 0% at 38400, which is what I use, and they were ex stock at my supplier.
The issue I had was baud = var according to the help. A long is a var so why won't Baud = var (from the lookup) compile. Anyway - i will try your soln tomorrow. Thanks for taking the time to reply.

_________________
Neil
Back to top
View user's profile
MWS

Bascom Member



Joined: 22 Aug 2009
Posts: 2262

blank.gif
PostPosted: Wed Jun 08, 2022 8:06 am    Post subject: Re: BAUD RATE Reply with quote

njepsen wrote:
Why can I not replace the whole case statement with
Code:
 baud = testbaudrate

Did you try
Code:
baud #3, testbaudrate
?

Edit:
Compiled and disassembled, while the compiler throws no error, it completely ignores the command, no opcodes are generated:
Code:
baud #3, testbaudrate

I'd expect an error and not an ignore.

The answer why baud = baudratevar does not work, is stated in the help, while it is contradictory in this case:

Quote:
BAUD = var
BAUD1 = var
BAUD2 = var
BAUD3 = var

Syntax Xmega

BAUD = var
BAUD1 = var
BAUD2 = var
BAUD3 = var

This suggests that variable arguments work for default (Mega) and XMega.

But also from the help:
Quote:
mega
...
You need to use a constant for the baud rate. Variables are not supported.

contradicts the first.
The same is given for XMegas.

Using constants is not required technically, as the baud rate registers can be rewritten anytime.


Last edited by MWS on Wed Jun 08, 2022 8:58 am; edited 1 time in total
Back to top
View user's profile
albertsm

Administrator



Joined: 09 Apr 2004
Posts: 5921
Location: Holland

blank.gif
PostPosted: Wed Jun 08, 2022 8:19 am    Post subject: Reply with quote

using BAUD= indeed only works with a constant. The reason is simple.
When using $baud the compiler calculates using the oscillator speed. It checks all possible values and checks what results in the lowest error. It also checks the double rate flag. So for some values it will be set, for others it wont
When a variable must be supported it will take more code. Something not needed IMO.

The software uart does allow to be changed with a variable but that is because it already has calculation routines since serin/serout can work dynamic with variables.

I just looked in the help and it seems to be very wrong (reversed). will change that.

using baud #3, someval will not work.

never got many q's about using a variable to change the baud but that is probably since it is relatively simple to change it. do take care however that there are various procedures, depending on the processor. some times a baud register is shared. so always check the datasheet.

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

Bascom Member



Joined: 13 Aug 2007
Posts: 469

newzealand.gif
PostPosted: Wed Jun 08, 2022 8:25 am    Post subject: Reply with quote

Hi MWS,
Yes I did and I tried it again just now. it compiles, but doesnt give me a correct solution. At least it compiles - I have had time to figure out why it doesnt give me a solution.

The next print statement
Code:

 print #1,">> try "; str(testbaudrate)

does give me the correct answers each iteration of the for/next loop so the lookup is working.

_________________
Neil
Back to top
View user's profile
albertsm

Administrator



Joined: 09 Apr 2004
Posts: 5921
Location: Holland

blank.gif
PostPosted: Wed Jun 08, 2022 8:27 am    Post subject: Reply with quote

Quote:
The software uart does allow to be changed with a variable but that is because it already has calculation routines since serin/serout can work dynamic with variables.


that is not correct. it allows a constant only. only serin/serout use dynamic baud.

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

Bascom Member



Joined: 22 Aug 2009
Posts: 2262

blank.gif
PostPosted: Wed Jun 08, 2022 9:06 am    Post subject: Reply with quote

albertsm wrote:
that is not correct. it allows a constant only. only serin/serout use dynamic baud.

As I've edited above and you did notice yourself, the help section in question is contradictory.


Last edited by MWS on Wed Jun 08, 2022 9:10 am; edited 1 time in total
Back to top
View user's profile
MWS

Bascom Member



Joined: 22 Aug 2009
Posts: 2262

blank.gif
PostPosted: Wed Jun 08, 2022 9:09 am    Post subject: Reply with quote

njepsen wrote:
but doesnt give me a correct solution. At least it compiles - I have had time to figure out why it doesnt give me a solution.

I had the time, see my edit.
Back to top
View user's profile
albertsm

Administrator



Joined: 09 Apr 2004
Posts: 5921
Location: Holland

blank.gif
PostPosted: Wed Jun 08, 2022 12:06 pm    Post subject: Reply with quote

both the baud and the help for it had some errors. will fix it
_________________
Mark
Back to top
View user's profile Visit poster's website
njepsen

Bascom Member



Joined: 13 Aug 2007
Posts: 469

newzealand.gif
PostPosted: Thu Jun 09, 2022 3:55 am    Post subject: Reply with quote

Thanks guys for the comments. I found that U2X needed to be set because of the high err at 115200 and my Xtal freq. I decided to run thru the loop again so that we ended up with U2X=0 for the higher USART sample rate. Not sure if this has any advantage but it seems like a good idea.
Code:

Sub Change_meter_baudrate()
  ' This sub checks the meter at all baud rate from 9600 to 115200 and exits when the correct response is seen
  'Becuase of high err rate at 115200, U2X = 1 is needed which has lower err rate


       n = 0
   do
       incr n
       'Single speed
       for m = 0 to 4
         my_UBRR = lookup(m,BR_data)
         print #1,">. test number=";my_UBRR
         UBRR = my_UBRR
         UCSR0A.U2X=0


         'Now we try to set the meter baud rate to 38400 using the 'test' baudrate
         print #1,">> try "; UBRR
         print #3,"BR2"    'command BR2 sets the meter baud rate to 38400
         waitms 1000       'only 100 needed
         msg_id = confirm_meter_id()
         if msg_id = 0 then
           print #1,">> Success.Single speed Both meter & USART are now at 38400"
           exit sub
         end if
       next m

       'try double speed because single speed didnt work
         for m = 5 to 9
              my_UBRR = lookup(m,BR_data)
              print #1,">. test number=";my_UBRR
              UBRR = my_UBRR
              UCSR0A.U2X=1


              'Now we try to set the meter baud rate to 38400 using the 'test' baudrate
              print #1,">> try "; UBRR
              print #3,"BR2"    'command BR2 sets the meter baud rate to 38400
              waitms 1000       'only 100 needed
              msg_id = confirm_meter_id()
              if msg_id = 0 then exit for  'Both meter and UART now at 38400 but U2x=1, so go back to single speed & try again

         next m


   loop until   n >= 100   'for test purposes
   print #1,">> no success"
   wait 2
   exit sub
   BR_data:

   data 63,31,15,10,4,127,63,31,20,10
End Sub

 

_________________
Neil
Back to top
View user's profile
MWS

Bascom Member



Joined: 22 Aug 2009
Posts: 2262

blank.gif
PostPosted: Thu Jun 09, 2022 12:15 pm    Post subject: Reply with quote

njepsen wrote:
I found that U2X needed to be set because of the high err at 115200 and my Xtal freq.

As general rule U2X = 1 gives the same or better error, compare to the baud rate example tables from the data sheet, USART section.
By comparing U2X = 0 vs. U2X = 1 over the shown clock frequencies you'll notice that if an error of 0% appears at U2X = 0, there is always 0% at U2X = 1.
Where the error is > 0% at U2X = 0, then the U2X = 1 error is always same or better.
This is simply explained by 'finer' sample steps.

Keeping U2X always on seems to be a sound idea.
The limit is not the higher baud rates, in contrary, only with U2X = 1 the highest baud rates can be achieved.

The limits are super slow baud rates at high clock frequencies, because of the 12bit-wide UBRR.
At 20 MHz clock, U2X = 1 and UBRR = 4095 the baud rate calculates to 610 baud, the half at U2X = 0.

Quote:
I decided to run thru the loop again so that we ended up with U2X=0 for the higher USART sample rate.
Not sure if this has any advantage but it seems like a good idea.
It is senseless, as you have the same error of 0% at the lower baud rates, regardless of U2X = 0/1, while the error at the two higher baud rates is much more acceptable with U2X = 1 (1.6/-3,0%), than double as high error with U2X = 0.

The only reason running tests with off-center baud rate is in case the connected hardware is off-center too.
Back to top
View user's profile
njepsen

Bascom Member



Joined: 13 Aug 2007
Posts: 469

newzealand.gif
PostPosted: Sat Jun 11, 2022 1:28 am    Post subject: Reply with quote

That all makes sense, and the error at my chosen 38400 baud rate is the same for both cases. I was thinking more of receiver performance & the lower sampling rate with U2X =1, where the sampling rate is 8x instead of 16x. Because the receiver decision ss to whether a bit is an 0 or a 1 is based on a majority decision of the samples - its seems logical that 16 samples should give a better result ?
_________________
Neil
Back to top
View user's profile
njepsen

Bascom Member



Joined: 13 Aug 2007
Posts: 469

newzealand.gif
PostPosted: Sat Jun 11, 2022 2:07 am    Post subject: Reply with quote

I am also getting some confusing results from setting UBRR and its siblings.
Code:
  UBRR0 = const
will compile and all 16 bits can be manipulated, but
Code:
 UBRR1 = const
is not accepted by the compiler. I note that there is no entry in the m1284p.def for UBRR1.
Also -
Code:
UBRR0L = 257
for example is accepted, but only the LS byte is loaded it seems, so if i run this in the 1284p, and then read UBRR0 and UBRR0L the result is consistent and only the LSB is set which I would expect. I cant check this with UBRR1 because it won't compile.

I can also write to and read UBRR
Code:

       UBRR = 257

       print #1,UBRR0
       print #1,bin(UBRR0)     ' -> 0000000000000001
       print #1,bin(UBRR)       ' -> 0000000000000001
       print #1, bin(UBRR0L)  ' -> 00000001
       stop
and the result is the same as writing to UBRR0
Code:
 
       UBRR0 = 257

       print #1,UBRR0
       print #1,bin(UBRR0)     ' -> 0000000000000001
       print #1,bin(UBRR)       ' -> 0000000000000001
       print #1, bin(UBRR0L)  ' -> 00000001


confusing

_________________
Neil
Back to top
View user's profile
MWS

Bascom Member



Joined: 22 Aug 2009
Posts: 2262

blank.gif
PostPosted: Sat Jun 11, 2022 10:07 am    Post subject: Reply with quote

njepsen wrote:
I was thinking more of receiver performance & the lower sampling rate with U2X =1
You misunderstand. Read U2X as U(art) 2(double) X(speed), from the data sheet "Double Speed Operation (U2Xn)", if set to 1 the option is on, otherwise off.

Quote:
where the sampling rate is 8x instead of 16x.
Definitely not, the prescaler for the sampling rate is 8 instead of 16, which means the sample rate is higher.
Easy to see from the data sheet's baud rate equations, at U2X = 1 one divisor becomes 8, if the dividend (fOsc) stays the same, then the quotient (baud) gets higher.

Quote:
its seems logical that 16 samples should give a better result ?
As written, you confuse sample rate with sample rate prescaler.
Back to top
View user's profile
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