Forum: Mikrocontroller und Digitale Elektronik wie Daten an MSP430F1611 seriell einlesen?


von Wolfgang-G (Gast)


Lesenswert?

Offensichtlich ist mein Problem so trivial, dass ich nichts darüber 
finde.
Der Temperaturfühler TSic 506 sendet in Abständen von ca. 3ms seine 2 
Bytes langen Daten seriell auf einer Datenleitung. (mit 8kHz).
Die Datenleitung soll bei mir an P2.5 des MSP430 angeschlossen sein. Und 
jetzt mein Problem:
Wie kriege ich die ankommenden Nullen und Einsen seriell in einen 
Puffer, um dann diese weiterverarbeiten zu können.
Als Ansatz hatte ich mir gedacht, ich definiere eine Variable, und 
schiebe den Inhalt der Variablen nach jedem Takt um eine Stelle nach 
links.
Aber wie kann ich P2.5 abfragen, ob dort eine Null oder  Eins steht und 
diesen Wert mit der Variablen so verknüpfen, dass die kompletten Daten 
nach Empfang von 2 Bytes in der Variablen stehen?
Oder wie macht man es richtig?  Programmierung  in C.
MfG
Wolfgang

von Christian R. (supachris)


Lesenswert?

Hmm...da haste dir ja einen Sensor ausgesucht. 11 Bit Single Wire Output 
für State of the Art µControllers. Ohje.
Eventuell lässt sich was über die UART machen, die irgendwie 
missbrauchen. Aber das wird alles schwierig. Du musst ja den Takt auch 
irgendwie rückgewinnen. Gibts da nen komplettes Datenblatt irgendwo? 
Kannst du mal verlinken?

von Michael (Gast)


Lesenswert?

Eine Möglichkeit ist die von dir beschriebene. Das heißt, einzeln im 
Takt von 8kHz den Pinzustand abfragen und immer ein weiter nach links 
schieben. Nach 16 Takten hast du dann dein fertigen Wert stehen.

Wenn du noch frei in der Pinanordnung bist, würde ich persönlich eine 
Hardware-SPI Schnittstelle verwenden. Dann übernimmt der MSP für dich 
das schieben und zusammensetzen.

Viele Grüße
Michael

von Wolfgang-G (Gast)


Lesenswert?

Hier geht es  zum Datenblatt
http://www.zmd.biz/temp.php?group=temp&content=products

den TSic 506 habe ich mir als „Referenznormal“ beschafft. Die Fehler 
soll bei < 0,1° liegen.

Es muss P2.5 als Eingang für den seriellen Datenstrom verwendet werden, 
da meine Leiterplatte als Datenschreiber fertig ist und der 
Temperaturfühler nur angeschlossen werden soll. Da eine serieller 
Anschluss häufiger mal gebraucht wird (z.B. 1wire) , möchte ich 
gleichzeitig auch noch etwas dazulernen

Von ZMD gibt es ein Programmbeispiel in C für einen 8051, welches ich 
leider nicht richtig verstehe.
Deshalb würde ich noch mal meine Kernfrage in den Raum stellen: Wie 
fragt man den Eingang P2.5 ab, ob dort eine logische 1 oder Null steht 
und wie  verknüpft man das Ergebnis mit einem Puffer?
Oder wie kann man es unter den vorgegeben Bedingungen besser machen?
Mit freundlichen Grüßen
Wolfgang

von Supa M. (supa_micha)


Lesenswert?

Im Wesentlichen würde das so aussehen:

Messwert = Messwert << 1;
if (P2IN&0x20)
  Messwert |= 0x01;

Diesen Code müsstest du im 8 kHz Takt aufrufen.

Viele Grüße
Michael

von Christian R. (supachris)


Lesenswert?

Naja, das ist doch kein komplettes Datenblatt. Da steht nix zum Timing 
usw. drin. Schon ein seltsames Teil. Seh ich das richtig, dass er alle 
3ms einfach so seine 11 Bit rausfeuert? Ohne extra Takt, ohne Kodierung 
ohne alles? Was soll´n das für ein Unsinn sein. Du müsstest dich ja 
irgendwie exakt auf den Anfang eines Datenwortes synchronidieren, da man 
ja aber nie weiß, ob das jetzt 0 oder 1 ist, wird´s bissl schwierig. 
Wenn man das erste Bit hat, kann man mit einem Timer-Int abtasten, keine 
Frage. Die Synchronisierung ist halt tricky. Gibts da kein richtiges 
Datenblatt? In dem 6-Seiten-Wisch steht ja nix drinne....

