PIC16F1847 wakeup from sleep interrupts - Page 1
Forum section: electronics / general

author: Veketti
author_rank: Regular Contributor
timestamp: March 16, 2023, 04:32:02 pm
content: Dear All,I've got an issue with PIC16F1847 and wake up by button press from sleep. I've got button connected to RB0 and it should wake up the PIC from sleep and turn on FET by function TurnOnDisplay();. However it never gets flag FlagForBtnPress set in interrupts. I've tried to understand this from datasheet:"On waking from Sleep, if the GIE bit is also set, theprocessor will branch to the interrupt vector. Otherwise,the processor will continue executing instructions afterthe SLEEP instruction. The instruction directly after theSLEEP instruction will always be executed beforebranching to the ISR."So I added INTCON = 0b11011000; before and after the sleep. Once it worked but when I tried removing either line it didn't go to interrupt anymore and after adding both never worked anymore. I don't understand that why it won't go to interrupt anymore. I measured the current and in sleep it draw 110uA and when I press the button 1mA so the PIC wakes up but disregards the interrupt. What's am I doing wrong? Using mikroC PRO for PIC. If I uncomment the "asm reset" line, it works from button press, so I can be sure it actually wakes up.Interrupt:Code:void Interrupt(void){if (INTF_bit){ // Pin Interrupt happenedINTF_bit = 0;FlagForBtnPress = 1;}if (IOCIF_bit) {IOCBF0_bit = 0;FlagForBtnPress = 1;}}In main loop.Code:// Go to sleepif (FlagForSleep == 1){if (ForceReading > 30) FlagForSleep = 0;else {Turnoffdisplay(); // Timer triggered sleepFlagForSleep = 0;INTCON = 0b11011000;asm sleep;INTCON = 0b11011000;//asm reset; // if this is uncommented, it works}}// Wake up from sleep and / or reset max readingif (FlagForBtnPress) {if (PORTA.f4 == 1) {TurnOnDisplay();SetTheADC();}FlagForBtnPress = 0;maxForce = 0; // Reset max Force from button pressVDetFlagPreviousStage = 0;}Edit: Ok, if I set the flag directly after the sleep, it obviously works and no need to reset. But the question remains, why it won't go to the interrupt handler when it wakes up from button press? When it is normally running and pressing the button, it sets the flag in interrupt.Code:if (FlagForSleep == 1){if (ForceReading > 30) FlagForSleep = 0;else {Turnoffdisplay(); // Timer triggered sleepFlagForSleep = 0;asm sleep;FlagForBtnPress = 1;}}

author: cv007
author_rank: Frequent Contributor
timestamp: March 16, 2023, 07:24:25 pm
content: Target your specific problem by creating a simple app. Once it works in the simple, you may understand why and can apply to the full app. If you still have a problem, then you have others that can help and they will only be looking at the specific problem and not your surrounding code which is not relevant.The nop after sleep is probably not needed in most cases, but is harmless and prevents from getting an instruction after the sleep that may cause a problem (1 instruction executes after the sleep instruction, whether gie is set or not). Also, it may be easier to skip using an interrupt as the pic will wake whether gie is set or not, just depends on what other interrupts are in use and whether gie needs to be on.Code://16F1619 - turn on led d4 for 2 seconds when s1 pressed#include <xc.h>#include <stdbool.h>#include <stdint.h>#define _XTAL_FREQ 500000ul //default speed out of reset//led D4=RA5, switch S1=RC4 (has external pullup)void __interrupt() ISR(){ //no checking is done in this example to determine the irq causeTRISA5 = 0; LATA5 = 1; //led output, on__delay_ms(2000);LATA5 = 0; //led offIOCCFbits.IOCCF4 = 0; //clear flag}void mySleep(){IOCCNbits.IOCCN4 = 1; //RC4 irq on change negativeINTCONbits.IOCIE = 1; //enable iocINTCONbits.GIE = 1; //global irq'sSLEEP();NOP();}int main(){while(1){mySleep();}}

author: DavidAlfa
author_rank: Super Contributor
timestamp: March 16, 2023, 08:06:43 pm
content: First of all, any variables modified inside a ISR must be declared as volatile.Are you doing so?

author: SiliconWizard
author_rank: Super Contributor
timestamp: March 16, 2023, 08:09:01 pm
content: Quote from: DavidAlfa on March 16, 2023, 08:06:43 pmYes, very likely culprit here.For the OP: to make sure the MCU is indeed running the ISR or not, toggle some GPIO inside of it. Contrary to optimization effects you can get with non-volatile variables, toggling a GPIO is guaranteed to be executed here.

author: Veketti
author_rank: Regular Contributor
timestamp: March 16, 2023, 09:10:27 pm
content: Actually, they were not declared as volatile. That would have made sense why the same code worked earlier few years back. Compiler has updated recently and maybe they've made some optimization. But unfortunately declaring volatile didn't fix this. This is very odd. If I compile the same code twice I might get different results. One time it works, other time not.

author: 8goran8
author_rank: Contributor
timestamp: March 17, 2023, 09:33:33 am
content: Can you post initialization code for your MCU?Why do you use INT0 and RB0 Interrupt on change at the same time?

author: SiliconWizard
author_rank: Super Contributor
timestamp: March 17, 2023, 11:36:57 pm
content: Quote from: Veketti on March 16, 2023, 09:10:27 pmHave you toggled some GPIO inside your ISR, as suggested, to see for sure whether it actually executes it or not?

author: Veketti
author_rank: Regular Contributor
timestamp: March 18, 2023, 07:36:30 am
content: Had to take some distance as banging head to brickwall two days with this single matter was getting my nerves. Anyhow.8goran8here are the initialization:Code:TRISA = 0b00100100;TRISB = 0b10000001;ANSELA = 0b00000000;ANSELB = 0b00000000;OPTION_REG = 0b10000000;INTCON = 0b11011000;IOCBN0_bit = 1;And attached is picture of the project settings. I'm not sure where it writes these values set in project properties, but I guess it uses OSC* and PCON registers to write these dropdown values. There is also I2C and timer registers involved, but maybe you're not interested in them..Originally I had only INT0 interrupt handling and now later tried also this RB0 to see whether it makes any differences. So that's why you see both, no other reason.SiliconWizardI added GPIO toggle inside the ISR and it successfully toggled the GPIO from button press wake up.Does this mean that there is a bug in the latest version (7.6.0) of compiler software?

author: DavidAlfa
author_rank: Super Contributor
timestamp: March 18, 2023, 12:21:57 pm
content: I doubt very much it's a compiler bug. Chances you're doing something wrong are 99%.cv007, what a terrible way of helping... 2s delay inside a ISR?? Code for a totally different pic...Veketti, depending on the RB pin you're using, modify IOCB_TRIS , IOCB_EDGE_N and IOCB_FLAG to match the same pin...Code:#define IOCB_TRIS TRISBbits.TRISB0#define IOCB_EDGE_N IOCBNbits.IOCBN0#define IOCB_FLAG IOCBFbits.IOCBF0volatile char got_ioc=0;void init(){INTCON = 0; // Disable everythingTRISAbits.TRISA5 = 0; // RA5 = output (LED)IOCB_TRIS = 1; // RBx = input (IOC pin)ANSELA = 0b00000000;ANSELB = 0b00000000;OPTION_REG = 0b10000000;IOCBP = 0; // Disable IOCB positive edgesIOCBN = 0; // Disable IOCB negative edgesIOCB_EDGE_N = 1; // Enable IOCBx negative edgeINTCONbits.PEIE = 1; // Peripheral Interrupt enabledINTCONbits.INTE = 1; // External Interrupt enabledIOCB_FLAG = 0; // Clear IOCBx flag just in case__delay_ms(200); // 200ms delay, let all the pins stabilize or you might get weird readingsINTCONbits.GIE = 1; // Global irqs enabled}void __interrupt() ISR(){if(IOCB_FLAG){ // Check IOCBx flagINTCONbits.IOCIE = 0; // Disable IOC isr until processedIOCB_FLAG = 0; // Clear IOCBx flaggot_ioc=1; // Indicate we got IOC ISR}}void mySleep(){INTCONbits.IOCIE = 1; // enable ioc irqSLEEP();NOP();}void woken(){if(got_ioc){ // got_ioc active?LATA5 = 1; // led on__delay_ms(2000); // 2s delayLATA5 = 0; // led offgot_ioc=0; // Clear flag}else{for(char i=0;i<10;i++){LATA5 ^= 1; // Toggle led fast several times__delay_ms(100); // 100ms delay}LATA5 = 0; // led off}}int main(){init();while(1){mySleep(); // Go to sleepwoken(); // Woke up}}

author: Veketti
author_rank: Regular Contributor
timestamp: March 18, 2023, 05:43:36 pm
content: Issue solved! I had two pic mcu's and the other was always in the programmer and I swapped between those two. Took a while to realize that the issue happened always with the other MCU. So it was somehow damaged. Now it's in garbage bin and never cause issue anymore.Thanks everybody.