gentoo linux, java, software libre y otras hierbas
Ene, 21 2008 - 10:48 am

Curso de programación en C para GNU/Linux

Ya hace un tiempo que escribí un manual de programación de C++ sobre Linux; esta vez Pablo Garaizar ha hecho un tutorial de referencia aún más completo acerca de este tema tan importante e interesante. En él se explican varios aspectos que circundan la programación en C sobre Linux, como el uso del gcc, make, librerías, debugging, etc.

Para descargar el archivo en PDF o en ODT, ve directamente a la página del autor.

3 Comentarios | deja el tuyo

Ago, 24 2007 - 12:00 am

Programación de Microcontroladores PIC16X84 [Diagramas de montaje + Programas]

Diagramas y SeudoEsquemas para implementar los Microcontroladores PIC16X84 en circuitos reales o protoboards + Programas en ASM y C

¡¡¡Put0 título tan largo que me he inventado xD!!! Nada, decir que obviamente los programas no los he inventado yo, sino que son la recopilación de los “ejemplos práticos” más usados. Los he sacado de unos cuantos libros cuyo nombre no me sé (en realidad son unas fotocopias que encontré por casualidad). Y aclarar que los dibujos los hice yo en Visio, y que talvez tengan uno que otro fallo, la verdad es que me costó un huevo hacer esos put0s dibujos; en fín, si encontrais algún fallo me lo comunicas por privado. Sino conoceis como es este rollo de los Microcontroladores PIC, podeis hecharle un vistazo a este post: Introducción a microcontroladores PIC [simulando nuestro programas en ASM y C] (no te demoras sino 20 o 30 minutillos leyéndolo).


Primer Ejemplo: Explorando interruptores y encendiendo luces.

SeudoEsquema de Montaje

Descripción: Lee el número binario introducido mediante 3 interruptores conectados a la puerta A, luego suma 2 unidades a ese valor y visualiza el resultado mediante 4 diodos led conectados a la puerta B.

Programa en Assembler:

;—————————————————————————-
LIST P=16C84 ;Comando que indica el PIC usado
RADIX HEX ;Los valores se representar n en hexadecimal
;—————————————————————————-
PUERTAA EQU 0X05 ;La etiqueta “PUERTAA” queda identificada con
;la dirección 0×05, que si corresponde con el
;banco 0 es el valor de PUERTAA y si es del
;banco 1 con el de TRISA.
PUERTAB EQU 0X06 ;Equivalencia de la etiqueta PUERTAB
ESTADO EQU 0X03 ;Estado corresponde con el valor 0×03.
W EQU 0 ;Identifica W con el valor 0.
;—————————————————————————-
ORG 0 ;Comando que indica al Ensamblador la
;dirección de la memeoria donde se
;situar la instrución siguiente
;—————————————————————————-
bsf ESTADO,5 ;Pone a 1 el bit 5 de ESTADO para direccionar
;la p gina 1 de la memoria de datos.
movlw 0xff ;W <– FF(Hex) movwf PUERTAA ;W –> TRISA
movlw 0×00 ;W <– 0 movwf PUERTAB ;W –> TRISB (Las líneas de PB salidas)
bcf ESTADO,5 ;Pone a 0 el bit 5 de ESTADO pasando a
;acceder al banco 0. inicio movf PUERTAA,W ;W <– PUERTAA. Se introduce el valor binario ;de los interruptores. addlw 2 ;W <– W + 2 movwf PUERTAB ;W –> PUERTAB. El valor de W sale por las
;líneas de PB a los led.
goto inicio ;Salta a la instrucción precedida por la
;etiqueta de inicio.
END

Programa en C:

#INCLUDE <16c84.h>
void main(void)
{
int valor; /* Valor temporal */
int * p_puertaa= 0×05; /* Puntero a PuertaA */
int * p_puertab= 0×06; /* Puntero a PuertaB */ SET_TRIS_A (0xff); /* 0xff –> TRISA */
SET_TRIS_B (0×00); /* 0×00 –> TRISB */
do
{
valor = * p_puertaa;/* PuertaA –> valor */
valor += 2; /* se incrementa valor en 2 */
*p_puertab = valor; /* valor –> puertaB */
}while(true); /* Bucle infinito */
}


Segundo Ejemplo: Más interruptores y diodos led.

