Hola a tod@s
Creo que se puede simplificar un poco el codigo utilizando bit_set() y bit_clear, en vez de output_high() y output_low() para poner el servo en alto y en bajo respectivamente, siempre que se disponga de un puerto completo para ello.
Ademas si el micro lo permite, creo que es mejor utilizar #int_CCPx para controlar el tiempo que esta en alto el servo, ya que hace que no sea tan critica la velocidad del micro y se pueden uilizar micros mas lentos.
Un ejemplo de como yo lo hago habitualmente:
////////////////////////////////////////////////////////////////////////////////////
//
// Moviendo 8 servos con un solo timer
//
//
// Propósito: Mover hasta 8 servos eficientemente
//
// Conectar 8 servos al PORT_B
//
////////////////////////////////////////////////////////////////////////////////////
#include <16f876.h>
#fuses HS,NOWDT,NOPROTECT,NOPUT,NOBROWNOUT,NOLVP,NOCPD,NODEBUG,NOWRT
#use delay(clock=20000000) //Cambiar segun el cristal utilizado
#define VAL_TIMER1 53000 // 65536-53000=12536 * 0,0002 = 2,5 milisegundos
float const uSxTick = 0.2; // Microsegundos por Tick de TMR1 a 20 Mhz
int8 servo=0; // Numero de servo
int1 flag_timer1=FALSE;
#int_timer1
void handle_timer1_int() // Se activa cada 2,5 ms
{
flag_timer1=TRUE;
set_timer1(VAL_TIMER1); // 65536-53000=12536*0,0002 = 2,5 ms
}
#int_ccp2 // Interrupción timer1 modo compare
void handle_ccp2_int()
{
bit_clear(*6,servo); // Pone en bajo el servo. Igual que output_low(PIN_Bx) pero le puedo pasar un parametro. *6=PORTB
}
////////////////////////////////////////////////////////////////////////////////////
//
// PROGRAMA PRINCIPAL
//
////////////////////////////////////////////////////////////////////////////////////
void main()
{
////////////////////////////////////////// INICIALIZACIONES GENERALES
delay_ms(333); // Espero a que todo se estabilice e ...
disable_interrupts(global); // Inicializo el Micro y ...
disable_interrupts(int_timer1); // deshabilitando todo lo no necesario ...
disable_interrupts(int_rda);
disable_interrupts(int_ext);
setup_adc_ports(NO_ANALOGS);
setup_adc(ADC_OFF);
setup_timer_1(T1_INTERNAL | T1_DIV_BY_1);
setup_timer_2(T2_DISABLED,0,1);
setup_ccp2(CCP_COMPARE_INT); // Configura CCP2 en modo COMPARE
set_timer1(VAL_TIMER1); // 65536-53000=12536*0,0002 = 2,5 ms
// Habilito las interrupciones necesarias
enable_interrupts(int_timer1); //Int timer 1
enable_interrupts(int_ccp2); // Habilito la interrpción INT_CCP2
enable_interrupts(global); //Habilita interrupciones
do
{
if(flag_timer1==TRUE) // Cuando se activa la int_timer1 -> cada 2,5 ms
{
servo++; //Controla secuencialmente cada servo
if (servo>=9) servo=1;
bit_set(*6,servo); // Pongo en alto el servo. Igual que output_high(PIN_Bx) pero le puedo pasar un parametro. *6=PORTB
CCP_2 = VAL_TIMER + pos_servo(servo); // Cargo CCP con el tiempo que tiene que estar en alto el servo
// La funcion pos_servo() debe devolver la posicion del servo en microsegundos
flag_timer1=FALSE;
}
}
while (TRUE);
}
Saludos a tod@s