PIC - can't toggle GP1 and GP2 - Page 1
Forum section: electronics / beginners

author: con-f-use
author_rank: Unknown
timestamp: September 08, 2015, 03:23:53 pm
content: I haven't used PIC chips until now. I'm programming a pic10f200 with MPLAB X IDE v2.35. The pic10 is a very small, limited micro controller, but I just need to toggle pins with delay in a certain order. It's working fine for the gernal purpuse IO pin number 0 and 1, but 2 won't do anything. I wonder why this is. I know that GP3 is input only, but GP2 should be bi-directional. Did I do something stupid? Can you help me?Here is aminimalverbose example:Code:#include <xc.h>#pragma config CP = OFF // Code protection off#pragma config MCLRE = OFF // Master Clear Enable (GP3/MCLR pin fuction is digital I/O, MCLR internally tied to VDD)#pragma config WDTE = OFF // Watchdog Timer disabled#define _XTAL_FREQ 40000000void main(void) {OPTION = 0| nGPWU // 7: no wake-up on pin change| nGPPU // 6: no weak pullups| ~T0CS // 5: internal clock| ~T0SE // 4: increment low to high| ~PSA // 3: pre-scale for Timer0| PS2 | PS1 | PS0 // 2-0: clock devision by 256;OSCCAL &= ~(FOSC4); // no clock output on GP2TRISGPIO = 0b00000000; // set all to outwhile(1) {GP0 = 1; GP1 = 1; GP2 = 1; __delay_ms( 50);GP0 = 0; GP1 = 0; GP2 = 0; __delay_ms(250);}}GP2 is connected directly to the gate of a small P-channel MOSFET that is pulled down to GND with a 12k resistor. I' measuring directly hat the gate. My intend is to have the MOSFET default to on and turn if off by pulling the gate high every once in a while.

author: con-f-use
author_rank: Unknown
timestamp: September 08, 2015, 04:06:27 pm
content: Thanks! The PIC10F200 doesn't have a comparator so MPLAB doesn't even recognize the comparator register to change anything. Even the clock output you're referring to is default-off. I just put in there to be sure. FOSC4 should be off because the timer is set for internal clock. I wouldn't know what else to turn off.

author: picandmix
author_rank: Frequent Contributor
timestamp: September 08, 2015, 04:23:02 pm
content: This tutorial might help...http://www.best-microcontroller-projects.com/12F675.html#Program_1_:_12F675_Flashing_an_LED

author: Zarhi
author_rank: Contributor
timestamp: September 08, 2015, 04:29:03 pm
content: Set T0CS in OPTION register to 0, it defaults to 1.

author: con-f-use
author_rank: Unknown
timestamp: September 08, 2015, 04:31:22 pm
content: Quote from: Zarhi on September 08, 2015, 04:29:03 pmYes, and it is set to 0 in this line:Code:| ~T0CS // 5: internal clockQuote from: picandmix on September 08, 2015, 04:23:02 pmI think I'm familiar with the basics. As I said, the Code works for pins zero and one, just not for two. I don't see anything in that tutorial related to this specific problem.

author: macboy
author_rank: Super Contributor
timestamp: September 08, 2015, 04:33:19 pm
content: Quote from: con-f-use on September 08, 2015, 04:06:27 pmWhat else to turn off is listed in table 5.1 as posted by AchMed99. Three function have precedence above the GPIO usage. You must ensure it is not set to output FOSC/4 by clearing bit 0 of OSCAL. You must ensure it is not used by the comparator (not an issue with this device). You must ensure it is not used as an input for Timer 0 by clearing bit T0CS of OPTION register. Then it is usable as a GPIO pin.

