Forum: Mikrocontroller und Digitale Elektronik AVR PWM-Steuerprogramm für LEDs


von Mario K. (mariok_atmel)


Lesenswert?

Hallo Leute,

eins vorweg, ich bin absoluter Einsteiger was C angeht, und plänkel 
aktuell noch in den Basics herum. Falls das Thema woanders hingehört 
bitte verschieben!

Ich will mir ein kleines Programm für mein eigenes Projekt schreiben und 
möchte dabei erreichen, dass ich zunächst erst einmal LEDs über einen 
Schalter (aktuell an PINA0) anschalten und in einer Art Abfolge laufen 
lassen kann.

Das Hauptproblem besteht darin, dass ich aktuell nicht weiß wie ich 
permanent den Schalter abfrage und meine LED-Abfolge damit starten 
lassen kann. Zudem weiß ich nicht wie ich die Abfolge unterbreche, falls 
der Schalter wieder auf "Aus" gestellt wird.

Die LEDs funktionieren in der gewünschten Abfolge bereits ohne Schalter 
über die PWM Steuerung. Aber die Integration des Schalters und damit der 
Start oder Abbruch darüber machen mir Kopfzerbrechen.

Hier mal mein bisheriges Programm:
1
/*
2
 * PWM.c
3
 *
4
 * Created: 24.10.2015 17:56:40
5
 * Author : lkrie
6
 */
7
 
8
#define F_CPU 970000UL
9
#include <avr/io.h>
10
#include <util/delay.h>
11
//#include <conio.h>
12
 
13
 
14
int wert = 3; //PWM Differenzwert - Verkürzt oder verlängert das PWM Signal
15
//int wert2 = 200;
16
int maxperf = 255; //maximale Leistung liegt bei 255
17
int minperf= 0; //minimale Leistung liegt bei 0
18
 
19
int main(void)
20
{
21
    DDRD = 0;
22
    DDRB = 0xFF;
23
    DDRA = 0x00;
24
    PORTA = 0xff;
25
    TCCR0A = (1<<WGM00)|(1<<COM0A1);
26
    TCCR1A = (1<<WGM10)|(1<<COM1A1);
27
    TCCR0B = (1 << CS01);
28
    OCR0A = 0;
29
    OCR0B = 0;
30
 
31
 
32
               
33
 
34
    while(1)
35
    {
36
                        //hier soll der Schalter rein, mitdem ich den Start der Abfolge initieren kann.
37
            for (OCR0A = minperf; OCR0A < maxperf; OCR0A = OCR0A + wert)
38
            {
39
            _delay_ms(10);
40
            }
41
            for (OCR0A = maxperf; OCR0A > minperf; OCR0A = OCR0A - wert)
42
            {
43
            _delay_ms(10);
44
            }
45
            for (OCR0A = minperf; OCR0A < maxperf; OCR0A = OCR0A +  wert)
46
            {
47
            _delay_ms(10);
48
            }
49
            for (OCR0A = maxperf; OCR0A > minperf; OCR0A = OCR0A - wert)
50
            {
51
            _delay_ms(10);
52
            }
53
            _delay_ms(600);
54
                for (OCR0A = minperf; OCR0A < maxperf; OCR0A = OCR0A + wert)
55
                {
56
                    _delay_ms(10);
57
                }
58
                for (OCR0A = maxperf; OCR0A > minperf; OCR0A = OCR0A - wert)
59
                {
60
                    _delay_ms(10);
61
                }
62
                for (OCR0A = minperf; OCR0A < maxperf; OCR0A = OCR0A +  wert)
63
                {
64
                    _delay_ms(10);
65
                }
66
                for (OCR0A = maxperf; OCR0A > minperf; OCR0A = OCR0A - wert)
67
                {
68
                    _delay_ms(10);
69
                }
70
                _delay_ms(500);
71
                                for (OCR0A = minperf; OCR0A < 180; OCR0A = OCR0A + wert)
72
                                {
73
                                    _delay_ms(12);
74
                                }
75
                                for (OCR0B = 0; OCR0B < 10; OCR0B = OCR0B + OCR0B)
76
                                {
77
                                    _delay_ms(600);
78
                                }
79
    }
80
}

von 0x4E (Gast)


Lesenswert?

Mario K. schrieb:
> eins vorweg, ich bin absoluter Einsteiger was C angeht, und plänkel
> aktuell noch in den Basics herum.

