it must have been covered in the past, but i did not found anything about it.
is there a “hack” or a simple way, using c, to have few digital outputs without using a “dout module” (74HC595), in the same way we can use analog inputs (J5) as digital ones with pull up resitors.
( i now talking about J14, because i’m looking for more than one output )
I want to find the cheapest way to build sync24 outputs (we need 2 lines : clock and start)
can send a byte to PORTB and “read” it thanks to RB0 to RB7 ?
You can use PortB as input when the appr. TRISB flags are set (Tristate driver - means: pin is not driving)
However, the best choice for output pins which are not used by any other resources are RC0, RC1 and RC3.
The best choice for an input pin which is not used by any other resource is RC2 (it already has an pull-up, which is perfect to prevent random values if the pin is open)
By using these pins, you don’t need to modify the TRISx configuration, just use (for example)
PORTCbits.RC0 = 1;
to set the pin to 5V, and
PORTCbits.RC0 = 0;
to set the pin to 0V
Same for RC1:
PORTCbits.RC1 = 1; // 5V
PORTCbits.RC1 = 0; // 0V
And don’t touch anything related to the LCD Port B
Hope that this answers your question?
Or do you need even more input/output pins? There are special solutions for J5 and LCD port, but they require additional configuration… and you need to warn the end-users to disconnect the LCD, or disconnect pots (of J5 used as output) to prevent short-circuits.
I think this is well and truly under control now but… http://www.midibox.org/dokuwiki/mios_pin_list will show you a list of pins and their usage so you can tell if you can use a pin depending on your hardware…
which is the most efficient C code I found by looking to the generated asm…
There are two issues, and two improvements to make it a bit faster (in C, the assembly variant beats it anyhow ;))
a) it isn’t guaranteed, that reading PORTA returns the same values which have been written into PORTA, because the “read view” of this register returns the current values of the input stage, while writing into PORTA is directed to the output stage.
Simple example: you are using RA4 as open drain pin, and you are setting it 1 to deactivate the output driver. But you could read 0, e.g. if an external device drives the dominant (=0) value.
Accordingly, with PORTA = (PORTA & 0xf0) … you would accidently activate the output driver of RA4 in such a scenario!
Thats the reason, why the LATx registers have been introduced in the PIC18F family - it gives you direct read and write access to the output register. And thats also the reason, why I prefer to access LATx registers in my code
(btw.: there is also a pipeline issue with PORTx registers, e.g. sequential read-modify-write operations (bsf/bcf/btg) can fail if they are done without at least one instruction between the accesses, because the second RMW access would read the previous value of the *input* register - which wasn’t already updated by the new output value at this time)
b) wrong mask is applied on PORTE (0x1f instead of 0xf8)
c) “(oct & 0xe0) >> 5)” - the AND mask is probably redundant, if C clears the carry flag before doing the shift operation, and masks the value after the swap operation (I would expect this)
d) you could also write: “LATA = (LATA & 0xd0) | (oct & 0x0F) | ((oct & 0x10) ? 0x20 : 0x00);”
There are two issues, and two improvements to make it a bit faster (in C, the assembly variant beats it anyhow ;))
a) it isn’t guaranteed, that reading PORTA returns the same values which have been written into PORTA, because the “read view” of this register returns the current values of the input stage, while writing into PORTA is directed to the output stage.
Simple example: you are using RA4 as open drain pin, and you are setting it 1 to deactivate the output driver. But you could read 0, e.g. if an external device drives the dominant (=0) value.
Accordingly, with PORTA = (PORTA & 0xf0) … you would accidently activate the output driver of RA4 in such a scenario!
Thats the reason, why the LATx registers have been introduced in the PIC18F family - it gives you direct read and write access to the output register. And thats also the reason, why I prefer to access LATx registers in my code
I read that in the I/O pin section of the datasheet but not understood it at first. I’m not so used to read the simplified diagrams. That’s ok now I think.
(btw.: there is also a pipeline issue with PORTx registers, e.g. sequential read-modify-write operations (bsf/bcf/btg) can fail if they are done without at least one instruction between the accesses, because the second RMW access would read the previous value of the *input* register - which wasn’t already updated by the new output value at this time)
Did not know the PIC had a pipelined architecture ! I hope sdcc takes care of this when he optimizes code…
b) wrong mask is applied on PORTE (0x1f instead of 0xf8)
Oups!
c) “(oct & 0xe0) >> 5)” - the AND mask is probably redundant, if C clears the carry flag before doing the shift operation, and masks the value after the swap operation (I would expect this)
Yeah! I did not even think of it
d) you could also write: “LATA = (LATA & 0xd0) | (oct & 0x0F) | ((oct & 0x10) ? 0x20 : 0x00);”
Well. I looked at the generated code for ternary (? and it used intermediate viariables and the generated code is not optimized then simple if then set else set…