bill Posted January 18, 2008 Report Share Posted January 18, 2008 Hello,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)-> http://www.midibox.org/dokuwiki/mb_sync24Thanks !!! =) Quote Link to comment Share on other sites More sharing options...
bill Posted January 20, 2008 Author Report Share Posted January 20, 2008 Am i unclear, or is this "impossible" ??? Quote Link to comment Share on other sites More sharing options...
TK. Posted January 20, 2008 Report Share Posted January 20, 2008 Do you mean something like demonstrated in this example: http://www.ucapps.de/mios_c_pic_pin.htmlBest Regards, Thorsten. Quote Link to comment Share on other sites More sharing options...
bill Posted January 20, 2008 Author Report Share Posted January 20, 2008 Well, yes, probably :pi dont understand the example very well yet, but i guess that's what i'm looking for.So, Port B is the LCD data bus right ?I can send a byte to PORTB and "read" it thanks to RB0 to RB7 ? ::)thank you ! Quote Link to comment Share on other sites More sharing options...
TK. Posted January 21, 2008 Report Share Posted January 21, 2008 So, Port B is the LCD data bus right ? 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 0VSame for RC1: PORTCbits.RC1 = 1; // 5V PORTCbits.RC1 = 0; // 0VAnd don't touch anything related to the LCD Port BHope 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.Best Regards, Thorsten. Quote Link to comment Share on other sites More sharing options...
bill Posted January 23, 2008 Author Report Share Posted January 23, 2008 Thank you Thorsten, yes, it helps a lot, but i would like to get... 8 outputs :pso i guess the only solution is j5 or lcd portB ! (i prefer j5)please can you tell me where to get some informations about those special solutions ?thanks =)edit :ok, i should use my brain more often... here it is http://ucapps.de/mios/j5_dout_v1_3c.zipunfortunately, this is ASM, and i did not find any conversion to C(i have zero ASM knowledge) :-[Can someone help me to turn this code into plain C ? Quote Link to comment Share on other sites More sharing options...
TK. Posted January 27, 2008 Report Share Posted January 27, 2008 Once the SVN server is up&running, a modular structure will be available where code modules can be easily shared between projects.So - once it is available, I will program a relocatable j5_dout module for you, that should be easily integratable.Best Regards, Thorsten. Quote Link to comment Share on other sites More sharing options...
TK. Posted January 27, 2008 Report Share Posted January 27, 2008 P.S.: so long the module is not available, you can control J5 outputs the following way from C:Add ADCON1 = 0x07; TRISA &= 0xd0; TRISE &= 0xf8;to the Init() hookNow you can toggle the pins withPORTAbits.RA0 = ...PORTAbits.RA1 = ...PORTAbits.RA2 = ...PORTAbits.RA3 = ...PORTAbits.RA5 = ... // no typo! RA4 is allocated by IICPORTEbits.RE0 = ...PORTEbits.RE1 = ...PORTEbits.RE2 = ...Please let me know if it works (it's untested)Best Regards, Thorsten. Quote Link to comment Share on other sites More sharing options...
bill Posted January 28, 2008 Author Report Share Posted January 28, 2008 a modular structure will be available where code modules can be easily shared between projects.So - once it is available, I will program a relocatable j5_dout module for you, that should be easily integratable. :oWooow !!! I love you Thorsten ;DThanks sooooo much, i test this this evening and revert as soon as it's done. Quote Link to comment Share on other sites More sharing options...
stryd_one Posted January 28, 2008 Report Share Posted January 28, 2008 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... Quote Link to comment Share on other sites More sharing options...
bill Posted January 28, 2008 Author Report Share Posted January 28, 2008 Please let me know if it works (it's untested)It works ! Quote Link to comment Share on other sites More sharing options...
bill Posted February 18, 2008 Author Report Share Posted February 18, 2008 Here is what i did : void J5_DOUT_Set(unsigned char oct){ char b0 = oct; char b1 = oct >> 1; char b2 = oct >> 2; char b3 = oct >> 3; char b4 = oct >> 4; char b5 = oct >> 5; char b6 = oct >> 6; char b7 = oct >> 7; PORTAbits.RA0 = b0 & 0x01; PORTAbits.RA1 = b1 & 0x01; PORTAbits.RA2 = b2 & 0x01; PORTAbits.RA3 = b3 & 0x01; PORTAbits.RA5 = b4 & 0x01; PORTEbits.RE0 = b5 & 0x01; PORTEbits.RE1 = b6 & 0x01; PORTEbits.RE2 = b7 & 0x01; } it works, but please tell me what you think of the code !(i guess it can be done in a better way) Quote Link to comment Share on other sites More sharing options...
nILS Posted February 18, 2008 Report Share Posted February 18, 2008 No major changes just a little shorter:void J5_DOUT_Set(unsigned char oct){ PORTAbits.RA0 = oct & 0x01; PORTAbits.RA1 = (oct >> 1) & 0x01; PORTAbits.RA2 = (oct >> 2) & 0x01; PORTAbits.RA3 = (oct >> 3) & 0x01; PORTAbits.RA5 = (oct >> 4) & 0x01; PORTEbits.RE0 = (oct >> 5) & 0x01; PORTEbits.RE1 = (oct >> 6) & 0x01; PORTEbits.RE2 = (oct >> 7) & 0x01;}[/code] Quote Link to comment Share on other sites More sharing options...
bugfight Posted February 18, 2008 Report Share Posted February 18, 2008 try this (off the top of my head): void J5_DOUT_Set(unsigned char oct) { PORTAbits.RA0 = (oct & 0x01) && 1; PORTAbits.RA1 = (oct & 0x02) && 1; PORTAbits.RA2 = (oct & 0x04) && 1; PORTAbits.RA3 = (oct & 0x08) && 1; PORTAbits.RA5 = (oct & 0x10) && 1; PORTEbits.RE0 = (oct & 0x20) && 1; PORTEbits.RE1 = (oct & 0x40) && 1; PORTEbits.RE2 = (oct & 0x80) && 1; } != 0 might be better than && 1, have to look at asm output...(maybe could even do without the && 1 at all) Quote Link to comment Share on other sites More sharing options...
bill Posted February 19, 2008 Author Report Share Posted February 19, 2008 Thank you guys !I knew there was an elegant way to do that :) Quote Link to comment Share on other sites More sharing options...
nILS Posted February 19, 2008 Report Share Posted February 19, 2008 Semi-untested and possibly controversial:__asm MOVF _PORTA, _WREG IORLW 0x1F MOVF _WREG, _PORTA MOVF _oct, _WREG IORLW 0xE0 ANDWF _PORTA, 1 MOVF _PORTE, _WREG IORLW 0x07 MOVF _WREG, _PORTE MOVF _oct, _WREG RRNCF _WREG, 5 IORLW 0xF8 ANDWF _PORTE, 1__endasm;[/code] Or sth. pretty close to what ptitjes suggested in the chat: [code] PORTA = (oct & 0x1F) | (PORTA & 0xE0); PORTE = ((oct >> 5) & 0x07) | (PORTE & 0xF8); Quote Link to comment Share on other sites More sharing options...
TK. Posted February 19, 2008 Report Share Posted February 19, 2008 See also: http://svnmios.midibox.org/trunk/apps/sequencers/midibox_seq_v3/src/j5_dout.inc(which can be optimized, yes... it's quite old. And it's better to use PROD[LH] as temporary registers than MIOS_PARAMETER[12])The official j5_dout module will get a C wrapper, similar to this module: http://svnmios.midibox.org/trunk/modules/iic_midiSo that it can be used by asm and C programs....Best Regards, Thorsten. Quote Link to comment Share on other sites More sharing options...
ptitjes Posted February 19, 2008 Report Share Posted February 19, 2008 Or sth. pretty close to what ptitjes suggested in the chat:In fact this was : PORTA = (PORTA & 0xF0) | (oct & 0x0F); if (oct & 0x10) { PORTAbits.RA5 = 1; } else { PORTAbits.RA5 = 0; } PORTE = (PORTE & 0x1F) | ((oct & 0xE0) >> 5); which is the most efficient C code I found by looking to the generated asm... Quote Link to comment Share on other sites More sharing options...
TK. Posted February 19, 2008 Report Share Posted February 19, 2008 In fact this was :PORTA = (PORTA & 0xF0) | (oct & 0x0F);if (oct & 0x10) { PORTAbits.RA5 = 1; } else { PORTAbits.RA5 = 0; }PORTE = (PORTE & 0x1F) | ((oct & 0xE0) >> 5);[/code]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);"Best Regards, Thorsten. Quote Link to comment Share on other sites More sharing options...
ptitjes Posted February 19, 2008 Report Share Posted February 19, 2008 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 codeI 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...Best regards, Didier. Quote Link to comment Share on other sites More sharing options...
TK. Posted February 20, 2008 Report Share Posted February 20, 2008 Did not know the PIC had a pipelined architecture ! I hope sdcc takes care of this when he optimizes code...It isn't really an CPU architectural issue, it's more a side effect caused by the way how GPIO SFRs are handled. The same issue exists for 8051 derivatives with single-cycle execution, and so far I remember also for AVRs. It doesn't exist in microcontrollers which insert wait cycles during a read access, or which handle masked RMW operations internally in the GPIO stage.It's one of the first things you will notice when toggling a pin as fast as possible with "bsf/bcf" instructions - the pin won't toggle due to the FF at the input stage. You have to insert a NOP (or a more useful instruction) between bsf/bcf --- or you have to write into LATx instead of PORTx (if available)However, modern controllers always provide a seperate IN and OUT register for GPIOs :)Best Regards, Thorsten. Quote Link to comment Share on other sites More sharing options...
ptitjes Posted February 20, 2008 Report Share Posted February 20, 2008 It's one of the first things you will notice when toggling a pin as fast as possible with "bsf/bcf" instructions - the pin won't toggle due to the FF at the input stage. You have to insert a NOP (or a more useful instruction) between bsf/bcf --- or you have to write into LATx instead of PORTx (if available)Happy to know that because I'll do some shift and latch clock generation these next days... I will have to do a __asm nop __endasm define or write to latch registers directly so... Thanks for that useful information!Best regards, Didier. Quote Link to comment Share on other sites More sharing options...
stryd_one Posted February 20, 2008 Report Share Posted February 20, 2008 OMG nils, amongst all that confusion last night, I did get something right! (use LATA) hahahhaha! Quote Link to comment Share on other sites More sharing options...
nILS Posted February 20, 2008 Report Share Posted February 20, 2008 [me=nILS Podewski]pats stryd_one on the head: "Good boy" :D[/me] Quote Link to comment Share on other sites More sharing options...
audiocommander Posted February 21, 2008 Report Share Posted February 21, 2008 I did get something right! (use LATA) hahahhaha!OMG I really shouldn't have googled for pictures on LATA Quote Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.