Autor Tema: Cómo usar pines como entrada y salida a la vez  (Leído 3266 veces)

0 Usuarios y 1 Visitante están viendo este tema.

Desconectado Protheus5

  • PIC10
  • *
  • Mensajes: 37
Cómo usar pines como entrada y salida a la vez
« en: 09 de Marzo de 2005, 06:26:00 »
Hola gente, de nuevo me surge una duda a la hora de programar mi 18F452.

La cuestión es la siguiente;
voy a hacer un bus de datos bidireccional de 8 bits con el puerto B del PIC,para poder comunicarme con un contador LS7166 que me indicará una lectura de unos encoders.

Bien,para inicializar el contador debo mandarle unos datos por el puerto B (es decir, actuaría como puerto de salida), además mandar los 4 bits menos significativos del puerto D, para poder escribir en el contador palabras de inicialización.

Pero en un determinado momento, debo leer el valor del contador, y para ello ahora los 8 bits del puerto B actuarán como entradas, y cargaré su valor en una varible cualquiera.

La pregunta es cómo debo definir este puerto de entrada-salida. No se si tengo que escribir set_tirs_b cada vez que quiera cambiarlo de un modo a otro, o hay otras opciones posibles.

Por si os sirve de ayuda, os pongo el cogido.
Un saludo a todos.

*******

#include <18F452.h>

#use delay(clock=8000000)
#fuses NOWDT,HS, NOPROTECT, NOOSCSEN, NOBROWNOUT, NOPUT,  NOLVP, NOWRT, NOWRTD, NOWRTB, NOWRTC, NOCPD, NOCPB, NOEBTR, NOEBTRB
#use rs232(baud=9600,parity=N,xmit=PIN_C6,rcv=PIN_C7,bits=8)

#byte puertob = 0xF81
#byte puertod = 0xF83
#use fast_io(B)
#use fast_io(D)

//#bit cs = puertod.0 //salidas del puerto d
//#bit cd = puertod.1
//#bit rd = puertod.2
//#bit wr = puertod.3

#define MASTER_RESET     0x20      /* 00100000 palabras de control del 7166 */
#define INPUT_SETUP      0x68      /* 01101000 */
#define CUAD_NO          0xC0      /* 11000000 */
#define CUAD_X1          0xC1      /* 11000001 */
#define CUAD_X2          0xC2      /* 11000010 */
#define CUAD_X4          0xC3      /* 11000011 */
#define ADDR_RESET       0x01      /* 00000001 */
#define LATCH_CONT       0x02      /* 00000010 */
#define RESET_CONT       0x04      /* 00000100 */

#define PRESET_CONT      0x08      /* 00001000 */
#define BINAR_CONT       0x80      /* 10000000 */


void init (void) //funcion que inicializa el contador
{
set_tris_b(0x00); //pueto b como salida. escribo en el bus
puertod=0x06;//00000110 permito la escritura
puertob=MASTER_RESET;  //PORTB=0x20
delay_us(200);

puertod=0x06;
puertob=INPUT_SETUP;
delay_us(200);

puertod=0x06;
puertob=CUAD_X4;
delay_us(200);

puertod=0x06;
puertob=RESET_CONT;
delay_us(200);

}


void latch (void) //latcheo:paso del registro CNT al OL para poder leer
{
puertod=0x06;
puertob=LATCH_CONT;
delay_us(200);
}


