TODOPIC

Microcontroladores PIC => Primeros pasos - Iniciación a los microcontroladores => Mensaje iniciado por: edu1989 en 30 de Noviembre de 2010, 08:15:06

Título: enviar datos de un sensor de temperatura y de un pot por el puerto serie RS232
Publicado por: edu1989 en 30 de Noviembre de 2010, 08:15:06
Hola amigos. Me dispongo a realizar un programita que tiene el objetivo de enviar datos de un sensor de temperatura( TC77) y un potenciometro por el puerto serie.
Quiero que el PIC este en un modo Sleep hasta que:

- Un cliente envie un comando o un caracter, y se envien los dos datos ( esquema Cliente- Servidor)
- Pase algo extraño con alguno de los dos valores. (p.ej: enviar la temperatura cuando baje de 18ºC o enviar el valor del potenciometro cuando supere una cierta barrera)

Tengo diversas dudas :

- He visto en el datasheet de toda mi placa( PICDEM FS USB Demo Board Users Guide 51526a) que para transmitir los datos del sensor tengo que usar el modulo SPI( Serial Peripheral Interface. En la pag 193 del datasheet sale como hay que configurarlo. Básicamente hay cuatro pines a tener en cuenta: Serial data out       ( RC7), Serial Data in(RB0), Serial Clock (RB1) y Slave select (RA5).
Para enviar los datos del potenciometro uso también el modulo SPI? ( no se si se puede considerar el potenciometro como periférico). Como leo y envió los datos del potenciometro?
Si la respuesta es que si, las funcionen para enviar, recibir etc... me imagino que tengo que sacarlas de la librería spi de Hi-tech picc18 verdad?

- Por otro lado, tengo que configurar el PIC en " Sleep Mode" hasta que suceda alguna interrupción?



De momento son las dudas que me surgen. Ya he leído la información del datasheet tanto del mudo EUSART como del modulo SPI.Ahora voy a hacer una primera versión del programa a ver que dudas mas me salen.

Muchas gracias a todos de antemano.

            
Título: Re: enviar datos de un sensor de temperatura y de un pot por el puerto serie RS232
Publicado por: AngelGris en 30 de Noviembre de 2010, 10:34:46
Hola amigos. Me dispongo a realizar un programita que tiene el objetivo de enviar datos de un sensor de temperatura( TC77) y un potenciometro por el puerto serie.
Quiero que el PIC este en un modo Sleep hasta que:

- Un cliente envie un comando o un caracter, y se envien los dos datos ( esquema Cliente- Servidor)
- Pase algo extraño con alguno de los dos valores. (p.ej: enviar la temperatura cuando baje de 18ºC o enviar el valor del potenciometro cuando supere una cierta barrera)

Tengo diversas dudas :

- He visto en el datasheet de toda mi placa( PICDEM FS USB Demo Board Users Guide 51526a) que para transmitir los datos del sensor tengo que usar el modulo SPI( Serial Peripheral Interface. En la pag 193 del datasheet sale como hay que configurarlo. Básicamente hay cuatro pines a tener en cuenta: Serial data out       ( RC7), Serial Data in(RB0), Serial Clock (RB1) y Slave select (RA5).
Para enviar los datos del potenciometro uso también el modulo SPI? ( no se si se puede considerar el potenciometro como periférico). Como leo y envió los datos del potenciometro?
Si la respuesta es que si, las funcionen para enviar, recibir etc... me imagino que tengo que sacarlas de la librería spi de Hi-tech picc18 verdad?

- Por otro lado, tengo que configurar el PIC en " Sleep Mode" hasta que suceda alguna interrupción?



De momento son las dudas que me surgen. Ya he leído la información del datasheet tanto del mudo EUSART como del modulo SPI.Ahora voy a hacer una primera versión del programa a ver que dudas mas me salen.

Muchas gracias a todos de antemano.

            

  Para leer el valor del potenciómetro tendrías que usar uno de los conversores A/D del PIC. O un conversor externo.

  No se me ocurre, o mejor dicho no he trabajado nunca con el modo sleep. Sí sé que de una manera sencilla podés dejar el PIC en sleep y que se "despierte" cuando le llega una interrupción por puerto serie (que sería el pedido de información por parte del cliente).
  Pero creo que para saber si la temperatura vario de cierto valor o el pote supero x valor vas a tener que tomar lecturas constantemente y luego evaluar.

 
Título: Re: enviar datos de un sensor de temperatura y de un pot por el puerto serie RS2
Publicado por: edu1989 en 30 de Noviembre de 2010, 15:24:01
Tienes razon, tendre que estar monitorizando todo el rato los valores.
Por otro lado creo que lo primero que tengo que hacer es:

- Hacer una función para leer los datos del sensor y otra para que lo escriba en el puerto serie ---> Esto a partir de las funciones de la librería SPI de Hi-tech PICC18?

- Por otro lado una función para leer el valor del potenciometro y otra para que lo escriba en el puerto serie.  En este caso puedo usar el modulo SPI o lo hago con el EUSART?

Tanto del pot como del sensor, imagino que los datos vendrán en hexadecimal o ASCII... ( cuando los lea). Me pregunto si tendré que hacer alguna función para convertir los datos a decimal, creo que si...

Si alguien tiene algún ejemplo que use el modulo SPI le agradecería que me dejara el link. Voy a buscar alguno.. Muchas gracias!
Título: Re: enviar datos de un sensor de temperatura y de un pot por el puerto serie RS2
Publicado por: AngelGris en 30 de Noviembre de 2010, 17:57:29
Tienes razon, tendre que estar monitorizando todo el rato los valores.
Por otro lado creo que lo primero que tengo que hacer es:

- Hacer una función para leer los datos del sensor y otra para que lo escriba en el puerto serie ---> Esto a partir de las funciones de la librería SPI de Hi-tech PICC18?


  La lectura SPI sí a travez de funciones para SPI. Busca en www.microchipc.com
  Pero para que lo escriba en el puerto serie, son las que estabas usando en tu primer post. Para distinguir entre ambas cosas te conviene llamar UART o RS232 al que se pueda comunicar con una PC. Si es que es éso lo que querés hacer.

- Por otro lado una función para leer el valor del potenciometro y otra para que lo escriba en el puerto serie.  En este caso puedo usar el modulo SPI o lo hago con el EUSART?

  El pote lo tenés que leer mediante el conversor A/D. Y para escribirlo al UART sería igual que en el caso anterior.

Te hacés una función "putch (unsigned char)" que envie datos al puerto UART y la usas tanto para los datos del pote como para los datos del sensor.

Tanto del pot como del sensor, imagino que los datos vendrán en hexadecimal o ASCII... ( cuando los lea). Me pregunto si tendré que hacer alguna función para convertir los datos a decimal, creo que si...

Si alguien tiene algún ejemplo que use el modulo SPI le agradecería que me dejara el link. Voy a buscar alguno.. Muchas gracias!

  El valor del pote es hexa o binario o decimal... es en realidad un valor de 0 a 1023 (si es que el A/D es de 10 bits) que se almacena en una variable. Vos te tendrías que encargar de separarlo en dos bytes para poder mandarlo al UART.
  Con respecto al formato del sensor, hay que leer el datasheet del sensor.

  En www.microchipc.com vas a encontrar rutinas de SPI
Título: Re: enviar datos de un sensor de temperatura y de un pot por el puerto serie RS232
Publicado por: edu1989 en 01 de Diciembre de 2010, 13:41:46
Muchas gracias AngelCris, como siempre rapido y eficaz. He empezado con el programita. Lo pongo aquí para que podais hechar un vistazo.

Código: [Seleccionar]
#include <htc.h>

/* =================================================================================
Definitions
    ================================================================================= */
#define PORTBIT(adr, bit) ( (unsigned)(&adr)*8 + (bit) )

#define Idle_Low 1 // No envia datos
#define Idle_High 2 // Envia datos

#define true 1
#define false 0

#define BAUD  9600 // Configuramos la velocidad, tanto puede ser 19200 o de 9600 kbaud/s pero hay q cambiarlo tb en la simulacion de proteus
#define PIC_CLK 20000000 // Clock de 20MHz   

/* =================================================================================
Function prototypes
    ================================================================================= */
static void interrupt service_routine (void); // This is the interrupt service routine

void init_system (void);
void time_delay (unsigned int );
char output_logic(void);
char future_state_logic(void);

char leer_potenciometro(void);
char leer_sensor(void);

void serial_setup(void);
void UsartWriteText(const unsigned char *txt);
void UsartWriteChar(unsigned char ch);
unsigned char getch(void);
unsigned char UsartReadChar_nonstop(void);
unsigned char getch_available(void);
void clear_usart_errors(void);


/* =================================================================================
Global variables 
  ================================================================================= */
static bit potenciometro @ PORTBIT(PORTA, 0); // Declaración del potenciometro
static bit sensor_temperatura @ PORTBIT(PORTB, 0);
//static bit sensor_datos_salida @ PORTBIT(PORTC, 7);  // SD0 disabled in master mode (configuración como entrada)
static bit LED @ PORTBIT(PORTB, 1);


static char present_state = Idle_Low; // state variable
static char future_state = Idle_Low; // state variable

static unsigned char valor_potenciometro;
static unsigned char valor_sensor_temperatura;
static unsigned char caracter_recibido;

unsigned char dummy;

/* =================================================================================
Main function
  ================================================================================= */
void main(void){

init_system ();
valor_potenciometro=0;
valor_sensor_temperatura=0;

LED = 0;

while(1) {

valor_potenciometro=leer_potenciometro();
valor_sensor_temperatura=leer_sensor();
// Siempre voy leyendo los valores del potenciometro y del sensor. Las funciones tienen que retornar el valor en ºC y en Ohms.


output_logic();
future_state_logic();
}

}

/* =================================================================================
Function definitions
  ================================================================================= */

//*****************************************************************************
//Future_state_logic routine
//*****************************************************************************
char future_state_logic(void){

char error = 0;

switch (present_state) {
case Idle_Low:
if ((valor_sensor_temperatura<20)||(valor_potenciometro<25)){ // Menor de 20ºC o la resistencia menos a 25Kohms
future_state = Idle_High;
}
else if (getch_available()==true) // Si hay un caracter disponible recibido por el puerto serie.
{
caracter_recibido=getch();
if(caracter_recibido=='a')
{
future_state = Idle_High;
LED=1;
error=0;
}
else{
future_state=Idle_Low;
LED=0;
error=1;
}
}

break;

case Idle_High:
if (TXIF==0){ // Buffer de transmision vacio
future_state = Idle_Low;
}
else{
error=1;
}
break;


default:
error = 1;
}
return (error);
}

//*****************************************************************************
//Output logic routine
//*****************************************************************************
char output_logic(void){
unsigned char error = 1;


switch (present_state) {

case Idle_Low:
LED = 0;
error = 0;
break;

case Idle_High:
if((valor_sensor_temperatura<20)||(valor_potenciometro<25))
{
UsartWriteText(&valor_potenciometro);
UsartWriteText(&valor_sensor_temperatura);
LED=1;
error=0;
}
else if (getch_available()==true) // Si hay un caracter disponible recibido por el puerto serie.
{
caracter_recibido=getch();
if(caracter_recibido=='a')
{
UsartWriteText(&valor_potenciometro);
UsartWriteText(&valor_sensor_temperatura);
LED=1;
error=0;
}
else
LED=0;
error=1;
}
else
error=1;
LED=0;

break;


default:
error = 1;
LED=0;
break;
}

return (error);
}

//*****************************************************************************
//Init operations 
//*****************************************************************************
void init_system (void){

// Configurar el LED.
ADCON1=0x0F; // Todos los bits como digitales
TRISB=1; // Todos los pones se comportaran como salidas menos RB0 2^0=1

ADCON1 = 0x0F; // Todos los bits como digitales
TRISA=32; // SS( Select Slave) must have TRISA<5> bit set (configure as digital in ADCON1)


// Confiurar el trisb 0 como digital.
//SDI must have TRISB<0> bit set (configure as digital in ADCON1).Configurat en master mode (bit 1 cleared, en mode slave bit 1 set)
TRISB=3; // bit 0 i 1 set.
TRISC=128; // Tots els bits a 1 menys la sortida 7 (SDO)


}

//***************************************************************************
//Interrupt Service Routine (only for the generation of the FSM's CLK sisgnal
//                           using Timer0)
//***************************************************************************


static void interrupt service_routine (void){ //Interrupt is the key word here
}


//*****************************************************************************
//Time delay routine.   
//*****************************************************************************
void time_delay(unsigned int delay){

unsigned int i;
for(i = 0; i <= delay ;i++){
NOP();
}
}

//*****************************************************************************
// SERIAL SETUP 
//*****************************************************************************
void serial_setup(void){
#define SPBRG_VALUE ((PIC_CLK/(16UL*BAUD)) -1)


BRGH = 1;
BRG16 = 0;
SPBRG = SPBRG_VALUE;

SPEN=1; // Enable serial port
SYNC=0; // Asincrono

TXIE=0; // Desactivar interrupciones en tx
TXEN=1; // Enable the transmitter
TX9=0; // 8 bits transmission

RCIE=1; // Activar interrupciones en rx
RX9=0; // 8 bits reception
CREN=1; //Enable reception

/* Using interruptions...*/
GIE=1;
PEIE=1;



#define clear_usart_errors_inline \
if (OERR)
{
TXEN=0; \
TXEN=1; \
CREN=0; \
CREN=1; \
}
if (FERR) \
{
dummy=RCREG; \
TXEN=0; \
TXEN=1; \
}

}


//*****************************************************************************
// Enviar datos ( un caracter)
//*****************************************************************************

void UsartWriteChar(unsigned char ch) {
   
while(TXIF!=0) // 0 = The EUSART transmit buffer is full
      continue;
TXREG = ch;

}
//*****************************************************************************
// Enviar datos (un buffer)
//*****************************************************************************
void UsartWriteText(const unsigned char *txt){

unsigned char i = 0;
while(txt[i]!='\0') {
UsartWriteChar(txt[i]);
i++;
}

}


//*****************************************************************************
//Leer datos ( un caracter)
//*****************************************************************************

unsigned char getch(void)
{
while(RCIF!=1){ //1 = The EUSART receive buffer, RCREG, is full
CLRWDT();
clear_usart_errors_inline;
}
return RCREG;
}

//*****************************************************************************
//Leer datos (un buffer)
//*****************************************************************************
unsigned char UsartReadChar_nonstop(void) {

if(!PIR1bits.RCIF) // TRMT1 is set when TSR is empty
      return 0;   

    return RCREG;
}


//*****************************************************************************
//Comprueba si aun faltan datos o no
//*****************************************************************************
unsigned char getch_available(void)
{
if(RCIF)
return true;
else
return false;
}


//*****************************************************************************
//Errores USART
//*****************************************************************************
void clear_usart_errors(void)
{
clear_usart_errors_inline;
}


//*****************************************************************************
//Leer entradas.
//*****************************************************************************

//*****************************************************************************
//Leer bytes recibidos del bus del modulo SPI
//*****************************************************************************

char leer_sensor(void)   
{
char Byte[8];
SSPSTAT = 0b00000000;
SSPCON1 = 0b00100000;

Byte = SSPBUF;  // Guardo los datos que tengo en el buffer (despues limpiare el buffer)

return Byte
}

//*****************************************************************************
//Leer estado potenciometro
//*****************************************************************************
char leer_potenciometro (void)
{


}
[code]

He estado buscando que tamaño ocupa la temperatura y no consigo encontrarlo. He supuesto 1byte ya que no creo que hagan falta mas de 256 valores...
Por otro lado, no se muy bien como leer el potenciometro. En la libreria adc que incorpora PICC18 he visto la siguiente definicion:

/* Read ADC data
 */
#define ReadADC() ((((unsigned int)ADRESH)<<8)|(ADRESL))
#endif

pero no se muy bien como utilizarla... puedo llamarla y ya sabe que tiene que darme el valor del potenciometro?

Muchas gracias de antemano.





[/code]
Título: Re: enviar datos de un sensor de temperatura y de un pot por el puerto serie RS232
Publicado por: AngelGris en 01 de Diciembre de 2010, 18:31:48
  Unas  cositas,

  Estás habilitando las interrupciones y en la rutina de interrupción no hacés nada (salvo que todavía te falte el código, no se) y si no hacés nada en la rutina de la interrupción no te conviene habilitarlas.

  Con respecto a la rutina de ADC, ese define lo que hace es simplemente mover el valor capturado por el AD a la variable que le indiques "x = ReadADC()". Pero el ADC hay que configurarlo, seleccionar el canal, iniciar la conversión....

  Y para leer el sensor, más allá que utilices el protocolo SPI, hay que ver como es que te tenés que comunicar con el dispositivo. No se, puede ser que primero le tengas que enviar el byte 00h u otras cosas y recién después obtener el valor... Eso lo tiene que decir el datasheet del sensor.
Título: Re: enviar datos de un sensor de temperatura y de un pot por el puerto serie RS232
Publicado por: edu1989 en 02 de Diciembre de 2010, 14:52:31
Gracias! Esta tarde he estado dandole vueltas a la rutina del pot, de momento solo cuelgo el codigo de lo que he hecho ya que tengo que mirar bien lo del sensor.

Código: [Seleccionar]
void ad_conversor_setup(void)
{

/*1. Configure the A/D module: Configure analog pins, voltage reference and digital I/O (ADCON1)*/

ADCON1=15; // PCFG3=1,PCFG2=1,PCFG1=1,PCFG0=1. Todas las entradas digitales


/* Select A/D input channel (ADCON0) */

CHS3=0;
CHS2=0; // Seleccionamos el canal 0 (AN0) que es donde esta conectado el potenciometro
CHS1=0;
CHS0=0;


/*Select A/D acquisition time select bits (ADCON2)*/
ACQT2=;
ACQT1=;
ACQT0=;

/* Select A/D conversion clock (ADCON2)*/

ADCS2=1;
ADCS1=0;       // Clock= Fosc/4 ( Igual que el timer)
ADCS0=0;

/*Turn on A/D module (ADCON0)*/
ADON=1; // A/D converter module is enabled

/* Configure A/D interrupt*/
ADIF=0;
ADIE=1;
GIE=1;

/*Wait the required acquisition time (if required).*/

/*Start conversion*/
GO/DONE=1; // A/D conversion in progress

/*Wait for A/D conversion to complete:Waiting for the A/D interrupt*/
/*Read A/D Result registers (ADRESH:ADRESL);
clear bit ADIF, if required*/

if( ADIF==1){ //An A/D conversion completed (must be cleared in software)
palabra_low= ADRESL;
palabra_high=ADRESH;
ADIF=0;
}  


/*For next conversion, go to step 1 or step 2, as
required. The A/D conversion time per bit is
defined as TAD. A minimum wait of 3 TAD is
required before the next acquisition starts*/

}

Las principales dudas que tengo son respecto a como configurar el tiempo de adquisicion y el tiempo de conversion. No se con que criterio escogerlo, de momento he puesto alguno que me ha parecido razonable. Por otro lado, la asignacion que hago:
palabra_low=ADRESL y palabra_high=ADRESH? como los declararia, como int, los dos? O por contra no hace falta que haga esta asignacion si voy a utilitzar la funcion readadc()?


Muchas gracias AngelCris! voy a seguir pues! Un saludo a todos.

Edito: Como veis en el tiempo de adquisicion no he puesto nada, aunque lo he dejado ya preparado.
Título: Re: enviar datos de un sensor de temperatura y de un pot por el puerto serie RS232
Publicado por: AngelGris en 02 de Diciembre de 2010, 16:27:30
  En este caso en particular (que querés usar el AN0 para el pote) tendrías que configurar el AD para que dicho pin funcione como analógico. Que según la tabla en la página 260 deberías poner PCFG3...PDFG0 en 1110.

  El tiempo tiene que cumplir con los requisitos mínimos especificados en el datasheet. En las páginas 264 y 265 muestra como calcularlo.

  Si vas a utilizar la función ReadADC(); sólo es necesario utilizar una variable y como el valor capturado por el ADC es de 10 bits y positivos, tu variable tendría que ser unsigned int.
Título: Re: enviar datos de un sensor de temperatura y de un pot por el puerto serie RS232
Publicado por: edu1989 en 03 de Diciembre de 2010, 06:42:43
Holaa de nuevo,muchas gracias por contestar tan rapido!. Ya he arreglado lo que me has dicho menos lo del tiempo que lo estoy mirando. Antes de todo en el proteus, el potenciometro tiene que ir conectado por una de las patas de los lados a un condensador ( de descarga) no? y desde la pata del centro del pot al pin AN0.

Antes de todo pongo una tabla donde pongo que sera cada cosa para que resulte mas claro:

Tacq= Tiempo adquisicion
Tamp= Amplifier Settling time
Tc=Holding Capacitor Charging Time
Tcoff= Temperature coefficient

Visto esto, vamos a ver la formula:


TACQ = TAMP + TC + TCOFF

Donde:
TAMP = 0.2 μs -----> Siempre es este valor? me imagino que si porque tampoco hay manera de saberlo y debe ser fijo.

TCOFF = (Temp – 25°C)(0.02 μs/°C) -----> en el datasheet lo calcula para una temperatura de 85º. Tengo que ponerme en el peor caso o con menos temperatura ya estara bien?

TC = -(CHOLD)(RIC + RSS + RS) ln(1/2048) μs ---> CHold me imagino que es el valor del condensador pero las tres resistencias no se donde habria que ponerlas...

A partir de estos calculalos podria calcular el tiempo de adquisicion que es el valor que va en los bits ACQT2,ACQT1,ACQT0 pero el clock (bits ADCS2,ADCS1,ADCS0 como lo escojo? No veo ninguna relacion entre el tiempo de clock y el tiempo de adquisicion.. me imagino que los dos tienen que ser parecidos para no notar la diferencia pero nada mas...

Muchas gracias por la ayuda de antemano. Saludos!

Edito: Pongo el codigo de lo nuevo que he hecho, ya he hecho la funcion para leer tanto el pot como la del sensor:

Código: [Seleccionar]
#include <htc.h>
#include "spi.h"
#include "adc.h"

/* =================================================================================
Definitions
    ================================================================================= */
#define PORTBIT(adr, bit) ( (unsigned)(&adr)*8 + (bit) )

#define Idle_Low 1 // No envia datos
#define Idle_High 2 // Envia datos

#define true 1
#define false 0

#define BAUD  9600 // Configuramos la velocidad, tanto puede ser 19200 o de 9600 kbaud/s pero hay q cambiarlo tb en la simulacion de proteus
#define PIC_CLK 4000000 // Clock de 4MHz (Cristal)

/* =================================================================================
Function prototypes
    ================================================================================= */
static void interrupt service_routine (void); // This is the interrupt service routine

void init_system (void);
void time_delay (unsigned int );
char output_logic(void);
char future_state_logic(void);

void sensor_setup(void);
void ad_conversor_setup(void);
void serial_setup(void);

void UsartWriteText(const unsigned char *txt);
void UsartWriteChar(unsigned char ch);
unsigned char getch(void);
unsigned char UsartReadChar_nonstop(void);
unsigned char getch_available(void);
void clear_usart_errors(void);


/* =================================================================================
Global variables 
  ================================================================================= */
static bit potenciometro @ PORTBIT(PORTA, 0); // Declaración del potenciometro
static bit sensor_temperatura @ PORTBIT(PORTB, 0);
//static bit sensor_datos_salida @ PORTBIT(PORTC, 7);  // SD0 disabled in master mode (configuración como entrada)
static bit LED @ PORTBIT(PORTB, 1);


static char present_state = Idle_Low; // state variable
static char future_state = Idle_Low; // state variable

static unsigned int valor_potenciometro;
static unsigned int valor_sensor_temperatura;

static unsigned char caracter_recibido;

unsigned char dummy;
static unsigned int palabra_low;
static unsigned int palabra_high;

/* =================================================================================
Main function
  ================================================================================= */
void main(void){

init_system ();

valor_potenciometro=0;
valor_sensor_temperatura=0;
LED = 0;

while(1) {

sensor_setup();
ad_conversor_setup();

valor_potenciometro=ReadADC();   // Libreria adc.h de PICC18
valor_sensor_temperatura=ReadSPI1();  //Libreria spi.h de PICC18

output_logic();
future_state_logic();
}

}

/* =================================================================================
Function definitions
  ================================================================================= */

//*****************************************************************************
//Future_state_logic routine
//*****************************************************************************
char future_state_logic(void){

char error = 0;

switch (present_state) {
case Idle_Low:
if ((valor_sensor_temperatura<20)||(valor_potenciometro<25)){ // Menor de 20ºC o la resistencia menos a 25Kohms
future_state = Idle_High;
}
else if (getch_available()==true) // Si hay un caracter disponible recibido por el puerto serie.
{
caracter_recibido=getch();
if(caracter_recibido=='a')
{
future_state = Idle_High;
LED=1;
error=0;
}
else{
future_state=Idle_Low;
LED=0;
error=1;
}
}

break;

case Idle_High:
if (TXIF==0){ // Buffer de transmision vacio
future_state = Idle_Low;
}
else{
error=1;
}
break;


default:
error = 1;
}
return (error);
}

//*****************************************************************************
//Output logic routine
//*****************************************************************************
char output_logic(void){
unsigned char error = 1;


switch (present_state) {

case Idle_Low:
LED = 0;
error = 0;
break;

case Idle_High:
if((valor_sensor_temperatura<20)||(valor_potenciometro<25))
{
UsartWriteText(&valor_potenciometro);
UsartWriteText(&valor_sensor_temperatura);
LED=1;
error=0;
}
else if (getch_available()==true) // Si hay un caracter disponible recibido por el puerto serie.
{
caracter_recibido=getch();
if(caracter_recibido=='a')
{
UsartWriteText(&valor_potenciometro);
UsartWriteText(&valor_sensor_temperatura);
LED=1;
error=0;
}
else
LED=0;
error=1;
}
else
error=1;
LED=0;

break;


default:
error = 1;
LED=0;
break;
}

return (error);
}

//*****************************************************************************
//Init operations 
//*****************************************************************************
void init_system (void)
{

TRISB=1; //LED. Todos los pines se comportaran como salidas menos RB0 2^0=1
TRISA=32; // SS( Select Slave) must have TRISA<5> bit set
TRISB=1; // SDI. El bit 0 a 1.Configurado en master mode (bit 1 cleared, en mode slave bit 1 set)
TRISC=128; // SDO. Tots els bits a 1 menys la sortida 7

}


//*****************************************************************************
//Time delay routine.   
//*****************************************************************************
void time_delay(unsigned int delay){

unsigned int i;
for(i = 0; i <= delay ;i++){
NOP();
}
}

//*****************************************************************************
// SERIAL SETUP 
//*****************************************************************************
void serial_setup(void){
#define SPBRG_VALUE ((PIC_CLK/(16UL*BAUD)) -1)


BRGH = 1;
BRG16 = 0;
SPBRG = SPBRG_VALUE;

SPEN=1; // Enable serial port
SYNC=0; // Asincrono

TXIE=0; // Desactivar interrupciones en tx
TXEN=1; // Enable the transmitter
TX9=0; // 8 bits transmission

RCIE=1; // Activar interrupciones en rx
RX9=0; // 8 bits reception
CREN=1; //Enable reception


/* Using interruptions...*/
/*
GIE=1;
PEIE=1;
*/


#define clear_usart_errors_inline \
if (OERR)
{
TXEN=0; \
TXEN=1; \
CREN=0; \
CREN=1; \
}
if (FERR) \
{
dummy=RCREG; \
TXEN=0; \
TXEN=1; \
}

}


//*****************************************************************************
// Enviar datos ( un caracter)
//*****************************************************************************

void UsartWriteChar(unsigned char ch) {
   
while(TXIF!=0) // 0 = The EUSART transmit buffer is full
      continue;
TXREG = ch;

}
//*****************************************************************************
// Enviar datos (un buffer)
//*****************************************************************************
void UsartWriteText(const unsigned char *txt){

unsigned char i = 0;
while(txt[i]!='\0') {
UsartWriteChar(txt[i]);
i++;
}

}

//*****************************************************************************
//Leer datos ( un caracter)
//*****************************************************************************

unsigned char getch(void)
{
while(RCIF!=1){ //1 = The EUSART receive buffer, RCREG, is full
CLRWDT();
clear_usart_errors_inline;
}
return RCREG;
}

//*****************************************************************************
//Leer datos (un buffer)
//*****************************************************************************
unsigned char UsartReadChar_nonstop(void) {

if(!PIR1bits.RCIF) // TRMT1 is set when TSR is empty
      return 0;   

    return RCREG;
}


//*****************************************************************************
//Comprueba si aun faltan datos o no
//*****************************************************************************
unsigned char getch_available(void)
{
if(RCIF)
return true;
else
return false;
}


//*****************************************************************************
//Errores USART
//*****************************************************************************
void clear_usart_errors(void)
{
clear_usart_errors_inline;
}


//*****************************************************************************
//Leer entradas.
//*****************************************************************************

//*****************************************************************************
//Leer bytes recibidos del bus del modulo SPI
//*****************************************************************************

void sensor_setup(void)  // SPI Master mode:
{

static unsigned int Byte;

SSPEN=1;    //Enables serial port and configures SCK, SDO, SDI and SS as serial port pins
BF=0;        //Receive not complete, SSPBUF is empty

//SCK is the clock output (Master Mode)
//Clock Polarity(Idle state of SCK)

SMP=1;      //Input data sampled at end of data output time
CKE=0;      //Transmit occurs on transition from Idle to active clock state

SSPM3=0;
SSPM2=0; //SPI Master mode, clock = FOSC/4
SSPM1=0;
SSPM0=0;

CKP=0; //Idle state for clock is a low level

SSPIF=0;   
if((BF==1)&&(SSPIF==1)){ //Receive complete, SSPBUF is full && The transmission/reception is complete (must be cleared in software)
Byte = SSPBUF; // Guardo los datos que tengo en el buffer (despues limpiare el buffer)
BF=0;
}

SSPIF=0; ////Waiting to transmit/receive

//return Byte
}




void ad_conversor_setup(void)
{

ADCON1=14; // PCFG3=1,PCFG2=1,PCFG1=1,PCFG0=0. Todas las entradas digitales


CHS3=0;
CHS2=0; // Seleccionamos el canal 0 (AN0) que es donde esta conectado el potenciometro
CHS1=0;
CHS0=0;

//Tiempo de adquisicion
ACQT2=0;
ACQT1=0;  // 2Tad> Fosc (Considerando Tadq=2.45us)
ACQT0=1;



ADCS2=0;
ADCS1=0;       // Clock= Fosc/2 (El mas pequeño posible)
ADCS0=0;


ADON=1; // A/D converter module is enabled

/* Configure A/D interrupt*/
ADIF=0;
ADIE=1;
GIE=1;

/*Wait the required acquisition time (if required).*/


GO/DONE=1; // A/D conversion in progress

/*Wait for A/D conversion to complete:Waiting for the A/D interrupt*/
/*Read A/D Result registers (ADRESH:ADRESL);
clear bit ADIF, if required*/

if( ADIF==1){ //An A/D conversion completed (must be cleared in software)
palabra_low= ADRESL;
palabra_high=ADRESH;
ADIF=0;
}   


}
Título: Re: enviar datos de un sensor de temperatura y de un pot por el puerto serie RS232
Publicado por: AngelGris en 03 de Diciembre de 2010, 10:13:33
Holaa de nuevo,muchas gracias por contestar tan rapido!. Ya he arreglado lo que me has dicho menos lo del tiempo que lo estoy mirando. Antes de todo en el proteus, el potenciometro tiene que ir conectado por una de las patas de los lados a un condensador ( de descarga) no? y desde la pata del centro del pot al pin AN0.

Antes de todo pongo una tabla donde pongo que sera cada cosa para que resulte mas claro:

Tacq= Tiempo adquisicion
Tamp= Amplifier Settling time
Tc=Holding Capacitor Charging Time
Tcoff= Temperature coefficient

Visto esto, vamos a ver la formula:


TACQ = TAMP + TC + TCOFF

Donde:
TAMP = 0.2 μs -----> Siempre es este valor? me imagino que si porque tampoco hay manera de saberlo y debe ser fijo.

TCOFF = (Temp – 25°C)(0.02 μs/°C) -----> en el datasheet lo calcula para una temperatura de 85º. Tengo que ponerme en el peor caso o con menos temperatura ya estara bien?

TC = -(CHOLD)(RIC + RSS + RS) ln(1/2048) μs ---> CHold me imagino que es el valor del condensador pero las tres resistencias no se donde habria que ponerlas...

A partir de estos calculalos podria calcular el tiempo de adquisicion que es el valor que va en los bits ACQT2,ACQT1,ACQT0 pero el clock (bits ADCS2,ADCS1,ADCS0 como lo escojo? No veo ninguna relacion entre el tiempo de clock y el tiempo de adquisicion.. me imagino que los dos tienen que ser parecidos para no notar la diferencia pero nada mas...

Muchas gracias por la ayuda de antemano. Saludos!

Edito: Pongo el codigo de lo nuevo que he hecho, ya he hecho la funcion para leer tanto el pot como la del sensor:

..........


  El pote lo tenés que conectar así: un extremo a GND, el otro extremo VCC y el medio a la entrada analógica. Entre el pin del medio y el terminal del PIC iría RS.

  Tamp: es fijo.
  TCoff: yo lo pondría en el pero de los casos que te puedan pasar. Por ejemplo donde estoy yo, la temperatura nunca superó los 50º (y ya estoy exagerando).
 
   Las tres resistencias que mencionás son:
   RSS: la interna del "sampling switch" y en la figura 21-3 que está en la página 263 hay un diagrama en ejes cartesianos que muestra el valor de dicha resistencia dependiendo de la tensión de alimentación del PIC
   RIC: dice que es la de interconexión y es menor o igual a 1K
   RS: es la resistencia que vos pongas en seria a tu señal a medir y según el primer párrafo de la página 264 el máximo valor recomendado para esta resistencia es de 2.5K

  El tiempo este calculado es la espera entre que seleccionamos el canal y podemos comenzar la conversión. En el 16F87xA, uno tenía que hacer la espera manualmente, pero por lo que yo entiendo en el datasheet del 18Fxxx podemos configurar esta espera con los bits ACQT2...ACQT0 y entonces automáticamente el conversor espera el tiempo configurado.
  Fijate que en la página 261, muestra según el valor de dichos bits 0TAD, 2TAD, 4TAD.... En la página 265 habla de como seleccionar el clock para la conversión, ahí menciona que el tiempo de conversión por bit está definido como TAD y que necesita 11TAD de tiempo para poder hacer una conversión de 10 bits. Entonces hay que escoger un clock que asegure un TAD mínimo. Para ello hay que referirse a la tabla 28-29 y allí indica que el TAD mínimo es de 0.7us.
  Volviendo a la página 265, hay una tabla que muestra unos ejemplos de selección de clock. Y te muestra la frecuencia máxima a la cual podría operar el PIC con esa selección de clock.
  En tu programa tenés definido un cristal de 4MHz, entonces la selección de clock para el AD y que cumpla con el TAD mínimo sería 4TOSC.
   TOSC: es el tiempo de oscilación del cristal. Como tenés 4MHz dicho tiempo es 1/4MHz = 250ns
   Como el TAD mínimo es de 0.7us, al elegir un clock AD de 4TOSC te da un TAD de 1u así que te asegurás que cumplís con el TAD mínimo.

  Pasando a tu programa veo que tenés en el while() tanto el setup_spi como el setup AD. Eso no es necesario, de hecho te conviene configurarlo sólo una vez y después hacés las lecturas en el while.

  Me cansé de escribir  :) Me voy a tomar unos mates
Título: Re: enviar datos de un sensor de temperatura y de un pot por el puerto serie RS232
Publicado por: edu1989 en 03 de Diciembre de 2010, 11:18:09
Holaa de nuevo! Muchas gracias.
Primero de todo he calculado el Tad:
Tamp=0.2us
Tcoff(con temp 50ºC)= 0.5us
Tc (Chold=25pF, Rss(5V)=2Kohm, Ric=1kohm,Rs=2kohm) = 0.95us

Por tanto Tad= Tamp+Tcoff+Tc= 1.65us. Hasta aquí, todo correcto? Cumplo la condicion de que el Tad minimo es de 0.7us

Con Fosc=4Mhz. Como has dicho antes hay que definir un clock para el Tad. Por tanto puedo escoger 000 = 0 TAD(1)  (ACQT2:ACQT0) ya que es superior a los 0.7us no? si escojo eso el Tad es equivalente a un tiempo de instruccion 0.25us

Como clock de conversion.. (minimo 11Tad):
11Tad= 18.15us si escogiese 110 = FOSC/64 me saldria 16us y no llegaria a cumplir los 18.15us... no se si me explico...
Estoy haciendo algo mal?

P.d: Si puedes mirarte la parte del codigo del SPI, te lo agradeceria mucho! voy a seguir trabajando, muchas gracias por la ayuda. Que disfrutes esos mates!
Título: Re: enviar datos de un sensor de temperatura y de un pot por el puerto serie RS232
Publicado por: AngelGris en 03 de Diciembre de 2010, 12:47:54
Holaa de nuevo! Muchas gracias.
Primero de todo he calculado el Tad:
Tamp=0.2us
Tcoff(con temp 50ºC)= 0.5us
Tc (Chold=25pF, Rss(5V)=2Kohm, Ric=1kohm,Rs=2kohm) = 0.95us

Por tanto Tad= Tamp+Tcoff+Tc= 1.65us. Hasta aquí, todo correcto? Cumplo la condicion de que el Tad minimo es de 0.7us


  El tiempo así calculado no se llama TAD sino TACQ, fijate en la fórmula de la página 264, y es el tiempo de adquisición.
Fijate que los bits para configurar el tiempo de adquisición se llaman ACQT2...ACQT0.
Con dichos bits tenés que configurar un tiempo que sea >= al tiempo calculado por la fórmula anterior.

Con Fosc=4Mhz. Como has dicho antes hay que definir un clock para el Tad. Por tanto puedo escoger 000 = 0 TAD(1)  (ACQT2:ACQT0) ya que es superior a los 0.7us no? si escojo eso el Tad es equivalente a un tiempo de instruccion 0.25us

Como clock de conversion.. (minimo 11Tad):
11Tad= 18.15us si escogiese 110 = FOSC/64 me saldria 16us y no llegaria a cumplir los 18.15us... no se si me explico...
Estoy haciendo algo mal?

  Estás confundiendo el TAD con el TAQC.

  Vayamos de vuelta.... Comencemos con el cálculo del TAD:

  El TAD es el tiempo de conversión por bit (que según el datasheet tiene que ser >= 0.7 us). Este tiempo lo tenés que calcular en base a la frecuencia de oscilación que estés utilizando. Los bits que configuran este tiempo son ADCS2..ADCS0 del registro ADCON2.
  En la página 261 donde están las posibles combinaciones de estos bits dice:

  ADCS2...ADCS0  Estos bits dan la frecuencia de clock del AD; para calcular el TAD hacés 1/clock AD

  111 = FRC        (clock derivado de un oscilador RC interno)
  110 = Fosc/64   (esto es lo mismo que decir Tosc*64)
  101 = Fosc/16   (esto es lo mismo que decir Tosc*16)
  100 = Fosc/4     (esto es lo mismo que decir Tosc*4)
  011 = FRC         (clock derivado de un oscilador RC interno)
  010 = Fosc/32   (esto es lo mismo que decir Tosc*32)
  001 = Fosc/8     (esto es lo mismo que decir Tosc*8 )
  000 = Fosc/2     (esto es lo mismo que decir Tosc*2)

  Ejemplo si tu cristal es de 4MHz, Fosc = 4MHz --> Tosc = 1/4MHz --> Tosc = 250ns. 
 
  Estos bits serán los que te den el tiempo de TAD al cual va a trabajar tu AD (siempre teniendo en cuenta que sea >= 0.7us). Entonces el cálculo sería de la siguiente forma  TAD = x (siendo x una de las posibles combinaciones de los bits) * Tosc. Como sabemos que TAD tiene que ser >= 0.7us -->  x * Tosc >= 0.7us, en tu caso Tosc = 250ns así que  x * 250ns >= 0.7us. La combinación mínima que cumple con esta condición es 100 porque es  4 * 250ns --> 1us que es >= 0.7us.
  Así calculaste el TAD y el clock del AD.


  Ahora pasemos al cálculo del TAQC (que es el tiempo mínimo de adquisición):

  Este tiempo se calcula con la fórmula que ya sabés y es TAQC = Tamp+Tcoff+Tc, utilizando los valores que vos das como ejemplo...

Tamp=0.2us
Tcoff(con temp 50ºC)= 0.5us
Tc (Chold=25pF, Rss(5V)=2Kohm, Ric=1kohm,Rs=2kohm) = 0.95us

nos queda que TAQC = 0.2us + 0.5 us + 0.95 us --> TAQC = 1.65us

Entonces tiempo de adquisición calculado es TAQC = 1.65us

Para configurar este tiempo tenés los bits ACQT2...ACQT0 y sus posibles combinaciones son:

111       (20TAD)
110       (16TAD)
101       (12TAD)
100       (8TAD)
011       (6TAD)
010       (4TAD)
001       (2TAD)
000       (0TAD)

  Hay que escoger una combinación que de un valor superior al TAQC calculado, para asegurarnos que funcione bien el AD.

Entonces TAQC(configurado) >= TAQC(calculado); 
TAQC(configurado) = x (siendo x una de las posibles combinaciones) * TAD(calculado).  Recordemos que el TAD(calculado) nos dio 1us, entonces TAQC(configurado) = x * 1us. Uniendo fórmulas.... x * 1us >= 1.65us. La combinación mínima que cumple con esta condición es 001 (que justamente dice 2TAD) entonces nuestra fórmula quedaría

TAQC(configurado) 001 --> TAQC(configurado) = 2TAD --> TAQC(configurado) = 2 * 1us --> TAQC(configurado) = 2 us

Esto cumple la condición TAQC(configurado) >= TAQC(calculado) ya que TAQC(configurado) = 2us y TAQC(calculado) = 1.65us
Título: Re: enviar datos de un sensor de temperatura y de un pot por el puerto serie RS232
Publicado por: edu1989 en 03 de Diciembre de 2010, 13:13:43
Muchas gracias AngelCris! ahora me ha quedado clarisimo.Siento la confusion de la primera parte. Lo entendia bien pero me confundi en escribir.
Ahora mismo cuelgo el programita otra vez.

Edito para subir el codigo...
-He estado mirando eso de transmitir una palabra previamente al mensaje.. y no he visto nada de eso en el datasheet. He seguido un proceso que hay en el datasheet para hacer el sensor_setup.
- La ultima parte de la funcion adc_setup asigna el valor de ADRESH y ADRESL  a dos variables. Esta bien hecha la asignacion?
- Por otra parte creo que debo modificar las funciones que tengo hechas para enviar por el puerto serie ya que las tengo hechas para un char y voy a transmitir int, concretamente unsigned int no?


Código: [Seleccionar]
#include <htc.h>
#include "spi.h"
#include "adc.h"

/* =================================================================================
Definitions
    ================================================================================= */
#define PORTBIT(adr, bit) ( (unsigned)(&adr)*8 + (bit) )

#define Idle_Low 1 // No envia datos
#define Idle_High 2 // Envia datos

#define true 1
#define false 0

#define BAUD  9600 // Configuramos la velocidad, tanto puede ser 19200 o de 9600 kbaud/s pero hay q cambiarlo tb en la simulacion de proteus
#define PIC_CLK 4000000 // Clock de 4MHz (Cristal)

/* =================================================================================
Function prototypes
    ================================================================================= */
static void interrupt service_routine (void); // This is the interrupt service routine

void init_system (void);
void time_delay (unsigned int );
char output_logic(void);
char future_state_logic(void);

void sensor_setup(void);
void ad_conversor_setup(void);
void serial_setup(void);

void UsartWriteText(const unsigned char *txt);
void UsartWriteChar(unsigned char ch);
unsigned char getch(void);
unsigned char UsartReadChar_nonstop(void);
unsigned char getch_available(void);
void clear_usart_errors(void);


/* =================================================================================
Global variables 
  ================================================================================= */
static bit potenciometro @ PORTBIT(PORTA, 0); // Declaración del potenciometro
static bit sensor_temperatura @ PORTBIT(PORTB, 0);
//static bit sensor_datos_salida @ PORTBIT(PORTC, 7);  // SD0 disabled in master mode (configuración como entrada)
static bit LED @ PORTBIT(PORTB, 1);


static char present_state = Idle_Low; // state variable
static char future_state = Idle_Low; // state variable

static unsigned int valor_potenciometro;
static unsigned int valor_sensor_temperatura;

static unsigned char caracter_recibido;

unsigned char dummy;
static unsigned int palabra_low;
static unsigned int palabra_high;

/* =================================================================================
Main function
  ================================================================================= */
void main(void){

init_system ();

valor_potenciometro=0;
valor_sensor_temperatura=0;
LED = 0;

sensor_setup();
ad_conversor_setup();

while(1) {

valor_potenciometro=ReadADC();   // Libreria adc.h de PICC18
valor_sensor_temperatura=ReadSPI1();  //Libreria spi.h de PICC18

output_logic();
future_state_logic();
}

}

/* =================================================================================
Function definitions
  ================================================================================= */

//*****************************************************************************
//Future_state_logic routine
//*****************************************************************************
char future_state_logic(void){

char error = 0;

switch (present_state) {
case Idle_Low:
if ((valor_sensor_temperatura<20)||(valor_potenciometro<25)){ // Menor de 20ºC o la resistencia menos a 25Kohms
future_state = Idle_High;
}
else if (getch_available()==true) // Si hay un caracter disponible recibido por el puerto serie.
{
caracter_recibido=getch();
if(caracter_recibido=='a')
{
future_state = Idle_High;
LED=1;
error=0;
}
else{
future_state=Idle_Low;
LED=0;
error=1;
}
}

break;

case Idle_High:
if (TXIF==0){ // Buffer de transmision vacio
future_state = Idle_Low;
}
else{
error=1;
}
break;


default:
error = 1;
}
return (error);
}

//*****************************************************************************
//Output logic routine
//*****************************************************************************
char output_logic(void){
unsigned char error = 1;


switch (present_state) {

case Idle_Low:
LED = 0;
error = 0;
break;

case Idle_High:
if((valor_sensor_temperatura<20)||(valor_potenciometro<25))
{
UsartWriteText(&valor_potenciometro);
UsartWriteText(&valor_sensor_temperatura);
LED=1;
error=0;
}
else if (getch_available()==true) // Si hay un caracter disponible recibido por el puerto serie.
{
caracter_recibido=getch();
if(caracter_recibido=='a')
{
UsartWriteText(&valor_potenciometro);
UsartWriteText(&valor_sensor_temperatura);
LED=1;
error=0;
}
else
LED=0;
error=1;
}
else
error=1;
LED=0;

break;


default:
error = 1;
LED=0;
break;
}

return (error);
}

//*****************************************************************************
//Init operations 
//*****************************************************************************
void init_system (void)
{

TRISB=1; //LED. Todos los pines se comportaran como salidas menos RB0 2^0=1
TRISA=32; // SS( Select Slave) must have TRISA<5> bit set
TRISB=1; // SDI. El bit 0 a 1.Configurado en master mode (bit 1 cleared, en mode slave bit 1 set)
TRISC=128; // SDO. Tots els bits a 1 menys la sortida 7

}


//*****************************************************************************
//Time delay routine.   
//*****************************************************************************
void time_delay(unsigned int delay){

unsigned int i;
for(i = 0; i <= delay ;i++){
NOP();
}
}

//*****************************************************************************
// SERIAL SETUP 
//*****************************************************************************
void serial_setup(void){
#define SPBRG_VALUE ((PIC_CLK/(16UL*BAUD)) -1)


BRGH = 1;
BRG16 = 0;
SPBRG = SPBRG_VALUE;

SPEN=1; // Enable serial port
SYNC=0; // Asincrono

TXIE=0; // Desactivar interrupciones en tx
TXEN=1; // Enable the transmitter
TX9=0; // 8 bits transmission

RCIE=1; // Activar interrupciones en rx
RX9=0; // 8 bits reception
CREN=1; //Enable reception


/* Using interruptions...*/
/*
GIE=1;
PEIE=1;
*/


#define clear_usart_errors_inline \
if (OERR)
{
TXEN=0; \
TXEN=1; \
CREN=0; \
CREN=1; \
}
if (FERR) \
{
dummy=RCREG; \
TXEN=0; \
TXEN=1; \
}

}


//*****************************************************************************
// Enviar datos ( un caracter)
//*****************************************************************************

void UsartWriteChar(unsigned char ch) {
   
while(TXIF!=0) // 0 = The EUSART transmit buffer is full
      continue;
TXREG = ch;

}
//*****************************************************************************
// Enviar datos (un buffer)
//*****************************************************************************
void UsartWriteText(const unsigned char *txt){

unsigned char i = 0;
while(txt[i]!='\0') {
UsartWriteChar(txt[i]);
i++;
}

}

//*****************************************************************************
//Leer datos ( un caracter)
//*****************************************************************************

unsigned char getch(void)
{
while(RCIF!=1){ //1 = The EUSART receive buffer, RCREG, is full
CLRWDT();
clear_usart_errors_inline;
}
return RCREG;
}

//*****************************************************************************
//Leer datos (un buffer)
//*****************************************************************************
unsigned char UsartReadChar_nonstop(void) {

if(!PIR1bits.RCIF) // TRMT1 is set when TSR is empty
      return 0;   

    return RCREG;
}


//*****************************************************************************
//Comprueba si aun faltan datos o no
//*****************************************************************************
unsigned char getch_available(void)
{
if(RCIF)
return true;
else
return false;
}


//*****************************************************************************
//Errores USART
//*****************************************************************************
void clear_usart_errors(void)
{
clear_usart_errors_inline;
}


//*****************************************************************************
//Leer entradas.
//*****************************************************************************

//*****************************************************************************
//Leer bytes recibidos del bus del modulo SPI
//*****************************************************************************

void sensor_setup(void)  // SPI Master mode:
{

static unsigned int Byte;

SSPEN=1;    //Enables serial port and configures SCK, SDO, SDI and SS as serial port pins
BF=0;        //Receive not complete, SSPBUF is empty

//SCK is the clock output (Master Mode)
//Clock Polarity(Idle state of SCK)

SMP=1;      //Input data sampled at end of data output time
CKE=0;      //Transmit occurs on transition from Idle to active clock state

SSPM3=0;
SSPM2=0; //SPI Master mode, clock = FOSC/4
SSPM1=0;
SSPM0=0;

CKP=0; //Idle state for clock is a low level

SSPIF=0;   
if((BF==1)&&(SSPIF==1)){ //Receive complete, SSPBUF is full && The transmission/reception is complete (must be cleared in software)
Byte = SSPBUF; // Guardo los datos que tengo en el buffer (despues limpiare el buffer)
BF=0;
}

SSPIF=0; ////Waiting to transmit/receive

//return Byte
}




void ad_conversor_setup(void)
{

ADCON1=14; // PCFG3=1,PCFG2=1,PCFG1=1,PCFG0=0. Todas las entradas digitales


CHS3=0;
CHS2=0; // Seleccionamos el canal 0 (AN0) que es donde esta conectado el potenciometro
CHS1=0;
CHS0=0;

//Tiempo de adquisicion
ACQT2=0;
ACQT1=0;  // 2Tad (Tad=1us) Por tanto 2x1us =2us >= 1.65us( Tacq calculado teoricamente)
ACQT0=1;



ADCS2=1;
ADCS1=0;       // Idem a 4Tosc. 4*Tosc(1us) es el primer valor que hace que sea superior a 0.7us( el minimo)
ADCS0=0;


ADON=1; // A/D converter module is enabled

/* Configure A/D interrupt*/
ADIF=0;
ADIE=1;
GIE=1;

/*Wait the required acquisition time (if required).*/


GO/DONE=1; // A/D conversion in progress

/*Wait for A/D conversion to complete:Waiting for the A/D interrupt*/
/*Read A/D Result registers (ADRESH:ADRESL);
clear bit ADIF, if required*/

if( ADIF==1){ //An A/D conversion completed (must be cleared in software)
palabra_low= ADRESL;
palabra_high=ADRESH;
ADIF=0;
}   


}

Gracias de antemano.
Título: Re: enviar datos de un sensor de temperatura y de un pot por el puerto serie RS232
Publicado por: AngelGris en 03 de Diciembre de 2010, 14:22:12
  Siguen habiendo cosas que no me cierran como por ejemplo que estás habilitando las interrupciones pero no las usas. Si habilitás las interrupciones pero nunca hacés nada en la rutina de interrupción y no borras los flag de la interrupción que se produzca vas a quedar en un ciclo cerrado porque vas a estar reentrando constantemente.

  Para enviar datos al puerto RS232, se envían de a 8 bits por lo tanto si querés enviar un int tendrías que hacer algo así

  putch (palabra_low);
  putch (palabra_high)

  Te dejo una librería de SPI  pero es para la familia 16F, así que tendrías que hacer los cambios necesarios para que funcione con la 18F

Código: C
  1. /**************************************************************************
  2. *         Libreria para protocolo SPI por HardWare para HiTech            *
  3. ***************************************************************************
  4.  
  5. ***************************************************************************
  6. *                                                                         *
  7. * En esta libreria se encuentran las siguientes funciones                 *
  8. *                                                                         *
  9. * setup_spi(int)      (inicializa el puerto SPI)                          *
  10. * write_spi(char)     (envia y lee un byte del SPI)                       *
  11. * read_spi()          (lee un byte del SPI)                               *
  12. * write_spi_int(char) (envia y lee un byte del SPI con interrupcion)      *
  13. * read_spi_int()      (lee un byte del SPI con interrupcion)              *
  14. *                                                                         *
  15. *  En esta libreria están definidos los parametros SPI_MASTER, SPI_SLAVE  *
  16. * SPI_SS_DISABLED, SPI_IDLE_L, SPI_IDLE_H, SPI_CLK_DIV4, SPI_CLK_DIV16,   *
  17. * SPI_CLK_DIV64, SPI_CLK_T2. SPI_SAMPLE_AT_END, SPI_XMIT_IDLE_TO_ACTIVE   *
  18. *                                                                         *
  19. * Dichos parametros son los que se usan en la funcion seupt_spi().        *
  20. *                                                                         *
  21. ***************************************************************************
  22.  
  23. ***************************************************************************
  24. *                                                                         *
  25. *  Para la configuracion como Maestro se pueden usar los siguientes       *
  26. * parametros, combinandolos con |                                         *
  27. * SPI_MASTER, SPI_IDLE_L, SPI_IDLE_H, SPI_CLK_DIV4, SPI_CLK_DIV16,        *
  28. * SPI_CLK_DIV64, SPI_CLK_T2, SPI_SAMPLE_AT_END, SPI_XMIT_IDLE_TO_ACTIVE   *
  29. *                                                                         *
  30. *  Para la configuracion como esclavo se pueden usar los siguientes       *
  31. * parametros, combinandolos con |                                         *
  32. * SPI_SLAVE, SPI_IDLE_L, SPI_IDLE_H, SPI_SS_DISABLED                      *
  33. *                                                                         *
  34. ***************************************************************************
  35.  
  36.  
  37.  
  38. * Ejemplo de configuracion y utilizacion
  39.  
  40.   #include "Hardspi.c"
  41.  
  42.   void main (void)
  43.   {
  44.     char lectura;
  45.  
  46.     .....
  47.     .....
  48.     .....
  49.  
  50.     setup_spi (SPI_MASTER || SPI_IDLE_L || SPI_XMIT_IDLE_TO_ACTIVE SPI_DIV4);
  51.    
  52.     write_spi (0x10);           //envia el dato 0x10 al spi
  53.     lectura = read_spi();       //leo el dato del spi
  54.     lectura = write_spi (0xFF); //envio 0xFF y a su vez guardo en lectura el dato leido
  55.   }
  56.  
  57.  
  58.  
  59. */
  60.  
  61.  
  62. #define SPI_MASTER                0x20
  63. #define SPI_SLAVE                 0x24
  64. #define SPI_SS_DISABLED           1
  65. #define SPI_IDLE_L                0
  66. #define SPI_IDLE_H                0x10
  67. #define SPI_CLK_DIV4              0
  68. #define SPI_CLK_DIV16             1
  69. #define SPI_CLK_DIV64             2
  70. #define SPI_CLK_T2                3
  71. #define SPI_SAMPLE_AT_END         0x8000
  72. #define SPI_XMIT_IDLE_TO_ACTIVE   0x4000
  73.  
  74.  
  75.  
  76. void setup_spi(unsigned int config)
  77. {
  78.   TRISC4 = 1;
  79.   SSPSTAT = config/256;
  80.   SSPCON = config &0xFF;
  81.   if (SSPM2 == 0) TRISC3 = 0;
  82.   else
  83.   {
  84.     TRISC3 = 1;
  85.     if (SSPM0 == 0) TRISA5 = 1;
  86.   }
  87. }
  88.  
  89. unsigned char write_spi (unsigned char spi_data_out)
  90. {
  91.   TRISC5 = 0;
  92.   SSPBUF = spi_data_out;
  93.   while (SSPIF==0);
  94.   SSPIF = 0;
  95.   return SSPBUF;
  96. }
  97.  
  98. unsigned char read_spi (void)
  99. {
  100.   TRISC5 = 1;
  101.   SSPBUF = 16;
  102.   while (SSPIF==0);
  103.   SSPIF = 0;
  104.   return SSPBUF;
  105. }
  106.  
  107. void write_spi_int (unsigned char spi_data_out)
  108. {
  109.   TRISC5 = 0;
  110.   SSPBUF = spi_data_out;
  111. }
  112.  
  113. void read_spi_int (void)
  114. {
  115.   TRISC5 = 1;
  116.   SSPBUF = 0;
  117. }

  Con esta librería, dentro de tu while podrías usar la función read_spi(); para leer el sensor
Título: Re: enviar datos de un sensor de temperatura y de un pot por el puerto serie RS232
Publicado por: edu1989 en 03 de Diciembre de 2010, 14:35:32
Gracias de nuevo.

Entonces si tengo algun bit que me avise cuando.. por ejemplo se acaba la conversion:
if( ADIF==1). Esto puedo tratarlo sin interrupciones no? tal y como hago a continuacion.

No se si te refieres a eso. Si es por la parte que pone "Using interruptions" esta entre /* */ como comentario.

Intentare modificar la libreria para poder usarla.
Gracias de antemano.

Edito para comentar el codigo de la libreria:
La parte de leer el sensor hecha por mi es:

Código: [Seleccionar]
SSPIF=0;   
if((BF==1)&&(SSPIF==1)){ /*Receive complete, SSPBUF is full && The transmission/reception is complete (must be cleared in software)*/

return SSPBUF;
BF=0;
}

SSPIF=0; ////Waiting to transmit/receive

La funcion leer de la libreria es:
Código: [Seleccionar]
unsigned char read_spi (void)
{
 
SSPBUF = 16; // ESTA LINEA QUE HACE?
while (SSPIF==0);
SSPIF = 0;
return SSPBUF;
}

Es equivalente...
Título: Re: enviar datos de un sensor de temperatura y de un pot por el puerto serie RS232
Publicado por: AngelGris en 03 de Diciembre de 2010, 17:10:04
Gracias de nuevo.

Entonces si tengo algun bit que me avise cuando.. por ejemplo se acaba la conversion:
if( ADIF==1). Esto puedo tratarlo sin interrupciones no? tal y como hago a continuacion.

No se si te refieres a eso. Si es por la parte que pone "Using interruptions" esta entre /* */ como comentario.

  Las interrupciones las estás habilitando cuando pones GIE = 1; (Global Interrupt Enable);

  Claro, podés usar cualquier flag IF (ya sea ADIF, para el caso del conversor) o (SSPIF para el caso de SPI) sin necesidad de habilitar las interrupciones.
Título: Re: enviar datos de un sensor de temperatura y de un pot por el puerto serie RS232
Publicado por: edu1989 en 03 de Diciembre de 2010, 19:01:52
Gracias, arreglado! He seguido haciendo cosas y he separado los "setups" de las funciones leer, asi mucho mas claro. He retocado sobretodo la funcion del pot, juntando ADRESH y ADRESL en un mismo buffer. Pero me siguen saliendo errores...

-En el setup_adc el bit GO(GO =1, A/D conversion in progress) no me lo reconoce.. no se el porque.
-En el ejemplo de antes he visto que SSPBUF era un caracter, porque lo asignaba a la variable lectura, declarada como caracter ( Lo he cambiado pues)
- Las funciones para tx por el puerto rs232 no se si ya corren y si esta bien como le paso el parametro:

   UsartWriteText(&valor_potenciometro);
   UsartWriteText(&valor_sensor_temperatura);

Adjunto el codigo a continuacion. Gracias de antemano.
Código: [Seleccionar]
#include <htc.h>



/* =================================================================================
Definitions
    ================================================================================= */
#define PORTBIT(adr, bit) ( (unsigned)(&adr)*8 + (bit) )

#define Idle_Low 1 // No envia datos
#define Idle_High 2 // Envia datos

#define true 1
#define false 0

#define BAUD  9600 // Configuramos la velocidad, tanto puede ser 19200 o de 9600 kbaud/s pero hay q cambiarlo tb en la simulacion de proteus
#define PIC_CLK 4000000 // Clock de 4MHz (Cristal)

/* =================================================================================
Function prototypes
    ================================================================================= */
static void interrupt service_routine (void); // This is the interrupt service routine

void init_system (void);
void time_delay (unsigned int );
char output_logic(void);
char future_state_logic(void);

void setup_sensor(void);
void setup_adc(void);
void serial_setup(void);

void UsartWriteText(const unsigned char *txt);
void UsartWriteChar(unsigned char ch);
unsigned char getch(void);
unsigned char UsartReadChar_nonstop(void);
unsigned char getch_available(void);
void clear_usart_errors(void);
unsigned char read_spi (void);
unsigned char read_adc(void);



/* =================================================================================
Global variables 
  ================================================================================= */
static bit potenciometro @ PORTBIT(PORTA, 0); // Declaración del potenciometro
static bit sensor_temperatura @ PORTBIT(PORTB, 0);
//static bit sensor_datos_salida @ PORTBIT(PORTC, 7);  // SD0 disabled in master mode (configuración como entrada)
static bit LED @ PORTBIT(PORTB, 1);


static char present_state = Idle_Low; // state variable
static char future_state = Idle_Low; // state variable

static unsigned int valor_potenciometro;
char valor_sensor_temperatura;

static unsigned char caracter_recibido;

unsigned char dummy;
static unsigned int palabra_low;
static unsigned int palabra_high;

/* =================================================================================
Main function
  ================================================================================= */
void main(void){

valor_potenciometro=0;
valor_sensor_temperatura=0;
LED = 0;

init_system ();

setup_sensor();
setup_adc();
serial_setup();


while(1) {

valor_sensor_temperatura=read_spi(); // Las pongo aqui porque es donde hago la lectura de los datos.
valor_potenciometro=read_adc();

output_logic();
future_state_logic();
}

}

/* =================================================================================
Function definitions
  ================================================================================= */

//*****************************************************************************
//Future_state_logic routine
//*****************************************************************************
char future_state_logic(void){

char error = 0;

switch (present_state) {
case Idle_Low:
if ((valor_sensor_temperatura<20)||(valor_potenciometro<25)){ // Menor de 20ºC o la resistencia menos a 25Kohms
future_state = Idle_High;
}
else if (getch_available()==true) // Si hay un caracter disponible recibido por el puerto serie.
{
caracter_recibido=getch();
if(caracter_recibido=='a')
{
future_state = Idle_High;
LED=1;
error=0;
}
else{
future_state=Idle_Low;
LED=0;
error=1;
}
}

break;

case Idle_High:
if (TXIF==0){ // Buffer de transmision vacio
future_state = Idle_Low;
}
else{
error=1;
}
break;


default:
error = 1;
}
return (error);
}

//*****************************************************************************
//Output logic routine
//*****************************************************************************
char output_logic(void){
unsigned char error = 1;


switch (present_state) {

case Idle_Low:
LED = 0;
error = 0;
break;

case Idle_High:
if((valor_sensor_temperatura<20)||(valor_potenciometro<25))
{
UsartWriteText(&valor_potenciometro);
UsartWriteText(&valor_sensor_temperatura);
LED=1;
error=0;
}
else if (getch_available()==true) // Si hay un caracter disponible recibido por el puerto serie.
{
caracter_recibido=getch();
if(caracter_recibido=='a')
{
UsartWriteText(&valor_potenciometro);
UsartWriteText(&valor_sensor_temperatura);
LED=1;
error=0;
}
else
LED=0;
error=1;
}
else
error=1;
LED=0;

break;


default:
error = 1;
LED=0;
break;
}

return (error);
}

//*****************************************************************************
//Init operations 
//*****************************************************************************
void init_system (void)
{

TRISB=1; //LED. Todos los pines se comportaran como salidas menos RB0 2^0=1
TRISA=32; // SS( Select Slave) must have TRISA<5> bit set
TRISB=1; // SDI. El bit 0 a 1.Configurado en master mode (bit 1 cleared, en mode slave bit 1 set)
TRISC=128; // SDO. Tots els bits a 1 menys la sortida 7

}


//*****************************************************************************
//Time delay routine.   
//*****************************************************************************
void time_delay(unsigned int delay){

unsigned int i;
for(i = 0; i <= delay ;i++){
NOP();
}
}

//*****************************************************************************
// SERIAL SETUP 
//*****************************************************************************
void serial_setup(void){
#define SPBRG_VALUE ((PIC_CLK/(16UL*BAUD)) -1)


BRGH = 1;
BRG16 = 0;
SPBRG = SPBRG_VALUE;

SPEN=1; // Enable serial port
SYNC=0; // Asincrono

TXIE=0; // Desactivar interrupciones en tx
TXEN=1; // Enable the transmitter
TX9=0; // 8 bits transmission

RCIE=1; // Activar interrupciones en rx
RX9=0; // 8 bits reception
CREN=1; //Enable reception


#define clear_usart_errors_inline \
if (OERR)
{
TXEN=0; \
TXEN=1; \
CREN=0; \
CREN=1; \
}
if (FERR) \
{
dummy=RCREG; \
TXEN=0; \
TXEN=1; \
}

}


//*****************************************************************************
// Enviar datos ( un caracter)
//*****************************************************************************

void UsartWriteChar(unsigned char ch) {
   
while(TXIF!=0) // 0 = The EUSART transmit buffer is full
      continue;
TXREG = ch;

}
//*****************************************************************************
// Enviar datos (un buffer)
//*****************************************************************************
void UsartWriteText(const unsigned char *txt){

unsigned char i = 0;
while(txt[i]!='\0') {
UsartWriteChar(txt[i]);
i++;
}

}

//*****************************************************************************
//Leer datos ( un caracter)
//*****************************************************************************

unsigned char getch(void)
{
while(RCIF!=1){ //1 = The EUSART receive buffer, RCREG, is full
CLRWDT();
clear_usart_errors_inline;
}
return RCREG;
}

//*****************************************************************************
//Leer datos (un buffer)
//*****************************************************************************
unsigned char UsartReadChar_nonstop(void) {

if(!PIR1bits.RCIF) // TRMT1 is set when TSR is empty
      return 0;   

    return RCREG;
}


//*****************************************************************************
//Comprueba si aun faltan datos o no
//*****************************************************************************
unsigned char getch_available(void)
{
if(RCIF)
return true;
else
return false;
}


//*****************************************************************************
//Errores USART
//*****************************************************************************
void clear_usart_errors(void)
{
clear_usart_errors_inline;
}


//*****************************************************************************
//Leer entradas.
//*****************************************************************************

//*****************************************************************************
//Leer bytes recibidos del bus del modulo SPI
//*****************************************************************************

void setup_sensor(void)  // SPI Master mode:
{

SSPEN=1;    //Enables serial port and configures SCK, SDO, SDI and SS as serial port pins
BF=0;        //Receive not complete, SSPBUF is empty

//SCK is the clock output (Master Mode)
//Clock Polarity(Idle state of SCK)

SMP=1;      //Input data sampled at end of data output time
CKE=0;      //Transmit occurs on transition from Idle to active clock state

SSPM3=0;
SSPM2=0; //SPI Master mode, clock = FOSC/4
SSPM1=0;
SSPM0=0;

CKP=0; //Idle state for clock is a low level

SSPIF=0;   

}


void setup_adc(void)
{

ADCON1=14; // PCFG3=1,PCFG2=1,PCFG1=1,PCFG0=0. Todas las entradas digitales


CHS3=0;
CHS2=0; // Seleccionamos el canal 0 (AN0) que es donde esta conectado el potenciometro
CHS1=0;
CHS0=0;

//Tiempo de adquisicion
ACQT2=0;
ACQT1=0;  // 2Tad (Tad=1us) Por tanto 2x1us =2us >= 1.65us( Tacq calculado teoricamente)
ACQT0=1;

ADCS2=1;
ADCS1=0;       // Idem a 4Tosc. 4*Tosc(1us) es el primer valor que hace que sea superior a 0.7us( el minimo)
ADCS0=0;


ADON=1; // A/D converter module is enabled

/* Configure A/D interrupt*/
ADIF=0;
ADIE=1;

//SALE ERROR EN ESTA INSTRUCCION Y EL BIT EXISTE!
//GO = 1; // A/D conversion in progress


}

//*****************************************************************************
//Leer entradas.
//*****************************************************************************

//*****************************************************************************
//LEER DATOS SENSOR
//*****************************************************************************
unsigned char read_spi (void)
{
if((BF==1)&&(SSPIF==1)){ //Receive complete, SSPBUF is full && The transmission/reception is complete (must be cleared in software)
SSPIF=0; ////Waiting to transmit/receive
BF=0;
return SSPBUF;
}
}

//*****************************************************************************
//LEER DATOS POTENCIOMETRO
//*****************************************************************************
unsigned char read_adc(void)
{
char buf[15];
int i=0;
int j=0;
int cont=0;

if( ADIF==1){ //An A/D conversion completed (must be cleared in software)
palabra_low= ADRESL;
palabra_high=ADRESH;
ADIF=0;
}   

for(i=0,i=7,i++)
{

if(palabra_low & 2^i)
buf[i] = '1';
else
    buf[i] = '0';
cont++;

if(cont==8)
j=8;
 
}               
             
for(j=8,j=15,j++)
{

if(palabra_high & 2^j)
buf[j] = '1';
else
  buf[j] = '0';
               
}   
return buf;
}
Título: Re: enviar datos de un sensor de temperatura y de un pot por el puerto serie RS232
Publicado por: AngelGris en 03 de Diciembre de 2010, 21:05:33
Gracias, arreglado! He seguido haciendo cosas y he separado los "setups" de las funciones leer, asi mucho mas claro. He retocado sobretodo la funcion del pot, juntando ADRESH y ADRESL en un mismo buffer. Pero me siguen saliendo errores...

-En el setup_adc el bit GO(GO =1, A/D conversion in progress) no me lo reconoce.. no se el porque.


  En la versión que tengo yo (Hitech PIC18 9.51PL2 linux) este bit se llama GODONE. Para saber esto vas a tener que buscar el archivo de definiciones que tenga tu versión. En mi caso busqué en la carpeta "include" el archivo "pic18f4550.h"


-En el ejemplo de antes he visto que SSPBUF era un caracter, porque lo asignaba a la variable lectura, declarada como caracter ( Lo he cambiado pues)
- Las funciones para tx por el puerto rs232 no se si ya corren y si esta bien como le paso el parametro:

   UsartWriteText(&valor_potenciometro);
   UsartWriteText(&valor_sensor_temperatura);


  Yo para enviar sólo un char me hice la función putch(); y para enviar un string hice putst(); El uso que le doy es como te muestro a continuación

Código: C
  1. void main (void)
  2. {
  3.   unsigned char dato = 50;
  4.   unsigned char * palabra = "HOLA";
  5.  
  6.   putch(48);
  7.   putch('A');
  8.   putch(dato);
  9.  
  10.   putst("Hola Mundo");
  11.   putst(palabra)
  12. }
Título: Re: enviar datos de un sensor de temperatura y de un pot por el puerto serie RS232
Publicado por: edu1989 en 04 de Diciembre de 2010, 12:58:37
He seguido toqueteando cosas. Gracias por el aporte anterior.

- Primero de todo, he visto que el bit GO/DONE  tal y como decias era GODONE=1; Lo he puesto pero me tira un warning: unused label "GODONE"

- He arreglado la funcion read_adc y me sale el error "illegal conversion of pointer to integer"

- En ambas funciones read_adc y read_sensor ---> illegal conversion of integer to pointer. No se porque no va! se queja con char y con int!


- En la funcion  char output_logic(void) hay cuando hago:  if((valor_sensor_temperatura<20)||(valor_potenciometro<25)) ya que 25 es un int y los dos valores son unsigned char.Transformo el valor del sensor o del pot a ASCII?

- En la funcion read_spi me tira un error "return at end of non-void function". Como retorno el caracter leido sino es con un return?

- Por ultimo la funcion putst.. no entiendo bien el codigo... no se porque hace if(*str==13) o if(*str==10). Creo que a mi estas lineas me sobran.

Adjunto el codigo, gracias de antemano:

Código: [Seleccionar]
#include <htc.h>

/* =================================================================================
Definitions
    ================================================================================= */
#define PORTBIT(adr, bit) ( (unsigned)(&adr)*8 + (bit) )

#define Idle_Low 1 // No envia datos
#define Idle_High 2 // Envia datos

#define true 1
#define false 0

#define BAUD  9600 // Configuramos la velocidad, tanto puede ser 19200 o de 9600 kbaud/s pero hay q cambiarlo tb en la simulacion de proteus
#define PIC_CLK 4000000 // Clock de 4MHz (Cristal)

/* =================================================================================
Function prototypes
    ================================================================================= */
static void interrupt service_routine (void); // This is the interrupt service routine

void init_system (void);
void time_delay (unsigned int );
char output_logic(void);
char future_state_logic(void);

void setup_sensor(void);
void setup_adc(void);
void serial_setup(void);

void putst(register const char *str);
void putch(unsigned char c);

unsigned char getch(void);
unsigned char UsartReadChar_nonstop(void);
unsigned char getch_available(void);
void clear_usart_errors(void);

unsigned char read_spi (void);
unsigned char read_adc(void);



/* =================================================================================
Global variables 
  ================================================================================= */
static bit potenciometro @ PORTBIT(PORTA, 0); // Declaración del potenciometro
static bit sensor_temperatura @ PORTBIT(PORTB, 0);
//static bit sensor_datos_salida @ PORTBIT(PORTC, 7);  // SD0 disabled in master mode (configuración como entrada)
static bit LED @ PORTBIT(PORTB, 1);


static char present_state = Idle_Low; // state variable
static char future_state = Idle_Low; // state variable

unsigned char * valor_potenciometro;
unsigned char * valor_sensor_temperatura;

unsigned char * buffer;

unsigned char high_result;
unsigned char low_result;

static unsigned char caracter_recibido;

unsigned char dummy;


/* =================================================================================
Main function
  ================================================================================= */
void main(void){

valor_potenciometro=0;
valor_sensor_temperatura=0;
LED = 0;

init_system ();

setup_sensor();
setup_adc();
serial_setup();


while(1) {

valor_sensor_temperatura=read_spi(); // Las pongo aqui porque es donde hago la lectura de los datos.
valor_potenciometro=read_adc();

output_logic();
future_state_logic();
}

}

/* =================================================================================
Function definitions
  ================================================================================= */

//*****************************************************************************
//Future_state_logic routine
//*****************************************************************************
char future_state_logic(void){

char error = 0;

switch (present_state) {
case Idle_Low:
if ((valor_sensor_temperatura<20)||(valor_potenciometro<25)){ // Menor de 20ºC o la resistencia menos a 25Kohms
future_state = Idle_High;
}
else if (getch_available()==true) // Si hay un caracter disponible recibido por el puerto serie.
{
caracter_recibido=getch();
if(caracter_recibido=='a')
{
future_state = Idle_High;
LED=1;
error=0;
}
else{
future_state=Idle_Low;
LED=0;
error=1;
}
}

break;

case Idle_High:
if (TXIF==0){ // Buffer de transmision vacio
future_state = Idle_Low;
}
else{
error=1;
}
break;


default:
error = 1;
}
return (error);
}

//*****************************************************************************
//Output logic routine
//*****************************************************************************
char output_logic(void){
unsigned char error = 1;


switch (present_state) {

case Idle_Low:
LED = 0;
error = 0;
break;

case Idle_High:
if((valor_sensor_temperatura<20)||(valor_potenciometro<25))
{

putst(valor_potenciometro);
putst(valor_sensor_temperatura);


LED=1;
error=0;
}
else if (getch_available()==true) // Si hay un caracter disponible recibido por el puerto serie.
{
caracter_recibido=getch();
if(caracter_recibido=='a')
{
putst(valor_potenciometro);
putst(valor_sensor_temperatura);
LED=1;
error=0;
}
else
LED=0;
error=1;
}
// else
error=1;
LED=0;

break;


default:
error = 1;
LED=0;
break;
}

return (error);
}

//*****************************************************************************
//Init operations 
//*****************************************************************************
void init_system (void)
{

TRISB=1; //LED. Todos los pines se comportaran como salidas menos RB0 2^0=1
TRISA=32; // SS( Select Slave) must have TRISA<5> bit set
TRISB=1; // SDI. El bit 0 a 1.Configurado en master mode (bit 1 cleared, en mode slave bit 1 set)
TRISC=128; // SDO. Tots els bits a 1 menys la sortida 7

}


//*****************************************************************************
//Time delay routine.   
//*****************************************************************************
void time_delay(unsigned int delay){

unsigned int i;
for(i = 0; i <= delay ;i++){
NOP();
}
}

//*****************************************************************************
// SERIAL SETUP 
//*****************************************************************************
void serial_setup(void){
#define SPBRG_VALUE ((PIC_CLK/(16UL*BAUD)) -1)


BRGH = 1;
BRG16 = 0;
SPBRG = SPBRG_VALUE;

SPEN=1; // Enable serial port
SYNC=0; // Asincrono

TXIE=0; // Desactivar interrupciones en tx
TXEN=1; // Enable the transmitter
TX9=0; // 8 bits transmission

RCIE=1; // Activar interrupciones en rx
RX9=0; // 8 bits reception
CREN=1; //Enable reception


#define clear_usart_errors_inline \
if (OERR)
{
TXEN=0; \
TXEN=1; \
CREN=0; \
CREN=1; \
}
if (FERR) \
{
dummy=RCREG; \
TXEN=0; \
TXEN=1; \
}

}


//*****************************************************************************
// Enviar datos ( un caracter)
//*****************************************************************************

void putch(unsigned char c)
{
while(!TXIF){
clear_usart_errors_inline;
CLRWDT();
}
TXREG=c;

}
//*****************************************************************************
// Enviar datos (un buffer)
//*****************************************************************************
void putst(register const char *str)
{
while((*str)!=0)
{
putch(*str);
if(*str==13)
putch(10);

if(*str==10)
putch(13);
str++;
}

}





//*****************************************************************************
//Leer datos ( un caracter)
//*****************************************************************************

unsigned char getch(void)
{
while(RCIF!=1){ //1 = The EUSART receive buffer, RCREG, is full
CLRWDT();
clear_usart_errors_inline;
}
return RCREG;
}

//*****************************************************************************
//Leer datos (un buffer)
//*****************************************************************************
unsigned char UsartReadChar_nonstop(void) {

if(!PIR1bits.RCIF) // TRMT1 is set when TSR is empty
      return 0;   

    return RCREG;
}


//*****************************************************************************
//Comprueba si aun faltan datos o no
//*****************************************************************************
unsigned char getch_available(void)
{
if(RCIF)
return true;
else
return false;
}


//*****************************************************************************
//Errores USART
//*****************************************************************************
void clear_usart_errors(void)
{
clear_usart_errors_inline;
}


//*****************************************************************************
//Leer entradas.
//*****************************************************************************

//*****************************************************************************
//Leer bytes recibidos del bus del modulo SPI
//*****************************************************************************

void setup_sensor(void)  // SPI Master mode:
{

SSPEN=1;    //Enables serial port and configures SCK, SDO, SDI and SS as serial port pins
BF=0;        //Receive not complete, SSPBUF is empty

//SCK is the clock output (Master Mode)
//Clock Polarity(Idle state of SCK)

SMP=1;      //Input data sampled at end of data output time
CKE=0;      //Transmit occurs on transition from Idle to active clock state

SSPM3=0;
SSPM2=0; //SPI Master mode, clock = FOSC/4
SSPM1=0;
SSPM0=0;

CKP=0; //Idle state for clock is a low level

SSPIF=0;   

}


void setup_adc(void)
{

ADCON1=14; // PCFG3=1,PCFG2=1,PCFG1=1,PCFG0=0. Todas las entradas digitales


CHS3=0;
CHS2=0; // Seleccionamos el canal 0 (AN0) que es donde esta conectado el potenciometro
CHS1=0;
CHS0=0;

//Tiempo de adquisicion
ACQT2=0;
ACQT1=0;  // 2Tad (Tad=1us) Por tanto 2x1us =2us >= 1.65us( Tacq calculado teoricamente)
ACQT0=1;

ADCS2=1;
ADCS1=0;       // Idem a 4Tosc. 4*Tosc(1us) es el primer valor que hace que sea superior a 0.7us( el minimo)
ADCS0=0;


ADON=1; // A/D converter module is enabled

/* Configure A/D interrupt*/
ADIF=0;
ADIE=1;



}

//*****************************************************************************
//Leer entradas.
//*****************************************************************************

//*****************************************************************************
//LEER DATOS SENSOR
//*****************************************************************************
unsigned char read_spi (void)
{
if((BF==1)&&(SSPIF==1)){ //Receive complete, SSPBUF is full && The transmission/reception is complete (must be cleared in software)
SSPIF=0; ////Waiting to transmit/receive
BF=0;

}
return SSPBUF;
}

//*****************************************************************************
//LEER DATOS POTENCIOMETRO
//*****************************************************************************



unsigned char read_adc(void)
{

GODONE=1; //A/D conversion in progress

if( ADIF==1){ //An A/D conversion completed (must be cleared in software)
buffer = ADRESH<<8;
buffer = buffer+ADRESL;
ADIF=0;
}   

return buffer;
}
 
Título: Re: enviar datos de un sensor de temperatura y de un pot por el puerto serie RS232
Publicado por: AngelGris en 04 de Diciembre de 2010, 13:59:17
Compilé el programa y voy a tratar de detallar un poco los warning, solo que me va a llevar un tiempo, de hecho estoy escribiendo esto mientras tengo el entorno de programación abierto.


- En la funcion read_spi me tira un error "return at end of non-void function". Como retorno el caracter leido sino es con un return?

- Por ultimo la funcion putst.. no entiendo bien el codigo... no se porque hace if(*str==13) o if(*str==10). Creo que a mi estas lineas me sobran.


  En el caso de la función read_spi te emite un warning porque el return lo tenés puesto dentro del if. Si por algún motivo no se cumple dicha condición en tu función salís sin retornar nada y eso no puede ser ya que tu función tiene que devolver algo. Se puede solucionar poniendo el return fuera del if o sino agregando, por ejemplo, return 0 y que quede fuera del if.

algo asi...
Código: C
  1. unsigned char read_spi (void)
  2. {
  3.   if((BF==1)&&(SSPIF==1))
  4.   {                             //Receive complete, SSPBUF is full && The transmission/reception is complete  (must be cleared in software)
  5.     SSPIF=0; ////Waiting to transmit/receive
  6.     BF=0;
  7.     return SSPBUF;
  8.   }
  9.   return 0;         // este es el agregado para que no emita el warning, sino dejas aca el return SSPBUF
  10. }

  En el caso de la función putst, esos if están para detectar el "salto de línea" y al "retroceso de carro". O sea, para enviar como si fuera un "Enter"



- Primero de todo, he visto que el bit GO/DONE  tal y como decias era GODONE=1; Lo he puesto pero me tira un warning: unused label "GODONE"

- He arreglado la funcion read_adc y me sale el error "illegal conversion of pointer to integer"

- En ambas funciones read_adc y read_sensor ---> illegal conversion of integer to pointer. No se porque no va! se queja con char y con int!


  Respecto al GODONE, a mi no me emite ningún error;

  read_spi() devuelve char así que la variable que vayas a usar en la lectura de spi tiene que estar definida como char o unsigned char; tu error es que "valor_sensor_temperatura" lo tenés definido como puntero a char.
  Lo mismo vale para read_adc();


  Después de haber corregido lo anterior sigue habiendo errores. Uno es que superaste el tamaño del array. Cuando definís un array tené en cuenta que entre corchetes "[" y "]" va la cantidad de elementos del array, pero cuando usas una variable definida como array, entre los corchetes va el índice comenzando por 0 y no por 1.
Así, una variable definida como "char variable[15]" tiene 15 elementos que van desde vairable[0] hasta variable[14].

  También sigue habiendo errores de "Illegal conversion of integer to pointer" y es porque tenés definido a buf[15] como un puntero a char. Pero está variable no la podés escribir de la forma buf
Título: Re: enviar datos de un sensor de temperatura y de un pot por el puerto serie RS232
Publicado por: AngelGris en 04 de Diciembre de 2010, 23:16:13
  En los 16F usaba la función ITOA "Tnteger To ASCII" para poder pasar un número entero a su representación en texto. Esto es, por ejemplo, para un valor de 128 tener un string "128" y así poder usar la función putst y enviarlos por el RS232.
  Según el manual del PIC18 también tendría que tener dicha función pero no la pude encontrar, así que copie el código desde el compilador para los 16F y cambié tu programa para hacer uso de dicha función y ahora, simulado en proteus, estoy enviando el valor del pote. No hago la lectura del sensor porque el proteus no tiene dicho integrado.
  También cambié la rutina read_ADC que habías hecho porque le habías dejado un loop infinito.
  También cambié tu función "Future_state_logic()" ya que dentro de ella cambiabas la variable "future_state", pero nunca se le asignaba el nuevo valor a "present_state"

 mi versión de tu programa

Código: C
  1. #include <htc.h>
  2. //#include <stdlib.h>  // para poder usar la funcion itoa
  3.  
  4. #include "itoa.c"
  5.  
  6. /*      =================================================================================
  7.         Definitions
  8.         ================================================================================= */
  9. #define         PORTBIT(adr, bit) ( (unsigned)(&adr)*8 + (bit) )
  10.  
  11. #define         Idle_Low 1      // No envia datos
  12. #define         Idle_High 2 // Envia datos
  13.  
  14. #define true 1
  15. #define false 0
  16.  
  17. #define BAUD  9600                      // Configuramos la velocidad, tanto puede ser 19200 o de 9600 kbaud/s pero hay q cambiarlo tb en la simulacion de proteus      
  18. #define PIC_CLK 4000000         // Clock de 4MHz (Cristal)
  19.  
  20. /*      =================================================================================
  21.         Function prototypes
  22.         ================================================================================= */
  23. static void interrupt service_routine (void);   // This is the interrupt service routine
  24.  
  25. void init_system (void);
  26. void time_delay (unsigned int );
  27. char output_logic(void);
  28. char future_state_logic(void);
  29.  
  30. void setup_sensor(void);
  31. void setup_adc(void);
  32. void serial_setup(void);
  33.  
  34. void putst(register const char *str);
  35. void putch(unsigned char c);
  36.  
  37. unsigned char getch(void);
  38. unsigned char UsartReadChar_nonstop(void);
  39. unsigned char getch_available(void);
  40. void clear_usart_errors(void);
  41.  
  42. unsigned char read_spi (void);
  43. unsigned char read_adc(void);
  44.  
  45.  
  46.  
  47. /*      =================================================================================
  48.         Global variables  
  49.         ================================================================================= */
  50. static bit potenciometro @ PORTBIT(PORTA, 0);   // Declaración del potenciometro
  51. static bit sensor_temperatura @ PORTBIT(PORTB, 0);
  52. //static bit sensor_datos_salida @ PORTBIT(PORTC, 7);  // SD0 disabled in master mode (configuración como entrada)
  53. static bit LED @ PORTBIT(PORTB, 1);    
  54.  
  55.                                
  56. static char present_state = Idle_Low;           // state variable
  57. static char future_state = Idle_Low;            // state variable
  58.  
  59. unsigned char  valor_potenciometro;
  60. unsigned char  valor_sensor_temperatura;
  61.  
  62. unsigned char  buf[16];
  63.  
  64.  
  65. char * valor_pote_en_texto;           // un puntero para almacenar el numero en texto
  66. char * valor_sensor_en_texto;         // un puntero para almacenar el numero en texto
  67.  
  68. unsigned char high_result;
  69. unsigned char low_result;
  70.  
  71. static unsigned char caracter_recibido;
  72.  
  73. unsigned char dummy;
  74.  
  75.  
  76. /*      =================================================================================
  77.         Main function
  78.         ================================================================================= */
  79. void main(void)
  80. {
  81.   valor_potenciometro = 0;
  82.   valor_sensor_temperatura = 0;
  83.   LED = 0;     
  84.   init_system();
  85.   setup_sensor();
  86.   setup_adc();
  87.   serial_setup();      
  88.   while(1)
  89.   {
  90.     //valor_sensor_temperatura = read_spi();    // Las pongo aqui porque es donde hago la lectura de los datos.
  91.     valor_potenciometro = read_adc();
  92.    
  93.     valor_pote_en_texto = itoa (buf, valor_potenciometro, 10);
  94.  //   valor_sensor_en_texto = itoa (buf, valor_sensor_temperatura, 10);
  95.  
  96.     output_logic();
  97.     future_state_logic();
  98.   }            
  99. }      
  100.  
  101. /*      =================================================================================
  102.         Function definitions
  103.         ================================================================================= */
  104.  
  105. //*****************************************************************************
  106. //Future_state_logic routine
  107. //*****************************************************************************
  108. char future_state_logic(void)
  109. {
  110.   char error = 0;
  111.   switch (present_state)
  112.   {
  113.     case Idle_Low:                             
  114.                   if ((valor_sensor_temperatura < 20) || (valor_potenciometro < 25))
  115.                   { // Menor de 20ºC o la resistencia menos a 25Kohms
  116.                     //future_state = Idle_High;
  117.                     present_state = Idle_High;
  118.                   }
  119.                   else
  120.                   if (getch_available() == true) //Si hay un caracter disponible recibido por el puerto serie
  121.                   {
  122.                     caracter_recibido = getch();
  123.                     if (caracter_recibido == 'a')
  124.                     {
  125.                       //future_state = Idle_High;
  126.                       present_state = Idle_High;
  127.                       LED = 1;
  128.                       error = 0;
  129.                     }
  130.                     else
  131.                     {
  132.                       //future_state = Idle_Low;
  133.                       present_state = Idle_Low;
  134.                       LED = 0;
  135.                       error = 1;
  136.                     }
  137.                   }
  138.                   break;
  139.     case Idle_High:                                            
  140.                    if (TXIF == 0)
  141.                    { // Buffer de transmision vacio
  142.                      //future_state = Idle_Low;
  143.                      present_state = Idle_Low;
  144.                    }
  145.                    else
  146.                    {
  147.                      error = 1;
  148.                    }
  149.                    break;
  150.     default:
  151.                           error = 1;
  152.   }    
  153.   return (error);
  154. }
  155.  
  156. //*****************************************************************************
  157. //Output logic routine
  158. //*****************************************************************************
  159. char output_logic(void)
  160. {
  161.   unsigned char error = 1;
  162.   switch (present_state)
  163.   {
  164.     case Idle_Low:                             
  165.                    LED = 0;
  166.                    error = 0;
  167.                    break;
  168.     case Idle_High:                    
  169.                    if ((valor_sensor_temperatura < 20) || (valor_potenciometro < 25))
  170.                    {
  171.                      putst ("Valor del pote: ");
  172.                      putst (valor_pote_en_texto);
  173.                      putst ("\n");  //cambio de linea
  174.                      putst ("Valor del sensor: ");
  175.                      //putst (valor_sensor_en_texto);
  176.                      putst ("Suponemos un valor de 25 grados");
  177.                      putst ("\n");
  178.                      LED = 1;
  179.                      error = 0;
  180.                     }
  181.                     else
  182.                     if (getch_available() == true)
  183.                    // Si hay un caracter disponible recibido por el puerto serie.
  184.                    {
  185.                      caracter_recibido = getch();
  186.                      if (caracter_recibido == 'a')
  187.                      {
  188.                        putch (valor_potenciometro);
  189.                        putch (valor_sensor_temperatura);
  190.                        LED = 1;
  191.                        error = 0;
  192.                      }
  193.                      else
  194.                        LED = 0;
  195.                      error = 1;
  196.                    }
  197.                    //   else
  198.                    error = 1;
  199.                    LED = 0;    
  200.                    break;
  201.     default:
  202.                    error = 1;
  203.                    LED = 0;
  204.                    break;              
  205.   }
  206.   return (error);
  207. }
  208.  
  209. //*****************************************************************************
  210. //Init operations  
  211. //*****************************************************************************
  212. void init_system (void)
  213. {
  214.   TRISB = 1; //LED. Todos los pines se comportaran como salidas menos RB0 2^0=1
  215.   TRISA = 32; // SS( Select Slave) must have TRISA<5> bit set
  216.   TRISB = 1; // SDI. El bit 0 a 1.Configurado en master mode (bit 1 cleared, en mode slave bit 1 set)
  217.   TRISC = 128; // SDO. Tots els bits a 1 menys la sortida 7
  218. }
  219.  
  220.  
  221. //*****************************************************************************
  222. //Time delay routine.  
  223. //*****************************************************************************
  224. void time_delay(unsigned int delay)
  225. {
  226.   unsigned int i;
  227.        
  228.   for (i = 0; i <= delay; i++)
  229.   {    
  230.     NOP();
  231.   }
  232. }
  233.  
  234. //*****************************************************************************
  235. // SERIAL SETUP  
  236. //*****************************************************************************
  237. void serial_setup(void)
  238. {
  239.   #define SPBRG_VALUE ((PIC_CLK/(16UL*BAUD)) -1)
  240.   BRGH = 1;
  241.   BRG16 = 0;
  242.   SPBRG = SPBRG_VALUE;
  243.   SPEN = 1; // Enable serial port
  244.   SYNC = 0; // Asincrono
  245.   TXIE = 0; // Desactivar interrupciones en tx
  246.   TXEN = 1; // Enable the transmitter
  247.   TX9 = 0; // 8 bits transmission
  248.   RCIE = 1; // Activar interrupciones en rx
  249.   RX9 = 0; // 8 bits reception
  250.   CREN = 1; //Enable reception
  251.   #define clear_usart_errors_inline     if (OERR)\
  252.                                     {\
  253.                                       TXEN = 0;\
  254.                                       TXEN = 1;\
  255.                                       CREN = 0;\
  256.                                       CREN = 1;\
  257.                                     }\
  258.                                     if (FERR)\
  259.                                     {\
  260.                                       dummy = RCREG;\
  261.                                       TXEN = 0;\
  262.                                       TXEN = 1;\
  263.                                     }
  264. }
  265.  
  266.  
  267. //*****************************************************************************
  268. // Enviar datos ( un caracter)
  269. //*****************************************************************************
  270.  
  271. void putch(unsigned char c)
  272. {
  273.   while (!TXIF)
  274.   {
  275.     clear_usart_errors_inline;
  276.     CLRWDT();
  277.   }
  278.   TXREG = c;
  279. }
  280. //*****************************************************************************
  281. // Enviar datos (un buffer)
  282. //*****************************************************************************
  283. void putst(register const char *str)
  284. {
  285.   while ((*str) != 0)
  286.   {
  287.     putch (*str);
  288.     if (*str == 13) putch (10);
  289.     if (*str == 10) putch (13);
  290.     str++;
  291.   }
  292. }
  293.  
  294. //*****************************************************************************
  295. //Leer datos ( un caracter)
  296. //*****************************************************************************
  297.  
  298. unsigned char getch(void)
  299. {
  300.   while (RCIF != 1)
  301.   {                             //1 = The EUSART receive buffer, RCREG, is full
  302.     CLRWDT();
  303.     clear_usart_errors_inline;
  304.   }
  305.   return RCREG;
  306. }
  307.  
  308. //*****************************************************************************
  309. //Leer datos (un buffer)
  310. //*****************************************************************************
  311. unsigned char UsartReadChar_nonstop(void)
  312. {
  313.   if (!RCIF)    // TRMT1 is set when TSR is empty
  314.     return 0;  
  315.   return RCREG;
  316. }
  317.  
  318.  
  319. //*****************************************************************************
  320. //Comprueba si aun faltan datos o no
  321. //*****************************************************************************
  322. unsigned char getch_available(void)
  323. {
  324.   if (RCIF)
  325.     return true;
  326.   else
  327.     return false;
  328. }
  329.  
  330.  
  331. //*****************************************************************************
  332. //Errores USART
  333. //*****************************************************************************
  334. void clear_usart_errors(void)
  335. {
  336.   clear_usart_errors_inline;
  337. }
  338.  
  339.  
  340. //*****************************************************************************
  341. //Leer entradas.
  342. //*****************************************************************************
  343.  
  344. //*****************************************************************************
  345. //Leer bytes recibidos del bus del modulo SPI
  346. //*****************************************************************************
  347.  
  348. void setup_sensor(void)  // SPI Master mode:
  349. {
  350.   SSPEN = 1;            //Enables serial port and configures SCK, SDO, SDI and SS as serial port pins
  351.   BF = 0;                                                               //Receive not complete, SSPBUF is empty
  352.   //SCK is the clock output (Master Mode)
  353.   //Clock Polarity(Idle state of SCK)
  354.   SMP = 1;                                                       //Input data sampled at end of data output time
  355.   CKE = 0;                                                        //Transmit occurs on transition from Idle to active clock state
  356.   SSPM3 = 0;
  357.   SSPM2 = 0;                                                    //SPI Master mode, clock = FOSC/4      
  358.   SSPM1 = 0;
  359.   SSPM0 = 0;
  360.   CKP = 0;                                                              //Idle state for clock is a low level
  361.   SSPIF = 0;                                                   
  362. }
  363.  
  364. void setup_adc(void)
  365. {
  366.   ADCON1 = 14;          // PCFG3=1,PCFG2=1,PCFG1=1,PCFG0=0. Todas las entradas digitales
  367.   CHS3 = 0;
  368.   CHS2 = 0;                     // Seleccionamos el canal 0 (AN0) que es donde esta conectado el potenciometro
  369.   CHS1 = 0;
  370.   CHS0 = 0;
  371.   //Tiempo de adquisicion
  372.   ACQT2 = 0;
  373.   ACQT1 = 0;            // 2Tad (Tad=1us) Por tanto 2x1us =2us >= 1.65us( Tacq calculado teoricamente)
  374.   ACQT0 = 1;
  375.   ADCS2 = 1;
  376.   ADCS1 = 0;    // Idem a 4Tosc. 4*Tosc(1us) es el primer valor que hace que sea superior a 0.7us( el minimo)
  377.   ADCS0 = 0;   
  378.   ADON = 1;             // A/D converter module is enabled
  379.   /* Configure A/D interrupt*/
  380.   ADIF = 0;
  381.   ADIE = 1;
  382. }
  383.  
  384. //*****************************************************************************
  385. //Leer entradas.
  386. //*****************************************************************************
  387.  
  388. //*****************************************************************************
  389. //LEER DATOS SENSOR
  390. //*****************************************************************************
  391. unsigned char read_spi (void)
  392. {
  393.   if ((BF == 1) && (SSPIF == 1))
  394.   {     //Receive complete, SSPBUF is full && The transmission/reception is complete (must be cleared in software)
  395.     SSPIF = 0; ////Waiting to transmit/receive
  396.     BF = 0;
  397.     return SSPBUF;
  398.   }
  399.   return 0;
  400. }
  401.  
  402. //*****************************************************************************
  403. //LEER DATOS POTENCIOMETRO
  404. //*****************************************************************************
  405. unsigned char read_adc(void)
  406. {
  407.   //Empezar a leer
  408.   GODONE=1; // A/D conversion in progress
  409.   while (ADIF == 0);
  410.   ADIF = 0;
  411.   return ((ADRESH << 8) + (ADRESL));
  412. }
  413.  
  414.     /*GUARDAR EL CONTENIDO DE HIGH_RESULT EN EL buf*/                
  415.     //Verificar si el bit 0 de high_result es 1 ó 0
  416. /*
  417.     if (high_result & 1) buf[0] = '1';
  418.     else
  419.       buf[0] = '0';
  420.     //Verificar si el bit 1 de high_result es 1 ó 0
  421.     if (high_result & 2) buf[1] = '1';
  422.     else
  423.       buf[1] = '0';
  424.     //Verificar si el bit 2 de high_result es 1 ó 0
  425.     if (high_result & 4) buf[2] = '1';
  426.     else
  427.       buf[2] = '0';
  428.     //Verificar si el bit 3 de high_result es 1 ó 0
  429.     if (high_result & 8) buf[3] = '1';
  430.     else
  431.       buf[3] = '0';
  432.     //Verificar si el bit 4 de high_result es 1 ó 0
  433.     if (high_result & 16) buf[4] = '1';
  434.     else
  435.       buf[4] = '0';
  436.     //Verificar si el bit 5 de high_result es 1 ó 0
  437.     if (high_result & 32) buf[5] = '1';
  438.     else
  439.      buf[5] = '0';
  440.     //Verificar si el bit 6 de high_result es 1 ó 0
  441.     if (high_result & 64) buf[6] = '1';
  442.     else
  443.       buf[6] = '0';
  444.     //Verificar si el bit 7 de high_result es 1 ó 0
  445.     if (high_result & 128) buf[7] = '1';
  446.     else
  447.        buf[7] = '0';
  448.  
  449. /*GUARDAR EL CONTENIDO DE Low_RESULT EN EL buf*/                
  450.              
  451.     //Verificar si el bit 0 de high_result es 1 ó 0
  452. /*
  453.     if (low_result & 1) buf[8] = '1';
  454.     else
  455.       buf[8] = '0';
  456.     //Verificar si el bit 1 de high_result es 1 ó 0
  457.     if(low_result & 2) buf[9] = '1';
  458.     else
  459.       buf[9] = '0';
  460.     //Verificar si el bit 2 de high_result es 1 ó 0
  461.     if (low_result & 4) buf[10] = '1';
  462.     else
  463.       buf[10] = '0';
  464.     //Verificar si el bit 3 de high_result es 1 ó 0
  465.     if (low_result & 8) buf[11] = '1';
  466.     else
  467.       buf[11] = '0';
  468.     //Verificar si el bit 4 de high_result es 1 ó 0
  469.     if (low_result & 16) buf[12] = '1';
  470.     else
  471.       buf[12] = '0';
  472.     //Verificar si el bit 5 de high_result es 1 ó 0
  473.     if (low_result & 32) buf[13] = '1';
  474.     else
  475.       buf[13] = '0';
  476.     //Verificar si el bit 6 de high_result es 1 ó 0
  477.     if (low_result & 64) buf[14] = '1';
  478.     else
  479.       buf[14] = '0';
  480.     //Verificar si el bit 7 de high_result es 1 ó 0
  481.     if(low_result & 128) buf[15] = '1';
  482.     else
  483.       buf[15] = '0';
  484. */

  y esto es el archivo itoa.c, que estoy incluyendo en mi versión del programa

Código: C
  1. #include        <stdlib.h>
  2.  
  3. char * utoa(char * buf, unsigned val, int base)
  4. {
  5.         unsigned        v;
  6.         char            c;
  7.  
  8.         v = val;
  9.         do {
  10.                 v /= base;
  11.                 buf++;
  12.         } while(v != 0);
  13.         *buf-- = 0;
  14.         do {
  15.                 c = val % base;
  16.                 val /= base;
  17.                 if(c >= 10)
  18.                         c += 'A'-'0'-10;
  19.                 c += '0';
  20.                 *buf-- = c;
  21.         } while(val != 0);
  22.         return buf;
  23. }
  24.        
  25. char * itoa(char * buf, int val, int base)
  26. {
  27.         char *  cp = buf;
  28.  
  29.         if(val < 0) {
  30.                 *buf++ = '-';
  31.                 val = -val;
  32.         }
  33.         utoa(buf, val, base);
  34.         return cp;
  35. }
Título: Re: enviar datos de un sensor de temperatura y de un pot por el puerto serie RS232
Publicado por: edu1989 en 06 de Diciembre de 2010, 08:39:51
Muchisimas gracias, eres muy amable. Te lo agradezco mucho.

He probado el programa y no se que pasa que no puedo añadir el fichero itoa.c, me sale el siguiente error:
function "_utoa" redefined
function "_itoa" redefined

He hecho dos cosas y no han funcionado:
 -Crear un fichero itoa.c y añadirlo  a "Source files" con el codigo que has puesto antes y hacer un itoa.h (que lo añadia a itoa.c) con la declaracion:

Código: [Seleccionar]
char * utoa(char * buf, unsigned val, int base);
char * itoa(char * buf, int val, int base);

- Lo segundo que he hecho ha sido ponerlo todo en el mismo fichero (final.c) definiendo stdlib.h y sigue habiendo un error: conflicting functions...
________________________________________________________________________________________________________________________________

Por otro lado, como has hecho la simulacion de proteus? con el simulador de puerto serie y  el pote conectado y el led conectados al PIC?. El sensor de temperatura tambien aparece (TC77). Igualmente existe un debugger SPI que podria utilitzarlo no? Pongo el debugger o el sensor conectado al PIC?



Al terminal del PIC tambien se le puede escribir? Es que solo prové de recibir bien pero de enviar aun no he probado nada.

Saludoos y gracias de antemano
Título: Re: enviar datos de un sensor de temperatura y de un pot por el puerto serie RS232
Publicado por: AngelGris en 06 de Diciembre de 2010, 10:03:38
Muchisimas gracias, eres muy amable. Te lo agradezco mucho.

He probado el programa y no se que pasa que no puedo añadir el fichero itoa.c, me sale el siguiente error:
function "_utoa" redefined
function "_itoa" redefined


  Tal vez sea  porque tu versión de compilador ya tenga dichas funciones. Revisa en la carpeta "include" que tiene que estar el archivo "stdlib.h" y mira su contenido a ver si ya tiene definidas ahí las funciones itoa y utoa. En mi caso en dicho archivo no tenía esas funciones.
  Si en tu caso las tiene, con que incluyas dicho archivo a tu código ya deberías poder usar las funciones. Osea, poner
"#include <stdlib.h>"


Por otro lado, como has hecho la simulacion de proteus? con el simulador de puerto serie y  el pote conectado y el led conectados al PIC?. El sensor de temperatura tambien aparece (TC77). Igualmente existe un debugger SPI que podria utilitzarlo no? Pongo el debugger o el sensor conectado al PIC?

Al terminal del PIC tambien se le puede escribir? Es que solo prové de recibir bien pero de enviar aun no he probado nada.


  Como te decía, el sensor no lo simulé porque no tiene dicho integrado. Utilicé el elemento "Virtual Terminal" conectado a los terminales TX y RX para poder ver la transmisión serial. El pote conectado al PIC.

  Gracias a esta prueba también encontré otros errores que corregí (pero me parece que dichas correcciones no están en el programita que te mandé), estos errores eran que tenías el puerto A configurado como salida y para poder usar el conversor AD tenés que configurarlo como entrada (al menos el puerto que quieras usar para el conversor) y también vi que la conversión estaba "justificada a la izquierda", yo ahora la dejé "justificada a la derecha", ésto último está en el datasheet.
 La diferencia entre ambas es la siguiente: para el valor 1111111111  (10 bits, todos en 1)

                ADRESH     ADRESL
izquierda: 11111111    11000000
derecha:   00000011   11111111

  También encontré otro error y es que uso la misma variable buf para convertir tanto el valor del pote como el del sensor y eso está mál. Habría que crear otra variable de similar a buf para usarla al convertir el valor del sensor.
Título: Re: enviar datos de un sensor de temperatura y de un pot por el puerto serie RS232
Publicado por: edu1989 en 06 de Diciembre de 2010, 10:52:01
Gracias de nuevo. He arreglado los errores menos el del justificado. Ese esta en el programita?
He probado la simulacion y me va enviando siempre los dos valores, he cambiado el valor de la resistencia y me va enviado que el valor es 192 siempre. Es un problema debido al justificado? La manera de variar el pot el cambiar la resistencia? recuerdo que habia un botoncito que te permitia cambiarlo durante la simulacion ( creo que era con el proteus.. a lo mejor me confundo de programa)

Por lo que respecta al sensor, lo que quieres decirme es que no lo encuentras en el proteus o que no esta directamente en el PIC? perdona pero no lo he entendido bien.

Edito: Me gustaría probar tambien si cuando envio el caracter a, me envia los datos.. como puedo hacerlo? tendria que conectar otro terminal no?
Título: Re: enviar datos de un sensor de temperatura y de un pot por el puerto serie RS232
Publicado por: AngelGris en 06 de Diciembre de 2010, 10:57:23
Gracias de nuevo. He arreglado los errores menos el del justificado. Ese esta en el programita?
He probado la simulacion y me va enviando siempre los dos valores, he cambiado el valor de la resistencia y me va enviado que el valor es 192 siempre. Es un problema debido al justificado? La manera de variar el pot el cambiar la resistencia? recuerdo que habia un botoncito que te permitia cambiarlo durante la simulacion ( creo que era con el proteus.. a lo mejor me confundo de programa)

Por lo que respecta al sensor, lo que quieres decirme es que no lo encuentras en el proteus o que no esta directamente en el PIC? perdona pero no lo he entendido bien.

  A también me pasaba que me enviaba siempre el mismo dato y por ello cambié el justificado. En la función "setup_adc" agregué ADFM = 1, con eso cambia el justificado.

  Para el pote busqué en resitors --> variable --> y allí algún POT que figure como ACTIVE y con ello te aparece un botoncito con el "+" y otro con el "-" en el pote y justamente con esos botoncitos cambias el valor.
  El sensor no está en el proteus, por eso no lo puedo simular.
Título: Re: enviar datos de un sensor de temperatura y de un pot por el puerto serie RS232
Publicado por: edu1989 en 06 de Diciembre de 2010, 11:39:39
Hombreee! ya funciona! que bieeen, muchisimas gracias!

Para comprobar lo de que cuando recibe un caracter me lo envia, tengo que conectar otro terminal no? En teoria la pata de rx ya esta al otro terminal..tendra que coger esa pata del PIC y conectarla al de tx de mi terminal, si?

Gracias de nuevo, amigo.
Título: Re: enviar datos de un sensor de temperatura y de un pot por el puerto serie RS232
Publicado por: AngelGris en 06 de Diciembre de 2010, 11:51:42
Hombreee! ya funciona! que bieeen, muchisimas gracias!

Para comprobar lo de que cuando recibe un caracter me lo envia, tengo que conectar otro terminal no? En teoria la pata de rx ya esta al otro terminal..tendra que coger esa pata del PIC y conectarla al de tx de mi terminal, si?

Gracias de nuevo, amigo.

 No, no es necesario conectar otro terminal. En el mismo que ya tenés conectado intentá escribir el caracter a enviar.
Te convendría modificar el programa para que no envié datos (así te queda libre la pantalla del termnal) constantemente, y recién los enviés cuando recibe algo a travez del terminal.
Título: Re: enviar datos de un sensor de temperatura y de un pot por el puerto serie RS232
Publicado por: AngelGris en 06 de Diciembre de 2010, 12:21:25
  Te dejo la nueva versión del programa. En la función "future_state_logic" comenté el if donde chequeabas si la temperatura < 20 o el pote < 25, para que no esté transmitiendo siempre.  También cambié la función "output_logic" ya que siempre que "present_state" se "Idle_High" vas a querer transmitir los datos.
  Cambié el TRISC, porque según el datasheet tanto el pin TX como el RX del uart deben ser configurados como entrada.
  Te dejo también una captura de la simulación.

Código: C
  1. #include <htc.h>
  2. #include <stdlib.h>  // para poder usar la funcion itoa
  3.  
  4.  
  5. /*      =================================================================================
  6.         Definitions
  7.         ================================================================================= */
  8. #define         PORTBIT(adr, bit) ( (unsigned)(&adr)*8 + (bit) )
  9.  
  10. #define         Idle_Low 1      // No envia datos
  11. #define         Idle_High 2 // Envia datos
  12.  
  13. #define true 1
  14. #define false 0
  15.  
  16. #define BAUD  9600                      // Configuramos la velocidad, tanto puede ser 19200 o de 9600 kbaud/s pero hay q cambiarlo tb en la simulacion de proteus      
  17. #define PIC_CLK 4000000         // Clock de 4MHz (Cristal)
  18.  
  19. /*      =================================================================================
  20.         Function prototypes
  21.         ================================================================================= */
  22. //static void interrupt service_routine (void); // This is the interrupt service routine
  23.  
  24. void init_system (void);
  25. void time_delay (unsigned int );
  26. char output_logic(void);
  27. char future_state_logic(void);
  28.  
  29. void setup_sensor(void);
  30. void setup_adc(void);
  31. void serial_setup(void);
  32.  
  33. void putst(const char *str);
  34. void putch(unsigned char c);
  35.  
  36. unsigned char getch(void);
  37. unsigned char UsartReadChar_nonstop(void);
  38. unsigned char getch_available(void);
  39. void clear_usart_errors(void);
  40.  
  41. unsigned char read_spi (void);
  42. unsigned int read_adc(void);
  43.  
  44.  
  45.  
  46. /*      =================================================================================
  47.         Global variables  
  48.         ================================================================================= */
  49. static bit potenciometro @ PORTBIT(PORTA, 0);   // Declaración del potenciometro
  50. static bit sensor_temperatura @ PORTBIT(PORTB, 0);
  51. //static bit sensor_datos_salida @ PORTBIT(PORTC, 7);  // SD0 disabled in master mode (configuración como entrada)
  52. static bit LED @ PORTBIT(PORTB, 1);    
  53.  
  54.                                
  55. static char present_state = Idle_Low;           // state variable
  56. static char future_state = Idle_Low;            // state variable
  57.  
  58. unsigned int  valor_potenciometro;
  59. unsigned char  valor_sensor_temperatura;
  60.  
  61. unsigned char pote_buf[6];
  62. unsigned char sensor_buf[10];
  63.  
  64.  
  65. char * valor_pote_en_texto;           // un puntero para almacenar el numero en texto
  66. char * valor_sensor_en_texto;         // un puntero para almacenar el numero en texto
  67.  
  68. //unsigned char high_result;
  69. //unsigned char low_result;
  70.  
  71. static unsigned char caracter_recibido;
  72.  
  73. unsigned char dummy;
  74.  
  75.  
  76. /*      =================================================================================
  77.         Main function
  78.         ================================================================================= */
  79. void main(void)
  80. {
  81.   valor_potenciometro = 0;
  82.   valor_sensor_temperatura = 0;
  83.   LED = 0;     
  84.   init_system();
  85.   setup_sensor();
  86.   setup_adc();
  87.   serial_setup();      
  88.   while(1)
  89.   {
  90.     //valor_sensor_temperatura = read_spi();  // Las pongo aqui porque es donde hago la lectura de los datos.
  91.     valor_potenciometro = read_adc();
  92.    
  93.     valor_pote_en_texto = itoa (pote_buf, valor_potenciometro, 10);
  94.     valor_sensor_en_texto = itoa (sensor_buf, valor_sensor_temperatura, 10);
  95.  
  96.     output_logic();
  97.     future_state_logic();
  98.   }            
  99. }      
  100.  
  101. /*      =================================================================================
  102.         Function definitions
  103.         ================================================================================= */
  104.  
  105. //*****************************************************************************
  106. //Future_state_logic routine
  107. //*****************************************************************************
  108. char future_state_logic(void)
  109. {
  110.   char error = 0;
  111.   switch (present_state)
  112.   {
  113.     case Idle_Low:
  114.                  /*                            
  115.                   if ((valor_sensor_temperatura < 20) || (valor_potenciometro < 25))
  116.                   { // Menor de 20ºC o la resistencia menos a 25Kohms
  117.                     //future_state = Idle_High;
  118.                     present_state = Idle_High;
  119.                   }
  120.                   else */
  121.                   if (getch_available() == true) //Si hay un caracter disponible recibido por el puerto serie
  122.                   {
  123.                     caracter_recibido = getch();
  124.                     if (caracter_recibido == 'a')
  125.                     {
  126.                       //future_state = Idle_High;
  127.                       present_state = Idle_High;
  128.                       LED = 1;
  129.                       error = 0;
  130.                     }
  131.                     else
  132.                     {
  133.                       //future_state = Idle_Low;
  134.                       present_state = Idle_Low;
  135.                       LED = 0;
  136.                       error = 1;
  137.                     }
  138.                   }
  139.                   break;
  140.     case Idle_High:                                            
  141.                    if (TXIF == 0)
  142.                    { // Buffer de transmision vacio
  143.                      //future_state = Idle_Low;
  144.                      present_state = Idle_Low;
  145.                    }
  146.                    else
  147.                    {
  148.                      error = 1;
  149.                    }
  150.                    break;
  151.     default:
  152.                           error = 1;
  153.   }    
  154.   return (error);
  155. }
  156.  
  157. //*****************************************************************************
  158. //Output logic routine
  159. //*****************************************************************************
  160. char output_logic(void)
  161. {
  162.   unsigned char error = 1;
  163.   switch (present_state)
  164.   {
  165.     case Idle_Low:                             
  166.                    LED = 0;
  167.                    error = 0;
  168.                    break;
  169.     case Idle_High:                    
  170.                    putst ("Valor del pote: ");
  171.                    putst (valor_pote_en_texto);
  172.                    putst ("\n");  //cambio de linea
  173.                    putst ("Valor del sensor: ");
  174.                    //putst (valor_sensor_en_texto);
  175.                    putst ("Suponemos un valor de 25 grados");
  176.                    putst ("\n");
  177.                    LED = 1;
  178.                    error = 0;
  179.                    break;
  180.     default:
  181.                    error = 1;
  182.                    LED = 0;
  183.                    break;              
  184.   }
  185.   return (error);
  186. }
  187.  
  188. //*****************************************************************************
  189. //Init operations  
  190. //*****************************************************************************
  191. void init_system (void)
  192. {
  193.   //TRISB = 1; //LED. Todos los pines se comportaran como salidas menos RB0 2^0=1
  194.   //TRISA = 32; // SS( Select Slave) must have TRISA<5> bit set
  195.   TRISA = 255;
  196.   TRISB = 1; // SDI. El bit 0 a 1.Configurado en master mode (bit 1 cleared, en mode slave bit 1 set)
  197.   TRISC = 192; // SDO. Tots els bits a 1 menys la sortida 7
  198. }
  199.  
  200.  
  201. //*****************************************************************************
  202. //Time delay routine.  
  203. //*****************************************************************************
  204. void time_delay(unsigned int delay)
  205. {
  206.   unsigned int i;
  207.        
  208.   for (i = 0; i <= delay; i++)
  209.   {    
  210.     NOP();
  211.   }
  212. }
  213.  
  214. //*****************************************************************************
  215. // SERIAL SETUP  
  216. //*****************************************************************************
  217. void serial_setup(void)
  218. {
  219.   #define SPBRG_VALUE ((PIC_CLK/(16UL*BAUD)) -1)
  220.   BRGH = 1;
  221.   BRG16 = 0;
  222.   SPBRG = SPBRG_VALUE;
  223.   SPEN = 1; // Enable serial port
  224.   SYNC = 0; // Asincrono
  225.   TXIE = 0; // Desactivar interrupciones en tx
  226.   TXEN = 1; // Enable the transmitter
  227.   TX9 = 0; // 8 bits transmission
  228.   RCIE = 1; // Activar interrupciones en rx
  229.   RX9 = 0; // 8 bits reception
  230.   CREN = 1; //Enable reception
  231.   #define clear_usart_errors_inline     if (OERR)\
  232.                                     {\
  233.                                       TXEN = 0;\
  234.                                       TXEN = 1;\
  235.                                       CREN = 0;\
  236.                                       CREN = 1;\
  237.                                     }\
  238.                                     if (FERR)\
  239.                                     {\
  240.                                       dummy = RCREG;\
  241.                                       TXEN = 0;\
  242.                                       TXEN = 1;\
  243.                                     }
  244. }
  245.  
  246.  
  247. //*****************************************************************************
  248. // Enviar datos ( un caracter)
  249. //*****************************************************************************
  250.  
  251. void putch(unsigned char c)
  252. {
  253.   while (!TXIF)
  254.   {
  255.     clear_usart_errors_inline;
  256.     CLRWDT();
  257.   }
  258.   TXREG = c;
  259. }
  260. //*****************************************************************************
  261. // Enviar datos (un buffer)
  262. //*****************************************************************************
  263. void putst(register const char *str)
  264. {
  265.   while ((*str) != 0)
  266.   {
  267.     putch (*str);
  268.     if (*str == 13) putch (10);
  269.     if (*str == 10) putch (13);
  270.     str++;
  271.   }
  272. }
  273.  
  274. //*****************************************************************************
  275. //Leer datos ( un caracter)
  276. //*****************************************************************************
  277.  
  278. unsigned char getch(void)
  279. {
  280.   while (RCIF != 1)
  281.   {                             //1 = The EUSART receive buffer, RCREG, is full
  282.     CLRWDT();
  283.     clear_usart_errors_inline;
  284.   }
  285.   return RCREG;
  286. }
  287.  
  288. //*****************************************************************************
  289. //Leer datos (un buffer)
  290. //*****************************************************************************
  291. unsigned char UsartReadChar_nonstop(void)
  292. {
  293.   if (!RCIF)    // TRMT1 is set when TSR is empty
  294.     return 0;  
  295.   return RCREG;
  296. }
  297.  
  298.  
  299. //*****************************************************************************
  300. //Comprueba si aun faltan datos o no
  301. //*****************************************************************************
  302. unsigned char getch_available(void)
  303. {
  304.   if (RCIF)
  305.     return true;
  306.   else
  307.     return false;
  308. }
  309.  
  310.  
  311. //*****************************************************************************
  312. //Errores USART
  313. //*****************************************************************************
  314. void clear_usart_errors(void)
  315. {
  316.   clear_usart_errors_inline;
  317. }
  318.  
  319.  
  320. //*****************************************************************************
  321. //Leer entradas.
  322. //*****************************************************************************
  323.  
  324. //*****************************************************************************
  325. //Leer bytes recibidos del bus del modulo SPI
  326. //*****************************************************************************
  327.  
  328. void setup_sensor(void)  // SPI Master mode:
  329. {
  330.   SSPEN = 1;            //Enables serial port and configures SCK, SDO, SDI and SS as serial port pins
  331.   BF = 0;                                                               //Receive not complete, SSPBUF is empty
  332.   //SCK is the clock output (Master Mode)
  333.   //Clock Polarity(Idle state of SCK)
  334.   SMP = 1;                                                       //Input data sampled at end of data output time
  335.   CKE = 0;                                                        //Transmit occurs on transition from Idle to active clock state
  336.   SSPM3 = 0;
  337.   SSPM2 = 0;                                                    //SPI Master mode, clock = FOSC/4      
  338.   SSPM1 = 0;
  339.   SSPM0 = 0;
  340.   CKP = 0;                                                              //Idle state for clock is a low level
  341.   SSPIF = 0;                                                   
  342. }
  343.  
  344. void setup_adc(void)
  345. {
  346.   ADFM = 1;
  347.   ADCON1 = 14;          // PCFG3=1,PCFG2=1,PCFG1=1,PCFG0=0. Todas las entradas digitales
  348.   CHS3 = 0;
  349.   CHS2 = 0;                     // Seleccionamos el canal 0 (AN0) que es donde esta conectado el potenciometro
  350.   CHS1 = 0;
  351.   CHS0 = 0;
  352.   //Tiempo de adquisicion
  353.   ACQT2 = 0;
  354.   ACQT1 = 0;            // 2Tad (Tad=1us) Por tanto 2x1us =2us >= 1.65us( Tacq calculado teoricamente)
  355.   ACQT0 = 1;
  356.   ADCS2 = 1;
  357.   ADCS1 = 0;    // Idem a 4Tosc. 4*Tosc(1us) es el primer valor que hace que sea superior a 0.7us( el minimo)
  358.   ADCS0 = 0;   
  359.   ADON = 1;             // A/D converter module is enabled
  360.   /* Configure A/D interrupt*/
  361.   ADIF = 0;
  362.   //ADIE = 1;
  363. }
  364.  
  365. //*****************************************************************************
  366. //Leer entradas.
  367. //*****************************************************************************
  368.  
  369. //*****************************************************************************
  370. //LEER DATOS SENSOR
  371. //*****************************************************************************
  372. unsigned char read_spi (void)
  373. {
  374.   if ((BF == 1) && (SSPIF == 1))
  375.   {     //Receive complete, SSPBUF is full && The transmission/reception is complete (must be cleared in software)
  376.     SSPIF = 0; ////Waiting to transmit/receive
  377.     BF = 0;
  378.     return SSPBUF;
  379.   }
  380.   return 0;
  381. }
  382.  
  383. //*****************************************************************************
  384. //LEER DATOS POTENCIOMETRO
  385. //*****************************************************************************
  386. unsigned int read_adc(void)
  387. {
  388.   //Empezar a leer
  389.   GODONE = 1; // A/D conversion in progress
  390.   while (GODONE == 1);
  391.   ADIF = 0;
  392.   return ((ADRESH << 8) + (ADRESL));
  393. }

Título: Re: enviar datos de un sensor de temperatura y de un pot por el puerto serie RS232
Publicado por: edu1989 en 07 de Diciembre de 2010, 07:23:03
Gracias de nuevo. Ya me funciono! todo va viento en popa :)
Ahora mismo estoy centrado en el funcionamiento del sensor. He estado mirando el manual y explicaré un poco lo que he hecho:

1. Setup de todos los pines que hay que configurar ( eso ya estaba en la version anterior del programa)
2.Coneccion de pines:
- Serial Data Out (SDO)- RC7 ---> disabled in master mode. Por tanto no lo he declarado ya que en RC7 tengo la salida                   del terminal
- Serial Data Input(SDI)- RB0---> Lo he conectado pero no lo he configurado en el TRISB porque en el datasheet pone:
"Automatically controlled by the SPI module". Aunque si lo tengo declarado como que el sensor esta conectado al pin RB0 del puertoB
-Serial Clock (SCK). En este pin el datasheet distingui dos opciones depende del modo(Master o Slave). En mi caso(master), TRISB<1> bit clear
Y por ultimo el pin Select Slave(SS) que no lo tengo declarado porque solo se declara y conecta en modo Slave.

Os adjunto una imagen del proteus para que veais como lo tengo conectado.
Gracias de antemano.
Título: Re: enviar datos de un sensor de temperatura y de un pot por el puerto serie RS232
Publicado por: AngelGris en 07 de Diciembre de 2010, 09:53:38
Gracias de nuevo. Ya me funciono! todo va viento en popa :)
Ahora mismo estoy centrado en el funcionamiento del sensor. He estado mirando el manual y explicaré un poco lo que he hecho:

1. Setup de todos los pines que hay que configurar ( eso ya estaba en la version anterior del programa)
2.Coneccion de pines:
- Serial Data Out (SDO)- RC7 ---> disabled in master mode. Por tanto no lo he declarado ya que en RC7 tengo la salida                   del terminal
- Serial Data Input(SDI)- RB0---> Lo he conectado pero no lo he configurado en el TRISB porque en el datasheet pone:
"Automatically controlled by the SPI module". Aunque si lo tengo declarado como que el sensor esta conectado al pin RB0 del puertoB
-Serial Clock (SCK). En este pin el datasheet distingui dos opciones depende del modo(Master o Slave). En mi caso(master), TRISB<1> bit clear
Y por ultimo el pin Select Slave(SS) que no lo tengo declarado porque solo se declara y conecta en modo Slave.

Os adjunto una imagen del proteus para que veais como lo tengo conectado.
Gracias de antemano.

  Bien, lo que te falta es usar un pin (el que vos quieras) para controlar el pin CS del dispositivo spi (en este caso el TC77). Cuando hacés "1" el pin CS de x dispositivo, éste no puede ni recibir ni mandar información al bus spi. Cuando ponés a "0" el pin CS de x dispositivo es cuando podés trabajar con el dispositivo en cuestión.
  Esto sirve para tener varios dispositivos en un mismo bus spi, pero cada uno con un pin CS distinto.
Título: Re: enviar datos de un sensor de temperatura y de un pot por el puerto serie RS2
Publicado por: edu1989 en 07 de Diciembre de 2010, 11:58:30
Gracias de nuevo. Por tanto conecto CS con cualquier pin del pic? por ejemplo el RA2. Lo declaro en el programa y controlo lo del cs=0 en el programa o ya directamente esta a 0?

Yo conectaria el cs con uno de los pines del pic ( supongo RA2) y declararia:
static bit CS @ PORTBIT(PORTA, 2);

Y lo declararia como entrada en el TRISA<2> bit set.

es correcto?
Gracias de antemano.
Título: Re: enviar datos de un sensor de temperatura y de un pot por el puerto serie RS2
Publicado por: AngelGris en 07 de Diciembre de 2010, 12:47:53
Gracias de nuevo. Por tanto conecto CS con cualquier pin del pic? por ejemplo el RA2. Lo declaro en el programa y controlo lo del cs=0 en el programa o ya directamente esta a 0?

Yo conectaria el cs con uno de los pines del pic ( supongo RA2) y declararia:
static bit CS @ PORTBIT(PORTA, 2);

Y lo declararia como entrada en el TRISA<2> bit set.

es correcto?
Gracias de antemano.


  No, lo tenés que declarar como salida. Porque desde el pic va a salir la señal hacia el TC77.
  Con lo cual para leer los 2 bytes que envía el TC77 deberías hacer algo así...

  CS = 0;
  byte_alto = read_spi;
  byte_bajo = read_spi;
  CS = 1;

Título: Re: enviar datos de un sensor de temperatura y de un pot por el puerto serie RS232
Publicado por: edu1989 en 07 de Diciembre de 2010, 13:13:56
y como junto los dos bytes en uno de solo? tendria que crear una variable de 16bits no? y guardarlo ahi...
En vez de hacerlo como tu dices podria poner una unica variable que leyera el contenido de read_spi, de 16 bits?

Gracias
Título: Re: enviar datos de un sensor de temperatura y de un pot por el puerto serie RS232
Publicado por: AngelGris en 07 de Diciembre de 2010, 13:28:07
y como junto los dos bytes en uno de solo? tendria que crear una variable de 16bits no? y guardarlo ahi...
En vez de hacerlo como tu dices podria poner una unica variable que leyera el contenido de read_spi, de 16 bits?

Gracias

  Para juntar los dos bytes es sencillo, declaras una variable tipo int y en el programa hacés
"variableint = (byte_alto << 8 ) + byte_bajo".

  Me parece que cada transferencia de SPI es de 8 bits, entonces no podrías hacer toda la lectura seguida. Tené en cuenta que el dato leído se almacena en el registro SSPBUF que es de 8 bits.

Código: C
  1. int lectura_sensor;
  2. .....
  3. .....
  4. .....
  5. CS = 0;
  6. byte_alto = read_spi();
  7. byte_bajo = read_spi();
  8. CS = 1;
  9. lectura_sensor = (byte_alto << 8) + byte_bajo;

Lo que sí podrías hacer es una rutina read_sensor(); que llamase 2 veces a read_spi() y que devuelva un int. Algo así:

Código: C
  1. int read_sensor(void)
  2. {
  3.   char byte_alto, byte_bajo;
  4.  
  5.   byte_alto = read_spi();
  6.   byte_bajo = read_spi();
  7.   return ((byte_alto >> 8) + byte_bajo);
  8. }

Título: Re: enviar datos de un sensor de temperatura y de un pot por el puerto serie RS232
Publicado por: edu1989 en 07 de Diciembre de 2010, 13:49:28
Sigue sin funcionarme... no se el porque la verdad. He hecho lo que me has dicho.. he probado tambien de enviar los datos por separado al puerto serie y ver los valores. He enviado "byte_sensor_high" y "byte_sensor_low" y he visto : 00. Por lo que no se si leemos bien los datos.. Adjunto codigo y un imp pantalla d la simulacion.

Gracias.

Código: [Seleccionar]
#include <htc.h>
#include <stdlib.h> // Para usar la funcion itoa

/* =================================================================================
Definitions
    ================================================================================= */
#define PORTBIT(adr, bit) ( (unsigned)(&adr)*8 + (bit) )

#define Idle_Low 1 // No envia datos
#define Idle_High 2 // Envia datos

#define true 1
#define false 0

#define BAUD  9600 // Configuramos la velocidad, tanto puede ser 19200 o de 9600 kbaud/s pero hay q cambiarlo tb en la simulacion de proteus
#define PIC_CLK 4000000 // Clock de 4MHz (Cristal)

/* =================================================================================
Function prototypes
    ================================================================================= */
static void interrupt service_routine (void); // This is the interrupt service routine

void init_system (void);
void time_delay (unsigned int );
char output_logic(void);
char future_state_logic(void);

void setup_sensor(void);
void setup_adc(void);
void serial_setup(void);

void putst(register const char *str);
void putch(unsigned char c);

unsigned char getch(void);
unsigned char UsartReadChar_nonstop(void);
unsigned char getch_available(void);
void clear_usart_errors(void);

unsigned char read_spi (void);
unsigned char read_adc(void);
int read_sensor(void);



/* =================================================================================
Global variables 
  ================================================================================= */
static bit potenciometro @ PORTBIT(PORTA, 0); // Declaración del potenciometro
static bit serial_data_in @ PORTBIT(PORTB, 0);
// Serial Data 0utput disabled in master mode (configuración como entrada)
static bit serial_clock @ PORTBIT(PORTB, 1);
static bit LED @ PORTBIT(PORTB, 2);
static bit CS @ PORTBIT(PORTB, 3);

static char present_state = Idle_Low; // state variable
static char future_state = Idle_Low; // state variable

unsigned char valor_potenciometro;
unsigned char valor_sensor_temperatura;



unsigned char buf_pot[6];
unsigned char buf_sensor[10];

char * valor_pote_en_texto;
char * valor_sensor_en_texto;

static unsigned char caracter_recibido;

unsigned char dummy;


/* =================================================================================
Main function
  ================================================================================= */
void main(void){

valor_potenciometro=0;
valor_sensor_temperatura=0;
LED = 0;
init_system ();
setup_sensor();
setup_adc();
serial_setup();


while(1) {

CS = 0;
  valor_sensor_temperatura = read_sensor(); // Lectura datos del sensor (2bytes)
CS = 1;

valor_potenciometro=read_adc(); //Lectura de datos del conversor (1byte)

valor_pote_en_texto= itoa(buf_pot,valor_potenciometro,10);
valor_sensor_en_texto=itoa(buf_sensor,valor_sensor_temperatura,10);

output_logic();
future_state_logic();
}

}

/* =================================================================================
Function definitions
  ================================================================================= */

//*****************************************************************************
//Future_state_logic routine
//*****************************************************************************
char future_state_logic(void){

char error = 0;

switch (present_state) {
case Idle_Low:

if ((valor_sensor_temperatura<20)||(valor_potenciometro<25)){ // Menor de 20ºC o la resistencia menos a 25Kohms
present_state = Idle_High;
}
else

if (getch_available()==true) // Si hay un caracter disponible recibido por el puerto serie.
{
caracter_recibido=getch();
if(caracter_recibido=='a')
{

present_state = Idle_High;
LED=1;
error=0;

}
else{
present_state=Idle_Low;
LED=0;
error=1;
}
}
else
error=1;
break;

case Idle_High:
if (TXIF==0){ // Buffer de transmision vacio
present_state = Idle_Low;
}
else{
error=1;
}
break;


default:
error = 1;

}
return (error);
}

//*****************************************************************************
//Output logic routine
//*****************************************************************************
char output_logic(void){
unsigned char error = 1;


switch (present_state) {

case Idle_Low:
LED = 0;
error = 0;
break;

case Idle_High:

putst("\n");   // Cambio de linea
putst("Valor del potenciometre: ");
putst(valor_pote_en_texto);
putst("\n");   // Cambio de linea
putst("Valor del sensor: ");
putst(valor_sensor_en_texto);

//putst("Suponemos un valor de 25 grados");
putst("\n");

LED=1;
error=0;
break;


default:
error = 1;
LED=0;
break;
}

return (error);
}

//*****************************************************************************
//Init operations 
//*****************************************************************************
void init_system (void)
{
// Declaración del potenciometro
TRISA = 255;

//Declaracion del sensor
//Serial Data Input is automatically controlled by the SPI module

TRISB = 4; // SCK. En master mode TRISB<1> bit cleared && El led como entrada en TRISB<2>. CS como salida ( a 0)

// Declaración del terminal (como entradas)
TRISC = 192; // tx/rx

}


//*****************************************************************************
//Time delay routine.   
//*****************************************************************************
void time_delay(unsigned int delay){

unsigned int i;
for(i = 0; i <= delay ;i++){
NOP();
}
}

//*****************************************************************************
// SERIAL SETUP 
//*****************************************************************************
void serial_setup(void){
#define SPBRG_VALUE ((PIC_CLK/(16UL*BAUD)) -1)


BRGH = 1;
BRG16 = 0;
SPBRG = SPBRG_VALUE;

SPEN=1; // Enable serial port
SYNC=0; // Asincrono

TXIE=0; // Desactivar interrupciones en tx
TXEN=1; // Enable the transmitter
TX9=0; // 8 bits transmission

RCIE=1; // Activar interrupciones en rx
RX9=0; // 8 bits reception
CREN=1; //Enable reception


#define clear_usart_errors_inline \
if (OERR)
{
TXEN=0; \
TXEN=1; \
CREN=0; \
CREN=1; \
}
if (FERR) \
{
dummy=RCREG; \
TXEN=0; \
TXEN=1; \
}

}


//*****************************************************************************
// Enviar datos ( un caracter)
//*****************************************************************************

void putch(unsigned char c)
{
while(!TXIF){
clear_usart_errors_inline;
CLRWDT();
}
TXREG=c;

}
//*****************************************************************************
// Enviar datos (un buffer)
//*****************************************************************************
//Los if están para detectar el "salto de línea" y al "retroceso de carro".Como si fuera un "Enter"

void putst(register const char *str)
{
while((*str)!=0)
{
putch(*str);
if(*str==13)
putch(10);

if(*str==10)
putch(13);
str++;
}

}


//*****************************************************************************
//Leer datos ( un caracter)
//*****************************************************************************

unsigned char getch(void)
{
while(RCIF!=1){ //1 = The EUSART receive buffer, RCREG, is full
CLRWDT();
clear_usart_errors_inline;
}
return RCREG;
}

//*****************************************************************************
//Leer datos (un buffer)
//*****************************************************************************
unsigned char UsartReadChar_nonstop(void) {

if(!PIR1bits.RCIF) // TRMT1 is set when TSR is empty
      return 0;   

    return RCREG;
}


//*****************************************************************************
//Comprueba si aun faltan datos o no
//*****************************************************************************
unsigned char getch_available(void)
{
if(RCIF)
return true;
else
return false;
}


//*****************************************************************************
//Errores USART
//*****************************************************************************
void clear_usart_errors(void)
{
clear_usart_errors_inline;
}


//*****************************************************************************
//Leer entradas.
//*****************************************************************************

//*****************************************************************************
//Leer bytes recibidos del bus del modulo SPI
//*****************************************************************************

void setup_sensor(void)  // SPI Master mode:
{

SSPEN=1;    //Enables serial port and configures SCK, SDO, SDI and SS as serial port pins
BF=0;        //Receive not complete, SSPBUF is empty

//SCK is the clock output (Master Mode)
//Clock Polarity(Idle state of SCK)

SMP=1;      //Input data sampled at end of data output time
CKE=0;      //Transmit occurs on transition from Idle to active clock state

SSPM3=0;
SSPM2=0; //SPI Master mode, clock = FOSC/4
SSPM1=0;
SSPM0=0;

CKP=0; //Idle state for clock is a low level

SSPIF=0;   

}


void setup_adc(void)
{

ADCON1=14; // PCFG3=1,PCFG2=1,PCFG1=1,PCFG0=0. Todas las entradas digitales


CHS3=0;
CHS2=0; // Seleccionamos el canal 0 (AN0) que es donde esta conectado el potenciometro
CHS1=0;
CHS0=0;

//Tiempo de adquisicion
ACQT2=0;
ACQT1=0;  // 2Tad (Tad=1us) Por tanto 2x1us =2us >= 1.65us( Tacq calculado teoricamente)
ACQT0=1;

ADCS2=1;
ADCS1=0;       // Idem a 4Tosc. 4*Tosc(1us) es el primer valor que hace que sea superior a 0.7us( el minimo)
ADCS0=0;


ADON=1; // A/D converter module is enabled

/* Configure A/D interrupt*/
ADIF=0;
//ADIE=1;

ADFM = 1; // justificada a la derecha


}

//*****************************************************************************
//Leer entradas.
//*****************************************************************************

//*****************************************************************************
//LEER DATOS SENSOR
//*****************************************************************************

unsigned char read_spi (void)
{
if((BF==1)&&(SSPIF==1)){ //Receive complete, SSPBUF is full && The transmission/reception is complete  (must be cleared in software)
SSPIF=0; ////Waiting to transmit/receive6.   
 BF=0;   
return SSPBUF;
}
  return 0;         
}

int read_sensor(void)
{
  char byte_alto, byte_bajo;
 
  byte_alto = read_spi();
  byte_bajo = read_spi();
  return ((byte_alto >> 8) + byte_bajo);
}


//*****************************************************************************
//LEER DATOS POTENCIOMETRO
//*****************************************************************************



unsigned char read_adc(void)
{
//Empezamos a leer
GODONE=1; //A/D conversion in progress

while(ADIF==0); //An A/D conversion completed (must be cleared in software)
ADIF=0;
return((ADRESH << 8)+(ADRESL));
}
 
 

 

Título: Re: enviar datos de un sensor de temperatura y de un pot por el puerto serie RS232
Publicado por: AngelGris en 07 de Diciembre de 2010, 14:26:51
 Hay un error en el ejemplo que te mostré para la función read_sensor; tiene que ser "return ((byte_alto << 8) + byte_bajo) (el byte alto rotarlo a la izquierda 8 veces, que es lo mismo que multiplicar por 256, o lo mismo que decir el byte alto de una variable de 16 bits).

  Otro cosa que veo es que tenés definida como unsigned char a la variable que almacena el dato leido del sensor; la tanés que definir como int.

  El pin que usas para el led lo tenés como entrada, tiene que ir como salida.

  En cuanto a que no funcione la lectura, ya ahí habría que usar el spi debugger del proteus para ver si hay aunque sea alguna transmisión de datos. Puede ser que tengas configurado la interface SPI en un modo que no es soportado por el TC77 o que falle la simulación de éste último.... ahí que probar
Título: Re: enviar datos de un sensor de temperatura y de un pot por el puerto serie RS232
Publicado por: edu1989 en 07 de Diciembre de 2010, 15:25:07
Las dos primeras cosas arregladas, muchas gracias. La simulacion sigue sin ir...en teoria el sensor tiene que soportar todos los modos.. si esta en la misma placa no? No se porque me parece que no estoy conectando bien las cosas..

El clock, lo conecto directamente a un pin pero no hago nada.. ( aunque lo tenga configurado en el setup_sensor).

Por otra parte leyendo un poco, he ido a parar aqui Aquí (http://www.todopic.com.ar/foros/index.php?topic=31816.0)
Habla de como conectar el chip select (CS).

Voy a seguir mirando...
Título: Re: enviar datos de un sensor de temperatura y de un pot por el puerto serie RS232
Publicado por: AngelGris en 07 de Diciembre de 2010, 16:14:39
Encontré un problema en tu código de la rutina read_spi() y es que no llenás el SSPBUF.
Para que comience la transmisión tiene que estar lleno el SSPBUF y ahí el PIC empieza a generar los pulsos de clock y a su vez va haciendo la lectura y va llenando el SSPBUF con el valor de entrada.

Por eso en mi rutina read_spi() pongo en alta impedancia (puero como entrada) SDO y a su vez pongo el dato 16 (podría ser cualquier otro) en SSPBUf. Al poner en alta impedancia dicho pin logro que el PIC no transmita datos hacia el periférico.

Código: C
  1. unsigned char read_spi()
  2. {
  3.   ....  // tris del SDO = 1
  4.   SSPBUF = 16; // puede ir cualquier cosa
  5.   while (SSPIF == 0);
  6.   SSPIF = 0;
  7.   return SSPBUF;
  8. }
Título: Re: enviar datos de un sensor de temperatura y de un pot por el puerto serie RS232
Publicado por: edu1989 en 07 de Diciembre de 2010, 20:42:21
Gracias de nuevo. He cambiado la funcion pero... para declarar SDO tendria que declararlo en RC7 ( que es donde tengo el terminal).
En el proteus me sale un warning despues de hacer este cambio en la funcion:

Logic contention(s) detected on net #00008

El problema tambien es que el sensor TC77 en proteus tiene 3 pines: cs,sck y una misma entrada para sdi y sdo ( data input y data output..). Como lo conecto entonces?
Título: Re: enviar datos de un sensor de temperatura y de un pot por el puerto serie RS232
Publicado por: AngelGris en 07 de Diciembre de 2010, 23:09:34
Gracias de nuevo. He cambiado la funcion pero... para declarar SDO tendria que declararlo en RC7 ( que es donde tengo el terminal).
En el proteus me sale un warning despues de hacer este cambio en la funcion:

Logic contention(s) detected on net #00008


  Pero ese error te sale porque seguramente no estás configurando el pin como entrada, sino como salida. Fijate que para que funcione como RX del UART ya queda en alta impedancia (puerto como entrada) entonces si yo lo vuelvo a configurar como entrada no tiene porque haber conflicto, de hecho ni siquiera es necesario volver a configurarlo como entrada. Simplemente te dije que lo configuraras como entrada así te hacés una rutina de lectura de spi genérica y la podes reutilizar en distintos proyectos.

  Te subo una captura donde se puede ver el circuito, la pantalla del "virtual terminal" con la información del potenciómetro y la información del TC77. También se ve la ventana del "SPI debugger" con la actividad del bus SPI;

  Este es el programa que estoy usando, hay que hacer correcciones para poder trabajar con los decimales y también con los números negativos. Fijate que en la rutina "read_spi();" sí pongo a 1 el tris de SDO y no me tira ningún error. También tuve que modificar la rutina de "setup_sensor" poniendo SMP = 0 en lugar de SMP = 1 porque sino el paquete recibido por el PIC no era correcto.

Código: C
  1. #include <htc.h>
  2. #include <stdlib.h>  // para poder usar la funcion itoa
  3.  
  4.  
  5. /*      =================================================================================
  6.         Definitions
  7.         ================================================================================= */
  8. #define         PORTBIT(adr, bit) ( (unsigned)(&adr)*8 + (bit) )
  9.  
  10. #define         Idle_Low 1      // No envia datos
  11. #define         Idle_High 2 // Envia datos
  12.  
  13. #define true 1
  14. #define false 0
  15.  
  16. #define BAUD  9600                      // Configuramos la velocidad, tanto puede ser 19200 o de 9600 kbaud/s pero hay q cambiarlo tb en la simulacion de proteus      
  17. #define PIC_CLK 4000000         // Clock de 4MHz (Cristal)
  18.  
  19. #define CS RB3
  20.  
  21. /*      =================================================================================
  22.         Global variables  
  23.         ================================================================================= */
  24. //static bit potenciometro @ PORTBIT(PORTA, 0);         // Declaración del potenciometro
  25. //static bit sensor_temperatura @ PORTBIT(PORTB, 0);
  26. //static bit sensor_datos_salida @ PORTBIT(PORTC, 7);  // SD0 disabled in master mode (configuración como entrada)
  27.  
  28.  
  29. static bit LED @ PORTBIT(PORTB, 2);    
  30. char present_state = Idle_Low;          // state variable
  31. char future_state = Idle_Low;           // state variable
  32. unsigned int  valor_potenciometro;
  33. unsigned int  valor_sensor_temperatura;
  34. unsigned char pote_buf[6];
  35. unsigned char sensor_buf[10];
  36. char * valor_pote_en_texto;           // un puntero para almacenar el numero en texto
  37. char * valor_sensor_en_texto;         // un puntero para almacenar el numero en texto
  38. char byte_alto, byte_bajo;
  39. //unsigned char high_result;
  40. //unsigned char low_result;
  41. unsigned char caracter_recibido;       
  42. unsigned char dummy;
  43.  
  44.  
  45. /*      =================================================================================
  46.         Function prototypes
  47.         ================================================================================= */
  48. //static void interrupt service_routine (void); // This is the interrupt service routine
  49.  
  50. void init_system (void);
  51. void time_delay (unsigned int );
  52. char output_logic(void);
  53. char future_state_logic(void);
  54.  
  55. void setup_sensor(void);
  56. void setup_adc(void);
  57. void serial_setup(void);
  58.  
  59. void putst(const char *str);
  60. void putch(unsigned char c);
  61.  
  62. unsigned char getch(void);
  63. unsigned char UsartReadChar_nonstop(void);
  64. unsigned char getch_available(void);
  65. void clear_usart_errors(void);
  66.  
  67. unsigned char read_spi (void);
  68. unsigned int read_adc(void);
  69.  
  70.  
  71.  
  72.  
  73.  
  74.  
  75.  
  76. /*      =================================================================================
  77.         Main function
  78.         ================================================================================= */
  79. void main(void)
  80. {
  81.   valor_potenciometro = 0;
  82.   valor_sensor_temperatura = 0;
  83.   LED = 0;     
  84.   init_system();
  85.   setup_sensor();
  86.   setup_adc();
  87.   serial_setup();      
  88.   while(1)
  89.   {
  90.     CS = 0;
  91.     byte_alto = read_spi();
  92.     byte_bajo = read_spi();
  93.     CS = 1;
  94.     valor_sensor_temperatura = (byte_alto << 8) + byte_bajo;
  95.     valor_sensor_temperatura = valor_sensor_temperatura >> 7;
  96.     //valor_sensor_temperatura = read_spi();  // Las pongo aqui porque es donde hago la lectura de los datos.
  97.     valor_potenciometro = read_adc();
  98.    
  99.     valor_pote_en_texto = itoa (pote_buf, valor_potenciometro, 10);
  100.     valor_sensor_en_texto = itoa (sensor_buf, valor_sensor_temperatura, 10);
  101.     output_logic();
  102.     future_state_logic();
  103.   }            
  104. }      
  105.  
  106. /*      =================================================================================
  107.         Function definitions
  108.         ================================================================================= */
  109.  
  110. //*****************************************************************************
  111. //Future_state_logic routine
  112. //*****************************************************************************
  113. char future_state_logic(void)
  114. {
  115.   char error = 0;
  116.   switch (present_state)
  117.   {
  118.     case Idle_Low:
  119.                  /*                            
  120.                   if ((valor_sensor_temperatura < 20) || (valor_potenciometro < 25))
  121.                   { // Menor de 20ºC o la resistencia menos a 25Kohms
  122.                     //future_state = Idle_High;
  123.                     present_state = Idle_High;
  124.                   }
  125.                   else */
  126.                   if (getch_available() == true) //Si hay un caracter disponible recibido por el puerto serie
  127.                   {
  128.                     caracter_recibido = getch();
  129.                     if (caracter_recibido == 'a')
  130.                     {
  131.                       //future_state = Idle_High;
  132.                       present_state = Idle_High;
  133.                       LED = 1;
  134.                       error = 0;
  135.                     }
  136.                     else
  137.                     {
  138.                       //future_state = Idle_Low;
  139.                       present_state = Idle_Low;
  140.                       LED = 0;
  141.                       error = 1;
  142.                     }
  143.                   }
  144.                   break;
  145.     case Idle_High:                                            
  146.                    if (TXIF == 0)
  147.                    { // Buffer de transmision vacio
  148.                      //future_state = Idle_Low;
  149.                      present_state = Idle_Low;
  150.                    }
  151.                    else
  152.                    {
  153.                      error = 1;
  154.                    }
  155.                    break;
  156.     default:
  157.                           error = 1;
  158.   }    
  159.   return (error);
  160. }
  161.  
  162. //*****************************************************************************
  163. //Output logic routine
  164. //*****************************************************************************
  165. char output_logic(void)
  166. {
  167.   unsigned char error = 1;
  168.   switch (present_state)
  169.   {
  170.     case Idle_Low:                             
  171.                    LED = 0;
  172.                    error = 0;
  173.                    break;
  174.     case Idle_High:                    
  175.                    putst ("Valor del pote: ");
  176.                    putst (valor_pote_en_texto);
  177.                    putst ("\n");  //cambio de linea
  178.                    putst ("Valor del sensor: ");
  179.                    putst (valor_sensor_en_texto);
  180.                    //putst ("Suponemos un valor de 25 grados");
  181.                    putst ("\n");
  182.                    LED = 1;
  183.                    error = 0;
  184.                    break;
  185.     default:
  186.                    error = 1;
  187.                    LED = 0;
  188.                    break;              
  189.   }
  190.   return (error);
  191. }
  192.  
  193. //*****************************************************************************
  194. //Init operations  
  195. //*****************************************************************************
  196. void init_system (void)
  197. {
  198.   //TRISB = 1; //LED. Todos los pines se comportaran como salidas menos RB0 2^0=1
  199.   //TRISA = 32; // SS( Select Slave) must have TRISA<5> bit set
  200.   TRISA = 255;
  201.   CS = 1;
  202.   TRISB = 1; // SDI. El bit 0 a 1.Configurado en master mode (bit 1 cleared, en mode slave bit 1 set)
  203.   TRISC = 192; // SDO. Tots els bits a 1 menys la sortida 7
  204. }
  205.  
  206.  
  207. //*****************************************************************************
  208. //Time delay routine.  
  209. //*****************************************************************************
  210. void time_delay(unsigned int delay)
  211. {
  212.   unsigned int i;
  213.        
  214.   for (i = 0; i <= delay; i++)
  215.   {    
  216.     NOP();
  217.   }
  218. }
  219.  
  220. //*****************************************************************************
  221. // SERIAL SETUP  
  222. //*****************************************************************************
  223. void serial_setup(void)
  224. {
  225.   #define SPBRG_VALUE ((PIC_CLK/(16UL*BAUD)) -1)
  226.   BRGH = 1;
  227.   BRG16 = 0;
  228.   SPBRG = SPBRG_VALUE;
  229.   SPEN = 1; // Enable serial port
  230.   SYNC = 0; // Asincrono
  231.   TXIE = 0; // Desactivar interrupciones en tx
  232.   TXEN = 1; // Enable the transmitter
  233.   TX9 = 0; // 8 bits transmission
  234.   RCIE = 1; // Activar interrupciones en rx
  235.   RX9 = 0; // 8 bits reception
  236.   CREN = 1; //Enable reception
  237.   #define clear_usart_errors_inline     if (OERR)\
  238.                                     {\
  239.                                       TXEN = 0;\
  240.                                       TXEN = 1;\
  241.                                       CREN = 0;\
  242.                                       CREN = 1;\
  243.                                     }\
  244.                                     if (FERR)\
  245.                                     {\
  246.                                       dummy = RCREG;\
  247.                                       TXEN = 0;\
  248.                                       TXEN = 1;\
  249.                                     }
  250. }
  251.  
  252.  
  253. //*****************************************************************************
  254. // Enviar datos ( un caracter)
  255. //*****************************************************************************
  256.  
  257. void putch(unsigned char c)
  258. {
  259.   while (!TXIF)
  260.   {
  261.     clear_usart_errors_inline;
  262.     CLRWDT();
  263.   }
  264.   TXREG = c;
  265. }
  266. //*****************************************************************************
  267. // Enviar datos (un buffer)
  268. //*****************************************************************************
  269. void putst(register const char *str)
  270. {
  271.   while ((*str) != 0)
  272.   {
  273.     putch (*str);
  274.     if (*str == 13) putch (10);
  275.     if (*str == 10) putch (13);
  276.     str++;
  277.   }
  278. }
  279.  
  280. //*****************************************************************************
  281. //Leer datos ( un caracter)
  282. //*****************************************************************************
  283.  
  284. unsigned char getch(void)
  285. {
  286.   while (RCIF != 1)
  287.   {                             //1 = The EUSART receive buffer, RCREG, is full
  288.     CLRWDT();
  289.     clear_usart_errors_inline;
  290.   }
  291.   return RCREG;
  292. }
  293.  
  294. //*****************************************************************************
  295. //Leer datos (un buffer)
  296. //*****************************************************************************
  297. unsigned char UsartReadChar_nonstop(void)
  298. {
  299.   if (!RCIF)    // TRMT1 is set when TSR is empty
  300.     return 0;  
  301.   return RCREG;
  302. }
  303.  
  304.  
  305. //*****************************************************************************
  306. //Comprueba si aun faltan datos o no
  307. //*****************************************************************************
  308. unsigned char getch_available(void)
  309. {
  310.   if (RCIF)
  311.     return true;
  312.   else
  313.     return false;
  314. }
  315.  
  316.  
  317. //*****************************************************************************
  318. //Errores USART
  319. //*****************************************************************************
  320. void clear_usart_errors(void)
  321. {
  322.   clear_usart_errors_inline;
  323. }
  324.  
  325.  
  326. //*****************************************************************************
  327. //Leer entradas.
  328. //*****************************************************************************
  329.  
  330. //*****************************************************************************
  331. //Leer bytes recibidos del bus del modulo SPI
  332. //*****************************************************************************
  333.  
  334. void setup_sensor(void)  // SPI Master mode:
  335. {
  336.   SSPEN = 1;            //Enables serial port and configures SCK, SDO, SDI and SS as serial port pins
  337.   BF = 0;                                                               //Receive not complete, SSPBUF is empty
  338.   //SCK is the clock output (Master Mode)
  339.   //Clock Polarity(Idle state of SCK)
  340.   SMP = 0;                                                       //Input data sampled at end of data output time
  341.   CKE = 0;                                                        //Transmit occurs on transition from Idle to active clock state
  342.   SSPM3 = 0;
  343.   SSPM2 = 0;                                                    //SPI Master mode, clock = FOSC/4      
  344.   SSPM1 = 0;
  345.   SSPM0 = 0;
  346.   CKP = 0;                                                              //Idle state for clock is a low level
  347.   SSPIF = 0;                                                   
  348. }
  349.  
  350. void setup_adc(void)
  351. {
  352.   ADFM = 1;
  353.   ADCON1 = 14;          // PCFG3=1,PCFG2=1,PCFG1=1,PCFG0=0. Todas las entradas digitales
  354.   CHS3 = 0;
  355.   CHS2 = 0;                     // Seleccionamos el canal 0 (AN0) que es donde esta conectado el potenciometro
  356.   CHS1 = 0;
  357.   CHS0 = 0;
  358.   //Tiempo de adquisicion
  359.   ACQT2 = 0;
  360.   ACQT1 = 0;            // 2Tad (Tad=1us) Por tanto 2x1us =2us >= 1.65us( Tacq calculado teoricamente)
  361.   ACQT0 = 1;
  362.   ADCS2 = 1;
  363.   ADCS1 = 0;    // Idem a 4Tosc. 4*Tosc(1us) es el primer valor que hace que sea superior a 0.7us( el minimo)
  364.   ADCS0 = 0;   
  365.   ADON = 1;             // A/D converter module is enabled
  366.   /* Configure A/D interrupt*/
  367.   ADIF = 0;
  368.   //ADIE = 1;
  369. }
  370.  
  371. //*****************************************************************************
  372. //Leer entradas.
  373. //*****************************************************************************
  374.  
  375. //*****************************************************************************
  376. //LEER DATOS SENSOR
  377. //*****************************************************************************
  378. unsigned char read_spi (void)
  379. {
  380. /*
  381.   if ((BF == 1) && (SSPIF == 1))
  382.   {     //Receive complete, SSPBUF is full && The transmission/reception is complete (must be cleared in software)
  383.     SSPIF = 0; ////Waiting to transmit/receive
  384.     BF = 0;
  385.     return SSPBUF;
  386.   }
  387. */
  388.   TRISC7 = 1; // así pongo en alta impedancia el pin SDO
  389.   SSPBUF = 16;
  390.   while (SSPIF == 0);
  391.   SSPIF = 0;
  392.   return SSPBUF;
  393. }
  394.  
  395. //*****************************************************************************
  396. //LEER DATOS POTENCIOMETRO
  397. //*****************************************************************************
  398. unsigned int read_adc(void)
  399. {
  400.   //Empezar a leer
  401.   GODONE = 1; // A/D conversion in progress
  402.   while (GODONE == 1);
  403.   ADIF = 0;
  404.   return ((ADRESH << 8) + (ADRESL));
  405. }


El problema tambien es que el sensor TC77 en proteus tiene 3 pines: cs,sck y una misma entrada para sdi y sdo ( data input y data output..). Como lo conecto entonces?


  A vos no te interesa mandarle datos al TC77, así que simplemente conectás el pin SDI del PIC al pin SI/O del TC77

Título: Re: enviar datos de un sensor de temperatura y de un pot por el puerto serie RS232
Publicado por: edu1989 en 09 de Diciembre de 2010, 08:55:13
Muchas gracias otra vez por la ayuda. El programa funciona perfecto menos cuando arranca. Cuando arranca siempre se envian los datos aunque no se tengan que enviar. Es como si se tardara un tiempo en saber que temperatura es la correcta. Creo que se envian porque al principio el valor del sensor es 0 y tarda un poco en actualizar el valor...pero no se si es exactamente esto porque he probado de inicializar valor_sensor_temperatura con algun valor distinto a 0 y sigue fallando...

A ver si puedes ayudarme...

Gracias de antemano.
Título: Re: enviar datos de un sensor de temperatura y de un pot por el puerto serie RS232
Publicado por: AngelGris en 09 de Diciembre de 2010, 09:10:46
Muchas gracias otra vez por la ayuda. El programa funciona perfecto menos cuando arranca. Cuando arranca siempre se envian los datos aunque no se tengan que enviar. Es como si se tardara un tiempo en saber que temperatura es la correcta. Creo que se envian porque al principio el valor del sensor es 0 y tarda un poco en actualizar el valor...pero no se si es exactamente esto porque he probado de inicializar valor_sensor_temperatura con algun valor distinto a 0 y sigue fallando...

A ver si puedes ayudarme...

Gracias de antemano.

  Lo que pasa es que más allá que vos inicialices el valor, cuando haya una lectura ya va valer 0. Según el SPI debugger eran cerca de 240 ms que transmitía 0 y luego de ese tiempo ya empezaba a envíar los datos correctos el TC77.

  Probá de hacer algún delay de 300ms antes del while y con eso ya le darías tiempo al sensor a que tome el valor correcto.
Título: Re: enviar datos de un sensor de temperatura y de un pot por el puerto serie RS2
Publicado por: edu1989 en 12 de Diciembre de 2010, 14:15:35
Funciona perfectamente! Perdona por contestar tan tarde... he tenido problemas con el Internet..
Mas tarde subo el proyecto entero.

Muchas gracias amigo.
Título: Re: enviar datos de un sensor de temperatura y de un pot por el puerto serie RS232
Publicado por: edu1989 en 13 de Diciembre de 2010, 17:27:59
Hola de nuevo! mañana es un dia clave, voy a probar el programita en el PIC a ver como va.. esperemos que bien! Esperare a tenerlo funcionando en el PIC para subir todo el proyecto entero.
Ahora estoy añadiendo los fuses para que funcione el proyecto. Las lineas de codigo que he añadido han sido estas:
Código: [Seleccionar]
/*
;******** Configuracion del Oscilador **********
CONFIG FOSC = XT_XT         ;Osc XT, XT usado para el USB

;******** Otros bits de configuracion **********
CONFIG PWRT = ON ;PWRT habilitado
CONFIG BOR  = OFF ;Brown out resete deshabilitado
CONFIG WDT = OFF ;Watch dog deshabilitado
CONFIG  MCLRE = OFF ;MCLR como entrada
[b]CONFIG PBADEN = ON [/b];Todos los pines como entradas analogicas
CONFIG LVP = OFF ;programacion en bajo voltaje deshabilitado

;********* Bits de proteccion ******************
CONFIG CP0 = OFF ;los bloques del codigo de programa
CONFIG CP1 = OFF ;no estan protegidos
CONFIG CP2 = OFF
CONFIG CP3 = OFF
CONFIG CPB = OFF ;Sector Boot no esta protegido
CONFIG CPD = OFF ;La EEPROM no esta protegida
*/

Esta todo correcto? Lo que he puesto en negrita es porque no se si esta bien. Por otra parte tengo que configurarlo para que el reloj sea de 4 Mhz no?
Otra cosa.. una gran duda que tengo. Como se hace el cambio de los dispositivos en el proteus a los dispositivos en la placa? me explico, yo tengo programado que un led se vaya encendiendo pero que LED sera de mi placa? igual que el potenciometro.. el sensor.. como asigno cual es cada uno?

Muchas gracias de antemano como siempre :)
Título: Re: enviar datos de un sensor de temperatura y de un pot por el puerto serie RS232
Publicado por: AngelGris en 13 de Diciembre de 2010, 18:51:24
Hola de nuevo! mañana es un dia clave, voy a probar el programita en el PIC a ver como va.. esperemos que bien! Esperare a tenerlo funcionando en el PIC para subir todo el proyecto entero.
Ahora estoy añadiendo los fuses para que funcione el proyecto. Las lineas de codigo que he añadido han sido estas:
Código: [Seleccionar]
/*
;******** Configuracion del Oscilador **********
CONFIG FOSC = XT_XT         ;Osc XT, XT usado para el USB

;******** Otros bits de configuracion **********
CONFIG PWRT = ON ;PWRT habilitado
CONFIG BOR  = OFF ;Brown out resete deshabilitado
CONFIG WDT = OFF ;Watch dog deshabilitado
CONFIG  MCLRE = OFF ;MCLR como entrada
[b]CONFIG PBADEN = ON [/b];Todos los pines como entradas analogicas
CONFIG LVP = OFF ;programacion en bajo voltaje deshabilitado

;********* Bits de proteccion ******************
CONFIG CP0 = OFF ;los bloques del codigo de programa
CONFIG CP1 = OFF ;no estan protegidos
CONFIG CP2 = OFF
CONFIG CP3 = OFF
CONFIG CPB = OFF ;Sector Boot no esta protegido
CONFIG CPD = OFF ;La EEPROM no esta protegida
*/

Esta todo correcto? Lo que he puesto en negrita es porque no se si esta bien. Por otra parte tengo que configurarlo para que el reloj sea de 4 Mhz no?
Otra cosa.. una gran duda que tengo. Como se hace el cambio de los dispositivos en el proteus a los dispositivos en la placa? me explico, yo tengo programado que un led se vaya encendiendo pero que LED sera de mi placa? igual que el potenciometro.. el sensor.. como asigno cual es cada uno?

Muchas gracias de antemano como siempre :)

  Por lo que estuve leyendo en el datasheet PBADEN sólo afecta respecto a como quedan los pines inmediatamente después de un RESET. Pero si vos lo configurás después (que es lo que hacés en la rutina de inicialización del AD), los pines se van a comportar de acuerdo a la nueva configuración.

  Si el reloj hay que configurarlo para que sea 4MHz. Vos ya estás poniendo que sea XT (porque supongo vas a usar un cristal de 4MHz) entonces tendrías que configurar los bits CPUDIV (tendrían que quedar en 0 para que pase la señal de 4MHz sin ninguna división), también los bits FOSC (que también tendrían que quedar en 0 para se use el oscilador externo XT). Fijate a partir de la página 286 que tiene la descripción de los bytes de configuración.

  No entiendo a lo que te referís con "el cambio de los dispositivos en el proteus".

  ¿Vos vas a probar el PIC en una placa entrenadora?

  Supongamos que tu placa tiene un led que va al puerto RB6, entonces habría que modificar el programa para que active dicha salida cuando vos quieras prender el led.
  También hay que ver a que puerto va el pote que tenga tu placa. Si va a AN5, habrá que setear dicho canal desde el programa del pic para que haga las lecturas analógicas.
