Forum: Mikrocontroller und Digitale Elektronik AVR SDK / API gesucht


von David P. (devryd)


Lesenswert?

Hi,
ich bin blutiger Anfänger was die Programmierung von AVR Chips angeht 
und wollte fragen ob es eine gesammelte Quelle an aufbereiteten 
Informationen gibt. Ich kenne das beispielsweise vom Pi Pico als SDK, 
oder, wenn auch ein etwas anderer Usecase, von der JAVA APi. Ich frage, 
weil ich jetzt schon seit über einer Stunde daran scheitere, einen 
simplen Timerinterrupt zum laufen zu bekommen. Ja, die Daten stehen im 
Datenblatt, aber das ist ja nicht wirklich anfängerfreundlich zu lesen.
Tut mir leid, wenn das als blöde Frage gilt
Danke für eure Ratschläge

von Εrnst B. (ernst)


Lesenswert?

die "blutige Anfänger API" für AVR µCs nennt sich "Arduino" :)

von David P. (devryd)


Lesenswert?

Dann suche ich etwas für "ein Schritt nach blutiger Anfänger"

von Adam P. (adamap)


Lesenswert?


von David P. (devryd)


Lesenswert?

Adam P. schrieb:
> 
https://www.mikrocontroller.net/articles/AVR-GCC-Tutorial/Die_Timer_und_Z%C3%A4hler_des_AVR

Diesen Beitrag habe ich schon gefunden und habe versucht ihn zu 
befolgen. Leider hab ich das nicht zum laufen bekommen. Ich nutze einen 
Atmega1284p, falls das einen Unterschied macht

von Εrnst B. (ernst)


Lesenswert?

Sowas vielleicht?
https://github.com/jfpoilpret/fast-arduino-lib
für C++ - Enthusiasten.

Da hast du dann Code wie
1
constexpr const board::Timer NTIMER = board::Timer::TIMER1;
2
using CALCULATOR = timer::Calculator<NTIMER>;
3
using TIMER = timer::Timer<NTIMER>;
4
constexpr const uint32_t PERIOD_US = 1000000;
5
6
constexpr const TIMER::PRESCALER PRESCALER = CALCULATOR::CTC_prescaler(PERIOD_US);
7
constexpr const TIMER::TYPE COUNTER = CALCULATOR::CTC_counter(PRESCALER, PERIOD_US);
8
[...]
9
10
  TIMER timer{timer::TimerMode::CTC, PRESCALER, timer::TimerInterrupt::OUTPUT_COMPARE_A};
11
  timer.begin(COUNTER);
12
[...]
(Ganzer Code:
https://github.com/jfpoilpret/fast-arduino-lib/blob/master/tuto-samples/fastarduino/timer_1_ctc.cpp
)

Deutlich mehr Tipparbeit als die handvoll Register von Hand zu setzen, 
aber "cleaner"?

von uff basse (Gast)


Lesenswert?

David P. schrieb:
> Leider hab ich das nicht zum laufen bekommen.

Wenn du weiterkommen willst dass müsstest du uns eben zeigen
was du schon gemacht hast und welche Probleme dabei auftauchen.

So richtig gute Hellseher sind wir hier alle nicht ....

von Adam P. (adamap)


Lesenswert?

David P. schrieb:
> Ich nutze einen
> Atmega1284p, falls das einen Unterschied macht

Ja da heißen die Register ein wenig anders.

von STK500-Besitzer (Gast)


Lesenswert?

David P. schrieb:
> aber das ist ja nicht wirklich anfängerfreundlich zu lesen.

Wo ist denn das Problem?
Atmel-Datenblätter sind verhältnismäßig gut.
Vor allem ist es ein Dokument pro Chip-Gruppe; nicht wie bei STM32, wo 
es ein Datenblatt, ein Reference- und ein Programming-Manual mit jeweils 
zig-tausend Seiten gibt.

von Stefan F. (Gast)


Lesenswert?

David P. schrieb:
> die Daten stehen im Datenblatt,
> aber das ist ja nicht wirklich anfängerfreundlich zu lesen.

Dur wirst keine "schöneren" Datenblätter finden, als die von AVR 
Mikrocontroller.

> Dann suche ich etwas für "ein Schritt nach blutiger Anfänger"

http://stefanfrings.de/mikrocontroller_buch/index.html

