View previous topic :: View next topic |
Author |
Message |
Shaheers
Joined: 23 Sep 2013 Posts: 14
|
Getting Samples over specific time using timer |
Posted: Sun Nov 10, 2013 10:06 am |
|
|
I am sampling the 50Hz AC signal resolution of 700uS using Timer1.
Here is a simple code i am trying but no success.
My purpose is to take a ADC samples over specific time and process it, here its 700uS.
Last Option i used
Code: |
#include <18F452.h>
#fuses HS,NOWDT,NOPROTECT,NOLVP
#use delay(clock=10000000)
#INT_TIMER1
void TIMER1_isr(void)
{
read_adc(ADC_START_ONLY);
set_timer1(0xF929); //Timer1 overflow at 700uS
}
void main(void)
{
setup_timer_1 ( T1_INTERNAL | T1_DIV_BY_1 );
set_timer1(0xF929); //overflow at 700uS
enable_interrupts(INT_TIMER1);
enable_interrupts(GLOBAL);
setup_adc_ports(AN0);
setup_adc(ADC_CLOCK_DIV_16); //time required to simple=1/a =1.6uS
set_adc_channel(0); // Built-in A/D setup function
delay_us(10); // wait for stabilizing ADC
float value;
int1 done = adc_done();
while(!done) {
done = adc_done();
}
value=read_adc(ADC_READ_ONLY);
printf("\r\n Hex Val%4x" , value);
}
|
First Approach i used was
Code: |
#INT_TIMER1
void TIMER1_isr(void)
{
value = read_adc();
set_timer1(0xF929); //Timer1 overflow at 700uS
}
float value;
void main(void)
{
setup_timer_1 ( T1_INTERNAL | T1_DIV_BY_1 );
set_timer1(0xF929); //overflow at 700uS
enable_interrupts(INT_TIMER1);
enable_interrupts(GLOBAL);
setup_adc_ports(AN0);
setup_adc(ADC_CLOCK_DIV_16); //time required to simple=1/a =1.6uS
set_adc_channel(0); // Built-in A/D setup function
delay_us(10); // wait for stabilizing ADC
printf("\r\n Hex Val%4x" , value);
}
|
|
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19515
|
|
Posted: Sun Nov 10, 2013 12:10 pm |
|
|
What you appear to be programming, differs from what you describe significantly
You talk about taking samples 'over' a particular time. If so, then you would need to store multiple samples:
Code: |
#include <18F452.h>
#device ADC=10 //otherwise ADC is only 8bit
#fuses HS,NOWDT,NOPROTECT,NOLVP
#use delay(clock=10000000)
#BIT T1IF=getenv("BIT:T1IF") //timer1 interrupt
void main(void)
{
int8 index=0,count;
int16 adc_vals[24];
//Stick to standard C, and declare variables at the start of the code
//section. Inline variables are a non standard feature, that often
//can cause problems with CCS...
setup_timer_1 ( T1_INTERNAL | T1_DIV_BY_1 );
setup_adc_ports(AN0);
setup_adc(ADC_CLOCK_DIV_16); //ADC clock
set_adc_channel(0); // Built-in A/D setup function
clear_interrupt(INT_TIMER1)
set_timer1(0xF929); //timer 1 will trigger 700uSec from now
do
{
delay_us(12); //let adc acquire between readings
adc_vals[index++]=read_adc();
}
while (T1IF==0);
//at this point we will have an array of ADC values taken for 700uSec
for (count=0;count<(index-1);count++)
printf("\r\n Val %d %4lx" ,count, adc_vals[count]);
while (TRUE); //ensure code does not drop off end
}
|
Now the ADC takes 12 ADC clock cycles to take a reading. During this time it's input is disconnected from the source. Then it requires 12.86uSec for the capacitor to charge back (worst case). This can be shortened massively on later chips. So each conversion takes (1.6*12)+12 = 31.2uSec. Then writing the data, and looping will take another few uSec, so you will probably get perhaps 18 or 19 readings in 700uSec. Hence I have made the array 24 elements long 'to be sure'.
Values from the ADC are integers, and %x prints integers not floats.
I loop until the timer interrupts saying that '700uSec has passed', but do this by polling the interrupt, rather than using an interrupt handler. No 'enabling' needed.
After reading for 700uSec, it then prints the readings taken.
Best Wishes |
|
|
Shaheers
Joined: 23 Sep 2013 Posts: 14
|
|
Posted: Fri Nov 22, 2013 1:02 am |
|
|
#BIT T1IF=getenv("BIT:T1IF") //timer1 interrupt
excuse me, this command is not working in CCS PCWHD v5.010 |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19515
|
|
Posted: Fri Nov 22, 2013 2:11 am |
|
|
They have changed the name to TMR1IF on the later compilers. So:
#BIT T1IF=getenv("BIT:TMR1IF") //timer1 interrupt
Best Wishes |
|
|
Shaheers
Joined: 23 Sep 2013 Posts: 14
|
|
Posted: Fri Nov 29, 2013 11:56 am |
|
|
how to reset or clear TMR1IF |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19515
|
|
Posted: Fri Nov 29, 2013 12:59 pm |
|
|
clear_interrupt(INT_TIMER1); |
|
|
Shaheers
Joined: 23 Sep 2013 Posts: 14
|
|
Posted: Sat Nov 30, 2013 1:09 am |
|
|
here i got an problem i want to take only one sample in a specific time set by timer interrupt flag,
but i take number of values and display them as well
plz look at code
Code: |
#include <Static_sw.h>
#include "flex_lcd.c" //Mdified lcd file, only contained in project directory
#BIT T1IF=getenv("BIT:TMR1IF") //timer1 interrupt
void main(void)
{
int8 count=0;
int1 flag=0;
float sample;
float min=65000;
float max=0;
setup_adc_ports(AN0_AN1_AN3);
setup_adc(ADC_CLOCK_DIV_16); //10Mhz/16=a ,time required to simple=1/a =1.6uS
//for 12 clock cycles its 19.2uS
set_adc_channel(1); // Built-in A/D setup function
setup_timer_1 ( T1_INTERNAL | T1_DIV_BY_8 );
set_timer1(0xF929); //timer 1 will trigger 700uSec from now
for(;;)
{
while (T1IF==0){
if(flag==0){
sample=read_adc();
sample=sample*0.004887585532746823069403714565; // divide by 1023
if(max<=sample)
{
max=sample;
}
else if(min>=sample)
{
min=sample;
}
flag=1;
}
}
if(flag==1){
lcd_gotoxy(1,2);
printf(lcd_putc, "%2.2fV %2.2fV %2.2fV",sample, max, min);
// lcd_gotoxy(1,2);
flag=0;
}
max=0;
min=0xFFFF;
if(count==10)
{
output_toggle(L1);
count=0;
}
clear_interrupt(INT_TIMER1);
count++;
}
} |
|
|
|
|