Título: Re: enviar datos de un sensor de temperatura y de un pot por el puerto serie RS2
Publicado por: edu1989 en 13 de Diciembre de 2010, 19:00:19
Gracias, ahora mirare lo de la configuracion del cristal y de los 4Mhz.

A lo que me refiero es que lo grabare en mi placa PICDEM  Aqui! (http://www.microchip.com/stellent/idcplg?IdcService=SS_GET_PAGE&nodeId=1406&dDocName=en021940)

Lo que no entiendo es como relacionar el LED que yo tengo conectado al puerto RB0 por ejemplo con el LED1 de mi placa.

Gracias de antemano.
Título: Re: enviar datos de un sensor de temperatura y de un pot por el puerto serie RS2
Publicado por: AngelGris en 13 de Diciembre de 2010, 19:13:18
Gracias, ahora mirare lo de la configuracion del cristal y de los 4Mhz.

A lo que me refiero es que lo grabare en mi placa PICDEM  Aqui! (http://www.microchip.com/stellent/idcplg?IdcService=SS_GET_PAGE&nodeId=1406&dDocName=en021940)

Lo que no entiendo es como relacionar el LED que yo tengo conectado al puerto RB0 por ejemplo con el LED1 de mi placa.

Gracias de antemano.

  Supongo que en el manual de la placa debería decirlo. Si en el manual dice que el Led 3 de tu placa está conectado a RB5, vas a tener que cambiar el programa para que al led lo maneje RB5.
  De hecho en la descripción del link que vos dejaste dice por ejemplo, que el potenciómetro, está conectado a RA0 (que es AN0).
Título: Re: enviar datos de un sensor de temperatura y de un pot por el puerto serie RS2
Publicado por: edu1989 en 13 de Diciembre de 2010, 19:52:33
Que tonteria! muchas gracias! ya lo entiendo todo, a ver como va mañana.

Un abrazo y gracias.
Título: Re: enviar datos de un sensor de temperatura y de un pot por el puerto serie RS232
Publicado por: edu1989 en 14 de Diciembre de 2010, 06:27:58
Hola de nuevo:
Les cuento, he probado de enviar datos desde proteus( con el compim) a otro PC y a funcionado perfectamente.
Ahora he cambiado el cable que unia los dos PC por Bluetooth. He conectado un modulo a un pc y el otro al otro pc. He hecho la conexion y lo que escribo en el terminal de PC1 lo veo en el PC2 y viceversa pero cuando lo simulo ( tambien con el compim claro) no envia los datos al PC2. No me permite tener el programa corriendo y el terminal del PC1 abierto.

He utilitzado un programa que crea un puerto virtual entre el compim y el terminal del PC1 ( para que envies los datos al terminal), lo que me gustaria hacer es ya tener la conexion hecha y cuando haga este puerto virtual que saliese automaticamente en el PC2.

El problema es que si establezco conexion entre pc1 y pc2 no puedo utilitzar compim. Alguna idea?
_________________________________________________________________________________________________________________________________
Por otro lado estoy configurando los fuses del PIC y me salen errores. A partir de un ejemplo de un pic16XXXXX he visto que lo hacia asi:
Código: [Seleccionar]
__CONFIG(WDTDIS & XT & UNPROTECT& PWRTEN &LVPDIS & DUNPROT & WRTEN & UNPROTECT & BOREN &DEBUGDIS);

Por lo que yo he configurado los fuses de la siguiente manera:
Código: [Seleccionar]
// WDTDIS: Watchdog disabled;
WDTEN=0;

// XT: --> crystal 4MHz;
CPUDIV1=0;
CPUDIV0=0;  // Primary oscillator used directly for system clock

FOSC3=0;
FOSC2=0;   // XT Oscillator (XT)
FOSC1=0;
FOSC0=0;



// UNPROTECT: unprotected code;
CP3=1;
CP2=1;
CP1=1;
CP0=1;
CPD=1;
CPB=1;

// PWRTEN: Power UP timer enabled;
PWRTEN=0;

// LVPDIS: Low voltage programming disabled;
LVP=0;

Gracias de antemano.
Título: Re: enviar datos de un sensor de temperatura y de un pot por el puerto serie RS232
Publicado por: AngelGris en 14 de Diciembre de 2010, 10:20:52
_________________________________________________________________________________________________________________________________
Por otro lado estoy configurando los fuses del PIC y me salen errores. A partir de un ejemplo de un pic16XXXXX he visto que lo hacia asi:
Código: [Seleccionar]
__CONFIG(WDTDIS & XT & UNPROTECT& PWRTEN &LVPDIS & DUNPROT & WRTEN & UNPROTECT & BOREN &DEBUGDIS);

Por lo que yo he configurado los fuses de la siguiente manera:
Código: [Seleccionar]
// WDTDIS: Watchdog disabled;
WDTEN=0;

// XT: --> crystal 4MHz;
CPUDIV1=0;
CPUDIV0=0;  // Primary oscillator used directly for system clock

FOSC3=0;
FOSC2=0;   // XT Oscillator (XT)
FOSC1=0;
FOSC0=0;



// UNPROTECT: unprotected code;
CP3=1;
CP2=1;
CP1=1;
CP0=1;
CPD=1;
CPB=1;

// PWRTEN: Power UP timer enabled;
PWRTEN=0;

// LVPDIS: Low voltage programming disabled;
LVP=0;

Gracias de antemano.

  Con respecto al tema del bluetooth no puedo ayudarte ya que no experimenté nada de nada.

  Con respecto a la configuración de los FUSES, sí hay que usar la forma

Código: C
  1. __CONFIG(x, ..........)

  Siendo x el número de palabra que querés configurar.
Para saber que parámetros se pueden usar dentro de cada palabra tenés que leer el archivo .h correspondiente al pic que quieras usar, en tu caso PIC18F4550.h

  Un ejemplo sería....

Código: C
  1. __CONFIG(1, CPUDIV1 & PLLDIV1 & IESODIS & FCMDIS);  // palabra de configuracion 1
  2. __CONFIG(2, VREGDIS & PWRTEN & WDTDIS); // palabra de configuracion 2
  3. __CONFIG(3, PBADEN & MCLRDIS);

Título: Re: enviar datos de un sensor de temperatura y de un pot por el puerto serie RS232
Publicado por: edu1989 en 14 de Diciembre de 2010, 16:00:00
Muchas gracias! Al final lo he puesto de esta manera, a ver que te parece.

Código: [Seleccionar]
__CONFIG(1, CPUDIV1 & PLLDIV1 & XT & FCMDIS);  
__CONFIG(2, VREGDIS & PWRTEN & WDTDIS);
__CONFIG(3, PBADEN & MCLRDIS);
__CONFIG(4,LVPDIS & ICPORTEN & DEBUGEN);
__CONFIG(5,UNPROTECT);
__CONFIG(6,UNPROTECT);
__CONFIG(7,UNPROTECT);



Por otro lado, voy a grabar el programa a ver si funciona... el tema de los pins creo que ya esta bien porque para hacer la simulacion mire la tabla donde ponia como conectarlo. Subo el programa:

Código: [Seleccionar]
#include <htc.h>
#include <stdlib.h>  // para poder usar la funcion itoa
#include <pic18.h>
 
/* =================================================================================
Definitions
    ================================================================================= */
#define PORTBIT(adr, bit) ( (unsigned)(&adr)*8 + (bit) )
 
#define Idle_Low 1 // No envia datos
#define Idle_High 2 // Envia datos
 
#define true 1
#define false 0
 
#define BAUD  9600 // Configuramos la velocidad, tanto puede ser 19200 o de 9600 kbaud/s pero hay q cambiarlo tb en la simulacion de proteus
#define PIC_CLK 4000000 // Clock de 4MHz (Cristal)
 
#define CS RB3
 


/* =================================================================================
Global variables 
  ================================================================================= */
//static bit potenciometro @ PORTBIT(PORTA, 0); // Declaración del potenciometro
//static bit sensor_temperatura @ PORTBIT(PORTB, 0);
//static bit sensor_datos_salida @ PORTBIT(PORTC, 7);  // SD0 disabled in master mode (configuración como entrada)
 
static bit LED @ PORTBIT(PORTB, 2);
char present_state = Idle_Low; // state variable
char future_state = Idle_Low; // state variable
unsigned int  valor_potenciometro;
unsigned int  valor_sensor_temperatura;
unsigned char pote_buf[6];
unsigned char sensor_buf[10];
char * valor_pote_en_texto;           // un puntero para almacenar el numero en texto
char * valor_sensor_en_texto;         // un puntero para almacenar el numero en texto
char byte_alto, byte_bajo;

unsigned char caracter_recibido;
unsigned char dummy;
 



/* =================================================================================
Function prototypes
    ================================================================================= */
//static void interrupt service_routine (void); // This is the interrupt service routine
 
void init_system (void);
void time_delay (unsigned int );
char output_logic(void);
char future_state_logic(void);

void setup_sensor(void);
void setup_adc(void);
void serial_setup(void);
 
void putst(const char *str);
void putch(unsigned char c);

unsigned char getch(void);
unsigned char UsartReadChar_nonstop(void);
unsigned char getch_available(void);
void clear_usart_errors(void);

unsigned char read_spi (void);
unsigned int read_adc(void);

 
 
/* =================================================================================
Main function
  ================================================================================= */
void main(void)
{
  valor_potenciometro = 0;
  valor_sensor_temperatura = 0;
  LED = 0;
  init_system();
  setup_sensor();
  setup_adc();
  serial_setup();
 
time_delay(30000);
while(1)
  {
    CS = 0;
    byte_alto = read_spi();
    byte_bajo = read_spi();
    CS = 1;
    valor_sensor_temperatura = (byte_alto << 8) + byte_bajo;
    valor_sensor_temperatura = valor_sensor_temperatura >> 7;
    //valor_sensor_temperatura = read_spi();  // Las pongo aqui porque es donde hago la lectura de los datos.
    valor_potenciometro = read_adc();
   
    valor_pote_en_texto = itoa (pote_buf, valor_potenciometro, 10);
    valor_sensor_en_texto = itoa (sensor_buf, valor_sensor_temperatura, 10);
   
output_logic();
    future_state_logic();
 
}
}

/* =================================================================================
Function definitions
  ================================================================================= */

//*****************************************************************************
//Future_state_logic routine
//*****************************************************************************
char future_state_logic(void)
{
  char error = 0;
  switch (present_state)
  {
    case Idle_Low:
                 
                  if ((valor_sensor_temperatura < 20) || (valor_potenciometro < 25))
                 { // Menor de 20ºC o la resistencia menos a 25Kohms
                    //future_state = Idle_High;
                    present_state = Idle_High;
                 }
                  else
                  if (getch_available() == true) //Si hay un caracter disponible recibido por el puerto serie
                  {
                    caracter_recibido = getch();
                    if (caracter_recibido == 'a')
                    {
                      present_state = Idle_High;
                    }
                    else
                    {
                     
                      present_state = Idle_Low;
                      error = 1;
                    }
                 }
                  break;
    case Idle_High:
                   if (TXIF == 0)
                   { // Buffer de transmision vacio
                     //future_state = Idle_Low;
                     present_state = Idle_Low;
                   }
                   else
                   {
                     error = 1;
                   }
                   break;
    default:
  error = 1;
  }
  return (error);
}

//*****************************************************************************
//Output logic routine
//*****************************************************************************
char output_logic(void)
{
  unsigned char error = 1;
  switch (present_state)
  {
    case Idle_Low:
                   LED = 0;
                   error = 0;
                   break;
    case Idle_High:
                   putst ("\n");
   putst ("Valor del pote: ");
                   putst (valor_pote_en_texto);
                   putst ("\n");  //cambio de linea
                   putst ("Valor del sensor: ");
                   putst (valor_sensor_en_texto);
                   //putst ("Suponemos un valor de 25 grados");
                   putst ("\n");
                   LED = 1;
                   error = 0;
                   break;
    default:
                   error = 1;
                   LED = 0;
                   break;
  }
  return (error);
}

//*****************************************************************************
//Init operations 
//*****************************************************************************
void init_system (void)
{
 
__CONFIG(1, CPUDIV1 & PLLDIV1 & XT & FCMDIS); 
__CONFIG(2, VREGDIS & PWRTEN & WDTDIS);
__CONFIG(3, PBADEN & MCLRDIS);
__CONFIG(4,LVPDIS & ICPORTEN & DEBUGEN);
__CONFIG(5,UNPROTECT);
__CONFIG(6,UNPROTECT);
__CONFIG(7,UNPROTECT);


//TRISB = 1; //LED. Todos los pines se comportaran como salidas menos RB0 2^0=1
  //TRISA = 32; // SS( Select Slave) must have TRISA<5> bit set
   TRISA = 255;
  CS = 1;
  TRISB = 1; // SDI. El bit 0 a 1.Configurado en master mode (bit 1 cleared, en mode slave bit 1 set)
  TRISC = 192; // SDO. Tots els bits a 1 menys la sortida 7
}

 
//*****************************************************************************
//Time delay routine.   
//*****************************************************************************
void time_delay(unsigned int delay)
{
  unsigned int i;

  for (i = 0; i <= delay; i++)
  {
    NOP();
  }
}
 
//*****************************************************************************
// SERIAL SETUP 
//*****************************************************************************
void serial_setup(void)
{
  #define SPBRG_VALUE ((PIC_CLK/(16UL*BAUD)) -1)
  BRGH = 1;
  BRG16 = 0;
  SPBRG = SPBRG_VALUE;
  SPEN = 1; // Enable serial port
  SYNC = 0; // Asincrono
  TXIE = 0; // Desactivar interrupciones en tx
  TXEN = 1; // Enable the transmitter
  TX9 = 0; // 8 bits transmission
  RCIE = 1; // Activar interrupciones en rx
  RX9 = 0; // 8 bits reception
  CREN = 1; //Enable reception
  #define clear_usart_errors_inline if (OERR)\
                                   {\
                                      TXEN = 0;\
                                      TXEN = 1;\
                                      CREN = 0;\
                                      CREN = 1;\
                                    }\
                                   if (FERR)\
                                  {\
                                     dummy = RCREG;\
                                      TXEN = 0;\
                                      TXEN = 1;\
                                    }
}
 
 
//*****************************************************************************
// Enviar datos ( un caracter)
//*****************************************************************************
 
void putch(unsigned char c)
{
  while (!TXIF)
  {
    clear_usart_errors_inline;
    CLRWDT();
  }
  TXREG = c;
}
//*****************************************************************************
// Enviar datos (un buffer)
//*****************************************************************************
void putst(register const char *str)
{
  while ((*str) != 0)
  {
    putch (*str);
    if (*str == 13) putch (10);
    if (*str == 10) putch (13);
    str++;
  }
}


//*****************************************************************************
//Leer datos ( un caracter)
//*****************************************************************************
 
unsigned char getch(void)
{
  while (RCIF != 1)
 { //1 = The EUSART receive buffer, RCREG, is full
    CLRWDT();
    clear_usart_errors_inline;
  }
  return RCREG;
}
 
//*****************************************************************************
//Leer datos (un buffer)
//*****************************************************************************
unsigned char UsartReadChar_nonstop(void)
{
  if (!RCIF)
    return 0;   
 return RCREG;
}
 
 
//*****************************************************************************
//Comprueba si aun faltan datos o no
//*****************************************************************************
unsigned char getch_available(void)
{
  if (RCIF)
    return true;
  else
    return false;
}
 
 
//*****************************************************************************
//Errores USART
//*****************************************************************************
void clear_usart_errors(void)
{
  clear_usart_errors_inline;
}
 

//*****************************************************************************
//Leer entradas.
//*****************************************************************************
 
//*****************************************************************************
//Leer bytes recibidos del bus del modulo SPI
//*****************************************************************************
 
void setup_sensor(void)  // SPI Master mode:
{
  SSPEN = 1; //Enables serial port and configures SCK, SDO, SDI and SS as serial port pins
  BF = 0;        //Receive not complete, SSPBUF is empty
  //SCK is the clock output (Master Mode)
  //Clock Polarity(Idle state of SCK)
  SMP = 0;      //Input data sampled at end of data output time
  CKE = 0;      //Transmit occurs on transition from Idle to active clock state
  SSPM3 = 0;
 SSPM2 = 0; //SPI Master mode, clock = FOSC/4
  SSPM1 = 0;
  SSPM0 = 0;
  CKP = 0; //Idle state for clock is a low level
  SSPIF = 0;   
}
 
void setup_adc(void)
{
  ADFM = 1;
  ADCON1 = 14; // PCFG3=1,PCFG2=1,PCFG1=1,PCFG0=0. Todas las entradas digitales
  CHS3 = 0;
  CHS2 = 0; // Seleccionamos el canal 0 (AN0) que es donde esta conectado el potenciometro
  CHS1 = 0;
  CHS0 = 0;
  //Tiempo de adquisicion
  ACQT2 = 0;
  ACQT1 = 0;  // 2Tad (Tad=1us) Por tanto 2x1us =2us >= 1.65us( Tacq calculado teoricamente)
  ACQT0 = 1;
  ADCS2 = 1;
  ADCS1 = 0;    // Idem a 4Tosc. 4*Tosc(1us) es el primer valor que hace que sea superior a 0.7us( el minimo)
  ADCS0 = 0;
  ADON = 1; // A/D converter module is enabled
  /* Configure A/D interrupt*/
  ADIF = 0;
  //ADIE = 1;
}
 
//*****************************************************************************
//Leer entradas.
//*****************************************************************************
 
//*****************************************************************************
//LEER DATOS SENSOR
//*****************************************************************************
unsigned char read_spi (void)
{
/*
  if ((BF == 1) && (SSPIF == 1))
  { //Receive complete, SSPBUF is full && The transmission/reception is complete (must be cleared in software)
    SSPIF = 0; ////Waiting to transmit/receive
    BF = 0;
    return SSPBUF;
 }
*/
  TRISC7 = 1; // así pongo en alta impedancia el pin SDO
  SSPBUF = 16;
  while (SSPIF == 0);
  SSPIF = 0;
  return SSPBUF;
}
 
//*****************************************************************************
//LEER DATOS POTENCIOMETRO
//*****************************************************************************
unsigned int read_adc(void)
{
  //Empezar a leer
  GODONE = 1; // A/D conversion in progress
  while (GODONE == 1);
  ADIF = 0;
  return ((ADRESH << 8) + (ADRESL));
}

Gracias!
Título: Re: enviar datos de un sensor de temperatura y de un pot por el puerto serie RS232
Publicado por: AngelGris en 14 de Diciembre de 2010, 16:18:34
  Creo que la línea

Código: C
  1. #include <pic18.h>

no es necesaria. En teoría basta con incluir htc.h sólamente.

  Y las líneas "__CONFIG(.....)" yo las pondría inmediatamente después de "#include <htc.h>" o a lo sumo después de todos los #include iniciales.

Código: C
  1. #include <htc.h>
  2. #include <stdlib.h>
  3. __CONFIG (......);
  4. __CONFIG (......);
  5. ....
  6. ....
Título: Re: enviar datos de un sensor de temperatura y de un pot por el puerto serie RS2
Publicado por: edu1989 en 14 de Diciembre de 2010, 16:20:21
De acuerdo. Gracias.
El grabador icd2 que tal funciona? voy a probarlo immediatamente...

Edito: Voy a grabar de la forma siguiente:

Conectar la alimentacion al icd2
Conecta el icd2 con el pic mediante el cable de red
Conectar el PIC al USB del ordenador

Necesito tambien conectar el usb del icd2 al ordenador? creo que eso es solo para alimentar al icd2 a partir del usb..
Pregunto porque no me gustaria fastidiarla en esto.. no es mio el material y... en fin hay que ir con cuidado :)

Edito: Estoy haciendo pruebas y cuando hago el paso previo antes de grabar "Programmable , Blank Check" me sale un error:
Verify failed(MemType=Program,Address=0x0, Expected Val=0xFFFF, Val Read=0xEE00)
Gracias
Título: Re: enviar datos de un sensor de temperatura y de un pot por el puerto serie RS2
Publicado por: AngelGris en 14 de Diciembre de 2010, 18:49:18
De acuerdo. Gracias.
El grabador icd2 que tal funciona? voy a probarlo immediatamente...

Edito: Voy a grabar de la forma siguiente:

Conectar la alimentacion al icd2
Conecta el icd2 con el pic mediante el cable de red
Conectar el PIC al USB del ordenador

Necesito tambien conectar el usb del icd2 al ordenador? creo que eso es solo para alimentar al icd2 a partir del usb..
Pregunto porque no me gustaria fastidiarla en esto.. no es mio el material y... en fin hay que ir con cuidado :)