author: Zarhi
author_rank: Contributor
timestamp: September 08, 2015, 04:38:03 pm
content: Well, that is assembly result from mplabx, xc 1.3360 005 _main:6162 ;newmain.c: 8: OPTION = 063 ;newmain.c: 9: | 0x8064 ;newmain.c: 10: | 0x4065 ;newmain.c: 11: | ~0x2066 ;newmain.c: 12: | ~0x1067 ;newmain.c: 13: | ~0x868 ;newmain.c: 14: | 0x4 | 0x2 | 0x169 ;newmain.c: 15: ;7071 ;incstack = 072 ; Regs used in _main: [wreg-fsr0h+status,2+status,0+btemp+3]73 005 CFF movlw 25574 006 002 option75So, You are setting OPTION to 0xff, which is default at power on.

author: con-f-use
author_rank: Unknown
timestamp: September 08, 2015, 04:43:38 pm
content: Okay, I might be mistaking, but I thing I got all that covered...Quote from: macboy on September 08, 2015, 04:33:19 pmCode:OPTION = 0 // <--------- here is a zero to start with| nGPWU // 7: no wake-up on pin change| nGPPU // 6: no weak pullups| ~T0CS // 5: internal clock <-------------- this ensures it's set to zero| ~T0SE // 4: increment low to high| ~PSA // 3: pre-scale for Timer0| PS2 | PS1 | PS0 // 2-0: clock devision by 256;Quote from: macboy on September 08, 2015, 04:33:19 pmCode:OSCCAL &= ~(FOSC4); // no clock output on GP2Also it is zero on power on see:

author: con-f-use
author_rank: Unknown
timestamp: September 08, 2015, 04:48:18 pm
content: Quote from: Zarhi on September 08, 2015, 04:38:03 pmOkay, than back to bit operators, for me.Just to double-check, it should work withCode:OPTION = 0b11011111;

author: Zarhi
author_rank: Contributor
timestamp: September 08, 2015, 05:04:14 pm
content: Code:OPTION = 0 // that 0 is not needed| nGPWU // 7: no wake-up on pin change| nGPPU // 6: no weak pullups& ~T0CS // 5: internal clock& ~T0SE // 4: increment low to high& ~PSA // 3: pre-scale for Timer0| PS2 | PS1 | PS0 // 2-0: clock devision by 256;Looking at cpu header file help allways ( in Your case pic10f200.h, look in xc8 installation directory )

author: con-f-use
author_rank: Unknown
timestamp: September 08, 2015, 05:16:41 pm
content: Okay, thank you guys. That is what I meant to write. It was a stupid little error on my part and rather embarrassing. I've coded thousands of lines on AVRs and never made a basic bit-operations error. Sorry to have bothered you.

author: con-f-use
author_rank: Unknown
timestamp: September 09, 2015, 12:09:42 pm
content: If I can bother you guys again. As an exercise in getting to grip with the C dialect that MPLAB uses, I now want to put the pic in sleep mode during the wait phases. Is that at all possible and if so, does the pic reset complete when waked by the watchdog or is there a way to preserve data between watchdog resets?With ATTinys and ATmegas, I would just configure the watchdog to do an interrupt instead of a reset, have the uC wake from that interrupt and have the interrupt function empty. Then it would automatically resume code execution where it left of before the sleep.So here is an idea of what I want, obviously that doesn't work:Code:#include <xc.h>#pragma config CP = OFF // Code protection off#pragma config MCLRE = OFF // GP3/MCLR pin fuction is digital I/O#pragma config WDTE = ON // Watchdog Timer enabled#define _XTAL_FREQ 4000000void main(void) {OPTION = 0 | nGPWU | nGPPU & ~T0CS & ~T0SE | PSA | PS2 | PS1 | PS0; // bits: 7: no wake-up on pin change; 6: no weak pullups; 5: internal clock; 4: incremnt low to high; 3: prescale on wdt (Timer0 if cleared); 2-0: clock division by 128TRISGPIO = 0b00000000; // set all to outputwhile(1) {GP0 = 1; GP1 = 1; GP2 = 1; SLEEP(); // set all high and sleep a bit// --------> MAGICALLY CONTINUE HERE AFTER SLEEP <---------GP0 = 0; GP1 = 0; GP2 = 0; SLEEP(); // set all low and sleep a bit}}I find the datasheet to be a bit vague on what exactly is reset during sleep and where the entry point after sleep is. Any help is very much appreciated!

