www.mikrocontroller.net

Forum: Compiler & IDEs LED leuchten zu schwach


Autor: Rachid Maoukil (rachid)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
hallo,

bin ein AVR-anfänger.
Ich möchte 3 LED's zum blinken bringen: Erste LED leuchtet z.B. 2s dann 
geht aus dann leuchtet die zweite dann geht sie auch aus dann die die 
Dritte usw...
Das tuts doch aber die Erste LED leuchtet ganz normal, aber dir zweite 
und dritte leuchten sehr schwach dann. Ich würde gern wissen woran es 
liegen könnte.

Ich habe mein Schaltung so: 
http://www.electronic-idea.de/typo3/index.php?id=1...  gebaut
hier ist mein Code:

/***************************************************************************************************
Identifikation *************************************************************************************
***************************************************************************************************/
/*-------------------------------------------------------------------------------------------------
Dateiname:    $Workfile:   test1.c  $
Version:      $Revision:   1.0  $ 
Copyright:    maoukil 
Beschreibung: Geblinkt wird in PortB (push-pull) drei LEDs.
-------------------------------------------------------------------------------------------------*/

/***************************************************************************************************
Includes *******************************************************************************************
***************************************************************************************************/

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

#ifndef SIGNAL
#include <avr/signal.h>
#endif

/*-------------------------------------------------------------------------------------------------
Der MCU-Takt. Wird gebraucht, um Timer1 mit den richtigen
Werten zu initialisieren. Voreinstellung ist 1MHz.
(Werkseinstellung für AVRs mit internem Oszillator).
Das Define wird nur gemacht, wenn F_CPU noch nicht definiert wurde.
F_CPU kann man so auch per Kommandozeile definieren, z.B. für 8MHz:
avr-gcc ... -DF_CPU=8000000
Der Wert von F_CPU hat rein informativen Character für
die korrekte Codeerzeugung im Programm!
Um die Taktrate zu ändern müssen die Fuses des Controllers
und/oder Quarz/Resonator/RC-Glied/Oszillator
angepasst werden!
-------------------------------------------------------------------------------------------------*/
#ifndef F_CPU
#define F_CPU 4000000
#endif

/***************************************************************************************************
Defines und Makros *********************************************************************************
***************************************************************************************************/

/*-------------------------------------------------------------------------------------------------
So viele IRQs (Interrupt Request (IRQ)) werden jede Sekunde ausgelöst.
Für optimale Genauigkeit muss
IRQS_PER_SECOND ein Teiler von F_CPU sein
und IRQS_PER_SECOND ein Vielfaches von 100.
Ausserdem muss gelten F_CPU / IRQS_PER_SECOND <= 65536
-------------------------------------------------------------------------------------------------*/

#define LED_1  0
#define LED_2  1
#define LED_3  2
#define PORT_LED PORTB
#define DDR_LED  DDRB     // DDR: Definiere Port X als Ausgang
#define IRQS_PER_SECOND   2000
#define IRQS_PER_10MS     (IRQS_PER_SECOND / 100) // Anzahl IRQs pro 10 Millisekunden

/***************************************************************************************************
Typdefinitionen ************************************************************************************
***************************************************************************************************/



/***************************************************************************************************
Konstanten *****************************************************************************************
***************************************************************************************************/


/***************************************************************************************************
Applikationsgroessen *******************************************************************************
***************************************************************************************************/


/***************************************************************************************************
Variablen ******************************************************************************************
***************************************************************************************************/

static volatile uint8_t timer_10ms; // Zähler-Variable. Wird in der ISR (Interrupt Service Routine,)  
                  // erniedrigt und in wait_10ms benutzt.

/***************************************************************************************************
Funktionsprototypen für Modul-interne Funktionen ***************************************************
***************************************************************************************************/

void wait_10ms (const uint8_t);
void timer1_init();

/***************************************************************************************************
Hauptprogramm **************************************************************************************
***************************************************************************************************/

int main()
{
    
    DDR_LED  |= (1 << LED_1); // LED-Port auf Ausgang
    
  timer1_init(); // Timer1 initialisieren
    
    sei(); // Interrupts aktivieren

/*-------------------------------------------------------------------------------------------------
Endlosschleife
Die LED ist jeweils 1 Sekunde an und 1 Sekunde aus,
blinkt also mit einer Frequenz von 0.5 Hz
-------------------------------------------------------------------------------------------------*/

    while (1)
    {
        
        PORT_LED |= (1 << LED_1); // LED 1 an
        
        wait_10ms (200); // 1 Sekunde warten
        
        PORT_LED &= ~(1 << LED_1); // LED 1 aus
        
        wait_10ms (200); // 1 Sekunde warten



    PORT_LED |= (1 << LED_2); // LED 2 an
        
        wait_10ms (200); // 1 Sekunde warten
        
        PORT_LED &= ~(1 << LED_2); // LED 2 aus
        
        wait_10ms (200); // 1 Sekunde warten



    PORT_LED |= (1 << LED_3); // LED 3 an
        
        wait_10ms (200); // 1 Sekunde warten
        
        PORT_LED &= ~(1 << LED_3); // LED 3 aus
        
        wait_10ms (200); // 1 Sekunde warten
    }

    // main braucht keine return-Anweisung, weil wir nie hier hin kommen
}


/***************************************************************************************************
Funktionen *****************************************************************************************
***************************************************************************************************/

/*-------------------------------------------------------------------------------------------------
Gültigkeitsprüfung.
Bei ungeeigneten Werten gibt es einen Compilerfehler
-------------------------------------------------------------------------------------------------*/

