Hallo Leute, ich bins mal wieder. Hab folgendes Problem. Möchte gerne
über einen Mikrokontroller meine Servomotoren ansteuern. Hab mir nun
einen C-Code geschrieben mit dem ich mehrere Sevo`s ansteuern kann.
Dieser funktioniert einwandfrei. Habe dafür nur einen Timer des Atmega
48 verwendet, musst allerdings auch ein Interrupt verwenden. Nun möchte
ich zusätzlich aber die einzelnen Motorenstellungen über meinen Computer
steuern und dies geht nun mal nur über Uart. Ich möchte beispielsweise
Motor1 2 Schritte nach rechts bewegen. Ich schicke nun über mein
Terminalprogramm (Terminal_G-A-System) einen Char an den µC. Und hier
sind wir dann auch schon bei meinem Problem:
Mein C-Code auf meinem µC löst alle 0,00001275 sec einen Interrupt aus.
Wo muss ich nun den Char den ich vom Pc bekomme auswerten? Direkt im
Interrupt? Soll ich mit cli(); und sei() arbeiten? Schickt mir doch
bitte ein paar vorschläge. Ich poste euch hier mal meinen C-Code:(var0
und var1 sind die Vergleichswerte die ich brauche um PD5 oder PD6 auf
high zu setzen)
1
#include<avr/io.h>
2
#include<util/delay.h>
3
#include<avr/interrupt.h>
4
#include<avr/signal.h>
5
#include<avr/pgmspace.h>
6
#include<util/delay.h>
7
#include"uart.h"
8
9
10
/* define CPU frequency in Mhz here if not defined in Makefile */
11
#ifndef F_CPU
12
#define F_CPU 20000000UL
13
#endif
14
15
/* 9600 baud */
16
#define UART_BAUD_RATE 9600
17
18
uint8_tempf;
19
volatileuint8_tvar0=105;
20
volatileuint8_tvar1=110;
21
22
ISR(TIMER2_COMPA_vect)
23
{
24
//hier kommt der Code zum steuern meiner Motoren//
25
//Das Interrupt wird alle 0,00001275 sec ausgelöst//
>Wo muss ich nun den Char den ich vom Pc bekomme auswerten?
Müssen gar nicht. Empfehlen würde ich in main(). Bei 9600 baud kommen
die Zeichen um eine Größenordnung langsamer, als der Timerinterrupt
läuft. Sollte deine uart_gtc gar auf das eintreffen eines Zeichen
warten, hat die in der ISR gar nichts zu suchen.
>Soll ich mit cli(); und sei() arbeiten?
Das sollte man immer. Aber hier ist das dann nicht erforderlich. var0
ist eine 8-bi-Variable, Zugriffe darauf sind damit nicht unterbrechbar.
Oliver
Du löst alle 12,75 µs einen Timer-Interrupt aus, in dessen Handler ein
Zeichen von einer seriellen Schnittstelle mit 9600 Baud eingelesen
wird? Und da wunderst Du Dich, dass nicht wirklich das rauskommt, was Du
erwartest? Ich verstehe auch absolut nicht, wozu Du den Timer-Interrupt
brauchst. Wenn Du irgendwas empfangen willst, musst Du sowieso warten,
bis der Sender was gesendet hat.
Dinge, die mit serieller Eingabe/Ausgabe zu tun haben, gehören sowieso
nicht in Interrupt-Handler. Aber als erstes solltest Du Dich hinsetzen
und nachrechnen, wie lange es bei 9600 Bd mindestens dauert, bis ein
Zeichen übertragen ist und Dir die Beschreibung der Funktion getc mal
näher ansehen...
Johannes M. wrote:
>Ich verstehe auch absolut nicht, wozu Du den Timer-Interrupt> brauchst. Wenn Du irgendwas empfangen willst, musst Du sowieso warten,> bis der Sender was gesendet hat.>
Ich brauche das Timer-Interrupt zum ansteuern meiner Motoren.
Sollte ich meine uart_getc()in die main so einbauen?
Hätte auch eine alternative Lösung dazu. Was wäre wenn ich folgende
Funktion für uart_getc() verwenden würde:
1
uint8_tuart_getC()
2
{
3
if(!(UCSR0A&(1<<RXC0)))
4
{
5
return0;
6
}
7
else
8
{
9
returnUDR0;
10
}
11
}
Ich würde mit dieser Funktion also nicht warten bis etwas im Ringbuffer
ist sondern einfach nachschauen ob etwas drin ist. Wenn was drin ist gib
ich das Zeichen zurück ansonsten nur 0.
Dies könnte ich dann auch prima als Alternative für uart_getc()
verwenden. Oder???
MfG Atmega168
Lass das cli und sei weg. Dein Timer läuft mit fast 80kHz, das dürfte
auch für einen mit 20MHz getakteten AVR eine ziemliche Last darstellen.
Anscheinend brauchts du aber solch eine hohe Frequenz, also stör die
nicht ohne wichtigen Grund.
Ob der Code des Hauptprogramms während des Empfangens unterbrochen wird,
oder nicht, ist völlig egal. Wichtig ist nur, daß der Schreibzugriff auf
die Variable var0 nicht so unterbrochen werden kann, daß fehlerhafte
Daten enstehen. Das kann aber nur bei Datentypen passieren, die 2 oder
mehr Byte breit sind. Und selbst da würde man(n) dann die ISR'S nur für
den eigentlichen Zugriff auf die Variable sperrren, nicht für die ganze
UART-Leseprozedur.
Deine neue Variante von uart_getC() ist prima, hat aber trotzdem in der
Timer-ISR nichts zu suchen. Brauchen wirst du die, wenn in der
Hauptschleife mal noch andere Dinge passieren sollen.
Oliver
Oliver wrote:
> Lass das cli und sei weg. Dein Timer läuft mit fast 80kHz, das dürfte> auch für einen mit 20MHz getakteten AVR eine ziemliche Last darstellen.> Anscheinend brauchts du aber solch eine hohe Frequenz, also stör die> nicht ohne wichtigen Grund.>> Ob der Code des Hauptprogramms während des Empfangens unterbrochen wird,> oder nicht, ist völlig egal. Wichtig ist nur, daß der Schreibzugriff auf> die Variable var0 nicht so unterbrochen werden kann, daß fehlerhafte> Daten enstehen. Das kann aber nur bei Datentypen passieren, die 2 oder> mehr Byte breit sind. Und selbst da würde man(n) dann die ISR'S nur für> den eigentlichen Zugriff auf die Variable sperrren, nicht für die ganze> UART-Leseprozedur.>> Deine neue Variante von uart_getC() ist prima, hat aber trotzdem in der> Timer-ISR nichts zu suchen. Brauchen wirst du die, wenn in der> Hauptschleife mal noch andere Dinge passieren sollen.>> Oliver
Vielen dank Oliver
Wie würdest du dann die main schreiben um ein char vom Pc auszuwerten?
Könntest du mir bitte einen C-Code posten?
MfG Atmega168
Hab jetzt mal probiert das uart_getc() in die main zu tun, allerdings
ruckelt mein servo da nur rum und macht nicht das was er soll.
Kann mir bitte einer behilflich sein und sagen wie ich mein Problem am
besten lösen kann?
MfG Atmega168
@ Atmega 168 (atmega168)
>Hab jetzt mal probiert das uart_getc() in die main zu tun, allerdings>ruckelt mein servo da nur rum und macht nicht das was er soll.
1
#include<avr/io.h>
2
#include<util/delay.h>
3
#include<avr/interrupt.h>
4
#include<avr/signal.h>
5
#include<avr/pgmspace.h>
6
#include<util/delay.h>
7
#include"uart.h"
8
9
10
/* define CPU frequency in Mhz here if not defined in Makefile */
11
#ifndef F_CPU
12
#define F_CPU 20000000UL
13
#endif
14
15
/* 9600 baud */
16
#define UART_BAUD_RATE 9600
17
18
uint8_tempf;
19
volatileuint8_tvar0=105;
20
volatileuint8_tvar1=110;
21
22
ISR(TIMER2_COMPA_vect)
23
{
24
//hier kommt der Code zum steuern meiner Motoren//
@Atmega 168 (atmega168)
>Danke Falk, hab das aber schon probiert, da ruckelt mein Motor nur rum.
Dann hast du noch woanders einen Fehler drin. Poste mal VOLLSTÄNDIGEN
Code als Anhang.
MFG
Falk
Falk Brunner wrote:
> Dann hast du noch woanders einen Fehler drin. Poste mal VOLLSTÄNDIGEN> Code als Anhang.>> MFG> Falk
Das Interrupt ist ok schreib ich diesen Code in die main dann geht der
Servo nach rechts wenn ich PINC2 auf high setze und nach links wenn ich
PINC1 auf high setzte: Hier ist der Code: