Forum: Mikrocontroller und Digitale Elektronik Bit verloren/zu viel - Schieberegister - AVR


von Jon (Gast)


Lesenswert?

Hallo Gemeinde,
ein Kollege und meine Wenigkeit verzweifeln almählich. Können uns den 
Fehler nicht erklären und obwohl wir das Projekt schon ein paar Tage 
Ruhe gegönnt haben finden wir den fehler noch immer nicht.

Der Aufbau:
Wir haben 12 Schieberegister hardwaremäßig an einem mega16. An den 74595 
sind dann ULN2803 diese treiben dann LED's. Hardwaretechnisch sollte 
alles passen (mehrmals durchgemessen)

Der Fehler:
Wir können verschiedenen Zahlen "rausschiften" und diese werden auch 
angezeigt. Mit einer Eigenschaft Qa (Pin15 vom 74595) leuchtet 
dauerhaft. Allerdings nicht nur bei einem Schiftregitser. Zusätzlich 
scheinen die Bits allerdings auch um eins verschoben. Folgendes soll das 
Problem verdeutlichen.

0x00
0000 0001

0x01
0000 0011

0x02
0000 0101

0x03
0000 0111

0x04
0000 1001

Folgender Code wird benutzt (stört euch nicht an den auskommentierten 
Zeilen das sind verzweifelte Versuch den Karren aus dem Dreck zu ziehen)
1
/*
2
 * Test_Schieberegister.c
3
 *
4
 * Created: 11.11.2011 20:39:27
5
 *  Author: ---
6
 */ 
7
8
9
#include "main.h"
10
#include <avr/interrupt.h>
11
unsigned char serpa[SERPA_SIZE]={0x01,0x02,0x03,0x04,0x05,0x06,0x01,0x02,0x03,0x04,0x00,0};
12
volatile unsigned int zaehler=0;
13
volatile unsigned char zaehler_1=0;
14
  
15
//ISR (TIMER2_OVF_vect)
16
//{
17
  //zaehler++;
18
  //if (zaehler>250)
19
  //{
20
    //zaehler_1++;
21
    //zaehler=0;
22
  //}
23
  //TCNT2 = 0;
24
//}
25
26
int main(void)
27
{
28
DDRA   =0b11111111;
29
PORTA |=0b00000000;  
30
31
DDRC   =0b11000000;
32
PORTC |=0b00111111;
33
34
DDRD   =0b01000111;
35
PORTD |=0b10111000;
36
37
serpa_init();
38
39
40
//T2
41
//TIMSK |= (1<<TOIE2);    //Timer Overflow  
42
//TCNT2 = 0;
43
//TCCR2 |= (1<<CS22);      //256 Prescaler
44
//TCCR2 |= (1<<CS21);      //256 Prescaler
45
//sei();
46
47
    while(1)
48
    {
49
       
50
     serpa_out();    
51
     
52
     if (PIND&=(1<<TASTER_1)) PORTD &=~(1<<SR_RESET);
53
     else PORTD |=(1<<SR_RESET);
54
     if (PIND&=(1<<TASTER_2)) PORTD &=~(1<<SR_ENABLE);
55
     else PORTD |=(1<<SR_ENABLE);
56
     // auch hier haben wir schon gespielt hat auch nicht geholfen
57
      
58
     
59
     //serpa[11]=zaehler_1;
60
     
61
//for (int i=0;i<SERPA_SIZE;i++)
62
//{
63
  //unsigned char merker_byte=0b00000000;
64
  //unsigned char zwischenspeicher=0b00000000;
65
  //
66
  //zwischenspeicher=serpa[i];
67
  //merker_byte=zwischenspeicher & 0b00000001;
68
  //merker_byte=merker_byte<<7;
69
  //serpa[i]=serpa[i]>>1;
70
  //serpa[i]=serpa[i]|merker_byte;
71
//}
72
73
74
    }
75
  
76
  return 0;
77
}

das ist die "Rausshift" Funktion
1
void serpa_init (void)
2
{
3
   DDRB |= (1<<PB5); 
4
   DDRB |= (1<<PB7);
5
   DDRB |= (1<<PB4); 
6
   PORTB |= (1<<PB4);
7
8
   // !!! SS muss OUT sein, damit SPI nicht in Slave-Mode wechselt !!! 
9
   // entfaellt, falls PORT_RCK = PORT_SS 
10
   //MAKE_OUT (PORT_SS);
11
12
   // SPI als Master 
13
   // High-Bits zuerst 
14
   // SCK ist HIGH wenn inaktiv 
15
   SPCR = (1 << SPE) | (1 << MSTR) | (1 << CPOL);
16
  
17
   // pullup an MISO vermeidet Floaten 
18
   PORTB |= (1<<PB6);
19
20
   // maximale Geschwindigkeit: F_CPU / 2 
21
   SPSR |= (1 << SPI2X);
22
}
23
24
void serpa_out (void)
25
{
26
   unsigned char anz = SERPA_SIZE;
27
   unsigned char* serp = serpa+SERPA_SIZE;
28
29
   do
30
   {
31
      unsigned char data = *--serp;
32
33
      // SPDR schreiben startet Uebertragung 
34
      SPDR = data;
35
36
      // warten auf Ende der Uebertragung für dieses Byte 
37
      while (!(SPSR & (1 << SPIF)));
38
39
      // clear SPIF durch Lesen von SPDR 
40
      SPDR;
41
   }
42
   while (--anz > 0);
43
44
   // Strobe an RCK bringt die Daten von den Schieberegistern in die Latches 
45
   PORTB &= ~(1<<PB4);
46
   PORTB |= (1<<PB4);
47
}

Öffnet uns die Augen!
Gruß Jon

PS: Schaltplan kann ich wenn benötigt auch noch posten.

von Stefan (Gast)


Lesenswert?

Hallo,

CPOL und/oder CPHA passen nicht !!!

Der 74595 übernimmt die Daten bei aufsteigender Flanke, also mussen die 
Daten bei fallender Flanke gesetzt werden !!!

von Stefan (Gast)


Lesenswert?

deutlicher:
es kommt nur mode 0 oder mode 3 in Frage, denn nur da sind bei 
aufsteigender Flanke die Daten stabil.
Da ihr idle=high haben wollt ist es dann mode 3 (CPOL=1, CPHA=1)

fertig

von Jon (Gast)


Lesenswert?

besten Dank - werde es diese Woche mal testen und berichte dann.
Gruß

von Jon (Gast)


Lesenswert?

Nabend,
konnte es dann doch nicht lassen und habe es direkt versucht. Super Tip, 
genau da schien das Problem zu liegen. Die Leds blinken so wie sie 
sollen.
Danke
Gruß Jon

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.