author: BloodyCactus
author_rank: Frequent Contributor
timestamp: September 09, 2015, 12:23:10 pm
content: Quote from: Zarhi on September 08, 2015, 05:04:14 pmthat C code for setting your option looks so wrong to me. you have bitwise AND's that are not operating on what you think they are operating on. I dont think you understand how the & is working in that specific statement regarding operator precedence and LR associativity.Code:OPTION = nGPWU | nGPPU | PS2 | PS1 | PS0;You could add but probably dont needCode:OPTION &= ~(T0CS | T0SE | PSA);after the above line.I see you spammed this all over stack exchange as well.

author: con-f-use
author_rank: Unknown
timestamp: September 09, 2015, 01:26:27 pm
content: Quote from: BloodyCactus on September 09, 2015, 12:23:10 pmYou are completely right. My code above is a bit convoluted.In my tests I always set it in bit-notation like `OPTION = 0b11000111` but for the Forum I thought the way above might be clearer. My bad for using something I normally don't and doing it without testing first.But it should yield the same results, provided the Macros are single bits in an 8bit integer, which we can assume. See thisexamplewritten in plain C and run on my laptop. I might still have the associativity and order wrong in my head, but at least it randomly seems to spurt out the right result.Quote from: BloodyCactus link=topic=54764.msg750484#msg750484I wouldn't say one question on a site that is made for questions, means it is "spammed all over". I asked it here again, after many hours, because it didn't get an answer and people were criticizing my choice of C as the language to use instead of either ignoring my stupid question or helping me. Here people tend to be a little more helpful.

author: Zarhi
author_rank: Contributor
timestamp: September 09, 2015, 02:33:01 pm
content: Quote from: BloodyCactus on September 09, 2015, 12:23:10 pmIt "may" looks wrong, but that is resolved/calculated in C pre-processor. Assembly result is only two instructions: load 199 ( 0xc7, 0b11000111 ) to W, load W to OPTION register.This was example how to set/clear particular bits when they are defined as bit-mask.In this case OPTION register is set at once, ignoring it's current value, so it's enough to OR with bit-masks we want to set to 1, or AND 0xFF with ~bit-mask we want to clear. In that particular cpu OPTION register is write-only, there is no way to read it's current value.

author: Maxlor
author_rank: Frequent Contributor
timestamp: September 09, 2015, 02:45:42 pm
content: Actually, SLEEP() works exactly like you want it to, i.e. like a pause in your program, with automagic resumption after the SLEEP() command. If you set the watchdog beforehand, it'll turn into a timed sleep (just don't forget to disable or otherwise handle the watchdog after sleeping!)The documentation is clear enough: it says that on watchdog reset during sleep, or !MCLR reset during sleep, all registers keep their values except for these four bits: !TO, !PD, GPWUF and CWUF. They allow you to check why you woke up, whether it was the watchdog expiry, whether !MCLR was pulled high, or whether one of the peripherals caused it. If there's only one possible wakeup source, i.e. just the watchdog, you can ignore those.

author: con-f-use
author_rank: Unknown
timestamp: September 09, 2015, 03:41:08 pm
content: Then I have no idea, why my example code doesn't work and I see all the pins high all the time. Do I have to clear the watchdog somehow with an extra command?Here isanother example. It never stops blinking, although it should enter an infinite while loop where all pins are low.I'm sure I'm missing something incredibly stupid, I just don't see what it is.

