PWM Spannung erhöhen per Taster

OP #901280
Lesenswert?
• ▲
▼
Hi Leute,


ich möchte eine Spannung 0 -5 V an einem Port ausgeben, starten soll es 
bei 0 V und stoppen bei 5 V mit einem Taster wollte ich nun die Spannung 
erhöhen.

Ich wollte das so machen:
 int a=50;
int main()
{

DDRD=0xFF;
DDRC=0x00;

void timer(){
TCCR1A = (1<<COM1A1) | (1<<WGM11);
 TCCR1B = (1<<WGM13) | (1<<WGM12) | (1<<CS10);
ICR1 = a
OCR1A = 0x0031;

TIMSK = TIMSK | (1 << OCIE1A);

 }
  for(;;){
  timer();

if (PINC & (1<<PINC0)){
  a++;}

}


aber irgendwie akzeptiert der keine variable für icr1.

Könnt ihr mir helfen?
Gast #901290
Lesenswert?
• ▲
▼
Was für einen Controller verwendest Du?

Dir ist schon klar, dass Du immer wieder den Timer neu initialisierst? 
Warum machst Du es nicht so:
1
 int a=50;
2
int main()
3
{
4

5
DDRD=0xFF;
6
DDRC=0x00;
7

8
TCCR1A = (1<<COM1A1) | (1<<WGM11);
9
 TCCR1B = (1<<WGM13) | (1<<WGM12) | (1<<CS10);
10
OCR1A = 0x0031;
11

12
TIMSK = TIMSK | (1 << OCIE1A);
13

14

15
  for(;;){
16
  timer();
17

18
if (PINC & (1<<PINC0)){
19
  ICR1 = a++;}
20

21
}}

Und Du hast das Semikolon hinter ICR1 = a vergessen.
Gast #901306
Lesenswert?
• ▲
▼
Ach so. Warum willst Du denn den Wert ins ICR1 schreiben? Die Spannung 
änderst Du durch ändern des Wertes in OCR1A. Also sollte es so heissen:
1
int a=50;
2
int main()
3
{
4

5
DDRD=0xFF;
6
DDRC=0x00;
7

8
TCCR1A = (1<<COM1A1) | (1<<WGM11);
9
TCCR1B = (1<<WGM13) | (1<<WGM12) | (1<<CS10);
10

11
TIMSK = TIMSK | (1 << OCIE1A);
12

13

14
  for(;;){
15
  timer();
16

17
if (PINC & (1<<PINC0)){
18
  OCR1A = a++;}
19

20
}}
Gast #901328
Lesenswert?
• ▲
▼
Wozu machst Du
1
TIMSK = TIMSK | (1 << OCIE1A);
 wenn Du den Interrupt gar nicht verwendest?

Versuche mal das:
1
int a=50;
2
int main()
3
{
4

5
DDRD=0xFF;
6
DDRC=0x00;
7

8
TCCR1A = (1<<COM1A1) | (1<<WGM11) | (1<<WGM10);
9
TCCR1B = (1<<WGM13) | (1<<WGM12) | (1<<CS10);
10

11

12
  for(;;){
13
 
14
if (PINC & ~(1<<PINC0)){
15
  OCR1A = a++;
16
}
17

18
}
19
return 0;
20
}
Gast #901946
Lesenswert?
• ▲
▼
Hats funktioniert?
Hast Du die Möglichkeit, den Taster auch wo anders anzuschliessen? Dann 
würde ich mit dem Taster einen externen Interrupt auslösen und damit den 
Wert erhöhen. Ansonsten wird solange Du die Taste drückst der Wert 
ziemlich schnell den Grenzwert überschreiten. Ein Beispiel:
1
#include <avr/interrupt.h>
2
#include <avr/io.h>
3

4
void init(void);
5

6
ISR (INT0_vect)
7
{
8
 OCR1A = a++;
9
}
10

11
void init(void)
12
{
13
 DDRD &= ~(1<<PIND2);
14
 PORTD &= ~(1<<PIND2);
15
 MCUCR = (1<<ISC01);       //fallende Flanke an INT0 löst Interrupt aus
16
 GICR |= (1<<INT0);        //Enable external Interrupt 0
17
 TCCR1A = (1<<COM1A1) | (1<<WGM11) | (1<<WGM10);
18
 TCCR1B = (1<<WGM13) | (1<<WGM12) | (1<<CS10);
19
 sei();                    //enable Interrupts
20
}
21

22
int main(void)
23
{
24
 init();
25
 while(1);
26
 return 0;
27
}

Das setzt voraus, dass Dein Taster beim drücken am Pin des Controllers 
ein Low erzeugt und über ein Pull-up Widerstand auf High angeschlossen 
ist.
Gast #901955
Lesenswert?
• ▲
▼
Ich habe es bei mir getestet und es funktioniert. Ich hab an Pin 2 von 
Port D (INT0) einen low aktiven Taster und an Pin 5 (OC1A)eine LED 
angeschlossen. Durch betätigen des Tasters lässt sich die LED dimmen. 
Jedoch sind von 50 bis 255 über 200 Tastendrücke notwendig. Du könntest 
aber auch a um mehr als 1 erhöhen, um die Schrittweite zu erhöhen. Hier 
noch der Code:
1
#include <avr/interrupt.h>
2
#include <avr/io.h>
3

4
void init(void);
5
int a = 50;
6

7
ISR (INT0_vect)
8
{
9
 OCR1A = a++;
10
 if (a>=255) a = 50;
11
 
12
}
13

14
void init(void)
15
{
16
 DDRD &= ~(1<<PD2);
17
 DDRD |= (1<<PD5);
18
 PORTD &= ~(1<<PD2);
19
 MCUCR = (1<<ISC01);       //fallende Flanke an INT0 löst Interrupt aus
20
 GICR |= (1<<INT0);        //Enable external Interrupt 0
21
 OCR1A = 0;
22
 TCCR1A = (1<<COM1A1) |(1<<WGM10);
23
 TCCR1B = (1<<WGM12) | (1<<CS10);
24
 sei();                    //enable Interrupts
25
}
26

27
int main(void)
28
{
29
 init();
30
 while(1);
31
 return 0;
32
}
Gast #901961
Lesenswert?
• ▲
▼
Wenn Du jedoch willst, dass sich die Spannung sich kontinuierlich 
ändert, solange Du den Taster drückst, kannst Du es so machen:
1
#include <avr/interrupt.h>
2
#include <avr/io.h>
3

4
void init(void);
5
void delay (int t);
6
int a;
7

8
void delay (int t)
9
{
10
 int i;
11

12
 while (t--)
13
 {
14
  for (i = 0;i < 100;i++) asm volatile ("nop");
15
 }
16
}
17

18
void init(void)
19
{
20
 DDRD &= ~(1<<PD2);
21
 DDRD |= (1<<PD5);
22
 PORTD &= ~(1<<PD2);
23
 OCR1A = 0;
24
 TCCR1A = (1<<COM1A1) |(1<<WGM10);
25
 TCCR1B = (1<<WGM12) | (1<<CS10);
26
}
27

28
int main(void)
29
{
30
 init();
31
 while(1)
32
 {
33
  if (bit_is_clear (PIND, PD2)){
34
  OCR1A = a++;
35
 }
36
  delay(200);
37
  
38
  }
39
 return 0;
40
}

Mit delay kannst Du einstellen, wie lange ein Durchlauf dauern soll. Ich 
hoffe, ich konnte Dir helfen.

Antwort schreiben

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.

Formatierung
  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] – Link zu einem Artikel
  • Verweis auf einen anderen Beitrag: Rechtsklick auf dessen Beitrags-ID (#8078628), „Adresse kopieren“, in den Text einfügen

Mehr zur Formatierung

Längeren Sourcecode als Anhang, nicht in den Text. JPG nur für Fotos und Scans; Zeichnungen und Screenshots als PNG oder GIF. Siehe Bildformate.

Schon registriert? Anmelden

Wird nicht angezeigt. Wir schicken dir einen Link; sobald du damit bestätigst, erscheint dein Beitrag.

Mit dem Abschicken legst du einen kostenlosen Account an und erkennst die Nutzungsbedingungen und die Datenschutzerklärung an.