#include <htc.h>
//#include <stdlib.h> // para poder usar la funcion itoa
#include "itoa.c"
/* =================================================================================
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 buf[16];
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
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();
valor_pote_en_texto
= itoa (buf
, valor_potenciometro
, 10); // valor_sensor_en_texto = itoa (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')
{
//future_state = Idle_High;
present_state = Idle_High;
LED = 1;
error = 0;
}
else
{
//future_state = Idle_Low;
present_state = Idle_Low;
LED = 0;
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:
if ((valor_sensor_temperatura < 20) || (valor_potenciometro < 25))
{
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;
}
else
if (getch_available() == true)
// Si hay un caracter disponible recibido por el puerto serie.
{
caracter_recibido
= getch(); if (caracter_recibido == 'a')
{
putch (valor_potenciometro);
putch (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 (!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;
}
return 0;
}
//*****************************************************************************
//LEER DATOS POTENCIOMETRO
//*****************************************************************************
unsigned char read_adc(void)
{
//Empezar a leer
GODONE=1; // A/D conversion in progress
while (ADIF == 0);
ADIF = 0;
return ((ADRESH << 8) + (ADRESL));
}
/*GUARDAR EL CONTENIDO DE HIGH_RESULT EN EL buf*/
//Verificar si el bit 0 de high_result es 1 ó 0
/*
if (high_result & 1) buf[0] = '1';
else
buf[0] = '0';
//Verificar si el bit 1 de high_result es 1 ó 0
if (high_result & 2) buf[1] = '1';
else
buf[1] = '0';
//Verificar si el bit 2 de high_result es 1 ó 0
if (high_result & 4) buf[2] = '1';
else
buf[2] = '0';
//Verificar si el bit 3 de high_result es 1 ó 0
if (high_result & 8) buf[3] = '1';
else
buf[3] = '0';
//Verificar si el bit 4 de high_result es 1 ó 0
if (high_result & 16) buf[4] = '1';
else
buf[4] = '0';
//Verificar si el bit 5 de high_result es 1 ó 0
if (high_result & 32) buf[5] = '1';
else
buf[5] = '0';
//Verificar si el bit 6 de high_result es 1 ó 0
if (high_result & 64) buf[6] = '1';
else
buf[6] = '0';
//Verificar si el bit 7 de high_result es 1 ó 0
if (high_result & 128) buf[7] = '1';
else
buf[7] = '0';
/*GUARDAR EL CONTENIDO DE Low_RESULT EN EL buf*/
//Verificar si el bit 0 de high_result es 1 ó 0
/*
if (low_result & 1) buf[8] = '1';
else
buf[8] = '0';
//Verificar si el bit 1 de high_result es 1 ó 0
if(low_result & 2) buf[9] = '1';
else
buf[9] = '0';
//Verificar si el bit 2 de high_result es 1 ó 0
if (low_result & 4) buf[10] = '1';
else
buf[10] = '0';
//Verificar si el bit 3 de high_result es 1 ó 0
if (low_result & 8) buf[11] = '1';
else
buf[11] = '0';
//Verificar si el bit 4 de high_result es 1 ó 0
if (low_result & 16) buf[12] = '1';
else
buf[12] = '0';
//Verificar si el bit 5 de high_result es 1 ó 0
if (low_result & 32) buf[13] = '1';
else
buf[13] = '0';
//Verificar si el bit 6 de high_result es 1 ó 0
if (low_result & 64) buf[14] = '1';
else
buf[14] = '0';
//Verificar si el bit 7 de high_result es 1 ó 0
if(low_result & 128) buf[15] = '1';
else
buf[15] = '0';
*/