Forum: Mikrocontroller und Digitale Elektronik Atmega88p 12bit senden ?


von Michael H. (h_m)


Lesenswert?

Guten Abend,

ich habe einen ltc1257 D/A wandler den ich jetzt auf die einfachste art 
erst einmal ansteuern will. Dazu habe ich nachfolgenden Code erstellt. 
In dem ich mit der Variable data 8bit zu dem Dac sende, was mir aber 
nicht ganz klar ist, kann ich mit meinem Code auch 12bit senden ? wenn 
ja, kann mir das  hier Bitte jemand zeigen ?
1
/* soft_serial_01.c ATmega88 @ 16MHz */
2
#include <avr/io.h>
3
 
4
void soft_serial (uint8_t data)         // Funktion soft_serial
5
{
6
    for (uint8_t i=0; i<=7; i++)     // for-Schleife 8 mal ausführen
7
    {
8
        if (data & 1)                   // Wenn data an Stelle 0 = 1
9
            PORTD |= (1<<PD0);            // Data serial = 1
10
        else
11
            PORTD &= ~(1<<PD0);           // Data serial = 0
12
             
13
        PORTD |= (1<<PD1);                // PD1 = 1 (CLK = low)
14
        PORTD &= ~(1<<PD1);               // PD1 = 0 (CLK = high)
15
         
16
        data = data >> 1;             // data um 1 Stelle nach rechts schieben
17
    }
18
}
19
 
20
int main(void)
21
{
22
    uint8_t data = 0xAA;                // data = 1010 1010
23
    DDRD = 0xFF;                        // Richtungsregister PORTD = Ausgang
24
    PORTD = 0x04;                       // PD2 (RCK) = HIGH, 0x04 = 0000 0100
25
     
26
    while(1)
27
    {
28
        soft_serial(data);              // Funktionsaufruf und Übergabe von data
29
        PORTD &= ~(1<<PD2);               // PD2 = 0 (Takt = LOW für RCK)
30
        PORTD |= (1<<PD2);                // PD2 = 1 (Takt = HIGH für RCK -> Ausgabe Schieberegister)
31
    }
32
}

von helge (Gast)


Lesenswert?

da mußt du doch nur ein data als unit16_t bereitstellen und in der 
soft_serial die for-schleife 12 mal durchlaufen zu lassen.

von Michael H. (h_m)


Lesenswert?

Danke, ich habe seit geraumer zeit nichts mehr gemacht, da vergisst man 
so einfache sachen.

von ... (Gast)


Lesenswert?

Michael H. schrieb:
> ... da vergisst man so einfache sachen.

Bis 12 zu zählen, statt bis 8?

von Michael H. (h_m)


Lesenswert?

jetzt muss ich doch noch einmal was fragen, schreibe ich zb. wenn ich 
alle auf 1 setzen will bei 16bit  4 nibble 0xFFFF oder bei 12 mal 1 halt 
0x0FFF

von Michael H. (h_m)


Lesenswert?

So, jetzt funktioniert es wie unten im Code. Aber ich habe noch ein 
kleines Problem, und zwar sind doch 12bit 4095 dez. oder ?

ich steuere hiermit eine DAC an der von 0- 10V ausgibt.

und mit dieser Zeile in data & möchte ich die bits maskieren und zwar 
das das 12. an erster stelle steht, und ich somit der Variable data 
einen Wert von 0-4095 also 0-10V eingeben kann
1
if (data & 0xC00) //hier soll  Wenn data an Stelle 12 = 1

allerdings habe ich mit dem Oszi. festgestellt das bei einem Wert von 
ca. 3000 schon 10V ausgegeben werden. kann mir vielleicht bitte jemand 
sagen wie ich das richtig maskieren kann das das funktioniert ?
1
/*
2
 * LTC1257_2.c
3
 *
4
 * Created: 23.02.2019 17:06:43
5
 * Author : USER
6
 */ 
7
8
/* soft_serial_01.c ATmega88 @ 16MHz */
9
10
#define F_CPU 16000000UL
11
#include <avr/io.h>
12
#include <util/delay.h>
13
14
void soft_serial (uint16_t data)         // Funktion soft_serial
15
{
16
  for (uint8_t i=0; i<=11; i++)     // for-Schleife 12 mal ausführen
17
  {
18
    if (data & 0xC00)                   //hier soll  Wenn data an Stelle 12 = 1
19
    PORTD |= (1<<PD0);            // Data serial = 1
20
    else
21
    PORTD &= ~(1<<PD0);           // Data serial = 0
22
    
23
    PORTD |= (1<<PD1);                // PD1 = 1 (CLK = low)
24
    //_delay_us(1); 
25
    PORTD &= ~(1<<PD1);               // PD1 = 0 (CLK = high)
26
    
27
    data = data << 1;             // data um 1 Stelle nach links schieben
28
  }
29
}
30
31
int main(void)
32
{
33
  uint16_t data = 3000;              // hier soll ein Wert 0-4095 12bit funktionieren
34
  DDRD = 0xFF;                        // Richtungsregister PORTD = Ausgang
35
  PORTD = 0x04;                      // PD2 (RCK) = HIGH, 0x04 = 0000 0100
36
  
37
  while(1)
38
  {
39
    soft_serial(data);              // Funktionsaufruf und Übergabe von data
40
    PORTD &= ~(1<<PD2);               // PD2 = 0 (Takt = LOW für RCK)
41
    //_delay_us(1); 
42
    PORTD |= (1<<PD2);                // PD2 = 1 (Takt = HIGH für RCK -> Ausgabe Schieberegister)
43
  }
44
}

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


Lesenswert?

Michael H. schrieb:
> if (data & 0xC00)                   //hier soll  Wenn data an Stelle
> 12 = 1

Du maskierst hier aber 2 Bits. Wenn da z.B. eine 4095 (0x0FFF) drin 
steht, dann sendest du ein Highbit, und das gleiche passiert bei 0x08nn 
und bei 0x04nn.
Maskiere also auf 0x0800, dann sieht das schon besser aus.

: Bearbeitet durch User
von Eric B. (beric)


Lesenswert?

> if (data & 0xC00)                   //hier soll  Wenn data an Stelle 12 = 1

Mach aus dem 0xC00 mal 0x0800.

von Michael H. (h_m)


Lesenswert?

Danke,

jetzt klappt es Wunderbar, jetzt glaube ich habe ich es endlich einmal 
Verstanden. Wenn ich jetzt mit 0x0c00, dann würde ich den 3ten nibble 
mit 1100 also mit 12 maskieren oder ?

von Falk B. (falk)


Lesenswert?

Michael H. schrieb:
> Danke,
>
> jetzt klappt es Wunderbar, jetzt glaube ich habe ich es endlich einmal
> Verstanden. Wenn ich jetzt mit 0x0c00, dann würde ich den 3ten nibble
> mit 1100 also mit 12 maskieren oder ?

Ja, und das wäre sinnlos. Siehe Bitmanipulation.

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.