#include <16f877.h>
#fuses HS,NOWDT,NOPROTECT,NOLVP,NOBROWNOUT,PUT
#use delay (clock=20000000)
#USE RS232 (baud=9600,bits=8,parity=N,xmit=PIN_C6,rcv=PIN_C7)
#use fast_io(A)
#use fast_io(B)
#use fast_io(C)
#use fast_io(D)
#use fast_io(E)
#byte PORTA = 0x05
#byte PORTB = 0x06
#byte PORTC = 0x07
#byte PORTD = 0x08
#byte PORTE = 0x09
#bit servo_00 = PORTB.0
#bit servo_01 = PORTB.1
#bit servo_02 = PORTB.2
#bit servo_03 = PORTB.3
#bit servo_04 = PORTB.4
#bit servo_05 = PORTB.5
#bit servo_06 = PORTB.6
#bit servo_07 = PORTB.7
#bit servo_08 = PORTD.0
#bit servo_09 = PORTD.1
#bit servo_10 = PORTD.2
#bit servo_11 = PORTD.3
#bit servo_12 = PORTD.4
#bit servo_13 = PORTD.5
#bit servo_14 = PORTD.6
#bit servo_15 = PORTD.7
#define n 16// número de servos
//para otro número de servos hay que hacer mediciones de tiempo
#define max_theCount 200// 200*100us=20ms
#define derecha 26// Éste valor fué determinado simulando el proceso
// en el proteus pero en teoría debería ser (25) 25*100us=2,5ms
// Sería cuestión de probar con servos reales y ajustar valores ;-)
#define centro 15// 15*100us=1,5ms
#define izquierda 5// 5*100us =0,5ms
#define val_timer0 88
int8 theCount=1;
int8 duty[n];
#INT_TIMER0
void isr_timer0(){// Cada 100us llega aqui de forma cíclica
#asm
nop
#endasm
if (duty[0] >= theCount)
{
servo_00=1;
}
else
{
servo_00=0;
#asm
nop
#endasm
}
if (duty[1] >= theCount)
{
servo_01=1;
}
else
{
servo_01=0;
#asm
nop
#endasm
}
if (duty[2] >= theCount)
{
servo_02=1;
}
else
{
servo_02=0;
#asm
nop
#endasm
}
if (duty[3] >= theCount)
{
servo_03=1;
}
else
{
servo_03=0;
#asm
nop
#endasm
}
if (duty[4] >= theCount)
{
servo_04=1;
}
else
{
servo_04=0;
#asm
nop
#endasm
}
if (duty[5] >= theCount)
{
servo_05=1;
}
else
{
servo_05=0;
#asm
nop
#endasm
}
if (duty[6] >= theCount)
{
servo_06=1;
}
else
{
servo_06=0;
#asm
nop
#endasm
}
if (duty[7] >= theCount)
{
servo_07=1;
}
else
{
servo_07=0;
#asm
nop
#endasm
}
if (duty[8] >= theCount)
{
servo_08=1;
}
else
{
servo_08=0;
#asm
nop
#endasm
}
if (duty[9] >= theCount)
{
servo_09=1;
}
else
{
servo_09=0;
#asm
nop
#endasm
}
if (duty[10] >= theCount)
{
servo_10=1;
}
else
{
servo_10=0;
#asm
nop
#endasm
}
if (duty[11] >= theCount)
{
servo_11=1;
}
else
{
servo_11=0;
#asm
nop
#endasm
}
if (duty[12] >= theCount)
{
servo_12=1;
}
else
{
servo_12=0;
#asm
nop
#endasm
}
if (duty[13] >= theCount)
{
servo_13=1;
}
else
{
servo_13=0;
#asm
nop
#endasm
}
if (duty[14] >= theCount)
{
servo_14=1;
}
else
{
servo_14=0;
#asm
nop
#endasm
}
if (duty[15] >= theCount)
{
servo_15=1;
}
else
{
servo_15=0;
#asm
nop
#endasm
}
theCount=theCount+1;
if (theCount>max_theCount)
{
theCount=1;
}
else
{
delay_us(1);
#asm
nop
#endasm
}
set_timer0(val_timer0);
}
/////////////////////////////////////// PRINCIPAL /////////////////////////////////////
void main()
{
int k;
int8 i=0;// es el índice exclusivo de duty[] en la recepción serial
int1 band=0;
set_tris_b(0x00);
set_tris_c(0b10000000);
set_tris_d(0x00);
PORTB=0x00;
PORTD=0x00;
port_b_pullups(FALSE);
for(k=0;k<=(n-1);k++)
duty[k]=izquierda;//
setup_adc_ports(NO_ANALOGS);
setup_adc(ADC_OFF);
setup_timer_1(T1_DISABLED);
setup_timer_2(T2_DISABLED,0,1);
setup_timer_0(RTCC_DIV_2);
set_timer0(val_timer0);
enable_interrupts(INT_TIMER0);
enable_interrupts(GLOBAL);
while (1)
{
// Recepción de datos
if (kbhit()){
if (band==0){
i=getc();
band=1;
}
else{
duty[i]=getc();
band=0;
}
}
}
}if (duty[0] >= theCount) será cierta 5 veces 100us lo que es igual a 500us=0,5ms por lo tanto el pin RB0 estará en alto ese tiempo y el resto en bajo, facilmente podemos deducir que para 2,5ms habría que cargar duty[0] con 25 ;-)if (duty[0] >= theCount)#include <18F4550.h>
#fuses HSPLL,NOWDT,NOPROTECT,NOLVP,NODEBUG,USBDIV,PLL5,CPUDIV1,VREGEN,NOPBADEN,NOBROWNOUT
#use delay(clock=48000000)//48MHz
#USE RS232 (baud=9600,bits=8,parity=N,xmit=PIN_C6,rcv=PIN_C7)
//#build(reset=0x000800,interrupt=0x000808:0x000818)
// Necesario para indicarle al compilador a partir de donde alojar mi programa
// Si se quiere usar bootloader se pueden habilitar estás dos líneas
//#ORG 0x000, 0x07FF {} // Espacio reservado para alojar el bootloader
#byte PORTA = 0xF80// Son las direcciones de memoria de los puertos en este PIC
#byte PORTB = 0xF81
#byte PORTC = 0xF82
#byte PORTD = 0xF83
#byte PORTE = 0xF84
/////////////////////////////////////////////////////////////////////////////
//
// CCS Library dynamic defines. For dynamic configuration of the CCS Library
// for your application several defines need to be made. See the comments
// at usb.h for more information
//
/////////////////////////////////////////////////////////////////////////////
#define USB_HID_DEVICE FALSE //deshabilitamos el uso de las directivas HID
#define USB_EP1_TX_ENABLE USB_ENABLE_BULK //turn on EP1(EndPoint1) for IN bulk/interrupt transfers
#define USB_EP1_RX_ENABLE USB_ENABLE_BULK //turn on EP1(EndPoint1) for OUT bulk/interrupt transfers
#define USB_EP1_TX_SIZE 2 //size to allocate for the tx endpoint 1 buffer
#define USB_EP1_RX_SIZE 2 //size to allocate for the rx endpoint 1 buffer
/////////////////////////////////////////////////////////////////////////////
//
// If you are using a USB connection sense pin, define it here. If you are
// not using connection sense, comment out this line. Without connection
// sense you will not know if the device gets disconnected.
// (connection sense should look like this:
// 100k
// VBUS-----+----/\/\/\/\/\----- (I/O PIN ON PIC)
// |
// +----/\/\/\/\/\-----GND
// 100k
// (where VBUS is pin1 of the USB connector)
//
/////////////////////////////////////////////////////////////////////////////
//#define USB_CON_SENSE_PIN PIN_B2 //CCS 18F4550 development kit has optional conection sense pin
/////////////////////////////////////////////////////////////////////////////
//
// Include the CCS USB Libraries. See the comments at the top of these
// files for more information
//
/////////////////////////////////////////////////////////////////////////////
#include <pic18_usb.h> //Microchip PIC18Fxx5x Hardware layer for CCS's PIC USB driver
#include <PicUSB.h> //Configuración del USB y los descriptores para este dispositivo
#include <usb.c> //handles usb setup tokens and get descriptor reports
#use fast_io(A)
#use fast_io(B)
#use fast_io(C)
#use fast_io(D)
#use fast_io(E)
#bit servo_00 = PORTB.0
#bit servo_01 = PORTB.1
#bit servo_02 = PORTB.2
#bit servo_03 = PORTB.3
#bit servo_04 = PORTB.4
#bit servo_05 = PORTB.5
#bit servo_06 = PORTB.6
#bit servo_07 = PORTB.7
#bit servo_08 = PORTD.0
#bit servo_09 = PORTD.1
#bit servo_10 = PORTD.2
#bit servo_11 = PORTD.3
#bit servo_12 = PORTD.4
#bit servo_13 = PORTD.5
#bit servo_14 = PORTD.6
#bit servo_15 = PORTD.7
#define i_usb recibe[0]// es el índice que se recibe vía usb
#define pos_usb recibe[1]// es la posición que se recibe vía usb
#define n 16// número de servos
//para otro número de servos hay que hacer mediciones de tiempo
#define max_theCount 200// 200*100us=20ms
#define derecha 25// 25*100us=2,5ms
#define centro 15// 15*100us=1,5ms
#define izquierda 5// 5*100us =0,5ms
#define val_timer0 127
int8 theCount=1;
int8 duty[n];
#INT_TIMER0
void isr_timer0(){
delay_cycles(5);
if (duty[0] >= theCount)// Cada 100us llega aqui de forma cíclica
{
servo_00=1;
}
else
{
servo_00=0;
#asm
nop
#endasm
}
if (duty[1] >= theCount)
{
servo_01=1;
}
else
{
servo_01=0;
#asm
nop
#endasm
}
if (duty[2] >= theCount)
{
servo_02=1;
}
else
{
servo_02=0;
#asm
nop
#endasm
}
if (duty[3] >= theCount)
{
servo_03=1;
}
else
{
servo_03=0;
#asm
nop
#endasm
}
if (duty[4] >= theCount)
{
servo_04=1;
}
else
{
servo_04=0;
#asm
nop
#endasm
}
if (duty[5] >= theCount)
{
servo_05=1;
}
else
{
servo_05=0;
#asm
nop
#endasm
}
if (duty[6] >= theCount)
{
servo_06=1;
}
else
{
servo_06=0;
#asm
nop
#endasm
}
if (duty[7] >= theCount)
{
servo_07=1;
}
else
{
servo_07=0;
#asm
nop
#endasm
}
if (duty[8] >= theCount)
{
servo_08=1;
}
else
{
servo_08=0;
#asm
nop
#endasm
}
if (duty[9] >= theCount)
{
servo_09=1;
}
else
{
servo_09=0;
#asm
nop
#endasm
}
if (duty[10] >= theCount)
{
servo_10=1;
}
else
{
servo_10=0;
#asm
nop
#endasm
}
if (duty[11] >= theCount)
{
servo_11=1;
}
else
{
servo_11=0;
#asm
nop
#endasm
}
if (duty[12] >= theCount)
{
servo_12=1;
}
else
{
servo_12=0;
#asm
nop
#endasm
}
if (duty[13] >= theCount)
{
servo_13=1;
}
else
{
servo_13=0;
#asm
nop
#endasm
}
if (duty[14] >= theCount)
{
servo_14=1;
}
else
{
servo_14=0;
#asm
nop
#endasm
}
if (duty[15] >= theCount)
{
servo_15=1;
}
else
{
servo_15=0;
#asm
nop
#endasm
}
theCount=theCount+1;
if (theCount>max_theCount)
{
theCount=1;
}
else
{
delay_us(1);
#asm
nop
#endasm
}
set_timer0(val_timer0);
}
/////////////////////////////////////// PRINCIPAL /////////////////////////////////////
void main()
{
int k;
int8 i=0;// es el índice exclusivo de duty[] en la recepción serial
int1 band=0;
int8 recibe[2];// Buffer de recepción vía usb
//int8 envia[2];// Habilitar en caso de necesitar
set_tris_b(0x00);
set_tris_c(0b10000000);
set_tris_d(0x00);
PORTB=0x00;
PORTD=0x00;
port_b_pullups(FALSE);
for(k=0;k<=(n-1);k++)
duty[k]=centro;//
setup_adc_ports(NO_ANALOGS);
setup_adc(ADC_OFF);
setup_timer_0(RTCC_DIV_8 | RTCC_8_BIT);
set_timer0(val_timer0);
enable_interrupts(INT_TIMER0);
enable_interrupts(GLOBAL);
usb_init();//inicializamos el USB
usb_task();//habilita periférico usb e interrupciones
usb_wait_for_enumeration();//esperamos hasta que el PicUSB sea configurado por el host
while (TRUE)
{
if(usb_enumerated())//si el PicUSB está configurado
//if (TRUE)
{
// Recepción de datos via rs232
if (kbhit()){
if (band==0){
i=getc();
band=1;
}
else{
duty[i]=getc();
band=0;
}
}
// Recepción vía USB
if (usb_kbhit(1))//El endpoint de salida contiene datos del host (EP1)?
{
usb_get_packet(1, recibe, 2);// Recibimos los 2 bytes: (servo,pos)
duty[i_usb]=pos_usb;
}
}
}
}
usb_wait_for_enumeration();colocar://usb_wait_for_enumeration();porque sino el pic se queda allí en el MPLABif(usb_enumerated())//si el PicUSB está configurado
//if (TRUE)//if(usb_enumerated())//si el PicUSB está configurado
if (TRUE)La idea es buena, pero la precisión es muy pequeña. Solo 20 posiciones por servo. Lo normal son 256 posiciones por servo.
Un saludo
setup_timer_0(RTCC_DIV_2);
set_timer0(val_timer0);
enable_interrupts(INT_TIMER0);
enable_interrupts(GLOBAL); #include <18F4550.h>
#fuses HSPLL,NOWDT,NOPROTECT,NOLVP,NODEBUG,USBDIV,PLL5,CPUDIV1,VREGEN,NOPBADEN,NOBROWNOUT
#use delay(clock=48000000)//48MHz
#USE RS232 (baud=9600,bits=8,parity=N,xmit=PIN_C6,rcv=PIN_C7)
//#build(reset=0x000800,interrupt=0x000808:0x000818)
// Necesario para indicarle al compilador a partir de donde alojar mi programa
// Si se quiere usar bootloader se pueden habilitar estás dos líneas
//#ORG 0x000, 0x07FF {} // Espacio reservado para alojar el bootloader
#byte PORTA = 0xF80// Son las direcciones de memoria de los puertos en este PIC
#byte PORTB = 0xF81
#byte PORTC = 0xF82
#byte PORTD = 0xF83
#byte PORTE = 0xF84
/////////////////////////////////////////////////////////////////////////////
//
// CCS Library dynamic defines. For dynamic configuration of the CCS Library
// for your application several defines need to be made. See the comments
// at usb.h for more information
//
/////////////////////////////////////////////////////////////////////////////
#define USB_HID_DEVICE FALSE //deshabilitamos el uso de las directivas HID
#define USB_EP1_TX_ENABLE USB_ENABLE_BULK //turn on EP1(EndPoint1) for IN bulk/interrupt transfers
#define USB_EP1_RX_ENABLE USB_ENABLE_BULK //turn on EP1(EndPoint1) for OUT bulk/interrupt transfers
#define USB_EP1_TX_SIZE 2 //size to allocate for the tx endpoint 1 buffer
#define USB_EP1_RX_SIZE 2 //size to allocate for the rx endpoint 1 buffer
/////////////////////////////////////////////////////////////////////////////
//
// If you are using a USB connection sense pin, define it here. If you are
// not using connection sense, comment out this line. Without connection
// sense you will not know if the device gets disconnected.
// (connection sense should look like this:
// 100k
// VBUS-----+----/\/\/\/\/\----- (I/O PIN ON PIC)
// |
// +----/\/\/\/\/\-----GND
// 100k
// (where VBUS is pin1 of the USB connector)
//
/////////////////////////////////////////////////////////////////////////////
//#define USB_CON_SENSE_PIN PIN_B2 //CCS 18F4550 development kit has optional conection sense pin
/////////////////////////////////////////////////////////////////////////////
//
// Include the CCS USB Libraries. See the comments at the top of these
// files for more information
//
/////////////////////////////////////////////////////////////////////////////
#include <pic18_usb.h> //Microchip PIC18Fxx5x Hardware layer for CCS's PIC USB driver
#include <PicUSB.h> //Configuración del USB y los descriptores para este dispositivo
#include <usb.c> //handles usb setup tokens and get descriptor reports
#use fast_io(A)
#use fast_io(B)
#use fast_io(C)
#use fast_io(D)
#use fast_io(E)
#bit servo_00 = PORTB.0
#bit servo_01 = PORTB.1
#bit servo_02 = PORTB.2
#bit servo_03 = PORTB.3
#bit servo_04 = PORTB.4
#bit servo_05 = PORTB.5
#bit servo_06 = PORTB.6
#bit servo_07 = PORTB.7
#bit servo_08 = PORTD.0
#bit servo_09 = PORTD.1
#bit servo_10 = PORTD.2
#bit servo_11 = PORTD.3
#bit servo_12 = PORTD.4
#bit servo_13 = PORTD.5
#bit servo_14 = PORTD.6
#bit servo_15 = PORTD.7
#define i_usb recibe[0]// es el índice que se recibe vía usb
#define byte_alto_usb recibe[1]//
#define byte_bajo_usb recibe[2]//
#define n 16// número de servos
//para otro número de servos hay que hacer mediciones de tiempo
#define periodo 60000//
#define derecha 7416//
#define centro 4417//
#define izquierda 1417//
#define inicio 7416
int8 i_int=1;// Índice de la interrupción del TIMER1
int8 x=0;// Número de interrupciones
int16 VTI_Servo[n+1], VTI[n+1];
// VTI_Servo[] contiene el estado de los servos y VTI los ticks de las proximas
// interrupciones
int16 TICK_dif[n];
int16 TICK[]={inicio,inicio,inicio,inicio,inicio,inicio,inicio,inicio,inicio,inicio,inicio,inicio,inicio,inicio,inicio,inicio};
int1 band_inicio=0;
#INT_TIMER1
void isr_timer1(){
servo_00=bit_test(VTI_Servo[i_int],0);
servo_01=bit_test(VTI_Servo[i_int],1);
servo_02=bit_test(VTI_Servo[i_int],2);
servo_03=bit_test(VTI_Servo[i_int],3);
servo_04=bit_test(VTI_Servo[i_int],4);
servo_05=bit_test(VTI_Servo[i_int],5);
servo_06=bit_test(VTI_Servo[i_int],6);
servo_07=bit_test(VTI_Servo[i_int],7);
servo_08=bit_test(VTI_Servo[i_int],8);
servo_09=bit_test(VTI_Servo[i_int],9);
servo_10=bit_test(VTI_Servo[i_int],10);
servo_11=bit_test(VTI_Servo[i_int],11);
servo_12=bit_test(VTI_Servo[i_int],12);
servo_13=bit_test(VTI_Servo[i_int],13);
servo_14=bit_test(VTI_Servo[i_int],14);
servo_15=bit_test(VTI_Servo[i_int],15);
set_timer1(VTI[i_int]);
i_int++;
}
/////////////////////////////////////// PRINCIPAL /////////////////////////////////////
void main()
{
int k, kk;
int8 i=0;// es el índice exclusivo de duty[] en la recepción serial
int8 dato=0;
int8 recibe[3];// Buffer de recepción vía usb
//int8 envia[2];// Habilitar en caso de necesitar
int16 aux;
int8 byte_alto, byte_bajo;// Son los baytes alto y bajo de la recepción
// Serial rs232
set_tris_b(0x00);
set_tris_c(0b10000000);
set_tris_d(0x00);
PORTB=0x00;
PORTD=0x00;
port_b_pullups(FALSE);
disable_interrupts(global);
setup_adc_ports(NO_ANALOGS);
setup_adc(ADC_OFF);
setup_timer_1(T1_INTERNAL | T1_DIV_BY_4);
usb_init();//inicializamos el USB
usb_task();//habilita periférico usb e interrupciones
usb_wait_for_enumeration();//esperamos hasta que el PicUSB sea configurado por el host
while (TRUE)
{
if(usb_enumerated())//si el PicUSB está configurado
//if (TRUE)
{
if (i_int>x){// Esto se repite al terminar un ciclo completo
// y la 1era vez que se ejecuta éste código también
// Hacemos una copia de TICK[] en TICK_dif[]
for (k=0; k<=n-1; k++) TICK_dif[k]=TICK[k];
// A continuación ordenamos TICK_dif[] de menor a mayor
for (k=0; k<=n-1; k++){
for (kk=k+1; kk<=n-1; kk++){
if (TICK_dif[k]>TICK_dif[kk]){
aux=TICK_dif[kk];
TICK_dif[kk]=TICK_dif[k];
TICK_dif[k]=aux;
}
}
}// Aqui ya terminamos de ordenar de menor a mayor TICK_dif[]
// Ahora vamor a eliminar los repetidos y nos quedamos con los diferentes
// solamente y a la vemos sabemos cuántos son
k=0;
for (kk=1; kk<=n-1;kk++){
if (TICK_dif[k]!=TICK_dif[kk]){
k++;
TICK_dif[k]=TICK_dif[kk];
}
}
x=k+1; // (x+1) es el número de interrupciones que se hacen
i_int=0; // índice de interrupciones
// Generamos el vector con los tiempos de las interrupciones
VTI[0]=65535-TICK_dif[0];//
// Una vez que se entre en la 1era interrupción por desborde del
// timer1 éste será el valor con que se cargará dicho contador
// para que ocurra la próxima interrupción.
VTI[x]=65535-periodo+TICK_dif[x-1];// periodo=60000
// Con éste valor se cargará el contador la última vez que entra
// en el manejo de interrupciones en un ciclo, cada ciclo es de
// 20ms, por lo tanto será el tiempo que esperará para que se
// cumpla dicho tiempo
// 60000ticks*(1/12000000)*4=20ms
// a éste valor le resto lo que ha transcurrido previamente
// Próximanete genramos los tiempos de duración de cada interrupción
for (k=1; k<=x-1; k++){
VTI[k]=65535-(TICK_dif[k]-TICK_dif[k-1]);
}
// Ahora vamos a generar el vector de los estados de los pines
// en las interrupciones VTI_Servo[]
for (k=0; k<=x-1;k++){
for (kk=0; kk<=n-1; kk++){
if (TICK_dif[k]<=TICK[kk]){
bit_set(VTI_Servo[k], kk);
}
else bit_clear(VTI_Servo[k], kk);
}
}
}
// Recepción de datos via rs232//
if (kbhit()){
switch (dato){
case 0:
i=getc();
dato=1;
break;
case 1:
byte_alto=getc();// recibe el byte alto
dato=2;
break;
case 2:
byte_bajo=getc();// recibe el byte bajo
TICK[i]=256*byte_alto+byte_bajo;
dato=0;
break;
}
}
// Recepción vía USB
if (usb_kbhit(1))//El endpoint de salida contiene datos del host (EP1)?
{
usb_get_packet(1, recibe, 3);// Recibimos los 3 bytes:
// (servo,byte_alto_usb, byte_bajo_usb)
TICK[i_usb]=256*byte_alto_usb+byte_bajo_usb;
}
if (band_inicio==0){// Se ejecuta una sola vez
set_timer1(65535-60000);// 65535-60000
// espero 20ms para empezar a mover los servos
enable_interrupts(INT_TIMER1);
enable_interrupts(GLOBAL);
band_inicio=1;
}
}
}
}
#include <18F4550.h>
#fuses HSPLL,NOWDT,NOPROTECT,NOLVP,NODEBUG,USBDIV,PLL5,CPUDIV1,VREGEN,NOPBADEN,NOBROWNOUT
#use delay(clock=48000000)//48MHz
#USE RS232 (baud=9600,bits=8,parity=N,xmit=PIN_C6,rcv=PIN_C7)
//#build(reset=0x000800,interrupt=0x000808:0x000818)
// Necesario para indicarle al compilador a partir de donde alojar mi programa
// Si se quiere usar bootloader se pueden habilitar estás dos líneas
//#ORG 0x000, 0x07FF {} // Espacio reservado para alojar el bootloader
#byte PORTA = 0xF80// Son las direcciones de memoria de los puertos en este PIC
#byte PORTB = 0xF81
#byte PORTC = 0xF82
#byte PORTD = 0xF83
#byte PORTE = 0xF84
/////////////////////////////////////////////////////////////////////////////
//
// CCS Library dynamic defines. For dynamic configuration of the CCS Library
// for your application several defines need to be made. See the comments
// at usb.h for more information
//
/////////////////////////////////////////////////////////////////////////////
#define USB_HID_DEVICE FALSE //deshabilitamos el uso de las directivas HID
#define USB_EP1_TX_ENABLE USB_ENABLE_BULK //turn on EP1(EndPoint1) for IN bulk/interrupt transfers
#define USB_EP1_RX_ENABLE USB_ENABLE_BULK //turn on EP1(EndPoint1) for OUT bulk/interrupt transfers
#define USB_EP1_TX_SIZE 2 //size to allocate for the tx endpoint 1 buffer
#define USB_EP1_RX_SIZE 2 //size to allocate for the rx endpoint 1 buffer
/////////////////////////////////////////////////////////////////////////////
//
// If you are using a USB connection sense pin, define it here. If you are
// not using connection sense, comment out this line. Without connection
// sense you will not know if the device gets disconnected.
// (connection sense should look like this:
// 100k
// VBUS-----+----/\/\/\/\/\----- (I/O PIN ON PIC)
// |
// +----/\/\/\/\/\-----GND
// 100k
// (where VBUS is pin1 of the USB connector)
//
/////////////////////////////////////////////////////////////////////////////
//#define USB_CON_SENSE_PIN PIN_B2 //CCS 18F4550 development kit has optional conection sense pin
/////////////////////////////////////////////////////////////////////////////
//
// Include the CCS USB Libraries. See the comments at the top of these
// files for more information
//
/////////////////////////////////////////////////////////////////////////////
#include <pic18_usb.h> //Microchip PIC18Fxx5x Hardware layer for CCS's PIC USB driver
#include <PicUSB.h> //Configuración del USB y los descriptores para este dispositivo
#include <usb.c> //handles usb setup tokens and get descriptor reports
#use fast_io(A)
#use fast_io(B)
#use fast_io(C)
#use fast_io(D)
#use fast_io(E)
#bit servo_00 = PORTB.0
#bit servo_01 = PORTB.1
#bit servo_02 = PORTB.2
#bit servo_03 = PORTB.3
#bit servo_04 = PORTB.4
#bit servo_05 = PORTB.5
#bit servo_06 = PORTB.6
#bit servo_07 = PORTB.7
#bit servo_08 = PORTD.0
#bit servo_09 = PORTD.1
#bit servo_10 = PORTD.2
#bit servo_11 = PORTD.3
#bit servo_12 = PORTD.4
#bit servo_13 = PORTD.5
#bit servo_14 = PORTD.6
#bit servo_15 = PORTD.7
#define i_usb recibe[0]// es el índice que se recibe vía usb
#define byte_alto_usb recibe[1]//
#define byte_bajo_usb recibe[2]//
#define n 16// número de servos
//para otro número de servos hay que hacer mediciones de tiempo
#define ventana 29827//
#define derecha 29827//
#define centro 17827//
#define izquierda 5827//
#define inicio 17827
#define ventana_ciclos 26176// Valor determinado en simulaciones
int8 i_int=0;// Índice de la interrupción del TIMER1
int8 x=0;// Número de interrupciones
int16 VTI_Servo[n+1], VTI[n+1];
// VTI_Servo[] contiene el estado de los servos y VTI los ticks de las proximas
// interrupciones
int16 TICK_dif[n];
int16 TICK[]={inicio,inicio,inicio,inicio,inicio,inicio,inicio,inicio,inicio,inicio,inicio,inicio,inicio,inicio,inicio,inicio};
int1 band_inicio=0;
int8 ciclos=9;
#INT_TIMER1
void isr_timer1(){
int8 parte_baja, parte_alta;
if (i_int>x){
ciclos++;
set_timer1(65535-ventana_ciclos);//
}
else {
parte_baja=make8(VTI_Servo[i_int], 0);
parte_alta=make8(VTI_Servo[i_int], 1);
if (parte_baja & 0b00000001){
servo_00=1;
}
else {
servo_00=0;
delay_cycles(1);
}
if (parte_baja & 0b00000010){
servo_01=1;
}
else {
servo_01=0;
delay_cycles(1);
}
if (parte_baja & 0b00000100){
servo_02=1;
}
else {
servo_02=0;
delay_cycles(1);
}
if (parte_baja & 0b00001000){
servo_03=1;
}
else {
servo_03=0;
delay_cycles(1);
}
if (parte_baja & 0b00010000){
servo_04=1;
}
else {
servo_04=0;
delay_cycles(1);
}
if (parte_baja & 0b00100000){
servo_05=1;
}
else {
servo_05=0;
delay_cycles(1);
}
if (parte_baja & 0b01000000){
servo_06=1;
}
else {
servo_06=0;
delay_cycles(1);
}
if (parte_baja & 0b10000000){
servo_07=1;
}
else {
servo_07=0;
delay_cycles(1);
}
if (parte_alta & 0b00000001){
servo_08=1;
}
else {
servo_08=0;
delay_cycles(1);
}
if (parte_alta & 0b00000010){
servo_09=1;
}
else {
servo_09=0;
delay_cycles(1);
}
if (parte_alta & 0b00000100){
servo_10=1;
}
else {
servo_10=0;
delay_cycles(1);
}
if (parte_alta & 0b00001000){
servo_11=1;
}
else {
servo_11=0;
delay_cycles(1);
}
if (parte_alta & 0b00010000){
servo_12=1;
}
else {
servo_12=0;
delay_cycles(1);
}
if (parte_alta & 0b00100000){
servo_13=1;
}
else {
servo_13=0;
delay_cycles(1);
}
if (parte_alta & 0b01000000){
servo_14=1;
}
else {
servo_14=0;
delay_cycles(1);
}
if (parte_alta & 0b10000000){
servo_15=1;
}
else {
servo_15=0;
delay_cycles(1);
}
set_timer1(VTI[i_int]);
i_int++;
}
}
/////////////////////////////////////// PRINCIPAL /////////////////////////////////////
void main()
{
int k, kk;
int8 i=0;// es el índice exclusivo de duty[] en la recepción serial
int8 dato=0;
int8 recibe[3];// Buffer de recepción vía usb
//int8 envia[2];// Habilitar en caso de necesitar
int16 aux;
int8 byte_alto, byte_bajo;// Son los baytes alto y bajo de la recepción
// Serial rs232
set_tris_b(0x00);
set_tris_c(0b10000000);
set_tris_d(0x00);
PORTB=0x00;
PORTD=0x00;
port_b_pullups(FALSE);
disable_interrupts(global);
setup_adc_ports(NO_ANALOGS);
setup_adc(ADC_OFF);
setup_timer_1(T1_INTERNAL | T1_DIV_BY_1);
usb_init();//inicializamos el USB
usb_task();//habilita periférico usb e interrupciones
usb_wait_for_enumeration();//esperamos hasta que el PicUSB sea configurado por el host
while (TRUE)
{
if(usb_enumerated())//si el PicUSB está configurado
//if (TRUE)
{
if (ciclos>8){// Esto se repite al terminar un ciclo completo de 20ms
// y la 1era vez que se ejecuta éste código también
ciclos=1;
// Hacemos una copia de TICK[] en TICK_dif[]
for (k=0; k<=n-1; k++) TICK_dif[k]=TICK[k];
// A continuación ordenamos TICK_dif[] de menor a mayor
for (k=0; k<=n-1; k++){
for (kk=k+1; kk<=n-1; kk++){
if (TICK_dif[k]>TICK_dif[kk]){
aux=TICK_dif[kk];
TICK_dif[kk]=TICK_dif[k];
TICK_dif[k]=aux;
}
}
}// Aqui ya terminamos de ordenar de menor a mayor TICK_dif[]
// Ahora vamor a eliminar los repetidos y nos quedamos con los diferentes
// solamente y a la vemos sabemos cuántos son
k=0;
for (kk=1; kk<=n-1;kk++){
if (TICK_dif[k]!=TICK_dif[kk]){
k++;
TICK_dif[k]=TICK_dif[kk];
}
}
x=k+1; // (x+1) es el número de interrupciones que se hacen
i_int=0; // índice de interrupciones
// Generamos el vector con los tiempos de las interrupciones
VTI[0]=65535-TICK_dif[0];//
// Una vez que se entre en la 1era interrupción por desborde del
// timer1 éste será el valor con que se cargará dicho contador
// para que ocurra la próxima interrupción.
VTI[x]=65535-ventana+TICK_dif[x-1];// ventana=2,5ms
// Con éste valor se cargará el contador la última vez que entra
// en el manejo de interrupciones en un ciclo, cada ciclo es de
// 2,5ms, por lo tanto será el tiempo que esperará para que se
// cumpla dicho tiempo
// 30000ticks*(1/12000000)=2,5ms
// a éste valor le resto lo que ha transcurrido previamente
// Próximanete genramos los tiempos de duración de cada interrupción
for (k=1; k<=x-1; k++){
VTI[k]=65535-(TICK_dif[k]-TICK_dif[k-1]);
}
// Ahora vamos a generar el vector de los estados de los pines
// en las interrupciones VTI_Servo[]
for (k=0; k<=x-1;k++){
for (kk=0; kk<=n-1; kk++){
if (TICK_dif[k]<=TICK[kk]){
bit_set(VTI_Servo[k], kk);
}
else bit_clear(VTI_Servo[k], kk);
}
}
}
// Recepción de datos via rs232//
if (kbhit()){
switch (dato){
case 0:
i=getc();
dato=1;
break;
case 1:
byte_alto=getc();// recibe el byte alto
dato=2;
break;
case 2:
byte_bajo=getc();// recibe el byte bajo
TICK[i]=256*byte_alto+byte_bajo;
dato=0;
break;
}
}
// Recepción vía USB
if (usb_kbhit(1))//El endpoint de salida contiene datos del host (EP1)?
{
usb_get_packet(1, recibe, 3);// Recibimos los 3 bytes:
// (servo,byte_alto_usb, byte_bajo_usb)
TICK[i_usb]=256*byte_alto_usb+byte_bajo_usb;
}
if (band_inicio==0){// Se ejecuta una sola vez
set_timer1(65535-ventana);//
// espero 20ms para empezar a mover los servos
enable_interrupts(INT_TIMER1);
enable_interrupts(GLOBAL);
band_inicio=1;
}
}
}
}
#include <18F4550.h>
#fuses HSPLL,NOWDT,NOPROTECT,NOLVP,NODEBUG,USBDIV,PLL5,CPUDIV1,VREGEN,NOPBADEN,NOBROWNOUT
#use delay(clock=48000000)//48MHz
#USE RS232 (baud=9600,bits=8,parity=N,xmit=PIN_C6,rcv=PIN_C7)
//#build(reset=0x000800,interrupt=0x000808:0x000818)
// Necesario para indicarle al compilador a partir de donde alojar mi programa
// Si se quiere usar bootloader se pueden habilitar estás dos líneas
//#ORG 0x000, 0x07FF {} // Espacio reservado para alojar el bootloader
#byte PORTA = 0xF80// Son las direcciones de memoria de los puertos en este PIC
#byte PORTB = 0xF81
#byte PORTC = 0xF82
#byte PORTD = 0xF83
#byte PORTE = 0xF84
/////////////////////////////////////////////////////////////////////////////
//
// CCS Library dynamic defines. For dynamic configuration of the CCS Library
// for your application several defines need to be made. See the comments
// at usb.h for more information
//
/////////////////////////////////////////////////////////////////////////////
#define USB_HID_DEVICE FALSE //deshabilitamos el uso de las directivas HID
#define USB_EP1_TX_ENABLE USB_ENABLE_BULK //turn on EP1(EndPoint1) for IN bulk/interrupt transfers
#define USB_EP1_RX_ENABLE USB_ENABLE_BULK //turn on EP1(EndPoint1) for OUT bulk/interrupt transfers
#define USB_EP1_TX_SIZE 2 //size to allocate for the tx endpoint 1 buffer
#define USB_EP1_RX_SIZE 2 //size to allocate for the rx endpoint 1 buffer
/////////////////////////////////////////////////////////////////////////////
//
// If you are using a USB connection sense pin, define it here. If you are
// not using connection sense, comment out this line. Without connection
// sense you will not know if the device gets disconnected.
// (connection sense should look like this:
// 100k
// VBUS-----+----/\/\/\/\/\----- (I/O PIN ON PIC)
// |
// +----/\/\/\/\/\-----GND
// 100k
// (where VBUS is pin1 of the USB connector)
//
/////////////////////////////////////////////////////////////////////////////
//#define USB_CON_SENSE_PIN PIN_B2 //CCS 18F4550 development kit has optional conection sense pin
/////////////////////////////////////////////////////////////////////////////
//
// Include the CCS USB Libraries. See the comments at the top of these
// files for more information
//
/////////////////////////////////////////////////////////////////////////////
#include <pic18_usb.h> //Microchip PIC18Fxx5x Hardware layer for CCS's PIC USB driver
#include <PicUSB.h> //Configuración del USB y los descriptores para este dispositivo
#include <usb.c> //handles usb setup tokens and get descriptor reports
#include <math.h>
#use fast_io(A)
#use fast_io(B)
#use fast_io(C)
#use fast_io(D)
#use fast_io(E)
#bit servo_00 = PORTB.0
#bit servo_01 = PORTB.1
#bit servo_02 = PORTB.2
#bit servo_03 = PORTB.3
#bit servo_04 = PORTB.4
#bit servo_05 = PORTB.5
#bit servo_06 = PORTB.6
#bit servo_07 = PORTB.7
#bit servo_08 = PORTD.0
#bit servo_09 = PORTD.1
#bit servo_10 = PORTD.2
#bit servo_11 = PORTD.3
#bit servo_12 = PORTD.4
#bit servo_13 = PORTD.5
#bit servo_14 = PORTD.6
#bit servo_15 = PORTD.7
#define i_usb recibe[0]// es el índice que se recibe vía usb
#define pos_usb recibe[1]//
#define n 16// número de servos
//para otro número de servos hay que hacer mediciones de tiempo
#define max_cont 101//
#define derecha 101//
#define centro 60//
#define izquierda 20// 20*25us =0,5ms
#define val_timer1 65497//65535-75, 1 tick=(1/12000000)*4
#define resto 13047//65535-52500
int8 cont=0;
int8 duty[n];
#INT_TIMER1
void isr_timer1(){
delay_cycles(1);
if (duty[0] >= cont)// Cada 25us llega aqui de forma cíclica por 2,5ms nada
// más, luego en 17,5ms
{
servo_00=1;
}
else
{
servo_00=0;
delay_cycles(1);
}
if (duty[1] >= cont)
{
servo_01=1;
}
else
{
servo_01=0;
delay_cycles(1);
}
if (duty[2] >= cont)
{
servo_02=1;
}
else
{
servo_02=0;
delay_cycles(1);
}
if (duty[3] >= cont)
{
servo_03=1;
}
else
{
servo_03=0;
delay_cycles(1);
}
if (duty[4] >= cont)
{
servo_04=1;
}
else
{
servo_04=0;
delay_cycles(1);
}
if (duty[5] >= cont)
{
servo_05=1;
}
else
{
servo_05=0;
delay_cycles(1);
}
if (duty[6] >= cont)
{
servo_06=1;
}
else
{
servo_06=0;
delay_cycles(1);
}
if (duty[7] >= cont)
{
servo_07=1;
}
else
{
servo_07=0;
delay_cycles(1);
}
if (duty[8] >= cont)
{
servo_08=1;
}
else
{
servo_08=0;
delay_cycles(1);
}
if (duty[9] >= cont)
{
servo_09=1;
}
else
{
servo_09=0;
delay_cycles(1);
}
if (duty[10] >= cont)
{
servo_10=1;
}
else
{
servo_10=0;
delay_cycles(1);
}
if (duty[11] >= cont)
{
servo_11=1;
}
else
{
servo_11=0;
delay_cycles(1);
}
if (duty[12] >= cont)
{
servo_12=1;
}
else
{
servo_12=0;
delay_cycles(1);
}
if (duty[13] >= cont)
{
servo_13=1;
}
else
{
servo_13=0;
delay_cycles(1);
}
if (duty[14] >= cont)
{
servo_14=1;
}
else
{
servo_14=0;
delay_cycles(1);
}
if (duty[15] >= cont)
{
servo_15=1;
}
else
{
servo_15=0;
delay_cycles(1);
}
set_timer1(val_timer1);
cont++;
}
/////////////////////////////////////// PRINCIPAL /////////////////////////////////////
void main()
{
int k;
int8 i=0;// es el índice exclusivo de duty[] en la recepción serial
int1 band=0;
int8 recibe[2];// Buffer de recepción vía usb
//int8 envia[2];// Habilitar en caso de necesitar
set_tris_b(0x00);
set_tris_c(0b10000000);
set_tris_d(0x00);
PORTB=0x00;
PORTD=0x00;
port_b_pullups(FALSE);
for(k=0;k<=(n-1);k++)
duty[k]=centro;//
setup_adc_ports(NO_ANALOGS);
setup_adc(ADC_OFF);
setup_timer_1(T1_INTERNAL | T1_DIV_BY_4);
set_timer1(resto);
enable_interrupts(INT_TIMER1);
enable_interrupts(GLOBAL);
usb_init();//inicializamos el USB
usb_task();//habilita periférico usb e interrupciones
usb_wait_for_enumeration();//esperamos hasta que el PicUSB sea configurado por el host
while (TRUE)
{
if(usb_enumerated())//si el PicUSB está configurado
//if (TRUE)
{
// Recepción de datos via rs232
if (kbhit()){
if (band==0){
i=getc();
band=1;
}
else{
duty[i]=getc();
band=0;
}
}
// Recepción vía USB
if (usb_kbhit(1))//El endpoint de salida contiene datos del host (EP1)?
{
usb_get_packet(1, recibe, 2);// Recibimos los 2 bytes: (servo,pos)
duty[i_usb]=pos_usb;
}
// Análisis
if (cont>max_cont+1){
cont=1;
set_timer1(resto);// Lo suficiente para que en 20ms exactos
// se produzca la próxima interrupción
}
}
}
}
Servo= pulsamos el 0...Servo= 0pulsamos ENTERServo= 0
Pos= pulsamos el 2...Servo= 0
Pos= 2pulsamos el 6Servo= 0
Pos= 26pulsamos ENTERServo= 0
Pos= 26
Dato enviado!#include <18F4550.h>
#fuses HSPLL,NOWDT,NOPROTECT,NOLVP,NODEBUG,USBDIV,PLL5,CPUDIV1,VREGEN,NOPBADEN,NOBROWNOUT
#use delay(clock=48000000)//48MHz
#USE RS232 (baud=9600,bits=8,parity=N,xmit=PIN_C6,rcv=PIN_C7)
#byte RCSTA= 0xFAB // Registro de recepcion de la usart
#byte RCREG= 0xFAE // Aquí se recibe el dato de la usart
#bit CREN= RCSTA.4 // Se activa para recepción continua
#bit OERR= RCSTA.1 // Error de Overrun
//#build(reset=0x000800,interrupt=0x000808:0x000818)
// Necesario para indicarle al compilador a partir de donde alojar mi programa
// Si se quiere usar bootloader se pueden habilitar estás dos líneas
//#ORG 0x000, 0x07FF {} // Espacio reservado para alojar el bootloader
#byte PORTA = 0xF80// Son las direcciones de memoria de los puertos en este PIC
#byte PORTB = 0xF81
#byte PORTC = 0xF82
#byte PORTD = 0xF83
#byte PORTE = 0xF84
/////////////////////////////////////////////////////////////////////////////
//
// CCS Library dynamic defines. For dynamic configuration of the CCS Library
// for your application several defines need to be made. See the comments
// at usb.h for more information
//
/////////////////////////////////////////////////////////////////////////////
#define USB_HID_DEVICE FALSE //deshabilitamos el uso de las directivas HID
#define USB_EP1_TX_ENABLE USB_ENABLE_BULK //turn on EP1(EndPoint1) for IN bulk/interrupt transfers
#define USB_EP1_RX_ENABLE USB_ENABLE_BULK //turn on EP1(EndPoint1) for OUT bulk/interrupt transfers
#define USB_EP1_TX_SIZE 2 //size to allocate for the tx endpoint 1 buffer
#define USB_EP1_RX_SIZE 2 //size to allocate for the rx endpoint 1 buffer
/////////////////////////////////////////////////////////////////////////////
//
// If you are using a USB connection sense pin, define it here. If you are
// not using connection sense, comment out this line. Without connection
// sense you will not know if the device gets disconnected.
// (connection sense should look like this:
// 100k
// VBUS-----+----/\/\/\/\/\----- (I/O PIN ON PIC)
// |
// +----/\/\/\/\/\-----GND
// 100k
// (where VBUS is pin1 of the USB connector)
//
/////////////////////////////////////////////////////////////////////////////
//#define USB_CON_SENSE_PIN PIN_B2 //CCS 18F4550 development kit has optional conection sense pin
/////////////////////////////////////////////////////////////////////////////
//
// Include the CCS USB Libraries. See the comments at the top of these
// files for more information
//
/////////////////////////////////////////////////////////////////////////////
#include <pic18_usb.h> //Microchip PIC18Fxx5x Hardware layer for CCS's PIC USB driver
#include <PicUSB.h> //Configuración del USB y los descriptores para este dispositivo
#include <usb.c> //handles usb setup tokens and get descriptor reports
#include <string.h>
#use fast_io(A)
#use fast_io(B)
#use fast_io(C)
#use fast_io(D)
#use fast_io(E)
#bit servo_00 = PORTB.0
#bit servo_01 = PORTB.1
#bit servo_02 = PORTB.2
#bit servo_03 = PORTB.3
#bit servo_04 = PORTB.4
#bit servo_05 = PORTB.5
#bit servo_06 = PORTB.6
#bit servo_07 = PORTB.7
#bit servo_08 = PORTD.0
#bit servo_09 = PORTD.1
#bit servo_10 = PORTD.2
#bit servo_11 = PORTD.3
#bit servo_12 = PORTD.4
#bit servo_13 = PORTD.5
#bit servo_14 = PORTD.6
#bit servo_15 = PORTD.7
#define i_usb recibe[0]// es el índice que se recibe vía usb
#define pos_usb recibe[1]//
#define n 16// número de servos
//para otro número de servos hay que hacer mediciones de tiempo
#define max_cont 101//
#define derecha 101//
#define centro 60//
#define izquierda 20// 20*25us =0,5ms
#define val_timer1 65497// 1 tick=(1/12000000)*4
#define resto 13047//
int8 cont=0;
int8 duty[n];
#INT_TIMER1
void isr_timer1(){
delay_cycles(1);
if (duty[0] >= cont)// Cada 25us llega aqui de forma cíclica por 2,5ms nada
// más, luego en 17,5ms
{
servo_00=1;
}
else
{
servo_00=0;
delay_cycles(1);
}
if (duty[1] >= cont)
{
servo_01=1;
}
else
{
servo_01=0;
delay_cycles(1);
}
if (duty[2] >= cont)
{
servo_02=1;
}
else
{
servo_02=0;
delay_cycles(1);
}
if (duty[3] >= cont)
{
servo_03=1;
}
else
{
servo_03=0;
delay_cycles(1);
}
if (duty[4] >= cont)
{
servo_04=1;
}
else
{
servo_04=0;
delay_cycles(1);
}
if (duty[5] >= cont)
{
servo_05=1;
}
else
{
servo_05=0;
delay_cycles(1);
}
if (duty[6] >= cont)
{
servo_06=1;
}
else
{
servo_06=0;
delay_cycles(1);
}
if (duty[7] >= cont)
{
servo_07=1;
}
else
{
servo_07=0;
delay_cycles(1);
}
if (duty[8] >= cont)
{
servo_08=1;
}
else
{
servo_08=0;
delay_cycles(1);
}
if (duty[9] >= cont)
{
servo_09=1;
}
else
{
servo_09=0;
delay_cycles(1);
}
if (duty[10] >= cont)
{
servo_10=1;
}
else
{
servo_10=0;
delay_cycles(1);
}
if (duty[11] >= cont)
{
servo_11=1;
}
else
{
servo_11=0;
delay_cycles(1);
}
if (duty[12] >= cont)
{
servo_12=1;
}
else
{
servo_12=0;
delay_cycles(1);
}
if (duty[13] >= cont)
{
servo_13=1;
}
else
{
servo_13=0;
delay_cycles(1);
}
if (duty[14] >= cont)
{
servo_14=1;
}
else
{
servo_14=0;
delay_cycles(1);
}
if (duty[15] >= cont)
{
servo_15=1;
}
else
{
servo_15=0;
delay_cycles(1);
}
set_timer1(val_timer1);
cont++;
}
/////////////////////////////////////// PRINCIPAL /////////////////////////////////////
void main()
{
int k;
int8 recibe[2];// Buffer de recepción vía usb
//int8 envia[2];// Habilitar en caso de necesitar
int8 i=0, i_old=0;// es el índice exclusivo de duty[] en la recepción serial
// i_old es una variable auxiliar, para saber si ya
// pase por el análisis del buffer
char buffer[32];// buffer de recepeción serial
int8 servo, pos;
int8 aux;// sirve para manejar el overrun, vacía buffer del pic
int1 band=0;// band=0 => recibir índice del servo
int1 mensj1=0, mensj2=0;// Son banderas para saber si se escribieron
// los mensajes 'Servo= ' y 'Pos= '
int1 inicio=0;
set_tris_b(0x00);
set_tris_c(0b10000000);
set_tris_d(0x00);
disable_interrupts(INT_TIMER1);
disable_interrupts(GLOBAL);
PORTB=0x00;
PORTD=0x00;
port_b_pullups(FALSE);
for(k=0;k<=(n-1);k++)
duty[k]=izquierda;//
setup_adc_ports(NO_ANALOGS);
setup_adc(ADC_OFF);
setup_timer_1(T1_INTERNAL | T1_DIV_BY_4);
printf("*** Programa para controlar 16 Sevos ***\r\n");
printf("*** Via Serial y USB al mismo tiempo ***\r\n");
printf("*** Realizado por Guillermo Nunez ***\r\n");
printf("*** Para el foro TODOPIC ;-) ***\r\n");
printf("*** Fecha: 21/03/08 ***\r\n");
printf("\r\n");
printf("Servo= [0..15]\r\n");
printf("Pos= [20..101]\r\n");
printf("Espere mientras se incializa el PicUSB...\r\n");
usb_init();//inicializamos el USB
usb_task();//habilita periférico usb e interrupciones
usb_wait_for_enumeration();//esperamos hasta que el PicUSB sea configurado por el host
printf(">>> Listo!\r\n");
while (TRUE)
{
if(usb_enumerated())//si el PicUSB está configurado
//if (TRUE)
{
// Si se reciben más de 2 bytes sin haberlos procesado, se produce un error
// de Overrun. En este caso, se borra el error reiniciando CREN para que nuestro pic
// no se cuelgue
// Análisis
if (cont>max_cont+1){
cont=1;
//delay_cycles(25);
set_timer1(resto);// Lo suficiente para que en 20ms exactos
// se produzca la próxima interrupción
}
if (OERR)
{
aux=RCREG;
aux=RCREG;
aux=RCREG;
CREN=0;
CREN=1;
printf("Error:\r\n");
printf("Envíe de nuevo los datos\r\n");
i=0;
}
// Recepción de datos via rs232
if (kbhit()){
buffer[i]=getc();
i++;
}
// Escribe los mensajes si no lo has hecho
if (band==0){
if (mensj1==0){
printf("\r\nServo= ");
mensj1=1;
}
}
else{
if (mensj2==0){
printf("\r\nPos= ");
mensj2=1;
}
}
// Procesa los datos recibidos
if (i_old!=i){
if ((!isdigit(buffer[i-1])) && (buffer[i-1]!=13)) { //Valida los datos
i--;// Lo sacamos del buffer y no se escribe en pantalla
}
else{
if (band==0){// Estamos recibiendo el índice del Servo
if (i>1){// si ya se recibieron 2 datos
i=0;
if (buffer[1]!=13){// Pregunto si el segundo dato es
// Distinto a ENTER
putc(buffer[1]);
servo=servo*10+buffer[1]-0x30;
if (servo>15){
printf("\r\nIngrese un valor entre 0 y 15\r\n");
mensj1=0;
}
else{
band=1;
mensj2=0;
}
}
else{// Si el 2do dato es ENTER
band=1;
mensj2=0;
}
}
else{// Se ha recibido 1 dato
if (buffer[0]!=13){// Verificamos que no sea ENTER
servo=buffer[0]-0x30;
putc(buffer[0]);
}
else i=0;// No nos interesa un ENTER, así que lo sacamos
// del buffer
}
}
else{// Estamos recibiendo la posición
switch (i){
case 1:// Hemos recibido 1 dato
if (buffer[0]!=13){// Verificamos que no sea ENTER
pos=buffer[0]-0x30;
putc(buffer[0]);
}
else i=0;// No nos interesa un ENTER, así que lo sacamos
// del buffer
break;
case 2:// Hemos recibido 2 datos
if (buffer[1]!=13){// Verificamos que no sea ENTER
pos=pos*10+buffer[1]-0x30;
putc(buffer[1]);
}
else{ // Terminamos de recibir datos
printf("\r\nIngrese un valor entre 20 y 101\r\n");
i=0;
mensj2=0;
}
break;
case 3:// Hemos recibido 3 datos
i=0;
if (buffer[2]!=13){// Verificamos que no sea ENTER
putc(buffer[2]);
pos=pos*10+buffer[2]-0x30;
if ((pos>=20) && (pos<=101)){
duty[servo]=pos;
mensj1=0;
band=0;
printf("\r\nDato enviado! \r\n");
}
else{
printf("\r\nIngrese un valor entre 20 y 101\r\n");
mensj2=0;
}
}
else{
if (pos>=20){
duty[servo]=pos;
mensj1=0;
band=0;
printf("\r\nDato enviado! \r\n");
}
else{
printf("\r\nIngrese un valor entre 20 y 101\r\n");
mensj2=0;
}
}
break;
}
}
}
i_old=i;
}
// Recepción vía USB
if (usb_kbhit(1))//El endpoint de salida contiene datos del host (EP1)?
{
usb_get_packet(1, recibe, 2);// Recibimos los 2 bytes: (servo,pos)
duty[i_usb]=pos_usb;
}
if (inicio==0){
inicio=1;
set_timer1(resto);
enable_interrupts(INT_TIMER1);
enable_interrupts(GLOBAL);
}
}
}
}
Enhorabuena Guillermo 8)
#include <18F4550.h>
#fuses HSPLL,NOWDT,NOPROTECT,NOLVP,NODEBUG,USBDIV,PLL5,CPUDIV1,VREGEN,NOPBADEN,NOBROWNOUT
#use delay(clock=48000000)//48MHz
#USE RS232 (baud=9600,bits=8,parity=N,xmit=PIN_C6,rcv=PIN_C7)
#byte RCSTA= 0xFAB // Registro de recepcion de la usart
#byte RCREG= 0xFAE // Aquí se recibe el dato de la usart
#byte TMR1L= 0xFCE// Byte bajo del timer1
#bit CREN= RCSTA.4 // Se activa para recepción continua
#bit OERR= RCSTA.1 // Error de Overrun
//#build(reset=0x000800,interrupt=0x000808:0x000818)
// Necesario para indicarle al compilador a partir de donde alojar mi programa
// Si se quiere usar bootloader se pueden habilitar estás dos líneas
//#ORG 0x000, 0x07FF {} // Espacio reservado para alojar el bootloader
#byte PORTA = 0xF80// Son las direcciones de memoria de los puertos en este PIC
#byte PORTB = 0xF81
#byte PORTC = 0xF82
#byte PORTD = 0xF83
#byte PORTE = 0xF84
#include <string.h>
#use fast_io(A)
#use fast_io(B)
#use fast_io(C)
#use fast_io(D)
#use fast_io(E)
#bit servo_00 = PORTB.0
#bit servo_01 = PORTB.1
#bit servo_02 = PORTB.2
#bit servo_03 = PORTB.3
#bit servo_04 = PORTB.4
#bit servo_05 = PORTB.5
#bit servo_06 = PORTB.6
#bit servo_07 = PORTB.7
#bit servo_08 = PORTD.0
#bit servo_09 = PORTD.1
#bit servo_10 = PORTD.2
#bit servo_11 = PORTD.3
#bit servo_12 = PORTD.4
#bit servo_13 = PORTD.5
#bit servo_14 = PORTD.6
#bit servo_15 = PORTD.7
#define n 16// número de servos
//para otro número de servos hay que hacer mediciones de tiempo
#define max_cont 100// 100*25us=2,5 siempre dejar fijo éste valor,
// con esto se logra 20ms de período
int8 derecha=100; // 100*25us=2.5ms
// Si queremos 2,3ms colocamos derecha=92, 2300/25=92
int8 centro=60;
int8 izquierda=20; // 20*25us =0,5ms
// Si queremos 0,3ms colocamos izquierda=92, 300/25=12
#define val_timer1 65389// Valor determinado por tanteo
#define resto 52819//Este valor sirve para lograr los 20ms del período total
// También determinado por tanteo, usando el mplab
int8 cont=0;
int8 duty[n];
int8 cont_old=0;// variable auxiliar
#INT_TIMER1
void isr_timer1(){
int8 cap_timer1;
cap_timer1=TMR1L;// Capturamos el valor bajo del timer1
if (cap_timer1==42){delay_cycles(4);}// Valor del timer1_low determinado por simulaciones
// usando el mplab
else delay_cycles(4);
// la idea es que aqui siempre sea la misma cantidad de ciclos en cada entrada
// esto fue determinado por tanteo
// cada 25us llegue aqui de forma cíclica, variando "val_timer1"
if (duty[0] > cont){servo_00=1;}
else{servo_00=0;delay_cycles(1);}
if (duty[1] > cont){servo_01=1;}
else{servo_01=0; delay_cycles(1);}
if (duty[2] > cont){servo_02=1;}
else{servo_02=0;delay_cycles(1);}
if (duty[3] > cont){servo_03=1;}
else{servo_03=0;delay_cycles(1);}
if (duty[4] > cont){servo_04=1;}
else{servo_04=0;delay_cycles(1);}
if (duty[5] > cont){servo_05=1;}
else{servo_05=0;delay_cycles(1);}
if (duty[6] > cont){servo_06=1;}
else{servo_06=0;delay_cycles(1);}
if (duty[7] > cont){servo_07=1;}
else{servo_07=0;delay_cycles(1);}
if (duty[8] > cont){servo_08=1;}
else{servo_08=0;delay_cycles(1);}
if (duty[9] > cont){servo_09=1;}
else{servo_09=0;delay_cycles(1);}
if (duty[10] > cont){servo_10=1;}
else{servo_10=0;delay_cycles(1);}
if (duty[11] > cont){servo_11=1;}
else{servo_11=0;delay_cycles(1);}
if (duty[12] > cont){servo_12=1;}
else{servo_12=0;delay_cycles(1);}
if (duty[13] > cont){servo_13=1;}
else{servo_13=0;delay_cycles(1);}
if (duty[14] > cont){servo_14=1;}
else{servo_14=0;delay_cycles(1);}
if (duty[15] > cont){servo_15=1;}
else{servo_15=0;delay_cycles(1);}
set_timer1(val_timer1);
cont++;
// Análisis
if (cont>max_cont){
if (cont_old!=cont){
cont_old=cont;
if ((cont-max_cont)<4){
set_timer1(0);// 5,461333ms+
}
else {
set_timer1(resto);// 20ms-5,461333ms*3-2,5ms=1.116ms
// => 13392 Ticks, 65535-13392=52143
cont=0;
}
}
}
}
/////////////////////////////////////// PRINCIPAL /////////////////////////////////////
void main()
{
int k;
int8 i=0, i_old=0;// es el índice exclusivo de duty[] en la recepción serial
// i_old es una variable auxiliar, para saber si ya
// pase por el análisis del buffer
char buffer[16];// buffer de recepeción serial
int8 servo, pos;
int8 aux;// sirve para manejar el overrun, vacía buffer del pic
int1 band=0;// band=0 => recibir índice del servo
int1 mensj1=0, mensj2=0;// Son banderas para saber si se escribieron
// los mensajes 'Servo= ' y 'Pos= '
int1 inicio=0;
set_tris_b(0x00);
set_tris_c(0b10000000);
set_tris_d(0x00);
disable_interrupts(INT_TIMER1);
disable_interrupts(GLOBAL);
PORTB=0x00;
PORTD=0x00;
port_b_pullups(FALSE);
for(k=0;k<=(n-1);k++)
duty[k]=izquierda;//
setup_adc_ports(NO_ANALOGS);
setup_adc(ADC_OFF);
setup_timer_1(T1_INTERNAL | T1_DIV_BY_1);
printf("*** Programa para controlar 16 Sevos ***\r\n");
printf("*** Via Serial RS232 ***\r\n");
printf("*** Realizado por Guillermo Nunez ***\r\n");
printf("*** Para el foro TODOPIC ;-) ***\r\n");
printf("*** Fecha: 24/03/08 ***\r\n");
printf("\r\n");
printf("Version 1.3\r\n");
printf("Servo= [0..15]\r\n");
printf("Pos= [%d..%d]\r\n", izquierda, derecha);
while (TRUE)
{
// Si se reciben más de 2 bytes sin haberlos procesado, se produce un error
// de Overrun. En este caso, se borra el error reiniciando CREN para que nuestro pic
// no se cuelgue
if (OERR)
{
aux=RCREG;
aux=RCREG;
aux=RCREG;
CREN=0;
CREN=1;
printf("Error:\r\n");
printf("Envíe de nuevo los datos\r\n");
i=0;
mensj1=0;
band=0;
}
// Recepción de datos via rs232
if (kbhit()){
buffer[i]=getc();
i++;
}
// Escribe los mensajes si no lo has hecho
if (band==0){
if (mensj1==0){
printf("\r\nServo= ");
mensj1=1;
}
}
else{
if (mensj2==0){
printf("\r\nPos= ");
mensj2=1;
}
}
// Procesa los datos recibidos
if (i_old!=i){
if ((!isdigit(buffer[i-1])) && (buffer[i-1]!=13)) { //Valida los datos
i--;// Lo sacamos del buffer y no se escribe en pantalla
}
else{
if (band==0){// Estamos recibiendo el índice del Servo
if (i>1){// si ya se recibieron 2 datos
i=0;
if (buffer[1]!=13){// Pregunto si el segundo dato es
// Distinto a ENTER
putc(buffer[1]);
servo=servo*10+buffer[1]-0x30;
if (servo>15){
printf("\r\nIngrese un valor entre 0 y 15\r\n");
mensj1=0;
}
else{
band=1;
mensj2=0;
}
}
else{// Si el 2do dato es ENTER
band=1;
mensj2=0;
}
}
else{// Se ha recibido 1 dato
if (buffer[0]!=13){// Verificamos que no sea ENTER
servo=buffer[0]-0x30;
putc(buffer[0]);
}
else i=0;// No nos interesa un ENTER, así que lo sacamos
// del buffer
}
}
else{// Estamos recibiendo la posición
switch (i){
case 1:// Hemos recibido 1 dato
if (buffer[0]!=13){// Verificamos que no sea ENTER
pos=buffer[0]-0x30;
putc(buffer[0]);
}
else i=0;// No nos interesa un ENTER, así que lo sacamos
// del buffer
break;
case 2:// Hemos recibido 2 datos
if (buffer[1]!=13){// Verificamos que no sea ENTER
pos=pos*10+buffer[1]-0x30;
putc(buffer[1]);
}
else{ // Terminamos de recibir datos
printf("\r\nIngrese un valor entre %d y %d\r\n", izquierda, derecha);
i=0;
mensj2=0;
}
break;
case 3:// Hemos recibido 3 datos
i=0;
if (buffer[2]!=13){// Verificamos que no sea ENTER
putc(buffer[2]);
pos=pos*10+buffer[2]-0x30;
if ((pos>=izquierda) && (pos<=derecha)){
duty[servo]=pos;
mensj1=0;
band=0;
printf("\r\nDato enviado! \r\n");
}
else{
printf("\r\nIngrese un valor entre %d y %d\r\n", izquierda, derecha);
mensj2=0;
}
}
else{
if (pos>=izquierda){
duty[servo]=pos;
mensj1=0;
band=0;
printf("\r\nDato enviado! \r\n");
}
else{
printf("\r\nIngrese un valor entre %d y %d\r\n", izquierda, derecha);
mensj2=0;
}
}
break;
}
}
}
i_old=i;
}
if (inicio==0){
inicio=1;
set_timer1(resto);
enable_interrupts(INT_TIMER1);
enable_interrupts(GLOBAL);
}
}
}