Bueno hoy hice varios cambios, me dí cuenta que no podía sensar las señales del encoder en el programa principal sino que para obtener mejores resultados lo cambié a procesarlos mediante interrupción, la cuestión es que tengo dos encoders con sus señales A y B cada uno, lo bueno es que el pic16f877 tiene interrupción por cambio de estado en los pines RB7:RB4 entonces lo que hice fué trasladé las señales para allá y habilité dicha interrupción, el cambio fue notorio ahora si veía más pulsos, pero todavía notaba que el pic se quedaba corto en velocidad así que como tenía un 18f4455 a la mano pasé el código a dicho pic y probé, aunque los resultados mejoraron no fué mucha la diferencia, pero es lo mejor hasta los momentos que e podido lograr para leer estas señales y procesarlas, los código resultantes son los siguientes:
Para el pic16f877:
#include <16f877.h>
#device adc=10//La resolución del módulo A/D es de 10 bits.
#fuses HS,NOWDT,NOPROTECT,NOLVP,NOBROWNOUT,PUT
#use delay (clock=20000000)//20Mhz
#USE RS232 (baud=9600,bits=8,parity=N,xmit=PIN_C6,rcv=PIN_C7)
#use standard_io(a)
#use fast_io(b)// Aqui están las señales del encoder
#use fast_io(c)
#use standard_io(d)
#use standard_io(e)
#byte port_a = 0x05
#byte port_b = 0x06
#byte port_c = 0x07
#byte port_d = 0x08
#byte port_e = 0x09
#byte INTCON = 0x0B// Registro de interrupciones
#bit TX = port_c.6// Bit de Stop
#bit RBIF = INTCON.0// RB Port Change interrupt Flag bit
typedef struct {
int low : 8;
int high : 8; } myWord;
// Declaración de variables
long cont_art_0=0, cont_art_1=0, cont_art_2=0, cont_art_3=0;
int1 pos_ant_A1, pos_ant_B1, pos_ant_A2, pos_ant_B2;
// Posiciones o lecturas anteriores de las señales de los encoders
int1 pos_act_A1, pos_act_B1, pos_act_A2, pos_act_B2;
// Posiciones o lecturas actuales de las señales de los encoders
int dato;// Dato recibido via RS232
#define A1 PIN_B7
#define B1 PIN_B6
#define A2 PIN_B5
#define B2 PIN_B4
#define Lee input
// Señales A y B de los encoders 1 y 2
int1 invierto_enc_1=1, invierto_enc_2=1;
// Si sucede el caso en el que se incrementa el contador de una articulación
// en un sentido de giro X, pero en realidad nos interesa que en ese sentido
// de giro dicha variable se decremente, entonces mediante un comando RS232
// podemos modificar éstas variables y lograr el objetivo, los comandos están
// en la rutina de interrupción por recepción de la UART
// Declaración de los prototipos de las funciones
long Toma_adc(int); // Devuelve la lectura del conversor AD
// del canal seleccionado
void Procesa_encoder(int); // Procesa el encoder seleccionado y actualiza
// los valores los valores de los contadores
// de las articulaciones correspondientes
int1 Beta(int, int); // Devuelve 1 si a ocurrido una transición Beta, ó
// flanco descendente, en caso contrario regresa 0
// Interrupción por recepción de datos RS232
#int_rda
void rda_isr() {
dato=getc();// Lee y almacena el dato recibido vía RS232
switch (dato){
case 0:
putc(((myWord)cont_art_0).low);
break;
case 1:
putc(((myWord)cont_art_0).high);
break;
case 2:
putc(((myWord)cont_art_1).low);
break;
case 3:
putc(((myWord)cont_art_1).high);
break;
case 4:
putc(((myWord)cont_art_2).low);
break;
case 5:
putc(((myWord)cont_art_2).high);
break;
case 6:
putc(((myWord)cont_art_3).low);
break;
case 7:
putc(((myWord)cont_art_3).high);
break;
case 8:// Resetea los contadores de todas las articulaciones
cont_art_0=0;
cont_art_1=0;
cont_art_2=0;
cont_art_3=0;
break;
case 9:// Resetea el contador de las articulación 0 solamente
cont_art_0=0;
break;
case 10:// Resetea el contador de las articulación 1 solamente
cont_art_1=0;
break;
case 11:// Resetea el contador de las articulación 2 solamente
cont_art_2=0;
break;
case 12:// Resetea el contador de las articulación 3 solamente
cont_art_3=0;
break;
case 13: // Invierto sentido de giro del encoder 1
if (invierto_enc_1==0){
invierto_enc_1=1;
}
else invierto_enc_1=0;
break;// Tipo Toggle ;-)
case 14: // Invierto sentido de giro del encoder 2
if (invierto_enc_2==0){
invierto_enc_2=1;
}
else invierto_enc_2=0;
break;// Tipo Toggle ;-)
}
}
#INT_RB
void rb_isr() {// Si al menos uno de los pines RB7:RB4 cambió de estado
// entra aquí
pos_act_A1=Lee(A1);// Lee las posiciones actuales de las señales
pos_act_B1=Lee(B1);// proveniente del encoder 1
pos_act_A2=Lee(A2);// Lee las posiciones actuales de las señales
pos_act_B2=Lee(B2);// proveniente del encoder 2
// Procesamos el encoder 1
if (Beta(pos_ant_A1, pos_act_A1)){// Ocurrió un flanco descendente?
if (pos_act_B1==1){
if (!invierto_enc_1) {cont_art_0++;}
else{ if (cont_art_0>0) cont_art_0--;};
};
};
if (Beta(pos_ant_B1, pos_act_B1)){// Ocurrió un flanco descendente?
if (pos_act_A1==1){
if (!invierto_enc_1) {if (cont_art_0>0) cont_art_0--;}
else cont_art_0++;
};
};
// Procesamos el encoder 2
if (Beta(pos_ant_A2, pos_act_A2)){// Ocurrió un flanco descendente?
if (pos_act_B2==1){
if (!invierto_enc_2) {cont_art_3++;}
else{ if (cont_art_3>0) cont_art_3--;};
};
};
if (Beta(pos_ant_B2, pos_act_B2)){// Ocurrió un flanco descendente?
if (pos_act_A2==1){
if (!invierto_enc_2) {if (cont_art_3>0) cont_art_3--;}
else cont_art_3++;
};
};
// Actualizamos las posiciones anteriores de los encoders
pos_ant_A1=pos_act_A1;
pos_ant_B1=pos_act_B1;
pos_ant_A2=pos_act_A2;
pos_ant_B2=pos_act_B2;
}
void main(){
setup_adc(ADC_CLOCK_DIV_32); //configura el reloj del conversor
setup_adc_ports(ALL_ANALOG);
enable_interrupts(int_rda);// Interrupción por recepción de datos via rs232
enable_interrupts(int_rb);// Interrupción por cambio de estado pines RB7:RB4
enable_interrupts(global);
set_tris_b(0xF0);
set_tris_c(0b10000000);
TX=1;// Bit de Stop = 1
// Incialización de las posiciones anteriores de los encoders
pos_ant_A1=Lee(A1);
pos_ant_B1=Lee(B1);
pos_ant_A2=Lee(A2);
pos_ant_B2=Lee(B2);
// Son posiciones referenciales para saber el estado anterior de un pin
while (1){
// Los contadores de las articulaciones 0 y 3, son actualizados
// a través de la interrupción de cambio de estado del puerto B
cont_art_1=Toma_adc(0);// Lee AN0
delay_us(5);// Espero 5 us antes de empezar una nueva conversión
cont_art_2=Toma_adc(1);// Lee AN1
}
}
// Desarrolo de funciones
long Toma_adc(int canal){
long valor;
set_adc_channel(canal);
delay_us(20);
Read_ADC(ADC_START_ONLY);
delay_us(20);
valor=read_adc(ADC_READ_ONLY);
return(valor);
}
int1 Beta(int1 pos_inic, int1 pos_final){// Devuelve 1 si ocurrió una transición
// Beta, en caso contrario regresa 0
if ((pos_inic==1) && (pos_final==0))
{
return(1);
}
else return(0);
}
Y para el 18f4455:
#include <18F4455.h>
#device adc=10//La resolución del módulo A/D es de 10 bits.
#fuses HSPLL,NOWDT,NOPROTECT,NOLVP,NODEBUG,USBDIV,PLL5,CPUDIV1,NOVREGEN
#fuses NOBROWNOUT,PUT,NOPBADEN
#use delay (clock=48000000)//48Mhz
#USE RS232 (baud=19200,bits=8,parity=N,xmit=PIN_C6,rcv=PIN_C7)
#use standard_io(a)
#use fast_io(b)// Aqui están las señales del encoder
#use fast_io(c)
#use standard_io(d)
#use standard_io(e)
#byte port_a = 0xF80
#byte port_b = 0xF81
#byte port_c = 0xF82
#byte port_d = 0xF83
#byte port_e = 0xF84
#bit TX = port_c.6// Bit de Stop
typedef struct {
int low : 8;
int high : 8; } myWord;
// Declaración de variables
long cont_art_0=0, cont_art_1=0, cont_art_2=0, cont_art_3=0;
int1 pos_ant_A1, pos_ant_B1, pos_ant_A2, pos_ant_B2;
// Posiciones o lecturas anteriores de las señales de los encoders
int1 pos_act_A1, pos_act_B1, pos_act_A2, pos_act_B2;
// Posiciones o lecturas actuales de las señales de los encoders
int dato;// Dato recibido via RS232
#define A1 PIN_B7
#define B1 PIN_B6
#define A2 PIN_B5
#define B2 PIN_B4
#define Lee input
// Señales A y B de los encoders 1 y 2
int1 invierto_enc_1=1, invierto_enc_2=1;
// Si sucede el caso en el que se incrementa el contador de una articulación
// en un sentido de giro X, pero en realidad nos interesa que en ese sentido
// de giro dicha variable se decremente, entonces mediante un comando RS232
// podemos modificar éstas variables y lograr el objetivo, los comandos están
// en la rutina de interrupción por recepción de la UART
// Declaración de los prototipos de las funciones
long Toma_adc(int); // Devuelve la lectura del conversor AD
// del canal seleccionado
void Procesa_encoder(int); // Procesa el encoder seleccionado y actualiza
// los valores los valores de los contadores
// de las articulaciones correspondientes
int1 Beta(int, int); // Devuelve 1 si a ocurrido una transición Beta, ó
// flanco descendente, en caso contrario regresa 0
// Interrupción por recepción de datos RS232
#int_rda
void rda_isr() {
dato=getc();// Lee y almacena el dato recibido vía RS232
switch (dato){
case 0:
putc(((myWord)cont_art_0).low);
break;
case 1:
putc(((myWord)cont_art_0).high);
break;
case 2:
putc(((myWord)cont_art_1).low);
break;
case 3:
putc(((myWord)cont_art_1).high);
break;
case 4:
putc(((myWord)cont_art_2).low);
break;
case 5:
putc(((myWord)cont_art_2).high);
break;
case 6:
putc(((myWord)cont_art_3).low);
break;
case 7:
putc(((myWord)cont_art_3).high);
break;
case 8:// Resetea los contadores de todas las articulaciones
cont_art_0=0;
cont_art_1=0;
cont_art_2=0;
cont_art_3=0;
break;
case 9:// Resetea el contador de las articulación 0 solamente
cont_art_0=0;
break;
case 10:// Resetea el contador de las articulación 1 solamente
cont_art_1=0;
break;
case 11:// Resetea el contador de las articulación 2 solamente
cont_art_2=0;
break;
case 12:// Resetea el contador de las articulación 3 solamente
cont_art_3=0;
break;
case 13: // Invierto sentido de giro del encoder 1
if (invierto_enc_1==0){
invierto_enc_1=1;
}
else invierto_enc_1=0;
break;// Tipo Toggle ;-)
case 14: // Invierto sentido de giro del encoder 2
if (invierto_enc_2==0){
invierto_enc_2=1;
}
else invierto_enc_2=0;
break;// Tipo Toggle ;-)
}
}
#INT_RB
void rb_isr() {// Si al menos uno de los pines RB7:RB4 cambió de estado
// entra aquí
pos_act_A1=Lee(A1);// Lee las posiciones actuales de las señales
pos_act_B1=Lee(B1);// proveniente del encoder 1
pos_act_A2=Lee(A2);// Lee las posiciones actuales de las señales
pos_act_B2=Lee(B2);// proveniente del encoder 2
// Procesamos el encoder 1
if (Beta(pos_ant_A1, pos_act_A1)){// Ocurrió un flanco descendente?
if (pos_act_B1==1){
if (!invierto_enc_1) {cont_art_0++;}
else{ if (cont_art_0>0) cont_art_0--;};
};
};
if (Beta(pos_ant_B1, pos_act_B1)){// Ocurrió un flanco descendente?
if (pos_act_A1==1){
if (!invierto_enc_1) {if (cont_art_0>0) cont_art_0--;}
else cont_art_0++;
};
};
// Procesamos el encoder 2
if (Beta(pos_ant_A2, pos_act_A2)){// Ocurrió un flanco descendente?
if (pos_act_B2==1){
if (!invierto_enc_2) {cont_art_3++;}
else{ if (cont_art_3>0) cont_art_3--;};
};
};
if (Beta(pos_ant_B2, pos_act_B2)){// Ocurrió un flanco descendente?
if (pos_act_A2==1){
if (!invierto_enc_2) {if (cont_art_3>0) cont_art_3--;}
else cont_art_3++;
};
};
// Actualizamos las posiciones anteriores de los encoders
pos_ant_A1=pos_act_A1;
pos_ant_B1=pos_act_B1;
pos_ant_A2=pos_act_A2;
pos_ant_B2=pos_act_B2;
}
void main(){
setup_adc(ADC_CLOCK_DIV_32); //configura el reloj del conversor
setup_adc_ports(ALL_ANALOG);
enable_interrupts(int_rda);// Interrupción por recepción de datos via rs232
enable_interrupts(int_rb);// Interrupción por cambio de estado pines RB7:RB4
enable_interrupts(global);
set_tris_b(0xF0);
set_tris_c(0b10000000);
TX=1;// Bit de Stop = 1
// Incialización de las posiciones anteriores de los encoders
pos_ant_A1=Lee(A1);
pos_ant_B1=Lee(B1);
pos_ant_A2=Lee(A2);
pos_ant_B2=Lee(B2);
// Son posiciones referenciales para saber el estado anterior de un pin
while (1){
// Los contadores de las articulaciones 0 y 3, son actualizados
// a través de la interrupción de cambio de estado del puerto B
cont_art_1=Toma_adc(0);// Lee AN0
delay_us(5);// Espero 5 us antes de empezar una nueva conversión
cont_art_2=Toma_adc(1);// Lee AN1
}
}
// Desarrolo de funciones
long Toma_adc(int canal){
long valor;
set_adc_channel(canal);
delay_us(20);
Read_ADC(ADC_START_ONLY);
delay_us(20);
valor=read_adc(ADC_READ_ONLY);
return(valor);
}
int1 Beta(int1 pos_inic, int1 pos_final){// Devuelve 1 si ocurrió una transición
// Beta, en caso contrario regresa 0
if ((pos_inic==1) && (pos_final==0))
{
return(1);
}
else return(0);
}
Adjunto una carpeta comprimida con winrar que contiene el cambio de pines principalmente y se puede ver que funciona, repito utilizo mi calculadora hp48gx a 9600 Baudios para mandarle y recibir datos del pic.