Forum: Mikrocontroller und Digitale Elektronik 74HC595 ohne SPI


von Frank L. (franklink)


Lesenswert?

Hallo,
ich benötige mal Eure Hilfe, ich versuche schon den ganzen Tag die 
Routine zur Ansteuerung eines 74HC595 ohne SPI ans laufen zu bekommen.

Im Simulator sieht es gut aus, aber technisch kommt nichts an.

Header:
1
/* SERiell nach PArallel (serpa) im SPI-Protokoll */
2
#ifndef _COM74HC595_H_
3
#define _COM74HC595_H_
4
5
/* 4 Bytes (32 Ports) */
6
#define COM74HC595_SIZE 1
7
8
#define PORT_COM74HC595 PORTB
9
#define PORT_SER     PB0    //74HC595 PIN 14
10
#define PORT_SCK     PB1    //74HC595 PIN 11
11
#define PORT_RCK     PB2    //74HC595 PIN 12
12
13
#define DDR_COM74HC595  DDRB
14
#define DDR_SER     DDB0  //74HC595 PIN 14
15
#define DDR_SCK     DDB1  //74HC595 PIN 11
16
#define DDR_RCK     DDB2  //74HC595 PIN 12
17
18
extern unsigned char com74hc595[];
19
extern void Com74hc595_out();
20
extern void Com74hc595_init();
21
22
#endif /* _COM74HC595_H_ */

Main:
1
#include <avr/io.h>
2
#include "Com74hc595.h"
3
4
/* Array fuer die Daten */
5
unsigned char com74hc595[ COM74HC595_SIZE ];
6
7
void Com74hc595_init()
8
{
9
    /* Verwendete Ports auf OUT */
10
  DDR_COM74HC595 |= ( 1 << DDR_SER);
11
  DDR_COM74HC595 |= ( 1 << DDR_SCK);
12
  DDR_COM74HC595 |= ( 1 << DDR_RCK);
13
14
15
  PORT_COM74HC595 &= ~(1<<PORT_SER);
16
    /* SCR und RCK auf definierten Level HIGH */
17
  PORT_COM74HC595 |= (1<<PORT_SCK);
18
  PORT_COM74HC595 |= (1<<PORT_RCK);
19
}
20
21
void Com74hc595_out()
22
{
23
    unsigned char anz = COM74HC595_SIZE;
24
    unsigned char* serp = com74hc595 + COM74HC595_SIZE;
25
26
    do
27
    {
28
        unsigned char bits;
29
        unsigned char data = *--serp;
30
31
        /* 8 Bits pro Byte rausschieben */
32
        for (bits = 8; bits > 0; bits--)
33
        {
34
            PORT_COM74HC595 &= ~(1<<PORT_SER);
35
            if (data & 0x80)
36
            {
37
                PORT_COM74HC595 |= (1<<PORT_SER);
38
            };
39
40
            data <<= 1;
41
            /* Strobe an SCK schiebt Daten im Gaensemarsch */
42
            /* um 1 Position weiter durch alle Schieberegister */
43
            PORT_COM74HC595 &= ~(1<<PORT_SCK);
44
            PORT_COM74HC595 |= (1<<PORT_SCK);
45
        }
46
    }
47
    while (--anz > 0);
48
49
    /* Strobe an RCK bringt die Daten von den Schieberegistern in die Latches */
50
  PORT_COM74HC595 &= ~(1<<PORT_RCK);
51
  PORT_COM74HC595 |= (1<<PORT_RCK);
52
}
53
 
54
int main(void)
55
{
56
    Com74hc595_init();
57
58
    com74hc595[0] = 0x1;
59
    com74hc595[1] = 0x1;
60
    com74hc595[2] = 0x1;
61
    com74hc595[3] = 0x1;
62
    com74hc595[4] = 0x0;
63
    com74hc595[5] = 0x0;
64
    com74hc595[6] = 0x0;
65
    com74hc595[7] = 0x0;
66
67
    Com74hc595_out();     
68
69
    while(1)
70
    {
71
    }
72
 
73
    return 0;
74
}

Der Ursprungscode stammt übringends von hier:

http://www.roboternetz.de/wissen/index.php/Portexpander_am_AVR#Makros.2C_Datenstrukturen.2C_Funktionen

Danke für jeden Tip.

Gruß
Frank

von Christian Z. (christianz)


Lesenswert?

Dir ist klar, dass die Routine nur die 8 Bits aus com74hc595[0] ausgibt?

von Ekschperde (Gast)


Lesenswert?

> #define COM74HC595_SIZE 1

> unsigned char com74hc595[ COM74HC595_SIZE ];

passt nicht zu:

>   com74hc595[0] = 0x1;
>   com74hc595[1] = 0x1;
>   com74hc595[2] = 0x1;
>   com74hc595[3] = 0x1;
>   com74hc595[4] = 0x0;
>   com74hc595[5] = 0x0;
>   com74hc595[6] = 0x0;
>   com74hc595[7] = 0x0;

Es gibt nämlich nur:

>   com74hc595[0] = 0x1;

Da steht das ganze Byte für den 595 drin.

von Frank L. (franklink)