#if (F_CPU/IRQS_PER_SECOND > 65536) || (IRQS_PER_10MS < 1) || (IRQS_PER_10MS > 255)
#   error Diese Werte fuer F_CPU und IRQS_PER_SECOND
#   error sind ausserhalb des gueltigen Bereichs!
#endif

/*-------------------------------------------------------------------------------------------------
Compiler-Warnung falls die Genauigkeit nicht optimal ist.
Wenn das nervt für deine Werte, einfach löschen :-)
-------------------------------------------------------------------------------------------------*/

#if (F_CPU % IRQS_PER_SECOND != 0) || (IRQS_PER_SECOND % 100 != 0)
#   warning Das Programm arbeitet nicht mit optimaler Genauigkeit.
#endif

// //////////////////////////////////////////////////////////////////////
// Implementierungen der Funktionen
// //////////////////////////////////////////////////////////////////////

#if !defined (TCNT1H)
#error Dieser Controller hat keinen 16-Bit Timer1!
#endif // TCNT1H


/***************************************************************************************************
void timer1_init()  ********************************************************************************
***************************************************************************************************/

/*-------------------------------------------------------------------------------------------------
Timer1 so initialisieren, daß er IRQS_PER_SECOND 
IRQs pro Sekunde erzeugt.
-------------------------------------------------------------------------------------------------*/

void timer1_init()

{
    TCCR1A = 0; // Timer1: keine PWM. TCCR1A Timer/Counter 1 Control Register A

/*-------------------------------------------------------------------------------------------------
Timer1 ist Zähler: Clear Timer on Compare Match (CTC, Mode #4)
Timer1 läuft mit vollem MCU-Takt: Prescale = 1
-------------------------------------------------------------------------------------------------*/

#if defined (CTC1) && !defined (WGM12)
   TCCR1B = (1 << CTC1)  | (1 << CS10);
#elif !defined (CTC1) && defined (WGM12)
   TCCR1B = (1 << WGM12) | (1 << CS10);
#else
#error Keine Ahnung, wie Timer1 fuer diesen AVR zu initialisieren ist!
#endif

/*-------------------------------------------------------------------------------------------------
OutputCompare für gewünschte Timer1 Frequenz
TCNT1 zählt immer 0...OCR1A, 0...OCR1A, ... 
Beim überlauf OCR1A -> OCR1A+1 wird TCNT1=0 gesetzt und im nächsten
MCU-Takt eine IRQ erzeugt.
-------------------------------------------------------------------------------------------------*/

    OCR1A = (unsigned short) ((unsigned long) F_CPU / IRQS_PER_SECOND-1);

#if defined (TIMSK1) // OutputCompareA-Interrupt für Timer1 aktivieren
    TIMSK1 |= (1 << OCIE1A);
#elif defined (TIMSK)
    TIMSK  |= (1 << OCIE1A);
#else   
#error Keine Ahnung, wie IRQs fuer diesen AVR zu initialisieren sind!
#endif

}

/***************************************************************************************************
void wait_10ms (const uint8_t t) *******************************************************************
***************************************************************************************************/

/*-------------------------------------------------------------------------------------------------
Wartet etwa t*10 ms. 
timer_10ms wird alle 10ms in der Timer1-ISR erniedrigt. 
Weil es bis zum nächsten IRQ nicht länger als 10ms dauert,
wartet diese Funktion zwischen (t-1)*10 ms und t*10 ms.
-------------------------------------------------------------------------------------------------*/

void wait_10ms (const uint8_t t)

{
    timer_10ms = t;
    while (timer_10ms);
}

/***************************************************************************************************
Die Interrupt Service Routine (ISR) ****************************************************************
***************************************************************************************************/
/*-------------------------------------------------------------------------------------------------
Die Interrupt Service Routine (ISR).
In interrupt_num_10ms werden die IRQs gezählt.
Sind IRQS_PER_10MS Interrups geschehen, 
dann sind 10 ms vergangen.
timer_10ms wird alle 10 ms um 1 vermindert und bleibt bei 0 stehen.
-------------------------------------------------------------------------------------------------*/

SIGNAL (SIG_OUTPUT_COMPARE1A)
{
    static uint8_t interrupt_num_10ms;

        if (++interrupt_num_10ms == IRQS_PER_10MS) // interrupt_num_10ms erhöhen und mit M
                           // aximalwert vergleichen
    {
        
        interrupt_num_10ms = 0; // 10 Millisekunden sind vorbei // interrupt_num_10ms zurücksetzen
              
        if (timer_10ms != 0) // Alle 10ms wird timer_10ms erniedrigt, falls es nicht schon 0 ist.
            timer_10ms--;    // Wird verwendet in wait_10ms
    }
}



Autor: Falk (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@Rachid Maoukil

>Das tuts doch aber die Erste LED leuchtet ganz normal, aber dir zweite
>und dritte leuchten sehr schwach dann. Ich würde gern wissen woran es
liegen könnte.

Du musst die Ports für alle drei LEDs auf Ausgang schalten, die sind 
mämlich na dem Reset alles Eingänge.


int main()
{

// ist unvollständig
//    DDR_LED  |= (1 << LED_1); // LED-Port auf Ausgang

// so isses sbesser
    DDR_LED  |= (1 << LED_1) | (1 << LED_2) | (1 << LED_3); // LED-Ports 
auf Ausgang

...

MfG
Falk

Autor: Rachid Maoukil (rachid)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Super. Danke sehr

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.