Esquema de Montaje

Descripción: Muestra por cinco diodos led en la puerta B la entrada que proporcionan cinco interruptores en la puerta A.

Programa en Assembler:

LIST p=16c84 ; Se usa el PIC16C84
RADIX hex ; Se emplea el sistema de numeración hexadecimal; ZONA DE ETIQUETAS———————————————————————–
W EQU 0 ; Cuando el destino es W, d = 0
F EQU 1 ; Cuando el destino es el registro f, d = 1
PUERTAA EQU 0×05 ; La Puerta A (datos) ocupa la dirección 5 del
; banco 0 y el registro de configuración la
; dirección 5 del banco 1
PUERTAB EQU 0×06 ; La misma etiqueta para el registro de datos y el
; de configuración de la Puerta B
ESTADO EQU 0×03 ; El registro Estado ocupa dirección 3 de los dos bancos

; COMIENZO DEL PROGRAMA —————————————————————–

ORG 0 ; El programa comienza en la dirección 0 (Vector Reset)
goto inicio ; Se salta a la etiqueta “inicio”
ORG 5 ; Se asigna la dirección 5 a la siguiente instrucción

inicio bsf ESTADO,5 ; Pone a 1 el bit 5 de Estado. Acceso al banco 1.
clrf PUERTAB ; Se configuran como salidas las líneas de la Puerta B
movlw 0xff ; El registro W se carga con unos
movwf PUERTAA ; Se configuran como entradas las líneas de la Puerta A
bcf ESTADO,5 ; Pone a 0 el bit 5 de Estado. Acceso al banco 0.
bucle movf PUERTAA,W; Carga el registro de datos de Puerta A en W
comf PUERTAA,W ; Complementa a 1 la entrada y la deposita en W
movwf PUERTAB ; El contenido de W se deposita en el registro de datos de
; la Puerta B
goto bucle ; Se crea un bucle cerrado e infinito

END ; Fin del programa

Programa en C:

#include <16c84.h>
#byte puertaa = 05 /* Posición de la puerta A */
#byte puertab = 06 /* Posición de la puerta B */
void main( void )
{
int temp;
set_tris_a( 0xFF ); /* Puerta A configurada para entrada */
set_tris_b( 0×00 ); /* Puerta B configurada para salida */
do
{
/* La variable temporal es necesaria porque */
temp = ~puertaa; /* la complementación se traduce en dos pasos: */
puertab = temp; /* a) Copia de puertaa en temp */
}
/* b) Complementación de temp */
/* De no hacerlo así los LED parpadearían */
while( TRUE );/* Repetir ininterrumpidamente */
}


Tercer Ejemplo: Contando y visualizando.

Esquema de Montaje

Descripción: Hace un conteo desde 0 hasta 0x5f y muestra en las patitas RB.

Programa en Assembler:

;—————————————————————————-
LIST P=16C84
RADIX HEX
;—————————————————————————- W EQU 0×00 ; Comienzo del campo de etiquetas.
F EQU 0×01
PUERTAB EQU 0×06
ESTADO EQU 0×03
CONTA EQU 0x0C

;—————————————————————————-

ORG 0 ; El programa comienza en la dirección 0 y
goto inicio ; salta a la dirección 5 para sobrepasar
ORG 5 ; el vector de interrupción.

;—————————————————————————-

inicio bsf ESTADO,5 ; Seleciona el banco 1
movlw 0×00 ; Se configura PuertaB como salida
movwf PUERTAB
bcf ESTADO,5 ; Selección del banco 0

;—————————————————————————-

clrf CONTA ; CONTA = 0
bucle1 incf CONTA,F ; CONTA + 1 –> CONTA
movf CONTA,W ; CONTA se carga en W
movwf PUERTAB ; W se carga en el registro de datos PB
movlw 0x5f ; W <– 0x5f subwf CONTA,W ; CONTA – W –> W
btfss ESTADO,2 ; Explora Z y si vale 1 se produce “brinco”
goto bucle1 ; Si Z = 0 se vuelve a bucle1

bucle2 goto bucle2 ; si Z = 1 se produce un bucle infinito
end

Programa en C:

