Перейти к содержанию
    

AVR и AT клавиатура

Вот решил прикрутить комповую клаву к контроллеру.

 

Вот весь код (пока только печатает сканкоды на 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 разные коды.

Кто-нибудь может помочь?

 

Спасибо.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Попробуйте контролировать интервалы между скан-кодами, таймауты и т.д.

Тут есть про протокол :

http://www.computer-engineering.org/ps2protocol/

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Кусок из работающего проекта.

 

 

// 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;

}

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Да, спасибо, заработало.

 

Теперь разбираюсь, как слать данные в клаву.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...