author: MarkF
author_rank: Super Contributor
timestamp: September 09, 2015, 04:50:31 pm
content: For your 1st example code, I'm having a hard time determining exactly what you tested with. You say you posted one thing for the OPTION and tested with another thing. Can you post exactly what you tested with? Maybe try setting and clearing the I/O bits by setting the GPIO byte instead of the individual bits. Maybe try this small variant:Code:#include <xc.h>// PIC10F200 Configuration Bit Settings#pragma config WDTE = OFF // Watchdog Timer (WDT disabled)#pragma config CP = OFF // Code Protect (Code protection off)#pragma config MCLRE = OFF // Master Clear Enable (GP3/MCLR pin fuction is digital I/O, MCLR internally tied to VDD)#define _XTAL_FREQ 4000000L // 4MHz clock#define delay_us(x) _delay((unsigned long)((x)*(_XTAL_FREQ/4000000.0)))#define delay_ms(x) _delay((unsigned long)((x)*(_XTAL_FREQ/4000.0)))int main(int argc, char** argv) {OSCCAL = 0b11111110;OPTION = 0b11000111;TRISGPIO = 0b00000000;// MAIN LOOPwhile (1) {GPIO = 0;delay_ms(1000);GPIO = 7;delay_ms(1000);}}In your 2nd example code, you turned on the Watchdog Timer but never clear it in the main loop.The Watchdog timeout = 18 ms * 128 prescaler = 2.304 sec.Without executing the CLRWDT(); instruction before the timeout, you MCU is resetting and starting over causing at least part of your problem.

author: macboy
author_rank: Super Contributor
timestamp: September 09, 2015, 04:50:38 pm
content: Quote from: con-f-use on September 09, 2015, 03:41:08 pmYour code example pasted here for reference:Code:#include <xc.h>#pragma config CP = OFF // Code protection off#pragma config MCLRE = OFF // GP3/MCLR pin fuction is digital I/O#pragma config WDTE = ON // Watchdog Timer enabled#define _XTAL_FREQ 4000000void main(void) {int ita;OPTION = 0b11011111;TRISGPIO = 0b00000000; // set all to output// toggle bin fast (blink)for(ita=0; ita<10; ++ita) {GP0 = 0; GP1 = 0; GP2 = 0;__delay_ms(50);GP0 = 1; GP1 = 1; GP2 = 1;__delay_ms(50);}// keep it high for about 2sGP0 = 1; GP1 = 1; GP2 = 1;__delay_ms(1000);__delay_ms(1000);// all pins low for about 20swhile( 1 ) {GP0 = 0; GP1 = 0; GP2 = 0;SLEEP(); // 1.8 and 2.3s}}Consider:The MCU can wake up in four ways (if each is enabled):1. WDT Reset2. MCLR Reset3. Change in GPIO 1, 2, or 34. Comparator output changeYou have enabled #1.(see section 9.9.2)Consider:AWDT Resetor aWDT wake-up Resetwill result in adevice resetregardless of whether the device is running normally or sleeping. (see section 9.6)Consider:The reset vector is 0x000. (This is the instruction executed after adevice reset. see section 4.1).Your simple blinky code has enabled the WDT, assigned the prescaler of 128 to it, and gone to sleep. After ~ 2.3 seconds, the WDT will expire and generate aWDT wake-upReset.Now, why does your example code not wait forever inside the while(1) loop?

author: MarkF
author_rank: Super Contributor
timestamp: September 09, 2015, 04:59:13 pm
content: Check the pic10f200 errata (This seems to apply to you):QuoteSorry. I miss read your 1st post.

author: macboy
author_rank: Super Contributor
timestamp: September 09, 2015, 05:02:23 pm
content: Quote from: MarkF on September 09, 2015, 04:50:31 pmExecuting SLEEP will reset the WDT and its prescaler.