Die Timer sind allerdings schon recht komplex. Am besten fängst du erst 
mal mit einfacheren Funktionen an, bis du mit dem Style des Datenblattes 
vertraut bist. Mein "Buch" leitet dich dazu an.

von David P. (devryd)


Lesenswert?

1
 /*
2
 * 1284p test.c
3
 *
4
 * Created: 16.02.2022 17:51:14
5
 * Author : David
6
 */ 
7
#define F_CPU 128000L
8
#include <avr/io.h>
9
#include <avr/interrupt.h>
10
#include <util/delay.h>
11
12
int help;
13
char sekunden;
14
int main(void)
15
{
16
    DDRA =0xFF;
17
  DDRC =0xFF;
18
  DDRD =0xFF;
19
  TCCR0A =  (1<<CS00); //
20
  TIMSK0 |= (1<<TOIE0);
21
  sei();
22
  
23
  while(1){
24
  //  PORTD=sekunden;
25
  //  PORTD |= (1<<0);
26
  //  _delay_ms(100);
27
  //  PORTD&= ~(1<<0);
28
  //  _delay_ms(100);
29
  ;
30
  }
31
}
32
ISR( TIMER0A_OVF_vect ) {
33
help++;
34
if(help%2)
35
PORTD |= (1<<1);
36
else
37
PORTD |= ~(1<<1);
38
  
39
}
Das ist der Code, den ich mir aus dem Internet zusammengesucht habe. 
Wenn ich das richtig verstehe, sollte die LED, die an PD1 angeschlossen 
ist jetzt schnell blinken oder "halbhell" leuchte, allerdings bleibt sie 
aus.

von S. Landolt (Gast)


Lesenswert?

Mal die Warnungen im Compiler ('-Wall') einschalten - bei mir kommt da 
ein "... appears to be a misspelled signal handler ...".

von STK500-Besitzer (Gast)


Lesenswert?

1
PORTD |= ~(1<<1);

das sollte wohl eher
1
PORTD &= ~(1<<1);
heissen!

von David P. (devryd)


Lesenswert?

STK500-Besitzer schrieb:
> das sollte wohl eherPORTD &= ~(1<<1);
> heissen!

Hab ich geändert, aber da gar keine LED an geht, ist das wohl nicht das 
Problem