Edito: Estoy haciendo pruebas y cuando hago el paso previo antes de grabar "Programmable , Blank Check" me sale un error:
Verify failed(MemType=Program,Address=0x0, Expected Val=0xFFFF, Val Read=0xEE00)
Gracias

  Me pareció leer, en el enlace que dejaste respecto de la placa que vas a usar, que dicha placa tiene un micro incorporado y dicho micro viene pregrabado con un programita y un bootloader. Los bootloader son programas que están en los micros y se usan para regrabar los mismos a travez de puerto serie o  usb, así que no sé si será necesario usar un grabador...
  Yo sólo tengo un grabador por puerto paralelo, y no conozco el ICD.

  Me parece que vas a tener que leerte todos los documentos que encuetres respecto de esa placa, para saber como programar el micro sin causar ningún daño.
Título: Re: enviar datos de un sensor de temperatura y de un pot por el puerto serie RS232
Publicado por: edu1989 en 14 de Diciembre de 2010, 18:51:09
Se puede usar el implab icd2 tambien. Has utilitzado alguna vez el ICD2?

Edito: El datasheet lo puedes ver Aqui (http://www.microchip.com/stellent/idcplg?IdcService=SS_GET_PAGE&nodeId=1406&dDocName=en021940)
Es mejor usar el bootloader?
Título: Re: enviar datos de un sensor de temperatura y de un pot por el puerto serie RS232
Publicado por: AngelGris en 14 de Diciembre de 2010, 18:55:47
  No, los únicos programadores que use fueron el JDM y el ProPic2.
Título: Re: enviar datos de un sensor de temperatura y de un pot por el puerto serie RS232
Publicado por: edu1989 en 14 de Diciembre de 2010, 19:11:38
He estado leyendo y tengo dos opciones, seguir programando con ICD2 o volver a reprogramar con el programa que venia y asi poder usar el Bootloader. Como vuelvo a poner el programa en el pic? dice que esta en la carpeta MCHPFSUSB\fw\_factory_hex\ pero que hay que reprogramarlo con un conector ICD

Edito: Voy a seguir con el ICD2. Lo que hay que resolver es el siguiente error que antes he comentado. Verify failed(MemType=Program,Address=0x0, Expected Val=0xFFFF, Val Read=0xEE00)

Edito1: Mejor voy a abrir un post nuevo que esto se va del tema...

Muchas gracias de antemano, a ver si alguien puede ayudarme
Título: Re: enviar datos de un sensor de temperatura y de un pot por el puerto serie RS232
Publicado por: AngelGris en 14 de Diciembre de 2010, 19:57:24
  En la sección 5.2.3 de la guia de usuario dice.

5.2.3
ICSP/ICD Configuration
Using the MPLAB IDE and MPLAB ICD 2, users can reprogram the board’s
microcontroller using In-Circuit Serial Programming™ (ICSP™), and debug firmware
code using In-Circuit Debugger. The RJ-11 receptacle (J3), also known as the
ICSP/ICD connector, is the standard MPLAB ICD 2 interface found on most Microchip
development boards.
Most PIC18 microcontrollers only have one legacy ICSP/ICD port, which shares I/O
pins RB6 and RB7. When used, the legacy port prevents applications from using these
pins as normal I/O ports. The 44-pin TQFP version of the PIC18F4550 is the only vari-
ant of the full-speed USB family of devices to have a second ICSP/ICD port on pins not
used for I/O. This dedicated port allows RB6 and RB7 to be utilized by the user’s
application.
The PICDEM FS USB board can be configured to work with either the legacy or dedi-
cated port by using jumpers, JP14 through JP16. As shipped, the demonstration board
is hardware-configured for the legacy port. To change this, the user must cut the traces
indicated in Figure 5-1 (item 14), and install pins and box jumpers. When installed, the
ICD connector is configured by the jumpers as shown in Table 5-2.
In addition to setting the jumpers, the ICPRT Configuration bit in CONFIG4L must also
be properly set. To enable the dedicated ICSP/ICD port, ICPRT must be set (= 1).
When the board is configured to use the dedicated ICSP/ICD port, the Reset switch,
S1, will no longer function. The ICRST pin acts only as an active-high Reset port, which
works when the MPLAB ICD 2 sends a high-voltage programming signal, (VIHH). The
MCLR pin acts as both active-low and active-high Reset ports. Thus, the Reset switch,
S1, only works when connected to the MCLR pin.
Additional information regarding the dedicated ICSP/ICD port can be found in the
“Special Features” section of the device data sheet (DS39632).

TABLE 5-2:
JUMPER CONFIGURATION FOR THE ICSP™/ICD CONNECTOR

ICD Connector Configuration                      JP14          JP15          J16
Legacy ICD (CHP_MCLR/RB7/RB6)            Pins 1-2     Pins 1-2    Pins 1-2
Dedicated Port (ICRST/ICPGD/ICPGC)      Pins 2-3     Pins 2-3    Pins 2-3

Note
1: For JP14 through JP16, pin 1 is the location closest to the microcontroller.
2: Before using the ICD connector for programming or debugging, verify
    that all three jumpers are set correctly. Failure to do so may result in
     programming or debugger failure.
Título: Re: enviar datos de un sensor de temperatura y de un pot por el puerto serie RS232
Publicado por: edu1989 en 14 de Diciembre de 2010, 20:06:34
No entiendo que quieres decirme con esto... lo siento
He conseguido grabar pero debo estar haciendo algo mal seguro..

A ver si puedes explicarme que quieres decir con eso por favor
Gracias.

Edito: Estoy debugando y me salen dos errores:
ICD0083: Debug:  Unable to enter debug mode.  Please double click this message for more information.
ICD0069: Debug:  Unable to run target

Adjunto codigo:
Código: [Seleccionar]
#include <htc.h>
#include <stdlib.h>  // para poder usar la funcion itoa
__CONFIG(1, CPUDIV1 & PLLDIV1 & XT & FCMDIS); 
__CONFIG(2, VREGDIS & PWRTEN & WDTDIS);
__CONFIG(3, PBADEN & MCLRDIS);
__CONFIG(4,LVPDIS & ICPORTEN & DEBUGEN);
__CONFIG(5,UNPROTECT);
__CONFIG(6,UNPROTECT);
__CONFIG(7,UNPROTECT);
 
/* =================================================================================
Definitions
    ================================================================================= */
#define PORTBIT(adr, bit) ( (unsigned)(&adr)*8 + (bit) )
 
#define Idle_Low 1 // No envia datos
#define Idle_High 2 // Envia datos
 
#define true 1
#define false 0
 
#define BAUD  9600 // Configuramos la velocidad, tanto puede ser 19200 o de 9600 kbaud/s pero hay q cambiarlo tb en la simulacion de proteus
#define PIC_CLK 4000000 // Clock de 4MHz (Cristal)
 
#define CS RB3
 


/* =================================================================================
Global variables 
  ================================================================================= */
//static bit potenciometro @ PORTBIT(PORTA, 0); // Declaración del potenciometro
//static bit sensor_temperatura @ PORTBIT(PORTB, 0);
//static bit sensor_datos_salida @ PORTBIT(PORTC, 7);  // SD0 disabled in master mode (configuración como entrada)
 
static bit LED @ PORTBIT(PORTB, 2);
char present_state = Idle_Low; // state variable
char future_state = Idle_Low; // state variable
unsigned int  valor_potenciometro;
unsigned int  valor_sensor_temperatura;
unsigned char pote_buf[6];
unsigned char sensor_buf[10];
char * valor_pote_en_texto;           // un puntero para almacenar el numero en texto
char * valor_sensor_en_texto;         // un puntero para almacenar el numero en texto
char byte_alto, byte_bajo;

unsigned char caracter_recibido;
unsigned char dummy;
 



/* =================================================================================
Function prototypes
    ================================================================================= */
//static void interrupt service_routine (void); // This is the interrupt service routine
 
void init_system (void);
void time_delay (unsigned int );
char output_logic(void);
char future_state_logic(void);

void setup_sensor(void);
void setup_adc(void);
void serial_setup(void);
 
void putst(const char *str);
void putch(unsigned char c);

unsigned char getch(void);
unsigned char UsartReadChar_nonstop(void);
unsigned char getch_available(void);
void clear_usart_errors(void);

unsigned char read_spi (void);
unsigned int read_adc(void);

 
 
/* =================================================================================
Main function
  ================================================================================= */
void main(void)
{
  valor_potenciometro = 0;
  valor_sensor_temperatura = 0;
  LED = 0;
  init_system();
  setup_sensor();
  setup_adc();
  serial_setup();
 
time_delay(30000);
while(1)
  {
    CS = 0;
    byte_alto = read_spi();
    byte_bajo = read_spi();
    CS = 1;
    valor_sensor_temperatura = (byte_alto << 8) + byte_bajo;
    valor_sensor_temperatura = valor_sensor_temperatura >> 7;
    //valor_sensor_temperatura = read_spi();  // Las pongo aqui porque es donde hago la lectura de los datos.
    valor_potenciometro = read_adc();
   
    valor_pote_en_texto = itoa (pote_buf, valor_potenciometro, 10);
    valor_sensor_en_texto = itoa (sensor_buf, valor_sensor_temperatura, 10);
   
output_logic();
    future_state_logic();
 
}
}

/* =================================================================================
Function definitions
  ================================================================================= */

//*****************************************************************************
//Future_state_logic routine
//*****************************************************************************
char future_state_logic(void)
{
  char error = 0;
  switch (present_state)
  {
    case Idle_Low:
                 
                  if ((valor_sensor_temperatura < 20) || (valor_potenciometro < 25))
                 { // Menor de 20ºC o la resistencia menos a 25Kohms
                    //future_state = Idle_High;
                    present_state = Idle_High;
                 }
                  else
                  if (getch_available() == true) //Si hay un caracter disponible recibido por el puerto serie
                  {
                    caracter_recibido = getch();
                    if (caracter_recibido == 'a')
                    {
                      present_state = Idle_High;
                    }
                    else
                    {
                     
                      present_state = Idle_Low;
                      error = 1;
                    }
                 }
                  break;
    case Idle_High:
                   if (TXIF == 0)
                   { // Buffer de transmision vacio
                     //future_state = Idle_Low;
                     present_state = Idle_Low;
                   }
                   else
                   {
                     error = 1;
                   }
                   break;
    default:
  error = 1;
  }
  return (error);
}

//*****************************************************************************
//Output logic routine
//*****************************************************************************
char output_logic(void)
{
  unsigned char error = 1;
  switch (present_state)
  {
    case Idle_Low:
                   LED = 0;
                   error = 0;
                   break;
    case Idle_High:
                   putst ("\n");
   putst ("Valor del pote: ");
                   putst (valor_pote_en_texto);
                   putst ("\n");  //cambio de linea
                   putst ("Valor del sensor: ");
                   putst (valor_sensor_en_texto);
                   //putst ("Suponemos un valor de 25 grados");
                   putst ("\n");
                   LED = 1;
                   error = 0;
                   break;
    default:
                   error = 1;
                   LED = 0;
                   break;
  }
  return (error);
}

//*****************************************************************************
//Init operations 
//*****************************************************************************
void init_system (void)
{
 
//TRISB = 1; //LED. Todos los pines se comportaran como salidas menos RB0 2^0=1
  //TRISA = 32; // SS( Select Slave) must have TRISA<5> bit set
   TRISA = 255;
  CS = 1;
  TRISB = 1; // SDI. El bit 0 a 1.Configurado en master mode (bit 1 cleared, en mode slave bit 1 set)
  TRISC = 192; // SDO. Tots els bits a 1 menys la sortida 7
}

 
//*****************************************************************************
//Time delay routine.   
//*****************************************************************************
void time_delay(unsigned int delay)
{
  unsigned int i;

  for (i = 0; i <= delay; i++)
  {
    NOP();
  }
}
 
//*****************************************************************************
// SERIAL SETUP 
//*****************************************************************************
void serial_setup(void)
{
  #define SPBRG_VALUE ((PIC_CLK/(16UL*BAUD)) -1)
  BRGH = 1;
  BRG16 = 0;
  SPBRG = SPBRG_VALUE;
  SPEN = 1; // Enable serial port
  SYNC = 0; // Asincrono
  TXIE = 0; // Desactivar interrupciones en tx
  TXEN = 1; // Enable the transmitter
  TX9 = 0; // 8 bits transmission
  RCIE = 1; // Activar interrupciones en rx
  RX9 = 0; // 8 bits reception
  CREN = 1; //Enable reception
  #define clear_usart_errors_inline if (OERR)\
                                   {\
                                      TXEN = 0;\
                                      TXEN = 1;\
                                      CREN = 0;\
                                      CREN = 1;\
                                    }\
                                   if (FERR)\
                                  {\
                                     dummy = RCREG;\
                                      TXEN = 0;\
                                      TXEN = 1;\
                                    }
}
 
 
//*****************************************************************************
// Enviar datos ( un caracter)
//*****************************************************************************
 
void putch(unsigned char c)
{
  while (!TXIF)
  {
    clear_usart_errors_inline;
    CLRWDT();
  }
  TXREG = c;
}
//*****************************************************************************
// Enviar datos (un buffer)
//*****************************************************************************
void putst(register const char *str)
{
  while ((*str) != 0)
  {
    putch (*str);
    if (*str == 13) putch (10);
    if (*str == 10) putch (13);
    str++;
  }
}


//*****************************************************************************
//Leer datos ( un caracter)
//*****************************************************************************
 
unsigned char getch(void)
{
  while (RCIF != 1)
 { //1 = The EUSART receive buffer, RCREG, is full
    CLRWDT();
    clear_usart_errors_inline;
  }
  return RCREG;
}
 
//*****************************************************************************
//Leer datos (un buffer)
//*****************************************************************************
unsigned char UsartReadChar_nonstop(void)
{
  if (!RCIF)
    return 0;   
 return RCREG;
}
 
 
//*****************************************************************************
//Comprueba si aun faltan datos o no
//*****************************************************************************
unsigned char getch_available(void)
{
  if (RCIF)
    return true;
  else
    return false;
}
 
 
//*****************************************************************************
//Errores USART
//*****************************************************************************
void clear_usart_errors(void)
{
  clear_usart_errors_inline;
}
 

//*****************************************************************************
//Leer entradas.
//*****************************************************************************
 
//*****************************************************************************
//Leer bytes recibidos del bus del modulo SPI
//*****************************************************************************
 
void setup_sensor(void)  // SPI Master mode:
{
  SSPEN = 1; //Enables serial port and configures SCK, SDO, SDI and SS as serial port pins
  BF = 0;        //Receive not complete, SSPBUF is empty
  //SCK is the clock output (Master Mode)
  //Clock Polarity(Idle state of SCK)
  SMP = 0;      //Input data sampled at end of data output time
  CKE = 0;      //Transmit occurs on transition from Idle to active clock state
  SSPM3 = 0;
 SSPM2 = 0; //SPI Master mode, clock = FOSC/4
  SSPM1 = 0;
  SSPM0 = 0;
  CKP = 0; //Idle state for clock is a low level
  SSPIF = 0;   
}
 
void setup_adc(void)
{
  ADFM = 1;
  ADCON1 = 14; // PCFG3=1,PCFG2=1,PCFG1=1,PCFG0=0. Todas las entradas digitales
  CHS3 = 0;
  CHS2 = 0; // Seleccionamos el canal 0 (AN0) que es donde esta conectado el potenciometro
  CHS1 = 0;
  CHS0 = 0;
  //Tiempo de adquisicion
  ACQT2 = 0;
  ACQT1 = 0;  // 2Tad (Tad=1us) Por tanto 2x1us =2us >= 1.65us( Tacq calculado teoricamente)
  ACQT0 = 1;
  ADCS2 = 1;
  ADCS1 = 0;    // Idem a 4Tosc. 4*Tosc(1us) es el primer valor que hace que sea superior a 0.7us( el minimo)
  ADCS0 = 0;
  ADON = 1; // A/D converter module is enabled
  /* Configure A/D interrupt*/
  ADIF = 0;
  //ADIE = 1;
}
 
//*****************************************************************************
//Leer entradas.
//*****************************************************************************
 
//*****************************************************************************
//LEER DATOS SENSOR
//*****************************************************************************
unsigned char read_spi (void)
{
/*
  if ((BF == 1) && (SSPIF == 1))
  { //Receive complete, SSPBUF is full && The transmission/reception is complete (must be cleared in software)
    SSPIF = 0; ////Waiting to transmit/receive
    BF = 0;
    return SSPBUF;
 }
*/
  TRISC7 = 1; // así pongo en alta impedancia el pin SDO
  SSPBUF = 16;
  while (SSPIF == 0);
  SSPIF = 0;
  return SSPBUF;
}
 
//*****************************************************************************
//LEER DATOS POTENCIOMETRO
//*****************************************************************************
unsigned int read_adc(void)
{
  //Empezar a leer
  GODONE = 1; // A/D conversion in progress
  while (GODONE == 1);
  ADIF = 0;
  return ((ADRESH << 8) + (ADRESL));
}
Título: Re: enviar datos de un sensor de temperatura y de un pot por el puerto serie RS232
Publicado por: AngelGris en 14 de Diciembre de 2010, 21:15:59
  Te había puesto ese texto porque pensé que no sabías como configurar la placa PICDEM para poder usar el ICD. Y como en esos párrafos explicaba como configurar los jumpers y también mencionaba algo acerca de usar unos pines dedicados únicamente a ICD o usar RB6 y RB7 para ICD y no usarlos como I/O en tu programa.

  Pregunta ¿El programador ICD 2 genera VPP de 13V? porque si no genera VPP alta vas a tener que dejar habilitado LVP.
Título: Re: enviar datos de un sensor de temperatura y de un pot por el puerto serie RS232
Publicado por: edu1989 en 14 de Diciembre de 2010, 21:23:16
La verdad es que nunca entendi bien para que funcionaban los jumpers. Se que se le puede quitar como la capucha para deshabilitar pines no?
No se muy bien.. por tanto no he configurado los jumpers.

Edito: En Programmer, settings y power pone que MPLAB ICD2 Vpp 12.46

Gracias
Título: Re: enviar datos de un sensor de temperatura y de un pot por el puerto serie RS232
Publicado por: AngelGris en 14 de Diciembre de 2010, 23:38:02
La verdad es que nunca entendi bien para que funcionaban los jumpers. Se que se le puede quitar como la capucha para deshabilitar pines no?
No se muy bien.. por tanto no he configurado los jumpers.

Edito: En Programmer, settings y power pone que MPLAB ICD2 Vpp 12.46

Gracias

  Por lo que yo entiendo del párrafo (ese que copié) dice que de fábrica no tiene los jumper, que se puede cortar las pistas e instalarlos. También creo que dice que de fábrica viene para trabajar con RB6 y RB7 como si fueran los pines de ICSP (InCircuitSerialPrograming) por lo tanto nuestro programa no los podría utilizar como pine I/O
  Ah, si dice que VPP es 12.46V entonces no es necesario que LVP esté activado.
Título: Re: enviar datos de un sensor de temperatura y de un pot por el puerto serie RS232
Publicado por: edu1989 en 15 de Diciembre de 2010, 06:21:51
Edito: Creo que el problema que tengo esta en los CONFIG. Tengo que declarar todas las opciones de cada palabra? Si el config1 tiene 6 palabras tengo que poner las 6? Para usar un cristal a 4MHz, esta bien configurado? Gracias de antemano.

Código: [Seleccionar]
__CONFIG(1, CPUDIV1 & PLLDIV1 & XT & FCMDIS);  
__CONFIG(2, VREGDIS & PWRTEN & WDTDIS);
__CONFIG(3, PBADEN & MCLREN);
__CONFIG(4, ICPORTEN & LVPDIS & DEBUGEN);
__CONFIG(5,UNPROTECT);
__CONFIG(6,UNPROTECT);
__CONFIG(7,UNPROTECT);
Título: Re: enviar datos de un sensor de temperatura y de un pot por el puerto serie RS232
Publicado por: AngelGris en 16 de Diciembre de 2010, 15:16:49
  Yo creería que no es necesario poner todas las opciones de cada palabra. En los 16f que tienen una palabra de configuración no se necesita poner todo. Fijate que cada una de las opciones se agregan con el operador &, que hace una "and" entre una opción y otra.

  De hecho la opción "CPUDIV1" es el valor 0xFFFF así que si ponés sólo esa opción quedarían seteados todos los bits de la palabra de configuración en cuestión.

  Yo creería que está bien como está configurado la palabra 1 para que trabaje con 4MHz.

  Tené en cuenta que si habilitás MasterClear, dicho pin tiene que quedar conectado a VCC (generalmente por medio de una resistencia) porque sino el micro no va a trabajar.
Título: Re: enviar datos de un sensor de temperatura y de un pot por el puerto serie RS232
Publicado por: edu1989 en 16 de Diciembre de 2010, 15:27:46
Edito el mensaje porque la situacion actual es totalmente distinta. Hoy he estado probando de grabar el programa y no da ningun error ( en el debug si) y no funciona. He mirado el datasheet para ver si utilitzaba los puertos correctos y he grabado un programa de prueba mas que nada para comprobar si funcionaba y si estaba grabando bien. Todo esto ha ido bien pero el programa sigue sin funcionar.

Es simplemente el programa que encendia el led cuando el pulsador estaba pulsado y lo apagaba cuando no. Creo que es un tema de fuses, que no lo configuro del todo bien. Me gustaria que alguien pudiese darme su opinion al respecto o algun ejemplo parecido. 
 
Edito1: Acabo de encontrar un fichero donde explica como son les config de cada PIC en mi caso pero no se como relacionar esos numeros en HEX  con las posibles palabras:
Código: [Seleccionar]
[b][18F4550][/b]
[b]CFGS_UNPROG=1,35C0,2,FFDF,3,F3FF,4,FF9F,5,FFFF,6,FFFF,7,FFFF[/b]

CFGS_UNPROG=<config word number>,<unprogrammed value>,...
# This is used to specified the unprogrammed value of a configuration word.
# Entries for each word are entered as a list of pairs as above.
# Every config word must be specified
# <config word number> = 1,2,3, etc
# <unprogrammed value> = a hex number, don't need to indicate radix

No se como relacionar 35C0 con las posibles opciones:
Código: [Seleccionar]
// config word 1
// USB Clock Selection
 #define USBPLL 0xFFDF // clk src from 96MHz PLL/2
 #define USBOSC 0xFFFF // clk src from OSC1/OSC2
// CPU Sys CLK Select
 #define CPUDIV4 0xFFE7 // div by 4
 #define CPUDIV3 0xFFEF // div by 3
 #define CPUDIV2 0xFFF7 // div by 2
 #define CPUDIV1 0xFFFF // no divide
 #define PLLPOSTDIV6 CPUDIV4 // 96 MHz PLL div by 6
 #define PLLPOSTDIV4 CPUDIV3 // 96 MHz PLL div by 4
 #define PLLPOSTDIV3 CPUDIV2 // 96 MHz PLL div by 3
 #define PLLPOSTDIV2 CPUDIV1 // 96 MHz PLL div by 2
// OSC Select
 #define PLLDIV12 0xFFF8 // div by 12 {48MHz input}
 #define PLLDIV10 0xFFF9 // div by 10 {40MHz input}
 #define PLLDIV6 0xFFFA // div by 6 {24MHz input}
 #define PLLDIV5 0xFFFB // div by 5 {20MHz input}
 #define PLLDIV4 0xFFFC // div by 4 {16MHz input}
 #define PLLDIV3 0xFFFD // div by 3 {12MHz input}
 #define PLLDIV2 0xFFFE // div by 2 {8MHz input}
 #define PLLDIV1 0xFFFF // no divide {4MHz input}

Título: Re: enviar datos de un sensor de temperatura y de un pot por el puerto serie RS232
Publicado por: AngelGris en 20 de Diciembre de 2010, 11:23:49
  Yo no puedo ayudarte mucho más porque no trabajé nunca con los PIC18, y creería que con la configuración que habías puesto debería funcionar.

  Sí puedo intentar ayudarte a entender de donde sale la configuración que muestras .

Tomemos como caso la primer palabra que dice 35C0, esto es en binario 0011 0101 1100 0000

Mirando el datasheet del 4550 (documento DS39632D, página 286) indica que los bit 6 y 7 de CONFIG1L y los bit 4 y 5 de CONFIG1H no están implementados y como dice el datasheet, hay que dejarlos en "1"

La configuración que se puede hacer con Hitech usa una & entre distintos valores, hay que recordar que al hacer uso de & (and) el bit x va a tomar el valor "1" sí y sólo sí el bit x está en "1" en todos los valores que usemos en la &. Veamos si con un ejemplo me explico mejor

  0011 & 0001 --> 0001  --> sólo queda en "1" el bit 0 porque es el único bit que está en "1" en los dos operandos.

Siguiendo con el ejemplo, para que el primer número sea 3 hay que lograr que la & forme dicho número y la única combinación que logra eso es (IESOEN & FCMEN) --> 7FFF & BFFF --> 0111 1111 1111 1111 & 1011 1111 1111 1111 -->
0011 1111 1111 1111 (al separar en hexa, cada dígito sale de utilizar 4 bits)

el primer dígito es 0011 --> 3

  Acá ya se me complica pues según tu ejemplo el siguiente número sería la 5 que en binario es 0101. Según el datasheet dicho valor correspondería a la configuración EC con CLKO en RA6, pero según el archivo PIC18F4550.h que tengo en mi HiTech nohay ningún valor que se corresponda con el 5 como segundo dígito.
  Con lo cual no sé si es un error mio (que no esté entendiendo algo), un error del .h del HiTech o un error en el datasheet.

  Si seguimos con tu ejemplo, el tercer dígito es la C --> 1100, busquemos que combinación daría ese valor y sería
(USBPLL & CPUDIV4) o (USBPLL & CPUDIV3) o (USBPLL & PLLPOSTDIV4) o (USBPLL & PLLPOSTDIV6) -->

(FFDF & FFE7) o (FFDF & FFEF) --> (1111 1111 1101 1111 & 1111 1111 1110 0111) o
(1111 1111 1101 1111 & 1111 1111 1110 1111) vamos a separar solo el tercer dígito que es el que nos interesa y quedaría

(1101 & 1110) o (1101 & 1110) --> 1100  o 1100 así que llegamos a la combinación de la C

  Esa sería la idea de como se forman las palabras de configuración. Pero como noté esa diferencia entre el .h de HiTech y el datasheet no sé que pensar.
Título: Re: enviar datos de un sensor de temperatura y de un pot por el puerto serie RS232
Publicado por: edu1989 en 20 de Diciembre de 2010, 16:15:39
Muchas gracias. Tienes toda la razon del mundo el datasheet dice lo contrario a lo que dice el .h del pic18f4550
Por ejemplo el bit 7 de CONFIG1H

#define IESODIS   0xFFFF    // Disabled         1111  1111  1111  1111
#define IESOEN   0x7FFF    // Enabled          0111  1111  1111  1111

El IESOEN tendria que estar enabled pero en el datasheet dice que si ese bit esta a 0 no esta activo...

Es como si estuvieran al revés. Es como si un 1111 1111 1111 1111 fuera un 0000 0000 0000 0000

Que solucion le ves al asunto? No podria configurar los fuses directamente tratandolo como si fuera un registro mas?

por ejemplo CONFIG1L=255 etc..

Muchas gracias como siempre por tu ayuda
Título: Re: enviar datos de un sensor de temperatura y de un pot por el puerto serie RS232
Publicado por: AngelGris en 20 de Diciembre de 2010, 16:24:50
Muchas gracias. Tienes toda la razon del mundo el datasheet dice lo contrario a lo que dice el .h del pic18f4550
Por ejemplo el bit 7 de CONFIG1H

#define IESODIS   0xFFFF    // Disabled         1111  1111  1111  1111
#define IESOEN   0x7FFF    // Enabled          0111  1111  1111  1111

El IESOEN tendria que estar enabled pero en el datasheet dice que si ese bit esta a 0 no esta activo...

Es como si estuvieran al revés. Es como si un 1111 1111 1111 1111 fuera un 0000 0000 0000 0000

Que solucion le ves al asunto? No podria configurar los fuses directamente tratandolo como si fuera un registro mas?

por ejemplo CONFIG1L=255 etc..

Muchas gracias como siempre por tu ayuda


  Creo que no se podría escribir como si fuese un registro mas, pero sí podrías escribirlo de la siguiente manera

__CONFIG (1,0XFFFF); Obviamente eligiendo un valor que se corresponda con la configuración que uno pretende.

  Otra solución, más trabajosa pero reutilizable, sería modificar el archivo .h en cuestión y así la próxima vez que quieras programar los fuses vas a tener bien los datos en el archivo.
Título: Re: enviar datos de un sensor de temperatura y de un pot por el puerto serie RS232
Publicado por: edu1989 en 20 de Diciembre de 2010, 16:30:25
Gracias por la solucion. Obviamente me quedare con la primera ya que todo esto me corre un poco de prisa.
He estado mirando y es que ni el ejemplo que sale en la guia del compilador (quickstart) esta bien.

En la palabra 1 salen activadas FCMDIS(FFFF), IESODIS(FFFF),XT(FAFF). Haciendo la & vemos que el resultado es FAFF. He supuesto que los bits estaban girados asi que he hecho el contrario digamos: 0500 que viene a ser : 0000 0101 0000 0000 . Los ultimos 8 bits(CONFIGL1) estan OK pero de los otros 8 el bit 0 no importa el valor que pongas( tanto 1 como 0 sirve) pero en el bit 2 tiene que ser 0, para poder usar la opcion XT (bits FOSC3-FOSC0) y no lo es.

Me pongo ahora mismo  a hacerlo como dices.
Gracias de nuevo.
Título: Re: enviar datos de un sensor de temperatura y de un pot por el puerto serie RS232
Publicado por: AngelGris en 20 de Diciembre de 2010, 16:35:00
  Yo acabo de comparar el .h correspondiente al pic 16f877 y el datasheet de dicho pic y en este caso si se corresponden los valores. Así que casi seguro es un error en el .h del 4550
Título: Re: enviar datos de un sensor de temperatura y de un pot por el puerto serie RS232
Publicado por: edu1989 en 20 de Diciembre de 2010, 19:10:24
Código: [Seleccionar]
Que mala suerte la mia! porque tenia que pasarme a mi!! Bueno, ahora que ya se donde esta el fallo.. nada.. voy a publicar lo que he hecho.
A continuacion explicare un poco como configurare cada palabra a ver si ya mañana todo funciona como dios manda.. alla voy! Ordenare de derecha a izquierda los bits

[code]
CONFIG PALABRA 1
config1H = 0000 000X
bit7 IESO (Internal/External Oscillator Switchover bit) // HE DEJADO EL BIT A 0 (POR DEFECTO VIENE DE ESTA FORMA)
bit6 FCMEN (Fail-Safe clock monitor enable bit)          // HE DEJADO EL BIT A 0 (POR DEFECTO VIENE DE ESTA FORMA)
bit5 y bit 4 :Read as 0
bit 3-0 (FOSC): Para XT hay que escoger 000X ( He puesto un 0 al valor d la x)

config1L=0000 0000
bit 7 y 6: read as 0
bit 5 USB clock selection bit: 0
bit 4-3 CPUDIV : 00 para los 4Mhz
bit 0-2 PLL : 000 para los 4Mhz

Por tanto la palabra 1 me queda 0x0000
[/code]


Código: [Seleccionar]
CONFIG PALABRA 2
config2H = 0000 0000
bit 7-5 : Read as 0
bit 4-1 Postscale Watch dog= 000 (1/1)
bit 0: watchdog disabled (0)

config2L=0011 1001
bit 7-6: Reas as 0
bit 5: VREGEN(USB internal voltatge regulator)=1 ( disabled)
bit 4-3: BORV ( Brown out Reset voltatge bits)= 11( Minimum settings)
bit 2-1: Brown out reset bits: 00 ( disabled in hardware and software)
bit0 PWRTEN ( Power on Reset)= 1 ( disabled)

Por tanto la palabra 2 me queda 0x0039



Código: [Seleccionar]
CONFIG PALABRA 3
config3H = 0000 0001
bit7: MCLRE ( disabled) =0
bit 6-3: Read as 0
bit 2 (LPT1OSC) =0    // HE DEJADO EL BIT A 0 (POR DEFECTO VIENE DE ESTA FORMA)
bit 1 PBADEN Port A/D enable bit = 0
bit 0 CCP2 mux bit = 1 ( multiplexed with RC1)

AQUI SOLO HAY PALABRA DE CONFIGURACION HIGH, LA PALABRA DE CONFIGURACION LOW QUE LA PONGO TODA A 1 O TODA A 0?)

