You are on page 1of 20

PROGRAMACIÓN EN LENGUAJE C

El WinAvr dispone de un compilador compatible con el ANSI C, adicionalmente dispone de librerías


específicas para el manejo de los diferentes recursos.

Se presenta una plantilla genérica para un programa escrito para el compilador C de WinAVR

//*****************************************************************************
//
// Titulo :
// Autor :
// Fecha : 2007-03-29
// Version : 1.0
// Target MCU : Atmel AVR series
//
//
//*****************************************************************************

// -------------------------------------------------------------------------------------------------------------
//************************* Inclusión de Librerías *******************************
// -------------------------------------------------------------------------------------------------------------

#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>
#include <avr/pgmspace.h>
#include <inttypes.h>
#include "lcd_lib.h"

// -------------------------------------------------------------------------------------------------------------
//*********************** Definiciones de Variables Globales *******************
// -------------------------------------------------------------------------------------------------------------

// -------------------------------------------------------------------------------------------------------------
// ************************* Definiciones y Macros *****************************
// -------------------------------------------------------------------------------------------------------------

// -------------------------------------------------------------------------------------------------------------
// ************************ Rutinas de Interrupción ****************************
// -------------------------------------------------------------------------------------------------------------
// -------------------------------------------------------------------------------------------------------------
// ************************* Declaración de Funciones **************************
// -------------------------------------------------------------------------------------------------------------

// -------------------------------------------------------------------------------------------------------------
// **************************** Cuerpo del Programa ****************************
// -------------------------------------------------------------------------------------------------------------

int main( void )


{

// -------------------------------------------------------------------------------------------------------------
// ********************** DECLARACIÓN DE VARIABLES **********************
// -------------------------------------------------------------------------------------------------------------

// -------------------------------------------------------------------------------------------------------------
// ************** CONFIGURACIÓN DE LOS PUERTOS DE E/S *******************
// -------------------------------------------------------------------------------------------------------------

// -------------------------------------------------------------------------------------------------------------
// ********************* INICIALIZACIÓN DE REGISTROS **********************
// -------------------------------------------------------------------------------------------------------------

// -------------------------------------------------------------------------------------------------------------
// ****************** HABILITACIÓN DE INTERRUPCIONES ********************
// -------------------------------------------------------------------------------------------------------------

// -------------------------------------------------------------------------------------------------------------
// ************** INICIALIZACIÓN DE FUNCIONES Y VARIABLES ***************
// -------------------------------------------------------------------------------------------------------------
// -------------------------------------------------------------------------------------------------------------
// ******************** CICLO PRINCIPAL DE EJECUCIÓN **********************
// -------------------------------------------------------------------------------------------------------------

while (1)
{

} //Fin while

return 0;
}

// -------------------------------------------------------------------------------------------------------------
//********************* DEFINICIÓN DE FUNCIONES **************************
// -------------------------------------------------------------------------------------------------------------

// __________________________________________________________________________

WinAVR dispone de una serie de librerías que pueden incluirse dentro del programa de la cual se
dispone la respectiva documentación, algunas son del estándar C y otras propias del WinAVR.

Como ejemplo

• <alloca.h>: Allocate space in the stack


• <assert.h>: Diagnostics
• <ctype.h>: Character Operations
• <errno.h>: System Errors
• <inttypes.h>: Integer Type conversions
• <math.h>: Mathematics
• <setjmp.h>: Non-local goto
• <stdint.h>: Standard Integer Types
• <stdio.h>: Standard IO facilities
• <stdlib.h>: General utilities
• <string.h>: Strings
• <avr/boot.h>: Bootloader Support Utilities
• <avr/eeprom.h>: EEPROM handling
• <avr/fuse.h>: Fuse Support
• <avr/interrupt.h>: Interrupts
• <avr/io.h>: AVR device-specific IO definitions
• <avr/lock.h>: Lockbit Support
• <avr/pgmspace.h>: Program Space Utilities
• <avr/power.h>: Power Reduction Management
• <avr/sfr_defs.h>: Special function registers
• <avr/sleep.h>: Power Management and Sleep Modes
• <avr/version.h>: avr-libc version macros
• <avr/wdt.h>: Watchdog timer handling

Variables Globales:
Las variables comunes, sólo son accesibles desde la función donde se encuentra definida, si se requiere
que la variable sea accesible desde cualquier parte del programa, es necesario declararla como global.
Para esto simplemente se define antes de la función main().

