Hi,
ich möchte mit meinem I2C Slave einen SRF05 auslesen.
Nur wird die Variable "us_time" nicht hochgezählt. Die Kommunikation mit dem Master funktioniert und wenn ich bei "return" der Funktion "readUS" z.B.
eine "45" direkt zurückgebe, kommt sie auch bei meinem Master an.
Der Sensor an sich funktioniert auch, weil die rote LED bei jedem Aufruf der Funktion leuchtet und ich das Signal mit einem Oszilloskop geprüft habe.
Mit dem jetztigen Code bekomme ich allerdings nur eine "0" zurück.
Code:
#include <avr/io.h>
#include <util/delay.h>
#include <util/twi.h>
#include <avr/interrupt.h>
#define LO_BYTE(a) ((uint8_t) (a & 0xFF))
#define HI_BYTE(a) ((uint8_t) ((a>>8)&0xFF))
//US-Defines
#define US1 US1_PIN
#define US2 US2_PIN
#define US_DDR DDRD
#define US_PORT PORTD
#define US1_PIN PD4
#define US2_PIN PD5
#define TIMER0_AN TIMSK |= (1<<OCIE0); //Timer interrupt aktivieren
#define TIMER0_AUS TIMSK &= ~(1<<OCIE0); //Timer interrupt deaktivieren
#define SLAVE_ADRESSE 0x50 //Die Slave-Adresse
//ACK nach empfangenen Daten senden/ ACK nach gesendeten Daten erwarten
#define TWCR_ACK TWCR = (1<<TWEN)|(1<<TWIE)|(1<<TWINT)|(1<<TWEA);
//NACK nach empfangenen Daten senden/ NACK nach gesendeten Daten erwarten
#define TWCR_NACK TWCR = (1<<TWEN)|(1<<TWIE)|(1<<TWINT);
//switched to the non adressed slave mode...
#define TWCR_RESET TWCR = (1<<TWEN)|(1<<TWIE)|(1<<TWINT)|(1<<TWEA);
//Datenstatuscodes
#define DEFAULT 0 //Normaler status (keine aktion)
#define READ_ENC_A 1 //Schritte vom linken Motor auslesen
#define READ_ENC_B 2 //Schritte vom rechten Motor auslesen
#define RESET_ENC_A 3 //Schritte vom linken Motor löschen
#define RESET_ENC_B 4 //Schritte vom rechten Motor löschen
#define READ_DIST_A 5 //Gefahrene Strecke auslesen (A)
#define READ_DIST_B 6 //Gefahrene Strecke auslesen (B)
#define RESET_DIST_A 7 //Gefahrene Strecke löschen (A)
#define RESET_DIST_B 8 //Gefahrene Strecke löschen (B)
#define READ_US1 9 //Ultraschall 1 Auslesen
#define READ_US2 10 //Ultraschall 2 Auslesen
void init_twi_slave (uint8_t adr);
void initTimer0(void);
uint16_t readUS(uint8_t us);
volatile uint8_t status = DEFAULT; //status was der master will (z.B. US auslesen)
volatile uint16_t us_time=0;
int main (void){
//TWI als Slave mit Adresse slaveadr starten
init_twi_slave(SLAVE_ADRESSE);
initTimer0();
sei();
while(1){
}
}
void init_twi_slave (uint8_t adr){
cli();
TWAR = adr; // Set own TWI slave address.
TWDR = 0xFF; // Default content = SDA released.
TWCR = (1<<TWEN);
sei();
// Start the TWI transceiver to enable reception of the first command from the TWI Master.
TWCR = (1<<TWEN)|(1<<TWIE)|(1<<TWINT)|(1<<TWEA);
}
SIGNAL(SIG_2WIRE_SERIAL){
static uint8_t teil=0; //Welcher teil der Variable übertragen wurde
static uint16_t daten=0; //entählt die daten die zum Master gesendet werden
switch (TW_STATUS){ //TWI-Statusregister prüfen und nötige Aktion bestimmen
case TW_ST_SLA_ACK: //SLA+R, adressiert
//kein ACk/Nack/break -> sonst geht nix
case TW_ST_DATA_ACK: // SLA+R received, ACK returned (Master fordert Daten an)
if(status==READ_US2){ //Ultraschall 2
if(teil==0){
daten = readUS(US2);
TWDR = LO_BYTE(daten); //Ersten 8 Bit übertragen
TWCR_ACK;
teil=1;
}
else{
TWDR = HI_BYTE(daten); //Zweiten 8 Bit übertragen
TWCR_ACK;
teil=0;
status = DEFAULT;
}
}
if(status==READ_US1){ //Ultraschall 1
if(teil==0){
daten = readUS(US1);
TWDR = LO_BYTE(daten); //Ersten 8 Bit übertragen
TWCR_ACK;
teil=1;
}
else{
TWDR = HI_BYTE(daten); //Zweiten 8 Bit übertragen
TWCR_ACK;
teil=0;
status = DEFAULT;
}
}
break;
case TW_SR_SLA_ACK: //SLA+W, adressiert
TWCR_ACK;
case TW_SR_DATA_ACK: //SLA+W received, ACK returned (Master sendet Daten)
status = TWDR; //Geforderte aktion vom master speichern
TWCR_ACK;
break;
default:
//TWCR=0x00;
TWCR_RESET;
break;
}
}
/* Ließt den Ultraschall sensor aus
US1 = Ultreaschall 1 (front)
US2 = Ultraschall 2 (side)
*/
uint16_t readUS(uint8_t us){
US_DDR |= (1<<us); //Pin auf Ausgang
US_PORT |=(1<<us); //Pin high
_delay_us(10); //15µs warten
US_PORT &= ~(1<<us); //Pin low
US_DDR &= ~(1<<us); //Pin auf Eingang
while(!(PIND & (1<<us))){} //Solange der Pin low
us_time = 0;
TIMER0_AN;
while(PIND & (1<<us)){} //Solange der Pin high
TIMER0_AUS;
return us_time/58;
}
/* Timer0 für den US Sensor konfigurieren
Alle 1us einen Interrupt = Freq 1000000 (1000khz)
OCR0 = 16000000/1/1000000=16
16Mhz Quarz, Prescaler 1, Frequenz
*/
void initTimer0(void){
TCCR0 |= (1<<WGM01) | (1<<CS00); //CTC, Prescaler 1
OCR0 = 16;
}
/*Interrupt für den US*/
SIGNAL(SIG_OUTPUT_COMPARE0){
us_time++;
}
Wo ist der Fehler?
MfG Jörn
Lesezeichen