Du musst von vorne anfangen und nicht gleich mit Timern. Du kannst noch 
kein C und versuchst dich an einer PWM. Das ist so, als wolltest du 
Schreibschrift schreiben und kannst noch nicht einmal das Alphabet. Du 
kannst den Programmcode gar nicht verstehen wenn du kein C kannst. ICh 
empfehle dir ein Buch zu lesen.

Der Erlenkötter ist gut für dich.

https://www.amazon.de/C-Programmieren-Anfang-Helmut-Erlenk%C3%B6tter/dp/3499600749.

Wenn du dann ein bisschen C kannst empfehle ich dir ein Buch von Florian 
Schäffer - Hardware und C Programmierung

https://www.amazon.de/AVR-Hardware-C-Programmierung-Florian-Sch%C3%A4ffer/dp/3895762008

Erst dann verstehst du überhaupt was du da tun willst.

Der Programm Code ist Schrott!

Mario K. schrieb:
> #define F_CPU 970000UL

Wie kommst du auf 970kHz?

Mario K. schrieb:
> DDRA = 0x00;
> PORTA = 0xff;

Du sagst dem µC, dass alle Pins des PortA Eingänge sein sollen, und dann 
willst du alle Pins auf 1 schalten. Das ist völliger Blödsinn.

von Einer K. (Gast)


Lesenswert?

0x4E schrieb:
> Du sagst dem µC, dass alle Pins des PortA Eingänge sein sollen, und dann
> willst du alle Pins auf 1 schalten. Das ist völliger Blödsinn.

Ich mache das schon häufiger mal so, oder so ähnlich.
Und dann ist das gut und richtig so.

Manchmal ist es sogar wichtig, das anders rum zu machen:
1
PORTA = 0xff;
2
DDRA = 0x00;

von Harry M. (harry4516)


Lesenswert?

Hallo Mario,

das einzige was hier "Schrott und Blödsinn" ist, sind die Kommentare von 
0x4E(Gast) zu deinem Code (die Links zu den Büchern sind allerdings 
empfehlenswert). Mir geht immer der Hut hoch wenn ich so respektloses 
Geschreibsel sehe.

Ich heiße dich als Einsteiger herzlich willkommen.
Auch wenn dein Code etwas eigenartig ist, das ist egal. Während der 
Lernphase muss man alles ausprobieren, nur so lernt man was.

Da deine LEDs bereits wie gewünscht blinken, gehts also nur mehr um den 
Schalter.
Dazu stellst du zunächst den Port A0 auf Eingang, was
du mit DDRA = 0 bereits richtig gemacht hast.
Danach schreibst du PORTA = 0xFF. Damit schaltest du die internen 
Pullups ein. Wenn dein Schalter gegen Masse schaltet ist auch das 
richtig.

Jetzt muss du nur mehr den PINA0 abfragen, und je nach Wert dein 
Programm in einer while Schleife warten lassen, fertig.
z.B. so:
while((PINA & 1) == 1);
oder in Kurzform, was das gleiche ist:
while(PINA & 1);

das kommt dort rein, wo du bereits den entsprechenden Kommentar in 
deinem Programm reingeschrieben hast.

solange das Bit 0 von Port-A auf 1 ist (der Schalter ist offen und der 
Pullup zieht den Eingang auf 1) kreiselt er endlos in der while 
Schleife. Sobald du den Schalter zumachst, wird die while Schleife nicht 
mehr ausgeführt und dein Code für die LEDs wird wieder laufen.

: Bearbeitet durch User
von Tobias N. (tobias_n)


Lesenswert?

Mario K. schrieb:
> Das Hauptproblem besteht darin, dass ich aktuell nicht weiß wie ich
> permanent den Schalter abfrage

Wenn das von meinem Vorredner hinhaut, erkundigst du dich mal nach 
externen Interrupts. Damit musst du dein Programm nicht die ganze Zeit 
mit dem Abfragen des Tasters beschäftigen.

Gruß

von chris (Gast)


Lesenswert?

Tobias N. schrieb:
> Wenn das von meinem Vorredner hinhaut, erkundigst du dich mal nach
> externen Interrupts.

NEIN nicht schon wieder dieser Unsinn.
Taster werden nicht über EXTI abgefragt sondern zyklisch gepollt!

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.