author: MarkF
author_rank: Super Contributor
timestamp: September 09, 2015, 05:04:57 pm
content: Quote from: macboy on September 09, 2015, 05:02:23 pmNo. CLRWDT() will just restart the WDT count. Not the prescaler.I don't think SLEEP resets the WDT.See the macros in my example code. I believe they match the Micochip versions.His example will never reach the SLEEP instruction. The WDT will timeout long before that.

author: con-f-use
author_rank: Unknown
timestamp: September 09, 2015, 05:09:03 pm
content: Okay. Thanks for all your replies, I really appreciate all the help and you're great. It's just that now you are confusing me alot.So one guy says, the uC just continues, where it left of, the other one says (as I suspected earlier) that after a wakeup the uC resets and executes the program from the start. Now which of the two is the case? If the latter, how do I keep a bit of data after a wakeup from sleep, to have the program act differently? E.g. spend more time than one WDT timer cycle in sleep, say five and then do something new. (How) Is that at all possible?

author: con-f-use
author_rank: Unknown
timestamp: September 09, 2015, 05:23:22 pm
content: Quote from: MarkF on September 09, 2015, 05:04:57 pmThat is exceedingly correct.In thisexample with CRLWDT, the pins are actually turned off until the WDT resets the uC after about 2s. Then the program starts over again. All I did was putting CLRWDT(); in after long delays. That is a step further.Now, can the WDT jump back into the infinite loop after reset? Or maybe can I set a variable that persists after the reset and jump into the loop? Something like that would be needed.

author: macboy
author_rank: Super Contributor
timestamp: September 09, 2015, 05:35:38 pm
content: Quote from: MarkF on September 09, 2015, 05:04:57 pmHis code will reset before hitting the while loop, since the CLRWDT is never called, and the total of all delays is 3 seconds. A CLRWDT must be done before every delay statement. If a longer delay than 1 second is needed, it should be broken into 1 second chunks with a CLRWDT between them.The datasheet clearly states that the SLEEP instruction resets the WDT prior to sleeping. The text of the datasheet is a little ambiguous as to what happens on SLEEP or CLRWDT, it says it will "reset the WDT" but does not elaborate. To knowexactlywhat happens when either of these instructions are executed, refer to the instruction set summary section. Under the CLRWDT instruction, it states that the WDT timer and prescaler are cleared (page 49). Same is true under the SLEEP instruction (page 51). Also refer to31026a.pdfwhich states "The CLRWDT and SLEEP instructions clear the WDT and the postscaler (if assigned to the WDT)".

author: macboy
author_rank: Super Contributor
timestamp: September 09, 2015, 05:50:15 pm
content: Quote from: con-f-use on September 09, 2015, 05:23:22 pmYou need to check the reset reason bits in STATUS. If you are using XC8, learn about the "resetbits" option so that these bits survive the initialization that XC8 does after resets. You could write some logic in there to identify a WDT reset, then jump (goto) a label in your while loop, but that looks rather ugly, especially in C.

author: macboy
author_rank: Super Contributor
timestamp: September 09, 2015, 05:59:14 pm
content: Quote from: con-f-use on September 09, 2015, 05:09:03 pmLook at section 9.9.2, "Wake-up From Sleep".There are four ways to wake up, but ALL of them cause a device reset.This is not necessarily the case for all PICs or for all other micros, but for this little guy, it is how it works.edit: All modes of wake up cause device reset.

author: Maxlor
author_rank: Frequent Contributor
timestamp: September 09, 2015, 06:30:02 pm
content: Quote from: macboy on September 09, 2015, 05:59:14 pmI must retract my earlier statement, macboy is quite correct. I was thinking of my experience with the PIC10F322, but upon comparing the sections about SLEEP in the two datasheets, it's clear that the PIC10F200 doesn't continue after SLEEP. I thought the 322 was essentially a 200 with more peripherals, but it appears the core is more modern too.So sorry for the confusion.