Por tanto queda 0x01XX ( xx=00 o xx=FF)



Código: [Seleccionar]
CONFIG PALABRA 4
config4H = 0010 0101
bit 7 Debug = activo ( a 0)
bit 6 ( XINST--> Extended Instruction Set Enable Bit)= a 0 ( disabled)
bit 5 (ICPRT) dedicated in circuit debut/programming = a 1 ( enabled)
bit 4-3= Read as 0
bit 2 LVP ( Low voltatge programming) a 1 (enabled), (valor por defecto)
bit 1 Read as 0
bit 0 STVREN Stack full/underflow reset enable bit a 1 ( valor por defecto)

AQUI SOLO HAY PALABRA DE CONFIGURACION HIGH, LA PALABRA DE CONFIGURACION LOW QUE LA PONGO TODA A 1 O TODA A 0?)

Por tanto queda 0x25XX (xx=00 o xx=FF)

Las palabras 5,6,7 las he configurado por defecto ya que solo implica proteccion del codigo.

Muchas gracias por la ayuda, espero haber podido hacer esto un poco claro, que la verdad es que no se yo si ha quedado claro
Un saludo
Título: Re: enviar datos de un sensor de temperatura y de un pot por el puerto serie RS232
Publicado por: edu1989 en 21 de Diciembre de 2010, 07:43:08
Ya funciona!! era eso lo que estaba mal. Ahora voy a probar con el programa del sensor y pote. Ya he grabado este programa y parece que funciona, he puesto temp 15 grados y el led no para de encenderse.. imagino que es porque va enviando los datos.