Lesenswert?

Danke,
das wars, wenn man sich nicht jeden Tag mit c beschäftigt, interpretiert 
man bestimmte Warnings des Compilers falsch.

Der Fehler ist entstanden durch ein Warnining, in der Zuweisung:
1
com74hc595[0] = 0x00000001;

korrekt muss es natürlich heißen

1
com74hc595[0] = 0b00000001;

dann funktionierts.

Danke
Gruß
Frank

von Andreas K. (a-k)


Lesenswert?

Interessant. Ist nämlich exakt das gleiche.

von Christian Z. (christianz)


Lesenswert?

Wenn
1
com74hc595[0] = 0x00000001;

nicht funktioniert, aber
1
com74hc595[0] = 0b00000001;

schon, dann ist Dein C-Compiler kaputt.

Übrigens: Die Zeilen
1
com74hc595[1] = 0x1;
2
com74hc595[2] = 0x1;
3
com74hc595[3] = 0x1;
4
com74hc595[4] = 0x0;
5
com74hc595[5] = 0x0;
6
com74hc595[6] = 0x0;
7
com74hc595[7] = 0x0;

haben keinen (von Dir gewünschten) Effekt.

von Frank L. (franklink)


Lesenswert?

Hallo,
1
com74hc595[0] = 0x00000000;
2
Com74hc595_out();     
3
sleep();
4
com74hc595[0] = 0x00000001;
5
Com74hc595_out();     
6
sleep();
7
com74hc595[0] = 0x00000010;
8
Com74hc595_out();     
9
sleep();
10
com74hc595[0] = 0x00000100;
11
Com74hc595_out();

ist nicht das selbe wie
1
com74hc595[0] = 0b00000000;
2
Com74hc595_out();     
3
sleep();
4
com74hc595[0] = 0b00000001;
5
Com74hc595_out();     
6
sleep();
7
com74hc595[0] = 0b00000010;
8
Com74hc595_out();     
9
sleep();
10
com74hc595[0] = 0b00000100;
11
Com74hc595_out();

in der ersten Variante erhalte in in dieser Zeile einen Warning

com74hc595[0] = 0x00000100;

warning: large integer implicity truncated to unsigned type

Vielleicht kann mir jemand erklären warum?

Ich kann natürlich falsch liegen, aber "0x" ist doch Hex- und "0b" 
Binärschreibweise oder?

Gruß
Frank

von Joachim (Gast)


Lesenswert?

>in der ersten Variante erhalte in in dieser Zeile einen Warning
>com74hc595[0] = 0x00000100;
>warning: large integer implicity truncated to unsigned type

Weil ein CHARacter nur 8 Bit hat, 0x00000100 aber 9.

von Bobby (Gast)


Lesenswert?

0x100 passt nicht in ein Byte...

von Christian Z. (christianz)


Lesenswert?

Klar. Ich habe ja nicht geschrieben, dass
1
com74hc595[0] = 0x00000100;

das selbe wäre wie
1
com74hc595[0] = 0b00000100;

sondern nur, dass 0x1 == 0b1 ist. Das eine ist eine hexadezimale 
Darstellung, das andere eine binäre (die übrigens kein Standard-C ist).

von Frank L. (franklink)


Lesenswert?

Danke, ich dachte ich wäre blöd.

Deshalb ist der Wert 0x00000001 = 0b00000001 aber in der Verwendung mit 
dem Rest der Routine nicht korrekt.

Die Definition von com74hc595 ist unsigned char com74hc595 also maximal 
1 Byte.

Aber mal eine andere Frage, wie setzte ich elegant ein Bit in einem 
unsigned char bzw. nehme das Bit wieder raus.

Gruß
Frank

von Christian Z. (christianz)


Lesenswert?

Frank Link wrote:

> Aber mal eine andere Frage, wie setzte ich elegant ein Bit in einem
> unsigned char bzw. nehme das Bit wieder raus.

Das hast Du doch schon oben in Deinem Code stehen: Setzen mit
1
byte |= (1 << BITNR)

löschen mit
1
byte &= ~(1 << BITNR)

von Matthias Kölling (Gast)


Lesenswert?

Ganz verstehe ich es immer noch nicht.
Wenn
#define COM74HC595_SIZE 1
dann sind doch
com74hc595[1] = 0x1;
com74hc595[2] = 0x1;
com74hc595[3] = 0x1;
com74hc595[4] = 0x0;
com74hc595[5] = 0x0;
com74hc595[6] = 0x0;
com74hc595[7] = 0x0;
undefinierte Speicherzugriffe.
Oder sehe ich das falsch?


Gruß Matthias

von Sven (Gast)


Lesenswert?

@ Matthias:

> Oder sehe ich das falsch?

Nein, siehst Du ganz richtig.
Array ist nur auf ...[0] definiert..

Gruß Sven

P.S.: Also mit dem Posting #1.

von Frank L. (franklink)


Lesenswert?

Ich sag ja, ich habe mich am Anfang von dem Warning des Compilers 
irritieren lassen, mein Fehler.

Jetzt läuft die ganze Sache rund.

Gruß
Frank

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.