von szimmi (Gast)


Lesenswert?

Hmmm, hab mal bei dem Link gesucht, unter
http://www.zmd.biz/pdf/IST_TSic_ZACwire_V2.3%20Digital%20Output_17-Oct-06.pdf
steht die Beschreibung zum Protokoll. Ist schon etwas abartig, aber mit 
dem MSP wohl machbar.
Also, wie in der Beschreibung mal folgendes testen:
1. Einen Timer mit 125kHz takten
2. Das Ausgangssignal auf einen interruptfähigen Eingang führen und so 
konfigurieren, dass bei negativer Flanke die ISR ausgeführt wird.
3. Timerwert (T1) beim Einsprung merken
4. In der ISR solange den Eingang pollen, bis er auf high geht. 
Timerwert (T2) merken und Differenz zu T1 bilden. Dabei kommt dT heraus.
5. Damit hast Du die "Strobe" Time beim Startbit ermittelt
6. Beim nächsten Einsprung in die ISR Timerwert (T3) wieder merken, T4 = 
T3+dT berechnen. Warten, bis der Timer T4 erreicht hat
7. In diesem Moment auf den Eingang schauen (am besten dreimal mit 
Majoritaetsenscheidung). Ist er high, hat der Sensor eine 1 ausgegeben, 
ist er 0, dann hat er eine 0 ausgegeben.
8. Nacheinander in dieser Art und Weise die Bits aufsammeln. Nach 21 
Bits (inclusive Startbit) ist ein Telegramm komplett und Du fängst 
wieder bei 1. an
Was die ISR-Last betrifft, er ist bei einem Telegramm (2,65ms) die 
Hälfte dieser Zeit in der ISR (1,3ms) beschäftigt. Bei einem Zyklus von 
100ms ist das eine CPU-Belastung von ca. 1,3%. Geht also noch (ich hoffe 
mal ich hab mich nicht arg verrechnet). In der Beschreibung kommen die 
auf Doppelte. Weiss allerdings nicht, warum.
Probiere es halt mal aus. Schoene Aufgabe, würde ich auch gerne machen, 
sicherlich interessant.

von Andreas K. (a-k)


Lesenswert?

Christian R. wrote:

> Ohne extra Takt, ohne Kodierung
> ohne alles? Was soll´n das für ein Unsinn sein.

Nix Unsinn, sondern schlicht PWM. Jedem, der schon man DCF77 dekodiert 
hat, sollte das verdammt bekannt vorkommen. Funktioniert exakt genauso, 
nur schneller, 8KHz statt 1Hz.

> Du müsstest dich ja
> irgendwie exakt auf den Anfang eines Datenwortes synchronidieren, da man
> ja aber nie weiß, ob das jetzt 0 oder 1 ist, wird´s bissl schwierig.

125µs lang high: Startbit folgt.
125µs lang low: Startbit isses.

Hat man einen capture-fähigen Timer, der auf beide Flanken reagieren 
kann, oder den man entsprechend umschaltet, ist das problemlos so 
nebenher zu erledigen. Aber bei dem dezenten Timing tut's ggf. auch ein 
externer Interrupt, wie oben beschrieben. Nur sollte die 
Interrupt-Latenzzeit dann unbedingt angenehm kurz bleiben.

von Wolfgang-G (Gast)


Lesenswert?

Zunächst einmal an alle vielen Dank.
Ich denke mal, dass ich jetzt ein Stück weiterkomme und werde zunächst 
mal mit Supa Michas  Programmschnipsel beginnen, falls dies der dafür 
gängige und einzige Weg ist, einen seriellen Datenstrom an einem Eingang 
zu erfassen.
@szimmi
Wenn ich es richtig verstanden habe, wird in dem von Dir zitierten 
Artikel eine weitere Möglichkeit beschrieben. Der Fühler wird über einen 
µC Ausgang zu- und abgeschaltet. Nach dem Zuschalten des Fühlers wartet 
man auf die fallende Flanke des Starbits auf der Datenleitung und hat 
somit den Anfang des Telegramms. Mal sehen, ob das so geht.
Mit freundlichen Grüßen
Wolfgang

von szimmi (Gast)


Lesenswert?

