PS2ジョイスティックをマイクロコントローラーSPIを備えたavr Atmega 640とインターフェースしようとしています。インターネットで利用可能なビットバンには多くのコードがありますが、AVRでPS2とSPIをインターフェースしたいです。ボタンが押されると、対応する LED がオフではなく点滅を開始します。
#include<avr/io.h>
#include<avr/interrupt.h>
#include<util/delay.h>
#define MISO 3 //data
#define MOSI 2 //cmnd
#define SCK 1 //clock
#define SS 0 //attention
//--------------------------------** SPI **-------------------------------------------------------------------------
void SPI_int_MSTR()
{
SPCR=(1<<SPE)|(1<<DORD)|(1<<MSTR)|(1<<CPOL)|(1<<CPHA)|(1<<SPR1)|(1<<SPR0); //interupt enable,spi enable,LSB first,master ,Fosc/128=115200hz
//SPSR=(1<<SPI2X); // not working at Fosc/64
DDRB=(1<<MOSI)|(1<<SCK)|(1<<SS); // mosi,sck,ant-output
DDRB&=~(1<<MISO);
//PORTB|=(1<<MISO); //ENABLE internal pull-up
PORTB|=(1<<SS);
}
unsigned char sendTo_slave(unsigned char cmd)
{
unsigned char data;
SPDR=cmd;
while(!(SPSR & (1<<SPIF)));
_delay_us(170); // 170-best
data=SPDR;
//_delay_us(40);
return(data);
}
//---------------------------** PS2 CONTROLLER **------------------------------------------------------------------------
void int_inanalogue()
{
// this loop continues to put PSx controller into analouge mode untill the
// controller responds with 0x73 in the 2nd byte.
// (PS2 controller responds with 0x73 when in analouge mode.)
// the status LEDs will continue to count upwards untill a controller is found.
// if everything is working correctly this should happen on the first pass of
// this loop but occasionally errors occur and a 2nd or 3rd itteration happen.
//lcd_string("0");
unsigned char chk_ana = 0,cnt = 0;;
while(chk_ana != 0x73)
{
//put controller in config mode-43
PORTB&=~(1<<SS);
sendTo_slave(0x01);
sendTo_slave(0x43);
sendTo_slave(0x00);
sendTo_slave(0x01); //enter confi
sendTo_slave(0x00);
_delay_us(1);
PORTB|=(1<<SS);
_delay_us(10);
// put controller in analouge mode-44
PORTB&=~(1<<SS);
sendTo_slave(0x01);
sendTo_slave(0x44); // for seting mode
sendTo_slave(0x00);
sendTo_slave(0x01); // for anlogue mode-0x01 ,digital=0x00
sendTo_slave(0x03); // lock the controller ,otherwise the user can change from analog to digital mode using the analog button on the controller.
sendTo_slave(0x00);
sendTo_slave(0x00);
sendTo_slave(0x00);
sendTo_slave(0x00);
_delay_us(1);
PORTB|=(1<<SS);
_delay_us(10);
// 0x4F Config controller to return all pressure values
/* PORTB&=~(1<<SS);
sendTo_slave(0x01);
sendTo_slave(0x4F);
sendTo_slave(0x00);
sendTo_slave(0xFF); //exit confi
sendTo_slave(0xFF);
sendTo_slave(0x03);
sendTo_slave(0x00);
sendTo_slave(0x00);
sendTo_slave(0x00);
PORTB|=(1<<SS);
_delay_us(20); */
// exit config mode-4
PORTB&=~(1<<SS);
sendTo_slave(0x01);
sendTo_slave(0x43);
sendTo_slave(0x00);
sendTo_slave(0x00); //exit confi
sendTo_slave(0x5A);
sendTo_slave(0x5A);
sendTo_slave(0x5A);
sendTo_slave(0x5A);
sendTo_slave(0x5A);
_delay_us(1);
PORTB|=(1<<SS);
_delay_us(10);
// poll controller and check in analouge mode
PORTB&=~(1<<SS);
sendTo_slave(0x01);
chk_ana=sendTo_slave(0x42); // the 2nd byte to be returned from the controller should = 0x73 for "red" analouge controller.
sendTo_slave(0x00);
sendTo_slave(0x00);
sendTo_slave(0x00);
sendTo_slave(0x00);
sendTo_slave(0x00);
sendTo_slave(0x00);
_delay_us(1);
PORTB|=(1<<SS);
_delay_us(10);
PORTC=cnt++;
if (cnt > 254){ cnt=0;}
}
}
//-----------------------------------------For Analogue-------------------------------------------------------------------
int main (void)
{
SPI_int_MSTR();
sei();
DDRC=0XFF;
int_inanalogue();
unsigned char data0, data1, data2, data3, data4, data5,temp;
while(1)
{
PORTB&=~(1<<SS);
sendTo_slave(0x01); // byte 0. header.
temp = sendTo_slave(0x42); // byte 1. header. (should possibly put test on this byte to detect unplugging of controller.)
sendTo_slave(0x00); // byte 2. header.
data0 = sendTo_slave(0x00); // byte 3. first data bite.
data1 = sendTo_slave(0x00); // byte 4.
data2 = sendTo_slave(0x00); // byte 5.
data3 = sendTo_slave(0x00); // byte 6.
data4 = sendTo_slave(0x00); // byte 7.
data5 = sendTo_slave(0x00); // byte 8.
PORTB|=(1<<SS);
PORTC=data1;
}
}
友達あなたの助けは非常に高く評価されます