Hi, I have this code - i know its pretty long, most of its comments though, but what the situation is, is two jumpers 1 on pc5 the other ground, and the idea is when you touch them, then touch them again, it tells you the time between each touch. but the lcd is displaying the most random of numbers and i cant quite work it out. please can someone see if i’m making a stupid error. thanks
P.S most of the code outside of the main function is to initialise the LCD
// F_CPU tells util/delay.h our clock frequency
#define F_CPU 8000000UL // Orangutan frequency (8MHz)
#include <avr/io.h>
#include <util/delay.h>
uint32_t timebetweenbuttonpresses;
#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))
#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))
//ABOVE HERE = STANDARD
//call delay function
void delayms( uint16_t millis ) {
while ( millis ) {
_delay_ms( 1 );
millis--;
}
}
//--------------------------------
//All to do with ADC
//--------------------------------
void analog_init(void)
{
ADMUX = (1 << REFS0);
ADCSRA = (6 << ADPS0);
ADCSRA |= (1 << ADEN);
}
// Read out the specified analog channel to 10 bits
unsigned int analog10(unsigned char channel)
{
// Clear the channel selection (low 5 bits in ADMUX)
ADMUX &= ~0x1F;
// Select the specified channel
ADMUX |= channel;
ADCSRA |= (1 << ADSC);
while (bit_is_set(ADCSRA, ADSC));
return (ADCL | ADCH << 8); // read ADC (full 10 bits);
}
unsigned int analog8(unsigned char channel)
{
return(analog10(channel) >> 2);
}
//--------------------------------
//All to do with ADC
//--------------------------------
//-----------------------------------------
//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);
}
// 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 * 15); cycles ++)
{
_delay_ms(15);
}
}
//-----------------------------------------
//All to do with LCD......................
//-----------------------------------------
//STANDARD MAIN FUNCTION
int main( void )
{
while(1)
{
//--------------------------------------
//LCD STUFF TO GO IN MAIN FUNCTION
//--------------------------------------
int i;
// 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
//------------------------------
cbi(DDRC, DDC5);
sbi(PORTC, PC5);
if (bit_is_clear(PINC, PINC5))
_delay_ms(50);
while (bit_is_clear(PINC, PINC5))
_delay_ms(10);
while bit_is_set(PINC, PINC5)
{
_delay_ms(1);
timebetweenbuttonpresses++;
}
// A variable to store our converted analog value in:
//int pot;
// Initialize the ADC:
// analog_init();
//SETTING PORT OUTPUTS INPUTS: REMEMBER CANT USE SWITCHES AND LCD...
// DDRB |= (1 << PB0); // set buzzer pin PB0 to output
// DDRC |= (1<< PC5);// led breadboard
// DDRB &= ~(1 << PB3); // make PB3 (button SW3 pin) an input - cant use with LCD
//DDRD |= (1<<PD1); //Led output
//-----------------------------------------
//COMMANDS FOR PRINTING WITH LCD
//-----------------------------------------
//for(;;)
// {
//pot = analog10(6);
// if (pot > 100)
//{
//PORTC |= (1<< PC5);// turn on breadboard (sonar transmitter)
//PORTB |= ( 1 << PB0 ); // buzzer on
//PORTD |= (1 << PD1);//LED ON
//delayms( 90 ); // delay 50 ms
//PORTB &=~ (1 << PB0); //BUZZER Off
//PORTC &= ~(1 << PC5);//turn off bread board (sonar transmitter)
//PORTD &= ~(1 << PD1); // LED OFF
// }
//else
//PORTD &= ~(1 << PD1);
//PORTC |= (1<< PC5);
//delayms( 45 );
//PORTC &= ~(1 << PC5);
// Startup Banner
//}
// delay_sec(2);
lcd_clear();
lcd_line1();
lcd_string("time:");
lcd_line2();
lcd_int(timebetweenbuttonpresses);
delay_sec(2);
}
return 1;
}