author: con-f-use
author_rank: Unknown
timestamp: September 09, 2015, 06:37:30 pm
content: Quote from: macboy on September 09, 2015, 05:59:14 pmFair enough. I knew the little one wouldn't reach as high, and it is still useful with its GPIOs and its Timer. The Timer seems straight forward at least. This was primary an exercise in getting to know the f200 and I thank you all for the introduction! For now I have no application where I would run it from battery, so all is good still. Of course if somebody comes up with new information, I'd be happy to here it. Thanks again everybody and good day!

author: Howardlong
author_rank: Super Contributor
timestamp: September 09, 2015, 08:06:09 pm
content: You PICked (see what I did there?) a bit of a bitch of a PIC to start on, and using the WDT as a way to do a blinky is also not a beginner exercise as your main() becomes a state machine.A couple of other tips are in the code below that blinks GP2 at about 2Hz.These low end devices are very restricted for debugging too, even with the debug header, which I have here. For example, you can't debug WDT resets at all, and there's only one breakpoint available. Having only six pins also means there's only one left after you've provided power and an ICP header!Code:#include <xc.h>#include <stdbool.h>#pragma config CP = OFF // Code protection off#pragma config MCLRE = OFF // Master Clear Enable (GP3/MCLR pin fuction is digital I/O, MCLR internally tied to VDD)#pragma config WDTE = ON // Watchdog Timer enabled#define _XTAL_FREQ 40000000static persistent bool _bState; // Persistent so the C startup code doesn't initialisevoid main(void){// Check STATUS bits for type of resetif ( ! ( GPWUF==0 && nPD==0 && nTO==0 ) ){// NOT a WDT wakeup from sleep, so treat as a power on reset_bState=false;OSCCALbits.FOSC4=0;}// These SFRs must be re-written after every resetOPTION = 0b11001100; // WDT is div-by-32 prescaledTRISGPIO = 0b1011; // GP2 outputGP2=_bState;_bState=!_bState;SLEEP();}Edited for code intentation correction

author: amyk
author_rank: Super Contributor
timestamp: September 10, 2015, 01:13:53 am
content: Quote from: Zarhi on September 09, 2015, 02:33:01 pmIt works only by accident; you should really learn theoperator precedenceof the language properly. The way you've written it makes no sense to everyone else who does know the language.

