I am working on a project which uses a PIC24FJ64GA002 mcu. I am working on a bit-banged serial communication function that will use one wire to send data and then switch to receive mode to receive data on the same pin. A separate pin will be used for clocking which will always be controlled by a different board (always an input). I am wondering is there a way to configure the pin for open-collector operation that that it can be used as an input and and output or do I have to change the pin configuration every time i go from reading to writing?
-
1\$\begingroup\$ It sounds like you want your PIC to act as a slave I2C device. Perhaps the tips on the Massmind on that subject might be useful. techref.massmind.org/techref/microchip/i2c.htm \$\endgroup\$– davidcaryCommented Feb 11, 2011 at 20:33
2 Answers
Change the pin configuration every time. It's the TRIS register that controls if it's an input (1) or output (0). And, when you change direction, you have to wait a moment (check the datasheet) like a cycle or two before you use that pin. a couple Nop(); will do fine.
And, make sure you write to the LAT register, and read from the R register.
e.g. for port D, pin 0.
//output
_TRISD0 = 0;
Nop();
Nop();
_LATD0 = 1;
_LATD0 = 0;
//input
_TRISD0 = 1;
Nop();
Nop();
int i = _RD0;
If you want to simulate an open collector write a zero to the latch register. Then you do the rest with the TRIS register. When a zero goes to the TRIS bit this will turn the bit to an output and the line will be driven low. Then if you write a one to the TRIS bit the line will become an input and the pull up will cause the line to go high unless an external device is driving it low. The line will also be in an input state at that time. You can read the port at any time and it will show the proper bus state because when TRIS bit is 0 the bus will be low and that is what will be read and if TRIS bit is high it will be an input and then what ever is on the bus will be read as well.
Some pins also have the ability to enable a weak pullup on them and you can also enable the pin change interrupt on some of the pins.
//init
_LATA0 = 0;
//drive low
_TRISA0 = 0;
// let pull up bring pin high.
_TRISA0 = 1;
// read bit
in = _RA0;