Right, so i now have timer running (although i dont think at the right speed cos the seconds are not seconds),
and i am trying to get it so when a push switch is press twice, the lcd displays the time between presses. Naturally i cant quite get it to do exacly that. Can anyone see where i;m going wrong?
// F_CPU tells util/delay.h our clock frequency
// #define F_CPU 1000000UL // Orangutan frequency (1MHz)
#include <avr/io.h>
#include <util/delay.h>
//-----------------------------------------
//All to do with LCD......................
//-----------------------------------------
#define PORTB_MASK 0x38 // PB3, PB4, PB5
#define PORTD_MASK 0x80 // PD7
#define PORTB_SHIFT 3
#define PORTD_SHIFT 1
#define LCD_RW PD3
#define LCD_RS PD2
#define LCD_E PD4
#define LCD_CLEAR 0x01
#define LCD_LINE1 0x02
#define LCD_LINE2 0xC0
#define LCD_SHOW_BLINK 0x0F
#define LCD_SHOW_SOLID 0x0E
#define LCD_HIDE 0x0C
#define LCD_CURSOR_L 0x10
#define LCD_CURSOR_R 0x14
#define LCD_SHIFT_L 0x18
#define LCD_SHIFT_R 0x1C
void lcd_nibble(unsigned char nibble)
{
nibble &= 0x0F;
// Shift our nibble so bits 0, 1, and 2 line up with PB3, PB4,
// and PB5:
nibble <<= PORTB_SHIFT;
// Clear those bits out of PORTB so we can write into them:
PORTB &= ~PORTB_MASK;
// And load PORTB with those three bits:
PORTB |= (nibble & PORTB_MASK);
// Now shift our nibble so bit 3 lines up with PD7:
nibble <<= PORTD_SHIFT;
// Clear that bit out of PORTD so we can write into it:
PORTD &= ~PORTD_MASK;
// And load pORTD with that last bit:
PORTD |= (nibble & PORTD_MASK);
// Delay for 1ms so the LCD can register it's got the nibble:
_delay_ms(1);
PORTD |= (1 << LCD_E);
asm(
"nop" "\n\t"
"nop" "\n\t"
"nop" "\n\t"
"nop" "\n\t"
"nop" "\n\t"
::);
// Bring E low
PORTD &= ~(1 << LCD_E);
asm(
"nop" "\n\t"
"nop" "\n\t"
"nop" "\n\t"
"nop" "\n\t"
"nop" "\n\t"
::);
// Our nibble has now been sent to the LCD.
}
void lcd_send(unsigned char data)
{
unsigned char temp_ddrb, temp_portb,
temp_ddrd, temp_portd;
// Store our port settings
temp_ddrb = DDRB;
temp_portb = PORTB;
temp_ddrd = DDRD;
temp_portd = PORTD;
// Set up port I/O to match what the LCD needs
DDRB |= PORTB_MASK;
DDRD |= PORTD_MASK;
// Send the data
lcd_nibble(data >> 4); // High nibble first
lcd_nibble(data); // Low nibble second
// Restore our port settings
DDRD = temp_ddrd;
PORTD = temp_portd;
DDRB = temp_ddrb;
PORTB = temp_portb;
}
void lcd_cmd(unsigned char cmd)
{
// Hold RW and RS low
PORTD &= !((1 << LCD_RW) | (1 << LCD_RS));
// Send the command
lcd_send(cmd);
// Delay for 1ms to let the command process
_delay_ms(1);
}
void lcd_data(unsigned char data)
{
// Hold RW low
PORTD &= ~(1 << LCD_RW);
// Hold RS high
PORTD |= (1 << LCD_RS);
// Send the data. No waits, so we can go right into sending more
// data.
lcd_send(data);
}
// lcd_string sends a string to the LCD.
void lcd_string(const unsigned char *str)
{
while (*str != 0)
lcd_data(*str++);
}
// lcd_int prints an integer.
void lcd_int(unsigned char n)
{
unsigned char st[4] = {0,0,0,0};
// The 0x30 addition shifts the decimal number up
// to the ASCII location of "0".
// Hundreds place
st[0] = (n / 100) + 0x30;
n = n % 100;
// Tens place
st[1] = (n / 10) + 0x30;
n = n % 10;
// Ones place
st[2] = n + 0x30;
// Print it as a string
lcd_string(st);
}
void lcd_time(unsigned long int n)
{
unsigned char st[8] = {0,0,0,'.',0,0,0,'s'};
// The 0x30 addition shifts the decimal number up
// to the ASCII location of "0".
//100s
st[0] = (n / 100000) + 0x30;
n = n % 100000;
//10s
st[1] = (n / 10000) + 0x30;
n = n % 10000;
// 1s
st[2] = (n / 1000) + 0x30;
n = n % 1000;
// 0.1s
st[4] = (n / 100) + 0x30;
n = n % 100;
// 0.01s
st[5] = (n / 10) + 0x30;
n = n % 10;
// 0.001s
st[6] = n + 0x30;
// Print it as a string
lcd_string(st);
}
// lcd_init initializes the LCD and MUST be called prior to
// every other LCD command.
void lcd_init(void)
{
DDRD |= (1 << LCD_RW) | (1 << LCD_RS) | (1 << LCD_E);
_delay_ms(30);
lcd_cmd(0x30); // 8-bit mode (wake up!)
_delay_ms(5);
lcd_cmd(0x30); // 8-bit mode (wake up!)
_delay_ms(1);
lcd_cmd(0x30); // 8-bit mode (wake up!)
_delay_ms(1);
lcd_cmd(0x32); // 4-bit mode
//telling the lcd everything..
lcd_cmd(0x20);
lcd_cmd(0x28); // 4-bit mode, 2-line, 5x8 dots/char
lcd_cmd(0x08); // Display off, cursor off, blink off
lcd_cmd(0x01); // Clear display
lcd_cmd(0x0F); // Display on, cursor on, blink on
lcd_cmd(0x02); // Return home
lcd_cmd(0x01); // Clear display
// At this point we're good to go.
}
void lcd_moveto(unsigned char line, unsigned char pos)
{
lcd_cmd((line == 1 ? 0x80 : 0xC0) + pos);
}
void lcd_moverel(unsigned char dir, unsigned char num)
{
unsigned char cmd;
cmd = dir ? LCD_CURSOR_R : LCD_CURSOR_L;
while(num-- > 0)
lcd_cmd(cmd);
}
void lcd_shift(unsigned char dir, unsigned char num)
{
unsigned char cmd;
cmd = dir ? LCD_SHIFT_R : LCD_SHIFT_L;
while(num-- > 0)
lcd_cmd(cmd);
}
#define lcd_clear() lcd_cmd(LCD_CLEAR)
// Move the cursor to the beginning of line 1
#define lcd_line1() lcd_cmd(LCD_LINE1)
// Move the cursor to the beginning of line 2
#define lcd_line2() lcd_cmd(LCD_LINE2)
// Show the cursor as a blinking block. (A non-blinking cursor is
// also available.)
#define lcd_show() lcd_cmd(LCD_SHOW_BLINK)
// Hide the cursor.
#define lcd_hide() lcd_cmd(LCD_HIDE)
void delay_sec(unsigned char sec)
{
unsigned int cycles;
for(cycles = 0; cycles < (sec * 100); cycles ++)
{
_delay_ms(10);
}
}
//-----------------------------------------
//All to do with LCD......................
//-----------------------------------------
//STANDARD MAIN FUNCTION
int main( void )
{
//--------------------------------------
//LCD STUFF TO GO IN MAIN FUNCTION
//--------------------------------------
// Make sure all our registers are clear
DDRB = 0;
DDRC = 0;
DDRD = 0;
PORTB = 0;
PORTC = 0;
PORTD = 0;
// Initialize the LCD
lcd_init();
//-----------------------------
//END MAIN FUNCTION LCD STUFF
//------------------------------
DDRC &= ~(1 << PC5);
int timing1, timing2, finaltimer;
int number = 0;
PORTC|=(1<<PC5);
//Timer
DDRD|=(1<<PD1); //Led output
TCCR1B|=(1<<CS10);//Set up timer
for (;;)
{
// Check timer value in if statement, true when count matches 1/20 of a second
if (TCNT1 >= 50000)
{
number=number+50;
PORTD ^= (1 << PD1); // Toggle the LED
if(!(PINC&(1<<PC5)))
{
_delay_ms(50);
timing1 = number;
}
while((PINC&(1<<PC5)))
{
}
{
_delay_ms(50);
timing2 = number;
finaltimer = timing2 - timing1;
lcd_line1();
lcd_string("time");
lcd_line2();
lcd_time(finaltimer);
//End Timer
number = 0;
TCNT1 = 0; // Reset timer value
}
}
}
}