S. Landolt schrieb:
> Mal die Warnungen im Compiler ('-Wall') einschalten - bei mir kommt da
> ein "... appears to be a misspelled signal handler ...".
1
ISR( TIMER0_OVF_vect ) {
Die Zeile hab ich geändert, entfernt die Warnung, tut sonst aber nichts

von STK500-Besitzer (Gast)


Lesenswert?

David P. schrieb:
> Die Zeile hab ich geändert, entfernt die Warnung, tut sonst aber nichts

kannst du die LED auch ohne Timer ansteuern?
Einfach mal eine Endlosschleife in der die LED ein- und ausgeschaltet 
wird.
Dazu dann noch ein paar Warteschleifen.
So kann man zumindest Hardware-Fehler ausschließen.

von David P. (devryd)


Lesenswert?

STK500-Besitzer schrieb:
> David P. schrieb:
>> Die Zeile hab ich geändert, entfernt die Warnung, tut sonst aber nichts
>
> kannst du die LED auch ohne Timer ansteuern?
> Einfach mal eine Endlosschleife in der die LED ein- und ausgeschaltet
> wird.
> Dazu dann noch ein paar Warteschleifen.
> So kann man zumindest Hardware-Fehler ausschließen.

Jap, das funktioniert. Dafür hatte ich die auskommentierte While 
Schleife benutzt.

von S. Landolt (Gast)


Lesenswert?

TCCR0B =  (1<<CS00);
nicht TCCR0A

von David P. (devryd)


Lesenswert?

S. Landolt schrieb:
> TCCR0B =  (1<<CS00);
> nicht TCCR0A

Das war der Fehler, danke

von S. Landolt (Gast)


Lesenswert?

Vorsicht vor Fehlinterpretationen: die LED blinkt mit 250 Hz. Und 
Helligkeiten täuschen oft.

von Adam P. (adamap)


Lesenswert?

David P. schrieb:
> #define F_CPU 128000L

Bist du sicher das das so richtig ist, auch wenn es nichts mit deinem 
Problem zu tun hat?

Also du hast nun den Timer mit dem TIMER0A_OVF_vect Interrupt verwendet,
hier noch mal ein Bsp. mit TIMER0_COMPA_vect.

Den Pin musst halt auf den richtigen ändern.
1
// Bsp. für ATmega1284P mit 16Mhz
2
#include <avr/io.h>
3
#include <avr/interrupt.h>
4
#include <stdint.h>
5
6
uint16_t ms;
7
8
ISR(TIMER0_COMPA_vect)
9
{
10
  ms--;
11
12
  if (ms == 0)
13
  {
14
    ms = 1000;
15
    PORTD ^= (1 << PIND5);
16
  }
17
}
18
19
int main(void)
20
{
21
  ms = 1000;
22
23
  DDRD = (1 << DDD5);
24
25
  /* Timer0 (1ms) */
26
  TCCR0A = (1 << WGM01);
27
  TCCR0B = (1 << CS01) | (1 << CS00);
28
  OCR0A = 249;
29
  TIMSK0 |= (1 << OCIE0A);
30
  
31
  sei();
32
33
  while(1)
34
  {
35
    
36
  }
37
38
  return 0;
39
}

: Bearbeitet durch User
von David P. (devryd)


Lesenswert?

Adam P. schrieb:
> #define F_CPU 128000L

steht doch für 128KHz oder?
Wenn ja, sollte es richtig sein.

von David P. (devryd)


Lesenswert?

Mitlerweile habe ich meinen Code soweit geändert. Die Anzgeige auf Port 
d klappt, die auf PortA gar nicht und auf PortC die ersten 2 Bits. 
Jemand ne idee, woran das liegen könnte?
1
/*
2
 * 1284p test.c
3
 *
4
 * Created: 16.02.2022 17:51:14
5
 * Author : David
6
 */ 
7
#define F_CPU 128000L
8
#include <avr/io.h>
9
#include <avr/interrupt.h>
10
#include <util/delay.h>
11
12
int help;
13
char sekunden;
14
char minuten;
15
char stunden;
16
void updateTime(){
17
  if(sekunden==59){
18
    sekunden=0;
19
    if(minuten==59){
20
      stunden=(stunden+1)%24;
21
      minuten=0;
22
    }
23
    else{
24
      ++minuten;
25
    }
26
  }
27
  else{
28
    ++sekunden;
29
  }
30
}
31
int main(void)
32
{
33
    DDRA =0xFF;
34
  DDRC =0xFF;
35
  DDRD =0xFF;
36
  TCCR0B =  (1<<CS00); 
37
  TIMSK0 |= (1<<TOIE0);
38
  sei();
39
  
40
  while(1){
41
    PORTD=sekunden;
42
    PORTA=stunden;
43
    PORTC=minuten;
44
    
45
  }
46
}
47
ISR( TIMER0_OVF_vect ) {
48
help++;
49
if(help==500){
50
updateTime();
51
help=0;
52
}
53
}

von Adam P. (adamap)


Lesenswert?

David P. schrieb:
> PORTA=stunden;

Dann musst du halt auch mindestens 1 Std. warten.

von STK500-Besitzer (Gast)


Lesenswert?

David P. schrieb:
> Mitlerweile habe ich meinen Code soweit geändert. Die Anzgeige auf Port
> d klappt, die auf PortA gar nicht und auf PortC die ersten 2 Bits.
> Jemand ne idee, woran das liegen könnte?

ja, Infos zu den Ports findest du im Datenblatt.
Da der Code ja inzwischen umfangreicher wird, solltest du ihn als Anhang 
mitliefern.

von David P. (devryd)


Lesenswert?

Adam P. schrieb:
> David P. schrieb:
>> PORTA=stunden;
>
> Dann musst du halt auch mindestens 1 Std. warten.

Um das ganze zu testen, habe ich den CPU Takt erhöht, sollte also 
deutlich weniger als ne stunde dauern

STK500-Besitzer schrieb:
> Da der Code ja inzwischen umfangreicher wird, solltest du ihn als Anhang
> mitliefern.

Mache ich in Zukunft.

von Adam P. (adamap)


Lesenswert?

Dann versuch es doch mal so:

PORTD = sekunden;
PORTA = sekunden;
PORTC = sekunden;

von S. Landolt (Gast)


Lesenswert?

PORTC2..5 wird von JTAG benutzt - ist das abgeschaltet?

von David P. (devryd)


Lesenswert?

Ändert leider nichts.
PORTA ist komplett aus, Bei PORTC funktionieren die ersten 2 Bits, der 
rest leuchtet sehr schwach

von David P. (devryd)


Lesenswert?

S. Landolt schrieb:
> PORTC2..5 wird von JTAG benutzt - ist das abgeschaltet?

Nein, noch nicht. Danke für den Tipp, ich schaue mal nach, wie das geht

von N. M. (mani)


Lesenswert?

Und mach Mal vor die Variablen die im Interrupt Context verwendet werden 
ein volatile davor.

von Adam P. (adamap)


Lesenswert?

S. Landolt schrieb:
> PORTC2..5 wird von JTAG benutzt - ist das abgeschaltet?

Aber nicht das er nur ein JTAG Adapter (Kabel) hat, sonst wars das dann 
mit wieder ändern.

von S. Landolt (Gast)


Lesenswert?

> PORTA ist komplett aus
Ist AVcc angeschlossen, d.h. mit Strom versorgt?

von David P. (devryd)


Lesenswert?

S. Landolt schrieb:
> Ist AVcc angeschlossen, d.h. mit Strom versorgt?

Jetzt ja, und schon funktioniert PortA

von Adam P. (adamap)


Lesenswert?

S. Landolt schrieb:
> Ist AVcc angeschlossen, d.h. mit Strom versorgt?

Man lernt nie aus...das wusst ich auch noch nicht.
Ich bin davon ausgegangen das AVcc lediglich für den Analog Teil ist, 
nicht das es auch "grundsätzlich" den PORTA versorgt.

Edit:
AVCC is the supply voltage pin for Port F and the Analog-to-digital 
Converter. It should be exter-
nally connected to VCC , even if the ADC is not used. If the ADC is 
used, it should be connected
to V CC through a low-pass filter.

: Bearbeitet durch User
von S. Landolt (Gast)


Lesenswert?

> Aber nicht das er nur ein JTAG Adapter (Kabel) hat,
> sonst wars das dann mit wieder ändern.

Man muss ja nicht per Fuse abschalten, per Software (zu Programmbeginn) 
geht auch.

von David P. (devryd)


Lesenswert?

S. Landolt schrieb:
> Man muss ja nicht per Fuse abschalten, per Software (zu Programmbeginn)
> geht auch.

Sollte das nicht mit dieser Zeile funktionieren?
1
MCUCR |= 0x80;

von S. Landolt (Gast)


Lesenswert?

Zweimal.

"The application software must write this bit [JTD] to the desired value 
twice within four cycles to change its value.

von David P. (devryd)


Lesenswert?

S. Landolt schrieb:
> "The application software must write this bit [JTD] to the desired value
> twice within four cycles to change its value.

Ah danke, das muss ich überlesen haben.
Edit: Klappt, danke

: Bearbeitet durch User
von Adam P. (adamap)


Lesenswert?

David P. schrieb:
> Adam P. schrieb:
>> #define F_CPU 128000L
>
> steht doch für 128KHz oder?
> Wenn ja, sollte es richtig sein.

Darf ich fragen, warum du den Controller so langsam laufen lässt?

von David P. (devryd)


Lesenswert?

Adam P. schrieb:
> Darf ich fragen, warum du den Controller so langsam laufen lässt?

Zum Strom sparen. Ich wollte es mal so niedrig wie möglich probieren, 
wenn das von der rechenleistung nicht reicht, kann ich ja immer noch 
mehr nehmen

von Thomas F. (igel)


Lesenswert?

David P. schrieb:
> Zum Strom sparen.

Dann lässt man ihn eher normal schnell laufen und benutzt den sleep-Mode 
wann immer es geht.

von David P. (devryd)


Lesenswert?

Rentieren sich sleep modes, wenn man etwas im Sekundentakt machen 
möchte?

von S. Landolt (Gast)


Lesenswert?

Da es hier offenbar um eine Uhr geht, uneingeschränkt: ja.
  Aber auch sonst sehr oft, zumindest von der Verarbeitungskapazität her 
gesehen; allerdings sind viele Peripherieeinheiten dann abgeschaltet.

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.