Forum: Mikrocontroller und Digitale Elektronik AVR + 74HC165 + UART


von Phillip H. (philharmony)


Lesenswert?

Moin, ich habe mal ein bisschen was zusammengetipselt und habe nun das 
Problem, daß ich über UART nur was empfange, wenn ich den Schalter (mit 
Pull UP) am D7 des SR verändere.
Alle anderen Schalter ergeben keine Reaktion.
Ich habe zum testen mal nur ein SR angehängt, dessen Serial In mit Masse 
verbunden.
Wenn ich jetzt Schalter 7 umstelle, dann wird der gesamte 16-Byte-Satz 
den ich empfange komplett 1 oder komplett 0.
Ich schätze daß irgendwas am umschalten Shift/Load oder so nicht 
hinhaut.
Vllt hat da jemand den Durchblick und schaut sich das kurz an?
LG
1
unsigned char   Data_to_send[17], 
2
        Data_to_send_old[17], 
3
        Data_output[16],
4
        Data_output_old[16],
5
        Data_received[16], 
6
        Number_of_bytes_RXD=0, 
7
        Type_of_bytes_RXD=0, 
8
        receive_type=0,
9
        receive_count=0;
10
11
#define Pin_Input       ((PINC & (1<<PINC0)) != 0 ? 1 : 0) //PIN C0 ist der Input Pin für das Input-Schieberegister
12
#define Input_Clock     1      //PIN C1 als Clock am Input Register
13
#define Input_Load_Shift   2      //PIN C2 als Load-Shift Wähler
14
#define Pin_Output      3      //PIN C3 als Output Pin für das Output Schieberegister
15
#define Output_Clock    4      //PIN C4 als Clock am Output Register
16
#define Output_Shift_Load  5      //PIN C5 als Shift-Load Wähler
17
18
19
//*******************************************//
20
//****************Hauptschleife**************//
21
//*******************************************//
22
23
int main(void)    
24
{
25
wdt_disable();  //Watchdog timer sicherheitshalber nach einem WDT-reset wieder deaktivieren
26
DDRC |= (1<<Input_Clock) | (1<<Input_Load_Shift) | (1<<Pin_Output) | (1<<Output_Clock) | (1<<Output_Shift_Load);//DDRC Setzen
27
sei();      //Interrupts Global zulassen
28
USART_Init(MYUBRR); //UASRT initialisieren (mit 9200 baud, 2 Stop)
29
UCSRB |=(1<<RXCIE); //Das UART_RXD_Complete Complete Interrupt zulassen
30
receive_count=0;
31
32
USART_Transmit('S');//S für Startup senden
33
34
for(;;)
35
  {
36
  Read_Inputs();
37
  if (memcmp(Data_to_send,Data_to_send_old,17))      //Vergleichen, ob sich was geändert hat
38
      {
39
        Send_To_PC(Data_to_send);          //wenn ja, dann an PC senden
40
        memcpy(Data_to_send_old, Data_to_send, 17);  //Und als "gesendet" ablegen
41
        Data_to_send_old[17]=0x00;          //Das "Mogelbyte" zurücksetzen
42
        Data_to_send[17]=0x00;            //hier auch
43
      }
44
45
// if (memcmp(Data_output,Data_output_old,16))
46
//    {
47
//       Write_Outputs();  //wenn neue output-daten, dann erneuern
48
//       memcpy(Data_output_old, Data_output, 16);//Output_old setzen
49
//    }
50
  }
51
}
52
53
//*******************************************//
54
//****************Deklarationen**************//
55
//*******************************************//
56
57
58
//********************************************//
59
//**Daten vom Input-Schieberegister einlesen**//
60
//********************************************//
61
62
//PORT C steuert das Schieberegister:
63
//PIN C0 als Input an Serial out QH
64
//PIN C1 als Clock
65
//PIN C2 als Parallel Load/Shift schalter am Register (0=Load, 1=Schieben) 
66
67
int Read_Inputs(void)
68
        
69
  {
70
    int i=0;
71
    int a=0;
72
    PORTC &= ~(1<<Input_Load_Shift);  //Low setzen damit geladen wird
73
    PORTC |= (1<<Input_Load_Shift);    //und wieder High
74
75
76
    while (a <16)
77
      {
78
        while(i<8)
79
        {  
80
          Data_to_send[a] &= ~(1<<i);      //BIr erst löschen
81
          Data_to_send[a] |= ((Pin_Input)<<i);//und 1 oder 0 setzen
82
          PORTC |= (1<<Input_Clock);       // Clock Flanke erzeugen um Register um eine Stelle zu schieben
83
          PORTC &= (0<<Input_Clock);       //Clock wieder löschen
84
          i++;                   //i erhöhen
85
        }
86
        i=0;                  //i löschen
87
        a++;                  //a erhöhen
88
      }
89
90
  }
