Forum: Mikrocontroller und Digitale Elektronik 24 Bit ADC HX711 auswerten mittels UART (in C)


von Kenan (Gast)


Lesenswert?

Hallo,
ich bin neu im Programmieren und wollte mir eine Waage bauen mittels 
einer Wägezelle und dem HX711. Ich programmiere mit dem ATMEGA16 und in 
ATMELSTUDIO. Ich habe bereits einen Code geschrieben, aber er 
funktioniert nicht ganz. Habe auch ein paar Warnings. Wäre sehr nett, 
wenn ihr kurz drüber schauen könntet.
Beim HX711 handelt sich es um einen 24 Bit ADC. Es gebt mir hierbei nur 
um die Auswertung der 24 Bit. MSB First. Außerdem bin ich mir nicht 
sicher ob man den HX711 mit UART auswerten kann.

Code:
1
#include <avr/io.h>
2
#include "printf.h"
3
#include "LCD_4.h"
4
#include <util/delay.h>
5
#include <avr/interrupt.h>
6
7
#define F_CPU 12000000
8
#define BAUD 9600
9
10
unsigned long x=12345600, y,sum;
11
unsigned long werte[10];
12
int j=0;
13
14
void init()
15
{
16
    int baudrate=(unsigned long)12000000/(BAUD-1)/16;
17
    // Baudrate einstellen -> 9600
18
    UBRRH =  (baudrate) | (1<<URSEL);         
19
 //URSEL=0
20
    UBRRL = baudrate;
21
  
22
    // UART-RAhmen konfigurieren
23
    // UCSRA=
24
    UCSRB=  (1<<TXEN);           
25
 //enable Receiver/Transmitter, RX Complete Interrupt Enable,
26
           
27
28
29
void clk()
30
{
31
    PORTB |=(1<<PD0);
32
    PORTB &=~(1<<PD1);
33
}
34
35
void bitWrite(unsigned long *x, char n, char value) {
36
  if (value)
37
  *x |= (1 << n);
38
  else
39
  *x &= ~(1 << n);
40
}
41
42
char bitRead(char *x, char n) {
43
  return (*x & (1 << n)) ? 1 : 0;
44
}
45
46
47
int main(void)
48
{
49
  
50
  for (int j=0; j<10; j++)
51
  {
52
    PORTD &=~(1<<PD1); // SCK auf LOW stellen
53
    
54
    werte[j]=y;
55
  }
56
  
57
  
58
  for (j=0;j<10;j++)
59
  {
60
    sum+=werte[j];
61
  }
62
  sum=sum/10;
63
  
64
  printf("%d",sum);
65
  // printf("%X",sum);
66
  _delay_ms(2000);
67
}
68
69
ISR(USART_RXC_vect)
70
{
71
  for (int i=0; i<24; i++)  // 24 BIT einlesen
72
  {
73
    clk();
74
    bitWrite(x,0,PIND & (1<<PIND0));    // schreibt den Inhalt von RXD in das erste Bit von der hilfsvariable x
75
    x=x<<1;
76
  }
77
  clk();
78
  y=x;
79
  x=0x12345600;  // 12345678 ... Debug Wert
80
  _delay_ms(200); // kann auch us sein bin mir nicht sicher
81
}

von Kenan (Gast)


Lesenswert?

Hab noch vergessen, das Warning ist: passing argument 1 of 'bitWrite' 
makes pointer from integer without a cast [-Wint-conversion]

von Achim M. (minifloat)


Lesenswert?

Kenan schrieb:
> bitWrite(x,0,PIND & (1<<PIND0));

Bist du dir da sicher?
Dazu passend auch...

Kenan schrieb:
> argument 1 of 'bitWrite' makes pointer from integer without a cast
> [-Wint-conversion]

Vielleicht mit einem klassischen
PIND |= (1<<PD0);
zum toggeln des Bit 0 im PORTD-Register probieren?
Geht aber nicht mit ganz alten Atmegas.
Oder willst du eigentlich was ganz anderes erreichen?

Kenan schrieb:
> ISR(USART_RXC_vect)

Wo wird das Interruptflag gelöscht?
Nirgendwo liest du das UART-Datenregister oder Schreibst eine 1 an 
passende Stelle im Flagregister.
Aus dem Kommentar hier
Kenan schrieb:
> // schreibt den Inhalt von RXD [...]
wird das sicher nicht gemacht

mfg mf

von Kenan (Gast)


Lesenswert?

Erstmals vielen Dank für deine schnelle Antwort.
> Oder willst du eigentlich was ganz anderes erreichen?
Ich will eigentlich nur die Daten die ich von PIND0 (RXD Terminal von 
UART am ATMEGA16) bekomme in eine Variable (in diesem Fall x) speichern 
und zwar MSB first. Die BitWrite Funktion soll eben diese Daten dann in 
richtiger Reihenfolge (wie schon gesagt MSB first) in die Variable x 
speichern.
Außerdem weiß ich nicht ganz genau wo ich das Interrupt Flag löschen 
soll. Ich habe dieses Interrupt schon öfters verwendet jedoch in ganz 
anderer Ausführung und zwar in dem ich einfach UDR in einer Variable 
speichere.
Lg kh

von Matthias S. (Firma: matzetronics) (mschoeldgen)


Lesenswert?

Kenan schrieb:
> void clk()
> {
>     PORTB |=(1<<PD0);
>     PORTB &=~(1<<PD1);
> }

Auch das hier sieht seltsam aus. Ein Clock Puls wird sicher nicht 
dadurch erzeugt, das PD0 auf 1 gesetzt wird und PD1 auf 0.

Noch ein Tipp: Du kannst in eine uint32_t Variable recht einfach Daten 
eines Pins reinshiften. Wir nehmen mal an, das PD0 der Datenausgang des 
ADC ist.
1
uint32_t ReadMy24Bits() {
2
uint8_t n;
3
uint32_t result = 0; 
4
for (n=0; n<24; n++) {
5
    clk();
6
    if (PIND & PD0) result |= 1;
7
    result <<= 1;
8
    }
9
 return result;

: Bearbeitet durch User
von Kenan (Gast)


Lesenswert?

Matthias S. schrieb:
> Kenan schrieb:
>> void clk()
>> {
>>     PORTB |=(1<<PD0);
>>     PORTB &=~(1<<PD1);
>> }
>
> Auch das hier sieht seltsam aus. Ein Clock Puls wird sicher nicht
> dadurch erzeugt, das PD0 auf 1 gesetzt wird und PD1 auf 0.
Ok danke für das Feedback, habe versucht hierbei einen Arduino Code 
nachzubauen. Wie kann ich denn einen Puls Clock erzeugen? Muss ich einen 
Timer verwenden?

> Noch ein Tipp: Du kannst in eine uint32_t Variable recht einfach Daten
> eines Pins reinshiften. Wir nehmen mal an, das PD0 der Datenausgang des
> ADC ist.uint32_t ReadMy24Bits() {
> uint8_t n;
> uint32_t result = 0;
> for (n=0; n<24; n++) {
>     clk();
>     if (PIND & PD0) result |= 1;
>     result <<= 1;
>     }
>  return result;

Aha ok alles klar, danke für den Tipp.

von Achim M. (minifloat)


Lesenswert?

Eigentlich sollte es eine SPI-Schnittstelle eher tun als der UART.
Da kann man glaub ich erstmal das AVR-GCC Tutorial in den Artikeln 
empfehlen...

Der Code sieht wahllos zusammenkopiert aus und fast keine Codezeile 
scheint das, was gewollt ist, zu tun. Zu sehen an den Kommentaren, die 
fast das Gegenteil der Auswirkungen des umgebenden Codes beschreiben.

Nun, so lernt man dieses Zeug. Scheitern und lernen.

mfg mf

von Kenan (Gast)


Lesenswert?

>> for (n=0; n<24; n++) {
>>     clk();
>>     if (PIND & PD0) result |= 1;
>>     result <<= 1;
>>     }
>>  return result;
Welche Funktion verwendest du hier für clk(); ?
lg kh

von Kenan (Gast)


Lesenswert?

Ok alles Klar, danke für die Antwort

von Matthias S. (Firma: matzetronics) (mschoeldgen)


Lesenswert?

Kenan schrieb:
> Welche Funktion verwendest du hier für clk(); ?
> lg kh

Ich setzt hier eine funktionierende Routine für das Erzeugen eines 
Clockpulses voraus. Da wir nach wie vor nichts über die Verdrahtung von 
ADC und AVR wissen, gehe ich da nicht näher ins Detail.
Aber wenn z.B. der ADC auf eine steigende Flanke des Clockpulses ein 
neues Bit zur Verfügung stellt und der Clock Eingang auf PD1 liegt, kann 
das so aussehen:
1
void clk(void) {
2
 _delay_us(10);  // nur als Beispiel , Datenblatt des ADC entscheidet
3
 PORTD &= ~(1 << PD1);   // Clock auf 0
4
 _delay_us(10);          // low für 10µs
5
 PORTD |= (1 << PD1);    // Clock auf 1, neues Bit kann eingelesen werden
6
}

: Bearbeitet durch User
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.