• AVR Freaks

Helpful ReplyHot!Interrupt on PIC16F874A is performing the task in the ISR

Author
vero
Starting Member
  • Total Posts : 69
  • Reward points : 0
  • Joined: 2018/09/08 15:09:26
  • Location: 0
  • Status: offline
2019/05/22 15:10:40 (permalink)
0

Interrupt on PIC16F874A is performing the task in the ISR

I am trying to use the RCIE for the USART to stop/start the ADC when a certain is key received through the USART. In order to see if the program is going to the ISR, I changed the task in the ISR to just transmit a letter to the USART. This works when I write to the USART in the ISR routine, but when I have the ISR turn off the ADC, nothing happens, the ADC continues to stay on. I would appreciate any help or advice on this. thanks.
Here is main:

int main(void) {  
    unsigned char d;  
    init_uart1(9600);
    PEIE = 1;
    GIE = 1;
    RCIE = 1;
    init_ADC();        
    
    unsigned char list[size],d;
    unsigned short x,er,max = 4;
    unsigned char *messg;
    int len;       
    
    x = digital_volts_out(0x0); //Gets Digital conversion from ADC AN0
    __delay_ms(100);
    er = decode_value(x,list);  //Calculation to get decimal value and
    __delay_ms(500);            //convert to ASCII    
    print_value(list);    
    
    x = digital_volts_out(0x1);    //Convert AN1 to digital value
    __delay_ms(100);
    er = decode_value(x,list);  //Calculation to get decimal value and
    __delay_ms(500);                           //convert to ASCII
    print_value(list);
    if(!er){
        messg = "Result is a negative value\n\r";
        len = sizeof(messg)/sizeof(unsigned char);
        write_string_Uart(messg,len);        
    }//end if    
    
    return 0;
}

 
This is the ISR function:
 

void __interrupt() ISR(void)
{
   ADON = 0;         //This line doesn't work
   write_Uart('B');  //This line gets executed when the USART receives a character

   unsigned char d; //The rest of the code below never works even if I leave out the two lines above
   if(RCIF){
      d = read_Uart();  
      RCIF = 0;  
       switch(d){
         case 115://'s'
           ADON = 0;
           break;
         case 103://'g'
           send_value();
           break;
         case 'P':
           write_Uart('P');
           break;
         default:
           ADC_off();           
      }//end case
   
   }//end if
}

#1
qhb
Superb Member
  • Total Posts : 9998
  • Reward points : 0
  • Joined: 2016/06/05 14:55:32
  • Location: One step ahead...
  • Status: offline
Re: Interrupt on PIC16F874A is performing the task in the ISR 2019/05/22 15:15:37 (permalink)
+1 (1)
The correct definition for your main function is:
void main(void)
 
and the main function should NEVER exit!
 
Get rid of this line. You are trying to clear a read-only flag.
      RCIF = 0;  

 
Now, how do you know the rest of the ISR code doesn't work?
 

Nearly there...
#2
qhb
Superb Member
  • Total Posts : 9998
  • Reward points : 0
  • Joined: 2016/06/05 14:55:32
  • Location: One step ahead...
  • Status: offline
Re: Interrupt on PIC16F874A is performing the task in the ISR 2019/05/22 15:17:12 (permalink)
+1 (1)
I'm also curious why you need
d = read_Uart(); 

when right there, all you need to do is
d = RCREG;




Nearly there...
#3
vero
Starting Member
  • Total Posts : 69
  • Reward points : 0
  • Joined: 2018/09/08 15:09:26
  • Location: 0
  • Status: offline
Re: Interrupt on PIC16F874A is performing the task in the ISR 2019/05/22 15:24:20 (permalink)
0
You're right, I checked the manual and RCIF is read only. I changed the line to d = RCREG and It's still not working. It seems the rest of the code in the ISR isn't working because the ADC isn't turning off when I write 's' to the USART.
#4
qhb
Superb Member
  • Total Posts : 9998
  • Reward points : 0
  • Joined: 2016/06/05 14:55:32
  • Location: One step ahead...
  • Status: offline
Re: Interrupt on PIC16F874A is performing the task in the ISR 2019/05/22 15:28:55 (permalink)
+1 (1)
Again, how do you know?
You're just reporting your assumptions, not what you are actually observing.
Have you stopped your main function from exiting?

Nearly there...
#5
vero
Starting Member
  • Total Posts : 69
  • Reward points : 0
  • Joined: 2018/09/08 15:09:26
  • Location: 0
  • Status: offline
