📄 keyboard side.c
字号:
else
wDAT=1; //write out a 1 to the keyboard to make it odd parity
}
else if (countOut==11)//sending out the stop bit
{
TCNT0=0; //reset timer0 since saw a clock signal
TIFR=TIFR&0xFD; //set bit1=0 to clear the timer0 comp match flag (just in case its set)
wDAT=1; //write the stop bit (when change DDR, this will also activate the pullups)
DDRD=0x00; //make DAT line input, CLK input already. Do this so kybd can send ack bit
}
else if (countOut==12)//getting the ack bit of 0 on DAT
{
TCCR0=0x00; //turn off timer0 since seen last clock
TIMSK=TIMSK&0xFD; //set bit1=0 to turn of timer0 comp match interrupt
TIFR=TIFR&0xFD; //set bit1=0 to clear timer0 comp match flag (just in case its set)
txDone=TRUE;//transmitting done
countOut=0; //reset countOut for next time
parityOut=0;//reset parity for next time
}
}
GIFR=0;
}
//used to make CLK low for at least 100uSec so can send stuff to keyboard
interrupt [TIM1_COMPA] timer1_compA(void)
{
TIMSK=TIMSK&0xEF; //set bit4=0 to turn off interrupt
TCCR1B=0x00; //turn off timer (saves power)
DDRD=0x80; //make CLK an input, keep DAT as output
wCLK=1; //write 1 to B.2 so pullup turn on
wDAT=0; //write 0 to DAT, this is the start bit...kybd will start generating a clock any moment now
}
//if this executes, then it has been at least 200uSec between clk pulses while receiving or transmitting data to keyboard
interrupt [TIM0_COMP] timer0_comp(void)
{
TIMSK=TIMSK&0xFD; //set bit1=0 to turn off timer0 comp match interrupt
TCCR0=0x00; //turn off timer0
TIFR=TIFR&0xFD; //set bit1=0 to clear timer0 comp match flag (just in case its set)
countIn=0; //reset counters
countOut=0;
parityIn=0; //reset parity calculations
parityOut=0;
txDone=TRUE; //there was some error, but pretend you are done
rxDone=TRUE;
receive=TRUE; //put system into receive mode (just a default option)
wDAT=1; //turn on pull ups
wCLK=1;
DDRD=0x00; //set DAT and CLK to input
}
//used to make sure we send something approximately every 25msec
interrupt [TIM2_OVF] timer2_overflow(void)
{
t2visits++;
//after visit this interrupt without reseting 6 times, then about 25msec
//elapsed since last time we sent something
if (t2visits==15)
{
//send some stuff for AGC
queuePut(0xAA);
queuePut(0xAA);
queuePut(0xAA);
queuePut(0xAA);
queuePut(0xAA);
queuePut(0xAA);
queuePut(0xAA);
queuePut(0xAA);
queuePut(0xAA);
queuePut(0xAA);
queuePut(0xAA);
queuePut(0xAA);
queuePut(0xAA);
queuePut(0xAA);
queuePut(0xAA);
queuePut(0xAA);
queuePut(0xFF);
queuePut(0xAA);
t2visits=0;//reset number of visits
}
}
//initialize the mcu
void initialize(void)
{
DDRD=0x00; //make PORTD pin D.3 and D.7 input for CLK and DAT
PORTD=0x88; //write 1 to B.7 and B.3 so pullups on for wCLK and wDAT
MCUCR=0x08; //int1 triggered on falling edge
GICR=0x80; //int1 enable
//Timer0 set up. The rest will be done inside the external interupt
OCR0=50; //Timer0 Outoput compare when 50 (decimal)....1/(16Mhz/64)*50=200uSec.
//Timer2 set up.
TCCR2=0x06; //prescal by 256
TIMSK=(TIMSK&0xBF)|0x40; //set bit6=1 to enable overflow interrupt
//UART
UCSRB=0x08; //enable transmitter only
UCSRC=0xB6; //Asynchronous mode, 8bit words, 1 stop bit ,odd parity
UBRRH = (int)300>>8;
UBRRL = (int)300 & 0xFF ; //need to change this 416 for 2400, 207 for 4800
DDRC=0xff; //for testing, set portc to output
PORTC=0xff; //for testing,set LEDs off
DDRA=0xff; //for testing set porta.0 to output
PORTA=0x00; //for testing,set to 0
receive=TRUE; //put int1 interupt into recieve mode
countIn=0; //no low clock pulses seen yet
countOut=0;
parityIn=0; //calculated parity at 0
parityOut=0;
//set up queue
queueFull=FALSE;//queue is not full
queueEmpty=TRUE;//queue is empty
queueIn=0; //where to insert into queue
queueOut=0; //where to take out of queue
rxDone=FALSE; //haven't finished receiving
txDone=FALSE; //haven't finished transmitting
#asm
sei
#endasm
}
void initializeKyBd(void)
{
//------------------------
dataIn=0;
countIn=0;
RXfromKyBd(); //put into receive mode
while(!rxDone) //wait until get 0xAA (por sucessfull) from kybd (get it only when turn
; //power on and off. Not when you reset microcontroller
//------------------------
TXtoKyBd(0xFF); //put int tranmsit mode, tell kybd to reset itself
while(!txDone) //wait until transmitting done
;
//------------------------
RXfromKyBd(); //put into receive mode
while(!rxDone) //wait until get 0xFA (ack) from kybd that it got the command
;
//------------------------
RXfromKyBd(); //put into receive mode
while(!rxDone) //wait until get 0xAA (reset sucesfull) from kybd
;
//------------------------
TXtoKyBd(0xF4); //put into transmit mode, tell kybd to enable all keys (cmd might not be needed)
while(!txDone) //wait until transmitting done
;
//------------------------
RXfromKyBd(); //put into receive mode
while(!rxDone) //wait until get 0xFA (ack) from kybd that it got the command
;
//------------------------
//kybd will now remain in receive mode unless we change it
}
//set interrupt to be in receive mode
void RXfromKyBd(void)
{
receive=TRUE; //set int2 to receive mode
rxDone=FALSE; //reset
wDAT=1; //pull ups on
wCLK=1; //pull ups on
DDRD=0x00; //set DAT and CLK to input
countIn=0;
}
//sets interrupt to be in transmit mode
void TXtoKyBd(char d)
{
receive=FALSE; //set int2 into transmit mode
txDone=FALSE; //reset
dataOut=d; //the data to transmit
DDRD=0x88; //set DAT and CLK to output
wDAT=1; //keey DAT high
wCLK=0; //pull CLK low to signal that you want to communicate. Int2 will trigger right away
}
void main(void)
{
initialize(); //initialize mcu
initializeKyBd(); //initialize keyboard
while(1)
{
if((!queueEmpty) && (UCSRA&0x20)) //if queue not empty and UART is available
{
t2visits=0; //reset timer2 count value
TCNT2=0; //reset timer2
TIFR=TIFR&0xBF; //set bit6=0 to reset overflow flag (just in case its set)
UDR=queueGet(); //send data out
}
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -