amal
17.05.2011, 16:57
hallo, ich habe schon mal unter anderem Thema mein Problem geschrieben, leider habe ich keine richtige Antwort bekommen, deswegen möchte ein neues Thema erstellen, es geht darum: ich habe ein Maussensor mit der Platine von einem Logitech Maus ausgeschlachtet, ich habe die rote LED entfernt und durch ein Laserpointer ersetzt auch die µc von PS2 entfernt, ich habe nur den Sensorchip und die Lense behalten. An dem Sensor habe ich die Pin 3(SDA) und 4(SCK) an Pb0 und Pc0 angeschlossen, und natürlich Pin 6 und 7 an GND und 5V angeschlossen.
und im Code Programm laut mein Datenblatt habe ich die Registern geändert:
0x16 -------> 0x01(Status)
0x17-------->0x03(DeltaX)
0x18-------->0x02(DeltaY)
aber leider ich bekomme kommische Werte, manchmal gar nicht.
und hier ist meine Code:
#include <stdlib.h>
#include <avr/io.h>
#include <util/delay.h>
//#include <USART.h>
#define DDR_SCK DDRC /*!< DDR fuer Maus-SCLK */
#define DDR_SDA DDRB /*!< DDR fuer Maus-SDA */
#define PORT_SCK PORTC /*!< PORT fuer Maus-SCK */
#define PORT_SDA PORTB /*!< PORT fuer Maus-SDA */
#define PIN_SDA PINB /*!< PIN fuer Maus-SDA */
#define SCK_PIN (1<<PC0) /*!< PIN nummer fuer Maus-SCK */
#define SDA_PIN (1<<PB0) /*!< PIN nummer fuer Maus-SDA */
#define FOSC 3686400 // Clock Speed
#define BAUD 9600
#define UBRR_VAL FOSC/16/BAUD-1
// Inizialisierung des Microcontrolers
void uart_init(void)
{
UCSR0B |= (1<<RXEN0)|(1<<TXEN0); // UART RX, TX und RX Interrupt einschalten
UBRR0H = UBRR_VAL >> 8;
UBRR0L = UBRR_VAL & 0xFF;
}
// Eine Funktion zum Senden von Zeichen über Seriellen Port
int uart_putc(unsigned char c)
{
while (!(UCSR0A & (1<<UDRE0))) //warten bis Senden moeglich
{
}
UDR0 = c; // sende Zeichen
return 0;
}
/* puts ist unabhaengig vom Controllertyp */
void uart_puts (char *s)
{
while (*s)
{ /* so lange *s != '\0' also ungleich dem "String-Endezeichen" */
uart_putc(*s);
s++;
}
}
/*!
* Uebertraegt ein Byte an den Sensor
* @param data das Byte
*/
void pan_writeByte(unsigned char data){
signed char i;
DDR_SDA|= SDA_PIN; // SDA auf Output
for (i=7; i>=0; i--){
PORT_SCK &= ~SCK_PIN; //SCK auf Low, Daten vorbereiten
if(data&(1<<i)){ //Bit rausschieben
PORT_SDA|=SDA_PIN;
}else{
PORT_SDA&=~SDA_PIN;
}
PORT_SCK |= SCK_PIN; // SCK =1 Sensor uebernimmt auf steigender Flanke
_delay_us(1); //Sensor Zeit lassen um Bit zu holen
}
DDR_SDA &=~ SDA_PIN; //HI-Z state
PORT_SDA &=~ SDA_PIN;
}
/*!
* Liest ein Byte vom Sensor
* @return das Byte
*/
unsigned char pan_readByte(void)
{
signed char i;
unsigned char data=0;
_delay_us(3); //Sensor Zeit lassen um die Daten aus dem Register zu holen
for (i=7; i>-1; i--){
PORT_SCK &= ~SCK_PIN; // SCK =0 Sensor bereitet Daten auf fallender Flanke vor !
_delay_us(1); //Sensor kurz Zeit lassen
PORT_SCK |= SCK_PIN; // SCK =1 Daten lesen auf steigender Flanke
if(PIN_SDA&SDA_PIN){ //BIT einlesen
data |= (1<<i);
}else{
data &=~ (1<<i);
}
}
return data;
}
/*!
* Uebertraegt ein write-Kommando an den Sensor
* @param adr Adresse
* @param data zu schreibendes byte
*/
void pan_write(unsigned char adr, unsigned char data)
{
adr|=(1<<7);
pan_writeByte(adr); //rl MSB muss 1 sein für Write Operation
pan_writeByte(data);
}
/*!
* Schickt ein Lesekommando an den Sensor
* und liest ein Byte zurueck
* @param adr die Adresse
* @return der registerwert
*/
unsigned char pan_read(unsigned char adr)
{
pan_writeByte(adr);
return pan_readByte();
}
/*!
* Initialisiere A2610
!! Muss unbedingt ganz am ANFANG von main stehen, sonst gibts FEHLER !!
(wenn der A2610 sich initialisiert hat, bevor der Controler SCK und
SDA auf Output gestellt hat)
Deshalb kann es auch sinnvoll sein die Powerup Zeit in den Config Bits
auf 4ms zu stellen oder noch besser mit Boden zu arbeiten.
*/
void pan_init(void)
{
DDR_SCK |= SCK_PIN; // SCK auf Output
DDR_SDA |= SDA_PIN; //SDA auf Output
PORT_SCK |= SCK_PIN; // SCK auf high
PORT_SDA|= SDA_PIN; //SDA auf high
// hier muessen bei Umstellung auf PAN101 die entsprechenden Register gesetzt werden
//Reset A2610
pan_write(0x00,0x80);
// kein Sleep modus
pan_write(0x00,0x01);
}
int main(void)
{
char s[15];
unsigned char ino;
signed char x,y;
signed short posx=0,posy=0;
//ganz an den Anfang damit der Controller schneller asl der PAN ist um Fehler zu vermeiden
pan_init();
//Individuelle Port Configuration und Initialisierung
uart_init(); // USART initialisieren
uart_puts("\r\n\n\n"); // sendet einen kleinen Begrüßungstext.
uart_puts("**** Hallo! Dies ist ein ADNS2610 Test ****\r\n");
uart_puts("\r\n");
uart_puts("Koord: ");
uart_puts("\r\n");
while(1)
{
//Endlosschleife
ino=pan_read(0x01);
//wenn 7tes bit vom Register 0x16 gesetzt ist wurde die Maus bewegt => Bewegungsdaten abfragen
if(ino&(1<<7)){
//Deltax Register auslesen
x=pan_read(0x03);
//und zu der Positionvariable addieren
posx=posx+x;
/* Nachschaun ob das Ueberlauf-Bit im Register 0x16 gesetzt ist
wenn das der Fall ist muss je nach Vorzeichen der Deltax Variable x
noch 128 (Ueberlauf nach oben) dazugezaehlt oder eben 128 abgezogen werden
*/
if(ino&(1<<3))
{
if(x<0)
{
posx-=128;
}else
{
posx+=128;
}
}
//ab hier nochmal das Gleiche fuer die yRichtung
y=pan_read(0x02);
posy=posy+y;
if(ino&(1<<4))
{
if(y<0)
{
posy-=128;
}else
{
posy+=128;
}
}
}
//hier kann jeder seine Ausgabevariante selber waehlen ;)
uart_puts("X= ");
uart_puts( itoa( posx, s, 10 ) );
uart_puts(" ");
uart_puts("Y= ");
//dtostrf(posy,6,3,s);
uart_puts( itoa( posy, s, 10 ) );
uart_puts("\r\n");
}
return 0;
}
und im Code Programm laut mein Datenblatt habe ich die Registern geändert:
0x16 -------> 0x01(Status)
0x17-------->0x03(DeltaX)
0x18-------->0x02(DeltaY)
aber leider ich bekomme kommische Werte, manchmal gar nicht.
und hier ist meine Code:
#include <stdlib.h>
#include <avr/io.h>
#include <util/delay.h>
//#include <USART.h>
#define DDR_SCK DDRC /*!< DDR fuer Maus-SCLK */
#define DDR_SDA DDRB /*!< DDR fuer Maus-SDA */
#define PORT_SCK PORTC /*!< PORT fuer Maus-SCK */
#define PORT_SDA PORTB /*!< PORT fuer Maus-SDA */
#define PIN_SDA PINB /*!< PIN fuer Maus-SDA */
#define SCK_PIN (1<<PC0) /*!< PIN nummer fuer Maus-SCK */
#define SDA_PIN (1<<PB0) /*!< PIN nummer fuer Maus-SDA */
#define FOSC 3686400 // Clock Speed
#define BAUD 9600
#define UBRR_VAL FOSC/16/BAUD-1
// Inizialisierung des Microcontrolers
void uart_init(void)
{
UCSR0B |= (1<<RXEN0)|(1<<TXEN0); // UART RX, TX und RX Interrupt einschalten
UBRR0H = UBRR_VAL >> 8;
UBRR0L = UBRR_VAL & 0xFF;
}
// Eine Funktion zum Senden von Zeichen über Seriellen Port
int uart_putc(unsigned char c)
{
while (!(UCSR0A & (1<<UDRE0))) //warten bis Senden moeglich
{
}
UDR0 = c; // sende Zeichen
return 0;
}
/* puts ist unabhaengig vom Controllertyp */
void uart_puts (char *s)
{
while (*s)
{ /* so lange *s != '\0' also ungleich dem "String-Endezeichen" */
uart_putc(*s);
s++;
}
}
/*!
* Uebertraegt ein Byte an den Sensor
* @param data das Byte
*/
void pan_writeByte(unsigned char data){
signed char i;
DDR_SDA|= SDA_PIN; // SDA auf Output
for (i=7; i>=0; i--){
PORT_SCK &= ~SCK_PIN; //SCK auf Low, Daten vorbereiten
if(data&(1<<i)){ //Bit rausschieben
PORT_SDA|=SDA_PIN;
}else{
PORT_SDA&=~SDA_PIN;
}
PORT_SCK |= SCK_PIN; // SCK =1 Sensor uebernimmt auf steigender Flanke
_delay_us(1); //Sensor Zeit lassen um Bit zu holen
}
DDR_SDA &=~ SDA_PIN; //HI-Z state
PORT_SDA &=~ SDA_PIN;
}
/*!
* Liest ein Byte vom Sensor
* @return das Byte
*/
unsigned char pan_readByte(void)
{
signed char i;
unsigned char data=0;
_delay_us(3); //Sensor Zeit lassen um die Daten aus dem Register zu holen
for (i=7; i>-1; i--){
PORT_SCK &= ~SCK_PIN; // SCK =0 Sensor bereitet Daten auf fallender Flanke vor !
_delay_us(1); //Sensor kurz Zeit lassen
PORT_SCK |= SCK_PIN; // SCK =1 Daten lesen auf steigender Flanke
if(PIN_SDA&SDA_PIN){ //BIT einlesen
data |= (1<<i);
}else{
data &=~ (1<<i);
}
}
return data;
}
/*!
* Uebertraegt ein write-Kommando an den Sensor
* @param adr Adresse
* @param data zu schreibendes byte
*/
void pan_write(unsigned char adr, unsigned char data)
{
adr|=(1<<7);
pan_writeByte(adr); //rl MSB muss 1 sein für Write Operation
pan_writeByte(data);
}
/*!
* Schickt ein Lesekommando an den Sensor
* und liest ein Byte zurueck
* @param adr die Adresse
* @return der registerwert
*/
unsigned char pan_read(unsigned char adr)
{
pan_writeByte(adr);
return pan_readByte();
}
/*!
* Initialisiere A2610
!! Muss unbedingt ganz am ANFANG von main stehen, sonst gibts FEHLER !!
(wenn der A2610 sich initialisiert hat, bevor der Controler SCK und
SDA auf Output gestellt hat)
Deshalb kann es auch sinnvoll sein die Powerup Zeit in den Config Bits
auf 4ms zu stellen oder noch besser mit Boden zu arbeiten.
*/
void pan_init(void)
{
DDR_SCK |= SCK_PIN; // SCK auf Output
DDR_SDA |= SDA_PIN; //SDA auf Output
PORT_SCK |= SCK_PIN; // SCK auf high
PORT_SDA|= SDA_PIN; //SDA auf high
// hier muessen bei Umstellung auf PAN101 die entsprechenden Register gesetzt werden
//Reset A2610
pan_write(0x00,0x80);
// kein Sleep modus
pan_write(0x00,0x01);
}
int main(void)
{
char s[15];
unsigned char ino;
signed char x,y;
signed short posx=0,posy=0;
//ganz an den Anfang damit der Controller schneller asl der PAN ist um Fehler zu vermeiden
pan_init();
//Individuelle Port Configuration und Initialisierung
uart_init(); // USART initialisieren
uart_puts("\r\n\n\n"); // sendet einen kleinen Begrüßungstext.
uart_puts("**** Hallo! Dies ist ein ADNS2610 Test ****\r\n");
uart_puts("\r\n");
uart_puts("Koord: ");
uart_puts("\r\n");
while(1)
{
//Endlosschleife
ino=pan_read(0x01);
//wenn 7tes bit vom Register 0x16 gesetzt ist wurde die Maus bewegt => Bewegungsdaten abfragen
if(ino&(1<<7)){
//Deltax Register auslesen
x=pan_read(0x03);
//und zu der Positionvariable addieren
posx=posx+x;
/* Nachschaun ob das Ueberlauf-Bit im Register 0x16 gesetzt ist
wenn das der Fall ist muss je nach Vorzeichen der Deltax Variable x
noch 128 (Ueberlauf nach oben) dazugezaehlt oder eben 128 abgezogen werden
*/
if(ino&(1<<3))
{
if(x<0)
{
posx-=128;
}else
{
posx+=128;
}
}
//ab hier nochmal das Gleiche fuer die yRichtung
y=pan_read(0x02);
posy=posy+y;
if(ino&(1<<4))
{
if(y<0)
{
posy-=128;
}else
{
posy+=128;
}
}
}
//hier kann jeder seine Ausgabevariante selber waehlen ;)
uart_puts("X= ");
uart_puts( itoa( posx, s, 10 ) );
uart_puts(" ");
uart_puts("Y= ");
//dtostrf(posy,6,3,s);
uart_puts( itoa( posy, s, 10 ) );
uart_puts("\r\n");
}
return 0;
}