Forum: Mikrocontroller und Digitale Elektronik AVR Attiny10 External Interrupt in C


von Cyrill S. (chrissel_eck)


Lesenswert?

Hallo allerseits,

ich versuche mich gerade an einem kleinen Programm für den Attiny10. 
Dieser soll später eine LED via PWM dimmen und per Taster gesteuert 
werden.
Da dies mein erstes Projekt mit diesem µC ist, habe ich mir erst ein mal 
ein "Test-Board" gebaut und versuche den Code "stückweise" zu 
implementieren (daher die auskommentierten Bereiche...). Als IDE nutze 
ich AVR-Studio 7.

Mein Problem: die LED leuchtet dauerhaft - so als würde der µC aus dem 
Interrupt nicht wieder zurück in die main springen. Kann das sein? - 
oder habe ich mich beim setzten der Interrupt-Register vertan?
1
/*
2
 * Attiny10_Kueche.c
3
 *
4
 * Created: 12.03.2017 23:50:20
5
 * Author : Chrissel
6
 *
7
 *---------------------------------------------------------
8
 * Pinbelegung:
9
 *
10
 * PB0 => Taster auf GND
11
 * PB1 => LED
12
 * PB2 => frei
13
 * PB3 => frei
14
 * VCC = 5V
15
 *---------------------------------------------------------
16
 *
17
 */ 
18
#define F_CPU 1000000UL
19
20
#include <avr/io.h>
21
#include <avr/interrupt.h>
22
#include <util/delay.h>
23
24
25
26
ISR(INT0_vect)
27
{
28
  //OCR0B = 1000;
29
  PINB = 0x02;
30
}
31
32
33
34
int main(void)
35
{
36
    int i;
37
  
38
  
39
  // CPU-Clock settings:
40
  
41
  CCP=0xD8;    // enable change on protected I/O
42
  CLKMSR=0x00;  // Use internal 8MHz internal clock
43
  
44
  CCP=0xD8;    // enable change on protected I/O
45
  CLKPSR=0x03;  // set Clock Prescaler to 8 ( => 8MHz / 8 = 1MHz ! )
46
  
47
  // Pin Definition:
48
  DDRB = 0x02;    // set PB1 to output
49
  PUEB = 0x01;    // enable Pull-up at PB0
50
  
51
  
52
  // PWM-Section:
53
  /*
54
  TCCR0A = 0x22;    // set COM00B1 to 1; COM0B0 to 0; ( non-inverting mode );; Set WGM00 to 0; WGM01 to 1 
55
  TCCR0B = 0x1A;    // set WGM02 to 1; set WGM03 to 1; ( Waveform Generation Mode 1110; Fast PWM, TOP = ICR0
56
  ICR0 = 1000;    // set TOP to 1000
57
  */
58
  
59
  // Interrupt-Section:
60
  
61
  EICRA = 0x00;    // Low-Level generates an interrupt
62
  EIMSK = 0x01;    // External Interrupt Request 0 Enable
63
  PCICR = 0x01;    // Pin Change Interrupt Control Register set to enable PCINT Interrupt
64
  PCMSK = 0x01;    // Pin Change Mask Register set to enable PCINT0
65
  
66
  sei();
67
  
68
  
69
  
70
  
71
    while (1) 
72
    {
73
    /*
74
    for (i = 0; i <= 1000; i++)
75
    {
76
      OCR0B = i;
77
      _delay_ms(3);
78
    }
79
    for (i = 1000; i >= 0; i--)
80
    {
81
      OCR0B = i;
82
      _delay_ms(3);
83
    }
84
    */
85
    PINB = 0x00;
86
    }
87
}

LG
Cyrill

von MWS (Gast)


Lesenswert?

PinX ist ein Eingangsregister, Ausgangsregister nennen sich PortX.
Außerdem hat das Ding einen kastrierten Registersatz, R1-R15 fehlen, 
soweit ich erinnere sind auch ein paar Opcodes anders.
Da wird dem Compiler schlecht.
Nimm Assembler, damit klappt's.

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Cyrill S. schrieb:
>     PINB = 0x00;

Die ISR toggelt per PINB = 0x02 PORT B1.

