![]() |
![]() |
![]() |
|
|
|||||||
| Micro Controllers Discuss all aspects of micro controllers - building them, coding them, etc. All controllers are welcome - PIC, BASIC, Z8 Encore!, etc. |
|
|
Thread Tools | Display Modes |
|
|
(permalink) |
|
Hi guys, firstly, great forum. I can't find a more active microcontroller forum on Google!
I've been toying around with the 16F877 and I've had some problems, pertaining to Timer0 interrupt and ADC. The problem: Enabling timer0 interrupt, affects my ADC values. Specifically when timer0 interrupt is disabled, my ADC values range properly from 0 -> 1024. But with timer0 interrupt enabled, ADC values range from 512 -> 1024. Weird problem! Do allow me to share the code: Code:
void timer0_enable (void) {
/* Initialise Timer 0 */
OPTION = 0b11010111; /* Set TMR0 to Internal CLk, 1:256 */
T0IF = 0; /* Clear TMR0 Flag, ready for use */
T0IE = 1; /* Enable Timer Overflow Interrupt */
}
void initialize_IO_ports (void) {
//set the digital IO ports as per requirement
TRISA = 0xFF ; //portA as input
TRISB = 0B10000000 ; //portB as input
TRISC = 0B11110000; //portC as output
TRISD = 0B10000000; //portD as output
ADCON1 = 0x82; //set PortE as digital io and portA as analog, and VDD and VSS; ADC output is right-justified.
//clear the output ports at the beginning
//PORTD = 0x00 ; //clear portD
// PORTC = 0x00 ; //clear portC
GIE=1; //global interrupt enabled
PEIE=1; //peripheral interrupt enabled
}
void initialize_ADC (void) {
ADON=1; //enable the ADC
ADCS1=0; //set clock source for the ADC
ADCS0=0;
}
int read_ADC_channel (unsigned int channel_number) {
int value;
switch (channel_number) {
case 0:
CHS2=0;
CHS1=0;
CHS0=0;
case 1:
CHS2=0;
CHS1=0;
CHS0=1;
case 2:
CHS2=0;
CHS1=1;
CHS0=0;
case 3:
CHS2=0;
CHS1=1;
CHS0=1;
default:;
}
ADGO=1; //start AD conversion
while(ADGO) {}; //wait for conversion to finish
value=(ADRESH<<8)+ADRESL; //read the values in the registers
return value;
}
void interrupt isr0 (void) {
// for timer0
if (T0IF == 1) {
luggage_present = luggage_ispresent();
T0IF = 0; // timer0 reload
}
}
void main() {
int myInt;
timer0_enable();
initialize_IO_ports();
lcd_init();
initialize_ADC();
// below is just a debugging tool to print ADC values
I'm thinking it's some problem with the way OPTION_REG is reacting with my ADC clock or something, but I've totally no idea after 2 days spent meddling and Googling. It's seriously killing me! Any help is appreciated guys! Thanks! |
|
|
|
|
|
|
(permalink) | |
|
Quote:
|
||
|
|
|
|
|
(permalink) |
|
What if TMR2 is taking care something else?
I'm curious as to the cause of this problem as I am currently using TMR0, TMR2 and ADC in one of my projects... and would like to know the cause and solution if I end up running into this. "Use something else" is the easy way, but it doesn't fix anything. It's kinda like saying "My car won't shift into second" and the solution being "don't worry about it... shift from first to third". |
|
|
|
|
|
|
(permalink) | ||
|
Quote:
Why do you need both TMR0 and TMR2 for your project? Quote:
Or go for a PIC with TMR3... |
|||
|
|
|
|
|
(permalink) |
|
Actually, in my case, I'm using TMR0 for a delay in my piezo control -- however, it is DISABLED... I'm just polling the overflow bit as I don't need an actual interrupt. This routine was one that I grabbed from piclist, so it could be rewritten to not use TMR0, I just haven't done so.
TMR2, in my case, controls the refresh rate of a 4 digit, 7 segment LED -- and it is interrupt driven. So, yes, in my case I could probably re-write it and move to TMR2 -- but I still don't agree with the process in general -- I like to FIX things, not forget about them. Now, back to the topic at hand... I'm scouring the datasheet trying to see if I see something that you (sebana) may have missed. One thing I did notice right away (but I'm not a C guy!) was that bit 3 of the OPTION_REG does not seem to be set (according to the datasheet, it is set to 1 by default (which sets the prescaler to the WDT and not TMR0). Just a thought! |
|
|
|
|
|
|
(permalink) | |
|
Quote:
|
||
|
|
|
|
|
(permalink) | |
|
Quote:
However, in this case I doubt that is the problem?, perhaps more down to what code the compiler is producing?. |
||
|
|
|
|
|
(permalink) | |
|
Quote:
kyle, ive tried tuning the prescaler to WDT, but it didn't work too.. i'm really not understanding this prescaler thing well (and if setting it on TMR0 affects the ADC F-osc..) These frequency thing may well be the thing killing the whole thing! eng1: i'd be using TMR1 initially, but that goes on to set up one of the pins on the 16877, which another of my module is already using.. Of course I'd like to move over to TMR2 if possible, but considering I've been brooding over these for 2 days, it'll be great to know what's wrong exactly.. It's a simple enough code (for sure) but the problems it brings up is weird! thanks for the help everyone, i'd keep trying whatever you all suggest! Last edited by sebana; 11th September 2007 at 03:31 PM. |
||
|
|
|
|
|
(permalink) |
|
Can you show how you're using the function read_ADC_channel?
|
|
|
|
|
|
|
(permalink) | |
|
Quote:
Now that's the kind of stuff I like to read! You give a reason / explanation and a solution -- that I understand! Rep points to you... (Nigel, your comments are appreciated as well!) To answer your question -- yes, I have thought about getting the piezo off of TMR0 -- the way the author set it up was to allow for "musical notes" to be generated with varying length and frequency. I don't really need all that as I use a "beep", "beep-beep" and a long "beeeeeeeep" all of the same frequency (just duration changes) -- I'm pretty sure I can do it without a TMR at all, but my standard Delay routine. @sebana -> just another thought (maybe grasping |
||
|
|
|
|
|
(permalink) | |
|
Quote:
Why is ADRESH being shifted 8 times as opposed to 6 times? |
||
|
|
|
|
|
(permalink) | |
|
Quote:
For example: ADRESH = b'00000010' ADRESL = b'11110000' result = 0 result = ADRESH = b'0000000000000010' result = result << 8 = b'0000001000000000' result += ADRESL = b'0000001011110000' |
||
|
|
|
|
|
(permalink) |
|
Is it possible the TMR0 is triggered in the middle of this shifting? Try setting a START_OF_SHIFT flag before shifting and clearning it after shifting, then when the interrupt occurs, check if this flag is set or cleared.
Also disable TMR0IE during critical computations, then set it back up and see what happens. |
|
|
|
|
|
|
(permalink) | ||
|
Quote:
Quote:
|
|||
|
|
|
| Bookmarks |
| Thread Tools | |
| Display Modes | |
|
|
|
|
||||
| Thread | Thread Starter | Forum | Replies | Latest |
| How to stop interrupt inthe the timer0 interrupt 1 | prevravanth | Micro Controllers | 9 | 5th April 2007 05:58 AM |
| Timer0 Prescale | lord loh. | Micro Controllers | 7 | 16th May 2006 07:39 AM |
| Cant get timer0 to interrupt | 2camjohn | Micro Controllers | 5 | 16th June 2004 12:05 PM |
| External Interrupt not working - 16F877 | usaf1 | Micro Controllers | 0 | 15th September 2003 12:17 AM |