Ej.

Volatile int var_1, var_2;

Es aconsejable aunque no obligatorio definir las variables globales como volactiles para indicarle al
compilador que no sobreescriba sobre esta posición de memoria.

Definiciones y Macros:
Mediante ciertas directivas se puede asignar a algún símbolo definido por el programador una
determinada expresión.

Ejemplos:

#define s1 2

#define larger( x, y) ( (x)>(y) ? (x) : (y))

#define _BV(bit) (1 << (bit))

#define set_bit(value, bit) (value=((value) | _BV(bit)))

Rutinas de Interrupción:
Son funciones cuyo cuerpo definen lo que se debe ejecutar en el momento que se presente una
determinada interrupción.
Ej.

ISR(TIMER0_OVF_vect)
{

PORTA=PORTA ^ 0x02;

No es necesario hacer un salto explícito a esta función, ni ejecutar alguna instrucción de retorno.

El nombre de los diferentes vectores de interrupción se definen en la librería <avr/io.h>.

/* External Interrupt Request 0 */


INT0_vect

/* External Interrupt Request 1 */


INT1_vect

/* External Interrupt Request 2 */


INT2_vect

/* Timer/Counter0 Overflow */
TIMER0_OVF_vect

/* Timer/Counter0 Compare Match */


TIMER0_COMP_vect

/* Timer/Counter1 Overflow */
TIMER1_OVF_vect

/* Timer/Counter1 Capture Event */


TIMER1_CAPT_vect

/* Timer/Counter1 Compare Match A */


TIMER1_COMPA_vect

/* Timer/Counter1 Compare Match B */


TIMER1_COMPB_vect

/* Timer/Counter2 Overflow */
TIMER2_OVF_vect

/* Timer/Counter2 Compare Match */


TIMER2_COMP_vect
/* Serial Transfer Complete */
SPI_STC_vect

/* USART, Rx Complete */
USART_RXC_vect

/* USART Data Register Empty */


USART_UDRE_vect

/* USART, Tx Complete */
USART_TXC_vect

/* ADC Conversion Complete */


ADC_vect

/* EEPROM Ready */
EE_RDY_vect

/* Analog Comparator */
ANA_COMP_vect

/* 2-wire Serial Interface */


TWI_vect

/* Store Program Memory Ready */


SPM_RDY_vect

Declaración de Funciones:
En este campo debe colocarse la declaración de las funciones a emplear con el prototipo de la función.

Ej.

int mi_funcion(int var1, int var2, float var3);

Cuerpo del Programa:


El cuerpo del programa siempre empieza con la función main() y desde donde el programa empieza
su ejecución.
Declaración de Variables:
Las variables que se definan aquí tienen un ámbito local, no son accesibles desde las funciones.

Configuración de los puertos:


// configura PORTA como salida
PORTA=0;
DDRA = 0xFF;

// configura PORTB como salida


PORTB=0;
DDRB = 0xFF;

// configura PORTC como entrada


PORTC=0;
DDRC = 0x00;

// configura PORTD as entrada


PORTD=0;
DDRD = 0x00;

Inicialización de Registros:
Se establecen los valores de los registros de propósito específico de acuerdo con las configuraciones de
los diferentes recursos.

TCNT1=0xA2B7;

En el archivo cabecera de cada dispositivo se tienen asignados los nombres de los registros.

#define TCNT1 _SFR_IO16(0x2C)

#define TCNT1L _SFR_IO8(0x2C)


#define TCNT1H _SFR_IO8(0x2D)

Habilitación de Interrupciones:
Habilitación de los diferentes bits de interrupción
Ej.

TIMSK=(1<<TOIE0);

sei(); //Habilitación del bit de interrupción global.

Inicialización de funciones y variables


Se debe establecer el estado inicial de las distintas variables y ejecutar las funciones de inicialización
requeridas.

Ej.

LCDinit();

INTRODUCCIÓN AL LENGUAJE C
PARA EL COMPILADOR WINAVR

Tipos de datos básicos:


char

Define variables de 8 bits, empleado especialmente para representación de caracteres.

Enteros: El Ansi C implementa los tipos int y long int, para datos enteros de 16 y 32 bits.

Int (-32768 a 32767)


Unsigned int (0 a 65535)

La librería #include <inttypes.h> implementa otros tipos adicionales:

Int8_t uint8_t
Int16_t uint16_t
Int32_t uint32_t
Int64_t uint64_t

float y double son punto flotante de 32 bits.


Operadores
Operador condicional

expresson1 ? expression2 : expression3

Si expresión1 es verdadera entonces se usa la expresion2, de lo contrario la expresión3.

(x)>(y) ? (x) : (y)


Ejercicios

1. Evaluar las siguientes expresiones:

(a) 5 / 2 + 20 % 6
(b) 4 * 6 / 2 - 15 / 2
(c) 5 * 15 / 2 / (4 - 2)
(d) 8 = = 16 || 7 != 4 && 4 < 1
(e) (4 * 3 < 6 || 3 > 5 - 2) && 3 + 2 < 12

2. Escriba la línea de código en C que corresponda con las siguientes sentencias:

(a) Si el residuo de A dividido B es diferente de 0 y A es mayor o igual que B o B es menor de 100


(b) Y= (AB+(C+D)’)((AB)’+C’)

Estructuras de Control
If - Else
if (expression1)
{
-------;
..-------;
} else if (expression2)
{
--------;
--------;
} else if (expression3)
{
---------;
---------;
}else
{
---------;
---------;
}
Ejemplo:

If (opcion= = 1)
{
Y=A+B;
}else if (opcion= =2)
{
Y=A-B;
} else if (opcion= =3)
{
Y= A*B;
}else
{
Y=A/B;
}

Cuando se tiene una sóla sentecia entre un para de llaves, no es obligación colocar éstas.

If (opcion= = 1)
Y=A+B;
else if (opcion= =2)
Y=A-B;
else if (opcion= =3)
Y= A*B;
else
Y=A/B;

Switch

switch (expression)
{
case constant expression1:
-----------;
-----------;
Break;
case constant expression2:
-----------;
-----------;
Break;
default constant expression2:
-----------;
-----------;
Break;
}
Ejemplo:

switch (opcion)
{

case 1:
Y=A+B;
Break;
case 2:
Y=A-B;
Break;
case 3:
Y=A*B;
Break;
default 3:
Y=A/B;
Break;
}

While

while(expression)
{
---------;
---------;
}

do - While

do
{
------------;
..------------;
} while(expression);

Ejemplo;

while ( i < 128)


{
PORTB = 2*i;
i++;
}
Cual sería el resultado obtenido en cada grupo de instrucciones:

(a) (b)

x=100; x=100;
y=0; y=0;

while ( x < 50) do


{ {
y= 2*x; y= 2*x;
x++; x++;
} } while ( x < 50);

y= ¿? y= ¿?

For

for(expresson1; expression2; expresson3)


{
--------------;
--------------;
}

for(i=0;i<=10;i++)
{
Var=2*i-1;
}

Break y Continue

Estas instrucciones permiten interrumpir una instrucción cíclica. En el caso de la instrucción break,
ésta hace que el bucle más interno que la contenga finalice inmediatamente sin tener en cuenta la
condición. La instrucción continue por su parte, finaliza la iteración actual sin salir del ciclo.

Ejemplo:
for (i=0; i<100;i++)
{
if(i==10)
continue;

sprintf(s_num,"%d\r",i); // Pasa al string s_num el valor numérico


LCDclr();
LCDGotoXY(0,0);
lcd_puts(s_num,16);
_delay_ms(500);
}

En este caso no se visualiza el valor 10 sino que es saltado.

for (i=0; i<100;i++)


{
if(i==10)
break;

sprintf(s_num,"%d\r",i); // Pasa al string s_num el valor numérico


LCDclr();
LCDGotoXY(0,0);
lcd_puts(s_num,16);
_delay_ms(500);
}

En este caso sólo se visualizan los números del 0 al 9 y termina el ciclo.

PUERTOS DE E/S

Cada Puerto tiene asociado tres registros

DDRx
Para configurar la dirección del puerto.
1 configura como salida
0 Configura como entrada

PORTx
Se emplea para enviar información por el puerto.
En caso que un determinado pin se configure como entrada, y por medio del registro PORTx se
coloque en 1, se habilita la correspondiente resistencia de pull-up.
Se recomienda que los pines que no se utilicen se les habiliten esta resistencia.

PINx
Lee el estado del puerto x

Ej.

DDRB = 0x1F;
DDRB = (1 << DDB0) | (1 << DDB1) | (1 << DDB2) | (1 << DDB3) | (1 << DDB4);

PORTB = 0x04;
PORTB = PORTB | 0x04;
PORTB |= (1<<PB2); Equivalente a la instrucción anterior.
PORTB |= (1<<PB4) | (1<<PB5); Pone los pines 4 y 5 en alto sin alterar los demás.

PORTB &= ~( (1<<PB4) | (1<<PB5) ); Pone los pines 4 y 5 en 0 sin alterar los demás.

Formas de examinar un pin.

if ( PINC & (1<<PINC1) ) { Será verdadero si el pin 1 está en alto.


/* action */
}

if ( !(PINB & (1<<PINB2)) ) { Será verdadero si el pin 1 está en bajo.


/* action */
}

Para simplificar la escritura pueden definirse ciertas macros

#define _BV( bit ) (1 << (bit))

#define E0 ((variable) & _BV(0)) Test sobre el bit 0


#define set_E0 (variable | = _BV(0))
#define clr_E0 (variable &= ~_BV(0))
INICIALIZACIÓN DE REGISTROS PARA LOS DIFERENTES RECURSOS

Timer 0 como temporizador

TCCR0=(1<<CS02)|(1<<CS00); //Escala 1024


TCNT0=T0_INI; //Inicializa el temporizador

Timer 0 como contador

TCCR0=(1<<CS02)|(1<<CS01)|(1<<CS00); //Contador por flanco de subida

Timer 0 como comparador

OCR0=128;
TCCR0=(1<<WGM01)|(1<<COM00)|(1<<CS01);
//Salida cambia de estado

Timer 0 como PWM

OCR0=128;
TCCR0=(1<<WGM00)|(1<<COM01)|(1<<CS01);

Timer 1 como temporizador

TCCR1B=(1<<CS11)|(1<<CS10); //Escala 64
TCNT1=T1_INI; //Inicializa el temporizador

Timer 1 como contador

TCCR1B=(1<<CS12)|(1<<CS11)|(1<<CS10); //Contador por flanco de subida

Timer 1 como comparador

OCR1A=256;
TCCR1A=(1<<COM1A0); //Salida cambia de estado
TCCR1B=(1<<WGM12)|(1<<CS11); //Escala 8 cambio cada 256us (OCR1A)
Timer 1 como PWM fase correcta de 10 bits

OCR1A=256;
TCCR1A=(1<<WGM11)|(1<<WGM10)|(1<<COM1A1)|(1<<COM1B1);

TCCR1B=(1<<CS11); //Escala 8 periodo 2048 ciclos con 8M = 2048us

Timer 2 como temporizador

TCCR2=(1<<CS22)|(1<<CS21)|(1<<CS20); //Escala 1024


TCNT2=T2_INI; //Inicializa el temporizador

Timer 2 como comparador

OCR2=128;
TCCR2=(1<<WGM21)|(1<<COM20)|(1<<CS21); //Salida cambia de estado

Timer 2 como PWM

OCR2=128;
TCCR2=(1<<WGM20)|(1<<COM21)|(1<<CS21); //Salida cambia de estado

Timer 2 como contador con oscilador externo

TCCR2=(1<<CS22)|(1<<CS20);
ASSR=(1<<AS2);
EJEMPLO DE INICIALIZACIÓN DE INTERRUPCIONES

Desbordamiento del TMR0

ISR(TIMER0_OVF_vect)
{
TCNT0=T0_INI;

frac++;
if(frac>=10)
{
segundos++;
frac=0;
PORTA=PORTA ^(1<<2);
}
}

TIMSK= (1<<TOIE0); //Habilita interrupción por desbordamiento TMR0

Desbordamiento del TMR1

ISR(TIMER1_OVF_vect)
{
TCNT1=T1_INI;

frac++;
if(frac>=10)
{
segundos++;
frac=0;
PORTA=PORTA ^(1<<2);
}
}

TIMSK= (1<<TOIE1); //Habilita interrupción por desbordamiento TMR1


Desbordamiento del TMR2

ISR(TIMER2_OVF_vect)
{
TCNT2=T2_INI;

frac++;
if(frac>=10)
{
segundos++;
frac=0;
PORTA=PORTA ^(1<<2);
}
}

TIMSK= (1<<TOIE2); //Habilita interrupción por desbordamiento TMR2

You might also like