Nein,da habe ich mich wohl missverständlich ausgedrückt. Der Sensor wird 
nur über eine Signalleitung mit einem Eingang des µC verbunden.
Der Sensor wird nicht zu- oder abgeschaltet.

von Christian R. (supachris)


Lesenswert?

Andreas Kaiser wrote:
> Christian R. wrote:
>
>> Ohne extra Takt, ohne Kodierung
>> ohne alles? Was soll´n das für ein Unsinn sein.
>
> Nix Unsinn, sondern schlicht PWM. Jedem, der schon man DCF77 dekodiert
> hat, sollte das verdammt bekannt vorkommen. Funktioniert exakt genauso,
> nur schneller, 8KHz statt 1Hz.

Jo, is schon recht. Da kannte ich das vollständige Datenblatt noch 
nicht.

von Wolfgang-G (Gast)



Lesenswert?

@szimmi
Wahrscheinlich noch ein Missverständnis.
Ich meinte den angehängten Artikel. Lt. Abschnitt 1.4.2 erfolgt hier die 
Stromversorgung des Fühlers vom µC aus. Der Stromverbrauch ist so 
gering, dass er von einem Ausgang des µC versorgt werden kann. 65ms bis 
85ms nach dem Zuschalten des Fühlers beginnt der Fühler mit dem Senden 
des ersten Temperaturtelegramms. So habe ich es verstanden.
Mit freundlichen Grüßen
Wolfgang Gröbel

von Jörg S. (Gast)


Angehängte Dateien:

Lesenswert?

Wo ist denn da jetzt eigentlich das Problem? Ein C-Code wird von ZMD ja 
schon zur verfügung gestellt. Einfach passend anwandeln und gut. Ein 
Source Code für den TSic für MSP430 hab ich mal in den Anhang gepackt.

von Jörg S. (Gast)


Angehängte Dateien:

Lesenswert?

Und die h-Datei...

von Jörg S. (Gast)


Angehängte Dateien:

Lesenswert?

Zur Sicherheit noch die Hardware Datei :)

von Gast (Gast)


Lesenswert?

Hat jemand das schon einmal für den AVR umgesetzt ?

von Rubert K. (Gast)


Lesenswert?

Here is a sample code, based on the C++ code from the datasheet 
mentioned above. Works well with atmega8 and avr-gcc compiler.

von Rubert K. (Gast)


Angehängte Dateien:

Lesenswert?

