CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to support@ccsinfo.com

Timer0 interrupt and adc conversion with pic16f88

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
mabauti



Joined: 08 Jul 2020
Posts: 4

View user's profile Send private message

Timer0 interrupt and adc conversion with pic16f88
PostPosted: Wed Jul 08, 2020 12:05 pm     Reply with quote

Hi gentlemen, I hope you're fine:

I'm writing here, because I having a problem with the Timer0 interrupt and adc conversion with pic16f88. Part of the code:
Code:
#INT_TIMER0
void timer0_isr(void)
{
  char m,portb_aux;
 
  clear_interrupt(INT_TIMER0);    // Clear timer0 interrupt flag bit
  set_timer0(61);
  i++;
  if(i > 2)
  {
    i = 0;
   //output_toggle(PIN_A1);
   
   m=read_adc();      //read ADC conversion
   //portb_aux = dec_bin(m);   //decimal to binary
   //output_b(portb_aux);
   output_b(m);
  }
}


main routine code
Code:
void main()
{
  // Setup timer0 with internal clock and 256 prescaler
  char portb_aux;
   
  setup_oscillator(OSC_4MHZ);
  setup_adc(ADC_CLOCK_DIV_32);
  setup_adc_ports(sAN0);
  set_adc_channel(0);
 
  setup_timer_0(RTCC_INTERNAL|RTCC_DIV_256);
  set_timer0(61);                // Timer0 preload value
  clear_interrupt(INT_TIMER0);   // Clear timer0 interrupt flag bit
  enable_interrupts(INT_TIMER0); // Enable timer0 interrupt
  enable_interrupts(GLOBAL);     // Enable all unmasked interrupt
  // Timer0_freq = MCU_freq / {4 * Prescaler * (256 – TMR0)}

  //period = 1/Timer0_freq
   
  while(TRUE) ;              // Endless loop
}


When I use delay instead of interrupts, the conversion is fine, however delays is a bad technique for this project; but when using interrupts like this I'm having irregular readings.



I'd appreciate your help pointing me at my mistake.
temtronic



Joined: 01 Jul 2010
Posts: 9127
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Wed Jul 08, 2020 1:03 pm     Reply with quote

hmm....

I believe that according to the ADC section of the datasheet, table 12-1 shows that ...
adc_clock-/32 is incorrect for a PIC clock of 4MHz....

also the ADC is actually 10 bits, so you need to tell the compiler to only use 8 bits ( 'm' is a char or 8 bits, 0-255).
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Wed Jul 08, 2020 2:18 pm     Reply with quote

Post a schematic of the circuit that is connected to the A/D input pin.
mabauti



Joined: 08 Jul 2020
Posts: 4

View user's profile Send private message

PostPosted: Wed Jul 08, 2020 3:25 pm     Reply with quote

temtronic: I changed it to 8bits, same result

PCM programer, pic


and thx for your answers
temtronic



Joined: 01 Jul 2010
Posts: 9127
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Wed Jul 08, 2020 4:09 pm     Reply with quote

Your 1st problem is that you cannot put an AC signal into the PIC ADC section !!!!
Like most(all ?) PICs, you'r ONLY accepts 0 to +5 VDC, never,ever a negative voltage.
Please reread the ADC section( 12 ?) as well as the 'electrical specification' section.

2nd problem is you don't have a current limiting resistor for the LED. There needs to be one, typically 470r for a VDD of 5 volts, though if you're using low current LEDs, you'll need maybe 2k2 or 4k7. That's easy to figure out once you know the 'specs' of the LED.
mabauti



Joined: 08 Jul 2020
Posts: 4

View user's profile Send private message

PostPosted: Wed Jul 08, 2020 4:20 pm     Reply with quote

I'm using a function generator. sine wave, offset +2.2, Vpk 2.2V
and the led disconnected : same result

thx for your answer temtronic
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Wed Jul 08, 2020 6:47 pm     Reply with quote

Thanks for posting that.

Now, post your delay code that works, so we can compare it to the
interrupt code. Also, post the waveforms for the delay code.
hmmpic



Joined: 09 Mar 2010
Posts: 314
Location: Denmark

View user's profile Send private message

PostPosted: Wed Jul 08, 2020 11:13 pm     Reply with quote

