TODOPIC
Microcontroladores PIC => Lenguaje C para microcontroladores PIC => Mensaje iniciado por: zagoaristides en 27 de Junio de 2009, 21:04:39
-
Bueno, quisiera consultar antes que nada si alguien tiene un ejemplo usando la librería RS485.C comunicando 2 pics.
A ver si alguien puede probar esto que posteo. Los hilos de RS485 ya me los leí a todos, también la norma RS485 y no puedo hacer funcionar esta bendita comunicación. Las librerías que andan por aquí desearía que tuvieran control de errores por eso uso esta que encontré por ahí y modifiqué un poquito. Ya habré escrito sin exagerar más de 100 códigos diferentes, algunos mejor otros peor funcionaron, pero nunca puedo hacer que funcione este ^#@*""%$"& protocolo para diferentes familias de PIC que es lo que quiero para que el próximo como yo que necesite RS485 no reniegue y sea como levantar el teléfono, discar y escuchar el interlocutor sin problemas, en fin ya estoy delirando.
Este es el último código de Maestro, Esclavo y Librería. Lo que no puedo hacer ahora es que el SLAVE se interrumpa por hard (INT_RDA)
Y el Proteus que vive diciendo Logic Contention aunque lo simule casi sin nada. Será Proteus el problema, habré puesto algo mal???
Ahora si, remito el código, pero por favor, si alguien quiere ayudar que lo simule, subo el archivito Proteus también. Lo digo porque se acostumbra a dar soluciones muy a priori en ocasiones que no ayudan mucho.
Gracias desde ya.
MASTER:
#include <16F876A.h>
#fuses HS, NOWDT, NOPROTECT, NOLVP, NOBROWNOUT, PUT
#use delay (clock=20000000)
//#define GREEN_LED PIN_C0
#define DATA_IN (ext_buffer_next_in != ext_buffer_next_out)
#define SEND_ADDRESS 0x02
#define MACHINE_ADDRESS 0x01
#include <RS485-mio.c>
void main() {
set_tris_c(0b00000000);
delay_ms(100);
while(1)
{
packet_buffer[0] = SEND_ADDRESS;
packet_buffer[1] = MACHINE_ADDRESS;
packet_buffer[2] = 0;
packet_buffer[3] = 0;
packet_buffer[4] = 9;
packet_buffer[5] = 'H';
packet_buffer[6] = 'i';
packet_buffer[7] = ' ';
packet_buffer[8] = 't';
packet_buffer[9] = 'h';
packet_buffer[10] = 'e';
packet_buffer[11] = 'r';
packet_buffer[12] = 'e';
packet_buffer[13] = '!';
send_packet(packet_buffer, 14);
}
}
SLAVE:
#include <16F876A.h>
#fuses HS, NOWDT, NOPROTECT, NOLVP, NOBROWNOUT, PUT
#use delay (clock=20000000)
#define DATA_IN (ext_buffer_next_in != ext_buffer_next_out)
#define SEND_ADDRESS 0x02
#define MACHINE_ADDRESS 0x01
#include <RS485-mio.c>
void main() {
setup_adc_ports(NO_ANALOGS);
setup_adc(ADC_OFF);
setup_comparator(NC_NC_NC_NC);
setup_vref(FALSE);
setup_timer_0(RTCC_INTERNAL|RTCC_DIV_256);
setup_timer_1(T1_INTERNAL|T1_DIV_BY_8);
setup_timer_2(T2_DIV_BY_16,255,16);
enable_interrupts(INT_RDA);
enable_interrupts(GLOBAL);
set_tris_c(0b10000000);
while(TRUE)
get_packet(ext_buffer, TRUE);
}
LIBRERÍA:
#use rs232(baud=9600,bits=8,parity=N,xmit=PIN_C6,rcv=PIN_C7,stream=COM1)
#use rs232(baud=9600,bits=8,parity=N,xmit=PIN_C6,rcv=PIN_C7,force_sw,stream=COM2)
#define enable_rcv_max PIN_C5
#define ACK 0x01
#define NACK 0xFF
#define BUFFER_SIZE 20
int packet_buffer[BUFFER_SIZE];
char ext_buffer[BUFFER_SIZE];
////////////////////////////////////////////////////////////////////////////////
/// Estructura variables comunicacion serial ///////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
struct _comm{
int1 nuevo_paquete; //hay un nuevo paquete a analizar
int8 cuenta_rx; //caracteres recibidos en el ultimo paquete
BYTE trama[BUFFER_SIZE];
int1 ocupado; //flag que indica si estamos procesando un paquete
BYTE byt; //caracter dummy, para sacar del puerto serie
} comm;
////////////////////////////////////////////////////////////////////////////////
/// Interrupción timer1 para timeout tiempo para saber si hay datos nuevos /////
////////////////////////////////////////////////////////////////////////////////
#int_TIMER1
void TIMER1_isr(){
disable_interrupts(int_TIMER1);
comm.ocupado=1; // No mas recepción de mensajes..
comm.nuevo_paquete=1; // Paquete a la espera de ser analizado
}
////////////////////////////////////////////////////////////////////////////////
/// Interrupción serial para entrada de datos //////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
#int_rda
void serial_isr(){
comm.byt=fgetc(COM1); // recoge dato byte entrante
if (!comm.ocupado){ // si estamos procesando un envió no se hace caso..
comm.trama[comm.cuenta_rx++]=comm.byt;
set_timer1(30000); // esperar el tiempo que deseemos como timeout
clear_interrupt(int_TIMER1); // limpiar el flag de overflow del timer1
enable_interrupts(int_TIMER1);
}
}
//#define CRC_CCITT 0x1021 //bit pattern (1)0001 0000 0010 0001
#include <CRC.C>
////////////////////////////////////////////////////////////////////////////////
/// Funcion que espera el bus para evitar colisiones ///////////////////////////
////////////////////////////////////////////////////////////////////////////////
void espera_bus(void){
int16 i;
setup_uart(FALSE); // Deshabilita UART para falsas recepciones
for(i=0; i <= 400; ++i){ // Espera aproximadamente 20 ms si el bus esta libre
if(!input(PIN_C7)) // sino se queda a la espera
i = 0;
else
delay_us(50);
}
}
// SEND_PACKET
// Función que envia paquete a otro dispositivo
void send_packet(int* packet_ptr, int16 packet_length)
{
int *ptr;
int16 CRC,i;
espera_bus(); // Espera el bus para evitar colisiones
output_high(enable_rcv_max); // Habilita salida datos max485
ptr = packet_ptr; // puntero a paquete
CRC = generate_16bit_crc(ptr, packet_length, CRC_CCITT); // crea CRC
for(i=0; i<packet_length; i++) // envia paquete
fputc(packet_ptr,COM2);
fputc((int)(CRC>>8),COM2); // envia CRC
fputc((int)(CRC),COM2);
delay_ms(10);
output_low(enable_rcv_max);
setup_uart(TRUE);
}
// GET_PACKET
// Función que procesa el paquete y analiza si es valido o no
// espera TRUE -> Espera paquete
// FALSE -> No espera paquete
short get_packet(int* packet_ptr, int1 espera)
{
short retval;
int16 length;
int16 CRC;
int16 i;
retval = TRUE;
if(espera){
while(!comm.nuevo_paquete); // Espera que halla nuevo paquete
}else{
if(!comm.nuevo_paquete){ // si no lo hay retorna cero
return(FALSE);
}
}
packet_ptr[0] = comm.trama[0]; // Direccion destino paquete
packet_ptr[1] = comm.trama[1]; // direccion de donde viene paquete
if(packet_ptr[0] != MACHINE_ADDRESS){
comm.ocupado=0; // Habilita recepción de nuevos datos
comm.nuevo_paquete=0; // ya no hay mas datos
comm.cuenta_rx=0; // Contador de index de datos a cero
return(FALSE);
}
packet_ptr[2] = comm.trama[2]; // Byte ACK o NACK
if(packet_ptr[2] == NACK){
comm.ocupado=0; // Habilita recepción de nuevos datos
comm.nuevo_paquete=0; // ya no hay mas datos
comm.cuenta_rx=0; // Contador de index de datos a cero
return(FALSE);
}
packet_ptr[3] = comm.trama[3]; // Tamaño de datos en el paquete
packet_ptr[4] = comm.trama[4];
length = make16(packet_ptr[3],packet_ptr[4]);
for(i=5; i<(length+5); i++) // recoje los datos
packet_ptr = comm.trama;
packet_ptr[length+5] = comm.trama[length+5]; // recoje CRC
packet_ptr[length+6] = comm.trama[length+6];
CRC = make16(packet_ptr[length+5],packet_ptr[length+6]);
if(CRC != generate_16bit_crc(packet_ptr, length+5, CRC_CCITT)){ // Analisis CRC
ext_buffer[0]=packet_buffer[1]; //En caso de CRC malo envia NACK
ext_buffer[1]=MACHINE_ADDRESS;
ext_buffer[2]=NACK;
ext_buffer[3]=0;
ext_buffer[4]=1;
ext_buffer[5]=NACK;
send_packet(ext_buffer,6);
retval = FALSE;
}
comm.ocupado=0; // Habilita recepción de nuevos datos
comm.nuevo_paquete=0; // ya no hay mas datos
comm.cuenta_rx=0; // Contador de index de datos a cero
return retval;
}
-
Bueno, esto se me está tornando rutinario, lo de escribir y pedir por ayuda, sea en español, inglés, italiano y próximamente en chino. No encontré un kit de desarrollo RS485 porque aunque saliera 200 dólares (lo que me costó el de CAN BUS) lo compraba. Por cierto, todo esto viene a que la maldita librería RS485.C es lo más increiblemente inútil que encontré, ya que (hace más de 2 meses) no hay ejemplos de comunicación entre 2 PICs, les escribí a los de CCS y muy amablemente me enviaron UN EJEMPLO MÁS DE PIC-PC!!! Ven que necesito chino!!!!
A ver si alguien (que sepa) puede probar esto. Ah, pro favor no me digan de los hilos de RS485 porque ya me los leí a todos, ni de la norma ni de la Claudia ya lei T.O.D.O. y no puedo hacer funcionar esta bendita comunicación. Y tampoco me gustan las librerías que crearon algunos aquí porque no tienen control de errores. Ya habré escrito sin exagerar más de 100 códigos diferentes, algunos mejor otros peor funcionaron, pero nunca puedo hacer que funcione este ^#@*""%$"& protocolo para diferentes familias de PIC que es lo que quiero para que el próximo gil como yo que necesite RS485 no reniegue y sea como levantar el teléfono, discar y escuchar la voz de la mina que te gusta, en fin ya estoy delirando.
Este es el último código de Maestro, Esclavo y Librería. Lo que no puedo hacer ahora es que el SLAVE se interrumpa por hard (INT_RDA)
Y el Proteus que vive diciendo Logic Contention aunque lo simule sin nada más o menos, es una ^#@*""%$"& Será Proteus el problema??? En Can no sirve, así que.... Bue, no nos desviemos de tema.
Ahora si, remito el código, pero por favor, si alguien quiere ayudar que lo simule, subo el archivito Proteus también. Lo digo porque se acostumbra a dar soluciones muy a priori en ocasiones que no ayudan a nadie.
Gracias desde ya.
Vaya que modos !
y tu hard?? como has conectado??
Seguro tienes problemas de comprension si te has leído todo y no resuelve tu problema. Aqui mismo han trabajado rs485 pic-pic.
Como no lo se todo no creo poder ayudarte !
suerte ! :angel:
-
Hola.
Las librerias del CCS son 100% funcionales -es decir, funcionan SI o SI-. Yo base mi codigo en el hilo del maestro RedPIC y lo unico que hice fue diseñar el firmware del del PIC Maestro.
Que pena que no te gusten las librerias creadas por otros :( pero es un muy buen precedente para que hagas la tuya mucho mas funcional que la del resto de nosotros.
En el control del Ascensor de Carga -entiendase Malacate- yo use un 18F452 y varios 16F628A ... y hasta un PIC12F629 con la misma libreria ....
El proteus simula a la perfeccion el RS485. A mi no me dio problema.
Mi fuerte no es la electronica -no soy ing. electronico- asi que, segun tus requerimentos, no te puedo ayudar, ya que no se lo suficiente.
Lo del Logic Contention -disculpa que te aconseje- es por que hay choques de logica entre pines de entrada y salida (si le das click al reporte de los warm esta especificado el warning, en ingles claro-.
Muchos exitos en el desarrollo de tu nueva libreria ...
Saludos
-
Hola.
Las librerias del CCS son 100% funcionales -es decir, funcionan SI o SI-. Yo base mi codigo en el hilo del maestro RedPIC y lo unico que hice fue diseñar el firmware del del PIC Maestro.
Que pena que no te gusten las librerias creadas por otros :( pero es un muy buen precedente para que hagas la tuya mucho mas funcional que la del resto de nosotros.
En el control del Ascensor de Carga -entiendase Malacate- yo use un 18F452 y varios 16F628A ... y hasta un PIC12F629 con la misma libreria ....
El proteus simula a la perfeccion el RS485. A mi no me dio problema.
Mi fuerte no es la electronica -no soy ing. electronico- asi que, segun tus requerimentos, no te puedo ayudar, ya que no se lo suficiente.
Lo del Logic Contention -disculpa que te aconseje- es por que hay choques de logica entre pines de entrada y salida (si le das click al reporte de los warm esta especificado el warning, en ingles claro-.
Muchos exitos en el desarrollo de tu nueva libreria ...
Saludos
Hola, no dije que no me gustan, dije que no me gustan las que hay por aquí porque no tienen control de errores simplemente. Pero de última usaré esas. Has usado la librería RS485.C? Puedes poner un ejemplo entre PICs?
Gracias.
-
Hola.
Las librerias del CCS son 100% funcionales -es decir, funcionan SI o SI-. Yo base mi codigo en el hilo del maestro RedPIC y lo unico que hice fue diseñar el firmware del del PIC Maestro.
Que pena que no te gusten las librerias creadas por otros :( pero es un muy buen precedente para que hagas la tuya mucho mas funcional que la del resto de nosotros.
En el control del Ascensor de Carga -entiendase Malacate- yo use un 18F452 y varios 16F628A ... y hasta un PIC12F629 con la misma libreria ....
El proteus simula a la perfeccion el RS485. A mi no me dio problema.
Mi fuerte no es la electronica -no soy ing. electronico- asi que, segun tus requerimentos, no te puedo ayudar, ya que no se lo suficiente.
Lo del Logic Contention -disculpa que te aconseje- es por que hay choques de logica entre pines de entrada y salida (si le das click al reporte de los warm esta especificado el warning, en ingles claro-.
Muchos exitos en el desarrollo de tu nueva libreria ...
Saludos
Hola! Estoy montando una red de sensores usando rs485. Le agradecería si pudiera enviarme algún ejemplo de aplicación del código de C
CCS y do Proteus, o que me podía ayudar con los códigos que yo hizo.
Este código me adapté del código de ejemplo de CCS. Esta aplicación que necesito que puedo enviar un mensaje de maestro a esclavo y el esclavo a el maestro.
Estoy enviando los códigos que lo hizo, si se me puede ayudar!
-
Hola a todos en esta conversa, tengo algunas recomendaciones que les puedo hacer en base a mi trabajo con RS485:
1) Comunicacion entre dos PIC -> protocolo USART asincrono -> RS232. (Todos deberian llegar a hacer funcionar esto primero)
2) Realizado lo anterior con exito, -> existen dos maneras de implementar el bus RS485:
- con uso del SN75179, este no tiene habilitadores ( DE y RE) y se pueden conectar directamente Tx y Rx de ambos uPIC. Desventaja: usa 4 hilos.
- con uso de MAX487 o equivalente, este tiene pines de habilitacion de envio/recepcion (DE y RE) que deben ser habilitados cuando se requiera enviar o recibir
-
Hola a todos en esta conversa, tengo algunas recomendaciones que les puedo hacer en base a mi trabajo con RS485:
1) Comunicacion entre dos PIC -> protocolo USART asincrono -> RS232. (Todos deberian llegar a hacer funcionar esto primero)
2) Realizado lo anterior con exito, -> existen dos maneras de implementar el bus RS485:
- con uso del SN75179, este no tiene habilitadores ( DE y RE) y se pueden conectar directamente Tx y Rx de ambos uPIC. Desventaja: usa 4 hilos.
- con uso de MAX487 o equivalente, este tiene pines de habilitacion de envio/recepcion (DE y RE) que deben ser habilitados cuando se requiera enviar o recibir
datos. Por lo tanto un pin mas sera necesario (pueden ver en ejemplos anteriores).
Como es sabido: todos quieren enviar un comando con el master, y este a su vez desea una respuesta del esclavo(s).
PROBLEMA: cuando hacen esa conexion con max485 no funciona, (pero conectado directamente ambos uPIC si funciona).
Solucion: tienen que tener en cuenta los tiempos, ya quepor ejemplo un uPIC con reloj de 4MHz, bus USART asincrono (8 N 1), y transmision a 9600 baudios,
osea un byte tarda 1/9600 seg = 104us aprox. Por lo tanto cuando habiliten la TRANSMISION de cualquiera de los uPIC deanle un poco mas de tiempo
para que termine de enviar el dato, luego recien deshabiliten el envio. Para la recepcion no es necesario porque tanto maestro y esclavo siempren
estan, por lo general, "escuchando el bus".
abrazo
-
Hola.
tienen que tener en cuenta los tiempos, ya quepor ejemplo un uPIC con reloj de 4MHz, bus USART asincrono (8 N 1), y transmision a 9600 baudios,
osea un byte tarda 1/9600 seg = 104us aprox. Por lo tanto cuando habiliten la TRANSMISION de cualquiera de los uPIC deanle un poco mas de tiempo
para que termine de enviar el dato, luego recien deshabiliten el envio. Para la recepcion no es necesario porque tanto maestro y esclavo siempren
estan, por lo general, "escuchando el bus".
O se testea el registro de fin de transmision del PIC -esa solución la dio el Sr. Nocturno ... pero no encontre el link para ponerlo- ;-)
-
Saludos amigos.
Estoy usando (sería mejor decir intentando usar) librerias RS485.C del compilador CCS en versión 4.104. El ejemplo que he usado es EX_RS485.C y lo he simulado en PROTEUS 7.6 con 2 16F628A y con 2 MAX487 como conversores 485.
Las librerias me atraen por que parece que implementan de una forma sencilla el control de errores y todo eso, pero la verdad es que no hay forma de que funciones.
¿Alguien tiene un ejemplo operativo con estas librerias?.
Gracias anticipadas.
Jc
-
Hola amigos!
Yo tambien estoy trabajando en un proyecto RS485, pero uso MPLAB y Proteus. Lo peor es que no puedo encontrar nada de ejemplos en MPLAB, todo lo que encuentro es para CCS. Es bastante diferente y no se como modificar el codigo del CCS para MPLAB. Necesito realizar comunicación master-esclavo.
Alguien me puede ayudar por favor!
Gracias y saludos!
-
Hola a todos, da gracia ver cómo nadie ha hecho andar esta bendita librería... lamentablemente soy uno más :(
Les comento, utilizo un 18F2550 como Master y varios 16F628 como esclavos.
Leí, detalle, comente, y revise todos y cada uno de los ejemplos, y la librería RS485.c por completo, y sigo sin poder hacerla funcionar.
El esquema que estoy utilizando es el siguiente:
Maestro:
(http://jdb9tg.blu.livefilestore.com/y1pVAFx3sQGCzxqHp5Z0zDr6I179oMsAsCctda9TfykrS4QmFGn-zcXu7qV3Fk7K6KwFLRDtExy1_-gPLVP33hSIkcgRNkeATJK/maestro.bmp?psid=1)
Esclavo:
(http://jdb9tg.blu.livefilestore.com/y1ppzXYBVR-1FtI_0yXyrV4WGGkjyRprpGK_ihjYmgvgb9tXYTn4ZHwv_BwKiqTIE5Ve6hNdiumyq_LUUaL2HMB-2F_01EC69zB/esclavo.bmp?psid=1)
El código del maestro:
#include "rs485_maestro.h"
#define RS485_RX_BUFFER_SIZE 64 //tamaño del buffer
#define RS485_USE_EXT_INT FALSE //Indico que uso interrupción por UART
int8 OUR_RS485_ID = 1; //N° de ID del Dispositivo
#define RS485_ID OUR_RS485_ID
#include "rs485_18F2550.c" //Librería para RS485
#include "lcd_bus_8bits.c" //Librería de manejo del LCD
int8 msg[64]; //Longitud del mensaje a enviar
void RS485send(char* s, int8 id) //Envia por rs485 el string donde apunta s
{ //al ID indicado
int8 size;
for(size=0; s[size]!='\0'; ++size); //Cuenta los caracteres del mensaje
rs485_wait_for_bus(TRUE); //Verifica que el bus esté desocupado
//TRUE: resetea el watchdog
while(!rs485_send_message(id, size, s)) //Envia el mensage de la forma:
//source | destination | data-length | data | checksum
//Sale del bucle con TRUE: el mensaje se envio sin colisiones
delay_ms(OUR_RS485_ID);
}
void main()
{
int i, dest_id = 0;
char dato[2];
lcd_init();
lcd_putc("Iniciando...\n");
RS485_init();
delay_ms(1000);
dest_id=15;
while(TRUE){
printf(lcd_putc,"\fEnviando a ID %d", dest_id);
for(i=0;i<=3;i++){
lcd_gotoxy(1,2);
printf(lcd_putc,"Activando rele %d", i+1);
dato[0]='A'+i;
dato[1]='1';
RS485send(dato, dest_id);
delay_ms(1000);
}
for(i=0;i<=3;i++){
lcd_gotoxy(1,2);
printf(lcd_putc,"Desact. rele %d ", i+1);
dato[0]='A'+i;
dato[1]='0';
RS485send(dato, dest_id);
delay_ms(1000);
}
}
}El código del esclavo:
#include "rs485_esclavo.h"
#define RS485_RX_BUFFER_SIZE 64 //tamaño del buffer
#define RS485_USE_EXT_INT FALSE //Indico que uso interrupción por UART
int8 OUR_RS485_ID = 15; //N° de ID del Dispositivo
#define RS485_ID OUR_RS485_ID
#include "rs485_16F628.c" //Librería para RS485
int8 msg[64]; //Longitud del mensaje a enviar/recibir
void RS485send(char* s, int8 id) //Envia por rs485 el string donde apunta s
{ //al ID indicado
int8 size;
for(size=0; s[size]!='\0'; ++size); //Cuenta los caracteres del mensaje
rs485_wait_for_bus(TRUE); //Verifica que el bus esté desocupado
//TRUE: resetea el watchdog
while(!rs485_send_message(id, size, s)) //Envia el mensage de la forma:
//source | destination | data-length | data | checksum
//Sale del bucle con TRUE: el mensaje se envio sin colisiones
delay_ms(OUR_RS485_ID);
}
void main()
{
char comando,accion;
RS485_init();
activar(rele1);
activar(rele2);
activar(rele3);
activar(rele4);
delay_ms(1000);
desactivar(rele1);
desactivar(rele2);
desactivar(rele3);
desactivar(rele4);
while(TRUE){
if(rs485_get_message(msg, TRUE))
{
comando = msg[2];
accion = msg[3];
switch(comando){
case 'A': if(accion == '1')
activar(rele1);
else
desactivar(rele1);
break;
case 'B': if(accion == '1')
activar(rele2);
else
desactivar(rele2);
break;
case 'C': if(accion == '1')
activar(rele3);
else
desactivar(rele3);
break;
case 'D': if(accion == '1')
activar(rele4);
else
desactivar(rele4);
break;
default: desactivar(rele1);
desactivar(rele2);
desactivar(rele3);
desactivar(rele4);
break;
}
}
}
}
Tanto rs485_18F2550.c como rs485_16F628.c son ni más ni menos que la librería rs485.c de CCS, modificadas para adaptarse a los pines de cada micro (y NO, no son los pines el problema).
La simulación en proteus funciona bien, pero al meter un virtual terminal me arroja todos FF, además que al enviar detecta colisiones permanentemente, y nunca sale del bucle. Al programar los micros y probar, el problema de las colisiones desaparece, pero el master sigue enviando "basura".
Alguna idea?
-
Hola quisiera que me pudieran ayudar con esta red de pics usando rs485 ya esta la comunicacion hacia el esclavo pero ahora lo que quiero es que el esclavo le responda al maestro que recibio bn la trama o que mediante un push botton pueda enviar datos al master, porfavor adjunto simulacion en proteus y codigos, espero y me puedan ayudar porfavor