Home
JAQForum Ver 20.06
Log In or Join  
Active Topics
Local Time 01:32 03 May 2024 Privacy Policy
Jump to

Notice. New forum software under development. It's going to miss a few functions and look a bit ugly for a while, but I'm working on it full time now as the old forum was too unstable. Couple days, all good. If you notice any issues, please contact me.

Forum Index : Microcontroller and PC projects : Some Serial Timing Thoughts

Author Message
panky

Guru

Joined: 02/10/2012
Location: Australia
Posts: 1094
Posted: 08:08pm 20 Dec 2016
Copy link to clipboard 
Print this post

There has been quite a lot of correspondance recently related to serial comms so I thought I might throw in a few timing numbers to put things in context.

At 9600 baud a single character takes approximately 1mSec to be sent/received. That is, if you loop back COM1 Tx to Rx and send 1 character out the Tx port, it will not be fully received at the Rx port for 1 mSec.

In this time, depending on clock speed and breed of 'mite, the 'mites will execute from 30 up to 100 MMBasic instructions.

On the Tx side, MMBasic dumps the characters to be sent out into the output buffer at full MMBasic speed so 10 characters transmitted will take just somewhere from 10 to 30uSec but the last character will not fully arrive at the destination receiver until roughly 10mSec later!

This timing is particularly important when you want to receive a string of characters. If a 10 character string is to be received, it will take at least 10mSec from start until last character is in the Rx buffer. In that time, MMBasic could have executed 300 to 1000 instructions.

Also, as you will realise, if you sit in a loop waiting for characters to arrive, you will be sitting there for some considerable time just twiddling your thumbs.

For that reason, the interrupt service routine method of handling serial input is by far and away the best method of doing so, particularly if the character string to be received is of any significant length.

I hope this makes sense for any newbies not familiar with serial comms.

Regards,
Doug.

... almost all of the Maximites, the MicromMites, the MM Extremes, the ArmMites, the PicoMite and loving it!
 
WhiteWizzard
Guru

Joined: 05/04/2013
Location: United Kingdom
Posts: 2794
Posted: 09:53pm 20 Dec 2016
Copy link to clipboard 
Print this post

Doug,

Probably worth including in this thread some very simple example code! Will make it easy to find in future (and not just for newbies!)
For everything Micromite visit micromite.org

Direct Email: whitewizzard@micromite.o
 
panky

Guru

Joined: 02/10/2012
Location: Australia
Posts: 1094
Posted: 02:26pm 21 Dec 2016
Copy link to clipboard 
Print this post