Para probarlo y conectar desde la salida rs232 del pic, al pc necesito que el cable rs232 sea cruzado verdad?
Pongo aqui la configuracion de los bits:

Código: [Seleccionar]
#include <htc.h>
__CONFIG(1, 0x0000);
__CONFIG(2, 0x0039);
__CONFIG(3, 0x01FF );
__CONFIG(4, 0x29FF);
__CONFIG(5, 0xC00F);
__CONFIG(6, 0xE00F);
__CONFIG(7, 0x000F);

Muchas gracias.
Título: Re: enviar datos de un sensor de temperatura y de un pot por el puerto serie RS232
Publicado por: AngelGris en 21 de Diciembre de 2010, 09:17:00
Ya funciona!! era eso lo que estaba mal. Ahora voy a probar con el programa del sensor y pote. Ya he grabado este programa y parece que funciona, he puesto temp 15 grados y el led no para de encenderse.. imagino que es porque va enviando los datos.

Para probarlo y conectar desde la salida rs232 del pic, al pc necesito que el cable rs232 sea cruzado verdad?
Pongo aqui la configuracion de los bits:


  Qué bueno que se haya podido encontrar el problema.

  Sí, del PIC al PC el cable tiene que ser cruzado TXpic->RXpc y TXpc->RXpic. Pero además de ello necesitás un adaptador de niveles como el max232.