PINB = 0 hat keine Funktion, vielleicht meinst du PORTB = 0 oder PORTB 
&= ~(1 << PB1) so dass nur das Bit wieder gelöscht wird oder per PORTB 
|= (1 << PB1) wieder gesetzt wird.

Zudem wird die Aktion in main immer ausgeführt, also auch unmittelbar 
nach der ISR.  Daher ist das Flackern viel zu kurz um es mit dem Auge 
erkennen zu können.

von Hubert G. (hubertg)


Lesenswert?

Ist es nicht so das man den über PINx den Eingangsstatus einliest und 
über PORTx den Ausgang setzt? Pintoggel mal ausgenommen.

von Cyrill S. (chrissel_eck)


Lesenswert?

Johann L. schrieb:
> vielleicht meinst du PORTB = 0 oder PORTB
> &= ~(1 << PB1) so dass nur das Bit wieder gelöscht wird oder per PORTB
> |= (1 << PB1) wieder gesetzt wird.

Ja, das meinte ich...

Aber auch mit den Änderungen bleibt die LED dauerhaft an.

MWS schrieb:
> Außerdem hat das Ding einen kastrierten Registersatz, R1-R15 fehlen,
> soweit ich erinnere sind auch ein paar Opcodes anders.
> Da wird dem Compiler schlecht.
> Nimm Assembler, damit klappt's.

