PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Software PWM 4-Kanal



premier
13.08.2005, 13:08
Hallo Robotikfreaks,

Was AVRs angeht bin ich ein ziemlicher NOOB!
Habe mir vor kurzem ein atmega16 Testboard bei ebay gekauft und habe es geschafft mal was über USART am PC auszugeben.

Ich habe das fertige C-Skript von Christian Schifferle angepasst, und man sollte eigentlich über ein Terminal Programm eine Eingabe der Form:

<Kanal 1..4>:<Wert von 0...255>

machen. die an den Ausgängen angeschlossenen LEDs sollten dann heller oder dunkler leuchten, aber bei mir sind sie die ganze Zeit "mittelhell" egal welchen Wert ich eingebe. :-s

Hier das Skript:



#include <avr/io.h>
#include <stdint.h> // Wir brauchen Zugriff auf die I/O's des Controllers
#include <string.h> // und eine Stringfunktion (strchr)
#include <stdlib.h> // sowie die Standardfunktion atoi aus stdlib


#define USART_BAUD_RATE 9600 /* 9600 baud */

// Berechnung des Inhalts des UBBR-Registers
#define USART_BAUD_SELECT (F_CPU/(USART_BAUD_RATE*16l)-1)


// Datentypdefinitionen
typedef unsigned char BYTE;
typedef unsigned short WORD;

#define CR 0x0d // Definition für Carriage Return
#define CHANNELS 4 // Anzahl PWM-Kanäle
#define MAX_BUFFER 15 // Maximal 15 Zeichen lange Befehlszeile zulassen

BYTE szBuffer[MAX_BUFFER+1]; // Puffer mit maximal 15 Zeichen plus Nullbyte
BYTE nBuffer; // Anzahl Zeichen im Puffer
BYTE nChannels[CHANNELS]; // PWM-Werte der 4 Kanäle


// Prototypen der lokalen Funktionen
void HdlBuffer (void);
void USART_Init(void);
void USART_transmit (unsigned char c);
unsigned char USART_receive (void);
void USART_transmit_string (unsigned char *string);

int main (void)
/************************************************** **************************
Hier ist der Programmeinstiegspunkt.
*/
{
register BYTE c; // Letztes empfangenes Zeichen
register BYTE nCnt; // Aktueller Zählerwert
register BYTE n; // Hilfsvariable
register BYTE nPortB; // Hilfsvariable


/* UART Control Register laden. Wir verwenden (immer noch)
keine Interrupts. Hier wollen wir nur empfangen, also wird
nur das Receiver Enable Flag gesetzt. */

USART_Init();


// Port B der Einfachheit halber komplett als Ausgang konfigurieren
DDRB=0xff;

// Timer/Counter0 (8-Bit-Timer) initialisieren
// Wir verwenden den Vorzähler 1024. Warum? Einfach so.
// Wenn wir einen zu kleinen Vorteiler wählen, dann kommt unser Programm nicht
// mehr mit und die Ausgangsignale werden unstabil.
TCCR0|=(1<<CS02)|(1<<CS00); // Vorzaehler = 1024

USART_transmit_string("Bitte Kanal:Wert eingeben\r\n");

// Und jetzt in die Hauptschleife
for (;;) {
// Prüfen, ob ein Zeichen empfangen wurde.
if ((UCSRA) & (1 << RXC)) { // Bit RXC im USR gesetzt ?
// Zeichen einlesen
c = UDR;

// Falls CR, dann Empfangspuffer auswerten, sonst Zeichen speichern,
// wenn der Puffer nicht bereits überlaufen ist.
if (c == CR) {
// Puffer auswerten
szBuffer[nBuffer] = '\0'; // Abschliessendes Nullbyte eintragen
HdlBuffer ();
nBuffer = 0; // Puffer wieder initialisieren
}
else {
if (nBuffer < MAX_BUFFER) {
szBuffer[nBuffer++] = c;
}
}
}

// Zählerwert abfragen
nCnt = TCNT0;
nPortB = 0; // Portinhalt mit 0 initialisieren
for (n=0; n<CHANNELS; n++) {
if (nChannels[n] >= nCnt) {
// Portbit setzen
nPortB |= (1 << n);
}
}
// Resultat auf Port B ausgeben
PORTB=nPortB;
}

} /* end of main */

void HdlBuffer (void)
{
BYTE *pColon; // Position des Doppelpunktes
BYTE nChannel, nVal;

// Doppelpunkt suchen, wenn keiner da ist -> Fehler
pColon = strchr (szBuffer, ':');
if (pColon) {
// Kanal bestimmen
nChannel = atoi (szBuffer);
// PWM-Wert bestimmen
nVal = atoi (pColon + 1);
// Die Kanalnummer wird zwischen 1 und 4 erwartet
if (nChannel >= 1 && nChannel <= 4) {
// und im Array abgespeichert.
// Achtung: Array-Indizes beginnen immer bei 0, deshalb das - 1
nChannels[nChannel-1] = nVal;
}
}

} /* end of HdlBuffer */

void USART_Init(void) {
UCSRB = (1<<RXCIE) | (1<<TXCIE) | (1<<RXEN) | (1<<TXEN);
UCSRB = (1<<RXEN) | (1<<TXEN);
UBRRL = (unsigned char) USART_BAUD_SELECT;
}

void USART_transmit (unsigned char c) {
while (!(UCSRA & (1<<UDRE))) {}
UDR = c;
}

unsigned char USART_receive (void) {
while(!(UCSRA & (1<<RXC))) {}
return UDR;
}

void USART_transmit_string (unsigned char *string) {
while (!(UCSRA & (1<<UDRE))) {}
while ( *string)
USART_transmit (*string++);
}




bitte helft mir!

premier
26.08.2005, 20:31
oooookay.... dann frag ich mal sorum:

Wenn ich über den PC (Terminal-Programm) eingegebene Strings im MC auswerten möchte wie muss ich da vorgehen?

Ist es prinzipiell wie oben oder mit Interrupts?

ist die USART-Initialisierung so richtig?




#define BAUD 9600 /* 9600 baud */
#define MYUBRR (F_CPU/(BAUD*16L)-1)
.
.
.
USART_Init(MYUBRR);
.
.
.
void USART_Init(unsigned int ubrr)
{
UBRRH=(unsigned char) (ubrr>>8);
UBRRL=(unsigned char) ubrr;

UCSRB=(1<<RXEN)|(1<<TXEN);
}

Ich vermute, dass der MC keine Werte bekommt... aber warum flackern dann die LEDs ganz dunkel?

premier
27.08.2005, 20:09
Kann mir denn keiner helfen???