14/08/2014
Programación Programac ión C para AVR AVR Programacion C Escuela Militar de Ingenieria Ing. Germán Pereira Pereira Muñoz
07/22/10
Ing. Germán Pereira Muñoz – Programacion C para AVR
1
14/08/2014
Herramientas de Programacion • Editor • Compilador • Linker • Loader • Debugger
07/22/10
• Integrated Development Environment › Algunas veces solo es una interface para comandos basicos: Programmers Notepad [WinAVR]
Ing. Germán Pereira Muñoz – Programacion C para AVR AVR
3
WinAVR • WinAVR es un ejecutable, pertenece a las herramientas herramientas de desarrollo (open source software) para Atmel AVR de la serie de microprocesadores microprocesadores RISC para plataforma Windows. Incluye GNU GCC compilador para C y C++. › http://winavr.sourceforge.net/
07/22/10
Ing. Germán Pereira Muñoz – Programacion C para AVR AVR
4
2
14/08/2014
Comentarios en C • /* Comentarios
de varias lineas */ • //Comentarios para fin de linea
07/22/10
Ing. Germán Pereira Muñoz – Programacion C para AVR
5
Includes • Include es un archivo – tipicamente es un archivo cabecera que contiene declaraciones • #include
› Es un archivo include de sistema estandar
• #include "mystuff.h" › Archivo include para un proyecto especifico
07/22/10
Ing. Germán Pereira Muñoz – Programacion C para AVR
6
3
14/08/2014
Definiciones • #define simbolo cualquier asignacion • Esto se llama macro › Define a cualquier cosa para ser un cadena estring de texto › Ejemplo: • #define FALSE 0 • #define Cadena “hola” • #define PI 3.1416 07/22/10
Ing. Germán Pereira Muñoz – Programacion C para AVR
7
Prototipos de Funcion(Cabeceras) • Las Funciones deben ser declaradas antes de su uso : › Una declaracion no es mas que cabecera de la funcion no la funcion en si • Las declaraciones de Funcion(cabeceras) puden ser incluidas en una archivo include
› La definicion de la funcion es incluida en el cuerpo de la funcion
• void function_name(int, float); //cabecera › Retorno de tipo es requerido; void significa que no retorna nada › Tipos de Argumentos (los nombres no son necesarios, pero se puede incluir los nombres si se decea)
07/22/10
Ing. Germán Pereira Muñoz – Programacion C para AVR
8
4
14/08/2014
Main • Cualquier programa C necesita una funcion llamada main • Generalmente definida (no declarada) int main(void){ int x; //variable local x = add(3, 9); //llamada a funcion return 0; }
• El cuerpo de programa se encuentra entre laves { } • Esta funcion tradicionalmente retorna 0 07/22/10
Ing. Germán Pereira Muñoz – Programacion C para AVR
9
Otras Funciones • Otras definiciones de funcion son usualmente puestas por debajo de la funcion main o en un archivo separado int add(int a, int b){ return a+b; }
07/22/10
Arguentos pasados por valor a la funcion Ing. Germán Pereira Muñoz – Programacion C para AVR
10
5
14/08/2014
Variables • Especificado por a tipo, scope, lifetime, y name › Tipo con char, int, float, etc • Los Tipos especiales de AVR como uint8_t, int16_t, etc
› Scope son • Local (block) – declaradas dentro de las funciones • Global (file) – declaradas fuera de las funciones • Program (external) – Usadas para enlazar entre varios archivos
› Lifetime son • Automatic (por defecto para variables locales) (en el stack) • Static (por defecto para variables globales y de programa) (en la ram) • Dynamic (programa controlado de asignacion de almacenamiento) (en la estructura de datos heap)
07/22/10
Ing. Germán Pereira Muñoz – Programacion C para AVR
11
Asignacion de Variables uint8_t x = 3; //asignacion e inicializacion externa int8_t loquesea(uint_8 a)//parametro local automatico { int_8 negOne = 0xFF;
// local automatico
static int8_t serial = 1;
//local statico
return (serial++) + a + negOne; }
• •
Locales automaticos existen solo cuando dura la llamada de la funcion Los datos globales y static son creados e inicializados una sola vez en el programa; estos retiene valores entre llamadas de funciones 07/22/10
Ing. Germán Pereira Muñoz – Programacion C para AVR
12
6
14/08/2014
Literales • Los enteros pueden ser expresados en varias bases › decimal: 29, -13, 0 › octal: 0377 › hexadecimal: 0x34F2 › binario: 0b011011 • Characteres › 'a' • String › “Es un Strig terminado en NUL almacenado en un ARRAY" 07/22/10
Ing. Germán Pereira Muñoz – Programacion C para AVR
13
Arrays • Declaracion de ARRAYS uint8_t edad[10]; int16_t temp[5]; int8_t ejemplo[] = {-1, 2, -5};
• Si es posible los Arrays son Dinamicamente asignados arrays, pero requieren una funcion de asignacion de memoria
07/22/10
Ing. Germán Pereira Muñoz – Programacion C para AVR
14
7
14/08/2014
Estructuras (struct) • Basicamente las Structuras no son mas que coleccion de variables llamadas miembros • Las Variables dentro de la estructura no tienen el mismo tipo • Declaracion general de una estructura: struct structure_tag_name{
struct structure_tag_name{
type member1; type member2; ... type memberX };
type member1; type member2; ... type memberX } structure_variable_name
07/22/10
Ing. Germán Pereira Muñoz – Programacion C para AVR
15
Ejemplo: struct struct posicion { int x; int y; }robot;
Tambien se puede utilizar lo siguiente: robot.x=10; robot.y=15;
O simplemente robot={10,15}; 07/22/10
Ing. Germán Pereira Muñoz – Programacion C para AVR
16
8
14/08/2014
Enumeracion de Variables • Similar a #define donde se puede describir un conjunto de constantes. Usando #define tenemos: • #define cero 0 • #define uno 1 • #define dos 2 • La alternativa es usando una enumeracion usando enum: • enum (cero=0,uno, dos); //cero=0, uno=1; dos=2 • La Enumercacion por defecto asigna los valores de 0
07/22/10
Ing. Germán Pereira Muñoz – Programacion C para AVR
17
Ejemplo Usando el siguiente ejemplo int n; e n u m ( c e ro = 0 ,u n o , d o s ) ; n = u n o ; / /n = 1
Se puede usar la enumeracion de la siguiente manera: enum escapes { B ELL = '\a', BA CKSPACE = '\b', HTAB = '\t', RETURN = '\r', NEWL INE = '\n', VTAB = '\v' }; o
enum bo olean { FALSE = 0, TRUE };
La ventaja usar enum sobre #define es que la variable solo es visible en el bloque donde fue declarada Ejemplo: main () { enum mes {Ene=1, Feb, Mar, Ap r, May, Jun, Ju l, Ago, Sep, Oct, Nov, Dec}; // ^ - - t a b l a d e e n u m e r a c i o n ^ - -l i s t a d e a l i as printf("%d\n" , mes=Sep); // Asign a un valor entero via el alias // es t a in s t ru c c io n re t o rn a 9 } 07/22/10
Ing. Germán Pereira Muñoz – Programacion C para AVR
18
9
14/08/2014
Seleccion • if (condición) si es verdadero; › En expresiones Aritméticas es verdadero si el resultado es diferente de cero y falso cuando es 0
• if (condición) { › Si es verdadero;
}
• else { //este bloque solo si es necesario › Si es falso;
}
07/22/10
Ing. Germán Pereira Muñoz – Programacion C para AVR
19
Seleccion multiple • Intruccion switch switch (condicion) {
case exprecion constate }
Ejemplo: switch (i/10) {
case 0: { printf ("Numero menor a 10"); // A break;} case 1: { printf ("Numero menor a 20"); // B break;} case 2: { printf ("Numero menor a 30"); // C break;} default: { printf ("Numero mayor o igual a 40"); // D break;}
} 07/22/10
Ing. Germán Pereira Muñoz – Programacion C para AVR
20
10
14/08/2014
Repeticion • while (condicion) {
// repite el bucle si la condicion es verdadero }; • do{
// repite el bucle si la condicion es verdadera
} while (condicion); • for (inicio; condicion; incremento) { //repite el bucle mientras se cumple la condicion } 07/22/10
Ing. Germán Pereira Muñoz – Programacion C para AVR
21
Puertos de E/S DDRx - Este registro determina la direccion (input/output) de los pins en port[x] A '0' bit en DDR pone al pin del puerto como entrada (input) A '1' bit en DDR pone al pin del puerto como salida (output) PORTx - Este registro contienen el estado para salida de los pines en port[x] A '0' bit pone al pin del puerto como salida=0 (LOW ~0V) A '1' bit pone al pin del puerto como salida=1 (HIGH ~5V) PINx - Este registro contiene el estado de entrada de los pines en port[x] A '0' bit indica que el pin del puerto es = 0 (LOW ~0V) A '1' bit indica que el pin del puerto es = 1 (HIGH ~5V)
La X puede ser reemplazada por A,B,C,D,E,F, o G dependiendo del puerto designado. 07/22/10
Ing. Germán Pereira Muñoz – Programacion C para AVR
22
11
14/08/2014
Instrucciones AVR-GCC En el Lenguaje C de AVR-GCC, los puertos pueden ser atendidos usando dos comandos › inb() lectura de byte › outb() salida de byte Ejemplo: outb(DDRB, 0xFE); conf. el bit menos significativo del PORTB como entrada a = inb(PINB); Lectura del estado de entrada de los pin es del PORTB
inb() y outb() pueden ser usados cuando se intenta leer o escribir varios bits en un registro a la vez. cbi() pone en cero un bit › › sbi() pone en uno un bit Ejemplo: sbi(DDRD, 7); // coloca PD7 como salida // coloca PD0 como salida sbi(DDRD, 0); cbi(DDRD, 4); // coloca PD4 como entrada
07/22/10
Ing. Germán Pereira Muñoz – Programacion C para AVR
23
Puertos • PORT E/S y manipulacion de bit › PORTB =
0xFF;
› GICR |= (1<
› uint8_t pins = PIND; 07/22/10
Ing. Germán Pereira Muñoz – Programacion C para AVR
24
12
14/08/2014
Testeando Bits • if
(PIND & _BV(4)){
//bit 4 en uno
} • if (~PIND & _BV(4)){ › //bit 4 en cero
} • if (!(PIND & _BV(4))){ › //bit 4 en cero
}
07/22/10
Ing. Germán Pereira Muñoz – Programacion C para AVR
25
Interrupciones • sei() y cli() habilitan o deshabilitan las interrupciones • Para preservar el estado de la interrupcion activa se puede usar: › uint8_t sreg = SREG; › cli(); ›… › SREG = sreg; 07/22/10
Ing. Germán Pereira Muñoz – Programacion C para AVR
26
13
14/08/2014
Uso en C de los Registros • Los Procedimientos pueden usar libremente los registros R18-R27, R30-R31 › Si se llama una funcion C desde assembler, este seguro de salvar estos registros si el contenido es importante
• Los Procedimientos pueden salvar los registros R2-R17, R28-R29 › La funciones en Ensamblador llamadas desde C deben salvar sus registros
• R0 es un registro temporal y puede ser usado libremente • R1 es siempre usado en el codigo C › En una funcion en lenguaje ensamblador llamada desde C se debe estar seguro de limpiar este registro antes del retorno
07/22/10
Ing. Germán Pereira Muñoz – Programacion C para AVR
27
Llamada a funciones en C • Los Argumentos son pasados a los pares de registros › › › ›
Arg1 esta en R25:R24 (byte data en R24) Arg2 esta en R23:R22 … Arg9 esta en R9:R8 • Para argumentos adicionales son colocados el pila de datos (data stack)
• El retorno de valores esta en los registros R25:R24 (datos de 8-bit si sign/zero), R25-R22 (32-bit), y R25-R18 (64-bit) 07/22/10
Ing. Germán Pereira Muñoz – Programacion C para AVR
28
14
14/08/2014
Punteros • Los punteros son variables que contienen la direccion de datos
//una variable uint8 uint8_t * numPtr; //un puntero a un valor uint8 uint8_t num = 5;
• Operador de Direccion › numPtr = # //direccion de variable 07/22/10
Ing. Germán Pereira Muñoz – Programacion C para AVR
29
Punteros y Arrays • Los Nombres de Array son punteros constantes › El nombre, representa la direccion base de un array, pero solo como valor • int16_t numbers[4] = {5, 7, -2, 6}; • int16_t * aPtr; • aPtr = numbers;
numbers 5 7
-2
6
• aPtr = &numbers;
Las ultimas 2 son identicas aPtr 0060
07/22/10
Ing. Germán Pereira Muñoz – Programacion C para AVR
El Array es almacenado en la direccion $0060 - $0067 30
15
14/08/2014
Aritmetica de Punteros bytes 5
42 7
-2
6
int8_t bytes[4] = {5, 7, -2, 6}; int8_t * aPtr = bytes; aPtr 5 0060 PORTB = *aPtr; -2 PORTB = *(aPtr+2); *(aPtr+1) = PIND; aPtr 42 aPtr++; 5 0061 PORTB = *(aPtr-1); aPtr+=2; aPtr 6 PORTB = *aPtr; 0063
07/22/10
• Aritmetica de Punteros respecto al tamaño de los datos apuntados › p+1 es uno {byte, word, double word, etc} pasa donde p apunta dependiendo del tipo de datos • Solo soporta adicion y sustraccion
Ing. Germán Pereira Muñoz – Programacion C para AVR
31
Parametros por Referencia • La funciones en C con llamada por valor void func_v(char x){ PORTB = x;
func_v(a); }
• Se puede pasar y recivir la direccion de un dato, resultando la llamada por referencia char a; func_r(&a); 07/22/10
void func_r(char * x){ *x = '$'; } Ing. Germán Pereira Muñoz – Programacion C para AVR
32
16
14/08/2014
Cadena de Caracteres (Strings) • Los Strings son implementados en arrays de caracteres p › char p[6]; //no inicializado › char q[6] = "Joe"; q
//Usa 4 de lo 6 bytes
?? ?? ?? ?? ?? ??
4A 6F 65 00 ?? ??
NUL
• Los Arrays pueden ser implicitamente creados como un puntero 4A 6F 65 n › char * n = "Joe";
00
07/22/10
33
Ing. Germán Pereira Muñoz – Programacion C para AVR
Datos en la Flash #include prog_uint16_t myData[] = {874, 299, 14987, 37};
prog_char Texto[] = “Hola Mundo";
• Esto crea datos en la memoria de programa (flash) › Debe ser una asignacion statica
07/22/10
Ing. Germán Pereira Muñoz – Programacion C para AVR
34
17
14/08/2014
Macros de Datos de Programa uint16_t x = pgm_read_word(miDato+2); for (i=0; i<3; i++) char y = pgm_read_byte(&Texto[i]);
• Estos macros requieren que la direccion (address) los datos sea accedida › La direccion de un Array es una direccion • miDato+2 es lo mismo que &miDato[2] • &Texto[i] es lo mismo que Texto+i
07/22/10
Ing. Germán Pereira Muñoz – Programacion C para AVR
35
Funciones para String de la Memoria de Programa • Adicionando _P a una funcion estandar para usar los string de la memoria programa › int n = strlen_P (Texto);
• El destino de los strings debe ser la RAM › strcpy_P(ramStr , Texto);
• Use PGM_P para declarar un puntero a string en la memoria de programa › PGM_P pptr = Texto; › char c; › while (c = pgm_read_byte(pptr++)){... 07/22/10
Ing. Germán Pereira Muñoz – Programacion C para AVR
36
18
14/08/2014
Delays • #define F_CPU 4000000UL • #include • _delay_us(93); › Maximo delay: 768 us / F_CPU en MHz
• _delay_ms(10); › Maximo delay: 262.14 ms / F_CPU en MHz.
• _delay_loop_1(24); › Usa un contador de 8 bit, 3 ciclos por iteracion › Pasa 0 para un maximo de (256) iterationes
// 4 MHz Numero de bucles de iteracion(para implementar el delay) esta basado en la velocidad del procesador
• _delay_loop_2(1039); › Usa un contador de 16 bit, 4 cicles por iteracion › Pasa 0 para un maximo de (65536) iteraciones
07/22/10
Ing. Germán Pereira Muñoz – Programacion C para AVR
37
math.h • Incluye todas las funciones matematicas necesarias – fabs, sqrt, sin, asin, ceil, floor, • Nota: trabaja con datos de punto flotante, y tambien con datos tipo entero requeridos en la mayodira de lo programas de AVR
07/22/10
Ing. Germán Pereira Muñoz – Programacion C para AVR
38
19
14/08/2014
Manejo de Interrupciones #include ISR(interrupt name) { //codigo de interrupcion //No se necesita salvar ni restaurar el estado del CPU, este proceso es automtico //la instruccion RETI es adicionada automaticamante
}
• In addition to defining the handler, you need to enable/disable interrupts – GICR |= (1<
Ing. Germán Pereira Muñoz – Programacion C para AVR
39
Ejemplo de Programa Diagrama Circuital iotest.c
07/22/10
Ing. Germán Pereira Muñoz – Programacion C para AVR
40
20
14/08/2014
Programa Ejemplo iotest.c archivo: global.h #ifndef GLOBAL_H #define GLOBAL_H // global AVRLIB defines #include "avrlibdefs.h" // global AVRLIB types definitions #include "avrlibtypes.h" // project/system dependent defines // CPU clock speed #define F_CPU 16000000 //#define F_CPU 14745000 //#define F_CPU 8000000 //#define F_CPU 7372800 //#define F_CPU 4000000 //#define F_CPU 3686400
// 16MHz processor // 14.745MHz processor // 8MHz processor // 7.37MHz processor // 4MHz processor // 3.69MHz processor
#define CYCLES_PER_US ((F_CPU+500000)/1000000) // cpu cycles per microsecond #endif
07/22/10
Ing. Germán Pereira Muñoz – Programacion C para AVR
41
########### change this lines according to your project ################## #put the name of the target mcu here (at90s8515, at90s8535, attiny22, atmega603 etc.) MCU = atmega16 #put the name of the target file here (without extension) TRG = iotest #put your C sourcefiles here SRC = $(TRG).c #put additional assembler source file here ASRC = #additional libraries and object files to link LIB = #additional includes to compile INC = #assembler flags ASFLAGS = -Wa, -gstabs #compiler flags CPFLAGS = -g -Os -Wall-Wstrict-prototypes -I$(AVRLIB) -Wa,-ahlms=$(<:.c=.lst) #linker flags LDFLAGS = -Wl,-Map=$(TRG).map,--cref ########### you should not need to change the following line ############# include $(AVRLIB)/make/avrproj_make buffer.o : buffer.c buffer.h uart.o : uart.c uart.h global.h uart2.o : uart2.c uart2.h global.h rprintf.o : rprintf.c rprintf.h Ing. Germán Pereira Muñoz – a2d.o : a2d.c a2d.h Programacion C para AVR timer.o : timer.c timer.h global.h pulse.o : pulse.c pulse.h timer.h global.h 07/22/10 42 lcd.o : lcd.c lcd.h global.h
Programa Ejemplo iotest.c archivo: make
21
14/08/2014
Programa Ejemplo iotest.c • Cabecera //----- Archivos Include --------------------------------------------------------#include // include I/O definiciones (nombres : port, pin , etc) #include // include nombres "signal" (nombres interrupcion) #include // include soporte para interrupciones #include "global.h" // include configuraciones globales #include
07/22/10
Ing. Germán Pereira Muñoz – Programacion C para AVR
43
Programa Ejemplo iotest.c • Funcion main //----- Inicio de Codigo -----------------------------------------------------------int main(void) { u08 a,cont; // declarando variables outb(DDRB, 0xFE); // configura el bit menossignificatibo del PORTB como entrada a = inb(PINB); // Lectura del estado de entrada de los pines del PORTB outb(DDRC, 0xFF); // configura todo el PORTC como salida outb(PORTC, 0xF0); // PORTC PC4-7 en HIGH Y PC0-3 to LOW sbi(DDRD, 7); sbi(DDRD, 0); while(1) {
// configura PD7 como salida // configura PD0 como salida
BUCLE INFINITO
} return 0; } 07/22/10
Ing. Germán Pereira Muñoz – Programacion C para AVR
44
22
14/08/2014
Programa Ejemplo iotest.c •
Bucle infinito
while(1) { for(cont=0;cont<255;cont++) { outb(PORTC, cont); sbi(PORTD, 0); _delay_ms(50); cbi(PORTD, 0); _delay_ms(50); a = inb(PINB); if(a==1) { sbi(PORTD, 7); // sets PD7 to output a 1 } else{ cbi(PORTD, 7); // sets PD7 to output a 0 } } } 07/22/10
Ing. Germán Pereira Muñoz – Programacion C para AVR
45
Programmers Notepad
07/22/10
Ing. Germán Pereira Muñoz – Programacion C para AVR
46
23
14/08/2014
Programmers Notepad
07/22/10
Ing. Germán Pereira Muñoz – Programacion C para AVR
47
Simulación en AVRStudio
07/22/10
Ing. Germán Pereira Muñoz – Programacion C para AVR
48
24
14/08/2014
Simulación en AVRStudio
07/22/10
Ing. Germán Pereira Muñoz – Programacion C para AVR
49
Simulador/Debugger • Para trasar atravez del codigo assembler, se necesita usar disassembly window
Puntero de depuracio n
07/22/10
Ing. Germán Pereira Muñoz – Programacion C para AVR
50
25