hd44780 0 3 марта, 2008 Опубликовано 3 марта, 2008 · Жалоба Вот решил прикрутить комповую клаву к контроллеру. Вот весь код (пока только печатает сканкоды на LCD): Компилятор -CvAVR /* Chip type : ATmega32 Clock frequency : 16,000000 MHz */ #include <mega32.h> #include <delay.h> #include <stdio.h> #include "hd44780lib.h" //#include "scancodes.h" #define LED1 PORTD.4 #define LED2 PORTD.5 #define LED3 PORTD.6 //#define LED4 PORTD.7 //#define BUTTON1 PINC.0 //#define BUTTON2 PINC.1 //#define BUTTON3 PINC.2 // Keyboard data #define KBD_DATA PINC.3 // переменные volatile u32 ms = 0; // миллисекунды volatile u08 hour = 0, min = 0, sec = 0; //////////////////////// // Клавиатура #define KEYB_DATA_PIN PINC.3 #define BUFF_SIZE 64 u08 edge, bitcount; // 0 = neg. 1 = pos. u08 kb_buffer[BUFF_SIZE]; u08 *inpt, *outpt; u08 buffcnt; void init_kb ( void ); void decode ( u08 sc ); void put_kbbuff ( u08 c ); u08 kb_getchar ( void ); int isKbBufferEmpty ( void ); //////////////////////// // инициализация CPU void cpuInit ( void ); // External Interrupt 0 service routine // Прерывание клавиатуры () interrupt [EXT_INT0] void ext_int0_isr(void) { // Place your code here static u08 data; // Holds the received scan code if (!edge) // Routine entered at falling edge { if(bitcount < 11 && bitcount > 2) // Bit 3 to 10 is data. Parity bit, { // start and stop bits are ignored. data = (data >> 1); if( KBD_DATA ) data = data | 0x80; // Store a '1' } // if MCUCR = 0x03; // ISC01..00 = 11 - INT0 by rising edge edge = 1; } // if else { // Routine entered at rising edge MCUCR = 0x02; // Set interrupt on falling edge edge = 0; if ( --bitcount == 0 ) { // All bits received decode ( data ); bitcount = 11; } // if } // else } // ext_int0_isr // Timer 0 overflow interrupt service routine interrupt [TIM0_OVF] void timer0_ovf_isr( void) { // Reinitialize Timer 0 value TCNT0 = 0x06; // Place your code here ms ++; if ( ms % 1000 == 0 ) { // прошла секунда sec ++; if ( sec == 59 ) { // прошла минута sec = 0; min ++; if ( min == 59 ) { // прошел час min = 0; hour ++; if ( hour == 23 ) hour = 0; } // if } // if } // if } // timer0_ovf_isr // Timer 2 overflow interrupt service routine interrupt [TIM2_OVF] void timer2_ovf_isr(void) { // Place your code here } // timer2_ovf_isr void main(void) { // Declare your local variables here char *m1 = "Тест AT клавиатуры"; char sBuf [ 25 ]; u08 kbCode; // инициализация CPU cpuInit ( ); // инициализация LCD lcdInit ( ); lcdPutsXY ( 0, 0, m1 ); delay_ms ( 500 ); LED1 = 1; delay_ms ( 250 ); LED1 = 0; delay_ms ( 250 ); LED2 = 1; delay_ms ( 250 ); LED2 = 0; delay_ms ( 250 ); LED3 = 1; delay_ms ( 250 ); LED3 = 0; delay_ms ( 250 ); // LED4 = 1; // delay_ms ( 250 ); // LED4 = 0; // delay_ms ( 250 ); init_kb ( ); // Initialize keyboard reception while ( 1 ) { sprintf ( sBuf, "%02d:%02d:%02d", hour, min, sec ); lcdPutsXY ( 0, 1, sBuf ); if ( isKbBufferEmpty () == 0 ) { // буфер не пуст kbCode = kb_getchar ( ); sprintf ( sBuf, "%d", kbCode ); lcdPutsXY ( 0, 2, sBuf ); } // if } // while } // main // инициализация CPU void cpuInit ( void ) { // Input/Output Ports initialization // Port A initialization // Func7=Out Func6=Out Func5=Out Func4=Out Func3=Out Func2=Out Func1=Out Func0=Out // State7=0 State6=0 State5=0 State4=0 State3=0 State2=0 State1=0 State0=0 PORTA=0x00; DDRA=0xFF; // Port B initialization // Func7=In Func6=In Func5=In Func4=In Func3=Out Func2=Out Func1=Out Func0=In // State7=T State6=T State5=T State4=T State3=0 State2=0 State1=0 State0=T PORTB = 0x00; DDRB = 0x0E; // Port C initialization // Func7=In Func6=In Func5=In Func4=In Func3=In Func2=In Func1=In Func0=In // State7=T State6=T State5=T State4=T State3=P State2=P State1=P State0=P // PC3 - KBD_DATA PORTC = 0x0F; DDRC = 0x00; // Port D initialization // Func7=Out Func6=Out Func5=Out Func4=Out Func3=In Func2=In Func1=In Func0=In // State7=0 State6=0 State5=0 State4=0 State3=P State2=P State1=T State0=T PORTD = 0x0C; DDRD = 0xF0; // Timer/Counter 0 initialization // Clock source: System Clock // Clock value: 250,000 kHz // Mode: Normal top=FFh // OC0 output: Disconnected TCCR0 = 0x03; TCNT0 = 0x06; OCR0 = 0x00; // Timer/Counter 1 initialization // Clock source: System Clock // Clock value: Timer 1 Stopped // Mode: Normal top=FFFFh // OC1A output: Discon. // OC1B output: Discon. // Noise Canceler: Off // Input Capture on Falling Edge // Timer 1 Overflow Interrupt: Off // Input Capture Interrupt: Off // Compare A Match Interrupt: Off // Compare B Match Interrupt: Off TCCR1A=0x00; TCCR1B=0x00; TCNT1H=0x00; TCNT1L=0x00; ICR1H=0x00; ICR1L=0x00; OCR1AH=0x00; OCR1AL=0x00; OCR1BH=0x00; OCR1BL=0x00; // Timer/Counter 2 initialization // Clock source: System Clock // Clock value: 125,000 kHz // Mode: Normal top=FFh // OC2 output: Disconnected ASSR=0x00; TCCR2=0x05; TCNT2=0x00; OCR2=0x00; // External Interrupt(s) initialization // INT0: On // INT0 Mode: Falling Edge // INT1: Off // INT2: Off GICR |= 0x40; // Enable INT0 MCUCR = 0x02; // ICS01..00 = 10 - INT0 by falling edge MCUCSR = 0x00; // GIFR = 0x40; // Reset INT0 flag // Timer(s)/Counter(s) Interrupt(s) initialization TIMSK = 0x41; // Analog Comparator initialization // Analog Comparator: Off // Analog Comparator Input Capture by Timer/Counter 1: Off ACSR = 0x80; SFIOR = 0x00; // Global enable interrupts #asm ( "sei" ); } // cpuInit void init_kb ( void ) { inpt = kb_buffer; // Initialize buffer outpt = kb_buffer; buffcnt = 0; // MCUCR = 2; // INT0 interrupt on falling edge edge = 0; // 0 = falling edge 1 = rising edge bitcount = 11; } // init_kb void decode ( u08 sc ) { put_kbbuff ( sc ); } // decode void put_kbbuff ( u08 c ) { if (buffcnt<BUFF_SIZE) // If buffer not full { *inpt = c; // Put character into buffer inpt++; // Increment pointer buffcnt++; if (inpt >= kb_buffer + BUFF_SIZE) // Pointer wrapping inpt = kb_buffer; } // if } // put_kbbuff u08 kb_getchar ( void ) { u08 kb_byte; while(buffcnt == 0); // Wait for data kb_byte = *outpt; // Get byte outpt++; // Increment pointer if (outpt >= kb_buffer + BUFF_SIZE) // Pointer wrapping outpt = kb_buffer; buffcnt--; // Decrement buffer count return kb_byte; } // kb_getchar int isKbBufferEmpty ( void ) { if ( buffcnt == 0 ) return 1; // буфер пуст return 0; } // isKbBufferEmpty Основа кода - AppNote AVR313. KBD_CLK - INT0, KBD_DATA - PC3. Проблема в том, что печатает на экране белиберду. Даже нажимая одну и ту же клавишу, я вижу на LCD разные коды. Кто-нибудь может помочь? Спасибо. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
vitko 0 3 марта, 2008 Опубликовано 3 марта, 2008 · Жалоба Попробуйте контролировать интервалы между скан-кодами, таймауты и т.д. Тут есть про протокол : http://www.computer-engineering.org/ps2protocol/ Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
GenaSPB 11 3 марта, 2008 Опубликовано 3 марта, 2008 · Жалоба Кусок из работающего проекта. // PD7 - clock to host // PD2 - clock from keyboard // PB2 - data from keyboard // PB1 - data to host // PB0 - MUX control: 1 - pass trough static const uint8_t mask8 [8] = { 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80 }; enum { PS2_STATE_DISABLED, // Ignore all interrupts from keyboard lines PS2_STATE_WAIT, // ready for receieve start bit PS2_STATE_SHIFT, // shift eight bits (bit osition is ps2_shift_count). PS2_STATE_PARITY, PS2_STATE_STOP }; static volatile uint8_t ps2_state; static volatile uint8_t ps2_shift_count; static volatile uint8_t ps2_shift_acc; static volatile uint8_t ps2_ones; // count ones in rcvd. byte and parity. Is non-zero if even parity #define PS2_FIFO_SIZE 32 static volatile uint8_t ps2_fifo [PS2_FIFO_SIZE]; static volatile uint8_t ps2_fifo_put; static volatile uint8_t ps2_fifo_get; // Keyboard subroutinues initialize void ps2_init(void) { ps2_state = PS2_STATE_DISABLED; ps2_fifo_put = ps2_fifo_get = 0; CLR_BIT(DDRD, PD2); // clock from keyboard is input, also INT0 input CLR_BIT(DDRB, PB2); // data from keyboard is input SET_BIT(MCUCR, ISC01); // ext. int. activated by falling edge CLR_BIT(MCUCR, ISC00); GIFR = (1<<INTF0); // clear ext. int. flag SET_BIT(GICR, INT0); // enable ext. int. } void ps2_enable() { cli(); ps2_state = PS2_STATE_WAIT; ps2_fifo_put = ps2_fifo_get = 0; sei(); } void ps2_disable() { cli(); ps2_state = PS2_STATE_DISABLED; ps2_fifo_put = ps2_fifo_get = 0; sei(); } ISR(INT0_vect) { switch (ps2_state) { case PS2_STATE_DISABLED: // Ignore all interrupts from keyboard lines break; case PS2_STATE_WAIT: // ready for receieve start bit if (PINB & (1<<PINB2)) break; ps2_state = PS2_STATE_SHIFT; ps2_shift_count = 0; ps2_shift_acc = 0x00; ps2_ones = 0; break; case PS2_STATE_SHIFT: // shift eight bits (bit osition is ps2_shift_count). if (PINB & (1<<PINB2)) { ps2_shift_acc |= mask8 [ps2_shift_count]; ps2_ones = ! ps2_ones; } if (++ ps2_shift_count >= 8) ps2_state = PS2_STATE_PARITY; break; case PS2_STATE_PARITY: if (PINB & (1<<PINB2)) { ps2_ones = ! ps2_ones; } ps2_state = PS2_STATE_STOP; break; case PS2_STATE_STOP: if (PINB & (1<<PINB2)) { if (ps2_ones != 0) { // place to output budffer uint8_t nextput = ((ps2_fifo_put + 1) == PS2_FIFO_SIZE) ? 0 : (ps2_fifo_put + 1); if (nextput != ps2_fifo_get) { ps2_fifo [ps2_fifo_put] = ps2_shift_acc; ps2_fifo_put = nextput; } } } ps2_state = PS2_STATE_WAIT; break; } } uint8_t ps2_get(void) { uint8_t scancode; cli(); scancode = ps2_fifo [ps2_fifo_get]; if (ps2_fifo_get == ps2_fifo_put) { scancode = 0x00; } else { ps2_fifo_get = ((ps2_fifo_get + 1) == PS2_FIFO_SIZE) ? 0 : (ps2_fifo_get + 1); } sei(); return scancode; } Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
hd44780 0 4 марта, 2008 Опубликовано 4 марта, 2008 · Жалоба Да, спасибо, заработало. Теперь разбираюсь, как слать данные в клаву. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться