#define F_CPU 8000000UL
#define DTOSTR_ALWAYS_SIGN 0x01 // put '+' or ' ' for positives
#define DTOSTR_PLUS_SIGN 0x02 // put '+' rather than ' '
#define DTOSTR_UPPERCASE 0x04 // put 'E' rather 'e'
#define EXIT_SUCCESS 0
#define EXIT_FAILURE 1
#include <avr/io.h> /* Include AVR std. library file */
#include <util/delay.h> /* Include inbuilt defined Delay header file */
#include <avr/interrupt.h>
#define RS PB3 /* Define Register Select (data reg./command reg.) signal pin */
#define EN PB2 /* Define Enable signal pin */
volatile int count =0;
volatile unsigned int mode = 0b00000000;
void lcd_sending_command( unsigned char cmnd )
{
PORTB = (cmnd & 0xF0); /* sending upper nibble */
PORTB &= ~ (1<<RS); /* RS=0, command reg. */
PORTB |= (1<<EN); /* Enable pulse */
_delay_us(1);
PORTB &= ~ (1<<EN);
PORTB = (cmnd << 4); /* sending lower nibble */
PORTB |= (1<<EN);
_delay_us(1);
PORTB &= ~ (1<<EN);
_delay_ms(2);
}
void lcd_sending_data( unsigned char data )
{
PORTB = (data & 0xF0); /* sending upper nibble */
PORTB |= (1<<RS); /* RS=1, data reg. */
PORTB|= (1<<EN);
_delay_us(1);
PORTB &= ~ (1<<EN);
PORTB = (data << 4); /* sending lower nibble */
PORTB |= (1<<RS);
PORTB |= (1<<EN);
_delay_us(1);
PORTB &= ~ (1<<EN);
_delay_ms(2);
}
void lcd_initialization (void) /* LCD Initialize function */
{
DDRB = 0xFF; /* Make LCD command port direction as o/p */
_delay_ms(20); /* LCD Power ON delay always >15ms */
lcd_sending_command(0x33); /* Ensures display is in 8-bit mode */
lcd_sending_command(0x32); /* send for 4 bit initialization of LCD */
lcd_sending_command(0x28); /* Use 2 line and initialize 5*7 matrix in (4-bit mode)*/
lcd_sending_command(0x0f); /* Display on, cursor on and blink cursor*/
lcd_sending_command(0x01); /* Clear display screen*/
lcd_sending_command(0x06); /* Clear display screen*/
lcd_sending_command(0x02); /* Clear display screen*/
_delay_ms(2);
}
void lcd_display_string (char *str) /* Send string to LCD function */
{
int i;
for(i=0;str[i]!=0;i++) /* Send each char of string till the NULL */
{
lcd_sending_data (str[i]);
}
}
void lcd_display_int(int LCD_number)
{
char buffer_LCD[10];
itoa(LCD_number, buffer_LCD, 10);
lcd_display_string(buffer_LCD);
}
void lcd_display_float(float LCD_number)
{
char buffer_LCD[13];
dtostrf(LCD_number, 5, 3, buffer_LCD);
lcd_display_string(buffer_LCD);
}
void int5_init(void)
{
// Make sure you have connected a SW between PD1 (External Interrupt) and GND.
cli(); // Clear all the interrupts
PORTE |= (1 << PE3); // External SW PullUp
DDRE &= ~(1 << PE3); // External Interrupt Sensing Port(PE3) Input Port
EICRB |= (1<<ISC50); // External Interrupt 5, Falling Edge Asynchronously Interrupt
EIMSK |= (1 << INT5);; // External Interrupt 5 enable
sei();
}
void T05Delay(void)
{
TCNT1 = 12500; // TCNT1= for delay of 0.1 seconds
TCCR1B |= (1<<CS11); // Scale down the timer frequency to 8MHz/256
while ((TIFR1 & (1<<TOV1))==0); // wait for TF1 to roll over
TCCR1B = 0; // Stop Timer
TIFR1 |=(1<<ICF1)|(1<<OCF1C)|(1<<OCF1B)|(1<<OCF1A)|(1<<TOV1);
}
int main()
{
int i;
count = 0;
lcd_initialization(); // Initialization of LCD
int5_init(); // Initialization of INT5 Interrupt
lcd_sending_command(0x01); // Clear display
lcd_sending_command(0x80);
lcd_display_string("Press START key");
while(1) {
}
}
ISR (INT5_vect, ISR_NOBLOCK)
{
sei();
int5_init();
mode = ~mode;
lcd_sending_command(0x01); // Clear display
lcd_sending_command(0x80);
lcd_display_string("Timing Started");
if (mode != 0b00000000) count=0;
lcd_sending_command(0x00);
while (mode != 0b00000000) {
T05Delay();
count++;
lcd_sending_command(0xc0);
lcd_display_float((float)count*0.1);
lcd_display_string(" sec");
}
EIMSK |= (1 << INT5); // External Interrupt 0 enable
}