#include <16c84.h> /* Tipo de PIC a usar */
#byte puertab=0×06
#byte conta=0x0C
void main(void)
{
set_tris_b(0×00); /* Configura la PB como salida */
for (conta=0;conta<=0x5f;++conta) /* Bucle que incrementa CONTA de 0 */ puertab=conta; /* a 0x5f */ }


Cuarto Ejemplo: Controlando el tiempo.

SeudoEsquema de Montaje

Descripción: Programa que ilustra cómo realizar una temporización sin emplear interrupciones.

Programa en Assembler:

LIST P=16C84
RADIX HEX
; ———————————————————————— PUERTAA EQU 0×06
OPTION EQU 0×01
ESTADO EQU 0×03
TMR EQU 0×01

; ————————————————————————

ORG 0 ; Inicio del programa en
; dirección 0

; ————————————————————————

bsf ESTADO,5 ; Banco 1
movlw b 1101 0110 ; Valor a cargar en
; OPTION
movwf OPTION
movlw 0×00
movwf PUERTAB ; La Puerta B salida
bcf ESTADO,5 ; Banco 0
clrf PUERTAB ; Las líneas de salida
; de PB a 0

parpa bsf PUERTAB,7 ; Enciende el led RB7 = 1
call retardo ; Llamada a subrutina de
; RETARDO
bcf PUERTAB,7 ; Apaga el led, RB7 = 0
call retardo
goto parpa

retardo clrf TMR0 ; TMR0 = 0 y empieza su
; incremento

explora btfss TMR0,4; TMR0<4> = 1?
goto explora ; No ha llegado TMR0 a 16d
return ; Ha llegado TMR0 al
; valor 16d y retorna
; al programa principal

END

Programa en C:

#include <16c84.h>
#use delay( clock = 1000000 ) /* Especifica reloj de 1 MHz */
#byte puertab = 06 /* Dirección de la puerta B */
void main( void )
{
set_tris_b( 0×00 );
puertab = 0;
do
{
delay_us( 8700 ); /* Crea un bucle de espera de 8700 microsegundos */
bit_set(puertab,7); /* Enciende el LED */
delay_us(8700); /* Espera */
bit_clear(puertab,7);/* Apaga el LED */
}while(true); /* Repetir siempre */
}


Quinto Ejemplo: Manejando Interrupciones.

SeudoEsquema de Montaje

Descripción: Refleja el estado de dos interruptores situados en RA0 y RA1 en RB0 y RB1 mientras hace parpadear un diodo en la línea RB7.

Programa en Assembler:

;—————————————————————————- LIST P=16C84
RADIX HEX

;—————————————————————————-

W EQU 0
F EQU 1
TMR_OPT EQU 0×01 ; TMRO en banco 0 OPTION en banco 1
ESTADO EQU 0×03
PUERTAA EQU 0×05 ; PA en banco 0 TRISA en banco1
PUERTAB EQU 0×06 ; PB en banco 0 TRISB en banco1
INTCON EQU 0x0B ;
CONTA EQU 0×10 ; Contador auxiliar

;—————————————————————————-

ORG 0 ; Vector de Reset
goto inicio

ORG 4 ; Vector de Interrupción
goto inter ; Salta a comienzo de rutina de interrupción
ORG 5

inicio bsf ESTADO,5 ; Selección del banco 1
clrf PUERTAB ; Configura PUERTA B como salida

movlw b’00000011′ ; Configura RA0, RA1 como entradas
movwf PUERTAA

movlw b’00000111′
movwf TMR_OPT

bcf ESTADO,5 ; Banco 0

movlw b’10100000′ ; Se permite interrupción del
movwf INTCON ; TMR0 y la globla (GIE)

movlw 0×10
movwf CONTA ; Se carga CONTA con 16 decimal

movlw 0x0c
movwf TMR_OPT ; Se carga TMR0 con 12 decimal

bucle btfsc PUERTAA,0 ; Explora RA0 y brinco si vale 0
goto ra0_1 ; salta a RA0_1
bcf PUERTAB,0 ; Si RA0 = 0 sa saca por RB0 un 0
goto ra1x ; A explorar RA1

ra0_1 bsf PUERTAB,0 ; Si RA0 = 1 se saca por RB0 un 1

ra1x btfsc PUERTAA,1 ; Examina ra1 y brinco si es 0
goto ra1_1 ; Salta si RA1 = 1
bcf PUERTAB,1 ; Si RA1 = 0, RB1 = 0