Re: Interrupt on PIC16F874A is performing the task in the ISR 2019/05/22 15:42:10 (permalink)
0
I got rid of the return 0 statement from main. Still not working as expected. It seems the other code isn't executing if it only does the statement that writes 'B' to the USART, but when I remove that statement and I type 's', the ADC stays on. The ADC should turn off. I will debug the program to step through those lines.
#6
qhb
Superb Member
  • Total Posts : 9998
  • Reward points : 0
  • Joined: 2016/06/05 14:55:32
  • Location: One step ahead...
  • Status: offline
Re: Interrupt on PIC16F874A is performing the task in the ISR 2019/05/22 15:52:28 (permalink)
+2 (2)
CVer2018
I got rid of the return 0 statement from main.

That wasn't your only problem.
main() will still exit if you let it get to the end of the function. You've made no mention of adding any code to stop that.
 

Still not working as expected. It seems the other code isn't executing if it only does the statement that writes 'B' to the USART, but when I remove that statement and I type 's', the ADC stays on.

For the third time, HOW DO YOU KNOW IF THE ADC IS OFF OR ON?
You keep saying it "stays on" without ever revealing what you are observing to determine this.
 

Nearly there...
#7
vero
Starting Member
  • Total Posts : 69
  • Reward points : 0
  • Joined: 2018/09/08 15:09:26
  • Location: 0
  • Status: offline
Re: Interrupt on PIC16F874A is performing the task in the ISR 2019/05/22 15:57:19 (permalink)
0
I know it's on because I am sending the decoded values to the USART continuously. I can see the values on tera term.
#8
qhb
Superb Member
  • Total Posts : 9998
  • Reward points : 0
  • Joined: 2016/06/05 14:55:32
  • Location: One step ahead...
  • Status: offline
Re: Interrupt on PIC16F874A is performing the task in the ISR 2019/05/22 16:00:24 (permalink)
+1 (1)
The code you posted only prints it once.
You only see it more than once because you are allowing your main function to exit, so everything is starting from scratch repeatedly. THAT is why the ADC is getting turned on again.
 
 
 

Nearly there...
#9
vero
Starting Member
  • Total Posts : 69
  • Reward points : 0
  • Joined: 2018/09/08 15:09:26
  • Location: 0
  • Status: offline
Re: Interrupt on PIC16F874A is performing the task in the ISR 2019/05/22 16:07:13 (permalink)
-1 (1)
No. It prints it continuously, even after I removed the return 0 statement.
#10
qhb
Superb Member
  • Total Posts : 9998
  • Reward points : 0
  • Joined: 2016/06/05 14:55:32
  • Location: One step ahead...
  • Status: offline
Re: Interrupt on PIC16F874A is performing the task in the ISR 2019/05/22 16:21:04 (permalink)
+1 (1)
Maybe when you start reading my replies correctly you will figure it out.
 

Nearly there...
#11
vero
Starting Member
  • Total Posts : 69
  • Reward points : 0
  • Joined: 2018/09/08 15:09:26
  • Location: 0
  • Status: offline
Re: Interrupt on PIC16F874A is performing the task in the ISR 2019/05/22 16:32:30 (permalink)
0
You know, I'm trying to learn and insulting me is not helping.
#12
vero
Starting Member
  • Total Posts : 69
  • Reward points : 0
  • Joined: 2018/09/08 15:09:26
  • Location: 0
  • Status: offline
Re: Interrupt on PIC16F874A is performing the task in the ISR 2019/05/22 18:10:38 (permalink)
0
I previously had a while(1) loop in main and it wasn't exiting, and it still didn't work.
#13
qhb
Superb Member
  • Total Posts : 9998
  • Reward points : 0
  • Joined: 2016/06/05 14:55:32
  • Location: One step ahead...
  • Status: offline
Re: Interrupt on PIC16F874A is performing the task in the ISR 2019/05/22 19:45:57 (permalink)
+1 (1)
CVer2018
I previously had a while(1) loop in main and it wasn't exiting, and it still didn't work.

Please post the actual code you used that contains a "while(1) loop",
and please report exactly what you observed when you did this test.
'"still didn't work" is not a useful observation.
 

Nearly there...
#14
Aussie Susan
Super Member
  • Total Posts : 3608
  • Reward points : 0
  • Joined: 2008/08/18 22:20:40
  • Location: Melbourne, Australia
  • Status: offline
