informática industrial. 3º iti electrónica.

Anuncio
INFORMÁTICA INDUSTRIAL. 3º ITI ELECTRÓNICA.
Práctica 3: Microcontrolador 8051: Programación en C para
monitorización a través de display LCD, de temperatura y tensión.
Objetivos.
Con esta práctica se pretende ilustrar el uso de la programación en C para
microcontroladores usando interrupciones. Así como el funcionamiento de los displays
LCDs, de los convertidores A/D y de los "timers" en los microcontroladores.
El alumno deberá traer a la práctica tanto el enunciado como la documentación del
microcontrolador Cygnal 8051 entregada durante el curso, y la documentación
adicional de esta práctica referente al display LCD.
Durante la práctica el alumno hará una primera toma de contacto con la placa ATC-C8051A, encendiendo y apagando los 2 leds de que dispone dicha placa, a una frecuencia
determinada sin hacer uso de ningún recurso del micro. Posteriormente realizará la misma
operación haciendo uso de los timers para controlar los tiempos. Y en la última etapa de la
práctica realizará un código que mediante interrupción, activada por fin de conversión del
ADC, y que muestre por pantalla LCD la temperatura del sensor interno del
microcontrolador, y la tensión que entra por una patilla del C8051, usando para visualizar
los resultados un display LCD. La práctica se puede dividir en dos grandes apartados, con
diversas fases cada uno:
1. Control básico con el microcontrolador C8051 de Cygnal.
1.1. Control de LEDs a una frecuencia determinada mediante polling.
1.2. Control de LEDs a una frecuencia marcada por Timer2 sin interrupciones.
2. Control avanzado con el microcontrolador C8051 de Cygnal.
2.1. Control de LEDs mediante interrupción lanzada por el ADC en fin de conversión.
El ADC se activa cuando se desborda Timer2.
2.2. Ampliación de la rutina de interrupción para que cambie la fuente de ADC, de
forma periódica, entre el termómetro interno y una entrada analógica de los GPIO.
2.3. Mostrar por pantalla LCD los resultados del ADC capturados por la interrupción.
Displays de cristal líquido.
Los visualizadores más usados en los entornos de los computadores son de dos tipos: de
tubo de rayos catódicos (CRT) o de cristal líquido. Los primeros son los clásicos monitores
con tecnología similar a la usada por los televisores domésticos. Las principales ventajas de
este tipo de sistemas es su relativo bajo coste, consiguiéndose muy buena resolución y una
gran gama de colorido (con enormes posibilidades gráficas). Sin embargo este tipo de
visualizadores tienen dos grandes inconvenientes: el consumo y el tamaño. Si además se
tiene en cuenta que en muchas ocasiones no son necesarias unas prestaciones gráficas tan
elevadas, se entiende como han surgido con tanta fuerza los visualizadores tipo LCDs. Los
"displays" LCD están compuestos por un "cristal liquido" retenido entre dos placas
transparentes conductoras. Dicho cristal cambia su estado de visualización dependiendo del
potencial a que se somete las placas conductoras, estas deben estar divididas en pequeñas
celdas controlables independientemente para poder activar cada elemento que compone el
visualizador. Según se puede deducir de esta descripción básica, la primera característica
1
que destaca de los LCDs es su bajo consumo, las placas conductoras se comportan como
condensadores que se cargan o descargan. La segunda característica a resaltar es la
posibilidad de miniaturización, en la actualidad hay televisores portátiles del tamaño de un
reloj de pulsera con pantallas LCDs en color. El "cristal líquido" del que están compuestos
los LCDs puede actuar de dos formas diferentes: cambiando la reflectividad o la
transparencia. En el primer caso es la luz que incide y se refleja sobre la pantalla la que
permite ver la información, en el segundo es la luz que pasa a través de la pantalla la que
descubre el mensaje. Todos los LCD usan ambos métodos de visualización, pero
dependiendo de cual es el principal se puede distinguir dos tipos de LCD: de iluminación
frontal y retroiluminados. Los primeros son los más normales, su uso se ha extendido en
relojería, el principal problema de este tipo de LCDs es que el ángulo de visualización suele
ser pequeño. Los retroiluminados son menos frecuentes, disponen de una superficie
reflectora en la que se apoyan las dos placas que contienen el "cristal líquido", además
suelen incluir un sistema de iluminación trasero artificial mediante lámpara. La ventaja
principal de este tipo de LCDs es que el ángulo de visualización es mucho mayor, además
al tener luz propia pueden visualizarse en lugares de escasa iluminación, sin embargo el
coste de este tipo de LCD es mucho mayor.
La tensión que se debe aplicar a cada una de las placas conductoras no puede ser continua
(posibilidad de rotura), debe ser una onda cuadrada, si las dos placas tienen dicha señal en
fase el "cristal liquido" es transparente, si no están en fase es opaco. Por tanto, en principio,
para gobernar un display LCD se necesitarían dos señales para cada elemento activo
celdilla). Lo normal es que el control de cada celdilla y de las señales necesarias se lleve a
cabo por un controlador específico que independice completamente la visualización de la
aplicación que se pretenda desarrollar. En la mayoría de los casos se encuentran el
controlador y la pantalla LCD integrado en una sola pieza, de forma que basta una
"interface hard" simple y unos pocos comandos para gobernar completamente un
visualizador, por muy compleja que sea la pantalla LCD.
Antecesores de los LCD son los visualizadores basados en diodos "LEDs", en este tipo de
dispositivos el mensaje se compone según se encuentre encendido o apagado un diodo; las
pantallas de los primeros relojes digitales de pulsera eran de este tipo ("números rojos o
verdes"), la principal dificultad de los visualizadores LEDs es el consumo y la
miniaturización. Realmente se puede conseguir pantallas LEDs pequeñas pero de muy poca
resolución, es por ello que el uso de LEDs en visualizadores pequeños se limita a aquellas
aplicaciones en que la información a representar es pequeña, como son visualizadores de 7
segmentos (relojes digitales), barras (equipos de audio), etc. Sin embargo en aplicaciones
en las que el tamaño de la pantalla es apreciable es preferible el uso de sistemas basados en
diodos LEDs: anuncios comerciales de gran tamaño, marcadores electrónicos en
instalaciones deportivas, anuncios en autobuses, oficinas, ventanillas, etc. En estos casos la
información puede ser compleja, inclusive información gráfica de bastante resolución.
En el mercado se pueden encontrar una amplia gama de visualizadores LCD. Los más
simples son los usados por los relojes digitales, que incluyen dígitos de 7 segmentos más
unos cuantos símbolos o caracteres fijos (AM, PM, ALM, etc.). Otros son muy complejos,
como las pantallas de los ordenadores portátiles, que pueden tener características similares
a las usadas en los ordenadores de sobremesa, pero con un coste más elevado. Diversos
fabricantes de LCDs ofertan diseños específicos para aquellas aplicaciones empotradas con
suficiente número de unidades a construir (por ejemplo displays LCDs que usan: los GPS
de SONY, algunas impresoras láser, voltímetros digitales, automóviles, etc.).
2
Esta gran diversidad de visualizadores LCDs podría hacer pensar que también hay una gran
variedad de controladores. Sin embargo, en lo que se refiere a displays alfanuméricos de
uso general, se ha impuesto un sistema controlador desde hace varios años, de forma que en
la actualidad es prácticamente un "estándar": el Hitachi HD44780 (forma sistema con el
HD44100). Este circuito puede gobernar una gran diversidad de LCDs, en principio desde
pantallas de 1 línea por 16 caracteres hasta de 2 líneas por 40.
Extensiones del HD44780 permiten gobernar displays alfanuméricos más complejos. Con
respecto a los displays LCD gráficos hay una mayor variedad de controladores, los más
tradicionales son el MSM6255 y el HD64645 (software compatible con el más clásico de
los controladores para CRT, el HD6845).
En esta práctica se usará un display alfanumérico retroiluminado (el LM091LN, de 2 líneas
por 20 caracteres de 5x7 "dots"), controlado por el HD44780. Al final del texto explicativo
de la práctica se pueden encontrar fotocopias de los manuales del LM091LN y del
HD44780.
El LCD LM091LN y el controlador HD44780.
El HD44780 dispone de 192 caracteres en ROM, más la posibilidad de definir otros 8 por
parte del diseñador (en RAM). Dispone de dos tipos de RAM: una donde se almacena el
carácter que se visualiza en cada posición del LCD (DD RAM) y otra que sirve para definir
nuevos símbolos (CG RAM). La cantidad de memoria para la visualización de caracteres es
de 80 bytes, de forma que cada posición del display se asocia a una posición de memoria en
la DD RAM, por tanto un display como el usado en la práctica de 2 x 20 sólo usa la mitad
de la DD RAM, siendo la otra mitad inútil para la visualización (a no ser que se produzcan
desplazamientos que pasen los datos a la mitad visible). De forma general siempre la
primera línea empieza en la posición $80 (realmente 00) y la segunda, si la hubiese, en la
$C0 (realmente $40). Si fuese un display de 4 líneas por 20, la tercera línea empezaría
después de la primera y la cuarta después de la segunda.
La transferencia entre el sistema procesador (68HC11 en nuestro caso) y el HD44780
puede ser mediante un bus de 8 o 4 bits. Con los microcontroladores en modo "single-chip"
es tradicional usar la "interface" de 4 bits para ahorrar puertos, sin embargo en sistemas con
bus de datos, direcciones y control externos es común usar 8 bits.
El controlador de LCD dispone de dos registros accesibles desde el exterior, el registro de
instrucciones (IR) y el de datos (DR), la señal RS indica cuando se accede a uno u otro.
Estos se pueden leer o escribir dependiendo de la señal R/W. Por tanto las cuatro
operaciones básicas son:
Escribir en el IR:
En este caso se envía un comando al LCD, que puede ser:
• Borrar Display (pone cursor en HOME): b 0 0 0 0 0 0 0 1
• Poner cursor en Home: b 0 0 0 0 0 0 1 X
• Modo de entrada: b 0 0 0 0 0 1 I/D S
S=1 Display se desplaza al escribir un nuevo carácter
S=0 Display no se desplaza " ....
I/D=1 Incremento automático del AC (contador de direcciones, apuntador)
I/D=0 Decremento automático del AC
3
• Control del display: b 0 0 0 0 1 D C B
B=1 Activa parpadeo cursor
B=0 Desactiva parpadeo cursor
C=0 Cursor no visible
C=1 Cursor visible
D=0 Apaga LCD
D=1 Enciende LCD
• Desplazamiento del cursor/display: b 0 0 0 1 S/C R/L X X
R/L=0 Desplazamiento a la izquierda
R/L=1 Desplazamiento a la derecha
S/C=0 Desplazamiento se aplica sobre el cursor
S/C=1 Desplazamiento se aplica sobre todo el display
• Control por 4 u 8 bits: b 0 0 1 D/L N F X X
D/L=0 Control 4 bits (se usan las líneas de datos DB4-DB7),
se manda primero parte alta, seguida de parte baja.
D/L=1 Control con 8 bits.
N=0 display con una línea activa
N=1 display con dos líneas activas
F=0 caracteres de 5x10 "dots"
F=1 caracteres de 5x7 "dots"
• Poner dirección CG RAM: b 0 1 CG5 CG4 CG3 CG2 CG1 CG0
Después de este comando los datos que se escriban se cargarán en la CG RAM.
• Poner dirección DD RAM: b 1 DD6 DD5 DD4 DD3 DD2 DD1 DD0
Después de este comando los datos que se escriban se cargarán en la DD RAM y se
visualizarán por el LCD.
Leer del IR: cuando se lee este registro informa con el bit 7 si está o no listo para recibir
un nuevo dato o comando (BF = BUSY FLAG), este bit hay que "testearlo" antes de
escribir en el HD44780 (BF=1 ocupado, BF=0 desocupado y listo para recibir otro dato o
comando). Los restantes bits (del 0 al 6) informan del AC (contador de dirección), éste
apunta a la dirección actual de la DD RAM (posición del cursor en el LCD) y de la CG
RAM.
Escribir en el DR: permite escribir en la posición actual (apuntada por AC) un dato o en
la DD RAM (pantalla LCD) o en la CG RAM.
Leer del DR: Permite leer de la posición apuntada por AC un dato de la DD RAM o de la
CG RAM.
El AC (contador de dirección) cada vez que se escribe un dato se incrementa o decrementa
dependiendo del modo seleccionado.
El código de los caracteres que visualizan por el LCD se corresponde con el ASCII (ver
fotocopias adjuntas, Apéndice 3), siendo los 8 primeros caracteres (del 0 al 7) los
correspondientes a los símbolos definidos en la CG RAM (tabla 3.4 de manual del
HD44780). Para cargar un símbolo en la CG RAM debe de colocarse en que posición de la
CG RAM desea cargarse, y posteriormente enviar 8 datos con el formato del símbolo. Hay
4
64 posiciones de CG RAM, para formar 8 posibles símbolos con 8 bytes de formato (ver
fotocopias del HD44780).
La placa ATC-C8051-A.
Esta placa ha sido desarrollada por el departamento de Arquitectura y Tecnología de
Computadores. El núcleo de la placa en un microcontrolador Cygnal 8051, que está
alimentado a través del bus USB, y que es accesible a través de un pin en la placa. El micro
tiene sus puertos P0-P2 accesibles desde el exterior por medio de arrays de pines. Dispone
además de un puerto JTAG para programar y depurar el microcontrolador. En la siguiente
figura se muestra un esquema de dicha placa.
2
1
L1 L2
J1
USB
2
1
1
3
J4
2
J2
JTAG
J3
1
2
1
2
Figura 1: Esquema de la placa ATC-C8051-A
Descripción de los conectores:
- JTAG: Interfaz con el adaptador serie EC2 de depuración del Cygnal.
- USB: Conector USB esclavo. Sólo usado para alimentación de 5v en esta práctica.
- L1 y L2: LEDs conectados a los puertos J1.1 y J1.3 respectivamente.
- J1, J2 y J3: Terminales de GPIO. Únicamente los pines impares corresponden con
líneas de entrada/salida del microcontrolador. Todas las líneas pares son GND.
Corresponden con los puertos P0 a P2 según la siguiente tabla:
J1 P2
1 7
3 6
5 5
7 4
9 3
11 2
13 1
15 0
-
J2
1
3
5
7
9
11
13
15
P1
7
6
5
4
3
2
1
0
J3
1
3
5
7
9
11
13
15
P0
7
6
5
4
3
2
1
0
J4: Reset y alimentación, según la siguiente tabla:
J4
Descripción
5
1
2
3
USB Vdd (5v)
GND
Reset (si conectado a GND)
Desarrollo de la práctica.
1. Control básico con el microcontrolador C8051 de Cygnal.
1.1. Control de LEDs a una frecuencia determinada mediante polling.
En este primer apartado se pretende encender y apagar los LEDs de la placa ATCC8051-A a una frecuencia determinada por el número de iteraciones de un bucle en el
main de nuestro programa.
Haciendo uso de la siguiente plantilla rellene el código necesario dentro del main para
conseguir el parpadeo de los LEDs. Tenga en cuenta que un número pequeño de
iteraciones puede implicar un parpadeo tan rápido que el propio LED no tenga tiempo
de encenderse y apagarse, con lo que se vería un poco atenuado, pero sin parpadeo.
/*
INFORMÁTICA INDUSTRIAL
3º ITI ELECTRÓNICA.
EUP
DPTO. ARQUITECTURA Y TECNOLOGÍA DE COMPUTADORES
UNIVERSIDAD DE SEVILLA
PROF. ALEJANDRO LINARES BARRANCO
******************************************/
#include <c8051f320.h>
// Declaraciones SFR
// System clock selections (SFR CLKSEL)
#define SYS_INT_OSC
0
//-----------------------------------------------------------------------// Constantes Globales
//-----------------------------------------------------------------------sbit LED3 = P2^6; // LED='1' significa encendido
sbit LED4 = P2^7;
//-----------------------------------------------------------------------// Prototipos de funciones globales
//-----------------------------------------------------------------------void PORT_Init (void);
void SYSCLK_Init (void);
//-----------------------------------------------------------------------// Variables globales
//-----------------------------------------------------------------------unsigned long int i;
//-----------------------------------------------------------------------// Routina principal
//-----------------------------------------------------------------------void main (void)
{
PCA0MD &= ~0x40;
// Deshabilita el Watchdog timer
PORT_Init ();
// Inicializa Crossbar y GPIO
SYSCLK_Init ();
// Inicializa oscilador
LED3=0;
LED4=0;
while (1){ // Bucle infinito.
// Poner led3 a 1 y led4 a 0.
// Esperar un tiempo con un bucle for.
// Poner led3 a 0 y led4 a 1.
// Esperar el mismo tiempo que antes.
}
}
//-----------------------------------------------------------------------// Rutinas de Inicialización
//-----------------------------------------------------------------------//---------------------------
6
// SYSCLK_Init
//--------------------------// Inicialización de SYSLCK
// - Inicializa el reloj del sistema.
void SYSCLK_Init (void)
{
unsigned char delay = 100;
OSCICN |= 0x83;
CLKMUL = 0x00;
CLKMUL |= 0x80;
while (delay--);
CLKMUL |= 0xC0;
while(!CLKMUL & 0x20);
CLKSEL |= SYS_INT_OSC;
//
//
//
//
//
//
//
//
//
Configura el oscilador interno a
su frecuencia máxima
Selecciona al oscilador interno como
entrada del multiplicador de reloj
Habilita el multiplicador de reloj
Espera algo más de 5us
Inicializa el multiplicador de reloj
Espera a que el multiplicador esté preparado
Selecciona el reloj del sistema
}
//--------------------------// PORT_Init
//--------------------------// Inicialización de Puertos
// - Configuración del Crossbar y los puertos GPIO.
void PORT_Init (void)
{
P2MDIN
= 0xDE;
// P2.0 y P2.5: Entrada analógica
P0MDOUT = 0xFF;
// P0.0-P0.6: push-pull
P1MDOUT = 0xFF;
// P1.0-P1.7: push-pull
P2MDOUT = 0xCC;
// P2.3-P2.2: push-pull
P2SKIP
= 0x01;
// P0.7 saltado en el Crossbar
XBR0
= 0x00;
//
XBR1
= 0x40;
// Habilitar el Crossbar
}
1.2. Control de LEDs a una frecuencia marcada por Timer3 sin interrupciones.
En este apartado de la práctica hemos de añadir la inicialización del timer3 del C8051, e
invocarlo cada vez que queramos hacer una espera y resetearlo cuando concluya dicha
espera.
Para la realización de este apartado usar la plantilla anterior añadiendo la función que
inicialize el timer3 para ser usado con 16 bits y autorecarga, sin interrupción.
Modificar la plantilla anterior y sustituir los bucles for por activaciones del timer 3 y
esperas de fin de cuenta.
//--------------------------// Timer3_Init
//--------------------------// Inicialización del Timer 3
// - Timer3 configurado para desbordarse a la frecuencia
// definida por <SAMPLERATE> para las conversiones del ADC
//
void Timer3_Init ()
{
TMR3CN = 0x00;
// Detener Timer3; Limpiar TF3;
CKCON &= 0xBF;
// SYSCLK/12 como fuente de reloj del Timer3
TMR3RL = 0x0000;
// Tope de cuenta de Timer3
TMR3
= 0x0000;
// y se recarga inmediatamente.
}
El tope de la cuenta del Timer3 se ha puesto al máximo que se permite con el reloj
interno, que implica una espera de 65.5 ms antes de cambiar el estado de los LEDs.
2. Control avanzado con el microcontrolador C8051 de Cygnal.
2.1. Control de LEDs mediante interrupción lanzada por el ADC por fin de conversión. El
ADC se activa cuando se desborda Timer2.
7
En este apartado de la práctica vamos a programar el timer2 para que se incremente con
la frecuencia de SYSCLK y que se desborde cada –(SYSCLK/SAMPLERATE), siendo
SAMPLERATE la cadencia de muestreo que deseamos para el convertidor.
El timer2 se programará con autorecarga para ahorrar operaciones en la rutina de
interrupción.
El convertidor ADC se programará para que inicie la conversión cada vez que se
desborde el timer2, usando un reloj SAR de 2MHz, con los datos justificados a la
derecha, con medición single-ended (el polo negativo a GND), y con interrupción de fin
de conversión habilitada.
La rutina de interrupción corresponde con la IRQ 10 del microcontrolador y en ella
vamos a incrementar un contador interno. Cada vez que el contador llegue a 20000
volverá a 0. Si la cuenta es menor de 10000 el estado de los LEDs debe ser opuesto a si
la cuenta es superior o igual a 10000.
El programa principal permanecerá ciclado en un bucle infinito sin hacer nada:
while (1);
La rutina de inicialización del timer2 y del ADC se muestran a continuación, así como
la plantilla para la rutina de interrupción.
sfr16 TMR2RL
= 0xca;
sfr16 TMR2
= 0xcc;
#define SYSCLK
23560000
#define SAMPLERATE
100000
#define AMX_TEMP_SENSE
0x1E
#define AMX_P2_0
0x08
#define AMX_GND
0x1F
// Timer2 reload
// Timer2 counter
// SYSCLK frequency in Hz
// ADC0 Sample Rate
// Temperature sensor
// P2.0 (potentiometer)
// Ground
//-----------------------------------------------------------------------// Routina principal
//-----------------------------------------------------------------------void main (void)
{
PCA0MD &= ~0x40;
// Desactiva Watchdog timer
PORT_Init ();
// Inicializa Crossbar and GPIO
SYSCLK_Init ();
// Inicializa oscillator
Timer2_Init ();
// Inicializa timer2
ADC_Init ();
// Inicializa ADC
EA = 1;
// Enable global interrupciones
LED3=1;
LED4=1;
cnt=0;
while (1){ // Bucle infinito.
}
}
//-----------------------------------------------------------------------// Rutina de servicio de interrupción
//-----------------------------------------------------------------------//--------------------------// ADC0_ISR
//--------------------------// - Guarda el dato convertido por el ADC
// - Actualiza el multiplexor para la próxima conversión
// - Cada 10000 llamadas a la interrupción se modifica el estado de los LEDs
//
void ADC0_ISR (void) interrupt 10
{
// Incremento del contador
// Cada 10000 desbordamientos de timer2 se modifica el estado de los LEDs
}
8
//-----------------------------------------------------------------------// Rutinas de Inicialización
//-----------------------------------------------------------------------//--------------------------// ADC_Init
//--------------------------// Inicialización del ADC
// - Modo Single-ended
// - Comienza la conversión cuando el Timer2 se desborda (overflows)
// - Datos justificados a la izquierda
// - Activa el modo trackign a baja potencia debido a la variación analógica
//
de la entrada (para apartado 2.2)
// - Habilita las Interrupciones
void ADC_Init (void)
{
REF0CN = 0x0E;
// Habilita el sensor de Temperatura,
// el bias interno
// y la tensión de referencia interna
// (para apartado 2.2)
AMX0P = AMX_TEMP_SENSE;
// Conecta el sensor de temp. como entrada
positiva
AMX0N = AMX_GND;
// y la tierra (GND) como la negativa
// (single-ended)
ADC0CF = (SYSCLK/2000000) << 3;
// SAR clock configurado a 2MHz
ADC0CF &= 0xFB;
// Datos justificados a la derecha
ADC0CN = 0xC2;
// ADC0 habilitado, con modo
// tracking de baja potencia y
// convirtiendo cuando se desborda Timer2
EIE1 |= 0x08;
// Habilita la interrupción de conversión
// finalizada
}
//--------------------------// Timer2_Init
//--------------------------// Inicialización del Timer 2
// - Timer2 configurado para desbordarse a la frecuencia
// definida por <SAMPLERATE> para las conversiones del ADC
//
void Timer2_Init ()
{
TMR2CN = 0x00;
// Detener Timer2; Limpiar TF2;
CKCON |= 0x10;
// SYSCLK como fuente de reloj del Timer2
TMR2RL = -(SYSCLK/SAMPLERATE);
// Timer2 se desborda con <SAMPLERATE>
TMR2
= 0xFFFF;
// y se recarga inmediatamente.
TR2
= 1;
// Comienza Timer2
}
2.2. Ampliación de la rutina de interrupción para que cambie la fuente de ADC de
forma periódica.
En este apartado simplemente hemos de tocar la rutina de interrupción para que
modifique la fuente del convertidor ADC cada vez que se cambia el estado del
LED3.
Para ello hemos de añadir una sentencia ‘if’ que modifique el valor de AMX0P para
que alterne entre el sensor de temperatura y la patilla 2.0 de los GPIO.
2.3 Mostrar por pantalla LCD los resultados del ADC capturados por la interrupción.
Por último, se pretende que nuestra placa entrenadora ATC-8051-A se conecte con
un display LDC para mostrar los valores de temperatura y tensión que estamos
midiendo al tiempo que cambiamos los LEDs de estado.
La temperatura obtenida en el convertidor ADC se convierte a grados centígrados
siguiendo la siguiente fórmula:
9
T= 4+((33000*ADC/1024)-77600)/286
Y la tensión se convierte en mili voltios siguiendo la siguiente fórmula:
V=3300*ADC/1024;
Para ello, se ofrece una serie de funciones que permiten la interacción con el
display:
-
LCD_Init() inicializa el display activando las dos filas de caracteres, borrando
la pantalla y llevando el cursor al inicio (Home) y apagándolo.
LCD_DisplayString(int fila, int columna, char *texto) Escribe en la posición
que se indique (fila,columna) la cadena de texto correspondiente. Se debe tener
presente que sólo tenemos 2 filas y 20 columnas. Esta rutina llama a otras de
más bajo nivel que interactúan con el display. Para ello hace uso del timer3, el
cual debe estar configurado para que haga una espera de 32,7 ms cada vez que
se active.
Utilice la siguiente plantilla para realizar este apartado:
//-----------------------------------------------------------------------// Routina principal
//-----------------------------------------------------------------------void main (void)
{
char ch_temp[20],ch_volt[20];
unsigned int t,v;
PCA0MD &= ~0x40;
// Desactiva Watchdog timer
PORT_Init ();
SYSCLK_Init ();
Timer2_Init ();
Timer3_Init ();
ADC_Init ();
EA = 1;
VDD = 1;
TEST=1;
LCD_Init();
//
//
//
//
//
//
Inicializa Crossbar and GPIO
Inicializa oscillator
Inicializa timer2
Inicializa timer3
Inicializa ADC
Enable global interrupciones
// Inicialización del display
LED3=1;
LED4=1;
cnt=0;
LCD_DisplayString(1,1,"Temperatura:");
LCD_DisplayString(2,1,"Tension:");
while (1){ // Bucle infinito. Mostramos por Display LCD la temperatura
// y el valor de tensión de P1.7
// que la rutina de interrupción irá modificando.
t=4+(((long int)IN_PACKET[0]*330000/1024)-77600)/286;
sprintf(ch_temp,"%4d",t);
LCD_DisplayString (1,14, ch_temp);
LCD_DisplayString (1,19,"oC");
v=(3300*(unsigned long int)IN_PACKET[1])/1024;
sprintf(ch_volt,"%4d",v);
LCD_DisplayString (2,14, ch_volt);
LCD_DisplayString (2,19,"mV");
}
}
/*
** LCD_Init: Initialize the LCD.
10
*/
void LCD_Init (void)
{
LCD_InitDriver();
LCD_Clear();
LCD_CursorOff();
}
/*
** LCD_DisplayCharacter: Display a single character,
**
at the current cursor location.
*/
void LCD_DisplayCharacter (char a_char)
{
LCD_WriteData (a_char);
}
/*
** LCD_DisplayString: Display a string at the specified row and column.
*/
void LCD_DisplayString (char row, char column, char *string)
{
LCD_Cursor (row, column);
while (*string)
LCD_DisplayCharacter (*string++);
}
/*
** LCD_CursorOff: Turn the cursor off.
*/
void LCD_CursorOff (void)
{
LCD_WriteControl (0x0c);
}
/*
** LCD_Cursor: Position the LCD cursor at "row", "column".
*/
void LCD_Cursor (char row, char column)
{
switch (row) {
case 1: LCD_WriteControl (0x80 + column - 1); break;
case 2: LCD_WriteControl (0xc0 + column - 1); break;
default: break;
}
}
/*
** LCD_Clear: Clear the LCD screen (also homes cursor).
*/
void LCD_Clear (void)
{
LCD_WriteControl(0x01);
}
/*
** LCD_WriteControl: Write a control instruction to the LCD
*/
void LCD_WriteControl (unsigned char dat)
{
int i;
// RS=0, R/W=0, E=0
RS=0;
RW=0;
EN=0;
DB0=dat%2;
DB1=(dat/2)%2;
DB2=(dat/4)%2;
DB3=(dat/8)%2;
DB4=(dat/16)%2;
DB5=(dat/32)%2;
DB6=(dat/64)%2;
DB7=(dat/128)%2;
// RS=0, R/W=0, E=1
11
RS=0;
RW=0;
EN=1;
// RS=0, R/W=0, E=0
RS=0;
RW=0;
EN=0;
// RS=0, R/W=1, E=0
RS=0;
RW=1;
EN=0;
TMR3CN |= 0x04;
// Comienza Timer3
i=0;
while (!(TMR3CN & 0x80)) i++; // Espera a que se desborde el timer
TMR3CN = 0;
// Detiene el Timer3
//TMR3 = 0x8000;
// Inicializa la cuenta del timer.
}
/*
** LCD_WriteData: Write one byte of data to the LCD
*/
void LCD_WriteData (unsigned char dat)
{
int i;
// RS=1, R/W=0, E=0
RS=1;
RW=0;
EN=0;
DB0=dat%2;
DB1=(dat/2)%2;
DB2=(dat/4)%2;
DB3=(dat/8)%2;
DB4=(dat/16)%2;
DB5=(dat/32)%2;
DB6=(dat/64)%2;
DB7=(dat/128)%2;
// RS=1, R/W=0, E=1
RS=1;
RW=0;
EN=1;
// RS=1, R/W=0, E=0
RS=1;
RW=0;
EN=0;
// RS=1, R/W=1, E=0
RS=1;
RW=1;
EN=0;
TMR3CN |= 0x04;
// Comienza Timer3
while (!(TMR3CN & 0x80)); // Espera a que se desborde el timer
TMR3CN = 0;
// Detiene el Timer3
//TMR3 = 0x8000;
// Inicializa la cuenta del timer.
}
12
Descargar