Hallo
Interruptlösungen sind schwierig weil die RP6-Lib schon alle Interrupts belegt. Ich hatte mir mal einen Ansatz (für 8 Servos an den LEDs und SCL/SDA) mit der ADC-ISR zusammengebastelt. Mit Servo_On() wird der ADC in den Dauerbetrieb (freeruning) mit ISR geschaltet (der ADC_Task könnte dabei übrigends weiterverwendet werden), mit Servo_Off() schaltet man die Servoansteuerung wieder aus und den ADC auf Lib-Einstellungen. Leider ist die Auflösung der Servoschritte nicht sehr groß, aber dafür funktioniert es mit der Lib zusammen:
Code:
// Domino Day für den RP6 mit neuem Greifarm und ADC-ISR 19.1.2008 mic
#include "RP6RobotBaseLib.h"
uint16_t s1, s2, s3, s4 ,s5, s6;
void servo_ON(void)
{
cli();
// Freeruning, 5V-Ref, ISR enable, prescale /32 ((8MHZ/32)/12,5 sind ca. 20kHz bzw. 0,05us)
// AVCC with external capacitor at AREF pin, Ergebniss linksbündig, Kanal ADC7 (UBAT)
ADMUX = (0<<REFS1) | (1<<REFS0) | (1<<ADLAR) | 7;
// setzte free running triggern
SFIOR = (0<<ADTS2) | (0<<ADTS1) | (0<<ADTS0);
// Interrupt ein, Wandler einschalten, prescaller /32
ADCSRA = (1<<ADIE) | (1<<ADEN) | (1<<ADPS2) | (0<<ADPS1) | (1<<ADPS0);
// Autotriggern bedeutet jetzt free running aktivieren, altes Flag löschen
ADCSRA |= (1<<ADATE) | (1<<ADIF);
// Initialisierung starten
ADCSRA |= (1<<ADSC);
// und noch die wohl eher unnötige Initiallesung
while (!(ADCSRA & (1<<ADIF)));
ADCSRA |= (1<<ADIF);
DDRC |= 0x70; // LED1-3 auf Ausgang und low
PORTC &= ~0x70;
DDRB |= 0x83; // LED4-6 auf Ausgang und low
PORTB &= ~0x83;
DDRC |= 0x3; // SCL und SDA auf Ausgang und low
PORTC &= ~0x3;
sei();
}
void servo_OFF(void)
{
cli();
// Initialize ADC: (Defaultsetup der RP6-Library)
ADMUX = 0; //external reference
ADCSRA = (0<<ADIE) | (0<<ADEN) | (1<<ADPS2) | (1<<ADPS1) | (1<<ADIF);
SFIOR = 0;
sei();
setLEDs(0); // LEDs restaurieren
}
int main(void)
{
initRobotBase();
s1=25;
s2=25;
s3=25;
s4=25;
s5=25;
s6=25;
servo_ON();
setLEDs(63);
mSleep(2000);
setLEDs(0);
while(1)
{
mSleep(1000);
s1=40;
mSleep(1000);
s1=25;
mSleep(1000);
s2=35;
mSleep(1000);
s2=15;
}
return 0;
}
ISR(ADC_vect)
{
static uint16_t count=0;
(count>s1)?(PORTC&=~SL1):(PORTC|=SL1);
(count>s2)?(PORTC&=~SL2):(PORTC|=SL2);
(count>s3)?(PORTC&=~SL3):(PORTC|=SL3);
(count>s4)?(PORTB&=~SL4):(PORTB|=SL4);
(count>s5)?(PORTB&=~SL5):(PORTB|=SL5);
(count>s6)?(PORTB&=~SL6):(PORTB|=SL6);
(count>s1)?(PORTC&=~1):(PORTC|=1); // SCL
(count>s2)?(PORTC&=~2):(PORTC|=2); // SDA
(count<500)?count++:(count=0);
}
(Für eine bessere Auflösung könnte man den ADC-Prescaller noch verkleinern)
Gruß
mic
Lesezeichen