author: KL27x
author_rank: Super Contributor
timestamp: September 10, 2015, 01:53:34 am
content: AFAIK, even with the 10F320, and possibly with all 8 bit PICs, the WDT performs a RESET. It would defeat the purpose, otherwise. Some of the simpler PICs RESET on all wakes, and some resume after waking... but not typically due to a WDT timeout.What you want is EEPROM. Read EEPROM to get data +-counter, load into RAM, run main code, save data/counter to EEPROM, SLEEP, WDT RESET, repeat.Hmm, on second thought, there may be a way to have multiple RESET states using a 10F200, as long as your states do not need arbitrary data, such as in your example of blinking an LED with two different predetermined intervals. You could examine the registers that do not change state and see which ones you can modify without affecting your code. On wake up, you would read these bits to identify the cuurent state; load the corresponding data into your data registers, then modify those bits for the next state in the sequence before SLEEP. The number of states would only be limited by the number of special function register bits you can read/modify/write without fudging your circuit. If you could identify enough of these bits, you could even use some of them to store arbitrary data, which you could use to jump to different states out of sequence, or for other purposes.If you want low power draw, check out 12F1822. A couple years back, this was one of the best PICs I could find to make a very low draw, 3 month interval coin cell timer with 5 I/O's. I set the WDT to 256 seconds and saved the state and counter data to EEPROM.It's an interesting suggestion to check the POR bits to determine a WDT reset; Check this bit and use it to conditionally initialize your data registers. One could presume that as long as power remains applied that the DATA registers might remain intact? (Not really sure how that works. I know when you flash a PIC with a PICKIT2 and you don't cycle the power, all the data registers start out cleared after that initial flash; then next time you cycle the power, the registers are random. This "bug" cost my a few gray hairs). Sounds like it might work, if the 10F200 has this POR feature, but I would rather avoid trying it in the first place.

author: MarkF
author_rank: Super Contributor
timestamp: September 10, 2015, 03:39:04 am
content: In all of this, has the original question that con-f-use asked been answered?"How to toggle GP2 bit?"How did we get into this discussion on the WDT and resets? Does the WDT need to be used in order to use GP2 as an output?For me, the WDT is a failsafe recovery mechanism. In normal operation, the WDT would never be invoked.

author: KL27x
author_rank: Super Contributor
timestamp: September 10, 2015, 04:20:57 am
content: I believe he fixed that issue. In any case, these errors almost always boil down to either misconfiguration or read/modify/write error.WDT is useful for low-draw battery-powered applications for keeping track of time while asleep 99.9999999999% of the time. I don't know of any other way to track time while asleep, without resorting to an external clock.

author: MarkF
author_rank: Super Contributor
timestamp: September 10, 2015, 05:44:52 am
content: Thanks KL27x. I'm currently working on a handheld device where that may come in handy. I'll have to explore the possibilities.

author: con-f-use
author_rank: Unknown
timestamp: September 10, 2015, 07:07:19 am
content: Quote from: MarkF on September 10, 2015, 03:39:04 amBoth issues were fixed. For GP2 I had made an error when setting the OPTION register. In two places I had used a bitwise OR, where an AND was required. I fixed that and it worked fine.Then I aspired for more and wanted to replace the __delay_ms() with a watchdog sleep. That is possible with a `persistent` variable, that apparently is not initialized and therefore sustains its state between resets. The problem is to initialize it. That can be solved by querrying certain other registers to distinguish a power on from a watchdog reset. SeeHowardlong's excellent answer.As far as I have seen, the 10f200 doesn't have Timer interrupts, so the Timer is not that practical to replace delays, but it seems easy and straight forward to use.

author: Howardlong
author_rank: Super Contributor
timestamp: September 10, 2015, 07:08:06 am
content: Quote from: MarkF on September 10, 2015, 03:39:04 amI believe it was answered.There were two other questions that came up.Firstly, what happens on WDT wake up during sleep? The processor does not continue, it resets and you have to check the status bits at the beginning of main() to determine that you've come out of sleep rather than a hard reset.Secondly, how do you preserve state at WDT reset? Some register bits are reset, some not. Most notably the TRIS bits are reset to all input and the OPTION register is reset to 0b11111111. RAM is preserved, but the C startup code will clobber it unless you use static or global variables with thepersistentmodifier.All of these questions were answered in my code segment a few posts back.I agree with the use of the newer enhanced core PICs, denoted PIC1xF1xxx. These are significantly easier to develop for for a number of reasons. But I remember thinking a decade ago that it was pretty cool having a SOT-23 with an MCU in it. I still use them for simple things like loading up registers via SPI for PLLs.One final thing, I wasn't quite sure what the point of the comment on Stack Exchange criticising the use of C. Personally I haven't written a purely assembly language solution for any PIC this century, and I was brought up on assembly language (direct machine code in fact) in the 70s. While it can of course be done, and for these tiny devices it's a reasonable option, finding someone who knows what they're doing to maintain it these days won't be an easy task.

author: MarkF
author_rank: Super Contributor
timestamp: September 10, 2015, 11:38:10 am
content: Quote from: Howardlong on September 10, 2015, 07:08:06 amI'm there with you. I wrote assembly (debugging the machine code) in the 70s and early 80s. Remember the Honeywell 516 and Dec PDP-11/55. Now it's all C/C++. For me, the most important coding factor is the read ability and maintainability. Execution time and memory constraints can then be addressed after the code has been developed. I have seen a number of people over the years try to cram as much functionality as they can into one line of code. Sure it works and it's cool but it's also a nightmare to maintain.Happy coding everyone.