Programación en C para microcontroladores PICC en HI‐TECH Profesor: Adrián Montero Ulate
EL PIC
HISTORIA DE C
Historia y particularidades •
•
•
•
•
C fue inventado en 1974 para escribir el sistema operativo UNIX C es “más” bajo nivel que otros lenguajes de alto nivel (bueno para microcontroladores) C soporta diversas arquitecturas de µC C puede hacer prácticamente cualquier cosa que se pueda hacer en ensamblador C es más rápido que ensamblador para programar
ESTRUCTURA DE UN ARCHIVO .C
Estructura #include #define _XTAL_FREQ #define _XTAL_FREQ void main(){ void main(){
Archivo de encabezado 8000000
Declaración de constante
Declaración de variable
Comentario
unsigned char var; TRISC = 0b00000000 0b00000000; ;
//Configurar Puerto C como salidas
PORTC = 0b00000001 0b00000001; ;
Función
while (1){ if(RD5 if (RD5 == 0){ PORTC = 0xF0; 0xF0; }else else{ { PORTC = 0x0F 0x0F; ; } var = var + 2; } }
COMENTARIOS
Comentarios •
Dos maneras de hacerlos –
Bloque de comentario: /*
Esto es un comentario
de dos líneas
–
*/
Comentario en una sola línea: //Comentario corto
VARIABLES
Variables Una variable es un nombre que representa una o más posiciones de memoria utilizadas para guardar datos del programa. •
Puede ser visto como un contenedor que puede guardar datos usados en el programa
int miVari int miVariable; able; miVariable miVariable = 5;
Variables ‐ Ejemplo #include #define PI 3.14 void main(){ void main(){ Tipo de dato
int radio, area;
Declaración de variables
Tipo de dato
//Calcular el área del círculo Variables en uso radio = 12 12; ; area = PI * radio * radio; }
Variables •
Las variables son nombres para posiciones de Memoria de datos (RAM) memoria
int factor; char letra; float longitud;
Variables •
La declaración consiste en un identificador Memoria de datos (RAM) único (nombre)
int factor; char letra; float longitud;
Variables •
Y un tipo de dato –
Determina el tamaño
–
Determina como se
interpreta el dato
int factor; char letra; float longitud;
Memoria de datos (RAM)
IDENTIFICADORES
Identificadores •
Nombres dados a elementos tales como –
Variables
–
Funciones
–
Arreglos
–
Otros elementos
Identificadores •
Caracteres válidos en identificadores
IDENTIFICADOR Primer Caracter ‘_’ (guión bajo) ‘A’ a la ‘Z’ ‘a’ a la ‘z’
Caracteres Restantes ‘_’ (guión bajo) ‘A’ a la ‘Z’ ‘a’ a la ‘z’ ‘0’ al ‘9’
•
Sensible a mayúsculas y minúsculas
•
Solo reconoce los primeros 31 caracteres
PALABRAS RESERVADAS
Palabras reservadas del ANSI C
•
Otros compiladores podrían incorporar más palabras reservadas
TIPOS DE DATOS
Tipos de datos fundamentales
•
Tipo
Descripción
bits
char
Caracter simple
8
Int
Entero
16
float
Coma flotante
32
double
Coma flotante de doble precisión
64
El tamaño de un int varía de un compilador a otro –
MPLAB C30 int es de 16‐bits
–
MPLAB C18 int es de 16‐bits
–
CCS PCB, PCM & PCH int es de 8‐bits
–
Hi‐Tech PICC int es de 16‐bits
Calificadores de tipos de dato •
Calificadores: unsigned, signed, short y long Calificador
Min
Max
unsigned char char, signed char
0
255
8
12 8
127
8
0
65535
16
32768
3276 7
16
0
65535
16
32768
3276 7
16
0
232 ‐ 1
32
231
231
32
0
264 ‐ 1
64
231
231
64
‐
unsigned short int short int, signed short int
‐
unsigned int int, signed int
‐
unsigned long int long int, signed long int
‐
unsi un sign gned ed lo long ng lo long ng int long long int, signed long long int
Bits
‐
Declaración de variables tipo identificador1, … , identificadorn; •
•
•
Una variable debe ser declarada antes de poder ser usada. El compilador necesita saber cuanto espacio asignarle y como manejar sus valores. Ejemplos
int x, y, z; float factor; char texto unsigned int indice;
Declaración de variables •
Las variables se pueden declarar de varias maneras:
Sintaxis Una declaración en una línea tipo identificador;
Una declaración en una línea con valor inicial tipo identificador = ValorInicial;
Múltiples declaraciones del mismo tipo en una línea tipo identificador1, identificador2, identificador3;
Múltiples declaraciones del mismo tipo en una línea con valor inicial tipo identificador1 = Valor1, identificador2 = Valor2;
Ejemplos unsigned int x; unsigned int y = 12 12; ; int a, b, c; long int var = 0x12345678 0x12345678; ; char primero char primero = ‘a’ ‘a’, , segundo, tercero = ‘c’ ‘c’; ; float numeroGrande = 6.02e+23 6.02e+23; ;
*Se acostumbra usar la notación “camel case” para las variables: primera palabra en minúscula y todas las siguientes con la primera letra en mayúscula. Ejemplo: unaVariable, estoEsUnNombreLargo, otroNombreAlternativo
Variables •
•
•
Algunas veces las variables (y otros elementos) son declarados en un archivo separado llamado archivo de encabezado Los archivos de encabezado terminan con la extensión ‘.h’ Se enlazan al programa principal por medio de
MiPrograma.h
la directiva #include MiPrograma.c
CONSTANTES
FUNCIONES
DECLARACIONES
OPERADORES
Operadores Definición: una expresión aritmética es una expresión que contiene uno o más operandos y operadores aritméticos •
Los operandos pueden ser variables, constantes o funciones que retornan un valor –
•
Generalmente se trata los registros de un µC como variables
Existen 9 operadores aritméticos: –
Operadores binarios: +, ‐, *, /, %
–
Operadores unarios: +, ‐, ++, ‐‐
Operadores Operador
Operación
Ejemplo
*
Multiplicación
x*y
Producto de x por y
/
División
x/y
Cociente de x entre y
%
Modulo
x%y
Residuo de x entre y
+
Suma
x+y
Suma de x más y
‐
Resta
x – y
Resta de x menos y
+(unario)
Positivo
+x
(unario)
Negativo
‐
‐
x
Resultado
Valor de x Valor opuesto de x
Conversiones implícitas •
En algunas expresiones, el tipo de un operando será temporalmente “promovido” al tipo más grande de operando
int x = 10 10; ; float y = 2.0 2.0, , z; z = x * y; //x es promovido a float durante la operación
Jerarquía de conversión implícita o p i t l a o n d ó i i t s r e e r v p n x o e c a s l e n o e ñ e e d u n q a e r p g s s á á m m o p i t l E
Incremento y decremento Operador
Operación
Ejemplo
Resultado
++
Incremento
x++ ++x
Usa x y luego incrementa por 1 Incrementa x por 1 y luego lo usa
‐‐
Decremento
x---x
Usa x y luego decrementa por 1 Decrementa x por 1 y luego lo usa
Ejemplo con sufijo
x = y = //y / /x
5; (x++) (x++ ) + 5; = 10 = 6
Ejemplo con prefijo
x = y = //y //x
5; (++x) (++x ) + 5; = 11 = 6
Sentencias de asignación Definición: una sentencia de asignación es una sentencia que asigna un valor a una variable •
Hay dos tipos de sentencias de asignación: –
Asignación simple •
variable = expresión;
La expresión se evalúa y luego se asigna a la variable –
Asignación compuesta •
variable = variable operador expresión;
La variable aparece de los dos lados del igual
Operadores de asignación Operador
Operación
Ejemplo
Resultado
=
Asignación
x=y
Asigna a x el valor de y
+=
x += y
x=x+y
‐
=
x ‐= y
x = x – y
*=
x *= y
x=x*y
/=
x /= y
x=x/y
x %= y
x=x%y
x &= y
x=x&y
^=
x ^= y
x=x^y
|=
x |= y
x=x|y
<<=
x <<= y
x = x << y
>>=
x >>= y
x = x >> y
%= &=
Asignación compuesta
Operadores relacionales Operador
Operación
Ejemplo
Resultado
<
Menor que
x
1 si x es menor que y, sino 0
<=
Menor o igual que
x <= y
1 si x es menor o igual a y, sino 0
>
Mayor que
x>y
1 si x es mayor que y, sino 0
>=
Mayor o igual que
x >= y
1 si x es mayor o igual a y, sino 0
==
Igual a
x == y
1 si x es igual a y, sino 0
!=
Diferente de
x != y
1 si x es diferente de y, sino 0
Diferencia entre = y == •
= es el operador de asignación x = 5 //Asigna 5 a la variable x
•
== es el operador relacional “igual a” x == 5
//REVISA si x es igual a 5
Operadores Lógicos Operador
Operación
Ejemplo
Resultado
&&
AND Lógico
x && y
1 si x ≠ 0 y y ≠ 0, sino 0
||
OR Lógico
x || y
0 si si x = 0 y y = 0, sino 1
!
NOT Lógico
!x
1 si x =0, sino 0
Cualquier valor diferente de cero es interpretado como TRUE (Verdadero). Un 0 siempre es falso.
Operadores Lógicos de bits Operador
Operación
Ejemplo
Resultado (para cada bit en el dato)
&
AND (bits)
x&y
1, si hay un 1 en ambos x,y 0, si hay un 0 en uno o ambos x,y
||
OR (bits)
x|y
1, si hay un 1 en x O y 0, si hay un 0 en ambos x,y
^
XOR (bits)
x^y
1, si hay un 1 en x O y, pero no en los dos 0, si hay un 0 ó 1 en ambos x,y
~
NOT (bits)
~x
1, si hay 0 en x 0, si hay 1 en x
•
La operación se lleva a cabo en cada bit del primer operando comparado al bit correspondiente del segundo operando
Diferencias entre operadores lógicos & y && Tenga cuidado de no confundir el & con el &&. No son intercambiables •
& es el operador AND entre bits 0b1010 & 0b1101
•
=
0b1000
&& es el operador Lógico AND 0b1010 && 0b1101
=
0b0001 (TRUE)
&& = 1 (TRUE) •
Operador condicional •
Sintaxis: (expr-prueba) ? hacer-si-cierto : hacer-si-falso;
Ejemplo: int x = 5; (x % 2 != 0) ? printf(“%d printf(“%d es impar”, impar”, x) : printf(“%d printf(“%d es par”, par”, x);
EXPRESIONES
Expresiones •
•
Representan un solo dato (ej: caracter, número, etc) Puede consistir de: –
–
Entidad simple (una constante, variable, etc) Combinación de entidades conectadas por operadores (+, ‐, +, /, etc)
Ejemplos de Expresiones a + b x = y v el o c i d a d = d is t / t i e m p o z = k c <= 7 x == 25 contador++ d = a + 5
SENTENCIAS
Sentencias •
Ocasionan una acción
•
Hay tres tipos de sentencias en C: –
Sentencias de expresión
–
Sentencias compuestas
–
Sentencias de control
Expresiones •
•
Una expresión es seguida por un ‘;’ El ejecutar la sentencia de expresión hace que la expresión sea evaluada
Ej: i = 0; i++; a = 5 + i; y = (m * x) + b;
Sentencias compuestas •
•
Un grupo de expresiones individuales agrupadas por corchetes { y } Puede contener cualquier tipo de sentencias, inclusive otras compuestas
•
Permite incluir sentencias dentro de otras
•
NO termina con un ;
•
También llamados “bloques de código”
Sentencias de control •
•
Usadas para lazos, decisiones y pruebas lógicas Usualmente requieren otra expresión dentro de ellas
Ejemplo: while (distancia < 400 400){ ){ printf(“Siga printf(“Siga corriendo”); corriendo”); distancia += 0.1 0.1; ; }
DECISIONES EXPRESIONES BOOLEANAS
Expresiones booleanas •
•
C NO tiene tipo de dato booleano Las expresiones booleanas retornan un valor entero (int) –
0: Falso
–
1: Verdadero (diferente de cero, no es 1 garantizado)
DECISIONES IF
IF Sintaxis: if (expresión) sentencia •
•
La expresión es evaluada por un valor booleano: Verdadero (≠ 0) ó Falso (= 0) Si expresión es verdadero se ejecuta la sentencia
IF ‐ Diagrama Sintaxis: if (expresión) sentencia
IF ‐ Anidados int potencia int potencia = 10 10; ; float banda float banda = 2.0 2.0; ; float frecuencia = 146.52 146.52; ; if (potencia > 5){ if(banda if (banda == 2.0 2.0){ ){ if((frecuencia if ((frecuencia > 144 144) ) && (frecuencia < 148 148)){ )){ //Frecuencia adecuada!! } } }
DECISIONES IF ELSE
IF ‐ ELSE Sintaxis: if (expresión) sentencia1 else sentencia2 •
•
La expresión es evaluada por un valor booleano: Verdadero (≠ 0) ó Falso (= 0) Si expresión es verdadero se ejecuta la sentencia1, sino se ejecuta la sentencia2
IF – IF – ELSE ‐ Diagrama Sintáxis: if (expresión) sentencia1 else sentencia2
DECISIONES IF ELSE IF
IF – IF – ELSE IF Sintaxis: if (expresión1) sentencia1 else if (expresión2) sentencia2 else sentencia3 •
•
•
•
•
La expresión1 es evaluada por un valor booleano: Verdadero (≠ 0) ó Falso (= 0) Si es verdadero se ejecuta sentencia 1 Si es falso, se evalúa la expresión 2 Si es verdadero se ejecuta la sentencia2 Si es falso se ejecuta la sentencia3
IF – IF – ELSE ‐ Diagrama Sintaxis: if (expresion1) sentencia1 else if (expresion2) sentencia2 else sentencia3
DECISIONES SWITCH
SWITCH Sintaxis: switch (expresion) { case const-expr1: sentencia1 … case const-expr2: sentencia2 default: default : sentencian+1 } else sentencia2
•
• •
“expresion” es evaluado contra cada valor de const‐ expr en cada “case” La sentencia en el “case” adecuado es la que se ejecuta Si ninguna condición se cumple se ejecuta la sentencia en el default
SWITCH Diagrama (pre‐definido) Nótese que el comportamiento pre‐ definido del switch es el de continuar con el siguiente caso una vez que se ejecuta el presente.
SWITCH Diagrama (modificado) Para evitar que luego de una sentencia se ejecute la siguiente automáticamente insertamos un break a cada bloque de código dentro de las sentencias. Esto permite que se ejecute únicamente la porción de código deseada.
SWITCH – SWITCH – Ejemplo 1 switch (puerto) { case 1: PORTA = 0xFF 0xFF; ; break break; ; case 2: PORTB = 0xFF 0xFF; ; break break; ; case 3: PORTC = 0xFF 0xFF; ; break break; ; case 4: PORTD = 0xFF 0xFF; ; break break; ; default: default : PORTA = 0x00 0x00; ; }
SWITCH – SWITCH – Ejemplo 2 switch (canal) Aplicar a los casos: 4, 5, 6 y 7 { case 4..7 4..7: : printf(“Estación printf(“Estación VHF”); VHF”); break break; ; case 9..12 9..12: : printf(“Estación printf(“Estación VHF”); VHF”); break break; ; case 3: Casos 3 y 8 “caen” al caso 13, case 8: ya que no tienen un break; case 13 13: : printf(“Señal printf(“Señal Débil”); Débil”); break break; ; case 14..69 14..69: : printf(“Estación printf(“Estación UHF”); UHF”); break break; ; default: default : printf(“No printf(“No hay señal disponible”); disponible”); }
CICLOS FOR
Ciclo FOR Sintaxis: for (expresion1; expresion2, expresion3) sentencia •
•
•
expresion1 inicializa una variable para el conteo al inicio del ciclo (ej: i = 0) expresion2 es la condición de prueba, el ciclo
continuará mientras esta condición sea cierta (ej: i <=10) expresion3 se ejecuta al final de cada iteración, usualmente para modificar la variable de conteo. (Ej: i++)
Ciclo FOR Diagrama for (expresion1; expresion2, expresion3) sentencia
Inicializar variable para el ciclo
i = 0
Modificar variable de ciclo
i++ Probar variable ante condición de salida
Ciclo FOR – FOR – Ejemplo 1 int i; for (i = 0; i < 5; i++) { PORTB = i; //Cada ciclo el valor de i varía por 1, y se cambia lo que se muestra en el el puerto. } Salida en el Puerto B: 0x00 0x01 0x02 0x03 0x04
Ciclo FOR Particularidades •
•
•
Cualquiera de las expresiones puede obviarse en el for, pero deben aparecer los ‘;’ Si expresion1 o expresion3 faltan, sus acciones simplemente desaparecen, o no se lleva a cabo ninguna acción. Si la expresion2 falta, se asume que es verdadera. for ( ; { … }
; ) Este ciclo se ejecutará indefinidamente, o hasta que se salga de él con un break;
CICLOS WHILE
Ciclo WHILE Sintaxis: while (expresion)
•
•
sentencia
Si expresion es verdadera, sentencia será ejecutada. Luego expresion será re‐evaluada para determinar si se ejecuta de nuevo sentencia o no. Es posible que sentencia nunca se ejecute si al evaluar por primera vez expresion esta es falsa.
Ciclo WHILE Diagrama while (expresion) sentencia
Ciclo WHILE – WHILE – Ejemplo int i = 0;
Se inicializa la variable afuera del ciclo
La condición se verifica al inicio de while (i < 5) cada iteración { PORTB = i; Ciclo incrementado manualmente i++; //Cada ciclo el valor de i varía por 1, y se cambia lo que se muestra en el el puerto. Salida en el Puerto B: } 0x00 0x01 0x02 0x03 0x04
Ciclo WHILE Particularidades •
•
La expresion SIEMPRE debe aparecer, no se puede obviar. Es utilizado más frecuentemente que el for para hacer ciclos infinitos.
while (1) { … }
Este ciclo se ejecutará indefinidamente, o hasta que se salga de él con un break;
CICLOS DO WHILE
Ciclo DO‐WHILE Sintaxis: do sentencia while (expresion)
•
sentencia es ejecutada y luego expresion se
evalúa para determinar si se debe o no ejecutar de nuevo la sentencia. •
sentencia SIEMPRE se va a ejecutar al menos
1 vez, aún cuando expresion sea falsa cuando se inicie el ciclo.
Ciclo DO‐WHILE Diagrama do sentencia while (expresion)
Ciclo DO‐WHILE – WHILE – Ejemplo int i = 0;
Se inicializa la variable afuera del ciclo
do { PORTB = i; Ciclo incrementado manualmente i++; //Cada ciclo el valor de i varía por 1, y se cambia lo que se muestra en el el puerto. Salida en el Puerto B: } while (i < 5) 0x00 La condición se verifica al final de cada iteración
0x01 0x02 0x03 0x04
CICLOS BREAK
CICLOS CONTINUE
ARREGLOS
PUNTEROS
ESTRUCTURAS
ENUMERACIONES
MACROS
INTERRUPCIONES
DELAYS
ARCHIVOS ENLAZADOS
PUERTOS A/D
LEDS
LCD
EEPROM
TIMERS
RS‐232
SPI
PWM
STEPPERS