#include <htc.h>
#include <stdlib.h> // para poder 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)
#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 high_result;
//unsigned char low_result;
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();
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')
{
//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:
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) // 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 = 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));
}