91
92
93
94
95
96
//*******************************************//
97
//***********Daten an PC senden**************//
98
//*******************************************//
99
100
int Send_To_PC(unsigned char data[])
101
  {
102
    int i=0;
103
    while(i<16)              //bis alle Inhalte gesendet sind
104
    {
105
      USART_Transmit(data[i]);    //schickte je einen array-inhalt raus
106
      i++;              //erhöhe i
107
    }
108
109
  }

von Peter D. (peda)


Lesenswert?

Phillip Hommel wrote:

>
1
>           PORTC &= (0<<Input_Clock);       //Clock wieder löschen
2
>

Wat dat denn?


Peter


P.S.:
- Funktionen ohne Returnwert als void
- nicht unnötig Speicherplatz verschwenden (Zähler bis 16 müssen kein 
int sein, da reicht unsigned char).

von helmi (Gast)


Lesenswert?

Ich habe deine einlese Routine mal ein bisschen umgeschrieben.
Ist dadurch etwas kürzerer Code und etwas einfacher zu lesen.

Bitte probier es mal aus ob es klappt

Gruss Helmi

int Read_Inputs(void)
{
    int i;
    int a;

    PORTC &= ~(1<<Input_Load_Shift);  //Low setzen damit geladen wird
    PORTC |= (1<<Input_Load_Shift);    //und wieder High


  for(a=0;a<16;a++)
    for(i=0;i<8;i++)
    {
      Data_to_send[a] <<=1;
      if(PINC & (1<<PINC0)) Data_to_send[a] |= 1;
      PORTC |= (1<<Input_Clock);       // Clock Flanke erzeugen um 
Register um eine Stelle zu schieben
      PORTC &= (0<<Input_Clock);       //Clock wieder löschen
     }

}

von helmi (Gast)


Lesenswert?

Korregierter Code

void Read_Inputs(void)
{
    unsigned char i,a;

    PORTC &= ~(1<<Input_Load_Shift);  //Low setzen damit geladen wird
    PORTC |= (1<<Input_Load_Shift);    //und wieder High


  for(a=0;a<16;a++)
    for(i=0;i<8;i++)
    {
      Data_to_send[a] <<=1;
      if(PINC & (1<<PINC0)) Data_to_send[a] |= 1;
      PORTC |= (1<<Input_Clock);       // Clock Flanke erzeugen um 
Register um eine Stelle zu schieben
      PORTC &= ~(1<<Input_Clock);       //Clock wieder löschen
     }

}

von Peter D. (peda)


Lesenswert?

helmi wrote:
> Ich habe deine einlese Routine mal ein bisschen umgeschrieben.

und den Fehler drin gelassen.


Peter


P.S.:
Mit Bitfeldern wär das nicht passiert:
Beitrag "Schieberegister-LCD vereinfachen"
15. Beitrag.

von Phillip H. (philharmony)


Lesenswert?

Das mit den Bitfeldern muß ich mir nochmal genauer zu Gemüte führen, ich 
verstehe es grade noch nicht.
Was aber den alten Text angeht: die PORTC &= (0<<Input_Clock);  war 
natürlich totaler Humbug, mit der Korrektur funzt es wunderbar...schön 
wenn Probleme so leicht gelöst werden können ;)

>Funktionen ohne Returnwert als void

Wie genau?
1
void Read_Inputs(void) 
2
{
3
(...)
4
}

gibt ne Fehlermeldung im Compiler...

von Helmi (Gast)


Lesenswert?

Du must dem Compiler an anfang einen sogenannten Prototype deiner 
Funktion mitgeben.

Bevor du eine Funktion aufrufst in deinem Programm must dem Compiler 
bekannt sein wie die Funktion aussieht.

Dazu gibt es 2 Moeglichkeiten.

1. Du stellst deine Funktion im Source Code vor dem 1. Aufruf.
   also so:
   void Read_Inputs(void)
   {
      blabla;
   }
   void main(void)
   {
     Read_Inputs();
   }


2. oder du Definierst deine Funktion am Anfang deines Programms

   void Read_Inputs(void);

   void main(void)
   {
      Read_Inputs();
   }

   void Read_Inputs(void)
   {
     blabal;
   }

So weiss der Compiler vor dem 1. Aufruf der Funktion wie der 
Rueckgabewert uebergeben wird. Wenn du es nicht machst nimmt er als 
default wert den Rueckgabetype int an.

Normal wird die Methode 2 benutzt. Diese Prototype kannst du dann in 
einer Headerdatei legen und koennen dann auch in anderen Programmmodulen 
benutz werden.

Gruss Helmi

von Phillip H. (philharmony)


Lesenswert?

aaaaah, so geht das, jetzt versteh ich auch manche Quelltexte bei denen 
ich genau das schon ein paar mal gesehen habe.
Mal ausprobieren wieviel Platz das spart.
Muß eigentlich in einer Headerdatei was bestimmtes drinstehen? 
Bestimmtes Format oder sowas? Oder durchsucht er diese Dateien einfach 
als wäre es ein Teil vom "Haupt-Quelltext"?

von Helmi (Gast)


Lesenswert?

Nein er durchsucht sie wie der Haupttext
wird ja auch nur ueber Include eingebunden.

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.