goto bucle2
ra1_1 bsf PUERTAB,1 ; Si RA1 = 1 , RB1 = 1
bucle2 goto bucle ; Bucle indefinido, se sale por la interupción

;—————————————————————————-

inter decfsz CONTA,1 ; RSI. Decrementa CONTA y brinco si vale 0
goto seguir

conta_0 movlw 0×10 ; Si CONTA = 0 se carga
movwf CONTA

btfsc PUERTAB,7 ; Si RB7 = 0, brinco
goto rb7_1
bsf PUERTAB,7 ; Si RB7 = 0, se invierte
goto seguir

rb7_1 bcf PUERTAB,7 ; Si RB7 = 1 , se invierte

seguir movlw b’10100000′ ; Se restaura INTCON por desactivar las
movwf INTCON ; interrupciones el procesador
movlw 0x0c
movwf TMR_OPT ; Se recarga TMR0 con 12
retfie

end

Programa en C:

#include <16c84.h> /* Selección del PIC a usar */
#use delay(clock= 4000000) /* Reloj de 4 MHz */
#BYTE puertab = 6
#define maximo 16 /* Constante: maximo = 16 */
byte conta;
/*————————————————————————–*/
/* SERVICIO DE LA INTERRUPCIóN */
#INT_RTCC /* Interrupción por desvordamiento del timer*/
clock_isr()
{
short valor;
short novalor;
valor = bit_test(puertab,7); /* El bit valor es igual al contenido */
/* de RB7 */ novalor = !valor;
if (–conta==0)
{
output_bit (PIN_B7,novalor); /* Voltea RB7 */
delay_us (5);
conta = maximo;
}
}

/* PROGRAMA PRINCIPAL */
main()
{
short ra0,ra1;

set_tris_b(0×00); /* Se inicializa PB */
conta=maximo;
set_rtcc(0); /* Se inicializa el timer a cero */

setup_counters(rtcc_internal,rtcc_div_256);

enable_interrupts(rtcc_zero); /* Se permite int del tmr0 */

enable_interrupts(GLOBAL); /* Se activa GIE */

/* Rutina de control de los leds e interruptores: */
do
{
ra0 = input(PIN_A0);
ra1 = input(PIN_A1);

output_bit (PIN_B0,ra0);
output_bit (PIN_B1,ra1);
}
while(true); /* Bucle infinito */
}


Séptimo Ejemplo: Proyecto para manejar un display de 7 segmentos.

SeudoEsquema de Montaje

Descripción: Programa que visualiza un número del 1 al 7 en un display de siete segmentos en la puerta B dependiendo del valor binario de tres interruptores situados en la puerta A.

Programa en Assembler:

LIST P=16C84
RADIX HEX w EQU 0
f EQU 1
PCL EQU 02
PUERTAA EQU 05
PUERTAB EQU 06
ESTADO EQU 03
VALOR EQU 12 ; Registro auxiliar

; RUTINA PRINCIPAL: Lectura de los interruptores y c lculo del valor a visualizar

ORG 0
goto inicio
ORG 5 ; Para saltar el Vector de
; Interrupción

inicio bsf ESTADO,5 ; Selección del banco 1
clrw
movwf PUERTAB ; Puerta B salida
movlw 0xff
movwf PUERTAA ; puerta A entrada
bcf ESTADO,5 ; Selección banco 0
explora movf PUERTAA,w ; Se cargan los
; interruptores en W
movwf VALOR ; Se usa un registro auxiliar
comf VALOR,f ; Invertir los niveles de interuptores
clrw
btfss VALOR,0 ; Si RA0 = 1, brinca
goto bit_1 ; Salta a explorar el bit_1
addlw 0×01 ; Si RA0 =1, se suma
bit_1 btfss VALOR,1; Si RA1 = 1, brinca
goto bit_2 ; Salta a explorar el bit_2
addlw 0×02 ; Si RA1 = 1, se suman 2
bit_2 btfss VALOR,2; Si RA2 = 1, brinca
goto visual ; Salta al módulo del display
addlw 0×04 ; Si RA2 0 1, se suman 4
visual call display ; Salta al módulo del display

; DISPLAY: Rutina de visualización del acumulador en el display de 7 segmentos

