PIC: 18F2550
Compilador: CCS 4
El proyecto cuenta con 3 tarjetas con el chip max485 y un pic 18F2550 en cada una de ellas. El código es el siguiente:
#include <18F2550.h>
#DEVICE ADC = 10
#include <stdlib.h>
#fuses INTRC,MCLR,NOWDT,NOPROTECT,NOPUT,NOBROWNOUT,NOLVP,NOCPD
#use delay(clock=4000000)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7, STREAM=COM_A, parity=N, bits=8)
#define TX_485_ENABLE PIN_C0
char p, term[2], command[66] = "", action[10] = "", values[45] = "";//, picid[10] = "";
char permited[9] = "";
int k = 0, contador1 = 0, distance[2], newdistance = 0, winche = 0, dir = 0;
int cmxcheck = 11, meters = 0, mdif = 0;
int32 seconds[14], times[14], epoch = 0, timeon = 0;
int16 checks = 0, cms = 0, oldchecks = 0;
int1 newcommand = 0, newsecond = 0, readsensor = 0, count = 0;
float value = 0;
unsigned int16 pic, picsaved;
//funciones 485
void USART_activa_tx(void){
output_high(TX_485_ENABLE);
delay_ms(5);
}
void USART_activa_rx(void){
delay_ms(5);
output_low(TX_485_ENABLE);
delay_ms(1);
}
// subrutina de interrupción del timer1
#int_TIMER1
void TIMER1_isr(){
contador1++;
if(contador1 == 2){
newsecond = 1;
contador1 = 0;
}
set_timer1(3036);
}
//interrupcion por usart del pic
#INT_RDA
void usart_modem(void)
{
disable_interrupts(INT_RDA);
newcommand = 0;
if (kbhit(COM_A))
{
p = fgetc(COM_A);
if(p == '#') {
command[k] = '\0';
newcommand = 1;
k = 0;
}else{
command[k] = p;
k++;
}
}
enable_interrupts(INT_RDA);
}
//comparar 2 cadenas
int is_equal(char *p1, char *p2)
{
int *p3;
p3 = strstr(p1,p2);
return (p3);
}
//variables a cero
void to_zero()
{
readsensor = 0;
meters = 0;
checks = 0;
cms = 0;
}
//encendido manual de pines segun comando
void open(void)
{
int i, j=0;
char numbers[3] = "", letter;
unsigned char number;
for(i = 0; i < strlen(values); i += 3){
numbers[0] = values[i];
numbers[1] = values[i+1];
numbers[2] = '\0';
letter = values[i+2];
number = atoi(numbers);
if(letter == 77) number *= 60;
seconds[j] = number;
times[j] = epoch;
j++;
}
if(seconds[0] > 0) output_bit(PIN_C0, 1);
if(seconds[1] > 0) output_bit(PIN_C1, 1);
if(seconds[2] > 0) output_bit(PIN_C2, 1);
if(seconds[3] > 0) output_bit(PIN_C3, 1);
if(seconds[4] > 0) output_bit(PIN_B7, 1);
if(seconds[5] > 0) output_bit(PIN_B6, 1);
if(seconds[6] > 0) output_bit(PIN_B5, 1);
if(seconds[7] > 0) output_bit(PIN_B4, 1);
if(seconds[8] > 0) output_bit(PIN_B3, 1);
if(seconds[9] > 0) output_bit(PIN_B2, 1);
if(seconds[10] > 0) output_bit(PIN_B1, 1);
if(seconds[11] > 0) output_bit(PIN_B0, 1);
if(seconds[12] > 0) output_bit(PIN_C5, 1);
if(seconds[13] > 0) output_bit(PIN_C4, 1);
}
//apagado manual de pines segun comando close
void close(void)
{
if(values[0] > 0) output_bit(PIN_C0, 0);
if(values[1] > 0) output_bit(PIN_C1, 0);
if(values[2] > 0) output_bit(PIN_C2, 0);
if(values[3] > 0) output_bit(PIN_C3, 0);
if(values[4] > 0) output_bit(PIN_B7, 0);
if(values[5] > 0) output_bit(PIN_B6, 0);
if(values[6] > 0) output_bit(PIN_B5, 0);
if(values[7] > 0) output_bit(PIN_B4, 0);
if(values[8] > 0) output_bit(PIN_B3, 0);
if(values[9] > 0) output_bit(PIN_B2, 0);
if(values[10] > 0) output_bit(PIN_B1, 0);
if(values[11] > 0) output_bit(PIN_B0, 0);
if(values[12] > 0) output_bit(PIN_C5, 0);
if(values[13] > 0) output_bit(PIN_C4, 0);
}
//auto apagado de pines segun paso del tiempo
void auto_off(void)
{
if(seconds[0] > 0 && (epoch - times[0]) > seconds[0]) output_bit(PIN_C0, 0);
if(seconds[1] > 0 && (epoch - times[1]) > seconds[1]) output_bit(PIN_C1, 0);
if(seconds[2] > 0 && (epoch - times[2]) > seconds[2]) output_bit(PIN_C2, 0);
if(seconds[3] > 0 && (epoch - times[3]) > seconds[3]) output_bit(PIN_C3, 0);
if(seconds[4] > 0 && (epoch - times[4]) > seconds[4]) output_bit(PIN_B7, 0);
if(seconds[5] > 0 && (epoch - times[5]) > seconds[5]) output_bit(PIN_B6, 0);
if(seconds[6] > 0 && (epoch - times[6]) > seconds[6]) output_bit(PIN_B5, 0);
if(seconds[7] > 0 && (epoch - times[7]) > seconds[7]) output_bit(PIN_B4, 0);
if(seconds[8] > 0 && (epoch - times[8]) > seconds[8]) output_bit(PIN_B3, 0);
if(seconds[9] > 0 && (epoch - times[9]) > seconds[9]) output_bit(PIN_B2, 0);
if(seconds[10] > 0 && (epoch - times[10]) > seconds[10]) output_bit(PIN_B1, 0);
if(seconds[11] > 0 && (epoch - times[11]) > seconds[11]) output_bit(PIN_B0, 0);
if(seconds[12] > 0 && (epoch - times[12]) > seconds[12]) output_bit(PIN_C5, 0);
if(seconds[13] > 0 && (epoch - times[13]) > seconds[13]) output_bit(PIN_C4, 0);
}
//mueve el winche
void move()
{
to_zero();
if(winche == 0)
{
if(dir == 0)
{
output_bit(PIN_B7, 1);
output_bit(PIN_B5, 1);
readsensor = 1;
}
if(dir == 1)
{
output_bit(PIN_B6, 1);
output_bit(PIN_B4, 1);
readsensor = 1;
}
}
if(winche == 1)
{
if(dir == 0)
{
output_bit(PIN_B3, 1);
output_bit(PIN_B1, 1);
readsensor = 1;
}
if(dir == 1)
{
output_bit(PIN_B2, 1);
output_bit(PIN_B0, 1);
readsensor = 1;
}
}
}
//detiene el winche
void stop()
{
to_zero();
if(winche == 0)
{
if(dir == 0)
{
output_bit(PIN_B7, 0);
output_bit(PIN_B5, 0);
}
if(dir == 1)
{
output_bit(PIN_B6, 0);
output_bit(PIN_B4, 0);
}
}
if(winche == 1)
{
if(dir == 0)
{
output_bit(PIN_B3, 0);
output_bit(PIN_B1, 0);
}
if(dir == 1)
{
output_bit(PIN_B2, 0);
output_bit(PIN_B0, 0);
}
}
}
//cuenta vueltas y calcula distancia recorrida ITG0001|MOVE|0$2$|#
void check_distance()
{
value = read_adc();
if(value < 500)
{
if(count == 1)
{
checks++;
count = 0;
timeon = epoch;
USART_activa_tx();
printf("cms:%ld\r\n", (checks * cmxcheck));
USART_activa_rx();
}
cms = checks * cmxcheck;
meters = cms / 100;
count = 0;
}else{
count = 1;
}
if(meters == mdif)
{
distance[winche] = newdistance;
stop();
USART_activa_tx();
printf("OK\r\n");
USART_activa_rx();
}
if(checks == oldchecks && readsensor == 1 && (epoch - timeon) > 3)
{
stop();
distance[winche] = meters;
USART_activa_tx();
printf("STOP\r\n");
USART_activa_rx();
}
oldchecks = checks;
}
//lleva el winche a la posicion cero
void reset()
{
if(winche == 0)
{
output_bit(PIN_B6, 1);
output_bit(PIN_B4, 1);
}
if(winche == 1)
{
output_bit(PIN_B2, 1);
output_bit(PIN_B0, 1);
}
newdistance = 0;
readsensor = 1;
mdif = distance[winche] + 5;
}
/********* Programa Principal *********/
void main(void)
{
//activo lectura entrada analógica
setup_port_A(ALL_ANALOG);
setup_adc(ADC_CLOCK_INTERNAL);
//activo todos los pines A como entradas
set_tris_a(0xFF);
//activo todos los pines B como salidas
set_tris_b(0b00000000);
//activo PIN_C7 como entrada
set_tris_c(0b10000000);
//pines C0 a C5 apagados, C6 y C7 no se tocan
output_B(0b00000000);
//output_bit(PIN_C0, 0);
output_bit(PIN_C1, 0);
output_bit(PIN_C2, 0);
output_bit(PIN_C3, 0);
output_bit(PIN_C4, 0);
output_bit(PIN_C5, 0);
//configuración reloj interno del pic
setup_oscillator(OSC_4MHZ);
setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1);
setup_timer_1(T1_INTERNAL|T1_DIV_BY_4);
setup_timer_2(T2_DISABLED,0,1);
setup_comparator(NC_NC_NC_NC);
setup_vref(FALSE);
port_b_pullups(False);
USART_activa_rx();
//activo interrupciones
enable_interrupts(GLOBAL);
enable_interrupts(INT_RDA);
enable_interrupts(INT_TIMER1);
set_timer1(3036);
//grabo id del pic. En este caso se compila usando el 3, pero se cambia por otro numero y se vuelve a compilar para otra tarjeta
picsaved = 3;
//distancias en cero
distance[0] = 0;
distance[1] = 0;
while(TRUE)
{
//llamo a autoapagado cada 1 segundo
if(newsecond)
{
epoch++;
if(!readsensor) auto_off();
newsecond = 0;
}
//chequeo de distancia recorrida
if(readsensor && distance[winche] != newdistance)
check_distance();
//si hay un nuevo comando lo analizo y ejecuto
if(newcommand)
{
newcommand = 0;
strcpy(term, "|");
//strcpy(picid, strtok(command, term));
pic = atoi(strtok(command, term));
strcpy(action, strtok(0, term));
strcpy(values, strtok(0, term));
if(pic == picsaved)
{
strcpy(permited, "OPEN");
if(is_equal(permited, action))
{
open();
USART_activa_tx();
printf("OK\r\n");
USART_activa_rx();
}
strcpy(permited, "RESET");
if(is_equal(permited, action))
{
winche = atoi(values);
set_adc_channel(winche);
reset();
USART_activa_tx();
printf("OK\r\n");
USART_activa_rx();
}
strcpy(permited, "SET");
if(is_equal(permited, action))
{
strcpy(term, "$");
winche = atoi(strtok(values, term));
distance[winche] = atoi(strtok(0, term));
USART_activa_tx();
printf("OK\r\n");
USART_activa_rx();
}
strcpy(permited, "SHOW");
if(is_equal(permited, action))
{
USART_activa_tx();
printf("D0:%d-D1:%d\r\n", distance[0], distance[1]);
USART_activa_rx();
}
strcpy(permited, "MOVE");
if(is_equal(permited, action))
{
stop();
strcpy(term, "$");
winche = atoi(strtok(values, term));
set_adc_channel(winche);
newdistance = atoi(strtok(0, term));
mdif = newdistance - distance[winche];
dir = 0;
if(newdistance > distance[winche]) mdif = newdistance - distance[winche];
if(newdistance < distance[winche]){
mdif = distance[winche] - newdistance;
dir = 1;
}
timeon = epoch;
if(newdistance != distance[winche]){
move();
}else{
USART_activa_tx();
printf("OK\r\n");
USART_activa_rx();
}
}
strcpy(permited, "CLOSE");
if(is_equal(permited, action))
{
readsensor = 0;
close();
USART_activa_tx();
printf("OK\r\n");
USART_activa_rx();
}
strcpy(permited, "STOP");
if(is_equal(permited, action))
{
stop();
USART_activa_tx();
printf("OK\r\n");
USART_activa_rx();
}
}
}
}
}
El problema es que cuando envío un comando desde el PC a una tarjeta, esta no responde al primer intento, si vuelvo a enviar el comando este se ejecuta correctamente. Pasa lo mismo al enviar el comando a cualquier otra tarjeta, siempre el primer comando no es ejecutado, los siguientes comandos si se ejecutan correctamente.