Re: Interrupt on PIC16F874A is performing the task in the ISR 2019/05/22 19:47:45 (permalink) ☄ Helpfulby mpgmike 2019/05/24 12:10:11
+7 (7)
No one is being insulting but there is a level of frustration when you don;t answer the questions that are asked.
Also I suspect that you don't understand some of the fundamentals of writing embedded code.
Firstly, there is no operating system for your code to 'return' to. When the MCU resets (power on, after programmed or whatever), as you have written your code in C, a special 'startup' bit of code is executed that initialises global variables etc, and then calls you 'main()' function. The expectation is that this function will never return.
If for any reason the 'main()' function does return, then the 'startup' code will perform a reset and the whole cycle starts over again.
The way you make your program work is to structure it so that your main() function performs whatever initialisation is required (setting up the clock, initialising the modules you will use etc.) and then it enters an infinite loop. As the common way of creating the infinite loop is with the 'while(1){...}' statement within the main () function, this is normally referred to as the 'main loop' or 'while loop'. In that loop you do all of the repetative work of the app.
One way of operating is to (using you example of reading a character from a UART) is to poll the module to see if it has data ready (or space for new data to be sent or the time has elapsed or whatever). When the flag is set by the module, you use an 'if' statement to branch into the code than handles the situation.
Sometimes you can write a main loop that takes longer than you can afford to go around (this could be considered bad design but that depends on your circumstances) which means that you cannot respond to a module fast enough - for example read the character from a UART before the next one is received.
For such cases you can use an interrupt service routine (ISR). An ISR should be written to be a fast running as possible. Typically when an ISR is running no other processing can be done by the device so you should not put any code that blocks execution in the ISR. (Unfortunately I suspect that you are breaking this rule in your code.)
Therefore, you normally write code to do whatever is the minimum processing required (e.g. read a character form the UART and put it into a buffer) and then set a flag that is tested in the main loop when there is something more that is needed.
What I suspect your code is doing is reading and outputting the ADC values, over and over again. After each time through your code, you are resetting the MCU which causes you to go through this cycle again. You should be putting most of your code inside the main loop'.
In your scenario, you have several delays that total just over 1 second. If you happen to send a character to the MCU during that time, then the ISR will be triggered and you will get output (I'm guessing that the functions that are called to interact with the UART are blocking and so the execution will be stuck in the ISR for this part). It will also turn off the ADC.
However, when the ISR does exit, you will rapidly fall out of your code, the MCU will reset and you then re-initialise the ADC as it starts up again. In this case you will AGAIN start seeing values for the active ADC.
When you are being asked about how you know the ADC is not being turned off, you are going only by the characters that is being output from your program. The *REAL* way to determine if the ADC is being turned off (apart from using a main loop so your code does not exit) is to use the debugger.
I recommend that you use the ISR to read the UART character into a buffer (also perhaps turning off the ADC) and then setting a flag that can be tested in the main loop. (Hint: declare the flag to be 'volatile'.) In the main loop you can test for the flag being set and then put in all of the other code that is in your ISR at the moment inside the 'then' clause of the if statement.
Susan
#15
vero
Starting Member
  • Total Posts : 69
  • Reward points : 0
  • Joined: 2018/09/08 15:09:26
  • Location: 0
  • Status: offline
Re: Interrupt on PIC16F874A is performing the task in the ISR 2019/05/23 10:11:21 (permalink)
0
I do understand there is not an operating system included here. The return statement was just a mistake. I have been working in visual studio recently and it was just out of a habit I have of putting that statement in my code. I thought I had already answered qhb's question. So simply a misunderstanding. I had a while(1) statement in my code and I accidentally cut it out when I entered it in the post. I also had my program polling for RCIF to set, which worked, but I prefer to have an ISR. I will follow your suggestions to get the ISR to work correctly.
#16
NKurzman
A Guy on the Net
  • Total Posts : 17611
  • Reward points : 0
  • Joined: 2008/01/16 19:33:48
  • Location: 0
  • Status: online
Re: Interrupt on PIC16F874A is performing the task in the ISR 2019/05/23 14:49:55 (permalink)
+3 (3)
We can Only see what you Post.
If you Post different code, Then the help you get may not reflect your actual problem.
 
#17
mlp
boots too small
  • Total Posts : 777
  • Reward points : 0
  • Joined: 2012/09/10 15:12:07
  • Location: previously Microchip XC8 team
  • Status: offline
Re: Interrupt on PIC16F874A is performing the task in the ISR 2019/05/24 16:11:34 (permalink)
0
NKurzman
We can Only see what you Post.
If you Post different code, Then the help you get may not reflect your actual problem.

 
See also my other comment today https://www.microchip.com/forums/FindPost/1099254
 
I feel like a broken record.
post edited by mlp - 2019/05/28 12:57:53

Mark (this opinion available for hire)
#18
Jump to:
© 2019 APG vNext Commercial Version 4.5