(uploading files doesn't work first time)

von beobachter (Gast)


Lesenswert?

Du könntest über capture-and-compare so weine Art Software-UART 
implementieren.
Beispielcodes dafür gibts jede Menge.

von Martin K. (mkkirchner)


Angehängte Dateien:

Lesenswert?

Hallo,
Habe mal versucht den Code für einen PIC 16F876A umzustricken.
Leider ist bei dem zweiten Byte der ParityCheck immer FAIL und die 
Temperatur wird um 10,00°C zu wenig angezeigt.
Allersings verstehe ich dieses Verhakten absolut nicht!!

Hat jemand eine Idee????

Bin am Verzweifeln

martin

von Wolfgang-G (Gast)


Lesenswert?

vielleicht hast Du 10° zweimal abgezogen
lt. Datenblatt: Temp.= DigitalSignal/2047*70 -10

von Jörg S. (joerg-s)


Lesenswert?

Welchen TSic hast du? Der 506er hat ein anderes Datenformat als die 
kleineren.

von overseer (Gast)


Lesenswert?

Guten Abend.

Ich versuche z.Z einen TSIC 306 zum laufen zu bringen.

atm verwende ich dazu das von Robert K. gepostete programm (zwei drei 
posts über meinem)

folgendes verstehe ich aber nicht.
temperatur ist eine 16bit unsigned integer variable...was bedeutet das 
float davor?
in diese variable wird der tempsensor output geladen bei 25°C sind das 
0x2FF
der sensor sendet immer 11bit pakete
1
Temp_celsius = ((float)temperatur / 2047 * 200) - 50;

temper

hier das ganze im kontext.
1
int main (void) {
2
3
  uint16_t temperatur;  // 11-bit temperature value
4
  uint8_t returnvalue;  // return value of getTSicTemp(*temp);
5
  uint8_t Temp_celsius; // converted temperature in °C
6
7
  TSIC_INIT();          // set data direction of IO-Pins
8
9
10
  while(1){
11
12
    returnvalue = getTSicTemp(&temperatur);  // pull the TSIC-Sensor
13
14
    // conversion equation from TSic's data sheet
15
    Temp_celsius = ((float)temperatur / 2047 * 200) - 50;

von Jörg S. (joerg-s)


Lesenswert?

>temperatur ist eine 16bit unsigned integer variable...was bedeutet das
>float davor?
Das von unsigned int auf float "gecastet" (gewandelt) wird.

von overseer (Gast)


Lesenswert?

gut, die rechnung läuft dann mit nachkommastellen ab...

aaaber: was passiert dann? dann wird eine kommazahl auf ein uint8_t 
variable geschrieben?
oder wirkt sich der cast auch irgendwie auf die Temp_celsius aus?

von Jörg S. (joerg-s)


Lesenswert?

> dann wird eine kommazahl auf ein uint8_t variable geschrieben?
Ja

>oder wirkt sich der cast auch irgendwie auf die Temp_celsius aus?
Nein

von overseer (Gast)


Lesenswert?

und wie sieht das im klartext aus, wenn eine kommazahl auf einen integer 
geschrieben wird?
wird die kommazahl einfach abgerundet?

mich wundert das es überhaupt möglich ist und der compiler keinen terror 
schiebt :/

von overseer (Gast)


Lesenswert?

danke jörg

habs jetzt am laufen :)

die angezeigte temp. macht mich zwar etwas stutzig (ich glaube 1 bis 2°C 
zuviel) aber das sollte nur ein kleines problem sein

von Toni (Gast)


Lesenswert?

Guten Abend,

wenn ich hier einfach mal Anknüpfen darf.
Bin nun schon seit einiger Zeit am probieren, den TSIC 306 zum laufen zu 
bringen, allerdings zeigt dieser mir nur Scheiße auf dem LCD an :(
Erstmal die Codeschnipsel:

Hauptprogramm:
1
// Definitionen
2
// lcd-anschlussbelegung
3
#define LCD_PORT  PORTC
4
#define LCD_DDR    DDRC
5
6
#define LCD_DB    PC0
7
#define LCD_E    PC4
8
#define LCD_RS    PC5
9
10
// INCLUDE
11
#include <avr/io.h>
12
#include <avr/interrupt.h>
13
#include <util/delay.h>
14
#include <stdint.h>
15
#include "lcd_steuerung.h"
16
#include "tempsensor_ansteuerung.h"
17
18
// MAIN
19
void main (void)
20
21
  {
22
      lcd_init();
23
24
    // Temperturmessung mit TSIC ausführen und Daten auf dem LCD ausgeben
25
      while(1)
26
      {
27
      unsigned char parity = 0; // referenz für 2. übergabewert
28
      uint16_t wert = 0;
29
      lcd_string("WERT:;");
30
      wert = temp_messung(&parity);  //temp_byte = übergabe
31
      lcd_zahl_16(wert);
32
      lcd_cursor(0,2);
33
      lcd_string("parity:;");
34
      lcd_zahl_8(parity);
35
      _delay_ms(500);
36
      lcd_befehl(1);
37
38
      //ende while
39
      //33246 bei 20°C      
40
      }
41
            
42
    
43
    
44
    while(1){};
45
      
46
47
  }

LCD-Ansteuerung:
1
// LCD_FUNKTIONEN
2
/* ansteuerung eines LC-Displays im 4bit modus.
3
   Wartezeiten nach Datenblatt, Pinbelegung einsellbar. 
4
5
6
// Definitionen
7
// lcd-anschlussbelegung
8
#define LCD_PORT  PORTC
9
#define LCD_DDR    DDRC
10
11
#define LCD_DB    PC0
12
#define LCD_E    PC4
13
#define LCD_RS    PC5
14
*/
15
16
// lcd-Befehle
17
18
// clear display----------------0b00000001
19
#define lcd_display_löschen    0x01
20
21
// cursor bewegen
22
#define LCD_CURSOR_HOME      0x02
23
24
// DDRAM - Adresse festelgen
25
#define LCD_DDRAM        0x80
26
27
/* lcd-adressen für die Zeilen
28
   angaben sind für ein 4x20 Zeichen lcd.
29
   bei anderen auflösungen müssen die werte angepasst werden.
30
*/
31
#define lcd_cursor_1zeile    0x00
32
#define lcd_cursor_2zeile    0x40
33
#define lcd_cursor_3zeile    0x14
34
#define lcd_cursor_4zeile    0x54
35
36
///////////////////////////////////////////
37
// LCD-INITIALISIEREN
38
void lcd_init(void)
39
40
  {
41
    unsigned char zaehler = 1;
42
    LCD_DDR = 0xff;        // PORTC = ausgang
43
    _delay_ms(15);         // 15 ms warten
44
    LCD_PORT = 0x3;        // PORTC = 0x03
45
    while(zaehler <= 3)      // 3-mal enable
46
      {
47
        lcd_enable();    //enable 
48
        zaehler++;      //Zähl-Variable +1
49
      }
50
    // 4-bit modus
51
    LCD_PORT = 0x2;
52
    lcd_enable();
53
    
54
    // 4-bit, 2-Zeilig, 5x8 matrix 
55
    lcd_befehl(0x28);
56
    
57
    // display ein, cursor aus, blinken aus
58
    lcd_befehl(0x0f);
59
    
60
    //cursor inkrement, kein scrollen
61
    lcd_befehl(0x06);
62
63
    //lcd löschen
64
    lcd_befehl(0x01);
65
66
  }
67
68
///////////////////////////////////////////
69
// LCD_ENABLE
70
void lcd_enable(void)
71
72
  {
73
      LCD_PORT |= ( 1 << LCD_E );    //E-Setzen
74
      _delay_us(50);          //50µS warten
75
      LCD_PORT &= ~( 1 << LCD_E );  //E-rücksetzen
76
      _delay_ms(5);          //5ms warten
77
  }  
78
79
///////////////////////////////////////////
80
// LCD DATEN senden
81
void lcd_daten(uint8_t data)
82
  
83
  {
84
      LCD_PORT |= (1 << LCD_RS);      //RS setzen
85
      uint8_t u_nibble = data & 0x0f;    //unteres nibble
86
      data &= 0xf0;            //nur die obersten 4 bit maskieren
87
      LCD_PORT &= ~(0xf0 >> (4-LCD_DB));  //untere 4 bits löschen
88
      LCD_PORT |= (data >> (4-LCD_DB));  //obere 4 bits ausgeben
89
      lcd_enable();            //enable
90
      LCD_PORT &= ~(0xf0 >> (4-LCD_DB));  //untere 4 bits löschen
91
      LCD_PORT |= u_nibble;        //untere 4 bit ausgeben
92
      lcd_enable();            //enable
93
  }
94
95
///////////////////////////////////////////
96
// LCD BEFEHL senden
97
void lcd_befehl(uint8_t data)
98
99
  {
100
    
101
      LCD_PORT &= ~( 1 << LCD_RS);    //RS löschen
102
      uint8_t u_nibble = data & 0x0f;    //unteres nibble
103
      data &= 0xf0;            //nur die obersten 4 bit maskieren
104
      LCD_PORT &= ~(0xf0 >> (4-LCD_DB));  //untere 4 bits löschen
105
      LCD_PORT |= (data >> (4-LCD_DB));  //obere 4 bits ausgeben
106
      lcd_enable();            //enable
107
      LCD_PORT &= ~(0xf0 >> (4-LCD_DB));  //untere 4 bits löschen
108
      LCD_PORT |= u_nibble;        //untere 4 bit ausgeben
109
      lcd_enable();
110
111
  }
112
113
///////////////////////////////////////////
114
// LCD_STRING ausgeben
115
void lcd_string(const char *data)
116
117
  {
118
      while( *data != ';' )
119
         lcd_daten( *data++ );  
120
  }
121
122
///////////////////////////////////////////
123
// lcd-cursor postition; x = zeile/horizont, y = spalte/vertikal
124
void lcd_cursor(uint8_t x, uint8_t y)
125
126
  {
127
      uint8_t zeile;
128
      switch(y)
129
        {
130
          case 1:    // 1 Zeile
131
            lcd_befehl(LCD_CURSOR_HOME);
132
            zeile = LCD_DDRAM + lcd_cursor_1zeile + x;
133
            lcd_befehl(zeile);
134
            break;
135
136
          case 2:    // 2 Zeile
137
            lcd_befehl(LCD_CURSOR_HOME);
138
            zeile = LCD_DDRAM + lcd_cursor_2zeile + x;
139
            lcd_befehl(zeile);
140
            break;
141
142
          case 3:   // 3 Zeile
143
            lcd_befehl(LCD_CURSOR_HOME);
144
            zeile = LCD_DDRAM + lcd_cursor_3zeile + x;
145
            lcd_befehl(zeile);
146
            break;
147
148
          case 4:    // 4 Zeile
149
            lcd_befehl(LCD_CURSOR_HOME);
150
            zeile = LCD_DDRAM + lcd_cursor_4zeile + x;
151
            lcd_befehl(zeile);
152
            break;
153
          
154
          default:  // eine falsche angabe.
155
            return;
156
        }
157
  }
158
159
///////////////////////////////////////////
160
// 8-bit Zahl in ASCII umwandel und gleich auf dem LCD ausgeben
161
void lcd_zahl_8(uint8_t zahl)
162
  {
163
  if(zahl < 0)
164
  {
165
  uint8_t zaehler;
166
  //100er
167
  while( zahl > -99)
168
    { 
169
      zahl += 100;
170
      zaehler++;
171
    }
172
      if(zaehler != 0)
173
      {  
174
        zaehler += 0x30;
175
        lcd_daten(zaehler);
176
      }
177
      zaehler = 0;
178
179
    //10er
180
    while( zahl > -9)
181
      { 
182
        zahl += 10;
183
        zaehler++;
184
      }
185
        if(zaehler != 0)
186
        {
187
          zaehler += 0x30;
188
          lcd_daten(zaehler);
189
        }
190
191
      //einer
192
      zahl += 0x30;
193
      lcd_daten(zahl);
194
  }
195
  uint8_t zaehler;
196
  //100er
197
  while( zahl > 99)
198
    { 
199
    zahl -= 100;
200
    zaehler++;
201
    }
202
    if(zaehler != 0)
203
    {  
204
      zaehler += 0x30;
205
      lcd_daten(zaehler);
206
    }
207
    zaehler = 0;
208
209
    //10er
210
    while( zahl > 9)
211
      { 
212
      zahl -= 10;
213
      zaehler++;
214
      }
215
      if(zaehler != 0)
216
      {
217
        zaehler += 0x30;
218
        lcd_daten(zaehler);
219
      }
220
221
      //einer
222
      zahl += 0x30;
223
      lcd_daten(zahl);
224
  }
225
226
///////////////////////////////////////////
227
// 16-bit Zahl in ASCII umwandel und gleich auf dem LCD ausgeben
228
void lcd_zahl_16(uint16_t zahl)
229
  {
230
  uint8_t zaehler;
231
  //10000er
232
  while( zahl > 9999)
233
    { 
234
    zahl -= 10000;
235
    zaehler++;
236
    }
237
    if(zaehler != 0)
238
    {
239
      zaehler += 0x30;
240
      lcd_daten(zaehler);
241
    }
242
    zaehler = 0;
243
244
    //1000er
245
    while( zahl > 999)
246
      { 
247
      zahl -= 1000;
248
      zaehler++;
249
      }
250
      if(zaehler != 0)
251
      {
252
        zaehler += 0x30;
253
        lcd_daten(zaehler);
254
      }
255
      zaehler = 0;
256
257
      //100er
258
      while( zahl > 99)
259
        { 
260
        zahl -= 100;
261
        zaehler++;
262
        }
263
        if(zaehler != 0)
264
        {  
265
          zaehler += 0x30;
266
          lcd_daten(zaehler);
267
        }
268
        zaehler = 0;
269
270
        //10er
271
        while( zahl > 9)
272
          { 
273
          zahl -= 10;
274
          zaehler++;
275
          }
276
          if(zaehler != 0)
277
          {
278
            zaehler += 0x30;
279
            lcd_daten(zaehler);
280
          }
281
282
          //einer
283
          zahl += 0x30;
284
          lcd_daten(zahl);
285
  }

und die wohl wichtigste Datei, Sensoransteuerung:
1
// TSIC 306
2
#define steigende_flanke  (PINB & (1 << PB2))    // steigende Flanke bzw. high
3
#define fallende_flanke    !(PINB & (1 << PB2))  // fallende Flanke bzw. low
4
#define tsic_on        PORTB |= (1 << PB1)    // Sensor einschalten
5
#define tsic_off      PORTB &= ~(1 << PB1)  // Sensor ausschalten
6
#define tsic_delay_us    1            // Flankenzeit des TSIC
7
8
unsigned int temp_messung(unsigned char *parity_byte)
9
{
10
      
11
      uint16_t temp_byte = 0;
12
      //tempsensor ansteuerung
13
      //Sensor starten und auf fallende flanke warten
14
      DDRB = ((1 << PB1) | (1 << PB0));    // PB0, PB1 = eingang
15
      
16
      tsic_on;
17
      _delay_ms(40);              // Sensor einschalten
18
      
19
      while (fallende_flanke);        // warte auf fallende Flanke
20
      
21
      while (steigende_flanke);        // auf steigende Flanke warten
22
              
23
      for (uint8_t i = 0; i < 8; i++)      // hier nun Bits auswerten
24
        {
25
          while (fallende_flanke);    // warten bis zum ersten bit.
26
          _delay_us(tsic_delay_us);    // 60µSekunden warten
27
          if (steigende_flanke)      // wenn eingang 1, 
28
            temp_byte |= 1 << (15-i);  // dann bit schreiben
29
            else               // wenn nicht,
30
              while (steigende_flanke);  // dann warten bis flanke wieder steigt, bzw. immernoch eingang = 1.
31
        }
32
33
      // parity auswerten bzw. erstmal abwarten
34
      while (fallende_flanke);        // Parity_bit
35
      _delay_us(tsic_delay_us);        // 60µs warten
36
      if (steigende_flanke)
37
        *parity_byte |= 1 << 1;        // wenn parity = 1, dann eine 1. eine stelle nach links schieben
38
        else while (steigende_flanke);    // wenn parity_byte = 0, dann warten bis flanke wieder steigt
39
      
40
      // stoppbit absitzen
41
      while (fallende_flanke);        // stop bit
42
      
43
      // startbit absitzen
44
      while (steigende_flanke);        // start bit
45
      
46
      // 2 byte LSB
47
      for (uint8_t i = 0; i < 8; i++)      // hier nun Bits auswerten
48
        {
49
          while (fallende_flanke);    // warten bis zum ersten bit.
50
          _delay_us(tsic_delay_us);    // 60µSekunden warten
51
          if (steigende_flanke)      // wenn eingang 0, 
52
            temp_byte |= 1 << (7-i);  // dann bit schreiben
53
            else               // wenn nicht,
54
              while (steigende_flanke);  // dann warten bis flanke wieder steigt, bzw. immernoch eingang = 1.
55
        }
56
      // parity auswerten bzw. erstmal abwarten
57
      while (fallende_flanke);        // Parity_bit
58
      _delay_us(tsic_delay_us);        // 60µs warten
59
      if (steigende_flanke)
60
        *parity_byte |= 1 << 0;        // wenn parity = 1, dann eine 1. 0 stellen nach links schieben
61
      
62
      tsic_off;                // Sensor ausschalten
63
      
64
      return temp_byte;            // gemessenen Wert zurückgeben          
65
}

Ich verwende aktuell im "main"-Abschnitt die direkte Wert-Ausgabe, d.h. 
er zeigt mir den eingelesenen Wert direkt an.
Da kommt aber absoluter Mist raus. Verändere ich die T-strobe Zeit auf 1 
µS, so zeigt er mir 65471 an, wobei nach meinem Verständnis hier 0 
angezeigt werden sollte. Allgemein kommt mit jeder anderen Wartezeit ein 
anderer Wert raus und ich kapier einfach nicht warum. Der Code ist stark 
an den im Datenblatt angegebenen angelehnt. Vielleicht kann ja mal 
jemand schnell drüber schauen ob er einen Fehler findet. Oder besser 
jemand hat mal ein Digitaloszi an den Sensor gehangen und kann mir 
beschreiben, wie der genaue Ablauf zwischen dem 1. und 2. Byte mit 
Stop/Start-Bit vonstatten geht. Die LCD-Funktionen funktionieren 
einwandfrei, der Fehler muss in der letzten Datei liegen, irgendwo bei 
der einleserei. Ich find einfach keinen Fehler.
Ich Danke Euch schonmal für die Hilfe.

von Dude (Gast)


Lesenswert?

Es gibt in Beitrag "AVR TSIC Auswertung => riesen Programm" eine 
verbesserte Fassung des Codes aus Beitrag 
Beitrag "Re: wie Daten an MSP430F1611 seriell einlesen?" für AVR (allerdings 
mit ein paar Fehlern).

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.