Continue to Site

Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

Help PIC16f877A start ADC reading at a specific time using timer0 interrupt

Status
Not open for further replies.

shaolinyo

Newbie level 6
Newbie level 6
Joined
Aug 9, 2018
Messages
13
Helped
0
Reputation
0
Reaction score
0
Trophy points
1
Activity points
102
Help PIC16f877A start adc reading at spesific time using timer0 interrupt

hello , used timer0 interrupt to start reading adc , but it not work when i debug the code , i see that the interruption never occur


Code C - [expand]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
int t=0;   //time counter
 
void interrupt()
{
  if(INTCON.T0IF){
          t++;      //for evry inettruption occure we increment t
          TMR0=150;//the value to start the tmr0 if is spesified in the main program
}
 
  INTCON.T0IF=0;
 
}
    float i;
float data1;
char txt[20];
void main() {
 
Option_Reg=0b10010000;
INTCON=0b10100000;
 
trisd=0;
portd=0;
 
 TMR0=150;
 
 i=0;
 data1=0   ;
 
 
           lcd_init();
 
      ADC_Init();
 
 
     for(;;){
              if(t==1) {
     i=ADC_Read(0);
 
     data1=i/(1023/5);
     
     
     }
     }
     }



thank you
 
Last edited by a moderator:

Re: Help PIC16f877A start adc reading at spesific time using timer0 interrupt

Microchip do not recommend setting the GIE bit in the same instruction as setting other interrupt enables.
Try changing the code for INTCON to this:
INTCON.T0IE = 1;
INTCON.GIE = 1;

I'm not sure which compiler you are using but also be careful that the routine for reading the ADC has completed the conversion before you use the value it returns.
If you formatted the code so the each section between { and } was indented it would be far easier to read!

Brian.
 

Re: Help PIC16f877A start adc reading at spesific time using timer0 interrupt

i use microc compiler,
INTCON.T0IE = 1;
INTCON.GIE = 1;
didnt work for me
 

Re: Help PIC16f877A start adc reading at spesific time using timer0 interrupt

Hi,

i=ADC_Read(0);
i is defined as float, but I don´t think that ADC_read function is able to return a float value

data1=i/(1023/5);
data1 is never used....

Klaus
 

Re: Help PIC16f877A start adc reading at spesific time using timer0 interrupt

Regardless of the data type, please tell us Shaolinyo, how do you know the interrupt is not happening?
Is it just because you do not get the ADC value or can you confirm that 't' is not changing?

Brian.
 

Re: Help PIC16f877A start adc reading at spesific time using timer0 interrupt

i know interrupt is not happening by debuging setting a break point at
if(t==1) {

and i watch the value of the t varriable , i get it 0 , evry time t=0
and then i set break point after if(t==1) {
and i run it , it never get there
 

Re: Help PIC16f877A start adc reading at spesific time using timer0 interrupt

I've reformatted it to make it easier to read and moved the declarations to the top and cleared INCON.T0IF earlier.
I can not see any reason why the TMR0 interrupts shouldn't work unless something else is also causing interrupts or the watchdog is resetting the PIC before TMR0 reaches overflow.

Code:
int t=0;   //time counter
float i;
float data1;
char txt[20];

// ***********************************************
// ********** Interrupt Service Routine **********
void interrupt()
{
    if(INTCON.T0IF)
    {
        t++;        //for evry inettruption occure we increment t
        TMR0=150;   //the value to start the tmr0 if is spesified in the main program
        INTCON.T0IF=0;
    }
}

// **********************************
// ********** Main Routine **********
void main() 
{
    Option_Reg=0b10010000;
    INTCON=0b10100000;
 
    TRISD=0;
    PORTD=0;
 
    TMR0=150;
 
    i=0;
    data1=0;
 
    lcd_init();
    ADC_Init();
 
    for(;;)
    {
        if(t==1) 
        {
            i=ADC_Read(0);
            data1=i/(1023/5);
        }
    }
}

I used a tab setting of 4 in the code above.

Brian.
 
You should be using code such as:
Code:
if(INTCON.T0IE && INTCON.T0IF)
{
....
}
in situations where you can have more than 1 interrupt source and/or you could be enabling/disabling an interrupt at various times. While it may not apply in this case, my experience is that it is good habit to get in to.
Also watch expressions such as
Code:
data1=i/(1023/5);
as some compilers (not sure which one you are using) do not follow the same data type promotions as used on compilers for lager systems. For example, the '1023/5' could well be computed using integer arithmetic (to give '204') before being converted to floating point.
Also remember that floating point on these smaller MCUs is always simulated in code and is very slow (compared to integer operations and even there you only have 8 or 16 bit add and subtract - multiply and divide are also in code).
Susan
 
Last edited by a moderator:
Change this

Code:
void interrupt()
{
    if(INTCON.T0IF)
    {
        t++;        //for evry inettruption occure we increment t
        TMR0=150;   //the value to start the tmr0 if is spesified in the main program
        INTCON.T0IF=0;
    }
}

to

Code:
void interrupt()
{
    if(INTCON.T0IF)
    {
        t++;        //for evry inettruption occure we increment t
        if(t > 2) t = 0;
        TMR0=150;   //the value to start the tmr0 if is spesified in the main program
        INTCON.T0IF=0;
    }
}

If the interrupt is too fast then t may get a value higher than 1 or 2 and when its value is 1 or 2 it might not be in the main loop at if(t == 1) and so you maybe thinking that interrupt is not happening.

I am not sure whether PEIE bit also have to be enabled or not.

Turn on a bit like RD7 in interrupt when interrupt occurs. This will tell if interrupt is happening or not.

Zip and post your complete project files including Proteus file if any so that it can be tested and fixed.

- - - Updated - - -

You have not configured ADCON1 register.

This is the code which I made. You can use mikroE Timer Calculator tool to get code for required timer delay.


Code C - [expand]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
unsigned char flagRegister = 0;
unsigned int adcValue = 0.0;
 
sbit readAdcFlag at flagRegister.B0;
 
//Timer0
//Prescaler 1:256; TMR0 Preload = 61; Actual Interrupt Time : 49.92 ms
void InitTimer0() {
    OPTION_REG = 0x87;
    TMR0 = 61;
    INTCON = 0xA0;
}
 
void interrupt() {
  if((TMR0IE_bit) && (TMR0IF_bit)) {
      TMR0IF_bit = 0;
      TMR0 = 61;
      //Enter your code here
      readAdcFlag = 1;
  }
}
 
void main() {
 
    CMCON = 0x07;
    ADCON1 = 0x8E;
    
    TRISA = 0x01;
    TRISB = 0x00;
    TRISC = 0x00;
    TRISD = 0x00;
    TRISE = 0x00;
    
    PORTA = 0x00;
    PORTB = 0x00;
    PORTC = 0x00;
    PORTD = 0x00;
    PORTE = 0x00;
    
    Delay_ms(100);
    
    InitTimer0();
    
    while(1) {
    
          if(readAdcFlag) {
              adcValue = (unsigned int)ADC_Read(0);
              Delay_us(20);
              PORTD = adcValue;
              readAdcFlag = 0;
          }
    }
}

 
Last edited:
Status
Not open for further replies.

Similar threads

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top