void main()
{
puertob = 0x00;
set_tris_d(0x00); //el puertod es siempre salida no hay problemas
puertod=0x0F; //00001111 inicializ

delay_us(200);

init();
latch();
while (1){

puertod=0x06;
puertob=ADDR_RESET;

delay_us(300);

   set_tris_b(0xFF); //ahora puerto b es como entrada.
   printf("encoder=%i
",input_b()); //leo el valor del contador

   set_tris_b(0x00); // puerto b ahora como salida

   puertod=0x06;
   puertob(RESET_CONT);
   delay_us(300);
}


}

Desconectado Nocturno

  • Administrador
  • DsPIC33
  • *******
  • Mensajes: 18310
    • MicroPIC
RE: Cómo usar pines como entrada y salida a la vez
« Respuesta #1 en: 09 de Marzo de 2005, 10:20:00 »
Si quitas la sentencia #use fast_io el compilador se encargará de poner los TRIS adecuados antes de cada instrucción, si él considera que hay que cambiar de entrada a salida o viceversa.
Si no quieres dejar que el compilador lo haga, tendrás que hacerlo tú, porque no hay forma de dejar un pin como entrada-salida permanentemente.

Desconectado Protheus5

  • PIC10
  • *
  • Mensajes: 37
RE: Cómo usar pines como entrada y salida a la vez
« Respuesta #2 en: 09 de Marzo de 2005, 12:33:00 »
Gracias Nocturno.

Quitare el fast_io al puerto b, que es el bidireccional, y se lo dejo al d, que es solo de salida.

Ya que estamos, una pregunta simple, pero que a mi no me funciona:

Las órdenes que le doy al contador a través del bus de datos, tengo que dárselas cuando me llegue un mensaje cualquiera vía serie de otra máquina.

Para ello había pensado en una rutina de atención a la interrupcion serie, de tal manera que activo un flag cuando me llegan datos, y entonces así procedo a enviar.

Te paso el código resumido, porque no se que es lo que tengo mal pero no consigo que vaya bien:



#include <18f452.h>
#include<STDDEF.h>
#device adc=10
#use delay(clock=8000000)
#fuses NOWDT,HS, NOPROTECT, NOOSCSEN, NOBROWNOUT, NOPUT,  NOLVP, NOWRT, NOWRTD, NOWRTB, NOWRTC, NOCPD, NOCPB, NOEBTR, NOEBTRB
#use rs232(baud=19200,xmit=PIN_C6,rcv=PIN_C7,parity=O,bits=8)


#define LBUF 26
unsigned char buffer[LBUF]; //buffer de datos para enviar
short int flag;

#int_rda
void int_serie()
{
flag=1; //activamos el flag
}

void enviar_buffer(unsigned char *datos)
{
int i;
for (i=0;i<LBUF;i++)
putc(datos);
}


void main()
{
flag=0;
enable_interrupts(int_rda); //int serie
enable_interrupts(global);

while(1){
buffer[0]=0xA5;
buffer[1]=0x00;
buffer[2]=0x00;
buffer[3]=0x00;
buffer[4]=0x00;
buffer[5]=0x00;
buffer[6]=0x00;
buffer[7]=0x00;
buffer[8]=0x00;
buffer[9]=0x00;
buffer[10]=0x00;
buffer[11]=0x00;
buffer[12]=0x00;
buffer[13]=0x00;
buffer[14]=0x00;
buffer[15]=0x00;
buffer[16]=0x00;
buffer[17]=0x00;
buffer[18]=0x00;
buffer[19]=0x00;
buffer[20]=0x00;
buffer[21]=0x00;
buffer[22]=0x00;
buffer[23]=0x00;
buffer[24]=0x00;

buffer[25]=0xA5; // es el checksum

if (flag==1)
{
enviar_buffer(buffer);
flag=0;
}


delay_us(200);
}

}

Os agradezco cualquier tipo de ayuda o comentario que hagais.

Un saludo

Desconectado Nocturno

  • Administrador
  • DsPIC33
  • *******
  • Mensajes: 18310
    • MicroPIC
RE: Cómo usar pines como entrada y salida a la vez
« Respuesta #3 en: 09 de Marzo de 2005, 15:49:00 »
Habría que probarlo y ahora mismo no puedo, pero a priori, lo que me ha resultado más chocante es que detectas que se ha recibido algo por el puerto serie, pero no lo lees, y por tanto no vacías el buffer serie. La segunda vez que te llegue es probable que no salte la interrupción o, lo que es peor, que se quede el pic colgado por saturación del buffer de recepción.

Desconectado Protheus5

  • PIC10
  • *
  • Mensajes: 37
RE: Cómo usar pines como entrada y salida a la vez
« Respuesta #4 en: 10 de Marzo de 2005, 03:30:00 »
Entiendo lo que expones Nocturno, pero resulta que es algo mas complicado de lo que yo pensaba en un primer momento.
Resulta que por el puerto serie me pueden llegar tramas de datos cuya longitud no es constante, sino que varia en funcion de unos parametros.

Es decir, me pueden llegar tramas de 3 bytes y otras de 9 bytes, pero yo no se cuando me llegan, por ello independientemente de que me llegue una u otra yo debo mandar como respuesta mi trama de 26 datos que he creado en el programa.

Otra manera que se me ocurrio ayer y que todavía no he probado es probar con la instruccion KBHIT, de modo que

if (kbhit)

contruyo trama...
envio trama..
meto un delay

aunque no se como funcionará-

Un saludo, gracias por la respuesta.

Desconectado gauchosuizo

  • Colaborador
  • PIC18
  • *****
  • Mensajes: 457
RE: Cómo usar pines como entrada y salida a la vez
« Respuesta #5 en: 11 de Marzo de 2005, 06:36:00 »
hola

yo utilizo el Modbus protocol y para la recepcion de los datos hago lo siguiente:
Codigo:

//Receive routine
#int_RDA
void RDA_isr(void)
{
   if (RCSTA & 0x02)
    {
       RCSTA &= ~0x10;
       RCSTA |=  0x10;
    }
   modbus.rxData[Recindex]=RCREG;
   Recindex++;
      set_timer3(Timer3_5); // Timer3 will be loaded
      bit_clear(*0xFA1,1);
     enable_interrupts(int_TIMER3);
     
}

Como yo tambien tengo tramas con diferentes largos, uso un timer, que despues de determinado tiempo que no lleguen nada, desactiva el interrupt para recibir datos y va al main para procesar los datos recibidos y mandar la respuesta.
Codigo:

#int_TIMER3 // 3.5 Character times
void TIMER3_isr(void)
{
   disable_interrupts(int_TIMER3);
   modbus.DataReceived=1;

}


Los datos recibidos se encuentran en modbus.rxData[Recindex]. Esto lo programe para un 18F252.

Aloha
Saludos desde Suiza, Pablo.


 

anything