Embedded Programming
 
Forums: » Register « |  User CP |  Games |  Calendar |  Members |  FAQs |  Sitemap |  Support | 
User Name:
Password:
Remember me

The Shed is going Social! Join us on FaceBook and Twitter and chime in on the conversation.

Go Back   Dev Shed ForumsComputer HardwareEmbedded Programming

Reply
Add This Thread To:
  Del.icio.us   Digg   Google   Spurl   Blink   Furl   Simpy   Y! MyWeb 
Thread Tools Search this Thread Rate Thread Display Modes
 
Unread Dev Shed Forums Sponsor:
  #1  
Old January 5th, 2010, 06:14 PM
baby_09 baby_09 is offline
Registered User
Dev Shed Newbie (0 - 499 posts)
 
Join Date: Jan 2010
Posts: 6 baby_09 User rank is Just a Lowly Private (1 - 20 Reputation Level) 
Time spent in forums: 34 m 25 sec
Reputation Power: 0
AVR interrupt C code

Hi,

I am using an ATmega16 microcontroller to read in the data off a temperature sensor. What I am trying to do now is to slow the output down so that it only displays the temperature say every 5 seconds with a timer interrupt. However, when debugging my code, the while loop inside the main function doesn't run even though the argument inside is true. The program counter just goes back to the start of the main function and never runs the code inside the while loop.

My code is below:

Code:
#include <avr/io.h>
#include <stdio.h>
#include <avr/interrupt.h>

volatile int counter = 0;
volatile unsigned char flag = 0x00;
static int uart_putchar(char c, FILE *stream);
static FILE mystdout = FDEV_SETUP_STREAM(uart_putchar, NULL,_FDEV_SETUP_WRITE);
static unsigned int temp;
static double ftemp;
static double adc_v;

void blink_led(void)
{
    PORTB=PORTB^0xff;
}

void timer_init(void)
{
    SREG |= 0x80; // enable global interrupt 

	TCCR0 = 0x05; // divide timer by 1024,  timer
                  

    TIMSK=0x01; // enable timer0 for overflow interrupt mode

    sei();     //  Global Interrupt Enable
}


//**********************************************
//InitADC: initialize analog to digital converter
//**********************************************

void InitADC(void)
{
ADMUX = 0x06;
ADCSRA = 0xCF;

while (!(ADCSRA & 0x10));
ADCSRA |= 0x10; //manually clear interrupt flag

}

//***********************************************
//ReadADC: read analog voltage from ADC converter
//***********************************************
unsigned int ReadADC(unsigned char channel)
{
unsigned int binary_weighted_voltage, binary_weighted_voltage_low;
unsigned int binary_weighted_voltage_high;

ADMUX = channel;
ADCSRA |= 0x4F; //start conversion

while (!(ADCSRA & 0x10));
ADCSRA |= 0x10; //manually clear interrupt flag

binary_weighted_voltage_low = ADCL;
binary_weighted_voltage_high = ((unsigned int) (ADCH << 8));
binary_weighted_voltage = binary_weighted_voltage_low | binary_weighted_voltage_high;
return binary_weighted_voltage;
}

//
//
void USART_init(void)
{
  UCSRA = 0x00;
  UCSRB = 0x08;
  UCSRC = 0x86;

  UBRRH = 0x00;
  UBRRL = 0x33; //9600 for 8MHz

} 

//
//
void USART_tx(unsigned char data)
{
  while((UCSRA & 0x20) == 0x00){};
  UDR = data;
}


int uart_putchar(char c, FILE *stream)
{
  if (c == '\n'){
    uart_putchar('\r', stream);
  }
  loop_until_bit_is_set(UCSRA, UDRE);
  UDR = c;
  return 0;
}

int
main(void)
{
	DDRB=0xff;  // PORTB as output
    PORTB=0x55;

    USART_init();
    stdout = &mystdout;
	InitADC();
	timer_init();

	printf("\nSystem Initialised\n");
	
    for(;;){
	   while(!(flag & 0xff));
	   temp = ReadADC(0x06); //read in the value from the ADC
	   adc_v = (temp*5.0/1024); //adjust for 5 Volts reference voltage and 1024 ADC Levels
	   ftemp = (double) (temp*5.0/1024/10e-3) - 273,15; //convert to degrees Celsius
	   //Print to screen
	   printf ("Temperature = %0.1f\n   Voltage = %0.5f",ftemp,adc_v);
	}

}


ISR(TIMER0_OVF_vect)
{
    /* This interrupt function would be called automatically after every 
10ms once the timer_init function has been called. */

    counter++; /* This variable multiplies with 10ms to generate custom timer. Adjust this as per your need */

   if ( counter == 153 )
    {
        /* Call your function here or put the events which you want to be called after every 1 second */
       blink_led();  // for example blink LEDs on PORTB
	   counter = 0;
	   flag = 0xff;
    }
	
}

Any hints as to what could be causing this?
Thanks in advance.

Reply With Quote
  #2  
Old January 6th, 2010, 08:56 AM
clifford's Avatar
clifford clifford is offline
Contributing User
Dev Shed Demi-God (4500 - 4999 posts)
 