movwf PUERTAB ; Al retornar de la subrutina
; el valor de W se saca por la
; Puerta B
bucle goto bucle ; bucle infinito

; TABLA DE CONVERSION———————————————————

display addwf PCL,f ; pcl + W -> W
; El pcl se incrementa con el
; valor de W proporcionando un
; salto
retlw 0x3F ; Retorna con el valor del
; código del 0
retlw 0×06 ; Retorna con el código del 1
retlw 0x5b ; Retorna con el código del 2
retlw 0x4f ; Retorna con el código del 3
retlw 0×66 ; Retorna con el código del 4
retlw 0x6d ; Retorna con el código del 5
retlw 0x7d ; Retorna con el código del 6
retlw 0×07 ; Retorna con el código del 7

END

Programa en C:

#include <16c84.h>
#byte puertaa = 05 /* Posición de la puerta A */
#byte puertab = 06 /* Posición de la puerta B */
void main( void )
{
int temp = 0, tabla[8]={ 0x3F, 0×06, 0x5B, 0x4F, 0×66, 0x6D, 0x7D, 0×07 };
int indice = 0;
set_tris_a( 0xFF ); /* Puerta A configurada para entrada */
set_tris_b( 0×00 ); /* Puerta B configurada para salida */
temp = ~puertaa; /* Se complementa la entrada de PA */
if ( bit_test( temp, 0 ) ) indice += 1;
if ( bit_test( temp, 1 ) ) indice += 2;
if ( bit_test( temp, 2 ) ) indice += 4;
puertab = tabla[indice];
}


Ejemplos básicos de programación de Microcontroladores PIC16X84 sin esquemas ni diagramas; enunciados de los ejemplos:

  • Control de un dispositivo desde dos puntos: Se desea controlar una lámpara, en este caso un diodo LED desde dos interruptores, de forma que cuando los dos interruptores están abiertos el LED está apagado. A partir de esta situación, cada vez que cambie el estado de un interruptor, el estado del LED bascula (si está apagado se enciende y viceversa)
  • Semáforo programabe: Se simula un semáforo con 3 diodos LED. Se dispone de 2 interruptores que según la combinación que adopten originan una secuencia de encendido de las luces del semáforo.
  • Dado electrónico: Este programa simula el juego del dado. Un dado típico tiene 6 caras, en cada una de las cuales viene dibujado un número del 1 al 6. Cada vez que se presiona un pulsador se produce un número aleatorio entre 1 y 6, el cual se visualiza en un display de 7 segmentos.
  • Temporizador programable: Con 3 microrruptores se selecciona un valor entre el 0 y el 7 (binario), que representa un tiempo en segundos y que ser visualizado por el display de 7 segmentos. Durante el tiempo que dura la temporización un LED rojo permanece activado, así como un zumbador. Al finalizar se desactivan ambos elementos y el display se pone a 0.
  • Alarma: Se tienen 3 detectores digitales, cada uno de los cuales provocar la activación de un LED, diferente en cada caso. Uno de los detectores ser un optoacoplador y los otros 2 se simularán mediante 2 microrruptores. El programa consiste en poner en marcha un zumbador cuando la alarma salte por causa de la activación de cualquiera de los detectores. También se enciende el LED correspondiente al detector. La alarma sólo funcionará cuando el microrruptor I1 de conexión esté a nivel alto.
  • Ejemplo tomado de Internet: (Autor: David Tait, david.tait@man.ac.uk) Este programa ilumina una serie de leds en secuencia principio-fin-principio (algo así como las luces del “El Coche Fantástico).
  • Manejo del WatchDog (perro guardián): El objetivo de este programa es mostrar en la práctica el funcionamiento del Watchdog en el PIC 16c84. El programa entra en un bucle infinito del que sale tras cumplirse la temporización asiganada al watchdog, que en este caso ser n 36 ms, es decir 2 veces la temporización nominal.

3 Comentarios | deja el tuyo

Jul, 02 2007 - 6:26 pm

Video tutorial C++

Me pillo en un post de cheatmaster un muy buen videotutorial de C++ hecho en Flash, muy recomendado si estás empenzando en C/C++… lo puedes ver aquí:
http://lnx.googlewrite.com/cpp/wimpy.swf

6 Comentarios | deja el tuyo

« Entradas anteriores
Entradas recientes »