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?
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;