Título: Re: enviar datos de un sensor de temperatura y de un pot por el puerto serie RS2
Publicado por: edu1989 en 21 de Diciembre de 2010, 09:18:36
Y el programa final tambien tiene pinta de funcionar ya que lo he programado para un umbral de temperatura de 15º y el led parpadea y para una temp de 30º y el led no parpadea. A ver a ver...

Muchas gracias como siempre :)
Título: Re: enviar datos de un sensor de temperatura y de un pot por el puerto serie RS232
Publicado por: edu1989 en 22 de Diciembre de 2010, 08:13:51
Hola de nuevo, estoy probando el programa y no acaba de funcionar.

Estoy alimentando el pic y conectando un cable desde el pic al pc. Cuando intento visualizar los datos en el terminal con el cable cruzado no se ve nada y con el cable normal se ven caracteres pero extraños, imagino que no estan en el formato adequado.

Que puede estar pasando? no tiene sentido que el cable sea el normal.. tendria que ser el cruzado...

P.d: Parece un problema de que los datos no estan en ASCII pero ya he hecho pruebas y se veian bien... es muy extraño.

Muchas gracias.
Título: Re: enviar datos de un sensor de temperatura y de un pot por el puerto serie RS232
Publicado por: umalrovi en 22 de Diciembre de 2010, 09:24:02
Buenas, has comprobado que las velocidades son idénticas tanto en el PC como en el pIC??? Estás transmitiendo datos de manera asíncrona y es fundamental que la configuración del puerto szerie sea la misma en el PC como en el PIC. No se si será ese tu problema, espero ayudarte en algo.

