Maikel_DudikoF
05-06-2008, 14:20:10
Tengo que entregar un programa para una asignatura de Informática en la Universidad y estoy clavado. El programa es para realizar un control de temperatura mediante el puerto serie del PC. Se tiene que usar el puerto COMM2 para el envío y la recepción de temperatura. El programa en principio está casi terminado, pero tengo que añadir un par de cosas que me están dando problemas, más que nada porque no controlo mucho de C:
- Controlar la temperatura mediante histéresis (poner un intervalo de temperatura máxima y mínima programables por el usuario)
- El programa debe tomar y mostrar una medida de temperatura cada 5 segundos mediante la programación del timmer0 del micro.
Os pongo el código que tengo hasta ahora y comento:
/************************************************** **************************/
/* Fichero: s2.c */
/* Descripcion: programa para comunicacion serie entre 2 PCs: el programa */
/* lee caracteres del teclado, los visualiza en pantalla y */
/* los envia por el COMM2; ademas tambien lee y visualiza */
/* los caracteres recibidos por dicho puerto */
/* la recepcion se realiza utilizando el mecanismo de */
/* interrupciones; la transmision se realiza por encuesta */
/* Compilador: TC++ 1.01 */
/* Autor: */
/* Fecha: */
/************************************************** **************************/
/****************************/
/* declaracion de funciones */
/****************************/
#include <stdio.h>
#include <conio.h>
#include <dos.h>
/************************************************** *****/
/* direcciones de los registros del controlador puerto */
/************************************************** *****/
#define COMM 0x2F8 // direccion base
// NOTA - cambiar por 0x3F8 si se utiliza el COMM1
#define LCR COMM+3 // Line Control Register
#define DLL COMM // Divisor Latch Lsb
#define DLM COMM+1 // Divisor Latch Msb
#define MCR COMM+4 // Modem Control Register
#define IER COMM+1 // Interruption Enable Register
#define LSR COMM+5 // Line Status Register
#define RBR COMM // Receiver Buffer Register
#define THR COMM // Transmitter Holding Register
/**********************/
/* variables globales */
/**********************/
unsigned short temperatura; // variable para almacenar la temperatura
// global para que puedan acceder a ella RSI y programa
unsigned char consignainf;
unsigned char consignasup;
unsigned char tiempo;
unsigned short flag=0; // variable para sincronizacion entre RSI y programa
unsigned char old_imr;
sbit led=P4^1;
//void interrupt (*old_rsi)();
/****************************************/
/* rutina de atencion a la interrupcion */
/****************************************/
void interrupt comm_rsi(void)
{
temperatura=inportb(RBR);
flag=1;
outportb(0x20,0x20); //EOI
}
/**************************************/
/* rutina de configuracion del puerto */
/**************************************/
void COMM_Configurar (void)
{
outportb(LCR,0x83);
outportb(DLM,0x00);
outportb(DLL,0x0C);
// configuracion de la interrupcion
outportb(LCR,0x03);
outportb(MCR,0x08);
outportb(IER,0x01); //que la interrupcion se dispare cuando llegue algo en RBR
//modificación respecto a la sesion 1
old_imr=inport(0x21);
old_rsi=getvect(0x0B); //COMM2=0x0B - COMM1=0x0C (posible error por numero en hexa)
setvect(0x0B,comm_rsi);
outportb(0x21,old_imr&0xF7); //hab. interr. COMM2 (COMM1 0xEF)
}
/*************************************************/
/* rutina para envio de caracteres por el puerto */
/*************************************************/
void COMM_Enviar (char caracter)
{
char lsr;
do
{
lsr=inportb(LSR);
lsr=lsr & 0x20;
} while (lsr==0);
outportb(THR,caracter);
}
/************************************************** */
/* Rutina para control de temperatura (histeresis) */
/************************************************** */
void control (void)
{
if (temperatura<consignainf)
led=1;
else
if (temperatura>consignasup)
led=0;
}
/**********************/
/* programa principal */
/**********************/
void main (void)
{
// variables
char car_envio=0; // variable para almacenar los caracteres a enviar
// inicializacion de la pantalla
clrscr();
// configuracion del COMM2
COMM_Configurar ();
// bucle principal (el programa acaba al pulsar "Return")
while (car_envio!='\r')
{
// si hay un caracter proveniente del teclado
if (kbhit())
{
// leer el caracter
car_envio = getch();
if (car_envio=='\c')
{
printf("Introduzca la temperatura minima: ");
scanf("%u",&consignainf);
// enviarlo por el COMM2
COMM_Enviar (consignainf);
// incrementar el contador de caracteres enviados
}
if (car_envio=='\d')
{
printf("Introduzca la temperatura maxima: ");
scanf("%u",&consignasup);
// enviarlo por el COMM2
COMM_Enviar (consignasup);
// incrementar el contador de caracteres enviados
}
}
// si se ha recibido un caracter por el COMM2
if (flag==1)
{
// escribir el caracter por pantalla
gotoxy(14,4)
printf("temp: %u\n",temperatura);
flag=0;
}
}
// restaurar mec. interrupciones
setvect(0x0B,old_rsi); //COMM2=0x0B - COMM1=0x0C
outportb(0x20,old_imr);
}
El tema está en la rutina esa de histéresis, que está mal porque se tiene que hacer de otra manera pero ni idea. Me faltaría poder poner los límites de la temperatura en base a lo que se ve en el programa principal (al pulsar "C" se introduce la consigna inferior y con "D" la superior), pero no se qué hacer con eso:aaahhh:
El otro tema sería la de la interrupción, para que muestre el valor de la temperatura cada 5 segundos.
Si alguien tiene ganas de pararse a mirarlo le estaré agradecido, que entiendo que es un coñazo xD
- Controlar la temperatura mediante histéresis (poner un intervalo de temperatura máxima y mínima programables por el usuario)
- El programa debe tomar y mostrar una medida de temperatura cada 5 segundos mediante la programación del timmer0 del micro.
Os pongo el código que tengo hasta ahora y comento:
/************************************************** **************************/
/* Fichero: s2.c */
/* Descripcion: programa para comunicacion serie entre 2 PCs: el programa */
/* lee caracteres del teclado, los visualiza en pantalla y */
/* los envia por el COMM2; ademas tambien lee y visualiza */
/* los caracteres recibidos por dicho puerto */
/* la recepcion se realiza utilizando el mecanismo de */
/* interrupciones; la transmision se realiza por encuesta */
/* Compilador: TC++ 1.01 */
/* Autor: */
/* Fecha: */
/************************************************** **************************/
/****************************/
/* declaracion de funciones */
/****************************/
#include <stdio.h>
#include <conio.h>
#include <dos.h>
/************************************************** *****/
/* direcciones de los registros del controlador puerto */
/************************************************** *****/
#define COMM 0x2F8 // direccion base
// NOTA - cambiar por 0x3F8 si se utiliza el COMM1
#define LCR COMM+3 // Line Control Register
#define DLL COMM // Divisor Latch Lsb
#define DLM COMM+1 // Divisor Latch Msb
#define MCR COMM+4 // Modem Control Register
#define IER COMM+1 // Interruption Enable Register
#define LSR COMM+5 // Line Status Register
#define RBR COMM // Receiver Buffer Register
#define THR COMM // Transmitter Holding Register
/**********************/
/* variables globales */
/**********************/
unsigned short temperatura; // variable para almacenar la temperatura
// global para que puedan acceder a ella RSI y programa
unsigned char consignainf;
unsigned char consignasup;
unsigned char tiempo;
unsigned short flag=0; // variable para sincronizacion entre RSI y programa
unsigned char old_imr;
sbit led=P4^1;
//void interrupt (*old_rsi)();
/****************************************/
/* rutina de atencion a la interrupcion */
/****************************************/
void interrupt comm_rsi(void)
{
temperatura=inportb(RBR);
flag=1;
outportb(0x20,0x20); //EOI
}
/**************************************/
/* rutina de configuracion del puerto */
/**************************************/
void COMM_Configurar (void)
{
outportb(LCR,0x83);
outportb(DLM,0x00);
outportb(DLL,0x0C);
// configuracion de la interrupcion
outportb(LCR,0x03);
outportb(MCR,0x08);
outportb(IER,0x01); //que la interrupcion se dispare cuando llegue algo en RBR
//modificación respecto a la sesion 1
old_imr=inport(0x21);
old_rsi=getvect(0x0B); //COMM2=0x0B - COMM1=0x0C (posible error por numero en hexa)
setvect(0x0B,comm_rsi);
outportb(0x21,old_imr&0xF7); //hab. interr. COMM2 (COMM1 0xEF)
}
/*************************************************/
/* rutina para envio de caracteres por el puerto */
/*************************************************/
void COMM_Enviar (char caracter)
{
char lsr;
do
{
lsr=inportb(LSR);
lsr=lsr & 0x20;
} while (lsr==0);
outportb(THR,caracter);
}
/************************************************** */
/* Rutina para control de temperatura (histeresis) */
/************************************************** */
void control (void)
{
if (temperatura<consignainf)
led=1;
else
if (temperatura>consignasup)
led=0;
}
/**********************/
/* programa principal */
/**********************/
void main (void)
{
// variables
char car_envio=0; // variable para almacenar los caracteres a enviar
// inicializacion de la pantalla
clrscr();
// configuracion del COMM2
COMM_Configurar ();
// bucle principal (el programa acaba al pulsar "Return")
while (car_envio!='\r')
{
// si hay un caracter proveniente del teclado
if (kbhit())
{
// leer el caracter
car_envio = getch();
if (car_envio=='\c')
{
printf("Introduzca la temperatura minima: ");
scanf("%u",&consignainf);
// enviarlo por el COMM2
COMM_Enviar (consignainf);
// incrementar el contador de caracteres enviados
}
if (car_envio=='\d')
{
printf("Introduzca la temperatura maxima: ");
scanf("%u",&consignasup);
// enviarlo por el COMM2
COMM_Enviar (consignasup);
// incrementar el contador de caracteres enviados
}
}
// si se ha recibido un caracter por el COMM2
if (flag==1)
{
// escribir el caracter por pantalla
gotoxy(14,4)
printf("temp: %u\n",temperatura);
flag=0;
}
}
// restaurar mec. interrupciones
setvect(0x0B,old_rsi); //COMM2=0x0B - COMM1=0x0C
outportb(0x20,old_imr);
}
El tema está en la rutina esa de histéresis, que está mal porque se tiene que hacer de otra manera pero ni idea. Me faltaría poder poner los límites de la temperatura en base a lo que se ve en el programa principal (al pulsar "C" se introduce la consigna inferior y con "D" la superior), pero no se qué hacer con eso:aaahhh:
El otro tema sería la de la interrupción, para que muestre el valor de la temperatura cada 5 segundos.
Si alguien tiene ganas de pararse a mirarlo le estaré agradecido, que entiendo que es un coñazo xD