www.mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik schieberegister pwm


Autor: Stk 500 anfänger (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
hallo leute,
bin gerade dabei 3 leds über ein schieberegister (74HC595) anzusteuern. 
dazu hab ich jetzt mal folgendes programm geschrieben:
#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>


//PB0 auf SER, PB1 auf SCK, PB2 auf RCK, PB3 auf SCL, PB4 auf G


ISR(TIMER0_OVF_vect)
{



PORTB |= (1<<PB4);


}


ISR(TIMER0_COMP_vect)
{


PORTB &=~ (1<<PB4);


}



inline uint8_t debounce(volatile uint8_t *port, uint8_t pin)
{
    if ( ! (*port & (1 << pin)) )
    {
        /* Pin wurde auf Masse gezogen, 100ms warten   */
        _delay_ms(50);  // max. 262.1 ms / F_CPU in MHz
        _delay_ms(50); 
        if ( *port & (1 << pin) )
        {
            /* Anwender Zeit zum Loslassen des Tasters geben */
            _delay_ms(50);
            _delay_ms(50); 
            return 1;
        }
    }
    return 0;
}





task_SCK(void)        // Bereitstellen von posiver Flanke an SCK- Eingang
{


  PORTB &=~(1<<PB1);  //SCK auf low

  PORTB |= (1<<PB1);  //SCK auf high


}

task_RCK(void)
{

PORTB &=~ (1<<PB2);    //RCK auf low

PORTB |= (1<<PB2);    //RCK auf high

}



int main(void)
{

DDRB = 0xFF;   //Gesamtes Portregister als Ausgang
DDRD = 0b11110000; // PD0 bis PD3 als Eingang
PORTB = 0b00000000;    //Alle Pins von PortB auf 0
PORTB |= (1<<PB3);    //SCL auf high => Reset von Schieberegister aus



TCCR0 |= (1<<COM01) | (1<<COM00);    // normal mode,  inverting mode
TCCR0 |= (1<<CS02);                //Prescaler auf 256

TIMSK |= (1<<TOIE0) | (1<<OCIE0);    // Interrupt bei Overflow und Compare Match


OCR0= 220;              //Auslösen von Compare Interrupt bei Vergleichswert 128




sei();                //globale Interrupts ein



while(1)
  {

if (debounce(&PIND, PD0))             /* Falls Taster an PIN PD0 gedrueckt..    */
   {

    PORTB |= (1<<PB3);    //Reset Schieberegister aus
    

    PORTB |= (1<<PB0);    //SER high
    task_SCK();

  _delay_ms(3);

  PORTB &=~ (1<<PB0);      //SER low
    task_SCK();

  _delay_ms(3);

  PORTB |= (1<<PB0);      //SER high (101 (QA bis QC))
    task_SCK();
  
  
task_RCK();
  
  }      

    
if (debounce(&PIND, PD1))              //Taster 1 gedrückt(entprellt)
  {  
    

  PORTB &=~(1<<PB3);    // Schieberegister RESET

  

  task_RCK();


  }




  }
  return 0;




}

das mit der PWM funktioniert auch schon ganz wunderbar. allerdings lässt 
sich das Schieberegister beim drücken von Taster 1 nicht löschen.

dass das löschen nicht funktioniert liegt allerdings nicht am 
schieberegister, sondern daran, dass PB3 beim drücken von Taster 1 nicht 
low wird.
ich bin mir ziemlich sicher, dass dieses fehlverhalten in zusammenhang 
mit meinem timer stehen muss. das löschen funktioniert nämlich, wenn ich 
in meinem programm auf das ganze PWM- Prozedere verzichte.

wer kann mir sagen warum das so ist, bzw. was ich machen kann, damit 
mein PB3 beim drücken von Taster 1 low wird wenn ich PWM verwende?

ich hoffe meine beschreibung war verständlich


mfg

Autor: Spezi (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Welcher Controller?  Ein Schaltplan wäre hilfreich.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Da hast keine internen Pullup Widerstände an den Tastern aktiviert.
Benutzt du externe?

Autor: Stk 500 anfänger (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
controller ist ein atmega16 mit eingestellten 8MHZ taktfrequenz. 
angeschlossen hab ich das schieberegister folgendermaßen:

-LED an QA
-LED an QB
-LED an QC
-PB0 auf SER
-PB1 auf SCK
-PB2 auf RCK
-PB3 auf SCL
-PB4 auf G


mfg

Autor: Stk 500 anfänger (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Karl heinz Buchegger schrieb:
> Da hast keine internen Pullup Widerstände an den Tastern aktiviert.
> Benutzt du externe?

ich benutze direkt die taster am stk500.  diese sind an einen pullup 
widerstand von 10K angeschlossen.

mfg

Autor: Spezi (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hier ist das Problem:

> TCCR0 |= (1<<COM01) | (1<<COM00)

Damit schaltest du den Pin OC0 (= PB3) auf PWM-Ausgang.
Da du diesen Hardware-PWM-Pin nicht verwendest, sondern PB4 in den ISRs 
einstellst, können die 2 Bits auf 0 bleiben. Dann klappt es auch mit dem 
Reset-Pin.
Oder du tauscht die Pins PB3 und PB4 in der Funktion. Dann ist PB3 der 
PWM-Ausgang, und bei richtiger Konfiguration des Timers sind die beiden 
ISRs nicht mehr notwendig (da alles in Hardware abläuft).

Achte auf den Plan des Schieberegisters: sein Reset-Pin wirkt nur auf 
das Schieberegister selbst, nicht auf die Ausgangsregister. Um die 
zurückzusetzen, ist nach dem Reset noch ein RCK-Impuls nötig.

Autor: Stk 500 anfänger (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Spezi schrieb:
> Hier ist das Problem:
>
>> TCCR0 |= (1<<COM01) | (1<<COM00)
>
> Damit schaltest du den Pin OC0 (= PB3) auf PWM-Ausgang.
> Da du diesen Hardware-PWM-Pin nicht verwendest, sondern PB4 in den ISRs
> einstellst, können die 2 Bits auf 0 bleiben. Dann klappt es auch mit dem
> Reset-Pin.

Respekt. jetzt funktioniert es. ich dachte ich muss die zwei bits 
setzen, weil im AVR- tutorial steht, dass man invertierendes PWM 
benutzen soll.

mfg

Autor: Spezi (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

> ich dachte ich muss die zwei bits setzen, weil im AVR- tutorial steht

Da hilft das Konsultieren des Controller-Datenblattes; es ist immer von 
Vorteil, nicht nur fertigen Code zu kopieren, sondern auch dessen 
Funktion zu verstehen ...   :-)

Autor: Stk 500 anfänger (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Spezi schrieb:
> Da hilft das Konsultieren des Controller-Datenblattes; es ist immer von
> Vorteil, nicht nur fertigen Code zu kopieren, sondern auch dessen
> Funktion zu verstehen ...   :-)

das habe ich schon gemacht. fertigen code kopieren ohne ihn zu verstehen 
ist auch gar nicht mein ziel. nur bestimmte dinge, wie das jetzt hier, 
muss man halt fast schon einmal ausprobiert haben um sie zu verstehen.

mfg

Autor: Stk 500 anfänger (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
so, jetzt hab ich mein schieberegister- programm zu einem programm mit 
lauflicht erweitert:
#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>


//PB0 auf SER, PB1 auf SCK, PB2 auf RCK, PB3 auf SCL, PB4 auf G

uint16_t Lauflicht;

ISR(TIMER0_OVF_vect)
{



PORTB |= (1<<PB4);


}


ISR(TIMER0_COMP_vect)
{


PORTB &=~ (1<<PB4);


}



inline uint8_t debounce(volatile uint8_t *port, uint8_t pin)
{
    if ( ! (*port & (1 << pin)) )
    {
        /* Pin wurde auf Masse gezogen, 100ms warten   */
        _delay_ms(50);  // max. 262.1 ms / F_CPU in MHz
        _delay_ms(50); 
        if ( *port & (1 << pin) )
        {
            /* Anwender Zeit zum Loslassen des Tasters geben */
            _delay_ms(50);
            _delay_ms(50); 
            return 1;
        }
    }
    return 0;
}


void long_delay(uint16_t ms)
{

for(;ms >0; ms--)
  {

  _delay_ms(1);


  }


}


task_SCK(void)        // Bereitstellen von posiver Flanke an SCK- Eingang
{


  PORTB &=~(1<<PB1);  //SCK auf low

  PORTB |= (1<<PB1);  //SCK auf high


}

task_RCK(void)
{

PORTB &=~ (1<<PB2);    //RCK auf low

PORTB |= (1<<PB2);    //RCK auf high

}







int main(void)
{

DDRB = 0xFF;   //Gesamtes Portregister als Ausgang
DDRD = 0b11110000; // PD0 bis PD3 als Eingang
PORTB = 0b00000000;    //Alle Pins von PortB auf 0
PORTB |= (1<<PB3);    //SCL auf high => Reset von Schieberegister aus




TCCR0 |= (1<<CS02);                //Prescaler auf 256

TIMSK |= (1<<TOIE0) | (1<<OCIE0);    // Interrupt bei Overflow und Compare Match


OCR0= 220;              //Auslösen von Compare Interrupt bei Vergleichswert 128




sei();                //globale Interrupts ein



while(1)
{

if (debounce(&PIND, PD0))             /* Falls Taster an PIN PD0 gedrueckt..    */
   {
  Lauflicht = 1;
  }  


if (debounce(&PIND, PD1))             //lauflicht abbrechen mit taster1
  {  
  
  Lauflicht = 0;

  PORTB &=~(1<<PB3);    // Schieberegister RESET

  

  task_RCK();
  
  
  }  



    if(Lauflicht ==1)
    {
  PORTB |= (1<<PB3);      //RESET aus

    PORTB |= (1<<PB0);    //SER  high , LED1 an
    task_SCK();

    task_RCK();

  long_delay(100);

  

  PORTB &=~ (1<<PB0);      //SER low, LED2 an
    task_SCK();
    task_RCK();

  long_delay(100);
  PORTB &=~ (1<<PB0);
    task_SCK();        //LED3an
    task_RCK();

  long_delay(100);    //LED4an
  PORTB &=~ (1<<PB0);
    task_SCK();
    task_RCK();

  long_delay(100);      //LED5an
  PORTB &=~ (1<<PB0);
    task_SCK();
    task_RCK();

  long_delay(100);      //LED6an
  PORTB &=~ (1<<PB0);
    task_SCK();
    task_RCK();

long_delay(100);      //LED7an
  PORTB &=~ (1<<PB0);
    task_SCK();
    task_RCK();

long_delay(100);      //LED8an
  PORTB &=~ (1<<PB0);
    task_SCK();
    task_RCK();

long_delay(100);
  PORTB &=~ (1<<PB0);
    task_SCK();
    task_RCK();


PORTB &=~ (1<<PB3);      //Schieberegister RESET

if(Lauflicht ==0)
  break;

    }

    

    


     
}
    

  return 0;




}

das mit dem lauflicht funktioniert soweit. allerdings würde mich 
interessieren, warum ich ins schieberegister 8 mal eine 0 reinschieben 
muss, damit das lauflicht bis zur 8. led läuft.
kann mir jemand erklären warum? hab schon im datenblatt und wiki 
nachgeforscht aber keinen grund gefunden.

dann habe ich noch ein anderes problem. und zwar möchte ich das 
lauflicht mit taster1(an PD1) abbrechen. doch leider läuft das lauflicht 
bisher beim drücken von taster1 ungehindert weiter.
es scheint mir so als würde das lauflicht die abbfrage von taster1 
blockieren.
an was liegt das bzw. wie kann ich dieses problem umgehen?

mfg

Autor: Stk 500 anfänger (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
.............................................

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Stk 500 anfänger schrieb:

> das mit dem lauflicht funktioniert soweit. allerdings würde mich
> interessieren, warum ich ins schieberegister 8 mal eine 0 reinschieben
> muss, damit das lauflicht bis zur 8. led läuft.

Was passiert denn wenn du eine 1 reinschreibst :-)
Welchen Schluss ziehst du daraus, wie ein Schieberegister eigentlich 
arbeitet.

> hab schon im datenblatt und wiki
> nachgeforscht aber keinen grund gefunden.

wie wärs mit ein bischen Nachdenken. Aus der Funktionsweise eines 
Schieberegisters ergibt sich völlig logisch warum das so ist.


schreibs einfacher so
int main(void)
{
  uint8_t i;

....

    if(Lauflicht ==1)
    {
      PORTB |= (1<<PB3);      //RESET aus

      PORTB |= (1<<PB0);    //SER  high , LED1 an
      task_SCK();
      task_RCK();

      for( i = 0; i < 8; ++i )
      {
        long_delay(100);

        PORTB &=~ (1<<PB0);      //SER low, LED2 an
        task_SCK();
        task_RCK();
      }

      PORTB &=~ (1<<PB3);      //Schieberegister RESET

      if(Lauflicht ==0)
        break;
    }
}

genau dafür wurden Schleifen erfunden, damit man nicht alles x-mal 
wiederholen muss. Dann kannst du auch einfacher experimentieren, indem 
du nur an einer Stelle die Anweisung ändern musst um anstelle einer 0 
lauter 1 nachzuschieben.

und achte ein wenig mehr auf deine Codeformatierung. Die ist ja 
grauenhaft.

> es scheint mir so als würde das lauflicht die abbfrage von taster1
> blockieren.

Nope.
Du hast einen Programmfehler bzw. einen Designfehler. Damit ein 
Tastendruck dein Lauflichtr jederzeit unterbrechen kann, musst du den 
ganzen Aufbau komplett anders gestalten. Im Moment registriert dein 
Programm einen Tastendruck nur dann, wenn genau zum Zeitpunkt, an dem es 
hier angelangt ist
if (debounce(&PIND, PD1))             //lauflicht abbrechen mit taster1
  {  
  
  Lauflicht = 0;

  PORTB &=~(1<<PB3);    // Schieberegister RESET

  

  task_RCK();
  
  
  }  

die Taste an PD1 gedrückt ist. Wenn dein Programm aber die meiste Zeit 
mit den _delay_ms rumtrödelt, kommt es lange nicht an diese Stelle. 
Drück doch mal den Taster und halte ihn gedrückt.




Fang an deinen Code besser zu formatieren. Viele, viele Leerzeilen 
ziehen den Code nur in die Länge, bringen aber nicht mehr Übersicht.

Autor: Stk 500 anfänger (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
jetzt hab ich den code mal so geändert, wie du mir vorgeschlagen hast:
#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>


//PB0 auf SER, PB1 auf SCK, PB2 auf RCK, PB3 auf SCL, PB4 auf G

uint16_t Lauflicht;

ISR(TIMER0_OVF_vect)
{



PORTB |= (1<<PB4);


}


ISR(TIMER0_COMP_vect)
{


PORTB &=~ (1<<PB4);


}



inline uint8_t debounce(volatile uint8_t *port, uint8_t pin)
{
    if ( ! (*port & (1 << pin)) )
    {
        /* Pin wurde auf Masse gezogen, 100ms warten   */
        _delay_ms(50);  // max. 262.1 ms / F_CPU in MHz
        _delay_ms(50); 
        if ( *port & (1 << pin) )
        {
            /* Anwender Zeit zum Loslassen des Tasters geben */
            _delay_ms(50);
            _delay_ms(50); 
            return 1;
        }
    }
    return 0;
}


void long_delay(uint16_t ms)
{

for(;ms >0; ms--)
  {

  _delay_ms(1);


  }


}


task_SCK(void)        // Bereitstellen von posiver Flanke an SCK- Eingang
{


  PORTB &=~(1<<PB1);  //SCK auf low

  PORTB |= (1<<PB1);  //SCK auf high


}

task_RCK(void)
{

PORTB &=~ (1<<PB2);    //RCK auf low

PORTB |= (1<<PB2);    //RCK auf high

}







int main(void)
{

DDRB = 0xFF;   //Gesamtes Portregister als Ausgang
DDRD = 0b11110000; // PD0 bis PD3 als Eingang
PORTB = 0b00000000;    //Alle Pins von PortB auf 0
PORTB |= (1<<PB3);    //SCL auf high => Reset von Schieberegister aus




TCCR0 |= (1<<CS02);                //Prescaler auf 256

TIMSK |= (1<<TOIE0) | (1<<OCIE0);    // Interrupt bei Overflow und Compare Match


OCR0= 220;              //Auslösen von Compare Interrupt bei Vergleichswert 128




sei();                //globale Interrupts ein

uint8_t i;


while(1)
{

if (debounce(&PIND, PD0))             /* Falls Taster an PIN PD0 gedrueckt..    */
   {
  Lauflicht = 1;
  }  


if (debounce(&PIND, PD1))
  {  
  
  Lauflicht = 0;

  PORTB &=~(1<<PB3);    // Schieberegister RESET

  

  task_RCK();
  
  
  }  



    if(Lauflicht ==1)
    {
  
    PORTB |= (1<<PB3);    //RESET aus

    PORTB |= (1<<PB0);    //SER high

    task_SCK();
    task_RCK();


      for(i=0; i<8; i++)
        {

        long_delay(100);

        PORTB &=~ (1<<PB0);    //SER low
        task_SCK();
        task_RCK();


        }

    PORTB &=~ (1<<PB3);    //RESET
    

    }

  if(Lauflicht ==0)
  break;
     

}  

  return 0;




}

allerdings geht jetzt nicht mal mehr das lauflicht. hab ich noch 
irgendwas vergessen zu ändern?

mfg

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Weiß ich nicht.
Solange du jetzt nicht anfängst deinen Code ein wenig übersichtlicher 
und durchschaubarer zu formatieren, weigere ich mich, mir den noch 
länger anzusehen.

Autor: Falk Brunner (falk)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@  Stk 500 anfänger (Gast)

>jetzt hab ich den code mal so geändert, wie du mir vorgeschlagen hast:

Lies mal was über Netiquette. Längere Quelltexte gehören in den 
Anhang.

MFG
Falk

Autor: Stk 500 anfänger (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Karl heinz Buchegger schrieb:
> Weiß ich nicht.
> Solange du jetzt nicht anfängst deinen Code ein wenig übersichtlicher
> und durchschaubarer zu formatieren, weigere ich mich, mir den noch
> länger anzusehen.
>
>
>
>
>
>     Beitrag melden | Bearbeiten | Löschen |

#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>


//PB0 auf SER, PB1 auf SCK, PB2 auf RCK, PB3 auf SCL, PB4 auf G

uint16_t Lauflicht;

ISR(TIMER0_OVF_vect)
{



PORTB |= (1<<PB4);


}


ISR(TIMER0_COMP_vect)
{


PORTB &=~ (1<<PB4);


}



inline uint8_t debounce(volatile uint8_t *port, uint8_t pin)
{
    if ( ! (*port & (1 << pin)) )
    {
        /* Pin wurde auf Masse gezogen, 100ms warten   */
        _delay_ms(50);  // max. 262.1 ms / F_CPU in MHz
        _delay_ms(50); 
        if ( *port & (1 << pin) )
        {
            /* Anwender Zeit zum Loslassen des Tasters geben */
            _delay_ms(50);
            _delay_ms(50); 
            return 1;
        }
    }
    return 0;
}


void long_delay(uint16_t ms)
{

for(;ms >0; ms--)
  {

  _delay_ms(1);


  }


}


task_SCK(void)        // Bereitstellen von posiver Flanke an SCK- Eingang
{


  PORTB &=~(1<<PB1);  //SCK auf low

  PORTB |= (1<<PB1);  //SCK auf high


}

task_RCK(void)
{

PORTB &=~ (1<<PB2);    //RCK auf low

PORTB |= (1<<PB2);    //RCK auf high

}







int main(void)
{

DDRB = 0xFF;   //Gesamtes Portregister als Ausgang
DDRD = 0b11110000; // PD0 bis PD3 als Eingang
PORTB = 0b00000000;    //Alle Pins von PortB auf 0
PORTB |= (1<<PB3);    //SCL auf high => Reset von Schieberegister aus




TCCR0 |= (1<<CS02);                //Prescaler auf 256

TIMSK |= (1<<TOIE0) | (1<<OCIE0);    // Interrupt bei Overflow und Compare Match


OCR0= 220;              //Auslösen von Compare Interrupt bei Vergleichswert 128




sei();                //globale Interrupts ein

uint8_t i;

while(1)
{

    if (debounce(&PIND, PD0))             /* Falls Taster an PIN PD0 gedrueckt..    */
       {
        Lauflicht = 1;
        }  


      if (debounce(&PIND, PD1))             //lauflicht abbrechen mit taster1
        {   
          Lauflicht = 0;
          PORTB &=~(1<<PB3);    // Schieberegister RESET
          task_RCK();  
         }  



            if(Lauflicht ==1)
          {
            PORTB |= (1<<PB3);      //RESET aus

              PORTB |= (1<<PB0);    //SER  high , LED1 an
              task_SCK();
            task_RCK();

            long_delay(100);

              for(i=0; i<8; i++)
            {
     
             long_delay(100);

                PORTB &=~ (1<<PB0);      //SER low, LED2 an
                task_SCK();
                task_RCK();



            }


            PORTB &=~ (1<<PB3);      //Schieberegister RESET

          }


    if(Lauflicht ==0)
      break;

}
     

    

  return 0;

}


für mich zur übung und natürlich auch für dich. ich hoffe nun ist der 
code besser zu lesen.

mfg

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Stk 500 anfänger schrieb:

> für mich zur übung und natürlich auch für dich. ich hoffe nun ist der
> code besser zu lesen.

Nein. Ist er nicht.
Er ist immer noch so grauenhaft wie vorher.

Autor: Stk 500 anfänger (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Karl heinz Buchegger schrieb:
> Stk 500 anfänger schrieb:
>
>> für mich zur übung und natürlich auch für dich. ich hoffe nun ist der
>> code besser zu lesen.
>
> Nein.
>
>
>
>
>
>     Beitrag melden | Bearbeiten | Löschen |


so vielleicht:
#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>


//PB0 auf SER, PB1 auf SCK, PB2 auf RCK, PB3 auf SCL, PB4 auf G

uint16_t Lauflicht;

ISR(TIMER0_OVF_vect)
{
PORTB |= (1<<PB4);
}

    ISR(TIMER0_COMP_vect)
    {
    PORTB &=~ (1<<PB4);
    }

inline uint8_t debounce(volatile uint8_t *port, uint8_t pin)
{
    if ( ! (*port & (1 << pin)) )
    {
        /* Pin wurde auf Masse gezogen, 100ms warten   */
        _delay_ms(50);  // max. 262.1 ms / F_CPU in MHz
        _delay_ms(50); 
        if ( *port & (1 << pin) )
        {
            /* Anwender Zeit zum Loslassen des Tasters geben */
            _delay_ms(50);
            _delay_ms(50); 
            return 1;
        }
    }
    return 0;
}

void long_delay(uint16_t ms)
{

for(;ms >0; ms--)
  {

  _delay_ms(1);


  }


}

    task_SCK(void)        // Bereitstellen von posiver Flanke an SCK- Eingang
    {
        PORTB &=~(1<<PB1);  //SCK auf low
        PORTB |= (1<<PB1);  //SCK auf high
    }

      task_RCK(void)
      {
        PORTB &=~ (1<<PB2);    //RCK auf low
        PORTB |= (1<<PB2);    //RCK auf high
      }

int main(void)
{

DDRB = 0xFF;   //Gesamtes Portregister als Ausgang
DDRD = 0b11110000; // PD0 bis PD3 als Eingang
PORTB = 0b00000000;    //Alle Pins von PortB auf 0
PORTB |= (1<<PB3);    //SCL auf high => Reset von Schieberegister aus

TCCR0 |= (1<<CS02);                //Prescaler auf 256
TIMSK |= (1<<TOIE0) | (1<<OCIE0);    // Interrupt bei Overflow und Compare Match

OCR0= 220;              //Auslösen von Compare Interrupt bei Vergleichswert 128

sei();                //globale Interrupts ein

uint8_t i;

  while(1)
  {

    if (debounce(&PIND, PD0))             /* Falls Taster an PIN PD0 gedrueckt..    */
       {
        Lauflicht = 1;
        }  


      if (debounce(&PIND, PD1))             //lauflicht abbrechen mit taster1
        {   
          Lauflicht = 0;
          PORTB &=~(1<<PB3);    // Schieberegister RESET
          task_RCK();  
         }  



            if(Lauflicht ==1)
          {
            PORTB |= (1<<PB3);      //RESET aus

              PORTB |= (1<<PB0);    //SER  high , LED1 an
              task_SCK();
            task_RCK();

            long_delay(100);

                for(i=0; i<8; i++)
              {
                 long_delay(100);
                    PORTB &=~ (1<<PB0);      //SER low, LED2 an
                    task_SCK();
                    task_RCK();
              }


            PORTB &=~ (1<<PB3);      //Schieberegister RESET

        }


    if(Lauflicht ==0)
      break;

  }
     
  return 0;

}

zufrieden?

mfg

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Stk 500 anfänger schrieb:

> zufrieden?
>

Nein.

Was ist so schwer daran, ein konsitentes Einrückschema durchzuziehen?
Bei einer { gehts um 2 Leerzeichen nach rechts, bei einem } gehts wieder 
um 2 Leerzeichen nach links. Un dabgesehen davon stehen alle anderen 
Ding in ihrer jeweiligen Einrückstufe untereinander.

Dann kann man nämlich ganz leicht erkennen, welche Dinge 
zusammengehören, wo Schleifen anfangen und wo sie aufhören, welche Teile 
innerhalb einer Schleife sind, welche Programmteile von einem if 
abhängen und welche nicht.

Wenn ich wissen will, welche Programmteile zusammen einen Block bilden, 
schau ich einfach wo die zugehörigen { } eine Einrückebene weiter links 
sind und weiss es.

Wenigstens die Unmengen an Leerzeilen hast du zum größten Teil entfernt
#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>

//PB0 auf SER, PB1 auf SCK, PB2 auf RCK, PB3 auf SCL, PB4 auf G

uint16_t Lauflicht;
 
ISR(TIMER0_OVF_vect)
{
  PORTB |= (1<<PB4);
}
 
ISR(TIMER0_COMP_vect)
{
  PORTB &=~ (1<<PB4);
}
 
inline uint8_t debounce(volatile uint8_t *port, uint8_t pin)
{
  if ( ! (*port & (1 << pin)) )
  {
    /* Pin wurde auf Masse gezogen, 100ms warten   */
    _delay_ms(50);  // max. 262.1 ms / F_CPU in MHz
    _delay_ms(50);
    if ( *port & (1 << pin) )
    {
      /* Anwender Zeit zum Loslassen des Tasters geben */
      _delay_ms(50);
      _delay_ms(50);
      return 1;
    }
  }
  return 0;
}
 
void long_delay(uint16_t ms)
{
  for(;ms >0; ms--)
  {
    _delay_ms(1);
  }
}
 
void task_SCK(void)        // Bereitstellen von posiver Flanke an SCK-Eingang
{
  PORTB &=~(1<<PB1);  //SCK auf low
  PORTB |= (1<<PB1);  //SCK auf high
}
 
void task_RCK(void)
{
  PORTB &=~ (1<<PB2);    //RCK auf low
  PORTB |= (1<<PB2);    //RCK auf high
}
 
int main(void)
{
  DDRB = 0xFF;   //Gesamtes Portregister als Ausgang
  DDRD = 0b11110000; // PD0 bis PD3 als Eingang
  PORTB = 0b00000000;    //Alle Pins von PortB auf 0
  PORTB |= (1<<PB3);    //SCL auf high => Reset von Schieberegister aus
  
  TCCR0 |= (1<<CS02);                //Prescaler auf 256
  TIMSK |= (1<<TOIE0) | (1<<OCIE0);    // Interrupt bei Overflow und  Compare Match
 
  OCR0= 220;              //Auslösen von Compare Interrupt bei  Vergleichswert 128
 
  sei();                //globale Interrupts ein
 
  uint8_t i;
 
  while(1)
  {
    if (debounce(&PIND, PD0))             /* Falls Taster an PIN PD0  gedrueckt..    */
    {
      Lauflicht = 1;
    }
 
    if (debounce(&PIND, PD1))             //lauflicht abbrechen mit taster1
    {
      Lauflicht = 0;
      PORTB &=~(1<<PB3);    // Schieberegister RESET
      task_RCK();
    }

    if(Lauflicht ==1)
    {
      PORTB |= (1<<PB3);      //RESET aus
      PORTB |= (1<<PB0);    //SER  high , LED1 an
      task_SCK();
      task_RCK();

      long_delay(100);
 
      for(i=0; i<8; i++)
      {
        long_delay(100);
        PORTB &=~ (1<<PB0);      //SER low, LED2 an
        task_SCK();
        task_RCK();
      }

      PORTB &=~ (1<<PB3);      //Schieberegister RESET
    }

    if(Lauflicht ==0)
      break;
  }

  return 0;
}

Und jetzt schau mal auf welcher Einrückebene deine Abfrage ganz unten ob 
Lauflicht gleich 0 ist steht und aus welcher Schleife daher 
hinausgebreakt wird. Vom break ausgehen die } in der nächsten 
Ausrückebene aufsuchen ( die } nehm ich weil sie näher liegt). Mit 
dieser Spaltenposition scroll ich dann nach oben, bis ich die zugehörige 
öffnende { in derselben Spalte gefunden habe und direkt darüber steht
  while(1)
also die allumfassende Endlosschleife.
Ist ja interessant, wenn Lauflicht 0 sein sollte (was zb bei 
Programmanfang der Fall ist), wird die Hauptschleife verlassen und dein 
Programm ist zu Ende.

Und das nächste mal machst du deine Einrückungen selber und siehst dann 
auch Fehler anstatt raten zu müssen.

Autor: Stk 500 anfänger (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Karl heinz Buchegger schrieb:
> Was ist so schwer daran, ein konsitentes Einrückschema durchzuziehen?
> Bei einer { gehts um 2 Leerzeichen nach rechts, bei einem } gehts wieder
> um 2 Leerzeichen nach links. Un dabgesehen davon stehen alle anderen
> Ding in ihrer jeweiligen Einrückstufe untereinander.

ich hab immer gedacht, dass ich von oben beginnend jeden block weiter 
nach rechts einrücken muss. aber du beginnst ja die "großen Blöcke" ja 
auch immer wieder von links.
ok, ich glaube jetzt habe ich verstanden wie ich es machen muss.

Karl heinz Buchegger schrieb:
> Ist ja interessant, wenn Lauflicht 0 sein sollte (was zb bei
> Programmanfang der Fall ist), wird die Hauptschleife verlassen und dein
> Programm ist zu Ende.

stimmt du hast recht. jetzt hab ich Lauflicht anfangs den wert 2 
zugewiesen um dieses problem zu umgehen:
#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>

//PB0 auf SER, PB1 auf SCK, PB2 auf RCK, PB3 auf SCL, PB4 auf G

uint16_t Lauflicht= 2;
 
ISR(TIMER0_OVF_vect)
{
  PORTB |= (1<<PB4);
}
 
ISR(TIMER0_COMP_vect)
{
  PORTB &=~ (1<<PB4);
}
 
inline uint8_t debounce(volatile uint8_t *port, uint8_t pin)
{
  if ( ! (*port & (1 << pin)) )
  {
    /* Pin wurde auf Masse gezogen, 100ms warten   */
    _delay_ms(50);  // max. 262.1 ms / F_CPU in MHz
    _delay_ms(50);
    if ( *port & (1 << pin) )
    {
      /* Anwender Zeit zum Loslassen des Tasters geben */
      _delay_ms(50);
      _delay_ms(50);
      return 1;
    }
  }
  return 0;
}
 
void long_delay(uint16_t ms)
{
  for(;ms >0; ms--)
  {
    _delay_ms(1);
  }
}
 
void task_SCK(void)        // Bereitstellen von posiver Flanke an SCK-Eingang
{
  PORTB &=~(1<<PB1);  //SCK auf low
  PORTB |= (1<<PB1);  //SCK auf high
}
 
void task_RCK(void)
{
  PORTB &=~ (1<<PB2);    //RCK auf low
  PORTB |= (1<<PB2);    //RCK auf high
}
 
int main(void)
{
  DDRB = 0xFF;   //Gesamtes Portregister als Ausgang
  DDRD = 0b11110000; // PD0 bis PD3 als Eingang
  PORTB = 0b00000000;    //Alle Pins von PortB auf 0
  PORTB |= (1<<PB3);    //SCL auf high => Reset von Schieberegister aus
  
  TCCR0 |= (1<<CS02);                //Prescaler auf 256
  TIMSK |= (1<<TOIE0) | (1<<OCIE0);    // Interrupt bei Overflow und  Compare Match
 
  OCR0= 220;              //Auslösen von Compare Interrupt bei  Vergleichswert 128
 
  sei();                //globale Interrupts ein
 
  uint8_t i;
 
  while(1)
  {
    if (debounce(&PIND, PD0))             /* Falls Taster an PIN PD0  gedrueckt..    */
    {
      Lauflicht = 1;
    }
 
    if (debounce(&PIND, PD1))             //lauflicht abbrechen mit taster1
    {
      Lauflicht = 0;
      PORTB &=~(1<<PB3);    // Schieberegister RESET
      task_RCK();
    }

    if(Lauflicht ==1)
    {
      PORTB |= (1<<PB3);      //RESET aus
      PORTB |= (1<<PB0);    //SER  high , LED1 an
      task_SCK();
      task_RCK();

      long_delay(100);
 
      for(i=0; i<8; i++)
      {      
        PORTB &=~ (1<<PB0);      //SER low, LED2 an
        task_SCK();
        task_RCK();
    long_delay(100);
    
      }

      PORTB &=~ (1<<PB3);      //Schieberegister RESET

    if(Lauflicht ==0)
      break;
    }

    
  }

  return 0;
}

das lauflicht läuft nun wieder. allerdings funktioniert der abbruch des 
lauflichts(ausgelöst durch
if(Lauflicht ==0)
      break;
) noch immer nicht.if(Lauflicht ==0)
      break;der for- schleife hängt und damit die wahrscheinlichkeit 
relativ gering ist, dass ich genau in dem moment taster1 drücke, wenn 
das programm ihn abfrägt.   ich habe jetzt schon alles probiert. hab 
diesen teil auch schon in die
if(Lauflicht ==0)break;
 auch schon in die for- schleife verschoben aber das lauflicht läuft 
beim drücken von taster1 ungehindert weiter.
irgendwie muss man dieses problem doch umgehen können. was schlägt ihr 
vor?

mfg

Autor: Stk 500 anfänger (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
.........................................

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.