I make no claim to being a good programmer whatsoever but have put a well commented example below. It was run on a micromite 470 (Peter M's great backpack board) under MMBasic 5.2 by Geoff Graham. Please feel free to comment in any way

If you copy the code and plug it into Jim's MMEdit, the colour coding will help you navigate through the code better.

' Sample COM port Interrupt Service Routine
' using MMBasic v5.2 by Geoff Graham
' Doug Pankhurst 2016
' The example below is designed to be an interrupt driven routine
' to handle a serial stream received by the Micromite of fixed length
' at regular or semi regular intervals. In this case, 14 characters every 2 secs.
' As we know "14 characters every 2 sec", when a receive interrupt is triggered,
' we need to ensure that all 14 characters have been received before reading
' the Rx buffer, so we trigger the interrupt after 14 characters received
' For the purposes of the test, put a jumper between COM1 Tx and Rx to
' loop the characters sent back into the receive input.

' If you don't know how many characters and/or how often, it is more complex
' and I will do some code for that later.

' Lets setup and define variables
option explicit
dim Tx_test$ = "Hello World." ' test string to transmit
dim Rx_test$ ' string to hold received data
dim Rx_Flag = 0 ' 1 means data received by Rx interrupt service routine,
' 0 means nother received yet
dim Rx_data_good_Flag = 0 ' Rx data length flag - if 1, Rx data error



' Now we need to set up some code to send a serial stream out the COM1 Tx port
' at 9600 baud every two seconds to test the Rx interrupt code.
settick 2000,Tx_Int ' every seconds, generate an interrupt that will send
' the characters Hello World. out the COM1 port

open "COM1:9600, 30, Rx_Int, 14" as #1 ' set up COM1 as our serial I/O
' Note we are specifying 9600 baud with a 30 character buffer (the default
' is 256), the name of the Rx interrupt service routine and importantly,
' the number of characters in the Rx buffer before the interrupt will be triggered.

' ******
' This will be our main program loop - it can be anything you want but in this
' case it just checks a flag that is set by the receive interrupt service routine
' to see whether any characters have been received
Main: ' just a label
print "Program to demonstrate COM1 receive interrupt service"
do
' anything you like in here - this is where all your actual data processing and
' display output goes
' in here somewhere, you would check the Rx_Flag to check if receive data
' is available to use
' eg.
If Rx_Flag = 1 then
print time$," Data Received: ",Rx_test$
Rx_Flag = 0 ' clear ready for next test
if Rx_data_good_Flag = 0 then
print "Rx data good."
else
print "Receive data error"
' if needed, handle the data error here
endif
endif
' other code as desired
loop

' ***** main program code end

'***** Subroutines *******
'*** the all important Rx interrupt service routine
sub Rx_Int ' the receive interrupt has occured
' at this point we know two things; we have received data and there are 14 characters
' waiting in the Rx buffer, so set the Rx data flag and read the data.
' That is all we need to do in here - get in, set the flag, get the data, get out!
Rx_Flag = 1
Rx_test$ = input$(30,#1) 'we will try to read 30 characters just to ensure
' the buffer is empty. If there are only 14 characters
' then that is how many will be read
' Note that the input buffer is now empty - the data is
' in Rx_test$
Rx_data_good_Flag = 0 ' clear flag ready for test
If len(Rx_test$) <> 14 then
Rx_data_good_Flag = 1 ' check how many characters actually read - if more than 14
' then there is a receive data problem
' - if you wanted, you could include a checksum in the Tx
' data sent and test it here
endif
' the sub routine will return with data in Rx_test$, Rx_Flag set and
' Rx_data_good_Flag clear if data length correct ( a very simple error check)
end sub

'


' Set Tick timer interrupt service routine, called every second
sub Tx_Int
Rx_Flag = 0 ' clear the Rx flag ready for the Rx interrupt to set it later
print #1,Tx_test$ ' just send the test string with CR LF at the end
' - 14 characters in all. Note that these
' characters will go out at MMBasic instruction speed
' to the Tx buffer - about 20uSec at which time the subroutine
' will return but actual transmit
' speed out the COM port will be 14mSec
end sub



PS. You should also have a look at Rob's GPS Serial with Circular Line Buffer post recently.

Doug.Edited by panky 2016-12-23
... almost all of the Maximites, the MicromMites, the MM Extremes, the ArmMites, the PicoMite and loving it!
 
lew247

Guru

Joined: 23/12/2015
Location: United Kingdom
Posts: 1676
Posted: 11:12pm 22 Dec 2016
Copy link to clipboard 
Print this post

I love this code
However I found one flaw with using interupts using for example this code

[code]open "COM1:9600, 30, Rx_Int, 14" as #1 ' set up COM1 as our serial I/O
' Note we are specifying 9600 baud with a 30 character buffer (the default
' is 256), the name of the Rx interrupt service routine and importantly,
' the number of characters in the Rx buffer before the interrupt will be triggered
.
[/code]

What if your receiving more than one set of serial data and each set has a different number of characters?

or
what if you don't know exactly how many will be received?
 
Grogster

Admin Group

Joined: 31/12/2012
Location: New Zealand
Posts: 9066
Posted: 11:43am 23 Dec 2016
Copy link to clipboard 
Print this post

  lew247 said  What if your receiving more than one set of serial data and each set has a different number of characters?

or
what if you don't know exactly how many will be received?


More then one message can be dealt with internally by the serial port buffer itself, and you just read the messages out of the buffer one byte at a time in a loop, adding them to a string as you go, till you reach an end-of-message marker byte.

That will cope with messages of ANY length, just so long as they all use the same end-of-message byte that the loop can detect, and then it knows that is the end of that message.

Code jumps out of the loop then, does what has to be done, then checks the buffer again.

If there is still data there, it does it again.

And again, and again, and again.........till the buffer is empty. In this way, the serial port buffer actually acts as your message queue for you, and you don't then need to worry about queuing messages in your code per-se'.
Smoke makes things work. When the smoke gets out, it stops!
 
Print this page


To reply to this topic, you need to log in.

© JAQ Software 2024