Trying to understand ISR timing
I've been reading some threads here, and trying to figure out using the ISR for serial communications. I think I have it figured out, but I wanted to run my numbers to make sure I'm on the right track, as I've never had to code anything based on cycles or critical timing before, so hopefully my examples make sense.
I'm using the external 4MHz resonator, as power consumption is a primary consideration. My understanding is that when sampling bits for serial communications an odd number should be used, though I've seen examples here using even that seem to work fine.
So, if I want 19200 baud with 5x oversampling, The calculation is:
5 * 19_200 = ISR Rate of 96_000 per second. To figure out the amount of time I divide 1 / 96_000 = .00001041667 seconds meaning the ISR runs every 10.417 uS, but the amount of time the ISR takes to execute is determined by the code IN the ISR, right?
Using a 4MHz clock, if the ISR executes 96_000 times per second this means that the total number of cycles that are available is 41.67 for code in the ISR plus any other code that needs to run outside the ISR, per ISR execution.
So, if my calculations are accurate, for solid serial communications at 19_200 I'm assuming that 5x is more than sufficient. Generally speaking as the baud rate decreases can the sampling rate stay the same? If I find that I need more cycles would reducing the baud to 9600 and setting the ISR rate to 38_400 be adequate?
Is there any recommend reading to help me get my head around this? I've been searching the forums and found some stuff, but I probably don't know what search terms to use.
Thanks
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
-Craig
I'm using the external 4MHz resonator, as power consumption is a primary consideration. My understanding is that when sampling bits for serial communications an odd number should be used, though I've seen examples here using even that seem to work fine.
So, if I want 19200 baud with 5x oversampling, The calculation is:
5 * 19_200 = ISR Rate of 96_000 per second. To figure out the amount of time I divide 1 / 96_000 = .00001041667 seconds meaning the ISR runs every 10.417 uS, but the amount of time the ISR takes to execute is determined by the code IN the ISR, right?
Using a 4MHz clock, if the ISR executes 96_000 times per second this means that the total number of cycles that are available is 41.67 for code in the ISR plus any other code that needs to run outside the ISR, per ISR execution.
So, if my calculations are accurate, for solid serial communications at 19_200 I'm assuming that 5x is more than sufficient. Generally speaking as the baud rate decreases can the sampling rate stay the same? If I find that I need more cycles would reducing the baud to 9600 and setting the ISR rate to 38_400 be adequate?
Is there any recommend reading to help me get my head around this? I've been searching the forums and found some stuff, but I probably don't know what search terms to use.
Thanks
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
-Craig
Comments
If you're going to use SX/B the attached program may give you a boost; you'll want to adjust the ISR rate and the baud constants, but that's pretty easy to do.
When you say this "(or higher lower baud rates when I want to choose)" did you mean "or higher _for_ lower baud rates..." ? I think I see why you'd want a higher sample rate for lower baud rates, bit is seems kind of counter intuitive...
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
-Craig
I'm sorry to disagree with you regarding odd vs even sampling intervals. Odd sampling can assure that you capture the middle part of a bit, whereas with even sampling that is not possible. In even sampling the best you can do is the sample intrerval just under or just over half way.
In your favourite 4x oversampling there is a 25% acceptance either side of dead center, depending on how your algoritm selects the following sample. This means there can be +25% to -75% or +75% to -25% jitter in the sampling clock to ensure data capture without error. The salient point being the 25% minimum, whether positive or negative.
In the case of 3X centered sampling, the sample at the center is permitted to jitter +33% or -33% before it falls out of tolerance. So in fact 3X is "better" because it is balanced, and hence more tolerant than 4X. But of course 5X is better than 3X. And 2X is absurd.
My personal choice usually is 3X, and if I have a lot of speed left over, sometimes I just choose to go 5X. I never choose even sampling, but of course, if other timing criteria dictate, even sampling at 4X or higher can work. But for basic minimal needs, 3X is best, and 5X is preferred.
Hope that helps shed some light on the issue.
Cheers,
Peter (pjv)
Thanks so much! I integrated your buffered routines into my code, set the rates appropriately, and it just worked. The first time. I'm sure I'll pay for that bit of good luck down the road
All in all it took me about an hour. I'm not good with assembly, and I've been looking up the commands to learn how it works. I did have one issue and that is that I'm using raw RS232 so my stuff is inverted. A look at the source code generated by SERIN got me going.
I'm far from an expert, in fact I'm a complete noob to this stuff, but mathematically (statistically?) Peters explanation makes sense to me, but unfortunately, simply changing the sampling rate to an odd number and calculating the new ISR rate did not work. I suspect it is because the constant Baud1x5 will create some sort of overflow type of error when you try to MOVe 4.5 (3 * 3 / 2) into rxDivide. I don't understand enough about this yet to know exactly what the issue is, but I do know that my program failed when I tried the odd route.
So, for now anyway, everything seems to be working just fine at 19200 with 4x sampling.
I've attached the excel spreadsheet I used to calculate the rates if anyone finds it useful.
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
-Craig