u1_t1_programación en lenguaje c de pic
DESCRIPTION
Programación en Lenguaje cTRANSCRIPT
w w w . i n a c a p . c l1
INGENIERIA ElectrónicaU
NID
AD
1
Introducción a Programación de
microcontroladores en Lenguaje C
w w w . i n a c a p . c l2
Contenido• Programación en C:
• Características, Instrucciones; • Datos y operaciones en C.
• COMPILAODRES PCB, PCW, PCH, PCHW, etc.• Definiciones de datos • Compilación de un programa en lenguaje C
mediante instrucciones simples• Ejemplos demostrativos
w w w . i n a c a p . c l
Programación de sistemas basados en microprocesador
Lenguajes de bajo nivel: el ensamblador
Ejemplo: microcontrolador PIC 16C61
Instrucción Operando
ANDLW 33d
EPROM
ProgramMemory
1K x 14
11 1001 00100001
11 1001 00100001
Instrucción en ensamblador
w w w . i n a c a p . c l
Programación de sistemas basados en microprocesador
Lenguajes de bajo nivel: el ensamblador; Rutina principal "modo RUN"
SIGUE4 BTFSC ANTIRB
GOTO SIGUE4
BTFSS PORTB,3 ; Si alguien pulsa select durante
GOTO PROG ; el modo RUN pasa a modo programa
SIGUE10 BTFSC PORTB,2
GOTO SIGUE5
BTFSC VA_RA1
GOTO SIGUE4
BSF VA_RA1
GOTO SIGUE6
SIGUE5 BTFSS VA_RA1
GOTO SIGUE4
BCF VA_RA1
SIGUE6 BSF ANTIRB
MOVLW 0x0F
MOVWF ARB_CTR
; Cuando se detecta que se ha llegado al medio ...
BCF INTCON,GIE ; Inhabilita interrupciones
BCF STATUS,C
; Actualiza la base de tiempo
MOVF TSEMAN0,W ; Suma la duración del semiciclo anterior
ADDWF TCICLO0,W ; con la duración del ciclo actual
MOVWF TREALM0
MOVF TSEMAN1,W
BTFSC STATUS,C
INCFSZ TSEMAN1,W
ADDWF TCICLO1,W
...
Fragmento de un programa en ensamblador para un microcontrolador PIC 16C61
Comentarios
Cada instrucción en ensamblador se traduce como una instrucción en código máquina
w w w . i n a c a p . c l
Programación de sistemas basados en microprocesador
Lenguajes de bajo nivel: el ensamblador
; Rutina principal "modo RUN"
SIGUE4 BTFSC ANTIRB
GOTO SIGUE4
BTFSS PORTB,3
GOTO PROG
SIGUE10 BTFSC PORTB,2
GOTO SIGUE5
BTFSC VA_RA1
GOTO SIGUE4
BSF VA_RA1
GOTO SIGUE6
SIGUE5 BTFSS VA_RA1
GOTO SIGUE4
BCF VA_RA1
SIGUE6 BSF ANTIRB
MOVLW 0x0F
MOVWF ARB_CTR
BCF INTCON,GIEBCF STATUS,C
MOVF TSEMAN0,WADDWF TCICLO0,WMOVWF TREALM0
...
Listado ensamblador
Archivo.asm
compilación
:02000000CE2808
:08000800012A82073F3448344D
:10001000483448343F347F344934493449343634E1
:100020003E3441344134413422347F34413441340C
:1000300041343E347F3449344934493449347F347F
:1000400048344834483440343E34413441344534F3
:1000500026347F340834083408347F344134413442
:100060007F344134413406340134013401347E3468
Código máquina
Archivo.hex
Volcado a mem
oria
w w w . i n a c a p . c l
Programación de sistemas basados en microprocesador
Lenguajes de bajo nivel: el ensamblador
Características de la programación en ensamblador:
Muy laborioso de programar
Es necesario conocer muchos detalles del funcionamiento interno del sistema para poder realizar la programación
Se tiene un control total de los recursos:
Máximo aprovechamiento de la memoria
Control total del tiempo de ejecución
w w w . i n a c a p . c l
Programación de sistemas basados en microprocesador
Lenguajes de alto nivel: C, PASCAL, FORTRAN, BASIC, …
void visualizacion()
{
if (!aux) {
vis=FALSE;
PORTB=0;
}
else {
PORTB=leds;
if (!no_leds) {
no_leds=TRUE;
targetH+=2;
nCaracter--;
leds=0;
}
else {
no_leds=FALSE;
targetH+=2;
if (nCaracter) {
if (--aux) obtenerH();
}
else {
nCaracter=6;
leds=0;
}
}
}
}
...
Fragmento de un programa en C
compilación
:02000000CE2808
:08000800012A82073F3448344D
:10001000483448343F347F344934493449343634E1
:100020003E3441344134413422347F34413441340C
:1000300041343E347F3449344934493449347F347F
:1000400048344834483440343E34413441344534F3
:1000500026347F340834083408347F344134413442
:100060007F344134413406340134013401347E3468
Código máquina
Archivo.hex
Listado en C
Archivo.c
Volcado a mem
oria
w w w . i n a c a p . c l
Programación de sistemas basados en microprocesador
Lenguajes de alto nivel:
Características de la programación en lenguajes de alto nivel:
Bastante menos laborioso de programar que el ensamblador
El compilador se encarga de generar el código específico para la máquina que se está usando:
No es necesario conocer todos los detalles de la máquina
Mayor portabilidad: cambiar de máquina recompilar
No se tiene tanto control de los recursos como en ensamblador:
Menor aprovechamiento de la memoria
Calcular el tiempo que tarda en ejecutarse una parte del programa es complejo
w w w . i n a c a p . c l9
Compilador C para PICCCS C
w w w . i n a c a p . c l10
Compilador C para PIC
CCS PIC COMPILER
• Un compilador convierte un lenguaje de alto nivel a instrucciones en código máquina.
• Un “cross-compiler” es un compilador que funciona en un procesador (normalmente en PC) diferente al procesador objeto. Varios compiladores C tiene como procesador objetos los PICmicro tal es el caso de HiTECH, MicroChip y CCS.
• Los programas son editados y compilados a instrucciones máquina en el PC.
• El código máquina es cargado del PC al sistema PIC mediante el ICD2.
• El código es ejecutado en el PIC y puede ser depurado (puntos de ruptura, paso a paso, etc) desde el PC.
Nota: Ver documentos anexos sobre CCS
w w w . i n a c a p . c l11
Compilador C para PIC
CCS PIC COMPILER
• Los elementos básicos de un programa en C
– Directivas de preprocesado• Indican al compilador cómo debe generar
el código máquina.
– Programas• Bloques de programa.• Siempre debe incluirse una llamada
main().
– Sentencias• Instrucciones que definen lo que hace el
programa y la secuencia de ejecución del mismo.
– Comentarios• Imprescindibles como documentación del
código fuente.
w w w . i n a c a p . c l12
Compilador C para PIC
VARIABLES
• Una variable es un nombre asignado a una o varias posiciones de memoria RAM.
• En C es necesario declarar todas las variables antes de poder utilizarlas, indicando el nombre asignado y el tipo de datos que en ella se van a almacenar (opcionalmente también el valor inicial asignado).
tipo nombre_variable [=valor]; p.e.:int i;
• Los tipos de datos aceptados en C estándar son cinco:char (carácter) int (entero)float (coma flotante en 32 bits) double (coma flotante en 64
bits)void (sin valor)
• Las variables pueden ser locales o globales. Las variables locales sólo pueden ser usadas en la función en que se declaran, mientras que las variables globales son compartidas por todas las funciones del programa (deben declararse fuera de cualquier función y antes de ser utilizadas).
w w w . i n a c a p . c l13
Compilador C para PIC
VARIABLES
• El compilador de CCS acepta los siguiente tipos de variable.
Especificación Significado Tamaño Rangochar carácter 8 bits 0 a 255 (sin signo)int entero 8 bits 0 a 255 (sin signo)float coma flotante 32 bits 6 bits de precisióndouble float doble precisión no soportado No para PCMvoid sin valor nulo ningunoint1 entero de 1 bit 1 bit 0 a 1int8 entero de 8 bits 8 bits 0 a 255 (sin signo)int16 entero de 16 bits 16 bits 0 a 65535 (sin signo)int32 entero de 32 bits 32 bits 0 a (232-1)short entero de 1 bit 1 bit 0 a 1long entero de 16 bits 16 bits 0 a 65535 (sin signo)
• Los tipos de variable short y long pueden tener detrás la palabra int sin efecto alguno.
w w w . i n a c a p . c l14
Compilador C para PIC
VARIABLES
• Todos los tipos de datos son por defecto sin signo (unsigned) salvo los de tipo float.
• Para almacenar datos con signo, hay que introducir el modificador signed delante del tipo. El efecto que se consigue es el recogido en la siguiente tabla.
Especificación Significado Tamaño Rangosigned char carácter con signo 8 bits -128 a 127signed int16 entero con signo 16 bits -
16384 a 16383signed long coma flotante 16 bits -32768 a
32767
• Los números negativos se codifican en complemento a 2.
• Cuando se opera con distintos grupos de datos en una misma expresión, se aplican una serie de reglas para resolver las diferencias. En general se produce una “promoción” hacia los tipos de datos de mayor longitud presentes en la expresión.
w w w . i n a c a p . c l15
Compilador C para PIC
FUNCIONES
• Las funciones son los bloques constructivos fundamentales en C. Todas las sentencias deben encontrarse dentro de funciones.
• Las funciones deben ser definidas antes de ser utilizadas.• Formato general de definición de una función:
tipo_dato_return nombre_func (tipo param1 , tipo param2 , … )
{cuerpo de la función (sentencias);}
• Las funciones pueden devolver un valor a la sentencia que las llama. El tipo de dato devuelto se indica mediante tipo_dato (char, int16, long). Si no se indica nada, se entiende que devuelve un entero. Si no devuelve nada, debe incluirse una especificación tipo void.
•
w w w . i n a c a p . c l16
Compilador C para PIC
FUNCIONES
• La manera que tiene una función para devolver un valor es mediante la sentencia return.
return (expresión); return expresión;
• La expresión debe proporcionar el mismo tipo de dato que el especificado en la función. Si no debe devolver nada, se finaliza con return;
• Cuando una función se encuentra con una sentencia return se vuelve a la rutina de llamada inmediatamente y las sentencias posteriores a return no se ejecutan.
• Además de con las sentencia return, las funciones terminan su ejecución y vuelven al lugar desde donde se les llamó cuando alcanzan la llave de cierre de función } tras ejecutar la última sentencia de la misma.
w w w . i n a c a p . c l17
Compilador C para PIC
FUNCIONES
• Además de devolver valores, una función también puede recibir parámetros (denominados argumentos) según se indicó en su definición.
int suma (int a , int b) Parámetros formales{ return (a+b);}main(){ int c; c = suma (10 , 23); Argumentos de llamada}
• Los argumentos se pueden pasar a las funciones por valor o por referencia.• La llamada por valor copia el argumento de llamada en el parámetro
formal de la función (No modifica su valor en la función de partida).• La llamada por referencia usa la dirección de la variable que se pasa a la
función (se consigue usando punteros o arrays).
w w w . i n a c a p . c l18
Compilador C para PIC
OPERADORES
• El lenguaje C define numerosos operadores mediante los cuales se construyen las expresiones (combinación de operadores y operandos).
• De asignación
• Aritméticos
w w w . i n a c a p . c l19
Compilador C para PIC
OPERADORES
• Relacionales
• Lógicos
• De bits
w w w . i n a c a p . c l20
Compilador C para PIC
OPERADORES
• In/decremento
• Desplazamiento bit
• Dirección/indirección
En lenguaje C “profesional” es muy frecuente usar abreviaturas.Así, por ejemplo, es más habitual ver a += b; que a = a + b;
w w w . i n a c a p . c l21
Compilador C para PIC
OPERADORES
w w w . i n a c a p . c l22
Compilador C para PIC
DECLARACIONES
w w w . i n a c a p . c l23
Compilador C para PIC
Sentencias de control de programa– Sentencia if
• Se ejecuta una sentencia o bloque de código si la expresión que acompaña al if tiene un valor distinto a cero (verdadero). Si es cero (falso) continúa sin ejecutar la sentencia o bloque de sentencias.
if (expresión)sentencia; {sentencia 1;sentencia 2;...}
– Sentencia if-else• Se evalúa una expresión y, si es cierta, se ejecuta el primer bloque
de código (o sentencia 1). Si es falsa, se ejecuta el segundo.if (expresión)sentencia 1; (expresión) ? (sentencia 1) : (sentencia 2);elsesentencia 2;
w w w . i n a c a p . c l24
Compilador C para PIC
Sentencias de control de programa– Sentencia if-else
If (P1 !=0) c=20;else c=0;
w w w . i n a c a p . c l25
Compilador C para PIC
Sentencias de control de programa– Sentencia if-if/else
If (a>b) {If (a>d) c = 15;else c=0; }
w w w . i n a c a p . c l26
Compilador C para PIC
Sentencias de control de programa– Sentencia if/else - if
If (a>b) {If (a>d) c = 15; }else c=0;
w w w . i n a c a p . c l27
Compilador C para PIC
Sentencias de control de programa– Sentencia switch
• Substituye a if-else cuando se realiza una selección múltiple que compara una expresión con una lista de constantes enteras o caracteres. Cuando se da una coincidencia, el cuerpo de sentencias asociadas a esa constante se ejecuta hasta que aparezca break.
switch (expresión){case constante 1:
grupo 1 de sentencias;break;
case constante 2:grupo 2 de sentencias;break;
...default:
grupo n de sentencias;}
default es opcional y el bloque asociado se ejecuta sólo si no hay ninguna coincidencia con las constantes especificadas.
break es opcional. Si no aparece se sigue con el case siguiente.
No puede haber constantes iguales en dos case de la misma sentencia switch.
w w w . i n a c a p . c l28
Compilador C para PIC
Sentencias de control de programa– Sentencia switch
Switch (k) {case 0:x=1;break;case 2:c=6;b=15;break;case 3: x=12;break;default: break;}
w w w . i n a c a p . c l29
Compilador C para PIC
Sentencias de control de programa– Sentencia de bucle for
• Se emplea para repetir una sentencia o bloque de sentencias.
for (inicialización ; condición ; incremento){sentencia(s);}
• En la inicialización se le asigna un valor inicial a una variable que se emplea para el control de la repetición del bucle.
• La condición se evalúa antes de ejecutar la sentencia. Si es cierta, se ejecuta el bucle. Si no, se sale del mismo.
• El incremento establece cómo cambia la variable de control cada vez que se repite el bucle.
• Es posible anidar bucles for para modificar dos o más variables de control.
w w w . i n a c a p . c l30
Compilador C para PIC
Sentencias de control de programa– Sentencia de bucle for
For (i=1;i<=100;i++) {delay_ms(33);px=?px;}
For (y=1;i<=99;y=y+3) {delay_ms(33);px=y;}
w w w . i n a c a p . c l31
Compilador C para PIC
Sentencias de control de programa– Sentencia de bucle while
• La repetición se lleva a cabo mientras sea cierta una expresión.while (expresión){
sentencia(s);}
• La expresión se evalúa antes de cualquier iteración. Si es falsa, ya no se ejecuta la sentencia o bloque de sentencias.
– Sentencia de bucle do-while.do{
sentencia(s);}while (expresión)
• Las sentencias se ejecutan antes de que se evalúe la expresión, por lo que el bucle se ejecuta siempre al menos una vez.
w w w . i n a c a p . c l32
Compilador C para PIC
Sentencias de control de programa– Sentencia de bucle do-while/while
while (x>0 && y++<5) {a=1;b=45;x=p1;}
w w w . i n a c a p . c l33
Compilador C para PIC
Sentencias de control de programa– Sentencia de bucle while-do/while
do {a=1;b=45;x=p1;}while (x>0 && y++>5);
w w w . i n a c a p . c l34
Compilador C para PIC
Comentarios– Los comentarios se incluyen en el código fuente para explicar el
sentido y la intención del código al que acompañan. Son ignorados por el compilador y no afectan a la longitud ni rapidez de ejecución del código final.
– Un comentario se puede colocan en cualquier lugar del programa y pueden tener la longitud y el número de líneas que se quiera.
– Hay dos formatos posibles para los comentarios.Formato 1. Empiezan por // y finalizan con el final de la línea.
// Esto es un comentario.
Formato 2. Empiezan por /* y finalizan por */. No es posible anidar comentarios con este formato.
/* Esto también esun comentario *//* Pero esto que /* parece un comentario válido*/ no lo es */
w w w . i n a c a p . c l35
Compilador C para PIC
C específico para los PIC
– Las principales diferencias entre compiladores residen en las directivas (pre-processor commands) y en las funciones integradas (built-in functions).
– Al final de esta sección se incluyen sendas listas con las directivas y las funciones integradas correspondientes al compilador de CCS.
Directivas de preprocesado más habituales:
#ASM Las líneas entre estas dos directivas deben ser
instrucciones #ENDASM ensamblador que se insertan tal y como aparecen.
#BIT id=x.y Se crea una variable tipo bit correspondiente al bit y del byte x
en memoria.
#BYTE id=x Se crea una variable y se sitúa en el byte x en memoria. Si ya
existía esa variable, se coloca físicamente en la posiciónespecificada.
w w w . i n a c a p . c l36
Compilador C para PIC
C específico para los PIC
#DEFINE id texto El identificador se sustituye por el texto adjunto.
#DEVICE chip Define el micro para el que se escribe el código.
#FUSES options Define la palabra de configuración para la grabación del
microcontrolador.
#INCLUDE <fichero> Se incluye el texto del fichero especificado en el#INCLUDE “fichero” directorio o fuera de él.
#INLINE La función que sigue a esta directiva se copia en memoria de
programa cada vez que se le llame. Puede servir para
mejorar la velocidad.
#SEPARATE La función que sigue a esta directiva se implementa de
manera separada (no INLINE). De esta manera se ahorra
ROM
w w w . i n a c a p . c l37
Compilador C para PIC
C específico para los PIC
#ORG start Sitúa el código a partir de una determinada posición de la
memoria de programa
#INT_xxxx Indica que la función que sigue es un programa detratamiento de la interrupción xxxx.
#INT_GLOBAL Indica que la función que sigue es un programa genérico de
tratamiento de interrupción. No se incluye código de
salvaguarda de registros ni de recuperación como cuando se
usa #INT_xxxx.
#PRIORITY ints Establece un orden de prioridad en las interrupciones.
#USE DELAY (clock = frecuencia en Hz)Define la frecuencia del oscilador que se va a
utilizar, que seemplea para realizar los cálculos para funciones
integradasde retardo.
w w w . i n a c a p . c l38
Compilador C para PIC
pre-processor commands
w w w . i n a c a p . c l39
Compilador C para PIC
built-in functions
w w w . i n a c a p . c l40
Compilador C para PIC
built-in functions
w w w . i n a c a p . c l41
Compilador C para PIC
PIC C COMPILER
INICIO > PIC-C > PIC C COMPILER
– Se puede Crear o abrir un fichero (FILE > NEW / OPEN) o crear un proyecto (conjunto de ficheros y opciones de compilación que se utilizan en un programa). Los proyectos tienen la extensión PJT.
– Para crear un nuevo proyecto PROJECT > NEW > PIC WIZARD / MANUAL CREATE
w w w . i n a c a p . c l42
Compilador C para PIC
PIC C COMPILER
COMPILAR (F9)
MONTARLO
PCB (12bit)PCM (14bit)PCH (PIC18)
w w w . i n a c a p . c l43
Compilador C para PIC
GESTION DE PUERTOS• Existen dos opciones para configurar y manejar los puertos E/S
– Definiendo los registros como variables localizadas en RAM. Se definen los puertos y los registros de dirección como variables de C y se colocan en las posiciones reales de estos registros en la memoria RAM de datos. Constituye la manera más directa de trabajar con los puertos E/S.
– Usando las funciones integradas específicas del compilador. Se definen la dirección de datos si es necesario y se gestionan las entradas y las salidas mediante funciones relativas al manejo de todo el puerto o de bits particulares del mismo.
• Cuando se usan las funciones integradas del compilador de CCS, el código que introduce el compilador puede variar en cuanto a tamaño y tiempo de ejecución. Dependerá de la activación de ciertas directivas de preprocesado:
#USE FAST_IO - #USE FIXED_IO - #USE STANDARD_IO
w w w . i n a c a p . c l44
Compilador C para PIC
GESTION DE PUERTOS: POR RAM
OPCIÓN 1. Definiendo los registros en la RAM. Se definen los registros PORTx y TRISx como bytes y se sitúan en la posición correspondiente de la memoria RAM. La directiva C utilizada es #BYTE:
#BYTE variable=constante;
#BYTE TRISA = 0x85 //Variable TRISA en 85h.#BYTE PORTA = 0x05 //Variable PORTA en 05h.#BYTE TRISB = 0x86 //Variable TRISB en 86h.#BYTE PORTB = 0x06 //Variable PORTB en 06h.
– Una vez definidas estas variables se pueden configurar y controlar los puertos mediante comandos de asignación.A partir de este punto, estas variables permiten controlar los puertos y se pueden utilizar en sentencias de asignación.
TRISA = 0xFF; // 8 terminales de entradaTRISB = 0x00; // 8 terminales de salidaTRISC = 0x0F; // 4 pin de mayor peso OUT,4 pin de menor peso IN
w w w . i n a c a p . c l45
Compilador C para PIC
GESTION DE PUERTOS: POR RAM
– Escritura en los puertos:
PORTC = 0x0A; // salida del datos 00001010 por el puerto C
– Lectura de puertos:
valor = PORTA; // Asigna el dato del puerto A a la variable valor.
– Manejo de sentencias:
TRISD=0x0F;
if (PORTD & 0x0F) PORTD |= 0xA0; //comprueba los 4 terminales de
// menor peso del puerto D y si son
// 1111 saca por los 4 terminales de
// mayor peso el dato 1010.
w w w . i n a c a p . c l46
Compilador C para PIC
GESTION DE PUERTOS: POR RAM
– El compilador de CCS incorpora una serie de funciones integradas que permite manejar los bits de una variable previamente definida.
bit_clear (var,bit); //Pone a 0 el bit específico (0 a 7) de la variable.
bit_set (var , bit); //Pone a 1 el bit específico (0 a 7) de la variable.
bit_test (var , bit); //Muestra el bit específico (0 a 7) de la variable.
swap (var); //Intercambia los 4 bits de mayor peso por los 4
//de menor peso de la variable.
bit_set (PORTC , 4); //”saca” un 1 por el terminal RC4if (bit_test(PORTB,0)==1) bit_clear(PORTB,1); //si RB0 es 1 borra RB1
– También se puede declarar un bit de un registro con una variable mediante la directiva #BIT y trabajar directamente con la variable.
#BIT nombre = posición.bit #BIT RA4 = 0x05.4......RA4 = 0;
w w w . i n a c a p . c l47
Compilador C para PIC
GESTION DE PUERTOS: POR RAM
Ejemplo: LED CONTROLADO POR BOTON
RA0/AN02
RA1/AN13
RA2/AN2/VREF-4
RA4/T0CKI6
RA5/AN4/SS7
OSC1/CLKIN9
OSC2/CLKOUT10
RC1/T1OSI/CCP212
RC2/CCP113
RC3/SCK/SCL14
RB7/PGD28
RB6/PGC27
RB526
RB425
RB3/PGM24
RB223
RB122
RB0/INT21
RC7/RX/DT18
RC6/TX/CK17
RC5/SDO16
RC4/SDI/SDA15
RA3/AN3/VREF+5
RC0/T1OSO/T1CKI11
MCLR/Vpp/THV1
U1
PIC16F876
SW1SW-SPST-MOMD1
LED-BLUE
R1180
COMPILAR (F9)
MONTARLO
w w w . i n a c a p . c l48
Compilador C para PIC
GESTION DE PUERTOS: POR DIRECTIVAS
• OPCIÓN 2. Usando funciones integradas del compilador.
– El compilador de CCS incorpora una serie de funciones integradas orientadas a trabajar con los puertos E/S.
output_X (valor); //Por el puerto correspondiente se saca
// el valor (0-255).input_X(); //Se obtiene el valor en el puerto
correspondiente.set_tris_X(valor); //Carga el registro TRISx con el
valor (0-255).port_b_pullups (valor); //Mediante valor=TRUE o valor=FALSE
habilita o//deshabilita las resistencias de pull-up en
PORTB.
w w w . i n a c a p . c l49
Compilador C para PIC
GESTION DE PUERTOS: POR DIRECTIVAS
– Hay una serie de funciones asociadas a un terminal o pin*. El parámetro pin* se define en un fichero include (por ejemplo, 16F876.h) con un formato del tipo PIN_Xn, donde X es el puerto y n es el número de pin.
#define PIN_A0 40#define PIN_A1 41
output_low (pin*); //Pin a 0.output_high (pin*); //Pin a 1.output_bit (pin* , valor); //Pin al valor especificado.output_toggle(pin*); //Complementa el valor del pin.output_float (pin*); //Pin de entrada, quedando a tensión
flotanteinput_state(pin*); //lee el valor del pin sin cambiar
su sentido input(pin*); // lee el valor del pin.
w w w . i n a c a p . c l50
Compilador C para PIC
GESTION DE PUERTOS: POR DIRECTIVAS
– La generación de código para las funciones output_x( ) e input_x( ) depende de la última directiva del tipo #USE *_IO que esté activa.
#USE FAST_IO (PUERTO) [PUERTO: A…]– Cada vez que se emplea una función output...() se saca el valor
directamente al puerto, y cada vez que se emplea una función input...() se lee el puerto, pero no se modifican previamente el registro TRIS correspondiente.
– El usuario debe asegurarse de que los registros TRIS están cargados adecuadamente antes de llamar a las funciones.
Ej. #USE FAST_IO (B)
#USE STANDARD_IO (PUERTO) [PUERTO: A…]– Cada vez que se emplea una función output...() se inserta código
previo para forzar a que el bit particular o el puerto completo sean de salida (mediante la carga del TRIS correspondiente). Si se trata de una función input...() se carga código para definir bit o puerto completo como de entrada.
– Ésta es la opción activa por defecto.Ej. #USE STANDARD_IO (C)
w w w . i n a c a p . c l51
Compilador C para PIC
GESTION DE PUERTOS: POR DIRECTIVAS
#USE FIXED_IO (PUERTO_OUTPUTS=pin* , ...) [PUERTO: A…]– Se genera código relativo a la dirección de los datos de manera
previa cada vez que aparece una función integrada del tipo input…( ) ó output…( ), pero los pines se configuran de acuerdo con la información que acompaña a la directiva (sólo se indican los pines de salida) y no dependiendo de que la operación sea de entrada o de salida como sucede con #USE STANDARD_IO(PUERTO)
Ej. USE FIXED_IO (B_OUTPUTS = PIN_B2 , PIN_B3)
– El efecto de colocar una u otra directiva se puede observar en los ficheros *.lst que se generan como resultado de la compilación. En general se puede decir que resulta más cómodo gestionar los pines de E/S de modo STANDARD, pero haciéndolo de modo FAST se adquiere más control de lo que se le está mandando al PIC y se optimiza código.
w w w . i n a c a p . c l52
Compilador C para PIC
GESTION DE PUERTOS: POR DIRECTIVAS
w w w . i n a c a p . c l53
Compilador C para PIC
GESTION DE PUERTOS: POR PUNTEROS
• La memoria se puede acceder en C usando punteros. Los punteros deben ser del tipo INT.
#define portb (int *) 0x06
– portb es un puntero INT cuyo valor es la dirección del bus del dispositivo. El puerto es accesible mediante el uso del operado *.
int pp = *portb
– En este ejemplo el valor del dato en el puerto direccionado en la posición de memoria 0x06 (puerto B) es asignado a la variable p. Antes de que el puerto sea leido es necesario establecer si es de entrada o salida
#define trisb (int *) 0x86*trisb = 0xFF
w w w . i n a c a p . c l54
Compilador C para PIC
GESTION DE PUERTOS: POR PUNTEROS
– Los pines pueden escritos o leídos mediante operadores lógicos.
*portb |= 0b00000100; pone el pin 2 del portB a 1
*portb &= 0b11111011; pone el pin 2 del portB a 0.
Para lee el valor del pin 7 del portB:
If (*portb & 0b10000000) {…..
w w w . i n a c a p . c l55
Compilador C para PIC
GESTION DE PUERTOS: POR PUNTEROS
w w w . i n a c a p . c l56
Compilador C para PIC
Ejemplo: DISPLAY
1.- Vss (Masa)2.- Vcc (Alimentación de 2.7V a 5.5V)3.- Ajuste de contraste (de 0 a 5.5V)4.- RS (selección de registro)5.- R/W (lectura/escritura)6.- E (enable)7.- D0 (dato LSB)8.- D19.- D210.- D311.- D412.- D513.- D614.- D7 (dato MSB)
LCD con driver HD44780
w w w . i n a c a p . c l57
Compilador C para PIC
Ejemplo: DISPLAY
w w w . i n a c a p . c l58
Compilador C para PIC
Ejemplo: DISPLAY
• LCD en el compilador C de CCS
– El compilador C de CCS incluye un driver para manejar LCD, el fichero que define las funciones indicadas a continuación.
lcd_init ();– Debe llamarse antes que ninguna otra función del fichero LCD.C.– Tal y como aparece en el fichero, además de borrar el display,
configura el LCD para trabajar como sigue:a) En formato de 4 bits, con dos líneas y con caracteres de 5×8
puntos.b) Con display encendido, cursor apagado y sin parpadeo.c) Con autoincremento del puntero de direcciones y sin
desplazamientodel display real.
lcd_gotoxy (x , y);– Establece la posición del LCD a la que se debe acceder.– Recuérdese que la primera posición de la primera línea tiene
coordenadas (1 , 1), y que la primera posición de la segunda línea es la (1 , 2).
w w w . i n a c a p . c l59
Compilador C para PIC
Ejemplo: DISPLAY
lcd_putc (dato);– Escribe dato en la posición a la que apunta el puntero de
direcciones.– La variable dato es de tipo char, y se definen algunos caracteres
especiales:\f Borra el display\n Se posiciona en el inicio de la segunda línea\b Retrocede una posición
lcd_getc (x , y);– Devuelve el carácter que ocupa la posición (x , y) del LCD.
– Por defecto, este driver usa siete bits del puerto B para establecer la comunicación entre el LCD y el microcontrolador (aunque también se puede utilizar el puerto D).
B0 Enable B4 Bit de datos D4B1 RS B5 Bit de datos D5B2 R/W B6 Bit de datos D6B3 - B7 Bit de datos D7
w w w . i n a c a p . c l60
Compilador C para PIC
Ejemplo: DISPLAY– También es posible escribir en el LCD usando la siguiente función.
printf(lcd_putc,cadena,vars);
• cadena: Cadena de caracteres que puede formarse usando el contenido de una o más variables.
• vars: Variables incluidas en la cadena (separadas por comas).
– Para indicar la posición y el tipo de las variables a incluir en la cadena, se usa el formato %nt, donde n es opcional.
n: 1-9 Indica el número de caracteres a mostrar(opcional) 01-09 Indica el número de ceros a la izquierda
1.1-9.9 Indica cuántos decimales se han de mostrar
t: c Carácter e Flotante (formato exp)
s Cadena o carácter f Flotante truncandou Entero sin signo lu Entero
largo sin signox ó X Entero hexadecimal lx ó lX Entero largo
hexadecimald Entero con signo ld Entero
largo con signog Flotante rendondeadow Entero sin signo. La 1ª cifra indica el total, la 2ª el
nº de decimales
w w w . i n a c a p . c l61
Compilador C para PIC
Ejemplo: DISPLAY
– Algunos ejemplos.printf(lcd_putc , ”Hola”);printf(lcd_putc , ”Tecla %c pulsada %u veces” , key ,
cont );
– Ejemplos de formato.Especificador Valor=0x12 Valor=0xfe%03u 018 254%u 18 254%2u 18 ???%5 18 254%d 18 -2%x 12 fe%X 12 FE%4X 0012 00FE%3.1w 1.8 25.4
w w w . i n a c a p . c l62
Compilador C para PIC
Ejemplo: DISPLAY– El driver LCD.C está pensado para trabajar con el PORTB o el PORTD.
– Si se quiere trabajar con otro puerto, como por ejemplo el PORTC, se deben cambiar los datos en el fichero
#define use_portb_lcd TRUE permite seleccionar el PORT
w w w . i n a c a p . c l63
Compilador C para PIC
Ejemplo: DISPLAY
RA0/AN02
RA1/AN13
RA2/AN2/VREF-4
RA4/T0CKI6
RA5/AN4/SS7
OSC1/CLKIN9
OSC2/CLKOUT10
RC1/T1OSI/CCP212
RC2/CCP113
RC3/SCK/SCL14
RB7/PGD28
RB6/PGC27
RB526
RB425
RB3/PGM24
RB223
RB122
RB0/INT21
RC7/RX/DT18
RC6/TX/CK17
RC5/SDO16
RC4/SDI/SDA15
RA3/AN3/VREF+5
RC0/T1OSO/T1CKI11
MCLR/Vpp/THV1
U1
PIC16F876
D7
14
D6
13
D5
12
D4
11
D3
10
D2
9D
18
D0
7
E6
RW
5R
S4
VS
S1
VD
D2
VE
E3
LCD2LM016L
COMPILAR (F9)
MONTARLO
w w w . i n a c a p . c l64
Compilador C para PIC
Ejemplo: DISPLAY/MENU
RA0/AN02
RA1/AN13
RA2/AN2/VREF-4
RA4/T0CKI6
RA5/AN4/SS7
OSC1/CLKIN9
OSC2/CLKOUT10
RC1/T1OSI/CCP212
RC2/CCP113
RC3/SCK/SCL14
RB7/PGD28
RB6/PGC27
RB526
RB425
RB3/PGM24
RB223
RB122
RB0/INT21
RC7/RX/DT18
RC6/TX/CK17
RC5/SDO16
RC4/SDI/SDA15
RA3/AN3/VREF+5
RC0/T1OSO/T1CKI11
MCLR/Vpp/THV1
U1
PIC16F876
R110k
D7
14
D6
13
D5
12
D4
11
D3
10
D2
9D
18
D0
7
E6
RW
5R
S4
VS
S1
VD
D2
VE
E3
LCD1LM016L
COMPILAR (F9)
MONTARLO
w w w . i n a c a p . c l65
Compilador C para PIC
Ejemplo: TECLADO/DISPLAY
• KEYPAD (3x4) en el compilador C de CCS
– El compilador C de CCS incluye un driver KBD.C para manejar el teclado (3x4).
kbd_get();• Devuelve el valor de la tecla pulsada en función de la tabla que
tiene programada.
Vista desde atrás
w w w . i n a c a p . c l66
Compilador C para PIC
Ejemplo: TECLADO/DISPLAY
– El driver KBD.C está pensado para trabajar con el PORTB o el PORTD.
#define use_portb_lcd TRUE permite seleccionar el PORT
w w w . i n a c a p . c l67
Compilador C para PIC
Ejemplo: TECLADO/DISPLAY
– Las conexiones vienen dadas en el fichero pero se pueden modificar:
col pin(port)
RA0/AN02
RA1/AN13
RA2/AN2/VREF-4
RA4/T0CKI6
RA5/AN4/SS7
OSC1/CLKIN9
OSC2/CLKOUT10
RC1/T1OSI/CCP212
RC2/CCP113
RC3/SCK/SCL14
RB7/PGD28
RB6/PGC27
RB526
RB425
RB3/PGM24
RB223
RB122
RB0/INT21
RC7/RX/DT18
RC6/TX/CK17
RC5/SDO16
RC4/SDI/SDA15
RA3/AN3/VREF+5
RC0/T1OSO/T1CKI11
MCLR/Vpp/THV1
U1
PIC16F876
1 2 3
4 5 6
7 8 9
0 #
1 2 3
A
B
C
D
D7
14
D6
13
D5
12
D4
11
D3
10
D2
9D
18
D0
7
E6
RW
5R
S4
VS
S1
VD
D2
VE
E3
LCD2LM016L
C0 C1 C2
R0
R1
R2
R3
w w w . i n a c a p . c l68
Compilador C para PIC
Ejemplo: TECLADO/DISPLAY
RA0/AN02
RA1/AN13
RA2/AN2/VREF-4
RA4/T0CKI6
RA5/AN4/SS7
OSC1/CLKIN9
OSC2/CLKOUT10
RC1/T1OSI/CCP212
RC2/CCP113
RC3/SCK/SCL14
RB7/PGD28
RB6/PGC27
RB526
RB425
RB3/PGM24
RB223
RB122
RB0/INT21
RC7/RX/DT18
RC6/TX/CK17
RC5/SDO16
RC4/SDI/SDA15
RA3/AN3/VREF+5
RC0/T1OSO/T1CKI11
MCLR/Vpp/THV1
U1
PIC16F876
1 2 3
4 5 6
7 8 9
0 #
1 2 3
A
B
C
D
D7
14
D6
13
D5
12
D4
11
D3
10
D2
9D
18
D0
7
E6
RW
5R
S4
VSS
1
VD
D2
VEE
3
LCD2LM016L
w w w . i n a c a p . c l69
Compilador C para PIC
Ejemplo: TECLADO/DISPLAY
RA0/AN02
RA1/AN13
RA2/AN2/VREF-4
RA4/T0CKI6
RA5/AN4/SS7
OSC1/CLKIN9
OSC2/CLKOUT10
RC1/T1OSI/CCP212
RC2/CCP113
RC3/SCK/SCL14
RB7/PGD28
RB6/PGC27
RB526
RB425
RB3/PGM24
RB223
RB122
RB0/INT21
RC7/RX/DT18
RC6/TX/CK17
RC5/SDO16
RC4/SDI/SDA15
RA3/AN3/VREF+5
RC0/T1OSO/T1CKI11
MCLR/Vpp/THV1
U1
PIC16F876
1 2 3
4 5 6
7 8 9
0 #
1 2 3
A
B
C
D
D7
14
D6
13
D5
12
D4
11
D3
10
D2
9D
18
D0
7
E6
RW
5R
S4
VSS
1
VD
D2
VEE
3
LCD2LM016L
w w w . i n a c a p . c l70
Compilador C para PIC
Ejemplo: TECLADO/DISPLAY
COMPILAR (F9)
MONTARLO
w w w . i n a c a p . c l71
Compilador C para PIC
Ejemplo: TECLADO/DISPLAY
w w w . i n a c a p . c l72
Compilador C para PIC
Ejemplo: INTERRUPCIONES– Las directivas #INT_xxxx. Indican que la función que aparece a
continuación corresponde al tratamiento de una interrupción (no tiene ni necesita parámetros).
– En el caso de los PIC 16F87x hay 14 posibles directivas.
#INT_RTCC Desbordamiento de TMR0. (T0IF)#INT_RB Cambio en los pines RB<4:7>. (RBIF)#INT_EXT Flanco en pin RB0. (INTF)#INT_AD Fin de conversión A/D. (ADIF)#INT_TBE Buffer de transmisión USART vacío.(TXIF)#INT_RDA Dato recibido en USART. (RCIF)#INT_TIMER1 Desbordamiento de TMR1. (TMR1IF)#INT_TIMER2 Desbordamiento de TMR2. (TMR2IF)#INT_CCP1 Captura / Comparación en módulo CCP1. (CCP1IF)#INT_CCP2 Captura / Comparación en módulo CCP2. (CCP2IF)#INT_SSP Envío / Recepción de dato serie síncrono. (SSPIF)#INT_BUSCOL Colisión de bus I2C. (BCLIF)#INT_EEPROM Escritura completa en EEPROM de datos. (EEIF)
w w w . i n a c a p . c l73
Compilador C para PIC
Ejemplo: INTERRUPCIONES
– La directiva #INT_DEFAULT. Indica que la función que viene a continuación será llamada si se dispara una interrupción y ninguno de los flags está activo.
– La directiva #INT_GLOBAL. Indica que la función que va a continuación sustituye todas las acciones que inserta el compilador al aceptarse una interrupción. Sólo se ejecuta lo que vaya en dicha función.
– Ventajas de usar las directivas de interrupciones
• El compilador genera el código necesario para saltar a la función que va tras esta directiva en el momento de la interrupción.
• También genera código para salvar al principio y restituir al final el contexto, y borrará el flag que se activó con la interrupción.
• El programador debe seguir encargándose de habilitar las interrupciones.
w w w . i n a c a p . c l74
Compilador C para PIC
Ejemplo: INTERRUPCIONES– Funciones para gestión de interrupciones. El compilador C de CCS
incluye algunas funciones integradas destinadas a manejar interrupciones.
• enable_interrupts (nivel);nivel es una constante definida en 16F876.h y genera el código necesario para activar las máscaras necesarias.Etiquetas de nivel definidas para el 16F876:GLOBAL INT_RTCC INT_RB INT_EXT INT_AD INT_TBE INT_RDA INT_TIMER1INT_TIMER2 INT_CCP1 INT_CCP2 INT_SSPINT_PSP INT_BUSCOL INT_EEPROMLa máscara global (la que hace GIE=1) debe activarse de manera independiente. Las otras sólo activan la máscara particular y el PEIE si es necesario.
• disable_interrupts (nivel);Hace la acción contraria a la función anterior, poniendo a 0 las máscaras relacionadas con la interrupción indicada.
w w w . i n a c a p . c l75
Compilador C para PIC
Ejemplo: INTERRUPCIONES– Existe también una función adicional destinada a configurar el flanco
activo que genera la interrupción externa (en RB0).
• ext_int_edge (H_TO_L);Selecciona flanco de bajada para activar el flag INTF.
• ext_int_edge (L_TO_H);Selecciona flanco de subida para activar el flag INTF.
#INT_EXText_isr() {......}
enable_interrupts (INT_EXT); // Activa máscara INTEext_int_edge (H_TO_L); // Flag INTF si flanco de bajada.enable_interrupts (GLOBAL); // Habilita máscara global de int.
/* Si entra una interrupción por flanco de bajada en RB0, se irá a lafunción que aparece tras la directiva #INT_EXT */
disable_interrupts (INT_EXT); // Desactiva interrupciones en RB0.disable_interrupts (GLOBAL); // Desactiva todas las interrupciones.
w w w . i n a c a p . c l76
Compilador C para PIC
Ejemplo: INTERRUPCIONES_RB0
RA0/AN02
RA1/AN13
RA2/AN2/VREF-4
RA4/T0CKI6
RA5/AN4/SS7
OSC1/CLKIN9
OSC2/CLKOUT10
RC1/T1OSI/CCP212
RC2/CCP113
RC3/SCK/SCL14
RB7/PGD28
RB6/PGC27
RB526
RB425
RB3/PGM24
RB223
RB122
RB0/INT21
RC7/RX/DT18
RC6/TX/CK17
RC5/SDO16
RC4/SDI/SDA15
RA3/AN3/VREF+5
RC0/T1OSO/T1CKI11
MCLR/Vpp/THV1
U1
PIC16F876R1180
D1LED-GREEN
SW1SW-SPDT-MOM
COMPILAR (F9)
MONTARLO
w w w . i n a c a p . c l77
Compilador C para PIC
Ejemplo: TIMER0– TMR0 / WDT en el compilador C de CCS
• Configuración del módulo TMR0.setup_timer_0 (modo);
modo: RTCC_INTERNAL (OPTION_REG ← 00h)RTCC_EXT_L_TO_H (OPTION_REG ← 20h)RTCC_EXT_H_TO_L (OPTION_REG ← 30h)RTCC_DIV_2 (OPTION_REG ← 00h)RTCC_DIV_4 (OPTION_REG ← 01h)RTCC_DIV_8 (OPTION_REG ← 02h)RTCC_DIV_16 (OPTION_REG ← 03h)RTCC_DIV_32 (OPTION_REG ← 04h)RTCC_DIV_64 (OPTION_REG ← 05h)RTCC_DIV_128 (OPTION_REG ← 06h)RTCC_DIV_256 (OPTION_REG ← 07h)Se pueden agrupar constantes de distintos grupos con |.
w w w . i n a c a p . c l78
Compilador C para PIC
Ejemplo: TIMER0– Configuración del módulo WDT.
setup_wdt (modo);
modo: WDT_18MS (OPTION_REG ← 08h)WDT_36MS (OPTION_REG ← 09h)WDT_72MS (OPTION_REG ← 0Ah)WDT_144MS (OPTION_REG ← 0Bh)WDT_288MS (OPTION_REG ← 0Ch)WDT_576MS (OPTION_REG ← 0Dh)WDT_1152MS (OPTION_REG ← 0Eh)WDT_2304MS (OPTION_REG ← 0Fh)
• Para que el temporizador WATCHDOG pueda llevar a cabo su misión es necesario indicarlo así con la directiva #fuses.
#fuses [opciones], WDT [opciones] WDT activado#fuses [opciones], NOWDT [opciones]
WDTdesactivado
w w w . i n a c a p . c l79
Compilador C para PIC
Ejemplo: TIMER0– Configuración de los módulos TMR0 y WDT (obsoleto).
• Funciones implementadas en el compilador por compatibilidad con versiones anteriores. No se recomienda su uso.
setup_counters (rtcc , prescaler);rtcc: RTCC_INTERNAL (OPTION_REG ←
00h)RTCC_EXT_L_TO_H (OPTION_REG ← 20h)RTCC_EXT_H_TO_L (OPTION_REG ← 30h)
prescaler: RTCC_DIV_2 (OPTION_REG ← 00h)... ...RTCC_DIV_256 (OPTION_REG ← 07h)WDT_18MS (OPTION_REG ← 08h)WDT_36MS (OPTION_REG ← 09h)WDT_72MS (OPTION_REG ← 0Ah)WDT_144MS (OPTION_REG ← 0Bh)WDT_288MS (OPTION_REG ← 0Ch)WDT_576MS (OPTION_REG ← 0Dh)WDT_1152MS (OPTION_REG ← 0Eh)WDT_2304MS (OPTION_REG ← 0Fh)
w w w . i n a c a p . c l80
Compilador C para PIC
Ejemplo: TIMER0
– Escritura en el módulo TMR0.set_timer0 (valor);
valor: Entero de 8 bits. (TMR0 ← valor)
– Lectura del módulo TMR0.valor = get_timer0 ();
valor: Entero de 8 bits. (valor ← TMR0)
– Puesta a cero del Watchdog.restart_wdt ();
No precisa ningún parámetro. (equivale a CLRWDT)
w w w . i n a c a p . c l81
Compilador C para PIC
Ejemplo: TIMER0
#INCLUDE <16F876.h>#use delay(clock=4000000)#fuses XT,NOWDT#use standard_io(B)
int1 var0=0; //variable de cambio
#int_TIMER0void TIMER0_isr(void) { var0++; //se complementa la variable if (var0==1) output_bit(PIN_B0,1); //para semiperiodo alto else output_bit(PIN_B0,0); //para semiperiodo bajo set_timer0 (0x06); } //se recarga el timer0
void main() { setup_timer_0(RTCC_INTERNAL|RTCC_DIV_2); //configuración timer0 set_timer0 (0x06); //carga del timer0 enable_interrupts(INT_TIMER0); //habilita interrupcion timer0 enable_interrupts(global); //habilita interrupción general while (1); //bucle infinito}
Generar una señal cuadrada de 1KHz utilizando la
interrupción del Timer0. Con un semiperiodo de
500us
500us=4/Fosc(256-x)X = 6Con Fosc=4MHz y preescaler 1:2
w w w . i n a c a p . c l82
Compilador C para PIC
Ejemplo: TIMER0Para ajustar el tiempo se
carga el timer0 con 29 (0x1D).
Esto es debido a la generación de código
ensamblador por parte del compilador.
w w w . i n a c a p . c l83
Compilador C para PIC
Ejemplo: TIMER1– Registro T1CON (10h)
bits 5-4 T1CKPS1:T1CKPS0: Selección del prescaler00: Prescaler1:1. 10: Prescaler1:4.01: Prescaler1:2. 11: Prescaler1:8.
bit 3 T1OSCEN: Habilitación del oscilador de TMR10: Apagado 1: Habilitado
bit 1 TMR1CS: Reloj de TMR10: Reloj interno (fOSC/4). 1: Reloj externo (↑ en RC0).
bit 2 T1SYNC: Control de la sincronización con el reloj externoSólo si TMR1CS=10: Sincronizar 1: No sincronizar
bit 0 TMR1ON: Bit de encendido de TMR10: TMR1 apagado. 1: TMR1 encendido.
w w w . i n a c a p . c l84
Compilador C para PIC
Ejemplo: TIMER1– TMR1 en el compilador C de CCS
• Configuración del módulo TMR1.setup_timer_1 (modo);
modo: T1_DISABLED (T1CON ← 00h)T1_INTERNAL (T1CON ← 85h)T1_EXTERNAL (T1CON ← 87h)T1_EXTERNAL_SYNC (T1CON ← 83h)T1_CLK_OUT (T1CON ← 08h)T1_DIV_BY_1 (T1CON ← 00h)T1_DIV_BY_2 (T1CON ← 10h)T1_DIV_BY_4 (T1CON ← 20h)T1_DIV_BY_8 (T1CON ← 30h)
Se pueden agrupar constantes de distintos grupos con |.
• Lectura / Escritura en el módulo TMR1.valor = get_timer1 (); set_timer1 (valor);
valor: Entero de 16 bits.
w w w . i n a c a p . c l85
Compilador C para PIC
Ejemplo: TIMER1
#include <16f876.h>#fuses XT,NOWDT#use delay(clock=4000000)#use standard_io(b)
temp1s(){ int cont=0; output_toggle(PIN_B1); while (cont<2) { set_timer1 (3036); while (get_timer1()>=3036); cont++; }}
main (){ setup_timer_1 (T1_INTERNAL | T1_DIV_BY_8);
while(1){ temp1s(); }}
Configurar el módulo TMR1 para generar una
temporización de 1s.(dos de 0,5)
0.5=4/Fosc(65536-x)PX = 3036Con Fosc=4MHz y preescaler 1:8
w w w . i n a c a p . c l86
Compilador C para PIC
Ejemplo: TIMER2
– Registro T2CON (12h)
bits 6-3 TOUTPS3:TOUTPS0: Selección del postscaler0000: Postscaler1:10001: Postscaler1:20010: Postscaler1:3.....1111: Postscaler1:16
bit 2 TMR2ON: Bit de encendido de TMR20: Apagado 1: Habilitado
bits 1:0 T2CKPS1:T2CKPS0: Selección del prescaler00: Prescaler101: Prescaler41x: Prescaler16
w w w . i n a c a p . c l87
Compilador C para PIC
Ejemplo: TIMER2
– TMR2 en el compilador C de CCS• Configuración del módulo TMR2.
setup_timer_2 (modo,periodo,postscaler);modo: T2_DISABLED (T2CON ← 00h)
T2_DIV_BY_1 (T2CON ← 04h)T2_DIV_BY_4 (T2CON ← 05h)T2_DIV_BY_16 (T2CON ← 06h)
periodo: Entero de 8 bits (0-255) que se pasa al registro PR2.postscaler: Valor del postscaler (1-16).
• Lectura / Escritura en el módulo TMR2.valor = get_timer2 (); set_timer2 (valor);
valor: Entero de 8 bits.
w w w . i n a c a p . c l88
Compilador C para PIC
Ejemplo: TIMER2
INCLUDE <16F876.h>#use delay(clock=4000000)#fuses XT,NOWDT#use standard_io(B)
int1 var0=0; //variable de cambio#int_TIMER2 void TIMER2_isr(void) { //Función Interrupción var0++; //se complementa la variable if (var0==1) output_bit(PIN_B0,1); //para semiperiodo alto else output_bit(PIN_B0,0); //para semiperiodo bajo set_timer0 (0x7C); } //se recarga el timer0
void main() { setup_timer_2 (T2_DIV_BY_4 ,124,1); //configuración timer2 enable_interrupts(INT_TIMER2); //habilita interrupcion timer0 enable_interrupts(global); //habilita interrupción general while (1); //bucle infinito}
Generar una señal cuadrada de 1KHz utilizando la interrupción del
Timer2.
Temp=[Prescaler(PR2+1)Postscaler]Tinstr
500us=(4/4000000)·[4· (X+1) ·1] x = 125Con Fosc=4MHzpreescaler 4postscaler 1
w w w . i n a c a p . c l89
Compilador C para PIC
Ejemplo: TIMER2Para ajustar el tiempo se carga el timer2 con 124
(0x7C). Esto es debido a la
generación de código ensamblador por parte del
compilador.
w w w . i n a c a p . c l90
Compilador C para PIC
Ejemplo: INTERRUPCIONES_TIMER
RA0/AN02
RA1/AN13
RA2/AN2/VREF-4
RA4/T0CKI6
RA5/AN4/SS7
OSC1/CLKIN9
OSC2/CLKOUT10
RC1/T1OSI/CCP212
RC2/CCP113
RC3/SCK/SCL14
RB7/PGD28
RB6/PGC27
RB526
RB425
RB3/PGM24
RB223
RB122
RB0/INT21
RC7/RX/DT18
RC6/TX/CK17
RC5/SDO16
RC4/SDI/SDA15
RA3/AN3/VREF+5
RC0/T1OSO/T1CKI11
MCLR/Vpp/THV1
U1
PIC16F876
R1180
D1LED-GREEN
R2180
D2LED-GREEN
R3180
D3LED-GREEN
COMPILAR (F9)
MONTARLO
w w w . i n a c a p . c l91
Compilador C para PIC
Ejemplo: INTERRUPCIONES_TIMER
– Medir el ancho de un pulso mediante el TIMER1 y la Interrupción Externa por RB0.
• El TIMER1 es un contador de 16 bits que se incrementa cada 4 ciclos de Reloj (FOSC *4). A este tiempo le vamos a llamar PASO de TIMER1. Si el cristal de cuarzo es de 4 Mhz, entonces 1µs se produce un PASO de TIMER1.
• Un ciclo completo del TIMER1, desde 0x0000 hasta 0xFFFF (65536 pasos), ocupa un tiempo total de 1µs * 65.536 = 65,536ms.
• Podemos fijar un tipo de flanco a detectar y escribir un cierto código para ejecutarlo cuando ese tipo de flanco, subida o bajada, es detectado. este código escrito para tratar la interrupción externa por RB0 podemos mantener o cambiar el flanco a detectar, cambiándolo del de Subida al de Bajada o viceversa y leer o escribir el valor de TIMER1 que en ese momento tiene el contador.
w w w . i n a c a p . c l92
Compilador C para PIC
Ejemplo: INTERRUPCIONES_TIMER
1. Se configura la INTEXT por RB0 para detectar inicialmente el Flanco de Subida.
2. Al llegarnos este Flanco de Subida se guarda el valor en ese momento de TIMER1.
3. Se cambia la configuración de la INTEXT por RB0 para detectar el siguiente Flanco de Bajada.
4. Cuando llegue el Flanco de Bajada se guarda de nuevo el valor de TIMER1.
5. Se vuelve a configurar la INTEXT por RB0 para detectar de nuevo un Flanco de Subida.
6. Con estos dos valores de TIMER1 se obtiene, expresados en PASOS de TIMER1, restando el segundo del primero, el tiempo que ha permanecido en alto el Pulso. Multiplicando dicho número de PASOS de TIMER1 por el tiempo que dura cada PASO (dependiente del cristal) se obtiene el Tiempo W.
7. El ancho de pulso máximo es de 65,536ms (un ciclo de TIMER1). El mínimo dependerá del tiempo que tarda en programa en gestionar la interrupción y los cálculos.
w w w . i n a c a p . c l93
Compilador C para PIC
Ejemplo: INTERRUPCIONES_TIMER
Modificar el fichero LCD.C para trabajar con el LCD en el puerto C (guardarlo como LCD_MIO.C)
RA0/AN02
RA1/AN13
RA2/AN2/VREF-4
RA4/T0CKI6
RA5/AN4/SS7
OSC1/CLKIN9
OSC2/CLKOUT10
RC1/T1OSI/CCP212
RC2/CCP113
RC3/SCK/SCL14
RB7/PGD28
RB6/PGC27
RB526
RB425
RB3/PGM24
RB223
RB122
RB0/INT21
RC7/RX/DT18
RC6/TX/CK17
RC5/SDO16
RC4/SDI/SDA15
RA3/AN3/VREF+5
RC0/T1OSO/T1CKI11
MCLR/Vpp/THV1
U1
PIC16F876
D7
14
D6
13
D5
12
D4
11
D3
10
D2
9D
18
D0
7
E6
RW
5R
S4
VS
S1
VD
D2
VE
E3
LCD2LM016L
U1(RB0/INT)
w w w . i n a c a p . c l94
Compilador C para PIC
Ejemplo: INTERRUPCIONES_TIMER
w w w . i n a c a p . c l95
Compilador C para PIC
Ejemplo: INTERRUPCIONES_TIMER
COMPILAR (F9)
MONTARLO
w w w . i n a c a p . c l96
Compilador C para PIC
Ejemplo: EEPROM INTERNA
Simularlo con el ISIS y leer la
EEPROM con el DEBUG
RA0/AN02
RA1/AN13
RA2/AN2/VREF-4
RA4/T0CKI6
RA5/AN4/SS7
OSC1/CLKIN9
OSC2/CLKOUT10
RC1/T1OSI/CCP212
RC2/CCP113
RC3/SCK/SCL14
RB7/PGD28
RB6/PGC27
RB526
RB425
RB3/PGM24
RB223
RB122
RB0/INT21
RC7/RX/DT18
RC6/TX/CK17
RC5/SDO16
RC4/SDI/SDA15
RA3/AN3/VREF+5
RC0/T1OSO/T1CKI11
MCLR/Vpp/THV1
U1
PIC16F876
D7
14
D6
13
D5
12
D4
11
D3
10
D2
9D
18
D0
7
E6
RW
5R
S4
VS
S1
VD
D2
VE
E3
LCD2LM016L
w w w . i n a c a p . c l97
Características generales en el PIC16F877
Ocho canales de conversión. Cinco pines E/S de PORTA y los tres de PORTE
Convierte la señal analógica en un número digital de 10 bits.Tensión de referencia seleccionable por software.
Puede ser VDD o la tensión aplicada en los pines RA2 y/o RA3
Posibilidad de seguir funcionando cuando el PIC está en modo SLEEP.Hay 11 registros asociados a este periférico.Definición de pines de entrada
TRISA - PORTA - TRISE - PORTE
Manejo de interrupcionesINTCON - PIE1 - PIR1
Control del conversor A/DADCON0 - ADCON1 - ADRESH - ADRESL
w w w . i n a c a p . c l98
w w w . i n a c a p . c l99
Registro ADCON0 (1Fh)
ADCS1 ADCS0 CHS1 CHS0 CHS2 GO/DONE - ADON
bit 7-6 ADCS1:ADCS0: Selección del reloj para la conversión A/D
00 = fOSC / 2 01 = fOSC / 8 10 = fOSC / 32 11 = fRC
bit 5-3 CHS2:CHS0: Selección del canal de conversión
000 = Canal 0 001 = Canal 1 010 = Canal 2 011 = Canal 3
100 = Canal 4 101 = Canal 5 110 = Canal 6 111 = Canal 7
bit 2 GO/DONE: Estado de la conversión
Si ADON=1:
1 = Conversión en progreso 0 = Conversión finalizada
bit 0 ADON: Bit de encendido del convertidor A/D
1 = Módulo A/D encendido 0 = Módulo A/D apagado
w w w . i n a c a p . c l
100
Registro ADCON1 (9Fh)
ADFM PCFG3 - - - PCFG2 PCFG1 PCFG0
bit 7 ADFM: Selección de formato del resultado
1 = Ajuste a la derecha 0 = Ajuste a la izquierda
bit 3-0 PCFG3:PCFG0: Configuración de las entradas al modulo A/D
PCFG3:PCFG0
AN7 RE2
AN6 RE1
AN5 RE0
AN4 RE1
AN3 RE3
AN2 RA2
AN1 RA1
AN0 RA0
0000 A A A A A A A A0001 A A A A VREF+ A A A0010 D D D A A A A A0011 D D D A VREF+ A A A0100 D D D D A D A A0101 D D D D VREF+ D A A011x D D D D D D D D1000 A A A A VREF+ VREF- A A1001 D D A A A A A A1010 D D A A VREF+ A A A1011 D D A A VREF+ VREF- A A1100 D D D D VREF+ VREF- A A1101 D D D D VREF+ VREF- A A1110 D D D D D D D A1111 D D D D VREF+ VREF- D A
w w w . i n a c a p . c l101
Registro INTCON (0Bh , 8Bh , 10Bh , 18Bh)
T0IF GIE PEIE INTE RBIE T0IE RBIF INTF
bit 7 GIE: Habilitación global de interrupciones
bit 6 PEIE: Habilitación de interrupciones de periféricos
Registro PIE1 (8Ch)
CCP1IE PSPIE ADIE TXIE SSPIE RCIE TMR1IE TMR2IE
bit 6 ADIE: Habilitación de la interrupción del convertidor A/D
Registro PIR1 (0Ch)
CCP1IF PSPIF ADIF TXIF SSPIF RCIF TMR1IF TMR2IF
bit 6 ADIF: Flag de la interrupción del convertidor A/D
1 = Conversión A/D completada. 0 = Conversión A/D aún no completada.
w w w . i n a c a p . c l102
Pasos en una conversión A/D
1. Configurar el módulo A/D.
- Definir entradas analógicas y tensión de referencia. (ADCON1)
- Seleccionar el canal de la conversión. (ADCON0)- Seleccionar el reloj de la conversión. (ADCON0)- Encender el módulo A/D. (ADCON0)
2. Configurar la interrupción por conversión A/D.
- Bajar el flag ADIF. (PIR1)- Habilitar la interrupción del convertidor A/D. (PIE1)- Habilitar las interrupciones de los periféricos. (INTCON)- Habilitar la máscara global de interrupciones. (INTCON)
3. Esperar a que transcurra el tiempo de adquisición.
- Tiempo necesario para capturar el valor analógico a convertir.- Los valores típicos del tiempo de adquisición son del orden de
20µs.
w w w . i n a c a p . c l103
4. Comenzar la conversión.- Poner a “1” el bit GO/DONE. (ADCON0)No activar este bit a la vez que se enciende el convertidor A/D
5. Esperar a que se complete la conversión A/D.
a) Controlando cuándo el bit GO/DONE se pone a “0”.b) Esperando a que llegue la interrupción del convertidor.
6. Leer el resultado de la conversión.- Disponible en los registros ADRESH:ADRESL.- Bajar el flag ADIF si se están usando interrupciones.
7. Llevar a cabo la siguiente conversión.- Volver al paso 1 ó 2, según convenga.- Espera mínima antes de empezar la siguiente adquisición: 2·TAD.
TAD: Tiempo necesario para la conversión de un bit.
w w w . i n a c a p . c l104
Tiempo de adquisición
Tiempo necesario para cargar el condensador de mantenimiento (CHOLD).
Máxima impedancia recomendada para la fuente: 10K. En estas condiciones, TACQ ≈20µs.
Mientras no se complete la conversión, no empieza otra adquisición.
Esperar TACQ : a) tras una conversión; b) tras seleccionar un nuevo canal; c) tras encender el módulo A/D.
w w w . i n a c a p . c l105
Tiempo de conversión
La conversión de 10 bits dura 12·TAD.
Comienza la conversión Se carga ADRES Se pone GO/DONE a “0”
Se abre SS (típ. 100ns) Se levanta el flag ADIF
GO/DONE 1 CHOLD conectado a entrada analógica
TAD configurable en ADCON0 (reloj de la conversión).
TAD=2·TOSC - TAD=8·TOSC - TAD=32·TOSC - TAD=2µs÷6µs (típ. 4µs)
Para un funcionamiento correcto se necesita un valor mínimo de TAD=1,6µs.
Tciclo÷TAD TAD TA
D
TA
D
TAD TA
D
TA
D
TAD TA
D
TAD TA
D
TAD
b9 b8 b7 b6 b5 b4 b3 b2 b1 b0
w w w . i n a c a p . c l106
Función de transferencia
La primera transición tiene lugar cuando la tensión analógica de entrada alcanza el valor VREF- + (VREF+ -
VREF-)/1024 ≡ 1LSb.
w w w . i n a c a p . c l107
Conversión A/D en el compilador C de CCSConfiguración del módulo conversor A/D
setup_adc (modo);
modo: ADC_OFF (ADCON0 ←00h)
ADC_CLOCK_DIV_2 (ADCON0 ← 01h)
ADC_CLOCK_DIV_8 (ADCON0 ← 41h)
ADC_CLOCK_DIV_32 (ADCON0 ← 81h)
ADC_CLOCK_INTERNAL (ADCON0 ← C1h)
Definición de entradas analógicas
setup_adc_ports (valor);
valor: NO_ANALOGS (ADCON1 ← 86h)
ALL_ANALOG (ADCON1 ← 80h)
ANALOG_RA3_REF (ADCON1 ← 81h)
A_ANALOG (ADCON1 ← 82h)
A_ANALOG_RA3_REF (ADCON1 ← 83h)
RA0_RA1_RA3_ANALOG (ADCON1 ← 84h)
RA0_RA1_ANALOG_RA3_REF (ADCON1 ← 85h)
w w w . i n a c a p . c l108
Definición de entradas analógicas (cont.)
setup_adc_ports (valor);
valor: ANALOG_RA3_RA2_REF (ADCON1 ← 88h)
ANALOG_NOT_RE1_RE2 (ADCON1 ← 89h)
ANALOG_NOT_RE1_RE2_REF_RA3 (ADCON1 ← 8Ah)
ANALOG_NOT_RE1_RE2_REF_RA3_RA2 (ADCON1 ← 8Bh)
A_ANALOG_RA3_RA2_REF (ADCON1 ← 8Ch)
RA0_RA1_ANALOG_RA3_RA2_REF (ADCON1 ← 8Dh)
RA0_ANALOG (ADCON1 ← 8Eh)
RA0_ANALOG_RA3_RA2_REF (ADCON1 ← 8Fh)
Selección del canal analógico
set_adc_channel (canal);
canal: 0 (AN0) 4 (AN4)
1 (AN1) 5 (AN5)
2 (AN2) 6 (AN6)
3 (AN3) 7 (AN7)
w w w . i n a c a p . c l109
Lectura del resultado
valor = read_adc ();valor: Entero de 16 bits según la directiva #device adc=
empleada.La influencia de dicha directiva se recoge en la siguiente tabla
El fichero 16f877.h incluye como primera directiva #device PIC16F877A.
Es necesario incluir información del tipo de conversor A/D. Por ello los ficheros C que usen este módulo deberán comenzar por
#include “16f877A.h”#device adc=10
#device 8 bits 10 bits 11 bits 16 bits
adc=8 00-FF 00-FF 00-FF 00-FF
adc=10 x 0-3FF x x
adc=11 x x 0-7FF x
adc=16 0-FF00 0-FFC0 0-FFE0 0-FFFF
w w w . i n a c a p . c l110
setup_adc_ports (A_ANALOG);
setup_adc (ADC_CLOCK_INTERNAL);
set_adc_channel (3);
delay_us (20);
valor = read_adc ();
setup_adc (ADC_OFF);
W ← 10000010Banco 1ADCON1 ← WBanco 0
W ← ADCON0W ← W & 00111000W ← W | 11000001
ADCON0 ← WW ← ADCON0W ← W & 11000111W ← W | 00011000ADCON0 ← W
GO/DONE ← 1Espera a GO/DONE=0W ← ADRESHTEMP ¬ WBanco 1W ← ADRESLBanco 0REGL ← WW ← TEMPREGH ¬ W
W ← ADCON0W ← W & 00111000ADCON0 ← W
Ejemplo