un saludo
Título: Re: enviar datos de un sensor de temperatura y de un pot por el puerto serie RS2
Publicado por: edu1989 en 22 de Diciembre de 2010, 10:13:09
Edito: Gracias por el comentario. Pensandolo bien creo que tienes razon. Antes te he dicho que habia hecho esta misma prueba con el compim pero esta herramienta te permite configurar bien el puerto. El puerto lo estoy configurando de esta forma:

Velocidad= 9600bits/s
Bits de datos = 8
Paridad= Ninguno
Bits de parada=1
Control de flujo= Ninguno

Adjunto el codigo ya que estoy seguro que es una mala configuracion como dices. Lo que me sorprende es que este caracter extraño me salga con el cable normal y que con el cable cruzado no salga nada...

Código: [Seleccionar]

#include <stdlib.h>  // para poder usar la funcion itoa
#include <htc.h>
__CONFIG(1, 0x0000);
__CONFIG(2, 0x0039);
__CONFIG(3, 0x01FF );
__CONFIG(4, 0x29FF);
__CONFIG(5, 0xC00F);
__CONFIG(6, 0xE00F);
__CONFIG(7, 0x000F);

 
/* =================================================================================
Definitions
    ================================================================================= */
#define PORTBIT(adr, bit) ( (unsigned)(&adr)*8 + (bit) )
 
