Hier mal meine LCD Routine. Wie gesagt, LCD_D6 und 7 sins als Pin PC6
und PC7 definiert. Wenn ich ein cli() und sei() in die LCD_data routine
einsetze, dann resetet mein µC beim druecken der Taste.
P.S. Die delay Zeiten musste ich aendern, sodass die Anzeige was
anzeigt.
#define LCD_D4 SBIT( PORTC, 7 )
#define LCD_DDR_D4 SBIT( DDRC, 7 )
#define LCD_D5 SBIT( PORTC, 6 )
#define LCD_DDR_D5 SBIT( DDRC, 6 )
#define LCD_D6 SBIT( PORTD, 2 )
#define LCD_DDR_D6 SBIT( DDRD, 2 )
#define LCD_D7 SBIT( PORTD, 3 )
#define LCD_DDR_D7 SBIT( DDRD, 3 )
#define LCD_RS SBIT( PORTD, 4 )
#define LCD_DDR_RS SBIT( DDRD, 4 )
#define LCD_E0 SBIT( PORTD, 5 )
#define LCD_DDR_E0 SBIT( DDRD, 5 )
void lcd_data( u8 d )
{
LCD_RS = 1;
lcd_byte( d );
}
void lcd_nibble( u8 d )
{
LCD_D4 = 0; if( d & 1<<4 ) LCD_D4 = 1;
LCD_D5 = 0; if( d & 1<<5 ) LCD_D5 = 1;
LCD_D6 = 0; if( d & 1<<6 ) LCD_D6 = 1;
LCD_D7 = 0; if( d & 1<<7 ) LCD_D7 = 1;
LCD_E0 = 1;
_delay_us( 4 );//1 // 1us
LCD_E0 = 0;
}
void lcd_byte( u8 d )
{
lcd_nibble( d );
lcd_nibble( d<<4 );
_delay_us( 45 );//45
// 45us
}
void lcd_command( u8 d )
{
LCD_RS = 0;
lcd_byte( d );
switch( d ){
case 1:
case 2:
case 3: _delay_ms( 4 );//2 // wait 2ms
}
}
void lcd_init( void )
{
LCD_DDR_D4 = 1;
LCD_DDR_D5 = 1;
LCD_DDR_D6 = 1;
LCD_DDR_D7 = 1;
LCD_DDR_RS = 1;
LCD_DDR_E0 = 1;
LCD_E0 = 0;
LCD_RS = 0; // send commands
_delay_ms( 40 );//15 // wait 15ms
lcd_nibble( 0x30 );
_delay_ms( 13 ); //5 // wait >4.1ms
lcd_nibble( 0x30 );
_delay_us( 400 ); //100 // wait >100æs
lcd_nibble( 0x30 ); // 8 bit mode
_delay_us( 400 ); //100 // wait >100æs
lcd_nibble( 0x20 ); // 4 bit mode
_delay_us( 400 );//100 // wait >100æs
lcd_command( 0x28 ); // 2 lines 5*7
lcd_command( 0x08 ); // display off
lcd_command( 0x01 ); // display clear
lcd_command( 0x06 ); // cursor increment
lcd_command( 0x0C );
// on, no cursor, no blink
}
// setzt den Cursor in Zeile y (1..4) Spalte x (0..15)
void set_cursor(uint8_t column, uint8_t line)
{
if( line & 1 )
column += 0x40;
lcd_command( 0x80 + column );
}
// Schreibt einen String auf das LCD
void lcd_string(char *data)
{
while(*data) {
lcd_data(*data);
data++;
}
}
Deine Routine wird im Compare Interrupt mit dieser Funktion abgefragt.
void exe_keypad(void)
{
static unsigned char ct0, ct1, rpt;
unsigned char i;
//TCNT0 = (u8)(s16)-(XTAL / 1024 * 10e-3 + 0.5); // preload for 10ms
i = key_state ^ ~KEY_PIN; // key changed ?
ct0 = ~( ct0 & i ); // reset or count ct0
ct1 = ct0 ^ (ct1 & i); // reset or count ct1
i &= ct0 & ct1; // count until roll over ?
key_state ^= i; // then toggle debounced state
key_press |= key_state & i; // 0->1: key press detect
if( (key_state & REPEAT_MASK) == 0 ) // check repeat function
rpt = REPEAT_START; // start delay
if( --rpt == 0 ){
rpt = REPEAT_NEXT; // repeat delay
key_rpt |= key_state & REPEAT_MASK;
}
}