Difference between revisions of "Read before write"
(New page: ==== Read before Write ==== The issue with 'read before write' is that the PIC16 does not store the state of it's output pins anywhere. The classic issue occurs when individual port bits...) |
(another discussion of this problem.) |
||
Line 36: | Line 36: | ||
port=sport[&porta-PORTA]; | port=sport[&porta-PORTA]; | ||
</pre> | </pre> | ||
+ | |||
+ | == Further reading == | ||
+ | |||
+ | * [http://massmind.org/techref/readmodwrite.htm The Read-Modify-Write problem] |
Revision as of 21:35, 21 April 2009
Read before Write
The issue with 'read before write' is that the PIC16 does not store the state of it's output pins anywhere.
The classic issue occurs when individual port bits are set, or toggled, causing outputs on the pins to behave unexpectedly.
This happens because the PIC16 reads the state of the port pins to calculate the value to write to the port. When the PIC16 writes to the port, it writes the value for all the pins at the same time.
For example with trisb set to zero, if you set portb.1=1, then later set portb.2=1. If portb.1 is excessively loaded, the PIC16 will read portb.1 as a zero and write 4 (0b100) to portb, instead of the expected 6 (0b110) to portb.
There are two solutions to the above issue:
The first, and by far the best is to ensure the output pins are not excessively loaded.
This is the best solution, as code not necessarily under your control, such as UART and I2C code will not affect the remainder of your application.
The second solution is to use some kid of 'shadow' register, in which the individual bits can be manipulated, then the resulting CHAR values can then be written to the port.
The various _port macros below, if called in place of the _bit macros, should do the job:
unsigned char sport[2]; // amend to # PIC ports #define set_port(port, no)\ set_bit(sport[&porta-PORTA], no);\ port=sport[&porta-PORTA]; #define clear_port(port, no)\ clear_bit(sport[&porta-PORTA], no);\ port=sport[&porta-PORTA]; #define test_port(port, no)\ test_bit(sport[&porta-PORTA], no) #define toggle_port(port, no)\ toggle_bit(sport[&porta-PORTA], no);\ port=sport[&porta-PORTA];