PIC PAL Video Library
<keywords content="TTL 74Ls164N, electronica, circuito, pic, NE555, PIC BASIC, PIC SIMULATOR IDE, esquema, circuito impreso, proyecto, gratis, download, programa, CMOS, pin, e/s, i/o, ucontrol, PIC, 16F628a, 16f84a" /> <center>
| Inicio | Foro | Revista uControl | Circuiteca | Microcontroladores | Electrónica Básica | Herramientas y Software | Tutoriales | Colaboradores | Enlaces |
|
¿Ya descargaste los ejemplares GRATUITOS de la Revista uControl? ¡No te los pierdas!. | |||||||||
|
wikipage=Dado electrónico con PIC
tooltip=Dado electrónico con PIC
img_src=Image:dado100.jpg
img_width=150px
img_alt=Dado electrónico con PIC
</linkedimage> |
wikipage=Como trucar un servo
tooltip=Como trucar un servo
img_src=Image:trucaservo150.jpg
img_width=150px
img_alt=Como trucar un servo
</linkedimage> |
wikipage=Comunicación inalámbrica entre PICs
tooltip=Comunicación inalámbrica entre PICs
img_src=Image:TXRX150.jpg
img_width=150px
img_alt=Comunicación inalámbrica entre PICs
</linkedimage> |
wikipage=CCS - Libreria de gráficos para GLCD K0108
tooltip=CCS - Libreria de gráficos para GLCD K0108
img_src=Image:GLCD-100.gif
img_width=150px
img_alt=CCS - Libreria de gráficos para GLCD K0108
</linkedimage> |
wikipage=Funcionamiento de una matriz de LEDs
tooltip=Funcionamiento de una matriz de LEDs
img_src=Image:GNUxx.jpg
img_width=150px
img_alt=Funcionamiento de una matriz de LEDs
</linkedimage> |
![]() |
Todos los articulos y proyectos de uControl tienen su lugar en el foro. Si tienes dudas o comentarios, busca o crea el hilo correspondiente, y tendrás una rapida respuesta.
|
![]() |
|
PIC PAL Video Library, para usar un TV como pantalla en tus proyectos.
| |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Introducción¿Alguna vez, como parte de alguno de tus proyectos, has necesitado mostrar alguna información en la pantalla de un televisor? Es posible que si. Pero el hardware y el software necesarios para este tipo de proyecto no es fácil de desarrollar. Sin ambargo, ahora podrás hacerlo. Este artículo te mostrará cómo convertir un PIC18 en un generador PAL de graficos y textos (en blanco y negro) con un número muy reducido de componentes de bajo costo, con un mínimo de esfuerzo de programación.
¿Por que una biblioteca PAL para PICs?Si estás utilizando PICs, posiblemente algun diá intentaste construir un dispositivo procesador de vídeo, ya sea para divertirse o como parte de un proyecto más grande. Si intentaste generar señales de vídeo, posiblemente hayas visto alguna de estas paginas web:
He tenido la idea de utilizar una escalera de resistores como una forma rápida y barata cde crear un convertidor digital a analógico, y comenzado a trabajar en el software.
La librería PIC PALComo la pantalla de vídeo que se ha mapeado en memoria, sólo un PIC con suficiente memoria RAM puede utilizar esta librería. Es por ello que la PIC PAL Video Library sólo funciona con la familia PIC18. El PIC debe funcionar a 32 MHz, con un cristal de 8 MHz, para poder obtener los 64 μs necesarios para la sincronización horizontal del sistema PAL. La libreria genera una señal PAL de 625 lineas interlazadas, y puede mostrar hasta 248 lineas verticales de 128 pixeles. Cualquier dispositivo con una entrada PAL de video compuesto puede emplearse para mostrar las imagenes generadas por el PIC. Dado que el manejo de los tiempos es crítico, el software se ha escrito en C con algunas rutinas en ensamblador. El C utilizado es el mikroC, y puedes descargar el proyecto completo (incluido el codigo fuente).
Manual del usuarioEsta es una guía que explica como usar cada una de las funciones contenidas en la librería.
InicializaciónEsta función prepara la librería PIC PAL. Cuanto mayor sea la cantidad de lineas verticales que desees mostrar en el TV, menor será la cantidad de memoria y de recursos que el PIC tenga para el resto del programa. Importante: Esta librería toma el control del TIMER0 y sus interrupciones asociadas. También utiliza el PORTD.
Control de videoEsta función controla la generación de la señal de video. Cuando comienza la sincronización PAL, la variable PAL_frameCtr (unsigned long global) se incrementa 25 veces por segundo.
Pintar pantallaEsta función llena la pantalla con un patrón determinado. Utiliza 0x00 para limpiar la pantalla y 0xFF para pintarla completamente de blanco.
Seleccionar el color del bordeEsta función cambia el color del borde que rodea la imagen.
Dibujar puntosEsta es la función que permite dibujar un punto en una posición determinada de la pantalla.
Dibujar lineasEsta función dibuja una linea desde (x0, y0) a (x1, y1).
Dibujar circulosEsta función dibuja un circulo con centro en (x,y) y radio z.
Dibujar rectangulos rellenosEsta función dibuja (y pinta) un rectangulo.
Dibujar rectangulos vacíosEsta función dibuja un rectangulo vacío.
Escribir un caracter de textoEsta función escribe un caracter de texto en la fila y columna deseada. Puedes usar PAL_box() para escribir en video invertido.
Escribir una cadena de textoEsta función escribe una cadena de texto a partir de la fila y columna deseada.
Escribir una cadena de textom almacenada en la ROMEsta función escribe una cadena de texto a partir de la fila y columna deseada. Es igual a la funcion anterior, pero para textos almacenados en ROM.
Mostrar un BitMap almacenado en ROMDibuja una imagen (BitMap) previamente almacenado en la ROM y apuntado por bm, en la posición (x, y). La imagen será monocroma, y puede utilizarse la herramienta para generar mapas de bits para GLCD T6963 de mikroElektronika para convertir las imagenes.
Rutina de videoEsta función no puede ser llamada directamente por el usuario, perodebe ser colocada dentro de la función interrupt(). Atención: Si están habilitadas, otras interrupciones puede ocasionar problemas de sincronismo en el video.
HardwareLa imagen siguiente muestra el esquema electrico del hardware propuesto. Puedes hacer click sobre la imagen para ver una ampliación.
La señal de salida puede aplicarse directamente a la entrada de video compuesto de un aparato de TV.
SoftwareEl siguiente programa sirve de ejemplo de como puedes utilizar las funciones incluidas en la PIC PAL Library. En un PIC18F4620 utiliza solamente el 25% de la ROM y el 55% de la RAM! La primer pantalla del programa muestra una imagen de 128x128 pixeles, con un borde parpadeante. El programa espera a que se pulse la tecla conectada a RB7 para mostrar la segunda pantalla.
Primer pantalla del ejemplo.
Segunda pantalla del ejemplo.
Código fuente del ejemplo
/*
* file : PALdemo.c
* project : PIC PAL SOFTWARE VIDEO GENERATOR DEMO
* author : Bruno Gavand
* compiler : mikroC V6.2
* date : January 17, 2006
*
* description :
* This program displays a clock, a calendar and the temperature on a TV screen
* and shows how to use the PIC PAL library.
* press RB7 to skip the welcome screen
* to adjust clock and calendar, press :
* RB0 to adjust minute
* RB1 to adjust hour
* RB2 to adjust day
* RB3 to adjust month
* RB4 to adjust year
* RB5 to adjust temperature
* press RB7 at the same time to decrement.
*
* target device :
* PIC18F4620 @ 32 Mhz (8 Mhz crystal + HS PLL)
*
* Licence :
* Feel free to use this source code at your own risks.
*
* history :
* created january 2007
*
* see more details on http://www.micro-examples.com/
*/
#include "PAL_Library.h"
#include "pictures.h"
/*************
* DEFINITIONS
*************/
/*
* graphic clock
*/
#define CLK_CENTER_X 90 // center
#define CLK_CENTER_Y 60
#define CLK_RADIUS_PSS 28 // clock radius
#define CLK_RADIUS_SS 25 // seconds
#define CLK_RADIUS_MN 20 // minutes
#define CLK_RADIUS_HH 15 // hours
#define DEG_NBHISTO 16 // number of temperature samples
/*
* number of vertical pixels
* from 1 to 128 included
* the more pixels you have :
* - the less RAM you have
* - the less MCU time you have
*/
#define PAL_Y 128
/*
* simple time structure definition
*/
typedef struct
{
unsigned char ss ; // seconds
unsigned char mn ; // minutes
unsigned char hh ; // hours
unsigned char md ; // day in month, from 1 to 31
unsigned char wd ; // day in week, monday=0, tuesday=1, .... sunday=6
unsigned char mo ; // month number, from 1 to 12
//(and not from 0 to 11 as with unix C time !)
unsigned int yy ; // year Y2K compliant, from 1892 to 2038
} TimeStruct ;
/********************
* ROM CONSTANTS
********************/
/*
* month names
*/
const unsigned char monthStr[13][4] =
{
"???", "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
} ;
/*
* day of week names
*/
const unsigned char wDaystr[7][4] =
{
"Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"
} ;
/********************
* RAM VARIABLES
********************/
/*
* screen memory map
* do not change this line !
*/
unsigned char PAL_screen[PAL_X * PAL_Y / 8] ;
/*
* general purpose string
*/
unsigned char str[20] ;
char degRef ; // DAC temperature reference
char degHisto[DEG_NBHISTO] ; // temperature samples buffer
char tIdx = 0 ; // temperature samples index
unsigned long secOffset = 0 ; // reference timestamp
unsigned long oldCtr = 0 ; // frame counter backup
TimeStruct ts ; // time struct
/*************************
* FUNCTIONS
*************************/
/*
* adjust time struct member
*/
void adjust(unsigned char *v, unsigned char min, unsigned char max)
{
if(PORTB.F7)
{
if(*v == min) *v = max ;
else (*v)-- ;
}
else
{
if(*v == max) *v = min ;
else (*v)++ ;
}
}
/*
* convert value v into string pointed to by p, leading zero blanks if blk is set
*/
void char2str(unsigned char *p, unsigned char v, unsigned char blk)
{
*p = v / 10 + '0' ;
if(blk && (*p == '0'))
{
*p = ' ' ;
}
p++ ;
*p = v % 10 + '0' ;
p++ ;
*p = 0 ;
}
/*
* draw screen with decoration if full is set, using video mode mode
*/
void drawScreen(unsigned char full, unsigned char mode)
{
static unsigned char osx = CLK_CENTER_X, osy = CLK_CENTER_Y,
omx = CLK_CENTER_X, omy = CLK_CENTER_Y,
ohx = CLK_CENTER_X, ohy = CLK_CENTER_Y ;
unsigned int i ;
int t ;
unsigned char ss ;
unsigned char sx, sy, mx, my, hx, hy ;
PAL_control(PAL_CNTL_START, mode) ;
if(full) // draw full screen with decoration
{
PAL_fill(0) ;
PAL_constWrite( 0, 0, "\xC9\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\
xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xBB", PAL_CHAR_STANDARD) ;
PAL_constWrite( 1, 0, "\xBA PAL LIBRARY DEMO \xBA", PAL_CHAR_STANDARD) ;
PAL_constWrite( 2, 0, "\xC8\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\
xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xBC", PAL_CHAR_STANDARD) ;
PAL_box(0, 0, 127, 21, PAL_COLOR_REVERSE) ;
PAL_constWrite( 3, 0, "\xC9\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCB\xCD\xCD\
xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xBB", PAL_CHAR_STANDARD) ;
PAL_constWrite( 4, 0, "\xBA \xBA \xBA", PAL_CHAR_STANDARD) ;
PAL_constWrite( 5, 0, "\xBA \xBA \xBA", PAL_CHAR_STANDARD) ;
PAL_constWrite( 6, 0, "\xBA \xBA \xBA", PAL_CHAR_STANDARD) ;
PAL_constWrite( 7, 0, "\xBA \xBA \xBA", PAL_CHAR_STANDARD) ;
PAL_constWrite( 8, 0, "\xBA \xBA \xBA", PAL_CHAR_STANDARD) ;
PAL_constWrite( 9, 0, "\xBA \xBA \xBA", PAL_CHAR_STANDARD) ;
PAL_constWrite(10, 0, "\xBA \xBA \xBA", PAL_CHAR_STANDARD) ;
PAL_constWrite(11, 0, "\xCC\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCA\xCD\xCD\
xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xB9", PAL_CHAR_STANDARD) ;
PAL_constWrite(12, 0, "\xBA \xBA", PAL_CHAR_STANDARD) ;
PAL_constWrite(13, 0, "\xBA \xBA", PAL_CHAR_STANDARD) ;
PAL_constWrite(14, 0, "\xBA \xBA", PAL_CHAR_STANDARD) ;
PAL_constWrite(15, 0, "\xC8\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\
xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xBC", PAL_CHAR_STANDARD) ;
PAL_write(4, 3, "H :", PAL_CHAR_DHEIGHT) ;
PAL_constWrite(12, 3, "TEMP. : ", 0x31) ;
PAL_constWrite(12, 17, "\xf8C", 0x31) ;
for(ss = 0 ; ss < 60 ; ss++)
{
sx = CLK_CENTER_X - (cosE3(90 + 6 * ss) * CLK_RADIUS_PSS) / 1000 ;
sy = CLK_CENTER_Y - (sinE3(90 + 6 * ss) * CLK_RADIUS_PSS) / 1000 ;
PAL_setPixel(sx, sy, PAL_COLOR_WHITE) ;
if((ss % 5) == 0)
{
PAL_setPixel(sx + 1, sy, PAL_COLOR_WHITE) ;
PAL_setPixel(sx - 1, sy, PAL_COLOR_WHITE) ;
PAL_setPixel(sx, sy + 1, PAL_COLOR_WHITE) ;
PAL_setPixel(sx, sy - 1, PAL_COLOR_WHITE) ;
}
}
}
if(PAL_frameCtr > OldCtr) // it's time to update the clock & calendar
{
unsigned char h ;
oldCtr = PAL_frameCtr + 24 ; // prepare oldCtr for next update time
// convert timestamp to date and time
Time_EpochToDate(secOffset + PAL_frameCtr / 25, &ts) ;
/*
* draw analog clock
*/
sx = CLK_CENTER_X - (cosE3(90 + 6 * ts.ss) * CLK_RADIUS_SS) / 1000 ;
sy = CLK_CENTER_Y - (sinE3(90 + 6 * ts.ss) * CLK_RADIUS_SS) / 1000 ;
mx = CLK_CENTER_X - (cosE3(90 + 6 * ts.mn) * CLK_RADIUS_MN) / 1000 ;
my = CLK_CENTER_Y - (sinE3(90 + 6 * ts.mn) * CLK_RADIUS_MN) / 1000 ;
h = (ts.hh % 12) * 5 + (ts.mn / 8) ;
hx = CLK_CENTER_X - (cosE3(90 + 6 * h) * CLK_RADIUS_HH) / 1000 ;
hy = CLK_CENTER_Y - (sinE3(90 + 6 * h) * CLK_RADIUS_HH) / 1000 ;
if((hx != ohx) || (hy != ohy))
{
PAL_line(CLK_CENTER_X, CLK_CENTER_Y, ohx, ohy, PAL_COLOR_BLACK) ;
}
if((mx != omx) || (my != omy))
{
PAL_line(CLK_CENTER_X, CLK_CENTER_Y, omx, omy, PAL_COLOR_BLACK) ;
}
if((sx != osx) || (sy != osy))
{
PAL_line(CLK_CENTER_X, CLK_CENTER_Y, osx, osy, PAL_COLOR_BLACK) ;
}
PAL_line(CLK_CENTER_X, CLK_CENTER_Y, hx, hy, PAL_COLOR_WHITE) ;
PAL_line(CLK_CENTER_X, CLK_CENTER_Y, mx, my, PAL_COLOR_WHITE) ;
PAL_line(CLK_CENTER_X, CLK_CENTER_Y, sx, sy, PAL_COLOR_WHITE) ;
/*
* print date and time
*/
char2str(str, ts.ss, 0) ;
PAL_write(4, 7, str, PAL_CHAR_DHEIGHT) ;
char2str(str, ts.mn, 0) ;
PAL_write(4, 4, str, PAL_CHAR_DHEIGHT) ;
char2str(str, ts.hh, 1) ;
PAL_write(4, 1, str, PAL_CHAR_DHEIGHT) ;
PAL_constWrite(6, 2, wdayStr[ts.wd], PAL_CHAR_STANDARD) ;
PAL_constWrite(7, 2, monthStr[ts.mo], PAL_CHAR_DHEIGHT) ;
char2str(str, ts.md, 1) ;
PAL_write(6, 5, str, 0x32) ;
wordToStr(ts.yy, str) ;
PAL_write(9, 1, str + 1, PAL_CHAR_DSIZE) ;
/*
* save old value for fast analog clock cleaning at next update
*/
osx = sx ;
osy = sy ;
omx = mx ;
omy = my ;
ohx = hx ;
ohy = hy ;
t = degRef - Adc_Read(4) ; // read temperature sensor
t *= 221 ; // temperature coefficient of the silicon junction
t /= 102 ;
t = 25 + t ; // get the result in celcius
/*
* adjust limits
*/
if(t < -99)
{
t = -99 ;
}
if(t > 99)
{
t = 99 ;
}
/*
* average values
*/
degHisto[tIdx] = t ;
tIdx++ ;
if(tIdx == DEG_NBHISTO)
{
tIdx = 0 ;
}
t = 0 ;
for(i = 0 ; i < DEG_NBHISTO ; i++)
{
t += degHisto[i] ;
}
t /= DEG_NBHISTO ;
/*
* print temperature
*/
if(t < 0)
{
i = -t ;
PAL_constWrite(12, 11, "-", 0x31) ;
}
else
{
i = t ;
PAL_constWrite(12, 11, " ", 0x31) ;
}
char2str(str, i, 1) ;
PAL_write(12, 12, str, 0x32) ;
}
// restore video rendering if it was stopped
PAL_control(PAL_CNTL_START, PAL_CNTL_RENDER) ;
}
/*
* interrupt service routine
*/
void interrupt(void)
{
/*
* do PAL stuff
*/
PAL_ISR() ; // library call
}
/*
* main program
*/
void main(void)
{
unsigned char i ;
/*
* I/O configuration
*/
ADCON1 = 0x0f ;
TRISA = 0xff ;
PORTA = 0 ;
TRISB = 0xff ;
PORTB = 0 ;
TRISC = 0xff ;
PORTC = 0 ;
TRISD = 0 ;
PORTD = 0 ;
TRISE = 0 ;
PORTE = 0 ;
degRef = EEPROM_read(0) ; // get temperature calibration from EEPROM
/*
* default time and date
*/
ts.ss = 0 ;
ts.mn = 0 ;
ts.hh = 12 ;
ts.md = 1 ;
ts.mo = 1 ;
ts.yy = 2007 ;
secOffset = Time_dateToEpoch(&ts) ;
/*
* start video and display first screen
*/
PAL_init(PAL_Y) ; // init PAL library
PAL_fill(0) ; // clear screen
PAL_picture(0, 0, logo_bmp, 128, 128) ; // paint picture
PAL_control(PAL_CNTL_START, PAL_CNTL_RENDER) ; // start video and rendering
i = 0 ;
while(PORTB == 0) // wait for a key to be pressed
{
/*
* change border color two times per second
*/
if(PAL_frameCtr > 12)
{
PAL_setBorder(i) ;
i = !i ;
PAL_frameCtr = 0 ;
}
}
PAL_setBorder(PAL_COLOR_BLACK) ;// clear border
drawScreen(1, PAL_CNTL_BLANK) ;// draw full screen in blank mode (faster)
for(;;)
{
if(PORTB & 0b1111111) // a key is pressed
{
Time_EpochToDate(secOffset + PAL_frameCtr / 25, &ts) ;
/*
* calendar settings
*/
if(PORTB.F0)
{
adjust(&ts.mn, 0, 59) ;
ts.ss = 0 ;
}
if(PORTB.F1)
{
adjust(&ts.hh, 0, 59) ;
ts.ss = 0 ;
}
if(PORTB.F2)
{
adjust(&ts.md, 1, 31) ;
}
if(PORTB.F3)
{
adjust(&ts.mo, 1, 12) ;
}
if(PORTB.F4)
{
if(PORTB.F7) ts.yy-- ; else ts.yy++ ;
}
secOffset = Time_dateToEpoch(&ts) ; // new timestamp
/*
* temperature calibration
*/
if(PORTB.F5)
{
if(PORTB.F7)
{
degRef-- ;
EEPROM_write(0, degref) ;
}
else
{
degRef++ ;
EEPROM_write(0, degref) ;
}
}
while(PORTB & 0b1111111) ; // wait for the key to be released
PAL_frameCtr = 0 ; // reset counters
oldCtr = 0 ;
}
drawScreen(0, PAL_CNTL_RENDER) ; // update screen
}
}
DescargasPuedes descargar el proyecto completo, incluido el codigo fuente del ejemplo desde aqui: Dentro del archivo ZIP encontrarás:
Autor
El artículo original (en inglés) puede encontrarse en la página de Bruno: www.micro-examples.com | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Este contenido se rige por la licencia de Creative Commons "Licencia Creative Commons Atribución-No Comercial-Sin Obras Derivadas 3.0". Para más información, véase la licencia en su forma reducida y completa. |