Mein Problem: ich beherrsche kein Assembler... :-(


Die aktuelle Fassung vom Code:
1
/*
2
 * Attiny10_Kueche.c
3
 *
4
 * Created: 12.03.2017 23:50:20
5
 * Author : Chrissel
6
 *
7
 *---------------------------------------------------------
8
 * Pinbelegung:
9
 *
10
 * PB0 => Taster auf GND
11
 * PB1 => LED
12
 * PB2 => frei
13
 * PB3 => frei
14
 * VCC = 5V
15
 *---------------------------------------------------------
16
 *
17
 */ 
18
#define F_CPU 1000000UL
19
20
#include <avr/io.h>
21
#include <avr/interrupt.h>
22
#include <util/delay.h>
23
24
25
26
ISR(INT0_vect)
27
{
28
  //OCR0B = 1000;
29
  PORTB &= (1 << 1);
30
  _delay_ms(500);
31
}
32
33
34
35
int main(void)
36
{
37
    int i;
38
  
39
  
40
  // CPU-Clock settings:
41
  
42
  CCP=0xD8;    // enable change on protected I/O
43
  CLKMSR=0x00;  // Use internal 8MHz internal clock
44
  
45
  CCP=0xD8;    // enable change on protected I/O
46
  CLKPSR=0x03;  // set Clock Prescaler to 8 ( => 8MHz / 8 = 1MHz ! )
47
  
48
  // Pin Definition:
49
  DDRB = 0x02;    // set PB1 to output
50
  PUEB = 0x01;    // enable Pull-up at PB0
51
  
52
  
53
  // PWM-Section:
54
  /*
55
  TCCR0A = 0x22;    // set COM00B1 to 1; COM0B0 to 0; ( non-inverting mode );; Set WGM00 to 0; WGM01 to 1 
56
  TCCR0B = 0x1A;    // set WGM02 to 1; set WGM03 to 1; ( Waveform Generation Mode 1110; Fast PWM, TOP = ICR0
57
  ICR0 = 1000;    // set TOP to 1000
58
  */
59
  
60
  // Interrupt-Section:
61
  
62
  EICRA = 0x00;    // Low-Level generates an interrupt
63
  EIMSK = 0x01;    // External Interrupt Request 0 Enable
64
  PCICR = 0x01;    // Pin Change Interrupt Control Register set to enable PCINT Interrupt
65
  PCMSK = 0x01;    // Pin Change Mask Register set to enable PCINT0
66
  
67
  sei();
68
  
69
  
70
  
71
  
72
    while (1) 
73
    {
74
    /*
75
    for (i = 0; i <= 1000; i++)
76
    {
77
      OCR0B = i;
78
      _delay_ms(3);
79
    }
80
    for (i = 1000; i >= 0; i--)
81
    {
82
      OCR0B = i;
83
      _delay_ms(3);
84
    }
85
    */
86
    PORTB &= ~(1 << 1);
87
    _delay_ms(500);
88
    }
89
}

von MWS (Gast)


Lesenswert?

Cyrill S. schrieb:
> Mein Problem: ich beherrsche kein Assembler... :-(

Da hast Du gleich zwei Probleme, zum einen könntest Du Dir im Studio den 
disassemblierten Code ansehen, dann sähst Du gleich, wo's klemmt und zum 
anderen hast Du den falschen Controller für die gewählte 
Programmiersprache.

Es ist einige Zeit her, dass ich festellten konnte, dass der AVR GCC bei 
diesem Kontroller scheitert und ich bezweifele, dass mittlerweile viel 
Energie in das Anpassen des GCC gesteckt wurde, damit der auf diesem 
Winzteil läuft. Zumal SRam- und Flash-Ausstattung eher in Richtung 
Assembler deutet.

Nimm einen Tiny13 oder 25, die gibt's auch in relativ kleinem Gehäuse 
und die sind in C problemlos programmierbar.

von Marc V. (Firma: Vescomp) (logarithmus)


Lesenswert?

Johann L. schrieb:
> Die ISR toggelt per PINB = 0x02 PORT B1.

 Nein, tut es nicht.

von MWS (Gast)


Lesenswert?

Marc V. schrieb:
> Johann L. schrieb:
>> Die ISR toggelt per PINB = 0x02 PORT B1.
>
>  Nein, tut es nicht.

Auszug DB ATiny10:
> However, writing '1' to a bit in the PINx Register will result in a toggle in 
the
> corresponding bit in the Data Register.

von Marc V. (Firma: Vescomp) (logarithmus)


Lesenswert?

MWS schrieb:
> Auszug DB ATiny10:
>> However, writing '1' to a bit in the PINx Register will result in a toggle in
> the
>> corresponding bit in the Data Register.

 Ich bin nach meiner Liste gegangen.
 AVRs mit Toggle Fähigkeit:
Beitrag "Re: Welche AVR besitzen die PIN Toggle Fähigkeit?"


 Jedenfalls steht in ATTiny10.xml nichts von Tiny10 Pintoggle
 Fähigkeiten.

 Und da ATMEL regelmässig Mist baut mit DaBlas, bin ich geneigt,
 .xml mehr Glauben zu schenken...

 P.S.
 Ich habe keine ATTINY10 um das zu prüfen, vielleicht kann das
 jemand testen ?

: Bearbeitet durch User
von Johann L. (gjlayde) Benutzerseite


Lesenswert?

MWS schrieb:
> Außerdem hat das Ding einen kastrierten Registersatz, R1-R15 fehlen,
> soweit ich erinnere sind auch ein paar Opcodes anders.

Und?

> Da wird dem Compiler schlecht.

Käse.

Der Code ist vielleicht nicht so gut wie für "normale" AVR, aber auch 
nicht schlimmer als seinen AVR bit BASCOM zu traktieren  oder 
bloated[tm] C oder C++ zu fabrizieren.

MWS schrieb:
> Cyrill S. schrieb:
>> Mein Problem: ich beherrsche kein Assembler... :-(
>
> Da hast Du gleich zwei Probleme, zum einen könntest Du Dir im Studio den
> disassemblierten Code ansehen, dann sähst Du gleich, wo's klemmt und zum
> anderen hast Du den falschen Controller für die gewählte
> Programmiersprache.

YMMV.

> Es ist einige Zeit her, dass ich festellten konnte, dass der AVR GCC bei
> diesem Kontroller scheitert und ich bezweifele, dass mittlerweile viel
> Energie in das Anpassen des GCC gesteckt wurde, damit der auf diesem
> Winzteil läuft.

Der GCC läuft immer noch aufm PC. Und was du mit "scheiten" meinst weiß 
ich auch nicht.

> Zumal SRam- und Flash-Ausstattung eher in Richtung
> Assembler deutet.

Schon, aber das schließt C nicht aus.  Das einzige ist die schlechtere 
Unterstützung von Standard-Funktionen durch die avr-libc und teilweise 
auch libgcc.  Aber wenn float-Support ein Ausschlusskriterieum ist, 
wirst du ihn für Tiny auch nicht in Assembler programmieren wollen.

Jedenfalls zeigt das, dass es Keute gibt, die zumindest GCC auf nem Tiny 
versuchen, und dass es daher nicht vergemene Liebesmüh ist, den Support 
in avr-gcc und avr-libc weiter auszubauen, was entgegen deine Unkenrufe 
auch geschieht.

: Bearbeitet durch User
von neuer PIC Freund (Gast)


Lesenswert?

Sicher dass du Pin Change Interrupts ohne ISR-Routine verwenden 
möchtest? Alternativ kannst du die Flags auch in der main pollen. Da der 
Tiny10 anscheinend nur einen Timer hat, der wahrscheinlich für die PWM 
draufgeht, ist die Generierung des 10ms-Tickes etwas schwieriger. Und 
ein Zeitraster willst du haben, damit der debouncer ordentlich arbeitet 
und diese unsäglichen _delay_ms() verschwinden.

Und schmeiß  die Magic numbers raus, wenigstens mit #defines.

von MWS (Gast)


Lesenswert?

Johann L. schrieb:
> MWS schrieb:
>> Außerdem hat das Ding einen kastrierten Registersatz, R1-R15 fehlen,
>> soweit ich erinnere sind auch ein paar Opcodes anders.
>
> Und?

Was und? Das Resultat war kaputter Maschinencode. Genug und?
>

> Der Code ist vielleicht nicht so gut wie für "normale" AVR, aber auch
> nicht schlimmer als seinen AVR bit BASCOM zu traktieren  oder
> bloated[tm] C oder C++ zu fabrizieren.

Zu dem Zeitpunkt, wo ich mir das Disassemblat des vom GCC erzeugten 
Codes ansah, war's unbrauchbar, es wurden Register verwendet, über die 
der Atiny10 nicht verfügte.

> MWS schrieb:
>> Cyrill S. schrieb:
>>> Mein Problem: ich beherrsche kein Assembler... :-(
>>
>> Da hast Du gleich zwei Probleme, zum einen könntest Du Dir im Studio den
>> disassemblierten Code ansehen, dann sähst Du gleich, wo's klemmt und zum
>> anderen hast Du den falschen Controller für die gewählte
>> Programmiersprache.
>
> YMMV.

Merkwürdige Bemerkung zu meinem Argument.

>
>> Es ist einige Zeit her, dass ich festellten konnte, dass der AVR GCC bei
>> diesem Kontroller scheitert und ich bezweifele, dass mittlerweile viel
>> Energie in das Anpassen des GCC gesteckt wurde, damit der auf diesem
>> Winzteil läuft.
>
> Der GCC läuft immer noch aufm PC. Und was du mit "scheiten" meinst weiß
> ich auch nicht.

Scheitert = Schrottcode, unbrauchbar,  Absturz mit Reboot, ungültige 
Opcodes, Verwendung nicht vorhandener Register. Sag mal, hast Du eine 
Flasche Wein im Kopf? Ich schreib was von Energie reingesteckt, um den 
Compiler auf den beschränkten Registersatz und abweichende Opcodes 
anzupassen und bekomme als Antwort, dass der GCC auf dem PC läuft. Was 
soll der Krampf, bist Du nicht in der Lage meine Aussage passend 
verstehen?

>> Zumal SRam- und Flash-Ausstattung eher in Richtung
>> Assembler deutet.
>
> Schon, aber das schließt C nicht aus.  Das einzige ist die schlechtere
> Unterstützung von Standard-Funktionen durch die avr-libc und teilweise
> auch libgcc.  Aber wenn float-Support ein Ausschlusskriterieum ist,
> wirst du ihn für Tiny auch nicht in Assembler programmieren wollen.

Vielleicht erzeugt der GCC mittlerweile keinen fehlerhaften Code mehr, 
das kann ich aber im Moment nicht nachvollziehen, da ich auf dem Tablet 
schreibe und kein AVR Studio starten kann, um mir das Ergebnis mal 
anzusehen.

> Jedenfalls zeigt das, dass es Keute gibt, die zumindest GCC auf nem Tiny
> versuchen, und dass es daher nicht vergemene Liebesmüh ist, den Support
> in avr-gcc und avr-libc weiter auszubauen, was entgegen deine Unkenrufe
> auch geschieht.

Es ist schwer zu verstehen, dass Du nicht verstehst, ich hab' schon 
wesentlich bessere Posts von Dir gesehen. Es geht nicht um Liebesmüh und 
Tiny, sondern es geht um die grundsätzlichen Unterschiede der normalen 
Tinys gegenüber den Tiny4/5/9/10.

Es soll hier nicht ge-unkt werden, sondern es geht darum den TE auf die 
Möglichkeit hinzuweisen,  dass der Compiler evtl. nicht das macht, was 
man denkt. Ich muss ja nicht recht haben, wenn jedoch der TE alle 
offensichtlichen Fehler ausgeräumt hat und es dann immer noch nicht 
läuft, dann könnte man über meine Argumente nochmal nachdenken ;-)

von malsehen (Gast)


Lesenswert?

Der Attiny10 ist nur begrenzt in C programmierbar,
da er keinen RAM hat.
Es gibt hier einen Artikel darüber.
"Attiny10 in C" oder so suchen.

von MWS (Gast)


Lesenswert?

malsehen schrieb:
> Der Attiny10 ist nur begrenzt in C programmierbar,
> da er keinen RAM hat

Das aktuelle DB sagt 32 Byte SRam.
Du meinst evtl. den Vorgänger ATiny10 , der unterscheidet sich 
grundlegend vom Nachfolger.

von malsehen (Gast)


Lesenswert?

MWS schrieb:
> Das aktuelle DB sagt 32 Byte SRam.
> Du meinst evtl. den Vorgänger ATiny10 , der unterscheidet sich
> grundlegend vom Nachfolger.

Danke, die neue Reihe tiny4/5... war mir entfallen.
Ist aber auch blöd, zwei komplett unterschiedliche µC
gleich zu benennen.

von Cyrill S. (chrissel_eck)


Lesenswert?

MWS schrieb:
> wenn jedoch der TE alle
> offensichtlichen Fehler ausgeräumt hat

... genau da bin ich mir nicht so sicher.
Ich werde das Gefühl nicht los, irgend wo einen dämlichen Fehler gemacht 
zu haben...
- verwende ich für die ISR den richtigen Vektor?

GCC gibt das als Assembler aus:
1
Attiny10_Kueche.elf:     file format elf32-avr
2
3
Sections:
4
Idx Name          Size      VMA       LMA       File off  Algn
5
  0 .text         00000098  00000000  00000000  00000054  2**1
6
                  CONTENTS, ALLOC, LOAD, READONLY, CODE
7
  1 .data         00000000  00800040  00800040  000000ec  2**0
8
                  CONTENTS, ALLOC, LOAD, DATA
9
  2 .comment      00000030  00000000  00000000  000000ec  2**0
10
                  CONTENTS, READONLY
11
  3 .note.gnu.avr.deviceinfo 0000003c  00000000  00000000  0000011c  2**2
12
                  CONTENTS, READONLY
13
  4 .debug_aranges 00000028  00000000  00000000  00000158  2**0
14
                  CONTENTS, READONLY, DEBUGGING
15
  5 .debug_info   0000046a  00000000  00000000  00000180  2**0
16
                  CONTENTS, READONLY, DEBUGGING
17
  6 .debug_abbrev 000003c2  00000000  00000000  000005ea  2**0
18
                  CONTENTS, READONLY, DEBUGGING
19
  7 .debug_line   0000025b  00000000  00000000  000009ac  2**0
20
                  CONTENTS, READONLY, DEBUGGING
21
  8 .debug_frame  00000050  00000000  00000000  00000c08  2**2
22
                  CONTENTS, READONLY, DEBUGGING
23
  9 .debug_str    000002b6  00000000  00000000  00000c58  2**0
24
                  CONTENTS, READONLY, DEBUGGING
25
 10 .debug_loc    00000056  00000000  00000000  00000f0e  2**0
26
                  CONTENTS, READONLY, DEBUGGING
27
 11 .debug_ranges 00000018  00000000  00000000  00000f64  2**0
28
                  CONTENTS, READONLY, DEBUGGING
29
30
Disassembly of section .text:
31
32
00000000 <__vectors>:
33
   0:  0a c0         rjmp  .+20       ; 0x16 <__ctors_end>
34
   2:  12 c0         rjmp  .+36       ; 0x28 <__vector_1>
35
   4:  10 c0         rjmp  .+32       ; 0x26 <__bad_interrupt>
36
   6:  0f c0         rjmp  .+30       ; 0x26 <__bad_interrupt>
37
   8:  0e c0         rjmp  .+28       ; 0x26 <__bad_interrupt>
38
   a:  0d c0         rjmp  .+26       ; 0x26 <__bad_interrupt>
39
   c:  0c c0         rjmp  .+24       ; 0x26 <__bad_interrupt>
40
   e:  0b c0         rjmp  .+22       ; 0x26 <__bad_interrupt>
41
  10:  0a c0         rjmp  .+20       ; 0x26 <__bad_interrupt>
42
  12:  09 c0         rjmp  .+18       ; 0x26 <__bad_interrupt>
43
  14:  08 c0         rjmp  .+16       ; 0x26 <__bad_interrupt>
44
45
00000016 <__ctors_end>:
46
  16:  11 27         eor  r17, r17
47
  18:  1f bf         out  0x3f, r17  ; 63
48
  1a:  cf e5         ldi  r28, 0x5F  ; 95
49
  1c:  d0 e0         ldi  r29, 0x00  ; 0
50
  1e:  de bf         out  0x3e, r29  ; 62
51
  20:  cd bf         out  0x3d, r28  ; 61
52
  22:  1e d0         rcall  .+60       ; 0x60 <main>
53
  24:  37 c0         rjmp  .+110      ; 0x94 <_exit>
54
55
00000026 <__bad_interrupt>:
56
  26:  ec cf         rjmp  .-40       ; 0x0 <__vectors>
57
58
00000028 <__vector_1>:
59
#include <util/delay.h>
60
61
62
63
ISR(INT0_vect)
64
{
65
  28:  1f 93         push  r17
66
  2a:  0f 93         push  r16
67
  2c:  0f b7         in  r16, 0x3f  ; 63
68
  2e:  0f 93         push  r16
69
  30:  10 e0         ldi  r17, 0x00  ; 0
70
  32:  4f 93         push  r20
71
  34:  5f 93         push  r21
72
  36:  6f 93         push  r22
73
  //OCR0B = 1000;
74
  PORTB &= (1 << 1);
75
  38:  42 b1         in  r20, 0x02  ; 2
76
  3a:  42 70         andi  r20, 0x02  ; 2
77
  3c:  42 b9         out  0x02, r20  ; 2
78
  #else
79
    //round up by default
80
    __ticks_dc = (uint32_t)(ceil(fabs(__tmp)));
81
  #endif
82
83
  __builtin_avr_delay_cycles(__ticks_dc);
84
  3e:  4f e9         ldi  r20, 0x9F  ; 159
85
  40:  56 e8         ldi  r21, 0x86  ; 134
86
  42:  61 e0         ldi  r22, 0x01  ; 1
87
  44:  41 50         subi  r20, 0x01  ; 1
88
  46:  50 40         sbci  r21, 0x00  ; 0
89
  48:  60 40         sbci  r22, 0x00  ; 0
90
  4a:  e1 f7         brne  .-8        ; 0x44 <__SREG__+0x5>
91
  4c:  00 c0         rjmp  .+0        ; 0x4e <__SREG__+0xf>
92
  4e:  00 00         nop
93
  _delay_ms(500);
94
}
95
  50:  6f 91         pop  r22
96
  52:  5f 91         pop  r21
97
  54:  4f 91         pop  r20
98
  56:  0f 91         pop  r16
99
  58:  0f bf         out  0x3f, r16  ; 63
100
  5a:  0f 91         pop  r16
101
  5c:  1f 91         pop  r17
102
  5e:  18 95         reti
103
104
00000060 <main>:
105
    int i;
106
  
107
  
108
  // CPU-Clock settings:
109
  
110
  CCP=0xD8;    // enable change on protected I/O
111
  60:  48 ed         ldi  r20, 0xD8  ; 216
112
  62:  4c bf         out  0x3c, r20  ; 60
113
  CLKMSR=0x00;  // Use internal 8MHz internal clock
114
  64:  17 bf         out  0x37, r17  ; 55
115
  
116
  CCP=0xD8;    // enable change on protected I/O
117
  66:  4c bf         out  0x3c, r20  ; 60
118
  CLKPSR=0x03;  // set Clock Prescaler to 8 ( => 8MHz / 8 = 1MHz ! )
119
  68:  43 e0         ldi  r20, 0x03  ; 3
120
  6a:  46 bf         out  0x36, r20  ; 54
121
  
122
  // Pin Definition:
123
  DDRB = 0x02;    // set PB1 to output
124
  6c:  42 e0         ldi  r20, 0x02  ; 2
125
  6e:  41 b9         out  0x01, r20  ; 1
126
  PUEB = 0x01;    // enable Pull-up at PB0
127
  70:  41 e0         ldi  r20, 0x01  ; 1
128
  72:  43 b9         out  0x03, r20  ; 3
129
  ICR0 = 1000;    // set TOP to 1000
130
  */
131
  
132
  // Interrupt-Section:
133
  
134
  EICRA = 0x00;    // Low-Level generates an interrupt
135
  74:  15 bb         out  0x15, r17  ; 21
136
  EIMSK = 0x01;    // External Interrupt Request 0 Enable
137
  76:  43 bb         out  0x13, r20  ; 19
138
  PCICR = 0x01;    // Pin Change Interrupt Control Register set to enable PCINT Interrupt
139
  78:  42 bb         out  0x12, r20  ; 18
140
  PCMSK = 0x01;    // Pin Change Mask Register set to enable PCINT0
141
  7a:  40 bb         out  0x10, r20  ; 16
142
  
143
  sei();
144
  7c:  78 94         sei
145
    {
146
      OCR0B = i;
147
      _delay_ms(3);
148
    }
149
    */
150
    PORTB &= ~(1 << 1);
151
  7e:  11 98         cbi  0x02, 1  ; 2
152
  80:  4f e9         ldi  r20, 0x9F  ; 159
153
  82:  56 e8         ldi  r21, 0x86  ; 134
154
  84:  61 e0         ldi  r22, 0x01  ; 1
155
  86:  41 50         subi  r20, 0x01  ; 1
156
  88:  50 40         sbci  r21, 0x00  ; 0
157
  8a:  60 40         sbci  r22, 0x00  ; 0
158
  8c:  e1 f7         brne  .-8        ; 0x86 <main+0x26>
159
  8e:  00 c0         rjmp  .+0        ; 0x90 <main+0x30>
160
  90:  00 00         nop
161
  92:  f5 cf         rjmp  .-22       ; 0x7e <main+0x1e>
162
163
00000094 <_exit>:
164
  94:  f8 94         cli
165
166
00000096 <__stop_program>:
167
  96:  ff cf         rjmp  .-2        ; 0x96 <__stop_program>

von MWS (Gast)


Lesenswert?

Von den Registern her, also dem Compilerergebnis sieht's gut aus, nichts 
unter r16.

Nicht zu übersehen ist - wurde vorhin von "neuer PIC Freund" schon 
erwähnt - dass Du keine ISR für PCINT0 hast, sondern nur für INT0.

Da Du einen Pullup auf PB0 legst, auch entsprechend im Kommentar, willst 
Du Dein Signal dort zuführen, dort liegt aber der PCINT0, den Du auch 
erlaubt hast, der aber ohne ISR ist und auf Bad Interrupt führt und für 
Neustarts sorgt.

INT0, für den Du eine ISR angelegt hast, hängt dagegen (wohl floatend) 
an PB2 und löst aufgrund des allgegenwärtigen Netzbrumms aus, während 
ein Signal an PB0 zum sofortigen Neustart führt.

von N. G. (newgeneration) Benutzerseite


Lesenswert?

Hallo,

Ist das immer noch der aktuelle Code?
Cyrill S. schrieb:
> ISR(INT0_vect)
> {
>   //OCR0B = 1000;
>   PORTB &= (1 << 1);
>   _delay_ms(500);
> }

Falls ja erübrigt sich die Diskussion über den "ach so schlechten" GCC 
(jedes Argument von Johann ist sowieso mehr wert ;-) ).

Das delay in der ISR ist natürlich ein Designfehler, aber ich denke, 
dass es eher aus Verzweiflung da rein gekommen ist.

Du löscht aber nicht PB1, sondern alle außer PB1.
Richtig wäre
PORTB &= ~(1 << 1); für den Fall, das der Pin in der ISR low werden 
soll, sonst
PORTB |= (1 << 1);
Da du in der Main()-Funktion den Pin aber immer auf low setzt, wohl eher 
Möglichkeit 2.

Des weiteren aktivierst du (laut deinen Kommentaren, ich hab die 
Register jetzt nicht gegengecheckt) den Pin-Change Interrupt zusätzlich 
zum normalen Externen Interrupt. Da es dazu keine ISR gibt wird der 
Prozessor neu starten.

Mit freundlichen Grüßen,
N.G.

von Cyrill S. (chrissel_eck)


Lesenswert?

Ok. Ich hatte das Datenblatt so verstanden, dass durch die PCIN 
Interrupts auch der INT0 interrupt getigert wird. (ja... das ergibt 
keinen Sinn... ;-)

In der jetzigen Version funktioniert der Code! Vielen Dank euch allen!

Jetzt muss ich mir nur noch überlegen, wie ich im Interrupt auf die 
OCR0B-Werte schreibend zugreifen kann ( ich meine ich muss das 
Interrupt-Flag zurücksetzten bevor das geht...).

Ja, der Assembler-Code war von der vorherigen Version...
1
/*
2
 * Attiny10_Kueche.c
3
 *
4
 * Created: 12.03.2017 23:50:20
5
 * Author : Chrissel
6
 *
7
 *---------------------------------------------------------
8
 * Pinbelegung:
9
 *
10
 * PB0 => Taster auf GND
11
 * PB1 => LED geneg VCC ( logisch 0 = LED an )
12
 * PB2 => frei
13
 * PB3 => frei
14
 * VCC = 5V
15
 *---------------------------------------------------------
16
 *
17
 */ 
18
#define F_CPU 1000000UL
19
20
#include <avr/io.h>
21
#include <avr/interrupt.h>
22
#include <util/delay.h>
23
24
25
26
ISR(PCINT0_vect)
27
{
28
  //OCR0B = 0;
29
  PORTB = 0x00;
30
  _delay_ms(500);
31
}
32
33
34
35
int main(void)
36
{
37
    int i;
38
  
39
  
40
  // CPU-Clock settings:
41
  
42
  CCP=0xD8;    // enable change on protected I/O
43
  CLKMSR=0x00;  // Use internal 8MHz internal clock
44
  
45
  CCP=0xD8;    // enable change on protected I/O
46
  CLKPSR=0x03;  // set Clock Prescaler to 8 ( => 8MHz / 8 = 1MHz ! )
47
  
48
  // Pin Definition:
49
  DDRB = 0x02;    // set PB1 to output
50
  PUEB = 0x0F;    // enable Pull-up at PB0
51
  
52
  
53
  // PWM-Section:
54
  /*
55
  TCCR0A = 0x22;    // set COM00B1 to 1; COM0B0 to 0; ( non-inverting mode );; Set WGM00 to 0; WGM01 to 1 
56
  TCCR0B = 0x1A;    // set WGM02 to 1; set WGM03 to 1; ( Waveform Generation Mode 1110; Fast PWM, TOP = ICR0
57
  ICR0 = 1000;    // set TOP to 1000
58
  */
59
  
60
  // Interrupt-Section:
61
  
62
  EICRA = 0x00;    // Low-Level generates an interrupt
63
  EIMSK = 0x01;    // External Interrupt Request 0 Enable
64
  PCICR = 0x01;    // Pin Change Interrupt Control Register set to enable PCINT Interrupt
65
  PCMSK = 0x01;    // Pin Change Mask Register set to enable PCINT0
66
  
67
  sei();
68
  
69
  
70
  
71
  
72
    while (1) 
73
    {
74
    /*
75
    for (i = 0; i <= 1000; i++)
76
    {
77
      OCR0B = i;
78
      _delay_ms(3);
79
    }
80
    for (i = 1000; i >= 0; i--)
81
    {
82
      OCR0B = i;
83
      _delay_ms(3);
84
    }
85
    */
86
    PORTB = 0x02;
87
    _delay_ms(500);
88
    }
89
}

Liebe Grüße
Cyrill

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.