Some hints.
-Real hw or a simulator?
-What is the frequency you convert on the ad?
-What and why is i++ in the interrupt, where is it defined?
-Remove the clear_interrupt in the interrupt service, i never use it, compiler clear it.
Ttelmah



Joined: 11 Mar 2010
Posts: 19249

View user's profile Send private message

PostPosted: Thu Jul 09, 2020 1:30 am     Reply with quote

One big problem here is that you end up sitting inside the timer interrupt
for the whole ADC conversion time. Now at Fosc/32, the ADC conversion
actually takes 1/13888 seconds. Now Fosc/32 is outside the specified
value for the chip:
Quote:

For correct A/D conversions, the A/D conversion clock
(TAD) must be selected to ensure a minimum TAD time
as small as possible, but no less than 1.6 μs and not
greater than 6.4 μs.

You are using 8uSec.....
(actually I can't see where you say what clock rate you are using for the
CPU).

So the first thing to do is choose a legal divider. Fosc/8.
This then gives the conversion taking 1/55000th second. Rather better.
Then consider not waiting in the interrupt for the conversion. Instead have
the conversion being done between the interrupts:
Code:

void main()
{
  // Setup timer0 with internal clock and 256 prescaler
  char portb_aux;
   
  setup_oscillator(OSC_4MHZ);
  setup_adc(ADC_CLOCK_DIV_8);
  setup_adc_ports(sAN0);
  set_adc_channel(0);
 
  setup_timer_0(RTCC_INTERNAL|RTCC_DIV_256);
  set_timer0(61);                // Timer0 preload value
  clear_interrupt(INT_TIMER0);   // Clear timer0 interrupt flag bit
  read_adc(ADC_START_ONLY); //trigger the ADC
  enable_interrupts(INT_TIMER0); // Enable timer0 interrupt
  enable_interrupts(GLOBAL);     // Enable all unmasked interrupt
  // Timer0_freq = MCU_freq / {4 * Prescaler * (256 – TMR0)}

  //period = 1/Timer0_freq
   
  while(TRUE) ;              // Endless loop
}

//Then the timer code:
#INT_TIMER0
void timer0_isr(void)
{
  char m,portb_aux;
 
  //clear_interrupt(INT_TIMER0);    // Clear timer0 interrupt flag bit
  //Not needed the compiler does this automatically
  set_timer0(61);
  i++;
  if(i > 2)
  {
    i = 0;
   //output_toggle(PIN_A1);
   
   m=read_adc(ADC_READ_ONLY); //read ADC conversion already done
   read_adc(ADC_START_ONLY); //start next conversion.
   //portb_aux = dec_bin(m);   //decimal to binary
   //output_b(portb_aux);
   output_b(m);
  }
}


What is happening here is that each time in the interrupt I 'read' the
conversion the ADC has already performed, and start a new conversion
(since the interrupt frequency is lower than the total of ADC conversion
time and Tacq, the ADC has time to acquire after the last conversion is
completed). This makes the time in the interrupt vastly lower.

Now you do realise that given you have the 'i' counter, the ADC will only
read every third interrupt (why?....). Seems a really silly bit of coding.
Your interrupt is occurring every 195 clocks on the timer, which is running
off the CPU/256. So as posted at 4Mhz, you would be only interrupting
every (4000000)/(4*256*195) = 20 times a second, and reading the
ADC just 6.6 times a second. Not surprising that the waveform shows steps.

Do you really want just 6 samples/second?.
mabauti



Joined: 08 Jul 2020
Posts: 4

View user's profile Send private message

PostPosted: Tue Jul 14, 2020 9:46 am     Reply with quote

hmmpic wrote:
Some hints.
-Real hw or a simulator?
-What is the frequency you convert on the ad?
-What and why is i++ in the interrupt, where is it defined?
-Remove the clear_interrupt in the interrupt service, i never use it, compiler clear it.

Simulator
1Hz
global variable
ok, cleared

Ttelmah wrote:
Do you really want just 6 samples/second?.

In fact, I want to sample a 10hz max signal, so I need at least 100 samples/s

Done!

It was a synchronization problem as Ttelmah said

Thank you Ttelmah, hmmpic ,PCM programmer and temtronic Very Happy
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group