View previous topic :: View next topic |
Author |
Message |
Pret
Joined: 18 Jul 2006 Posts: 92 Location: Iasi, Romania
|
Reading 16bit registers on 8bit mcu |
Posted: Thu Mar 14, 2013 5:15 pm |
|
|
I was curious on how can you read an 16bit timer (while it runs), store it in a 16bit variable and having consistent high and low byte. As I read into a random datasheet (say 18F26k22), I've seen that they made a trick with a hidden buffer on the high byte of the 16bit timer register. That's neat and it works fine.
But what if I'm using CCP on capture mode, being set on falling edge, without any interrupts. Just want to know how much time occurred since last falling edge. But reading the CCP register (say CCP_2) and store it in a local var, exposes the same issue.
For instance: Code: | int16 capt = CCP_2; |
Now, how can I know for sure if high and low byte of the capt are consistent? What if a new capture occurred just between reading the low and reading the high?
A solution that I'm thinking is: Code: | int16 capt = CCP_2;
while(CCP_2 != capt) capt = CCP_2; |
... meaning that I'm reading it in loop as long the values are not equal.
Is there any "right" way to do this? |
|
|
asmboy
Joined: 20 Nov 2007 Posts: 2128 Location: albany ny
|
|
Posted: Thu Mar 14, 2013 6:21 pm |
|
|
you just did it the right way as far as i'm concerned
with or without INTS on - this will never fail
IMHO the optimum solution as you never have to kill global or an individual INTs
i regard killing global ints as a serious crime ,
when more than one actual, individual int is enabled.
|
|
|
Mike Walne
Joined: 19 Feb 2004 Posts: 1785 Location: Boston Spa UK
|
|
Posted: Thu Mar 14, 2013 6:49 pm |
|
|
Could you consider this?
When a capture occurs, an int flag is set.
Clear the int flag before reading the timer.
If the int flag is set after reading the timer, another capture has occured.
You don't have to be actually using the int routines to use of the flags.
Mike |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19537
|
|
Posted: Fri Mar 15, 2013 2:15 am |
|
|
Killing GLOBAL INTs, is perfectly acceptable, for reading a 16bit value updated in an interrupt. Remember it is only for a couple of instructions.
Microchip in their own examples and application notes use both methods for accessing values updated inside interrupts.
However it is not the way to handle this, since in this case it a hardware value, which will still update when interrupts are disabled. The read and test, _is_ the only way to go. Depending on the circumstances, you might want to do the update the other way round, so:
Code: |
unsigned int16 capt;
do
capt = CCP_2;
while (capt!=CCP_2);
|
Both will give exactly the same results. The most efficient of all, will actually be:
Code: |
int16 capt;
while(CCP_2 != capt)
capt = CCP_2;
|
There is no 'point' in reading the value again, if it does already match...
Best Wishes |
|
|
Pret
Joined: 18 Jul 2006 Posts: 92 Location: Iasi, Romania
|
|
Posted: Fri Mar 15, 2013 4:32 am |
|
|
Yes, in this case it has nothing to do with interrupts.
Ttelmah, in your last example, it will definitely will create heart attacks on Lint or a second viewer for that uninitiated value, even it makes sense not to initialize it.
Though, I think your last example is not fully proof. You have to read it twice. For instance, if your random value for capt matches with a single read of a faulty (inconsistent) read of CCP_2? It's possible, right? Basically you might simply guess the wrong value of CCP_2. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19537
|
|
Posted: Fri Mar 15, 2013 4:38 am |
|
|
That's why I slightly prefer the first way.
It does depend on circumstances. In a loop that reads the value, the second is the more efficient, and since the value then should never be uninitialised, it avoids the extra read if it hasn't changed.
Best Wishes |
|
|
Pret
Joined: 18 Jul 2006 Posts: 92 Location: Iasi, Romania
|
|
Posted: Fri Mar 15, 2013 4:48 am |
|
|
Yes, but I still believe your very last version is not fully proof. Because with your uninitialized value you can simply guess a faulty read of CCP_2, and it moves on as the right value... |
|
|
Mike Walne
Joined: 19 Feb 2004 Posts: 1785 Location: Boston Spa UK
|
|
Posted: Fri Mar 15, 2013 5:09 am |
|
|
Pret wrote: | Yes, but I still believe your very last version is not fully proof. Because with your uninitialized value you can simply guess a faulty read of CCP_2, and it moves on as the right value... |
Am I missing something?
As I see it the first falling edge, initialises the system.
Any read of the CCP_x before the first falling edge has to be meaningless.
The coding must take this into account.
Mike
EDIT Have you considered using the CCP_x interrupt flag, or is it a non-starter? |
|
|
Pret
Joined: 18 Jul 2006 Posts: 92 Location: Iasi, Romania
|
|
Posted: Fri Mar 15, 2013 5:52 am |
|
|
We are not worrying about the meaning of CCP_x in application, we are worrying about the read of the 16bit register in a consistent manner, regarding its low and high byte. Using the interrupt flag seems to be a solution as well, but I find reading the register twice a more elegant manner. |
|
|
|