C Programm in Ultraschallsenor implementieren
-
Hallo Leute, ich bin echt am verzweifeln weil ich in Programmieren eine absolute niete bin
Ich hoffe ihr könnt mir helfenAufgabe:
Guten Tag,
ich muss mich auf Praktikum vorbereiten und dazu folgende Aufgaben
lösen.
Leider tapp ich zur zeit heftig im dunklen, weil ich eigentlich
überhaupt keine Ahnung habe.Ich hoffe ihr könnt mir helfenDie Aufgabe:Abfragen eines Sensors über I^2C Bus
Die TWI-Schnittstelle des ATmega erlaubt den Zugriff auf I2C-Bus-Geräte.
Deswegen gelten im folgenden Text TWI und I2C als gleichbedeutend.
a) Machen Sie sich mit dem prinzipiellen Ablauf einer I2C-Kommunikation
vertraut (z.B. ATmega Dokumentation).
b) Laden Sie von der ITI-Page das Template-Paket zu dieser Aufgabe
herunter. Machen Sie sich mit dem TWI-Treiber (iti_twi.c, iti_twi.h)
vertraut.
c) Implementieren Sie in der Hauptdatei Uebung2.c die fehlenden
Routinen:
int twi_writeregister(uint8_t twi_addr, uint8_t reg, uint8_t data)
int twi_readregister (uint8_t twi_addr, uint8_t reg, uint8_t* data)
d) Machen Sie sich mit der Möglichkeit vertraut, den SRF02 Sensor über
I2C-Bus anzu-sprechen (siehe SRF02-Datenblatt auf der ITI-Page).
e) Führen Sie in der Hauptschleife des Programms eine Messung mit dem
SRF02 aus und stellen Sie das Ergebnis auf dem Bildschirm dar.
f) Bringen Sie in Erfahrung, an welchen Pins des ATmega16 der SRF02
angeschlossen werden sollte.
g) Testen Sie sie ausgiebig ihre LösungPraktische Anmerkungen zu Aufgabe 1:
Bevor Sie ihre Lösung testen können müssen folgende Einstellun-gen im
AVR-Studio vorgenommen werden: Menu->Project->Configuration
Options->General-> Optimization: -O1 Fuses: Int. Osc. 4MHz. + 64 ms
In der Abbildung rechts ist die Anschlussbox für den Ultraschall-Sensor
und ein Servo dargestellt. Für die Aufgabe 1 sollen alle Anschlüsse bis
auf PWM verbunden werden.Meine Lösungen:
a)
Der Beginn einer Übertragung wird mit dem Start-Signal vom Master
angezeigt, dann folgt die Adresse. Diese wird durch das ACK-Bit vom
entsprechenden Slave bestätigt. Abhängig vom R/W-Bit werden nun Daten
Byte-weise geschrieben (Daten an Slave) oder gelesen (Daten vom Slave).
Das ACK beim Schreiben wird vom Slave gesendet und beim Lesen vom
Master. Das letzte Byte eines Lesezugriffs wird vom Master mit einem NAK
quittiert, um das Ende der Übertragung anzuzeigen. Eine Übertragung wird
durch das Stop-Signal beendet. Oder es wird ein Repeated Start am Beginn
einer erneuten Übertragung gesendet, ohne die vorhergehende Übertragung
mit einem Stop-Signal zu beenden.
Alle Bytes werden dabei „Most Significant Bit First“ übertragen.
Für den High Speed Mode wird zuerst im Fast oder Standard Mode ein
Master Code geschickt, bevor auf die erhöhte Frequenz umgeschaltet wird.
Der I²C-Bus ist von der Definition her recht einfach, aber auch
störanfällig. Diese Tatsache schränkt die Verwendung auf störungsarme
Anwendungsbereiche ein, wo weder mit Übersprechen, Rauschen,
EMV-Problemen, noch mit Kontaktproblemen (Stecker, Buchsen) zu rechnen
ist.b)Diese Dateien hab ich als Anhang hinzufegügt
c)Leider bin ich hier vollkommmen überfordert
Ich bräuchte dringend hilfe von euchd)Auch zu diesem Punkt habe ich leider nichts gefunden
Ich könnt echt verzeifeln bei der c)
ich hab noch nie in c programmiert, nur java bis jetzt und bin da echt überfordert.:(Ich hoffe ihr könnt mir den einstieg erleichtern und helfen
Anhang:
- Uebung2.c
include "iti_twi.h" #include "lcd.h" #include <avr/io.h> // Informiert den Compiler über die CPU-Taktfrequenz: 4 MHz // Nötig für <util/delay.h> #define F_CPU 4000000UL #include <util/delay.h> /* Schreibt ein Byte in ein Register eines TWI-Gerätes. Parameter: uint8_t twi_addr - Addresse des TWI-Gerätes. uint8_t reg - Nr Register des TWI-Gerätes in das geschrieben werden soll. uint8_t data - Byte das geschrieben werden soll. Rückgabe: 1 falls Schreiben erfolgreich, sonst 0. Ablauf: 1. Starte die TWI-Kommunikation. 2. Schreibe die Schreib-Addresse des TWI-Gerätes auf den Bus. 3. Schreibe die Nr. des Registers auf den Bus 4. Schreibe das Byte auf den Bus. 5. Stoppe die TWI-Kommunikation. */ int twi_writeregister(uint8_t twi_addr, uint8_t reg, uint8_t data) { // ... return 1; } /* Liest ein Byte aus einem Register eines TWI-Gerätes. Parameter: uint8_t twi_addr - Addresse des TWI-Gerätes. uint8_t reg - Nr Register des TWI-Gerätes von dem gelesen werden soll. uint8_t* data - Addresse einer Variable, in die das gelesene Byte geschrieben werden soll. Rückgabe: 1 falls Lesen erfolgreich, sonst 0. Insbesondere soll 0 zurückgegeben werden, falls der Pointer data==0. Ablauf: 1. Starte die TWI-Kommunikation. 2. Schreibe die Schreib-Addresse des TWI-Gerätes auf den Bus. 3. Schreibe die Nr des Registers. 4. Stoppe die Kommunikation 5. Starte die TWI-Kommunikation. 6. Schreibe die Lese-Addresse (LSB==1!!!) des TWI-Gerätes auf den Bus. 7. Lese das Byte aus dem Register, setze dabei kein ACK. 5. Stoppe die TWI-Kommunikation. */ int twi_readregister(uint8_t twi_addr, uint8_t reg, uint8_t* data) { // ... return 1; } int main () { int dist = 0; // Entfernung // ... // Initialisiere den TWI-Bus: // ... // Initialisiere den Bildschirm: // ... while (1) { // Sende den Befehl für "Messung in cm Starten" // an den SRF02 Sensor: // ... // Warte bis das Ergebnis bereit steht: _delay_ms (80.0); // Lese das Ergebnis vom SRF02: // ... // Schreibe das Ergebnis auf dem Bildschirm: lcd_write(VT); // erste Zeile, erste Spalte lcd_puti(dist);// schreibe Ergebnis // Füge Wartezeit hinzu, um nicht zu häufig zu lesen } return 0; }
2.lcd.h
#ifndef _lcd_h_ #define _lcd_h_ ////////////////////////////////////////////////////////////////////// ///////////////////// ITI - ATmega-Display ///////////////////////// // Anschluesse: // // Display = ATmega //------------------- // RS = PD1 // R/W = PD4 // E1 = PD0 // // D7:0 = PB7:0 /* Nach einer Initialisierung mit lcd_init(), ist der Bildschirm einsatzbereit. */ ////////////////////////////////////////////////////////////////////// /* Initialisiert den Bildschirm */ void lcd_init(); /* Schreibt ein Zeichen auf den Bildschirm */ void lcd_putc( char ); /* Löscht den Bildschirm */ void lcd_clear( void ); /* Steuerzeichen fuer lcd_write */ #define LF 0x0A //Cursor auf Zeile 2 #define FF 0x0C //Display loeschen, Cursor auf Zeile 1 #define VT 0x0B //Cursor auf Zeile 1 /* Schreibt ein Zeichen auf den Bildschirm. * Erkennt Steuerzeichen. z.B.: * lcd_write(VT); * setzt den Cursor auf Anfang der Zeile 1. */ void lcd_write( char ); /* Schreibt ein int-Wert auf den Bildschirm * Die Gesamtlänge der Zahl darf nicht * länger als 9 Zeichen sein! */ void lcd_puti( int a ); /* Schreibt ein float-Wert auf den Bildschirm * Es werden 2 Nachkommastellen ausgegeben. * Die Gesamtlänge der Zahl (mit '.') * darf nicht länger als 9 Zeichen sein! */ void lcd_putf( float a ); #endif
3.lcd.c
#include <avr/io.h> #include <stdlib.h> #include "lcd.h" //#include <avrx-io.h> //#include <avrx-signal.h> //#include "avrx.h" //#include "hardware.h" #include <stdio.h> //extern TimerControlBlock DisplayTimer; char LCD_CTRL_RS = (1<<1); // Register Select char LCD_CTRL_RW = (1<<4); // Read/Write char LCD_CTRL_E = (1<<0); // Bitmaske für Enable void lcd_ctrl(char c); void lcd_wait(); void lcd_init() { DDRD |= LCD_CTRL_E|LCD_CTRL_RW|LCD_CTRL_RS; // als Ausgabepins konfigurieren (E, RW, RS) PORTD &= ~(LCD_CTRL_E|LCD_CTRL_RW|LCD_CTRL_RS); DDRB = 0xff; // Alle Pins des 8 Bit breiten LCD-Daten-Ports sind Ausgabepins. lcd_wait(); lcd_ctrl(0b00001100); // Display einschalten. lcd_wait(); lcd_ctrl(0b00111000); // Display auf 8-Bit-Ansteuerung und Zweizeilenbetrieb schalten. } // Low-Level-Funktion zum Schreiben eines Datenworts // zum Displaycontroller. void lcd_write( char c ) { if (c == LF) { lcd_wait(); lcd_ctrl(0xc0); } else if (c == FF) { lcd_clear(); } else if (c == VT) { lcd_wait(); lcd_ctrl(0x80); } else { lcd_putc(c); } } void lcd_putc( char c ) { lcd_wait(); char ctrl_port = PORTD; ctrl_port &= ~(LCD_CTRL_RW|LCD_CTRL_E); ctrl_port |= LCD_CTRL_RS; PORTD = ctrl_port; // Ausgeben: RS <- 1, R/W <- 0, E <- 0 ctrl_port |= LCD_CTRL_E; // min. tAS (140 ns) warten PORTD = ctrl_port; // Ausgeben: E <- 1 PORTB = c; // Ausgeben: D0 bis D7 ctrl_port &= ~LCD_CTRL_E; // min. tDSW (195 ns) warten PORTD = ctrl_port; // Ausgeben: E <- 0 // min. max{tAH,tH} (10 ns) warten } // Displayinhalt löschen. void lcd_clear( void ) { lcd_wait(); lcd_ctrl(0b00000001); } // Low-Level-Funktion zum Schreiben eines Kontrollworts // zum Displaycontroller void lcd_ctrl(char c) { char ctrl_port = PORTD; ctrl_port &= ~(LCD_CTRL_RW|LCD_CTRL_RS|LCD_CTRL_E); PORTD = ctrl_port; // Ausgeben: RS <- 0, R/W <- 0, E <- 0 ctrl_port |= LCD_CTRL_E; // min. tAS (140 ns) warten PORTD = ctrl_port; // Ausgeben: E <- 1 PORTB = c; // Ausgeben: D0 bis D7 ctrl_port &= ~LCD_CTRL_E; // min. tDSW (195 ns) warten PORTD = ctrl_port; // Ausgeben: E <- 0 // min. max{tAH,tH} (10 ns) warten } // Warten auf Ende der Verarbeitung im Displaycontroller, // ermitteln der aktuellen Position in dessen Datenspeicher. void lcd_wait() { PORTB = 0; DDRB = 0; char ctrl_port = PORTD; ctrl_port &= ~(LCD_CTRL_RS|LCD_CTRL_E); // RS <- 0, E <- 0 ctrl_port |= LCD_CTRL_RW; // R/W <- 1 PORTD = ctrl_port; // Ausgeben: E <- 0, R/W <- 1 char data_port = 0; do { ctrl_port |= LCD_CTRL_E; // E <- 1, min. tAS (140 ns) warten PORTD = ctrl_port; // Ausgeben: E <- 1 ctrl_port &= ~LCD_CTRL_E; // E <- 0, min. tDDR (320 ns) warten data_port = PINB; // Daten von Displaycontroller lesen PORTD = ctrl_port; // Ausgeben: E <- 0 } while (data_port & 0b10000000); // Busy-Flag = 1?, dann warten. ctrl_port &= ~LCD_CTRL_RW; PORTD = ctrl_port; // Ausgeben: R/W <- 0 DDRB = 0xff; // wieder als Ausgabe. } #define CLEN 10 void lcd_puti( int a ) { int i = 0; char s[CLEN]; s[0] = 0; // Schreibe den ganzzahligen Teil in den Buffer itoa((int)a, s, 10); i = 0; while (s[i] && i < CLEN) { lcd_putc(s[i]); i++; } } void lcd_putf( float a ) { int i = 0; int k = 0; float rest = 0.0; char s[CLEN]; s[0] = 0; // Schreibe den ganzzahligen Teil in den Buffer itoa((int)a, s, 10); // Suche das Ende der ganzzahligen Teils und schreibe ein '.' k = 0; while (s[k]) {k++;} s[k] = '.'; k++; s[k] = 0; // Gebe den Nachkommateil aus: if (a < 0) (a=-a); rest = a-((int)a); itoa( (int)(rest*100), &(s[k]), 10); // Gebe die Zahl aus i = 0; while (s[i] && i < CLEN) { lcd_putc(s[i]); i++; } }
4)iti_twi.h
#ifndef _ITI_TWI_H #define _ITI_TWI_H #include <inttypes.h> //////////////////////////////////////////////////////////// // Init-, Start- und Stop-Routinen: //////////////////////////////////////////////////////////// /* Setzt die Geschwindikeit des Busses abhängig von der CPU-Geschwindigkeit. ==> SLCfreq==50KHz bei 1MHz CPU-Takt */ void twi_init(); /* Leitet einen TWI (I2C) Sende- oder Empfangsvorgang ein. Falls erfolgreich gibt 1 zurück, sonst 0; */ int twi_start(); int twi_rep_start(); /* Beendet einen TWI (I2C) Sende- oder Empfangsvorgang. */ void twi_stop(); //////////////////////////////////////////////////////////// // Senderoutinen: /* Alle Sende-Routinen geben eine 0 zurück, falls Sendevorgang nicht erfolgreich. */ /* Sendet eine slave-Addresse, um anschließend zu schreiben. (8Bit, LSB muss 0 sein) */ int twi_sla_w(uint8_t slave_adress); /* Sendet eine slave-Addresse, um anschließend zu lesen. (8Bit, LSB muss 0 sein) */ int twi_sla_r(uint8_t slave_adress); /* Schreibt ein Byte auf den Bus */ int twi_send(uint8_t data); //////////////////////////////////////////////////////////// // Empfangsroutine: /* Liest ein Byte vom Bus. Parameter: int ack - ACK-Bit uint8_t* data - Unter *data wird das gelesene Byte gespeichert Falls ack!=0 wird der Empfang mit einem ACK-Bit bestätigt (== Erwarte nächstes Byte). Sonst wird das Bit nicht gesetzt (== Transmission beendet). Rückgabewert: Die Methode gibt eine 0 zurück falls ein Fehler auftritt. Sonst eine 1. Ein Fehler tritt auf wenn: - data==0 (null-pointer) - Lesen nicht erfolgreich war. Falls das Lesen nicht erfolgreich war, wird *data auf 0x00 gesetzt. */ int twi_read(int ack, uint8_t* data); #endif
5)iti_twi_c
#include <util/twi.h> //////////////////////////////////////////////////////////// // Interne-Routinen: //////////////////////////////////////////////////////////// /* Gibt 1 zurück, falls TWINT gesetzt wird. Falls nach 40000 Schleifendurchgängen TWINT noch nicht gesetzt wurde, gibt 0 zurück. */ int twi_wait4TWINT() { uint16_t x=0; while (x<40000) { x++; if ( TWCR & (1<<TWINT) ) { return 1; } } return 0; } /* Gibt 0 zurück, falls der Parameter status nicht in den oberen 5 Bytes von TWSR zu finden ist. Sonst, wenn alles in Ordnung ist 1. */ int twi_check( uint8_t status ) { return ((TWSR & 0xF8) == status ); } //////////////////////////////////////////////////////////// // Init-, Start- und Stop-Routinen: //////////////////////////////////////////////////////////// /* Setzt die Geschwindikeit des Busses abhängig von der CPU-Geschwindigkeit. */ void twi_init() { TWBR = 2; TWSR = 0; //==> SLCfreq==50KHz bei 1MHz CPU-Takt } /* Leitet einen TWI (I2C) Sende- oder Empfangsvorgang ein. Falls erfolgreich, gibt 1 zurück sonst 0; */ int twi_start() { // Setze Start-Condition: TWCR = (1<<TWINT)|(1<<TWSTA)|(1<<TWEN); // Warte auf das TWINT-Flag: twi_wait4TWINT(); // Gebe den Status zurück: return twi_check(TW_START); } int twi_rep_start(){ // Setze Start-Condition: TWCR = (1<<TWINT)|(1<<TWSTA)|(1<<TWEN); // Warte: auf das TWINT-Flag: twi_wait4TWINT(); // Gebe den Status zurück: return twi_check(TW_REP_START); } /* Beendet einen TWI (I2C) Sende- oder Empfangsvorgang. */ void twi_stop(){ TWCR = (1<<TWINT)|(1<<TWSTO)|(1<<TWEN); } //////////////////////////////////////////////////////////// // Sende-Routinen: //////////////////////////////////////////////////////////// int twi_sla_w(uint8_t slave_adress){ TWDR = slave_adress; // Slave Adresse in das Data Register schreiben TWCR = (1<<TWINT)|(1<<TWEN); // Adresse senden. // Warten auf das TWINT-Flag twi_wait4TWINT(); return twi_check(TW_MT_SLA_ACK); } int twi_sla_r(uint8_t slave_adress){ TWDR = slave_adress; // Slave Adresse in das Data Register schreiben TWCR = (1<<TWINT)|(1<<TWEN); // Adresse senden. // Warten auf das TWINT-Flag twi_wait4TWINT(); return twi_check(TW_MR_SLA_ACK); } int twi_send(uint8_t data){ TWDR = data; // Datum in das Data Register schreiben TWCR = (1<<TWINT)|(1<<TWEN); // Datum Senden. // Warten auf das TWINT-Flag twi_wait4TWINT(); return twi_check(TW_MT_DATA_ACK); } //////////////////////////////////////////////////////////// // Empfangs-Routine: //////////////////////////////////////////////////////////// /* Liest ein Byte vom Bus. Parameter: int ack - ACK-Bit uint8_t* data - Unter *data wird das gelesene Byte gespeichert Falls ack!=0 wird der Empfang mit einem ACK-Bit bestätigt (== Erwarte nächstes Byte). Sonst wird das Bit nicht gesetzt (== Transmission beendet). Rückgabewert: Die Methode gibt eine 0 zurück falls ein Fehler auftritt. Sonst eine 1. Ein Fehler tritt auf wenn: - data==0 (null-pointer) - Lesen nicht erfolgreich war. Falls das Lesen nicht erfolgreich war, wird *data auf 0x00 gesetzt. */ int twi_read(int ack, uint8_t* data){ // Falls data ein 0-Pointer ist, beende: if (data==0) { return 0; } // Starte den Lesevorgang: if (ack) { // ACK Senden TWCR = (1<<TWINT)|(1<<TWEN)|(1<<TWEA); } else { // NACK Senden TWCR = (1<<TWINT)|(1<<TWEN); } // Warten auf das TWINT-Flag twi_wait4TWINT(); // Überprüfe den Status des Lesevorgangs: int status = 0; if (ack) { status = twi_check(TW_MR_DATA_ACK); } else { status = twi_check(TW_MR_DATA_NACK); } // Falls lesen erfolgreich, übergebe es an die // *data-Variable. Sonst setze *data auf 0: if (status) { // Lese das Datenregister: *data = TWDR; } else { *data = 0; } // gebe den Status zurück: return status; }
Es ist das meiste eigentlich vorgegeben
wahrscheinlich ist es auch nur ein kleiner teil der noch ergänzt werden muss
aber ich leider hierzu keinen ansatz den ich schicken kannviele viele viele leibe grüße und daaaanke für Hilfe
Eine Idee wär vielleich dass ihr mir Hilft bei der c) int twi_writeregister(uint8_t twi_addr, uint8_t reg, uint8_t data) zu programmieren und ich dann int twi_readregister (uint8_t twi_addr, uint8_t reg, uint8_t* data) alleine ProgrammiereWas hält ihr davon ?
butterfliege89
-
erwartest du wirklich, dass wir uns den ganzen I²C Treiber anschauen? Wie viel willst du dafür zahlen?
-
Ich versteh nicht, warum du , wenn du nix produktives beitragen kannst oder willst, dann so n s... posten musst.
Dein Kommentar ist echt nicht angemessen und einer Hilfsgemeinschaft unwürdigEs bringt ja nix wenn ich euch den anhang vorenthalte
-
dir ist schon klar, dass du hier keinen Anspruch auf Hilfe und/oder sinnvolle Antworten hast, oder?
Außerdem, und das können andere bezeugen, bin ich einer, der lange dabei ist und auch viel hilft. Aber manchmal muss man den Leuten sagen, dass das so nicht geht und das tue ich. *Du* willst was von uns, nicht wir etwas von dir. Ich bezweifle, dass jemand sich den ganzen Code anschauen wird und auf mögliche Fehler untersuchen wird.
-
Dieser Thread wurde von Moderator/in rüdiger aus dem Forum ANSI C in das Forum Rund um die Programmierung verschoben.
Im Zweifelsfall bitte auch folgende Hinweise beachten:
C/C++ Forum :: FAQ - Sonstiges :: Wohin mit meiner Frage?Dieses Posting wurde automatisch erzeugt.
-
Ich glaube, du kommst wohl von der Uni Lübeck, wo wir gerade in Eingebettete Systeme das schöne Übungblatt 2 haben. Ich erkenne die Aufgaben 1-zu-1 wieder. Vorlesung besuchen wäre ein Tipp von mir