Code:
#define F_CPU 14745600
#include <avr/io.h>
#include <inttypes.h>
#include <avr/interrupt.h>
#include <util/delay.h>
#define FOSC 14745600 //Clock Speed
#define BAUD 9600
#define UBRR ((FOSC / (BAUD * 16L)) - 1)
#define STATE_IDLE 10
#define STATE_SERVO1 20
#define STATE_SERVO2 30
#define STATE_PWM 40
// Initialisierung Timer0
void timer0_init();
//// Initialisierung Timer1
void timer1_init();
// Initialisierung Timer2
void timer2_init();
//Initialisierung UART
void uart_init();
//Werte für das erste Signal
volatile unsigned char Array_Servo1[] = { 20, 45, 245, 54, 255, 54, 255, 54, 255, 54, 255, 54, 255, 54, 255, 54, 255, 35};
//Werte für das zweite Signal
volatile unsigned char Array_Servo2[] = { 20, 45, 245, 54, 255, 54, 255, 54, 255, 54, 255, 54, 255, 54, 255, 54, 255, 35};
//Zähler für ausgelösten Compare-Interrupt beim ersten Signal
volatile unsigned char NrCompare_Servo1 = 0;
//Zähler für ausgelösten Compare-Interrupt beim zweiten Signal
volatile unsigned char NrCompare_Servo2 = 0;
//Zähler für das erste Signal
volatile unsigned int Count_Servo1 = 0;
//Zähler für das zweite Signal
volatile unsigned int Count_Servo2 = 0;
unsigned char i, d;
//Hilfsaray zur Byteauswertung beim UART-Empfang für Servo1
unsigned char array1[8];
//Hilfsaray zur Byteauswertung beim UART-Empfang für Servo2
unsigned char array2[8];
//Zeiger für die Byteauswertung beim UART-Empfang für Servo1
unsigned char *tmp;
//Zeiger für die Byteauswertung beim UART-Empfang für Servo2
unsigned char *tmp2;
unsigned char c;
/*Funktion des Interrupts: Die Schleife wird 18 mal durchlaufen. Darin wird geschaut ob NrCompare_Servo1 in diesem Durchlauf
gerade oder ungerade ist und dementsprechend der Port ein oder ausgeschaltet. Hat NrCompare_Servo1 das ganze Array
abgearbeitet, fängt es wieder von vorne an.
Danach wird der neue Wert in das Register OCR2A geschrieben. Der Timer zählt dann bis zu diesem Wert, führt ein
Interrupt aus, schaltet den Port um und setzt den Timer wieder auf 0 (da CTC-Modus). Das ergibt hinterher ein
Signal mit einem dauernden Highpegel und neun "verschiedenen" Lowpegeln. Also erster Wert Array_Servo1[0] = Highpegel,
zweiter Wert Array_Servo1[1] = Lowpegel usw.
Count_Servo1 wird dann noch bis 8216 hochgezählt, um zwischen den Signalen eine Pause von ca. 90ms zu erzeugen.*/
ISR(TIMER2_COMPA_vect)
{
//erstes Signal
{
if(Count_Servo1 <= 17 ){ //Schleife wird 18 mal durchlaufen, also für jeden Wert des Array_Servo1 ein mal
if(NrCompare_Servo1 % 2 == 0) //Wenn gerade, dann ausschalten
PORTC &= ~(1 << PC0);
else
{PORTC |= (1 << PC0);} //Wenn ungerade, dann einschalten
NrCompare_Servo1++; //Wird bei jedem Interrupt um eins hochgezählt
if( NrCompare_Servo1 == sizeof(Array_Servo1) / sizeof(unsigned char) )
NrCompare_Servo1 = 0;
OCR2A = Array_Servo1[ NrCompare_Servo1]; // Den Timer damit laden
}
else
{PORTC |= (1 << PC0);} //Highpegel während der 90ms Pause
}
//Zweits Signal
{
if((Count_Servo2 >= 19) && (Count_Servo2 <= 36)){
if(NrCompare_Servo2 % 2 == 0)
PORTC &= ~(1 << PC2);
else
{PORTC |= (1 << PC2);}
NrCompare_Servo2++;
if( NrCompare_Servo2 == sizeof(Array_Servo2) / sizeof(unsigned char) )
NrCompare_Servo2 = 0;
OCR2A = Array_Servo2[NrCompare_Servo2]; // Den Timer damit laden
}
else
{PORTC |= (1 << PC2);}
}
Count_Servo1++;
if(Count_Servo1 == 8216) //erzeugt eine pause von ca.90ms
Count_Servo1 = 0;
Count_Servo2++;
if(Count_Servo2 == 8216) ////erzeugt eine pause von ca.90ms
Count_Servo2 = 0;
}
void timer2_init()
{
DDRC = 0xFF; // PORTC als Ausgang schalten
PORTC = 0x00; // Alle Ausgaenge auf 0 schalten
OCR2A = 0;
TCCR2B |= (1 << CS21); // Teiler 8
TCCR2A |= (1 << WGM21); // CTC Modus
TIMSK2 |= (1 << OCIE2A); // Timer 2 Compare Interrupt enable
}
/* Timer0 initialisieren */
void timer1_init()
{
OCR1A = 100; //Wert 100 im Compare Register setzen
DDRB = 0xff; // Als Ausgänge
PORTB = 0x00;
TCCR1A = (1<<COM1A1)|(1<<COM1A0)|(1<<WGM10); //PWM Phase Correct
TCCR1B = (1<<CS11) | (1 << WGM12); // No prescaling
}
void uart_init()
{
DDRB |= (1 << PB2) | (1 << PB4);
/* Aktivieren des Empfängers, des Senders und des "Daten empfangen"-Interrupts */
UCSR0B = (1<<RXCIE0)|(1<<RXEN0)|(1<<TXEN0);
/* baud rate*/
UBRR0H = (unsigned char) (UBRR>>8);
UBRR0L = (unsigned char) UBRR;
/* Frame Format: 8Data-Bit, 2Stop-Bit*/
UCSR0C = (1 << USBS0) | (3 << UCSZ00);
}
// Das Hauptprogramm (Einsprungpunkt)
int main()
{
//UART initialisieren
uart_init();
//Timer1 initialisieren
timer1_init();
//Timer2 initialisieren
timer2_init();
// Interrupts aktivieren
sei();
// Eine Endlosschleife.
while (1)
{}
}
ISR(USART_RX_vect)
{
static unsigned char state = STATE_IDLE;
c = UDR0;
switch (state)
{
case STATE_IDLE:
if(c == 'b')
{
state=STATE_SERVO1;
}
if(c == 'c')
{
state=STATE_SERVO2;
}
if(c == 'a')
{
state=STATE_PWM;
}
break;
case STATE_SERVO1:
tmp = array1;
for( i = 1; i; i *= 2 )
*(tmp++) = (c&i) ? 54 : 35;
Array_Servo1[3] = array1[0];
Array_Servo1[5] = array1[1];
Array_Servo1[7] = array1[2];
Array_Servo1[9] = array1[3];
Array_Servo1[11] = array1[4];
Array_Servo1[13] = array1[5];
Array_Servo1[15] = array1[6];
Array_Servo1[17] = array1[7];
state = STATE_IDLE;
break;
case STATE_SERVO2:
tmp2 = array2;
for( i = 1; i; i *= 2 )
*(tmp2++) = (c&i) ? 54 : 35;
Array_Servo2[3] = array2[0];
Array_Servo2[5] = array2[1];
Array_Servo2[7] = array2[2];
Array_Servo2[9] = array2[3];
Array_Servo2[11] = array2[4];
Array_Servo2[13] = array2[5];
Array_Servo2[15] = array2[6];
Array_Servo2[17] = array2[7];
state = STATE_IDLE;
break;
case STATE_PWM:
OCR1A = c;
state = STATE_IDLE;
break;
default:
break;
}
}
Lesezeichen