-
@SimLock :-)
Lernen ist immer gut
>Ich habe mich beim Markieren, einfügen verklickt.
ja, hier gibts keinen precompiler
Grundsätzlich C ist eine mächtige Sprache, lesbar wird sie nur - auch für einen selbst - wenn man klar strukturiert und akribisch Ordnung hält. In meinen Augen sollte eine Initalisierung in eine entsp. Funktion z.B. AvrINIT(void) und eben alle Initialisierung oder weitere Aufrufe. Die Portdefinitionen stehen bei mir immer am Anfang, das Ende meist ein sei();
hiermit setzt Du nur ein Bit von PortB
> PortB |= (1 << BIT2);
Löschen wäre
PortB &=~ (1 << BIT2);
hiermit setzt Du den gesamten Port ...
> DDRB = (1 << PB1);
... wenn Du das später im Code auch so machst, wirst Du irgendwann lange nach Fehlern suchen.
Setze lieber immer nur die BIts, die Du wirklich verändern willst.
-
Hi Hubert,
danke für dein Code, aber funktioniert nicht bei mir trotz OCRA anpassung :-(
Mal paar fragen dazu:
1. Hier wird der Ausgang für UART Signale gewählt oder?
Code:
ISR(USART_RXC_vect){
rxwert= UDR;
PORTB=(1<<PB0);
}
2. Mit "break" wird doch das Programm angehalten und springt nicht wieder zur Hauptschleife oder?
Code:
switch(rxwert){
case 0x38 :
OCR1A=470;
break;
Ich hab dein Programm mal geändert für eine Led ansteuerrung.
Siehe Code. Wenn ich Taster PD2 drücke geht Lampe PD5 an und aus.
Wenn ich jetzt über Hyberterminal Taste stücke, geht an PB0 eine Led dauernt an und die funktion über normalen Taster PD2 funktioniert nicht mehr. Hängt sich das Programm jetzt auf vielleicht wegen "break" oder stimmt die einstellungen von UART nicht?
Code:
#include <avr/io.h>
#include <stdbool.h>
#include <stdlib.h>
#include <avr/io.h>
#include <AVR/iom8.h>
#include <inttypes.h>
#include <avr/interrupt.h>
#define F_CPU 8000000 // clock
#define BAUD 9600
#define bauddivider (unsigned int)(F_CPU / BAUD / 16 - 0.5)
volatile unsigned char rxwert=0x30;
ISR(USART_RXC_vect){
rxwert= UDR;
PORTB=(1<<PB0);
}
void usart_init(void){
UBRRL = bauddivider; //set baud rate
UBRRH = bauddivider >> 8;
UCSRB = (1<<RXCIE)|(1<<RXEN);
UCSRC = (1<<URSEL)|(3<<UCSZ0);
}
int main (void)
{
usart_init();
//*** LED ***
DDRB |= (1<<PB0); /* Pin PB0 als Ausgang für UART */
DDRD |= (1<<PD5); /* Pin PD5 als Ausgang für Led */
//*** Taster ***
DDRD &= ~ (1<<PD2); /* Pin D2 als Eingang */
PORTD |= (1<<PD2); /* Pull Up von PIN D2 aktivieren */
sei();
while(1){
if(rxwert==0x30){
if (!( PIND & (1<<PIND2))) /* mache was wenn PinD2 low ist */
{
PORTD |= (1<<PD5); /* Setzt Pin PD5 auf High */
}
else {
PORTD &= ~ (1<<PD5); /* Setzt Pin PD5 wieder auf low */
}
}
switch(rxwert){
case 0x38 :
PORTD |= (1<<PD5); /* Setzt Pin PD5 auf High */
break;
case 0x32 :
PORTD &= ~ (1<<PD5); /* Setzt Pin PD5 wieder auf low */
break;
}
}
}
vajk, danke für dein Hinweiß. Hab es mir aufgeschrieben :-)
-
1. Das ist der Interrupt den ausgelöst wird wenn ein Zeichen Empfangen wurde, es wird unter rxwert gespeichert.
2. mit break verlässt du die switch-Schleife
3. wenn die Led aufleuchtet dann funktioniert die ISR , die Tasten funktionieren erst wieder wenn du einen 0 drückst.
Die UART-Einstellungen sind für einen 8MHz Takt, es könnte nur Probleme geben wenn du mit dem internen Oszillator arbeitest, der ist nicht sehr genau. Sonstige Einstellung 8bit, no parity, 1 Stoppbit.
-
Mein Programm, das müsste ja ok sein oder?
Wenn ich über Hyperterminal geal welche Taste ich drücke dann leutete dauernt die Led an PB0 und die PD5 tut sich nichts, kann die auch nicht über den Taster ansteuern. Wenn ich 0 drücke leutet die Led immer noch und nichts verändert sich.
Einstellungen sind genau wie du gesagt hast. Benutze den internen Quarz. Wenn ich den externen Quarz von 3,6Mhz benutze, passiert genau das gleiche.
sieht so aus, das er diesen Wert nicht erreicht, weil das ist ja die Funktion des Taster drin, und solange dieses Signal nicht da ist..
if(rxwert==0x30)
-
Du musst schon einen Quarz mit 8MHz verwenden, sonst stimmt die Baudrate nicht und du bekommst irgend einen Unsinn übertragen. Der interne Oszillator kann zu ungenau sein.
Die PB0 leuchtet beim ersten Interrupt auf und geht nicht mehr aus. Das sich mit PD5 dann nichts tut ist klar, im rxwert steht irgend ein Blödsinn und solange da nicht 0x30 drinnen steht geht nichts.
-
Dann muss ich mir mal einen 8 Mhz Quarz besorgen.
Heißt das jetzt, wenn es Funktioniert muss ich jedesmal 0x30 drücken, also 0 damit die Tasterfunktionschleife funktioniert?
Also ich habe mal ein Testprogramm mit Senden geschrieben, wenn ich einen Taster drücke, soll dann 'W' rüber geschickt werden. Im Terminal kommt auch was an, aber nicht W sonder a~ und noch ein symbol.
Das liegt jetzt daran wegen des Quarz?
-
Richtig, wenn du 0 drückst laufen die Servos in Mittelstellung und die Taster sind wieder aktiv. Das kann man durch ändern des Programms natürlich ganz anders gestalten, hier sollte es ja nur eine Demo des UART sein.
Du kannst diesen 3,6864 MHz Quarz auch nehmen, allerdings musst du F_CPU ändern und den PWM-Timer anpassen damit die Servos funktionieren.
-
Die Servos lassen wir erstmal weg. Will nur die Led von PC aus an und aus machen. Also dann F_CPU auf 3,6864 MHz und externen Quarz einstellen.
Somit klappt es! <-- Thx.
Frage noch zu UART, der Signal bei PB0 kann ich dann nicht mehr benutzen oder? Der wird dann für die Empfangen genutz...
Und noch eine Frage zu case:
case 0x38 :
PORTD |= (1<<PD5); /* Setzt Pin PB3 auf High */
break;
kann man da auch else mit einbauen?
Dacht da so an:
case 0x38 :
PORTD |= (1<<PD5); /* Setzt Pin PB3 auf High */
Else
PORTD &= ~ (1<<PD5); /* Setzt Pin PB3 wieder auf low */
break;
oder geht das nur mit einer If/Else?
-
In den Fuses den externen Quarz einstellen.
Das PB0 in der ISR kannst du weglassen, war für mich nur eine Indikator ob die ISR funktioniert, wenn du es änderst auf PORTB^=(1<<PB0); dann geht die Led an und aus.
-
Also das mit Empfangen geht schon mal, F_CPU umgestellt.
Das PB0 in der ISR ist weg, geht auch und leutet nicht mehr.
1000 Danke schon mal dafür!!!
Hast du meine letzt Frage gelesen mit If/Else oder case?