|
|
View previous topic :: View next topic |
Author |
Message |
nfs
Joined: 28 Apr 2004 Posts: 18
|
about timer_1 overflow and loop!!! plz help |
Posted: Tue May 04, 2004 3:33 am |
|
|
i want to sample voltage during 2s so i set up timer_1 to interrupt every 100µs and set up a counter of 20000 which will cover the 2s.
i wrote this code but by simulation i changed voltage to view how can this changes the reponse but unsuccessfully.
this is the code:
Code: |
#include <16F876.h>
/* Set configuration bits in the PIC processor */
#fuses XT, NOPROTECT, NOPUT, NOWDT, NOBROWNOUT, NOLVP, NOCPD, NOWRT
#device adc=10
#device *=16
#use delay (clock=4000000)
#define led1 PIN_A1
#define led2 PIN_A2
#define led3 PIN_A3
#define Vpp 1024
#define Vppmin 973
#define Vss 0
#define Vctq 921
#define tension_maxi_touche_0 34
#define tension_mini_touche_0 0
#define tension_maxi_touche_R 790
#define tension_mini_touche_R 750
#define tension_maxi_touche_plus 523
#define tension_mini_touche_plus 463
#define tension_maxi_touche_moins 287
#define tension_mini_touche_moins 245
#byte INTCON = 0x0b //registre des interruptions
#byte PIE1 = 0x8c //registre contenant les autorisations d'interruptions
#byte PIR1 = 0x0c
#byte ADCON0 = 0x1f //registre du convertisseur
#byte ADCON1 = 0x9f //rôle des pins+justification du resultat de la conversion
#byte ADRESH = 0x1e
#byte ADRESL = 0x9e
#byte port_b = 0x06
#byte port_c = 0x07
#bit GO_DONE = ADCON0.2
#bit ADON = ADCON0.0
#bit ADIE = PIE1.6
#bit ADIF = PIR1.6
#define SET_TRIS_A = 0b00001; // PORTA AN0 entrée et les autres en sortie
#define SET_TRIS_B = 0x00; // PORTB en sortie
#define TMR1IE = PIE1.0
#define TMR1IF = PIR1.0
#bit ADFM_BIT=0x9F.7
#bit PCFG3_BIT=0X9F.3
#bit PCFG2_BIT=0X9F.2
#bit PCFG1_BIT=0X9F.1
#bit PCFG0_BIT=0X9F.0
int16 us;
int16 ADCvaleur;
long int Counter;
void InitialiseADC ()
{
setup_port_a( RA0_ANALOG );
setup_adc( ADC_CLOCK_DIV_8 );
set_adc_channel( 0 );
}
#int_TIMER1
TIMER1_isr()
{
if(Counter++ == 20000)
{Counter = 0;
ADIF = 1;}
}
void main( void )
{
long ADCvaleur;
InitialiseADC();
ADFM_BIT=1;
output_high (led1);
delay_ms(500);
ADCvaleur = 0;
{setup_timer_1(T1_INTERNAL|T1_DIV_BY_8); // at 4MHz clock that is overflow at 20us, so find another crystal?????
enable_interrupts(int_timer1);
enable_interrupts(global);
ADCvaleur = read_ADC();
while(GO_DONE);
if (ADCvaleur<=34)
{
output_low (led1);
output_high(led2);
}
else
{
output_low (led1);
output_high (led3);
}
while(1)
{
;
}
}
} |
_________________ nfs
Last edited by nfs on Tue May 04, 2004 9:20 am; edited 2 times in total |
|
|
Ttelmah Guest
|
Re: about this code?? |
Posted: Tue May 04, 2004 5:05 am |
|
|
nfs wrote: | i want to sample voltage during 2s so i set up timer_1 to interrupt every 100µs and set up a counter of 20000 which will cover the 2s.
i wrote this code but by simulation i changed voltage to view how can this changes the reponse but unsuccessfully.
this is the code:
Code: |
#include <16F876.h>
/* Set configuration bits in the PIC processor */
#fuses XT, NOPROTECT, NOPUT, NOWDT, NOBROWNOUT, NOLVP, NOCPD, NOWRT
#device adc=10
#device *=16
#use delay (clock=4000000)
#define led1 PIN_A1
#define led2 PIN_A2
#define led3 PIN_A3
#define Vpp 1024
#define Vppmin 973
#define Vss 0
#define Vctq 921
#define tension_maxi_touche_0 34
#define tension_mini_touche_0 0
#define tension_maxi_touche_R 790
#define tension_mini_touche_R 750
#define tension_maxi_touche_plus 523
#define tension_mini_touche_plus 463
#define tension_maxi_touche_moins 287
#define tension_mini_touche_moins 245
#byte INTCON = 0x0b //registre des interruptions
#byte PIE1 = 0x8c //registre contenant les autorisations d'interruptions
#byte PIR1 = 0x0c
#byte ADCON0 = 0x1f //registre du convertisseur
#byte ADCON1 = 0x9f //rôle des pins+justification du resultat de la conversion
#byte ADRESH = 0x1e
#byte ADRESL = 0x9e
#byte port_b = 0x06
#byte port_c = 0x07
#bit GO_DONE = ADCON0.2
#bit ADON = ADCON0.0
#bit ADIE = PIE1.6
#bit ADIF = PIR1.6
#define SET_TRIS_A = 0b00001; // PORTA AN0 entrée et les autres en sortie
#define SET_TRIS_B = 0x00; // PORTB en sortie
#define TMR1IE = PIE1.0
#define TMR1IF = PIR1.0
#bit ADFM_BIT=0x9F.7
#bit PCFG3_BIT=0X9F.3
#bit PCFG2_BIT=0X9F.2
#bit PCFG1_BIT=0X9F.1
#bit PCFG0_BIT=0X9F.0
int16 us;
int16 ADCvaleur;
long int Counter;
void InitialiseADC ()
{
setup_port_a( RA0_ANALOG );
setup_adc( ADC_CLOCK_DIV_8 );
set_adc_channel( 0 );
}
#int_TIMER1
TIMER1_isr()
{
if(Counter++ == 20000)
{Counter = 0;
ADIF = 1;}
}
void main( void )
{
long ADCvaleur;
InitialiseADC();
ADFM_BIT=1;
output_high (led1);
delay_ms(500);
ADCvaleur = 0;
{setup_timer_1(T1_INTERNAL|T1_DIV_BY_8); // at 4MHz clock that is overflow at 20us, so find another crystal?????
enable_interrupts(int_timer1);
enable_interrupts(global);
ADCvaleur = read_ADC();
while(GO_DONE);
if (ADCvaleur<=34)
{
output_low (led1);
output_high(led2);
}
else
{
output_low (led1);
output_high (led3);
}
while(1)
{
;
}
}
} |
|
At the moment, your interrupt code, doesn't really do anything...
ADIF, is the 'interrupt flag', set when the AD completes it's operation. Setting this doesn't really do anything.
The 'read_adc' operation, allready waits for the ADC to complete (so GO_DONE is also pointless).
Why not just use a higher divider for timer_1. You do not need your 'interval' to be an exact count. Your calculation for 'overflow' time is wrong. The incoming crystal, is divided by 4 internally, then by 8, then by 256 to give the 'overflow'. This is 2048uSec, not 20. To give 2 seconds, requires you to count to 976 (will give 1.998848 seconds).
So code the timer as:
Code: |
int1 wait=true;
int16 Counter=976;
#int_TIMER1
TIMER1_isr()
{
if(Counter) Counter--;
else wait=false;
}
|
Then in main, simply wait with:
and then read the ADC.
If you want to keep looping multiple times, then code as:
Code: |
while (true) {
counter=976;
wait=true;
while (wait) ;
ADCvaleur=READ_ADC();
if (ADCvaleur<=34)
{
output_low (led1);
output_high(led2);
}
else
{
output_low (led1);
output_high (led3);
}
}
|
If you want the timing to be dead accurate, use the code posted here in the past, of adding a count to the counter, and then testing for it reaching a limit. Define the added value as a binary multiple of the correct 2 second count, and though there will be a slight oscillation of the sample point (equivalent to one interrupt timeout period), the overall accuracy will be as good as your clock. This was I think originally published by Neutone, in some threads dealing with real time clock applications.
Best Wishes |
|
|
nfs
Joined: 28 Apr 2004 Posts: 18
|
re |
Posted: Tue May 04, 2004 8:27 am |
|
|
this does not work. in fact i want that when i change voltage input a new acquisition takes place and i have a new response from led in output.
i've changed the time of acquisition to become 20s but no response. like the program takes only the first value and this is the new program:
Code: |
#include <16F876.h>
/* Set configuration bits in the PIC processor */
#fuses XT, NOPROTECT, NOPUT, NOWDT, NOBROWNOUT, NOLVP, NOCPD, NOWRT
#device adc=10
#device *=16
#use delay (clock=4000000)
#define led1 PIN_A1
#define led2 PIN_A2
#define led3 PIN_A3
#define Vpp 1024
#define Vppmin 973
#define Vss 0
#define Vctq 921
#define tension_maxi_touche_0 34
#define tension_mini_touche_0 0
#define tension_maxi_touche_R 790
#define tension_mini_touche_R 750
#define tension_maxi_touche_plus 523
#define tension_mini_touche_plus 463
#define tension_maxi_touche_moins 287
#define tension_mini_touche_moins 245
#byte INTCON = 0x0b //registre des interruptions
#byte PIE1 = 0x8c //registre contenant les autorisations d'interruptions
#byte PIR1 = 0x0c
#byte ADCON0 = 0x1f //registre du convertisseur
#byte ADCON1 = 0x9f //rôle des pins+justification du resultat de la conversion
#byte ADRESH = 0x1e
#byte ADRESL = 0x9e
#byte port_b = 0x06
#byte port_c = 0x07
#bit GO_DONE = ADCON0.2
#bit ADON = ADCON0.0
#bit ADIE = PIE1.6
#bit ADIF = PIR1.6
#define SET_TRIS_A = 0b00001; // PORTA AN0 entrée et les autres en sortie
#define SET_TRIS_B = 0x00; // PORTB en sortie
#define TMR1IE = PIE1.0
#define TMR1IF = PIR1.0
#bit ADFM_BIT=0x9F.7
#bit PCFG3_BIT=0X9F.3
#bit PCFG2_BIT=0X9F.2
#bit PCFG1_BIT=0X9F.1
#bit PCFG0_BIT=0X9F.0
int16 us;
int16 ADCvaleur;
int1 wait=true;
int16 Counter=9760;
int i;
void InitialiseADC ()
{
setup_port_a( RA0_ANALOG );
setup_adc( ADC_CLOCK_DIV_8 );
set_adc_channel( 0 );
}
#int_TIMER1
TIMER1_isr()
{
if(Counter)
Counter--;
else wait=false;
}
void main( void )
{
long ADCvaleur;
InitialiseADC();
output_high (led1);
delay_ms(1500);
ADCvaleur = 0;
{
setup_timer_1(T1_INTERNAL|T1_DIV_BY_1); // overflow 2048uSec
enable_interrupts(int_timer1);
enable_interrupts(global);
wait=true;
while (!wait) ;
ADCvaleur=read_ADC();
if (ADCvaleur<=34)
{
output_low (led1);
output_high(led2);
}
else
{
output_low (led1);
output_high (led3);
}
while(1)
{
;
}
}
}
|
_________________ nfs |
|
|
Haplo
Joined: 06 Sep 2003 Posts: 659 Location: Sydney, Australia
|
|
Posted: Tue May 04, 2004 5:37 pm |
|
|
Maybe I'm missing something here, but it appears that your code in main() runs only once and then it gets stuck in your while(1) endless loop. That is why you only see one conversion. What you need to do is to put your while(1) around the ADC code, something like this:
Code: |
void main( void )
{
long ADCvaleur;
InitialiseADC();
output_high (led1);
delay_ms(1500);
ADCvaleur = 0;
setup_timer_1(T1_INTERNAL|T1_DIV_BY_1); // overflow 2048uSec
enable_interrupts(int_timer1);
enable_interrupts(global);
while(1) //while needs to be here
{
wait=true;
while (!wait) ;
ADCvaleur=read_ADC();
if (ADCvaleur<=34)
{
output_low (led1);
output_high(led2);
}
else
{
output_low (led1);
output_high (led3);
}
}
}
|
|
|
|
Gerrit
Joined: 15 Sep 2003 Posts: 58
|
|
Posted: Wed May 05, 2004 1:16 am |
|
|
Hello nfs,
I have askt you some questions in private mail, and if I follow this
discusion I see every time new specs. (at this moment you want only
samples when there is a change on adc) keep in mind 10 bit adc
needs a very stable source to no hope between some bcounts.
1 please first define what you want,
2 make a understandable description of you demants
3 make a description of you problem you encountered
4 than post
I'l think the group will be mutch more helpfull in giving good advice.
kind regards,
gerrit |
|
|
|
|
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
|