#define Idle_Low 1 // No envia datos
#define Idle_High 2 // Envia datos
 
#define true 1
#define false 0
 
#define BAUD  9600 // Configuramos la velocidad, tanto puede ser 19200 o de 9600 kbaud/s pero hay q cambiarlo tb en la simulacion de proteus
#define PIC_CLK 4000000 // Clock de 4MHz (Cristal)
 
#define CS RB2
 


/* =================================================================================
Global variables 
  ================================================================================= */
//static bit potenciometro @ PORTBIT(PORTA, 0); // Declaración del potenciometro
//static bit sensor_temperatura @ PORTBIT(PORTB, 0);
//static bit sensor_datos_salida @ PORTBIT(PORTC, 7);  // SD0 disabled in master mode (configuración como entrada)
 
static bit LED @ PORTBIT(PORTD, 0);
char present_state = Idle_Low; // state variable
char future_state = Idle_Low; // state variable
unsigned int  valor_potenciometro;
unsigned int  valor_sensor_temperatura;
unsigned char pote_buf[6];
unsigned char sensor_buf[10];
char * valor_pote_en_texto;           // un puntero para almacenar el numero en texto
char * valor_sensor_en_texto;         // un puntero para almacenar el numero en texto
char byte_alto, byte_bajo;

unsigned char caracter_recibido;
unsigned char dummy;
 



/* =================================================================================
Function prototypes
    ================================================================================= */
//static void interrupt service_routine (void); // This is the interrupt service routine
 
void init_system (void);
void time_delay (unsigned int );
char output_logic(void);
char future_state_logic(void);

void setup_sensor(void);
void setup_adc(void);
void serial_setup(void);
 
void putst(const char *str);
void putch(unsigned char c);

unsigned char getch(void);
unsigned char UsartReadChar_nonstop(void);
unsigned char getch_available(void);
void clear_usart_errors(void);

unsigned char read_spi (void);
unsigned int read_adc(void);

 
 
/* =================================================================================
Main function
  ================================================================================= */
void main(void)
{
  valor_potenciometro = 0;
  valor_sensor_temperatura = 0;
  LED = 0;
  init_system();
  setup_sensor();
  setup_adc();
  serial_setup();
 
time_delay(30000);
while(1)
  {
    CS = 0;
    byte_alto = read_spi();
    byte_bajo = read_spi();
    CS = 1;
    valor_sensor_temperatura = (byte_alto << 8) + byte_bajo;
    valor_sensor_temperatura = valor_sensor_temperatura >> 7;
    //valor_sensor_temperatura = read_spi();  // Las pongo aqui porque es donde hago la lectura de los datos.
    valor_potenciometro = read_adc();
   
    valor_pote_en_texto = itoa (pote_buf, valor_potenciometro, 10);
    valor_sensor_en_texto = itoa (sensor_buf, valor_sensor_temperatura, 10);
   
output_logic();
    future_state_logic();
 
}
}

/* =================================================================================
Function definitions
  ================================================================================= */

//*****************************************************************************
//Future_state_logic routine
//*****************************************************************************
char future_state_logic(void)
{
  char error = 0;
  switch (present_state)
  {
    case Idle_Low:
                 
                  if ((valor_sensor_temperatura < 15) || (valor_potenciometro < 25))
                 { // Menor de 20ºC o la resistencia menos a 25Kohms
                    //future_state = Idle_High;
                    present_state = Idle_High;
                 }
                  else
                  if (getch_available() == true) //Si hay un caracter disponible recibido por el puerto serie
                  {
                    caracter_recibido = getch();
                    if (caracter_recibido == 'a')
                    {
                      present_state = Idle_High;
                    }
                    else
                    {
                     
                      present_state = Idle_Low;
                      error = 1;
                    }
                 }
                  break;
    case Idle_High:
                   if (TXIF == 0)
                   { // Buffer de transmision vacio
                     //future_state = Idle_Low;
                     present_state = Idle_Low;
                   }
                   else
                   {
                     error = 1;
                   }
                   break;
    default:
  error = 1;
  }
  return (error);
}

//*****************************************************************************
//Output logic routine
//*****************************************************************************
char output_logic(void)
{
  unsigned char error = 1;
  switch (present_state)
  {
    case Idle_Low:
                   LED = 0;
                   error = 0;
                   break;
    case Idle_High:
                   putst ("\n");
   putst ("Valor del pote: ");
                   putst (valor_pote_en_texto);
                   putst ("\n");  //cambio de linea
                   putst ("Valor del sensor: ");
                   putst (valor_sensor_en_texto);
                   //putst ("Suponemos un valor de 25 grados");
                   putst ("\n");
                   LED = 1;
                   error = 0;
                   break;
    default:
                   error = 1;
                   LED = 0;
                   break;
  }
  return (error);
}

//*****************************************************************************
//Init operations 
//*****************************************************************************
void init_system (void)
{
 

 
  TRISA = 255;
  CS = 1;
  TRISB = 1; // SDI. El bit 0 a 1.Configurado en master mode (bit 1 cleared, en mode slave bit 1 set)
  TRISC = 192; // RC7 i RC6 a 1
  TRISD=0;
}

 
//*****************************************************************************
//Time delay routine.   
//*****************************************************************************
void time_delay(unsigned int delay)
{
  unsigned int i;

  for (i = 0; i <= delay; i++)
  {
    NOP();
  }
}
 
//*****************************************************************************
// SERIAL SETUP 
//*****************************************************************************
void serial_setup(void)
{
  #define SPBRG_VALUE ((PIC_CLK/(16UL*BAUD)) -1)
  BRGH = 1;
  BRG16 = 0;
  SPBRG = SPBRG_VALUE;
  SPEN = 1; // Enable serial port
  SYNC = 0; // Asincrono
  TXIE = 0; // Desactivar interrupciones en tx
  TXEN = 1; // Enable the transmitter
  TX9 = 0; // 8 bits transmission
  RCIE = 1; // Activar interrupciones en rx
  RX9 = 0; // 8 bits reception
  CREN = 1; //Enable reception
  #define clear_usart_errors_inline if (OERR)\
                                   {\
                                      TXEN = 0;\
                                      TXEN = 1;\
                                      CREN = 0;\
                                      CREN = 1;\
                                    }\
                                   if (FERR)\
                                  {\
                                     dummy = RCREG;\
                                      TXEN = 0;\
                                      TXEN = 1;\
                                    }
}
 
 
//*****************************************************************************
// Enviar datos ( un caracter)
//*****************************************************************************
 
void putch(unsigned char c)
{
  while (!TXIF)
  {
    clear_usart_errors_inline;
    CLRWDT();
  }
  TXREG = c;
}
//*****************************************************************************
// Enviar datos (un buffer)
//*****************************************************************************
void putst(register const char *str)
{
  while ((*str) != 0)
  {
    putch (*str);
    if (*str == 13) putch (10);
    if (*str == 10) putch (13);
    str++;
  }
}


//*****************************************************************************
//Leer datos ( un caracter)
//*****************************************************************************
 
unsigned char getch(void)
{
  while (RCIF != 1)
 { //1 = The EUSART receive buffer, RCREG, is full
    CLRWDT();
    clear_usart_errors_inline;
  }
  return RCREG;
}
 
//*****************************************************************************
//Leer datos (un buffer)
//*****************************************************************************
unsigned char UsartReadChar_nonstop(void)
{
  if (!RCIF)
    return 0;   
 return RCREG;
}
 
 
//*****************************************************************************
//Comprueba si aun faltan datos o no
//*****************************************************************************
unsigned char getch_available(void)
{
  if (RCIF)
    return true;
  else
    return false;
}
 
 
//*****************************************************************************
//Errores USART
//*****************************************************************************
void clear_usart_errors(void)
{
  clear_usart_errors_inline;
}
 

//*****************************************************************************
//Leer entradas.
//*****************************************************************************
 
//*****************************************************************************
//Leer bytes recibidos del bus del modulo SPI
//*****************************************************************************
 
void setup_sensor(void)  // SPI Master mode:
{
  SSPEN = 1; //Enables serial port and configures SCK, SDO, SDI and SS as serial port pins
  BF = 0;        //Receive not complete, SSPBUF is empty
  //SCK is the clock output (Master Mode)
  //Clock Polarity(Idle state of SCK)
  SMP = 0;      //Input data sampled at end of data output time
  CKE = 0;      //Transmit occurs on transition from Idle to active clock state
  SSPM3 = 0;
 SSPM2 = 0; //SPI Master mode, clock = FOSC/4
  SSPM1 = 0;
  SSPM0 = 0;
  CKP = 0; //Idle state for clock is a low level
  SSPIF = 0;   
}
 
void setup_adc(void)
{
  ADFM = 1;
  ADCON1 = 14; // PCFG3=1,PCFG2=1,PCFG1=1,PCFG0=0. Todas las entradas digitales
  CHS3 = 0;
  CHS2 = 0; // Seleccionamos el canal 0 (AN0) que es donde esta conectado el potenciometro
  CHS1 = 0;
  CHS0 = 0;
  //Tiempo de adquisicion
  ACQT2 = 0;
  ACQT1 = 0;  // 2Tad (Tad=1us) Por tanto 2x1us =2us >= 1.65us( Tacq calculado teoricamente)
  ACQT0 = 1;
  ADCS2 = 1;
  ADCS1 = 0;    // Idem a 4Tosc. 4*Tosc(1us) es el primer valor que hace que sea superior a 0.7us( el minimo)
  ADCS0 = 0;
  ADON = 1; // A/D converter module is enabled
  /* Configure A/D interrupt*/
  ADIF = 0;
  //ADIE = 1;
}
 
//*****************************************************************************
//Leer entradas.
//*****************************************************************************
 
//*****************************************************************************
//LEER DATOS SENSOR
//*****************************************************************************
unsigned char read_spi (void)
{
/*
  if ((BF == 1) && (SSPIF == 1))
  { //Receive complete, SSPBUF is full && The transmission/reception is complete (must be cleared in software)
    SSPIF = 0; ////Waiting to transmit/receive
    BF = 0;
    return SSPBUF;
 }
*/
  TRISC7 = 1; // así pongo en alta impedancia el pin SDO
  SSPBUF = 16;
  while (SSPIF == 0);
  SSPIF = 0;
  return SSPBUF;
}
 
//*****************************************************************************
//LEER DATOS POTENCIOMETRO
//*****************************************************************************
unsigned int read_adc(void)
{
  //Empezar a leer
  GODONE = 1; // A/D conversion in progress
  while (GODONE == 1);
  ADIF = 0;
  return ((ADRESH << 8) + (ADRESL));
}
Título: Re: enviar datos de un sensor de temperatura y de un pot por el puerto serie RS232
Publicado por: AngelGris en 22 de Diciembre de 2010, 10:39:02
  Subí el circuito que estás usando incluyendo el max232, tal vez haya algún error de conexionado o incluso que esté fallando el max232
Título: Re: enviar datos de un sensor de temperatura y de un pot por el puerto serie RS232
Publicado por: edu1989 en 22 de Diciembre de 2010, 10:51:30
El PIC que estoy utilitzando pertenece a la  placa (http://www.microchip.com/stellent/idcplg?IdcService=SS_GET_PAGE&nodeId=1406&dDocName=en021940) y ya incorpora un max232 por lo tanto ese no creo que sea el problema

Por otro lado acabo de probar otra vez el compim y con la configuracion de los fuses no funciona (sin los fuses si, como ya dije antes). El error es el siguiente:
Illegal FOSC bits 0b1010 in CONFIGH. El Pic esta configurado en el proteus esta a 4Mhz.

Subo el proyecto entero, muchas gracias por todo de nuevo.
Edito: Estoy mirando si funciona con el compim puesto y sin la configuracion de los fuses y si, si que funciona bien.

Edito1: Imagino que es por el tema del oscil.lador con el cristal.. que claro, esta implementado en la placa pero no en el proteus.
Título: Re: enviar datos de un sensor de temperatura y de un pot por el puerto serie RS232
Publicado por: edu1989 en 23 de Diciembre de 2010, 09:01:23
Hola amigos, he seguido probando cosas.. si cambio el oscilador de XT (000x) a Internal oscillator, XT used by USB (INTXT) (1010) ya no me da ese error...
Por lo que creo que debo implementar el oscilador en proteus ya que este es interno y funciona.

Por otro lado ahora me tira un warning:

ADC conversion clock period (8.3332e-8) violates the minimum required TAD time.

Cambiaria el TAD pero creo que este error es fruto a que cambio el oscilador porque esto ya estaba calculado.

A ver si sabeis que es lo que pasa, mas que nada con el primer problema que tengo, muchas gracias!
Título: Re: enviar datos de un sensor de temperatura y de un pot por el puerto serie RS232
Publicado por: AngelGris en 23 de Diciembre de 2010, 09:53:30
Hola amigos, he seguido probando cosas.. si cambio el oscilador de XT (000x) a Internal oscillator, XT used by USB (INTXT) (1010) ya no me da ese error...
Por lo que creo que debo implementar el oscilador en proteus ya que este es interno y funciona.

Por otro lado ahora me tira un warning:

ADC conversion clock period (8.3332e-8) violates the minimum required TAD time.

Cambiaria el TAD pero creo que este error es fruto a que cambio el oscilador porque esto ya estaba calculado.

A ver si sabeis que es lo que pasa, mas que nada con el primer problema que tengo, muchas gracias!

  Justo estaba pensando en que tal vez ésa es la única configuración que se puede usar con esa placa, me parece raro pero....
  Supuestamente con esa configuración hace uso del oscilador interno que es de 8MHz. Imagino que habrá que configurar el registro OSCCON para lograr una frecuencia de 4MHz

  De todas maneras no entiendo tampoco a que te referís cuando decís "por lo que creo que debo implementar el oscilador en proteus ya que este es interno y funciona"

  Ese error que da respecto del TAD indica que el clock del PIC es mayor al que se uso para calcular el TAD. Por dar un ejemplo sería como si yo configuro un TAD para un clock de 4MHz pero hago trabajar al PIC a 10MHz
Título: Re: enviar datos de un sensor de temperatura y de un pot por el puerto serie RS232
Publicado por: edu1989 en 23 de Diciembre de 2010, 09:59:33
Hola, segun la tabla que sale en la pagina 30 del datasheet "TABLE 2-3: OSCILLATOR CONFIGURATION OPTIONS FOR USB OPERATION (CONTINUED)"
Se puede configurar el XT a 4Mhz y de esa tabla he sacado los parametros para configurar bien la palabra de configuracion.

Que solucion propones Angel?

Gracias.
Título: Re: enviar datos de un sensor de temperatura y de un pot por el puerto serie RS232
Publicado por: AngelGris en 23 de Diciembre de 2010, 10:06:33
Hola, segun la tabla que sale en la pagina 30 del datasheet "TABLE 2-3: OSCILLATOR CONFIGURATION OPTIONS FOR USB OPERATION (CONTINUED)"
Se puede configurar el XT a 4Mhz y de esa tabla he sacado los parametros para configurar bien la palabra de configuracion.

Que solucion propones Angel?

Gracias.

  Por lo que yo entiendo esa tabla se refiere a los modos XT, HS, EC, ECIO, HSPLL, ECPLL, XTPLL y ECPIO, pero en tu caso no usas ninguno de esos modos. Fijate que en la página 288 donde muestra el registro CONFIG1H muestra claramente que la configuración 1010 de los bits FOSC3...FOSC0 no se corresponde con ninguno de los modos mostrados en la tabla
Título: Re: enviar datos de un sensor de temperatura y de un pot por el puerto serie RS232
Publicado por: edu1989 en 23 de Diciembre de 2010, 10:09:00
Si, ya veo que esos bits estan fijos a 1010. Entonces para conseguir un oscilador de 4Mhz con XT..? Si no habria que cambiar los setup de adc y sensor.. ( si cmbiariamos de freq)
Título: Re: enviar datos de un sensor de temperatura y de un pot por el puerto serie RS232
Publicado por: AngelGris en 23 de Diciembre de 2010, 10:14:40
Si, ya veo que esos bits estan fijos a 1010. Entonces para conseguir un oscilador de 4Mhz con XT..? Si no habria que cambiar los setup de adc y sensor.. ( si cmbiariamos de freq)

  Me parece que sería con lo que te comentaba en el otro mensaje del registro OSCCON. Con dicho registro se modifica el oscilador interno. Fijate en la página 32 del datasheet.

  Y si no, si es que en realidad la señal es tomada desde el bloque PLL habría que configurar los bits CPUDIV para que de dividido 6, eso nos daría 96MHz / 6 que son 16MHz y entonces sí habría que recalcular el TAD para dicha frecuencia.
Título: Re: enviar datos de un sensor de temperatura y de un pot por el puerto serie RS232
Publicado por: edu1989 en 23 de Diciembre de 2010, 13:07:11
Entonces utilitzando el registro OOSCON pongo los bits IRCF2:IRCF0 a 110 = 4 MHz y hago SCS1:SCS0: 1x = Internal oscillator en mi funcion init?
El error del proteus decia FOSC3-FOSC0 tenia que ser 1010 y eso si que se corresponde con una opcion ( he entendido que tu has dicho que no).Es la opcion 1010 = Internal oscillator, XT used by USB (INTXT)

Edito: No funciona,sigue saliendo el error pero no entiendo porque, sigue diciendo lo del error en Fosc 1010

Edito1: En el ultimo o penultimo mensaje que has escrito dices que no uso ninguno de los modos ( de los 12 que hay de oscilacion). Queria comentarte que si que uso el modo XT.. a lo mejor estoy entiendo mal lo que me dices pero como modo.. yo entiendo eso


Si te fijas en la FIGURE 2-1: PIC18F2455/2550/4455/4550 CLOCK DIAGRAM ( pag 24) el camino que se sigue para conseguir el XT de 4Mhz es:
Del oscilador primario al oscilador postscaler ( con CPDIV = 00) y despues va directo a los bits FOS3-FOSC0 que tendrian que ser configurados como XT (000X)

La verdad es que he estado probando muchas cosas y sigue tirandome el error. Podrias mirarte a ver como lo harias.. ya no se que probar ni se donde esta el error. Creo que la clave esta en saber seleccionar la "Input frequency " a 4MHz ya que como dice en esa tabla con esa input frequency y esta configuracion se obtienen los 4Mhz
Muchas gracias de nuevo.



Título: Re: enviar datos de un sensor de temperatura y de un pot por el puerto serie RS232
Publicado por: AngelGris en 24 de Diciembre de 2010, 09:27:16

.........
Edito: No funciona,sigue saliendo el error pero no entiendo porque, sigue diciendo lo del error en Fosc 1010
.........


  ¿Qué software te da ese error? ¿El proteus, cuando intentás colocar esa configuración en el PIC? ¿O el grabador cuando intentás programar al PIC con otra configuración?
Título: Re: enviar datos de un sensor de temperatura y de un pot por el puerto serie RS232
Publicado por: edu1989 en 24 de Diciembre de 2010, 09:30:56
Es el proteus. El grabador funciona perfectamente pero como cuando intento comunicarme desde el pic al pc ( con un cable rs232 cruzado) no funciona, pienso que el error del proteus puede que sea la causa real tambien.

Como ya dije con el cable cruzado no recibo nada y con el cable normal recibo caracteres extraños...
Título: Re: enviar datos de un sensor de temperatura y de un pot por el puerto serie RS232
Publicado por: AngelGris en 24 de Diciembre de 2010, 10:03:05
Es el proteus. El grabador funciona perfectamente pero como cuando intento comunicarme desde el pic al pc ( con un cable rs232 cruzado) no funciona, pienso que el error del proteus puede que sea la causa real tambien.

Como ya dije con el cable cruzado no recibo nada y con el cable normal recibo caracteres extraños...


  Yo no tomaría al error del Proteus como posible causa del problema real. Puede ocurrir que Proteus tire dicho error por no ser capaz de simular con esa configuración.

  Volviendo al caso de la vida real. ¿De cuanto es el cristal que tiene tu placa?
Título: Re: enviar datos de un sensor de temperatura y de un pot por el puerto serie RS2
Publicado por: edu1989 en 24 de Diciembre de 2010, 10:16:29
Pues en la pag 25  en la tabla TABLE 2-2:CAPACITOR SELECTION FOR CRYSTAL OSCILLATOR pone que el crystal es de 4MHz. Es difícil entenderlo bien porque hay muchos modos y muchas configuraciones distintas.
Título: Re: enviar datos de un sensor de temperatura y de un pot por el puerto serie RS2
Publicado por: AngelGris en 24 de Diciembre de 2010, 10:21:16
Pues en la pag 25  en la tabla TABLE 2-2:CAPACITOR SELECTION FOR CRYSTAL OSCILLATOR pone que el crystal es de 4MHz. Es difícil entenderlo bien porque hay muchos modos y muchas configuraciones distintas.

  Si te referís a la página 25 del datasheet del PIC18F4550, lo que allí figura es para usarlo como guía.

  Mi pregunta se refería a ¿Qué cristal tiene tu placa PICDEM? Pues si no sabemos eso no vamos a poder determinar los bits de configuración.
Título: Re: enviar datos de un sensor de temperatura y de un pot por el puerto serie RS2
Publicado por: edu1989 en 24 de Diciembre de 2010, 10:24:15
Es de 20MHz, confirmado!
Acabo de mirarlo..
Título: Re: enviar datos de un sensor de temperatura y de un pot por el puerto serie RS2
Publicado por: AngelGris en 24 de Diciembre de 2010, 10:37:26
Y como puedo saberlo? en la placa encima del crystal pone JWT20.000.. imagino que de 20MHz no?

  Claro, casi seguro que es de 20MHz.
  Y como vos habías configurado los bits para que pase directo la señal del cristal hacia el núcleo, tu PIC termina trabajando a 20MHz, entonces por ello es que no te envía bien los datos. Porque habías calculado la velocidad para una frecuencia de 4MHz.

  Mirando el diagrama de la página 24 del datasheet del PIC, veo que el oscilador primario puede ser dividido en 4, 3, 2 o 1 (según la configuración de los bits CPUDIV). Así que no se podría hacer que trabaje a 4MHz

  Se puede recalcular el TAD para 20MHz y cambiar en el programa PIC_CLK de 4000000 a 20000000. Con eso debería funcionar.

  Sino también se puede configurar los CPUDIV para que divida 4, recalcular el TAD para 5MHz y cambiar PIC_CLK 4000000 por PIC_CLK 5000000
Título: Re: enviar datos de un sensor de temperatura y de un pot por el puerto serie RS2
Publicado por: edu1989 en 24 de Diciembre de 2010, 10:39:12
Vale la pena que el PIC trabaje a 5MHz en vez de a 20MHz? mas que nada es por si se ve claramente la diferencia.
Título: Re: enviar datos de un sensor de temperatura y de un pot por el puerto serie RS2
Publicado por: AngelGris en 24 de Diciembre de 2010, 10:49:39
Vale la pena que el PIC trabaje a 5MHz en vez de a 20MHz? mas que nada es por si se ve claramente la diferencia.

  Yo te mostraba la opción de 5MHz para que sea más parecida a los 4MHz conque se había pensado el programa. Porque tal vez para 20MHz habría que cambiar alguna otra cosa en cuanto a la configuración del UART. Aunque viendo la fórmula, me parece que funcionaría bien igual.
Título: Re: enviar datos de un sensor de temperatura y de un pot por el puerto serie RS2
Publicado por: edu1989 en 24 de Diciembre de 2010, 11:28:06
Me quedo con los 5 entonces y ya esta. Entonces lo dejo todo tal y como lo tngo y cambio los bits para que divida por 4 no? Volvere a calcular el Tad tanto del sensor como del pote.

Muchas gracias
Título: Re: enviar datos de un sensor de temperatura y de un pot por el puerto serie RS2
Publicado por: AngelGris en 24 de Diciembre de 2010, 11:41:13
Me quedo con los 5 entonces y ya esta. Entonces lo dejo todo tal y como lo tngo y cambio los bits para que divida por 4 no? Volvere a calcular el Tad tanto del sensor como del pote.

Muchas gracias

  Sí, hay que recalcular el TAD del conversor AD. También cambiar la definición de PIC_CLK de 4000000 a 5000000.

  ¿A que te referís con el TAD del sensor?
Título: Re: enviar datos de un sensor de temperatura y de un pot por el puerto serie RS2
Publicado por: edu1989 en 24 de Diciembre de 2010, 11:44:33
Me parecia recordar que alguna otra funcion tambien jugaba con la freq. Voy a mirarlo y a arreglarlo y ya te dire.

Gracias
Título: Re: enviar datos de un sensor de temperatura y de un pot por el puerto serie RS232
Publicado por: edu1989 en 25 de Diciembre de 2010, 15:09:57
Estoy arreglando la funcion del conversor para que funcione  tambien con la nueva freq (5MHz) y me da un error en el proteus..
" adc clock period (1.6667e-7) violates the minimum required Tad time"

He seguido los pasos que hicimos la otra vez... Me explico:

Para el Tad ( tiempo de conversion bit a bit), dijimos que la Tad real tenia que ser mayor a una Tad minima ( dijimos 0.7us pero en el datasheet he visto 0.8us)
Por tanto la Tad sera Tosc( 1/5Mhz=0.2us)* X >= 0.8 o 0.7
En principio la configuracion que teniamos de los bits ADCS2:ADCS0 (100) ya funcionaria (Tosc*4= 0.2us*4= 0.8us). Por tanto Tad=0.8us

En cambio para el Tacq habia la condicion que el Tacq tenia que ser mayor a un tiempo de adquisicion calculado ( en base a unos tiempos etc etc...) que daba 1.65us.

Aqui es donde creo que hay que hacer el cambio ya que Tacq(calculada teoricamente)<= x* Tad que viene siendo 1.65us<= x* 0.8. Por tanto ya no podria ser 2Tad y tendria que ser 4Tad para cumplir la condicion.

Dejo el codigo aqui:
Código: [Seleccionar]
void setup_adc(void)
{
  ADFM = 1;
  ADCON1 = 14; // PCFG3=1,PCFG2=1,PCFG1=1,PCFG0=0. Todas las entradas digitales
  // Seleccionamos el canal 0 (AN0) que es donde esta conectado el potenciometro
  CHS3 = 0;
  CHS2 = 0;
  CHS1 = 0;
  CHS0 = 0;
  //Tiempo de adquisicion
  ACQT2 = 0;
  ACQT1 = 1; 
  ACQT0 = 0;
  // Tiempo de conversion
  ADCS2 = 1;
  ADCS1 = 0;    //                         Idem a 4Tosc. 4*Tosc(1/5Mhz = 0.2us) es el primer valor que hace que sea superior a 0.7us( el minimo) (100)
  ADCS0 = 0;
 
  ADON = 1; // A/D converter module is enabled
  /* Configure A/D interrupt*/
  ADIF = 0;
}

Gracias de nuevo.
Título: Re: enviar datos de un sensor de temperatura y de un pot por el puerto serie RS232
Publicado por: AngelGris en 26 de Diciembre de 2010, 12:38:47
Estoy arreglando la funcion del conversor para que funcione  tambien con la nueva freq (5MHz) y me da un error en el proteus..
" adc clock period (1.6667e-7) violates the minimum required Tad time"

He seguido los pasos que hicimos la otra vez... Me explico:

Para el Tad ( tiempo de conversion bit a bit), dijimos que la Tad real tenia que ser mayor a una Tad minima ( dijimos 0.7us pero en el datasheet he visto 0.8us)


  El parámetro 130 de la tabla 28-29 indica que el TAD mínimo para un PIC18Fxxxx con una VCC >=3V es de 0.7us


Por tanto la Tad sera Tosc( 1/5Mhz=0.2us)* X >= 0.8 o 0.7
En principio la configuracion que teniamos de los bits ADCS2:ADCS0 (100) ya funcionaria (Tosc*4= 0.2us*4= 0.8us). Por tanto Tad=0.8us

En cambio para el Tacq habia la condicion que el Tacq tenia que ser mayor a un tiempo de adquisicion calculado ( en base a unos tiempos etc etc...) que daba 1.65us.

Aqui es donde creo que hay que hacer el cambio ya que Tacq(calculada teoricamente)<= x* Tad que viene siendo 1.65us<= x* 0.8. Por tanto ya no podria ser 2Tad y tendria que ser 4Tad para cumplir la condicion.

Dejo el codigo aqui:
Código: [Seleccionar]
void setup_adc(void)
{
  ADFM = 1;
  ADCON1 = 14; // PCFG3=1,PCFG2=1,PCFG1=1,PCFG0=0. Todas las entradas digitales
  // Seleccionamos el canal 0 (AN0) que es donde esta conectado el potenciometro
  CHS3 = 0;
  CHS2 = 0;
  CHS1 = 0;
  CHS0 = 0;
  //Tiempo de adquisicion
  ACQT2 = 0;
  ACQT1 = 1; 
  ACQT0 = 0;
  // Tiempo de conversion
  ADCS2 = 1;
  ADCS1 = 0;    //                         Idem a 4Tosc. 4*Tosc(1/5Mhz = 0.2us) es el primer valor que hace que sea superior a 0.7us( el minimo) (100)
  ADCS0 = 0;
 
  ADON = 1; // A/D converter module is enabled
  /* Configure A/D interrupt*/
  ADIF = 0;
}

Gracias de nuevo.

  A mi me parece que está bien como lo estás dejando.

  El error te lo tira proteus, pregunto ¿Que frecuencia le estás poniendo al proteus para que trabaje? Porque si no me equivoco tenés que ponerle la frecuencia de trabajo del núcleo. En este caso sería 5MHz y no los 20MHz que es el cristal que tenés.
Título: Re: enviar datos de un sensor de temperatura y de un pot por el puerto serie RS2
Publicado por: edu1989 en 26 de Diciembre de 2010, 15:19:59
He puesto 5MHz.. no se porque me tira el error.. mas tarde subo el proteus y el codigo entero.

Edito: He probado de grabarlo y sigue sin funcionar.. sigue pasando lo mismo.. se envian caracteres extraños.. ( con el cable normal, sin cruzar). Adjunto una carpeta con todo el proyecto.

A ver si descubrimos que es lo que passa..

 Aprovecho tambien para felicitaros las fiestas desde España. Un saludo y gracias.
Título: Re: enviar datos de un sensor de temperatura y de un pot por el puerto serie RS232
Publicado por: edu1989 en 27 de Diciembre de 2010, 09:14:06
Hola de nuevo. He estado probando pero esta vez he encontrado un esquema en el proteus que simula toda mi placa. En esa simulacion cuando clicas encima del PIC te permite poner la palabra de configuracion, he hecho la AND de todas las palabras y me ha quedado una que he puesto alli y la he quitado del programa      ( del mplab). Funciona y por lo que creo es que la palabra de configuracion en el proteus no se pone en el codigo sino que se especifica en esa opcion.

Ahora hay que descubrir porque no funciona y recibo caracteres raros...

Gracias
Título: Re: enviar datos de un sensor de temperatura y de un pot por el puerto serie RS232
Publicado por: AngelGris en 27 de Diciembre de 2010, 11:06:41
  Yo lo simuló en Proteus sin poner nada en la palabra de configuración e incluso sin poner las sentencias "__CONFIG (x,xx)" en el programa. Lo único que hice fue asignar un clock de 5MHz y obviamente los cambios de PIC_CLK en el programa y también el cambio en el TAD y en el tiempo de adquisición. Al simularlo así funcionó perfectamente.

  Voy a investigar eso de la palabra de configuración, a ver que pasa.
Título: Re: enviar datos de un sensor de temperatura y de un pot por el puerto serie RS232
Publicado por: edu1989 en 27 de Diciembre de 2010, 11:08:26
Si eso ya lo intente y tambien me funciono. Ahora cuando agregues las palabras de configuración a ver que pasa... yo lo hago como te he explicado antes.

Gracias nuevamente.
Título: Re: enviar datos de un sensor de temperatura y de un pot por el puerto serie RS232
Publicado por: edu1989 en 28 de Diciembre de 2010, 08:16:13
Sigue sin funcionar... he pensado que podia ser el max232 pero ya viene dentro de la placa y no tendria que dar problemas..
Tambien he pensado en la velocidad y es la misma en los dos.. no se que mas probar la verdad..
He probado de bajar la velocidad a 4800 y configurarla de esta forma tambien en el hyperterminal y nada..

Lo que me estoy preguntando ahora ( que estoy seguro que no es el problema) es que en el hyperterminal hay un bit de parada y en mi caso.. no he configurado nada de eso.

Tengo que entregar el proyecto pronto y pensaba que esta parte seria un poco mas rapida.. pero ya veo que no..
A ver si alguien puede ayudarme, muchas gracias de antemano.