NerdKits - electronics education for a digital generation

You are not logged in. [log in]

NEW: Learning electronics? Ask your questions on the new Electronics Questions & Answers site hosted by CircuitLab.

Support Forum » Realtimeclock1.c program fails to display result on LCD with ATmega328P

August 28, 2011
by vgphotog
vgphotog's Avatar

The interrupt handler sei() seems to disable the LCD display when using the ATmega328P. I have just changed over to the ATmega328P from the ATmega168. I have tested most of the basic programs that came with the nerd kit and they work but the display failed to work in a program that I am writing to test the capacity of rechargeable batteries. After much trouble shooting I have discovered that the failure comes from the code that I am using from the realtimeclock1.c program. So I loaded the into the 328 and it also fails to display a result on the LCD. If I comment out the sei() about six lines from the end of the program the display is active and displays zero. Of course the program will not function as intended with that line commented out. I seems that some way sei() disables the LCD. The display remains completely blank if sei() is not commented out.

What can I do to make this program work with the ATmega328P? "LCD with sei() commented pic"

// realtimeclock1.c
// for NerdKits with ATmega328p
// mrobbins@mit.edu

#define F_CPU 14745600

#include <stdio.h>
#include <stdlib.h>

#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/pgmspace.h>
#include <inttypes.h>

#include "../libnerdkits/delay.h"
#include "../libnerdkits/lcd.h"
#include "../libnerdkits/uart.h"
#include "../libnerdkits/io_328p.h"

// PIN DEFINITIONS:

void realtimeclock_setup() {
  // setup Timer0:
  // CTC (Clear Timer on Compare Match mode)
  // TOP set by OCR0A register
  TCCR0A |= (1<<WGM01);
  // clocked from CLK/1024
  // which is 14745600/1024, or 14400 increments per second
  TCCR0B |= (1<<CS02) | (1<<CS00);
  // set TOP to 143
  // because it counts 0, 1, 2, ... 142, 143, 0, 1, 2 ...
  // so 0 through 143 equals 144 events
  OCR0A = 143;
  // enable interrupt on compare event
  // (14400 / 144 = 100 per second)
  TIMSK0 |= (1<<OCIE0A);
}

// the_time will store the elapsed time
// in hundredths of a second.
// (100 = 1 second)
// 
// note that this will overflow in approximately 248 days!
//
// This variable is marked "volatile" because it is modified
// by an interrupt handler.  Without the "volatile" marking,
// the compiler might just assume that it doesn't change in 
// the flow of any given function (if the compiler doesn't
// see any code in that function modifying it -- sounds 
// reasonable, normally!).
//
// But with "volatile", it will always read it from memory 
// instead of making that assumption.
volatile int32_t the_time;

SIGNAL(SIG_OUTPUT_COMPARE0A) {
  // when Timer0 gets to its Output Compare value,
  // one one-hundredth of a second has elapsed (0.01 seconds).
  the_time++;
}

int main() {
  realtimeclock_setup();

  // init lcd
  lcd_init();
  FILE lcd_stream = FDEV_SETUP_STREAM(lcd_putchar, 0, _FDEV_SETUP_WRITE);
  lcd_home();

  // init serial port
  uart_init();
  FILE uart_stream = FDEV_SETUP_STREAM(uart_putchar, uart_getchar, _FDEV_SETUP_RW);
  stdin = stdout = &uart_stream;

  // turn on interrupt handler
   sei();

  while(1) {
    lcd_home();
    fprintf_P(&lcd_stream, PSTR("%16.2f sec"), (double) the_time / 100.0);
  }

  return 0;
}
August 28, 2011
by missle3944
missle3944's Avatar

Hi vgphotog,

Change line 56

SIGNAL(SIG_OUTPUT_COMPARE0A)

TO:

SIGNAL(TIMER0_COMPA_vect)

I just had that problem about an hour ago ,too.

-Dan

August 28, 2011
by vgphotog
vgphotog's Avatar

Dan thank you very much, that fixed it. Where would I have been able to find this information and possibly other fixes for the 328

August 29, 2011
by SpaceGhost
SpaceGhost's Avatar

Well, Ralph and I had some dialog a while back in which we discovered this same issue: Forum Topic - Nerdy Stopwatch / Kitchen Timer.

Here I posted my modified version of the realtimeclock.c project... Trouble was, the code worked for me but not Ralph.

Noter figured it out for us and offered the same fix that Dan provided you. And yes, part of the issue involved the fact that I was using the '168, and Ralph was using the '328P...

Then Rick posted some additional information to the thread. He suggested that we replace

SIGNAL(SIG_OUTPUT_COMPARE0A)

with

ISR(TIMER0_COMPA_vect)

What we learned from Rick was that "The SIGNAL syntax has been depreciated ( LINK ) and replaced by ISR."

Rick also stated "that is also why the vector name changed. The reason SIGNAL still works is that interrupt.h still handles both but it may not in the future."

Rick referenced this snippet from interrupt.h -

/** \def SIGNAL(vector)
\ingroup avr_interrupts

\code #include <avr/interrupt.h> \endcode

Introduces an interrupt handler function that runs with global interrupts
initially disabled.

This is the same as the ISR macro without optional attributes.
\deprecated Do not use SIGNAL() in new code. Use ISR() instead.

Please check out the "Nerdy Stopwatch / Kitchen Timer" thread for an interesting and more detailed explanation of this topic!

Post a Reply

Please log in to post a reply.

Did you know that first-order systems have a exponentially decaying response to step inputs? Learn more...