TODOPIC
Microcontroladores PIC => Lenguaje C para microcontroladores PIC => Mensaje iniciado por: jbte en 31 de Octubre de 2014, 13:51:18
-
buenas tardes, lo que pasa es que estoy enviado un dato desde labview al pic16f887 , el envia algunas eces 1byte otras 2 byte dependiendo dle numero que sea(0-100),
en el micro se recibe con RCREG cuando se activa RCIF , pero este dato queda en ascii y lo necesito trabajar endecimal, yo se que si es un solo byte le resto 48 pero como son dos bytes los que se reciben por aparte no se como trabajarlos, cada byte se almacena en la posicion de un vector luego el numero completo estaria
en la posicion BufferIn[0] y BufferIn[1] del vector.
ejemplo : labview envia el numero 50 y el pic recibe BufferIn[0]=53 y BufferIn[1]=48 en ascii
como puedo concatenar estos dos datos(bytes) que estan en ascci y volverlos a numero decimal y se asigno RCREG una variable unsigned char solo toma un byte y no los dos y sigue siendo ascii.
muchas gracias si me pueden colaborar.
unsigned char n;
int a=0,b;
unsigned char array[1];
volatile char BufferIn[20]={0};
volatile unsigned char pos=0;
unsigned char bytein;
unsigned char var = 3;
unsigned char buffer;
#define _XTAL_FREQ 4000000
void putch (unsigned char byte);
unsigned char getch(void);
unsigned char getche(void);
void putUART(const char c);
void main()
{
ANSEL=1;
ANSELH=0;
TRISC=0b10000000;
PORTC=0;
OPTION_REG=0XC0;
INTCON=0B11010000;
TXSTA=0X20; //trasmir habilita tx
RCSTA=0X90;// para poder transmitir o recibir
SPBRG=25;
RCIE=1;
PEIE=1; //enable RX interrupt
GIE=1;
while(1){ printf("\r%d%d \n",BufferIn[0]-48,BufferIn[1]-48);
}
}
void ISR(void){
if(RCIF){
/*El registro "RCREG" tiene el byte recibido*/
bytein=RCREG;
BufferIn[pos]=bytein;
pos++;
if(pos>1) pos=0; // colocarlo e dos bytes vector dos posiciones
RCIF=0; //Limpia bandera de interrupcion
}}
-
No entiendo cual es el problema xD
Si es el primer byte, le restas 48 y lo multiplcas por 10
if(RCIF){
/*El registro "RCREG" tiene el byte recibido*/
BufferIn=(RCREG - 48); // Recibo el byte
if(pos>1) { // Caso que sea el segundo byte
amostrar = temp + BufferIn; // Tus unidades, utilizo una variable mas asi solo se actualiza cuando llegaron todos los datos y usas "amostrar" en el printf
pos=0; // ya estan los 2 bytes
}
else { // Caso primer byte, cada vez q entra aca resetea el valor del registro temp con el nuevo valor
temp = BufferIn * 10; // Tus decenas, si es 0, queda en 0
pos++;
}
RCIF=0; //Limpia bandera de interrupcion
}}
Otro cambio en tu codigo y hacerlo simple seria:
while(1){ printf("\r%d \n",(((BufferIn[0]-48)*10) +BufferIn[1]-48));
Ahora que leo en tu condicion no sabes cuantos datos van a llegar :/ Y es el mayor problema por que no sabes si es una unidad o una decena. Con lo cual el codigo hasta ahora puede hacer cualquier cosa, en espcial si mandas un dato de 1 byte y luego otro de 2.
Se me ocurren algunas ideas para determinar cual es el primero...
1- Usar una trama al final que indique cuando termino, entonces podes mandar 100 datos si queres (Ej. 0x35 0xFF - 5). O una inicial indicando la cantidad bytes tambien. (Ej. 0xF3 0x32 0x31 0x35 - 215) De todas formas un temproizador para que no se quede esperando por siempre.
2- Usar el metodo que usas, pero al recibir uno que actue un temporizador, y de no recibir ningun dato en un tiempo establecido que lo tome como un byte.
3- Si usas como maximo 2 bytes, mandar 2 bytes, si queres mandar un "5", mandas primero un "0" y luego un "5" y asi tenes 05 o 5... O mandar un byte 0xFF y comprobas que al estar fuera de escala significa que el dato no lo mas en cuenta y es igual a 0. (Es complicarse mas si es que podes mandar un 0)
-
muchas gracias por la idea. ya lo termine y puedo concatenar haasta 3 bytes (3 digitos), desde labview envio un@ para identificar la trama y otro@ para finalizarla y leo lo que hay entre ellos y lo guardo en un vector y ahi si se cual es unidades decenas o centenas.
aca dejo el codigo muchas gracias.
while(1)
{
__delay_ms(800);
if(BufferIn[1]==49){ // longitud 1byte
printf("\r%d %d %d %d \n",BufferIn[0],BufferIn[1]-48,BufferIn[2]-48,BufferIn[3]);// trama por separado
b=(BufferIn[2]-48) ;
printf("\r%d \n",b);
}
if(BufferIn[1]==50){//longitud 2 byte
printf("\r%d %d %d %d %d \n",BufferIn[0],BufferIn[1]-48,BufferIn[2]-48,BufferIn[3]-48,BufferIn[4]);// trama por separado
b=(((BufferIn[2]-48)*10) +BufferIn[3]-48);
printf("\r%d \n",b);
}
if(BufferIn[1]==51){ longitud 3byte
printf("\r%d %d %d %d %d %d \n",BufferIn[0],BufferIn[1]-48,BufferIn[2]-48,BufferIn[3]-48,BufferIn[4]-48,BufferIn[5] ); // trama por separado
b=(((BufferIn[2]-48)*100) +((BufferIn[3]-48)*10)+((BufferIn[4]-48)) ); //unidades decennas*10 centenas *100 3 bytes separados asi los concateno
printf("\r%d \n",b);
}
//----------------------------------------------------------
if(RCIF){
/*El registro "RCREG" tiene el byte recibido*/
bytein=RCREG;
bytein=RCREG;
BufferIn[pos]=bytein;
pos++; //vario posicion vector
if(BufferIn[0]==64 && BufferIn[1]==49){ // si el primera posicion del vector[0] es el identificador de la trama [1]==49 es # bytes 1 (1 digito)
if(pos>3) pos=0; // colocarlo e dos bytes vector 4 posiciones
}
if(BufferIn[0]==64 && BufferIn[1]==50){// si el primera posicion del vector[0] es el identificador de la trama [1]==49 es # bytes 2 (2 digito)
if(pos>4) pos=0; // colocarlo e dos bytes vector 5 posiciones
}
if(BufferIn[0]==64 && BufferIn[1]==51){// si el primera posicion del vector[0] es el identificador de la trama [1]==49 es # bytes 3 (3 digito)
if(pos>5) pos=0; // colocarlo e dos bytes vector 6 posiciones
}
RCIF=0; //Limpia bandera de interrupcion
}
-
podrias usar un switch case, y no tantos if
Y te recuerdo el temporizador, mas que nada por que si en algun momento falla la conexcion y se envia mal un caracter o directamente se corta, el micro va a estar esperando sin sentido. Aunque esto es como para ya una version final y no tanto como para probar :P
switch ( BufferIn[1] ) {
case 49:
// Codigo para cuando vale 49
break;
case 50:
// Codigo para cuando vale 50
break;
case 51:
// Codigo para cuando vale 51
break;
default:
// Codigo para cuando recibe cualquier otro valor.
break;
}
-
Gracias.
-
Buenas al igual me meto donde no me llaman.
no he leído el pos en su totalidad pero según creo el pic recibe el dato en un array unidimensional y nunca es el mismo tamaño.
¿estoy en lo cierto?
si es así podrías utilizar una función de c estándar para calcular el tamaño del array.
strlen te devuelve el tamaño del array recibido y en función del tamaño puede hacer tu código para que trabaje de forma automática con los distintos tamaños de los datos.
luego puedes restar cada posición del array por -48, para ello yo utilizaría un bucle for con el valor de bucle el valor dado por strlen y por último convertir con la función de c estándar atoi el array a un número char, c18 tiene unas librerías para esto
no sé es una idea.
saludos
-
gracias por interesarse enn el tema, lo que pasa es que no se recibe unpaquete de varios byte sino que se recibe cada byte, si recibiera un paquete de varios byte ahi si puedo hacer lo que usted dice.
ya que con RCREG solo se recibe un bytew ala vez.
-
Vale entendido