Komme leider trotz rumtüfteln und einigen Hilfestellungen von mare_crisium leider immernoch nicht zu meinem gewünschten Ergebniss. Muss ich eigentlich nicht dafür sorgen, das mein SCK Pegel lange gennug auf High bzw. Low steht? Oder muss ich nur beachten, das zwischen den übertragungen mindestens 100us liegen. Im Datenblatt steht, das SCK 250ns jeweils auf High dann auf low stehen soll, aber wie setzte ich das um?, Naja 250ns sind nicht grade lang
Ich denke/hoffe das der Rest eigentlich ganz ok/brauchbar ist.
Code:
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
#define F_CPU 4000000UL
#define ADNS_PORT PORTB
#define ADNS_DDR DDRB
#define ADNS_PIN PINB
#define ADNS_SCK 7 // Pinnumber für SCK vom ATMega32
#define ADNS_MISO 6 // Pinnumber für MISO vom ATMega32 nicht benötigt
#define ADNS_MOSI 5 // Pinnumber für MOSI vom ATMega32
#define ADNS_CONFIG 0x00
#define ADNS_STATUS 0x01
#define ADNS_DY 0x02
#define ADNS_DX 0x03
#define ADNS_SQUAL 0x04
#define ADNS_MAX_PIXEL 0x05
#define ADNS_MIN_PIXEL 0x06
#define ADNS_PIXEL_SUM 0x07
#define ADNS_PIXEL_DATA 0x08
#define START_OF_FRAME 0x80
#define VALID_DATA 0x40
void SCK_High (void);
void SCK_Low (void);
void USART_Init (void) ;
void USART_Transmit (unsigned char data) ;
void ADNS_Init (void) ;
void ADNS_Transmit (unsigned char data1) ;
unsigned char ADNS_Receive(void);
void ADNS_Write (unsigned char adr, unsigned char data) ;
unsigned char ADNS_Read (unsigned char adr) ;
void Delay1ms (unsigned int time) ;
void Delay1us (unsigned int time) ;
void SCK_High (void)
{
ADNS_PORT |= (1<<ADNS_SCK);
}
void SCK_Low (void)
{
ADNS_PORT &=~ (1<<ADNS_SCK);
}
//**************************************************Def's für die UART Verbindung
void USART_Init (void)
{
UBRRL = F_CPU / (16 * 9600UL) - 1;
UCSRB = (1<<RXEN) | (1<<TXEN) ;
UCSRC = (1<<URSEL) | (1<<USBS) | (3<<UCSZ0) ;
}
void USART_Transmit (unsigned char data0)
{
while ( !(UCSRA & (1<<UDRE)) ) ;
UDR = data0 ;
}
//******************************************Def's für die SPI Verbindung zum ADNS
void ADNS_Init (void)
{
ADNS_DDR |= (1<<ADNS_SCK); //Setzt SCK als Ausgang
ADNS_DDR &=~ (1<<ADNS_MOSI); //Setzt MOSI als Eingang
ADNS_PORT |= (1<<ADNS_SCK); //Setzt SCK signal auf High
ADNS_PORT &=~ (1<<ADNS_MOSI); //Setzt Mosi Port nauf 0 also Hi-Z
//SPCR = (1<<SPE) | (1<<MSTR) | (1<<SPR0); //Müssen CPOL und CPHA gesetzt werden?
} //SPI wird ja voll simuliert also INIT nur für erste
//DDR und PORT Einstellung
void ADNS_Transmit (unsigned char data1)
{ //Nach Transmit SCK=High MOSI=Input MOSIPORT=0 ==> HI-Z
unsigned char i,mask;
mask=0b00000001; //Start der Übertragung mit Bit 0<<<
ADNS_DDR |= (1<<ADNS_MOSI); //Stellt sicher das DDR vom MOSI als Output ist
ADNS_PORT &=~ (1<<ADNS_MOSI); //und kein Strom am Ausgang anliegt (low)
for (i=0; i<8; i++)
{
SCK_Low(); //Clock Low
Delay1us(2);
if (data1 & mask) //Wenn Datenbit und Datenstelle (mask) 1 wird
{ //MOSI auf High gesetzt
ADNS_PORT |= (1<<ADNS_MOSI);//Datenstelle startet mit bit0 und läuft bis bit7
}
else
{
ADNS_PORT &=~ (1<<ADNS_MOSI);
}
SCK_High(); //ADNS holt Daten bei Steigender SCK Flanke
Delay1us(2);
mask >>= 1; //Datenstelle wird versschoben 0x01 wird zu 0x02
}
ADNS_DDR &=~ (1<<ADNS_MOSI); //Setzt DDR_MOSI als Input also MOSI->MISO zum Ende
ADNS_PORT &=~ (1<<ADNS_MOSI); //PORT vom Mosi auf 0 ==> Hi-Z
}
unsigned char ADNS_Receive (void)
{ //Nach Receive SCK= High MOSI=Input MOSIPORT=1
unsigned char i,mask,result;
result = 0;
ADNS_DDR &=~ (1<<ADNS_MOSI); //Setzt DDR vom MOSI als INPUT -> MISO Empfang
ADNS_PORT |= (1<<ADNS_MOSI); //Setzt Port auf 1->als Eingang und nicht als Hi-Z
mask = 0b00000001; //Initialisiert die Maske auf Bit0
for (i=0; i<8; i++)
{
SCK_High(); //uC Ließt Daten ein
if (bit_is_set(ADNS_PIN,ADNS_MOSI))//wenn an MOSI(MISO) 5v anliegen schreibt die
{ //schleife an Bitpositionder Maske eine 1 result
result |= mask;
}
SCK_Low(); //ADNS stellt jetzt neue Daten bereit
mask>>=1;
}
Delay1us(1);
SCK_High(); //Setzt Clock zum Ende hin auf High? Ist das ok so?
ADNS_PORT &=~ (1<<ADNS_MOSI); //So ist nach jedem Receive oder Transmit immer gleich
return result; //SCK auf High Mosi auf Input und Hi-Z da MosiPort auf 0
}
void ADNS_Write (unsigned char adr, unsigned char data)
{
ADNS_Transmit(adr | 0b10000000); //SETZT MSB auf 1 und somit R/W auf 1 und Verbindet dies mit der Registeradresse
Delay1us(150); //oder müssen bit8 und bit7 auf 1 also 0b11000000
ADNS_Transmit(data); //Also sollte die Maus jetzt bereit sein ein Datenbyte zu empfangen
Delay1us(150); //Datenbyte wird genauso übermittelt, wie schon vorher das Registeradressbyte
} //nur das jetzt volle 8Bits für DAten zu verfügung stehen und kein R/W und MSB
//Lieber einmal zuviel Pause als einmal zu wenig
unsigned char ADNS_Read (unsigned char adr)
{
char temp;
ADNS_Transmit(adr); //Die Adressen alleine haben immer MSB auf 0, jetzt sollte also der ADNS
Delay1us(150); //die Daten bereitstellen (eigentlich nur 100us aber 150 sind wir auf der sicheren)
temp = ADNS_Receive(); //Im Receive wird jetzt der MOSI Pin als Eingang konfiguriert und mittels wechselndem SCK
Delay1us(150); //von High auf Low (Fallende Flanke) vom uC eingelesen.
return temp;
}
void Delay1ms (unsigned int time)
{
while(time--) _delay_ms(1);
}
void Delay1us (unsigned int time)
{
while(time--) _delay_us(1);
}
int main (void)
{
unsigned char send;
USART_Init ();
Delay1ms(100);
ADNS_Init (); //wird bis auf DDR vom SCK eigentlich nicht benötigt da SPI simuliert wird
Delay1ms(100);
ADNS_Write (ADNS_CONFIG , 0x80);
Delay1ms(500);
ADNS_Write (ADNS_CONFIG , 0x01); //Always AWAKE
Delay1ms(500);
while(1)
{
USART_Transmit ('Y');
send = ADNS_Read (ADNS_DY);
USART_Transmit (send);
USART_Transmit ('X');
send = ADNS_Read (ADNS_DX);
USART_Transmit (send);
}
}
Lesezeichen