Join Date: Aug 2003
Location: UK
Posts: 4,808 clifford User rank is General 12nd Grade (Above 100000 Reputation Level)clifford User rank is General 12nd Grade (Above 100000 Reputation Level)clifford User rank is General 12nd Grade (Above 100000 Reputation Level)clifford User rank is General 12nd Grade (Above 100000 Reputation Level)clifford User rank is General 12nd Grade (Above 100000 Reputation Level)clifford User rank is General 12nd Grade (Above 100000 Reputation Level)clifford User rank is General 12nd Grade (Above 100000 Reputation Level)clifford User rank is General 12nd Grade (Above 100000 Reputation Level)clifford User rank is General 12nd Grade (Above 100000 Reputation Level)clifford User rank is General 12nd Grade (Above 100000 Reputation Level)clifford User rank is General 12nd Grade (Above 100000 Reputation Level)clifford User rank is General 12nd Grade (Above 100000 Reputation Level)clifford User rank is General 12nd Grade (Above 100000 Reputation Level)clifford User rank is General 12nd Grade (Above 100000 Reputation Level)clifford User rank is General 12nd Grade (Above 100000 Reputation Level)clifford User rank is General 12nd Grade (Above 100000 Reputation Level) 
Time spent in forums: 1 Month 2 Days 17 h 42 m 37 sec
Reputation Power: 1800
Post

I cannot immediately see your problem, but as I suggested before you would do better posting this on the AVR Freaks forum. There are few embedded systems specialists here, let alone AVR specialists.

If you are stepping this with the debugger have you configured the debugger to stop the timer while the processor is halted? If not, every time you halt, a timer interrupt will become pending an the code in main may never run while stepping. Moreover if you break in the ISR, an interrupt will become pending and teh ISR may re-enter, eventually overflowing the call stack, and causing a crash.

The comment for the baud rate suggests you are running at 8MHz; so the Timer 0 overflow will occur at 32.768ms intervals, not 10ms as in the comment - that would explain the value of 153 in your ISR! If you are going to post the code for help, at least keep the comments consistent, since that only adds confusion!

Any how, you are making your timer far less flexible that necessary. I suggest that you make the 1 second event counter internal to the ISR (if you need it at all), and create a separate continuous counter for timing, as follows:

Code:
volatile unsigned char systick = 0 ;

ISR(TIMER0_OVF_vect)
{
    static counter = 0 ;

    tick++ ;

    counter++ ;

    // every second (approx)...
    if ( counter == 31 )
    {
        blink_led() ;
	counter = 0;
    }
}


Then your timing look can look more like:
Code:
for(;;)
{
    unsigned char start = systick ;
    while( systick - start < 153 ) /* do nothing for 5 seconds (approx)*/ ;

    ...
}


Note that I have used an unsigned char for systick so that access is atomic. If you need a larger counter (this one is good for intervals of up to ~8.39 seconds), you will need to disable the interrupt to read systick, or use a mechanism where by you must read the same value twice in succession to validate it, for example:
Code:
unsigned int getSysTick()
{
    int now ;
    do
    {
        now = systick ;
    } while( systick != now ) ;

    return now ;
}
or
Code:
unsigned int getSysTick()
{
    int now ;

    TIMSK=0x00; 
    now = systick ;
    TIMSK=0x01; 

    return now ;
}

Reply With Quote
  #3  
Old January 6th, 2010, 02:27 PM
jwdonahue's Avatar
jwdonahue jwdonahue is offline
Bellevue WA, USA
Dev Shed Loyal (3000 - 3499 posts)
 
Join Date: May 2004
Location: Bellevue Washington, USA
Posts: 3,398 jwdonahue User rank is Lieutenant General (80000 - 90000 Reputation Level)jwdonahue User rank is Lieutenant General (80000 - 90000 Reputation Level)jwdonahue User rank is Lieutenant General (80000 - 90000 Reputation Level)jwdonahue User rank is Lieutenant General (80000 - 90000 Reputation Level)jwdonahue User rank is Lieutenant General (80000 - 90000 Reputation Level)jwdonahue User rank is Lieutenant General (80000 - 90000 Reputation Level)jwdonahue User rank is Lieutenant General (80000 - 90000 Reputation Level)jwdonahue User rank is Lieutenant General (80000 - 90000 Reputation Level)jwdonahue User rank is Lieutenant General (80000 - 90000 Reputation Level)jwdonahue User rank is Lieutenant General (80000 - 90000 Reputation Level)jwdonahue User rank is Lieutenant General (80000 - 90000 Reputation Level)jwdonahue User rank is Lieutenant General (80000 - 90000 Reputation Level)jwdonahue User rank is Lieutenant General (80000 - 90000 Reputation Level)jwdonahue User rank is Lieutenant General (80000 - 90000 Reputation Level)jwdonahue User rank is Lieutenant General (80000 - 90000 Reputation Level) 
Time spent in forums: 3 Weeks 5 Days 6 h 48 m 17 sec
Reputation Power: 886
We do have an embedded systems forum.
__________________
My worst nightmare was a pointless infinite loop.
Work in progress; don't poke the curmudgeon!
http://www.odonahue.com/

Reply With Quote
Reply

Viewing: Dev Shed ForumsComputer HardwareEmbedded Programming > AVR interrupt C code

Developer Shed Advertisers and Affiliates



Thread Tools  Search this Thread 
Search this Thread:

Advanced Search
Display Modes  Rate This Thread 
Rate This Thread:


Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

vB code is On
Smilies are On
[IMG] code is On
HTML code is Off
View Your Warnings | New Posts | Latest News | Latest Threads | Shoutbox
Forum Jump

Forums: » Register « |  User CP |  Games |  Calendar |  Members |  FAQs |  Sitemap |  Support | 
  
 


Powered by: vBulletin Version 3.0.5
Copyright ©2000 - 2013, Jelsoft Enterprises Ltd.

© 2003-2013 by Developer Shed. All rights reserved. DS Cluster - Follow our Sitemap