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.
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!
#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]
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*/
}
#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;
}
}
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:
..........
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?
#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;
}
}
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
unsigned char read_spi (void)
{
SSPBUF = 16; // ESTA LINEA QUE HACE?
while (SSPIF==0);
SSPIF = 0;
return SSPBUF;
}
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.
#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;
}
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);
#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;
}
- 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.
- 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!
char * utoa(char * buf, unsigned val, int base);
char * itoa(char * buf, int val, int base);
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
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.
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.
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.
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.
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.
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
#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));
}
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?
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.
/*
;******** 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
*/
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 :)
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.
__CONFIG(WDTDIS & XT & UNPROTECT& PWRTEN &LVPDIS & DUNPROT & WRTEN & UNPROTECT & BOREN &DEBUGDIS); // 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;
_________________________________________________________________________________________________________________________________
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.
__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);
#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));
}
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
#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));
}
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
__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);
[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
// 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}
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
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
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
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)
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)
#include <htc.h>
__CONFIG(1, 0x0000);
__CONFIG(2, 0x0039);
__CONFIG(3, 0x01FF );
__CONFIG(4, 0x29FF);
__CONFIG(5, 0xC00F);
__CONFIG(6, 0xE00F);
__CONFIG(7, 0x000F);
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:
#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));
}
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!
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.
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)
.........
Edito: No funciona,sigue saliendo el error pero no entiendo porque, sigue diciendo lo del error en Fosc 1010
.........
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...
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.
Y como puedo saberlo? en la placa encima del crystal pone JWT20.000.. imagino que de 20MHz no?
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.
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
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;
}
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.