Hola a todos. Tengo un gran problema con la comunicación con MAX485. Tengo conectado un Pic principal que va haciendo un barrido de los otros dos pics conectados. Es decir les envía un dato para que respondan. El tema del conexionado está revisado.
El problema que tengo es que creo que no estoy realizando algo bien a nivel de software ya que cuando solicito que un pic responda solo el primer pic al que llamé responde y el otro no responde cuando se lo solicito. Si luego vuelvo a cambiar el orden de solicitud pasa lo mismo solo acaba respondiendo el primero al que llamé.
El tema de identificar cada pic con una ID es correcto pero creo que al iniciar los pic quizás se debe hacer alguna secuencia para que el max485 quede bien activado.
Es decir quizás se debe poner el pin de control RE/DE (en mi caso B0) a HIGH y luego a LOW una cantidad de tiempo determinado para que quede completamente en funcionamiento el MAX. Os adjunto el código que utiliza uno de los pics al que se le solicita respuesta a ver si ven algo raro y también el conexionado.
He probado de todo pero no lo soluciono. A ver si alguien puede ayudarme o darme nuevas ideas.
#include <16f870.h>
#device ADC=10
//#fuses NOWDT, NOLVP, NOBROWNOUT, NOPROTECT, PUT, INTRC_IO
#fuses HS, NOWDT, NOLVP, NOBROWNOUT, NOPROTECT, PUT
//#use delay (internal=8MHz)
#use delay (clock=8MHz)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7, ERRORS) //CONFIGURO PUERTO SERIE
//#use RS232(UART1, ERRORS)
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
//**VARIABLES PARA GESTIONAR LA TRAMA RECIBIDA Y LA TRAMA A ENVIAR POR PUERTO SERIE**//
long valor_adc=0; //Variable de 16 bits para lectura ADC
int P_W=0; //indice escritura
int P_R=0; //indice lectura
int i=0;
int j=0;
int inicio=0;
int final=0;
char string_valor_adc[5]="0000";//Cadena de caracteres para guardar valor ADC en Carcteres
char trama_entrada[51]={0}; //String para guardar el dato de entrada por UART
char direccion_pic[4]="P02";
char tipo_dato[5]="$ADQ";
char canal[4]="CH0";
char dato[14]="$ADQ,P02,CH0\r";
char miretorno[2]="\r";
char misimbolo[2]="$";
short flag_final=0;
short flag_permiso=0;
short flag_tst=0;
short flag_envio=0;
//FUNCIÓN PARA LEER LOS DATOS PROCEDENTES DEL PUERTO SERIE//
void lectura(){
for(P_R=0; P_R<51; P_R++){
if(trama_entrada[P_R]==misimbolo[0]){
inicio=P_R;
for(P_R=inicio; P_R<51; P_R++){
if(trama_entrada[P_R]==miretorno[0]){
P_W=0;
final=P_R;
flag_permiso=1;
break;
}
}
break;
}
}
}
//FUNCIÓN PARA COPIAR EL DATO PROCEDENTE DEL BUFFER DEL PUERTO SERIE//
void escritura(){
for(i=inicio; i<=final; i++){
dato[j]=trama_entrada[i];
j++;}
i=0;
j=0;
memset(trama_entrada, 0, sizeof(trama_entrada));
return;
}
//FUNCIÓN PARA PROCESAMIENTO DEL DATO PROCEDENTE DEL PUERTO SERIE//
void procesamiento(){
//Se copia la dirección de la solicitud para saber a qué pic va dirigido//
//Éste pic tiene la dirección "P01"//
for(i=0; i<3; i++){
direccion_pic[i]=dato[i+5];}
direccion_pic[3]='\0';
//Se compara la dirección obtenida con la de éste pic//
if(strcmp(direccion_pic, (char*)"P02")==0){
memset(direccion_pic, 0, sizeof(direccion_pic));
//Se copia el tipo de dato que puede ser "$ADQ" o "$TST"//
for(i=0; i<4; i++){
tipo_dato[i]=dato[i];}
tipo_dato[4]='\0';
//Se compara el tipo de dato con "$ADQ" que es para obtener medidas del ADC//
if(strcmp(tipo_dato, (char*)"$ADQ")==0){
memset(tipo_dato, 0, sizeof(tipo_dato));
flag_tst=0;//flag para el case de la función enviar
//Se copia el canal para ver qué canal se quiere escoger "CH0" o "CH1"//
for(i=0; i<3; i++){
canal[i]=dato[i+9];}
canal[3]='\0';
//Se compara el canal//
if(strcmp(canal,(char*)"CH0")==0){
set_adc_channel(0);}
else if(strcmp(canal,(char*)"CH1")==0){
set_adc_channel(1);}
//Lectura del ADC//
delay_us(20);//retardo para leer ADC
valor_adc=read_adc();//lectura ADC
sprintf(string_valor_adc,"%04ld",valor_adc);
}
//Se compara el tipo de dato con "$TST" que es para que éste pic responda con "$TST,P01\r"//
else if(strcmp(tipo_dato,(char*)"$TST")==0){
memset(tipo_dato, 0, sizeof(tipo_dato));
flag_tst=1;
}
//Se da permiso para enviar dato//
flag_envio=1;//flag para el case de la función enviar
}
return;
}
void enviar(){
switch(flag_tst){
case 0:
output_high(PIN_B0);
delay_ms(3);
printf("$ADQ,P02,%s,%s\r", canal,string_valor_adc);
delay_ms(3);
output_low(PIN_B0);
break;
case 1:
output_high(PIN_B0);
delay_ms(3);
printf("$TST,P02\r");
delay_ms(3);
output_low(PIN_B0);
flag_tst=0;
break;
}
return;
}
void main(){
output_low(PIN_B0);
output_high(PIN_C4);
disable_interrupts(INT_RDA);
enable_interrupts(GLOBAL); //HABIlLITO TODAS LAS INTERRUPCIONES GLOBALES
enable_interrupts(INT_RDA); //HABILITO LA INTERRUPCIÓN UART
setup_adc_ports(ALL_ANALOG); //INDICO EL PIN A0/A1/A2/A3/A4/A5 COMO ENTRADA ANALÓGICA
setup_adc(ADC_CLOCK_INTERNAL); //CLOCK INTERNO PARA CONVERSIÓN ADC
while(1){
output_high(PIN_C4);
delay_ms(1000);
output_low(PIN_C4);
delay_ms(1000);
if(flag_final==1){
flag_final=0;
lectura();
if(flag_permiso==1){
flag_permiso=0;
escritura();
procesamiento();
if(flag_envio==1){
flag_envio=0;
enviar();
}
}
}
}
}
#INT_RDA
void INT_UART(void) {
trama_entrada[P_W]=getc();
if(trama_entrada[P_W]=='\r'){
P_W=0;
flag_final=1;
}
else{
P_W++;
if(P_W >=21 ){
P_W=0;
}
}
}