Escolar Documentos
Profissional Documentos
Cultura Documentos
Desenvolvimento Com Microcontroladores Atmel AVR
Desenvolvimento Com Microcontroladores Atmel AVR
Desenvolvimento Com Microcontroladores Atmel AVR
8000
8 256
1
= 0, 256 ms
Caso seja do interesse utilizar taxas de amostragem mais precisas, alm de alterar os valores do
relgio e do prescaler, pode-se, por exemplo, escrever determinado valor no registrador TCNT0 toda
vez em que ocorrer o sinal de overow. Assim, cada contagem se dar a partir do valor escrito, e no
do zero, que o padro.
A congurao destas funcionalidades nos outros dois timers similar. Basta consultar [Atmel 2004]
para vericar os registradores envolvidos.
5.2.2 PWM
Com exceo do timer/counter 0, os outros temporizadores trazem consigo a funcionalidade da con-
gurao do PWM. Como j foi dito, este tipo de modulao muito utilizado para o acionamento
de motores de corrente contnua. Um exemplo de circuito utilizado para tal nalidade com o uso do
AVR e do circuito integrado L298 encontra-se disponvel no circuito do Anexo E. Neste exemplo,
implementou-se um controle bidirecional de velocidade (um ciclo de trabalho de 50 % mantm o motor
parado e o sinal do pino 14 deve ser o complemento do sinal do pino 15).
A gerao do sinal PWM com o AVR se baseia na comparao dos estados dos contadores com
valores pr-determinados. Assim, o resultado dessa comparao utilizado para alterar a sada do
PWM e, em ltima instncia, denir o ciclo de trabalho do sinal PWM gerado.
Neste contexto, o ATmega8 permite a gerao de trs sinais PWM simultneos. Dois deles so
gerados com o timer/counter 1, que permite resoluo de 16 bits, e o outro com o timer/counter 2, cuja
resoluo permitida de 8 bits. A congurao dessa funo relativamente simples, bastando atentar
s tabelas de congurao referentes aos registradores TCCR1A, TCCR1B ou TCCR2, dependendo
do caso, disponveis em [Atmel 2004]. Abaixo demonstra-se um exemplo de funo para inicializar a
gerao de dois sinais PWM simultneos a partir do timer/counter 1. Para alterar o valor da taxa de
trabalho, basta escrever nos registradores OCR1AH e OCR1AL para o sinal A e OCR1BH e OCR1BL
para o sinal B.
19
void PWM_Iniciar (void){
// valores iniciais dos sinais PWM
OCR1AH = 0x03;
OCR1AL = 0xFF;
OCR1BH = 0x03;
OCR1BL = 0xFF;
// configuracao do PWM
TCCR1A = _BV(COM1A1) | _BV(COM1A0) | _BV(COM1B1) | _BV(COM1B0) | _BV(WGM10) | _BV(WGM11);
TCCR1B = _BV(CS11) | _BV(WGM12);
// set PB1 e PB2 as output
DDRB = _BV(DDB1) | _BV(DDB2);
}
Na congurao acima descrita, o prescaler foi congurado para 8 (CS11) e utilizado o Fast
PWM de 10 bits (WGM10,11,12). Os bits COMXXX so utilizados para denir a sada da operao
de comparao.
5.3 Converso A/D
Muitos sistemas que utilizam microcontroladores requerem a medio de variveis de natureza anal-
gica. Alguns exemplos so a temperatura medida por um termmetro, a posio angular medida por
um potencimetro, entre outros. Neste contexto, para que essas informaes possam ser utilizadas
pelo microcontrolador, h a necessidade de se converter tais sinais para seus correspondentes digitais.
O dispositivo utilizado para esta operao o conversor analgico/digital, ou conversor A/D.
O AVR possui um conversor A/D com resoluo de 10 bits. Esse mesmo conversor pode ser
acessado por seis diferentes canais nos encapsulamentos PDIP. Ou seja, com um AVR ATmega8 neste
encapsulamento pode-se medir facilmente seis sinais analgicos, porm no simultaneamente. Isso se
d porque existe um nico conversor A/D com entradas multiplexadas. Alm do mais o AVR possui
um circuito sample-and-hold que mantm o valor analgico da entrada constante durante o processo
de converso, o que quer dizer que o projetista no precisa se preocupar quanto a esse aspecto no
projeto do circuito. De fato, est disponvel em anexo um simples circuito para conexo dos valores
a serem medidos nos pinos correspondentes. Este circuito oferece certa proteo ao conversor A/D
contra sub- e sobre-tenses. Alm disso, a converso A/D se utiliza uma fonte de tenso distinta
(AVCC), cujo valor no pode diferir muito do valor de VCC, sendo na verdade a alimentao VCC
passada por um ltro para minimizar utuaes na tenso de alimentao do conversor. O conversor
A/D ainda requer uma tenso de referncia analgica (AREF), que pode ser tanto interna como
externa. De fato, o mximo valor obtido na converso, que seria 1023 visto que o conversor A/D
de 10 bits, ocorrer quando a entrada se igualar ao valor de AREF. Recomenda-se a consulta ao
manual do microcontrolador [Atmel 2004] para melhor compreender o funcionamento do conversor
A/D e atentar para restries de operao, sob o risco de danicar permanentemente o conversor.
A utilizao das funes de converso A/D tambm no complicada, conforme mostra o exemplo
a seguir:
void AD_Iniciar (void) {
// enable ADC e prescaler com division factor 64(ADPS2 e ADPS1)
ADCSRA = _BV(ADEN) | _BV(ADPS2) | _BV(ADPS1);
// setar referncia
ADMUX = _BV(REFS0);
}
void AD_Converter(unsigned char canal, unsigned char *pdatah, unsigned char *pdatal){
ADMUX = _BV(REFS0) | (canal & 0x0F);
ADCSRA |= (0x01<<ADSC);
// esperar fim de conversao
while((ADCSRA & (0x40)));
20
// copiar resultado
*pdatal = ADCL; // deve ser lido antes de ADCH
*pdatah = ADCH;
}
void main (void) {
unsigned char canal,convh, convl;
...
AD_Iniciar();
...
while(true){
...
canal = 1;
AD_Converter(canal,&convh,&convl);
...
}
}
Deve ser observado que o programa acima pode ser usado com o circuito de teste da seo E,
que faz uso do canal 1 do conversor. No CD, o projeto exemplo voltmeter mais completo pois
corresponde a um voltmetro com display de LEDs. No entanto, o projeto voltmeter usa o canal 0
do conversor A/D.
5.4 Comunicao Serial (no revisado)
A m de que o AVR envie e receba dados por meio de sua interface serial, basta congurar os
registradores corretos. Neste sentido, os principais bits a serem ativados so o RXEN e o TXEN do
registrador UCSRB, que liberam a recepo e a transmisso, respectivamente. Alm disso, preciso
indicar o baud rate utilizado por meio dos registradores UBRRH e UBRRL (ver pginas 156-159
de [Atmel 2004] para tabela de valores), o tamanho da palavra, por meio dos bits UCSZ0, UCSZ1
e UCSZ2 do registrador UCSRC e o bit de parada por meio do bit USBS do mesmo registrador.
A seguir disponibiliza-se exemplos de funo para congurar a comunicao serial, enviar e receber
dados:
void USART_Iniciar (void) {
//Setar baud rate 38400
UBRRH = (unsigned char)(25>>8);
UBRRL = (unsigned char)(25);
//Enable TXD, RXD e ativar RXCIE(enable interrupt on the RCX flag)
UCSRB = _BV(TXEN) | _BV(RXEN); //| _BV(RXCIE);
//Setar tamanho palavra (formatao da comunicao serial)
UCSRC = _BV(URSEL) | _BV(UCSZ1) | _BV(UCSZ0) | _BV(USBS);
//Ativar double speed
UCSRA = _BV(U2X);
}
void USART_Transmitir (unsigned char c) {
//Verificar se o buffer da serial est vazio
while ( !(UCSRA & (1<<UDRE)) );
//coloca o dado no buffer e envia
UDR = c;
}
unsigned char USART_Receber (void) {
//Esperar at que seja feita comunicao em RXD
while ( !(UCSRA & (1<<RXC)) );
//Recebe o dado do buffer
21
return UDR;
}
Dos cdigos acima, percebe-se que, para enviar e receber, basta ler ou escrever no registrador
UDR, a partir do momento em que ele se encontra preenchido ou no, de acordo com o caso. Mais
especicamente, UDRE um bit que informa se o registrador em questo est vazio e RXC o bit que
informa se a recepo se foi nalizada.
Para compatibilidade com o padro RS-232, necessria uma interface, que compe a camada
fsica do protocolo. Isto devido ao fato de o protocolo RS-232 trabalhar com faixas de tenso
distintas do padro 0-5V da interface de comunicao serial. Com este objetivo, utiliza-se o circuito
integrado MAX-232 e um conjunto de capacitores de 10F. O circuito correspondente encontra-se
disponvel no Anexo E.
Para testar o funcionamento do sistema de comunicao serial, recomenda-se a utilizao de
programas como o HyperTerminal, disponvel no Windows ou o Terminal, disponvel online.
5.5 Usando o PC como terminal de teclado/vdeo
Quando as funes da biblioteca STDIO direcionam seus canais stdin e stdout porta serial do micro-
controlador, pode-se utilizar funes tais como printf ou scanf para imprimir mensagens na tela ou
ler teclas do teclado de um microcomputador PC. Nesta congurao, diz-se que o microcomputador
est operando apenas como terminal. Para tanto, faz-se necessrio conectar o ATmega8 porta serial
do PC por meio de um conversor de nvel RS-232, tal como o MAX232. Isto feito no circuito da
Figura 12. No PC, faz-se necessrio ter um programa terminal rodando, tal como o Hyperterminal.
Em um programa terminal, tudo que for teclado enviado porta serial na forma de caractere ASCII.
E tambm, todo dado que chegar pela porta serial impresso na tela tambm como caractere ASCII.
O programa exemplo abaixo faz com que o ATmega8 reenvie ao PC tudo que for recebido pela
porta serial. O exemplo est tambm disponvel no CD de iniciao na forma do exemplo terminal.
#include <avr/io.h>
#include <stdio.h>
void USART_Init(void);
int USART_Transmit( char data );
int USART_Receive( void );
int main(void)
{
char ch;
USART_Init();
/*registrando as funes de leitura e escrita de um byte pela serial*/
fdevopen(USART_Transmit, USART_Receive, 0);
//escrevendo "Ola, mundo!" pela serial
printf ("Ola, mundo");
while(1){
// As duas linhas abaixo fazem a mesma coisa: o caracter que chegar
// pela serial ser ecoado por ela. Entretanto, as funes usadas so diferentes.
// A diferena fundamental est na compexidade de cada uma delas.
// Para ter uma melhor compreenso disto, descomente apenas uma das linhas abaixo,
// e compile o programa para ver a diferena de tamanho do programa compilado.
scanf ("%c", &ch); printf ("%c", ch); // Soluo 1.
// putchar(getchar()); // Soluo 2.
}
22
}
/*
Funo que faz a inicializcao da usart para comunicacao assincrona com o PC
a 9600 baud rate com 16MHz de cristal externo.
A recepo e transmisso so habilitadas, sobrepondo as funes dos pinos TxD e RxD.
Nenhuma interrupo habilitada.
*/
void USART_Init(void)
{
/*zerando o contedo do registrador de dados da serial*/
UDR=0;
//Seta baud rate de 9600 para fosc= 16MHz
UBRRH = 0;
UBRRL = 103;
//Habilita transmisso e recepo serial
UCSRB = _BV(TXEN)| _BV(RXEN);
//Setar tamanho palavra
//URSEL = 1 -> seleciona acesso para UCSRC (0 is UBRRH) reading and writing
//UMSEL = 0 -> Asynchronous Operation
//UPM1 e UPM0 = 00 -> sem paridade
//USBS = 1 -> seleciona 2 bits de parada a ser inserido pelo transmissor
//UCSZ 2 1 0 = 011 -> escolhe tamanho de caractere de 8 bits p/ dado
UCSRC = _BV(URSEL) | _BV(UCSZ1) | _BV(UCSZ0);
}
// Faz a leitura de um byte da serial usando pooling
int USART_Receive( void )
{
while ( !(UCSRA & (1<<RXC)) ); // Wait for data to be received
return UDR; // Get and return received data from buffer
}
// Faz a transmissao de um byte pela serial
int USART_Transmit( char data )
{
while ( !( UCSRA & (1<<UDRE)) ); // Wait for empty transmit buffer
UDR = data; // Put data into buffer, sends the data
return 0;
}
Caso o usurio deseje imprimir no terminal nmeros em ponto utuante com a funo printf, ele
deve descomentar a seguinte linha do arquivo makele (Anexo D):
#LDFLAGS += -Wl,-u,vfprintf -lprintf_flt
5.6 Display LCD
Uma das maneiras mais interessantes de apresentar informaes relativas ao sistema utiliza displays
de cristal lquido (LCDs). Neste sentido, esta subseo disponibiliza um exemplo que pode auxiliar
aqueles que pretendem utilizar este dispositivo. Este exemplo faz uso da bilioteca lcd.c disponvel
no site http://homepage.hispeed.ch/peterfleury/avr-lcd44780.html. O exemplo est tambm
disponvel no CD de iniciao na forma do exemplo lcdmsg.
#include <inttypes.h>
#include <string.h>
#include <stdio.h>
#include <avr/io.h>
23
#define F_CPU 16.0E6 // relgio com cristal externo de 16MHz
#include <avr/delay.h>
#include "lcd.h"
void delay_us(unsigned int timedelay_us);
void delay_ms(unsigned int timedelay_ms);
int main (void)
{
unsigned int segundos = 0, milisegundos = 0;
char s[10];
lcd_init(LCD_DISP_ON);
lcd_clrscr();
lcd_home();
lcd_puts("Iniciando...");
delay_ms(1000);
lcd_clrscr();
lcd_home();
for(;;){
delay_ms(100);
if((milisegundos+=100)>=1000){
milisegundos = 0;
++segundos;
}
sprintf(s,"%d:%2d",segundos, milisegundos/10);
lcd_gotoxy(7-strlen(s)/2,0);
lcd_puts(s);
}
}
void delay_us(unsigned int timedelay_us)
{
while(timedelay_us>1000){
_delay_loop_2(4000); // 1ms
timedelay_us-=1000;
}
timedelay_us = (4*timedelay_us);
_delay_loop_2(timedelay_us);
}
void delay_ms(unsigned int timedelay_ms)
{
while(--timedelay_ms>0)
delay_us(1000); // 1ms;
}
6 Concluses
Esta nota tcnica apresentou algumas ferramentas bsicas para desenvolvimento de projetos com
microcontroladores AVR. A partir das informaes disponibilizadas, o leitor convidado a buscar as
mais diversas aplicaes, bem como novas funcionalidades no descritas neste documento. Este ,
de fato, o maior objetivo daqueles que contriburam para a elaborao deste documento e que foram
efetivamente usurios do microcontrolador ATmega8.
24
Referncias
[Atmel 2004]ATMEL. ATmega8(L) Complete Datasheet. [S.l.], 2004.
25
A CD de iniciao ao AVR
Para melhor acompanhar esta nota tcnica, est sendo disponibilizado no site http://www.ene.unb.
br/~gaborges/recursos/embarcados/index.htm um CD com todas as ferramentas de desenvolvi-
mento, exemplos e documentao. Como o CD est disponvel na internet, qualquer outra pessoa
interessada pode baix-lo. O arquivo leiame.txt detalha o contedo do CD e d vrias dicas de
como fazer melhor uso do microcontrolador. No CD tambm existem vrios exemplos de programas.
B Iniciao rpida
Para aqueles que querem se iniciar rapidamente com o desenvolvimento com AVR, mesmo que cor-
rendo todos os riscos associados compreenso limitada do que est sendo realizado, sugere-se seguir
os seguintes passos:
Instalar o WinAVR (Ferramentas - software\WinAVR). Se houver uma verso anterior no
microcomputador, a mesma deve ser desinstalada;
Construir uma gravadora BSD (Ferramentas - hardware\BSD prog simples). No esquecer
de congurar na BIOS do seu computador que a porta paralela deve operar em modo Standard
(geralmente usa-se a sigla SPP);
Construir um circuito de referncia (Ferramentas - hardware\Circuito de referncia ATMEGA8);
Testar o circuito de referncia e a gravadora seguindo o procedimento da Seo 3.1.3.
Usar o Programmers Notepad para desenvolver o projeto (instalado com o WinAVR). Se o
microcontrolador novo, deve-se lembrar que sua congurao de fbrica implica que a fonte
de relgio um circuito RC interno a 1MHz. Uma recomendao para os novatos consiste em
partir de um dos exemplos do CD de iniciao ao AVR;
Vericar se o Makele est adaptado ao projeto. No esquecer de especicar o microcontrolador
(no caso, ATmega8), a gravadora (no caso, bsd) e a porta em que ela est conectada (lpt1, se
porta paralela 1);
Ligue a alimentao do circuito com o microcontrolador. A gravadora BSD deve estar conectada
ao microcontrolador e ao microcomputador;
Use as opes [WinAVR] Make Clean, [WinAVR] Make All e [WinAVR] Make Program do menu
Tools do Programmers Notepad para limpar o projeto, compilar e gravar no microcontrolador.
Se tudo der certo, ao nal dos procedimentos acima o programa dever estar sendo executado no
microcontrolador.
Estes passos foram escritos considerando que o usurio dispe do CD de iniciao (Anexo A);
C Referncias na Internet
http://www.atmel.com/ : pgina do fabricante, com manuais e notas de aplicao;
http://www.avrfreaks.net/ : a principal fonte para aqueles que buscam auxlio para o desen-
volvimento com microcontrolador da srie AVR c da Atmel;
26
http://www.microschematic.com/ : apresentao em Flash indicada para aqueles que desejam
programar em assembly;
http://winavr.sourceforge.net/ : site ocial do pacote de desenvolvimento WinAVR;
http://www.bsdhome.com/avrdude/ : site do programador AVRDUDE (BSD);
http://www.freertos.org/ : site do FreeRTOS, um kernel que possui suporte linha de
microcontroladores AVR;
http://members.home.nl/jmnieuwkamp1/AVRlib/ : site da biblioteca AVRlib, que contm um
grande nmero de funes par uso e interface para microcontroladores AVR;
http://homepage.hispeed.ch/peterfleury/index.html : site do Peter Fleury com projetos,
exemplos. Tem uma placa de desenvolvimento e algumas bibliotecas.
D Exemplo de makele
O arquivo makefile (sem extenso) essencial para projetos em que o processo de compilao
mais complexo, embora seja tambm bastante til para projetos simples. O makefile um arquivo
texto com diretivas que determinam como cada arquivo do projeto deve ser compilado, linkado e
como o resultado nal deve ser apresentado. Este arquivo usado pelo utilitrio make.exe, devendo
estar no mesmo diretrio da chamada, quando se executa algo do tipo make procedimento em que
procedimento uma palavra reservada que caracteriza o procedimento a ser realizado. De acordo
com o arquivo makefile abaixo, esto denidos procedimentos all, clean e program, entre outros
procedimentos intermedirios:
make all: procedimento de compilao de todos os arquivos fonte que foram alterados desde
a ltima compilao, e gerao de vrios arquivos, entre eles a imagem .hex a ser gravada no
microcontrolador.
make clean: apaga todos os arquivos intermedirios e resultantes de compilao, deixando
apenas os arquivos fonte de um projeto. um procedimento geralmente usado quando se
deseja guardar apenas o necessrio de um projeto para, talvez, enviar para algum.
make program: grava o programa no microcontrolador utilisando a gravadora congurada no
makefile.
O arquivo makefile usado como exemplo foi extrado de um exemplo do pacote WinAVR. Para
compreend-lo, faz-se necessrio saber como o utilitrio make.exe funciona. Para tanto, sugere-se
o site http://www.gnu.org/software/make/manual/make.html. Entretanto, o arquivo est muito
bem comentado.
# Hey Emacs, this is a -*- makefile -*-
#----------------------------------------------------------------------------
# WinAVR Makefile Template written by Eric B. Weddington, Jrg Wunsch, et al.
#
# Released to the Public Domain
#
# Additional material for this makefile was written by:
# Peter Fleury
# Tim Henigan
# Colin OFlynn
# Reiner Patommel
# Markus Pfaff
# Sander Pool
27
# Frederik Rouleau
# Carlos Lamas
#
#----------------------------------------------------------------------------
# On command line:
#
# make all = Make software.
#
# make clean = Clean out built project files.
#
# make coff = Convert ELF to AVR COFF.
#
# make extcoff = Convert ELF to AVR Extended COFF.
#
# make program = Download the hex file to the device, using avrdude.
# Please customize the avrdude settings below first!
#
# make debug = Start either simulavr or avarice as specified for debugging,
# with avr-gdb or avr-insight as the front end for debugging.
#
# make filename.s = Just compile filename.c into the assembler code only.
#
# make filename.i = Create a preprocessed source file for use in submitting
# bug reports to the GCC project.
#
# To rebuild project do "make clean" then "make all".
#----------------------------------------------------------------------------
# MCU name
MCU = atmega8
# Processor frequency.
# This will define a symbol, F_CPU, in all source code files equal to the
# processor frequency. You can then use this symbol in your source code to
# calculate timings. Do NOT tack on a UL at the end, this will be done
# automatically to create a 32-bit value in your source code.
# Typical values are:
# F_CPU = 1000000
# F_CPU = 1843200
# F_CPU = 2000000
# F_CPU = 3686400
# F_CPU = 4000000
# F_CPU = 7372800
# F_CPU = 8000000
# F_CPU = 11059200
# F_CPU = 14745600
F_CPU = 16000000
# F_CPU = 18432000
# F_CPU = 20000000
# Output format. (can be srec, ihex, binary)
FORMAT = ihex
# Target file name (without extension).
TARGET = voltmeter
# Object files directory
# To put object files in current directory, use a dot (.), do NOT make
28
# this an empty or blank macro!
OBJDIR = .
# List C source files here. (C dependencies are automatically generated.)
SRC = main.c
# List C++ source files here. (C dependencies are automatically generated.)
CPPSRC =
# List Assembler source files here.
# Make them always end in a capital .S. Files ending in a lowercase .s
# will not be considered source files but generated files (assembler
# output from the compiler), and will be deleted upon "make clean"!
# Even though the DOS/Win* filesystem matches both .s and .S the same,
# it will preserve the spelling of the filenames, and gcc itself does
# care about how the name is spelled on its command-line.
ASRC =
# Optimization level, can be [0, 1, 2, 3, s].
# 0 = turn off optimization. s = optimize for size.
# (Note: 3 is not always the best optimization level. See avr-libc FAQ.)
OPT = 2
# Debugging format.
# Native formats for AVR-GCCs -g are dwarf-2 [default] or stabs.
# AVR Studio 4.10 requires dwarf-2.
# AVR [Extended] COFF format requires stabs, plus an avr-objcopy run.
DEBUG = dwarf-2
# List any extra directories to look for include files here.
# Each directory must be seperated by a space.
# Use forward slashes for directory separators.
# For a directory that has spaces, enclose it in quotes.
EXTRAINCDIRS =
# Compiler flag to set the C Standard level.
# c89 = "ANSI" C
# gnu89 = c89 plus GCC extensions
# c99 = ISO C99 standard (not yet fully implemented)
# gnu99 = c99 plus GCC extensions
CSTANDARD = -std=gnu99
# Place -D or -U options here for C sources
CDEFS = -DF_CPU=$(F_CPU)UL
# Place -D or -U options here for ASM sources
ADEFS = -DF_CPU=$(F_CPU)
# Place -D or -U options here for C++ sources
CPPDEFS = -DF_CPU=$(F_CPU)UL
#CPPDEFS += -D__STDC_LIMIT_MACROS
#CPPDEFS += -D__STDC_CONSTANT_MACROS
29
#---------------- Compiler Options C ----------------
# -g*: generate debugging information
# -O*: optimization level
# -f...: tuning, see GCC manual and avr-libc documentation
# -Wall...: warning level
# -Wa,...: tell GCC to pass this to the assembler.
# -adhlns...: create assembler listing
CFLAGS = -g$(DEBUG)
CFLAGS += $(CDEFS)
CFLAGS += -O$(OPT)
CFLAGS += -funsigned-char
CFLAGS += -funsigned-bitfields
CFLAGS += -fpack-struct
CFLAGS += -fshort-enums
CFLAGS += -Wall
CFLAGS += -Wstrict-prototypes
#CFLAGS += -mshort-calls
#CFLAGS += -fno-unit-at-a-time
#CFLAGS += -Wundef
#CFLAGS += -Wunreachable-code
#CFLAGS += -Wsign-compare
CFLAGS += -Wa,-adhlns=$(<:%.c=$(OBJDIR)/%.lst)
CFLAGS += $(patsubst %,-I%,$(EXTRAINCDIRS))
CFLAGS += $(CSTANDARD)
#---------------- Compiler Options C++ ----------------
# -g*: generate debugging information
# -O*: optimization level
# -f...: tuning, see GCC manual and avr-libc documentation
# -Wall...: warning level
# -Wa,...: tell GCC to pass this to the assembler.
# -adhlns...: create assembler listing
CPPFLAGS = -g$(DEBUG)
CPPFLAGS += $(CPPDEFS)
CPPFLAGS += -O$(OPT)
CPPFLAGS += -funsigned-char
CPPFLAGS += -funsigned-bitfields
CPPFLAGS += -fpack-struct
CPPFLAGS += -fshort-enums
CPPFLAGS += -fno-exceptions
CPPFLAGS += -Wall
CFLAGS += -Wundef
#CPPFLAGS += -mshort-calls
#CPPFLAGS += -fno-unit-at-a-time
#CPPFLAGS += -Wstrict-prototypes
#CPPFLAGS += -Wunreachable-code
#CPPFLAGS += -Wsign-compare
CPPFLAGS += -Wa,-adhlns=$(<:%.cpp=$(OBJDIR)/%.lst)
CPPFLAGS += $(patsubst %,-I%,$(EXTRAINCDIRS))
#CPPFLAGS += $(CSTANDARD)
#---------------- Assembler Options ----------------
# -Wa,...: tell GCC to pass this to the assembler.
# -adhlns: create listing
# -gstabs: have the assembler create line number information; note that
# for use in COFF files, additional information about filenames
# and function names needs to be present in the assembler source
# files -- see avr-libc docs [FIXME: not yet described there]
# -listing-cont-lines: Sets the maximum number of continuation lines of hex
30
# dump that will be displayed for a given single line of source input.
ASFLAGS = $(ADEFS) -Wa,-adhlns=$(<:%.S=$(OBJDIR)/%.lst),-gstabs,--listing-cont-lines=100
#---------------- Library Options ----------------
# Minimalistic printf version
PRINTF_LIB_MIN = -Wl,-u,vfprintf -lprintf_min
# Floating point printf version (requires MATH_LIB = -lm below)
PRINTF_LIB_FLOAT = -Wl,-u,vfprintf -lprintf_flt
# If this is left blank, then it will use the Standard printf version.
PRINTF_LIB =
#PRINTF_LIB = $(PRINTF_LIB_MIN)
#PRINTF_LIB = $(PRINTF_LIB_FLOAT)
# Minimalistic scanf version
SCANF_LIB_MIN = -Wl,-u,vfscanf -lscanf_min
# Floating point + %[ scanf version (requires MATH_LIB = -lm below)
SCANF_LIB_FLOAT = -Wl,-u,vfscanf -lscanf_flt
# If this is left blank, then it will use the Standard scanf version.
SCANF_LIB =
#SCANF_LIB = $(SCANF_LIB_MIN)
#SCANF_LIB = $(SCANF_LIB_FLOAT)
MATH_LIB = -lm
# List any extra directories to look for libraries here.
# Each directory must be seperated by a space.
# Use forward slashes for directory separators.
# For a directory that has spaces, enclose it in quotes.
EXTRALIBDIRS =
#---------------- External Memory Options ----------------
# 64 KB of external RAM, starting after internal RAM (ATmega128!),
# used for variables (.data/.bss) and heap (malloc()).
#EXTMEMOPTS = -Wl,-Tdata=0x801100,--defsym=__heap_end=0x80ffff
# 64 KB of external RAM, starting after internal RAM (ATmega128!),
# only used for heap (malloc()).
#EXTMEMOPTS = -Wl,--section-start,.data=0x801100,--defsym=__heap_end=0x80ffff
EXTMEMOPTS =
#---------------- Linker Options ----------------
# -Wl,...: tell GCC to pass this to linker.
# -Map: create map file
# --cref: add cross reference to map file
LDFLAGS = -Wl,-Map=$(TARGET).map,--cref
LDFLAGS += $(EXTMEMOPTS)
LDFLAGS += $(patsubst %,-L%,$(EXTRALIBDIRS))
LDFLAGS += $(PRINTF_LIB) $(SCANF_LIB) $(MATH_LIB)
#LDFLAGS += -T linker_script.x
31
#---------------- Programming Options (avrdude) ----------------
# Programming hardware
# Type: avrdude -c ?
# to get a full listing.
#
AVRDUDE_PROGRAMMER = bsd
# com1 = serial port. Use lpt1 to connect to parallel port.
AVRDUDE_PORT = lpt1 # programmer connected to parallel port
AVRDUDE_WRITE_FLASH = -U flash:w:$(TARGET).hex
#AVRDUDE_WRITE_EEPROM = -U eeprom:w:$(TARGET).eep
# Uncomment the following if you want avrdude leave with /RESET=1 (microcontroller running).
AVRDUDE_EXIT_NO_RESET = -E noreset
# Uncomment the following if you want avrdudes erase cycle counter.
# Note that this counter needs to be initialized first using -Yn,
# see avrdude manual.
#AVRDUDE_ERASE_COUNTER = -y
# Uncomment the following if you do /not/ wish a verification to be
# performed after programming the device.
#AVRDUDE_NO_VERIFY = -V
# Increase verbosity level. Please use this when submitting bug
# reports about avrdude. See <http://savannah.nongnu.org/projects/avrdude>
# to submit bug reports.
#AVRDUDE_VERBOSE = -v -v
AVRDUDE_FLAGS = -p $(MCU) -P $(AVRDUDE_PORT) -c $(AVRDUDE_PROGRAMMER)
AVRDUDE_FLAGS += $(AVRDUDE_NO_VERIFY)
AVRDUDE_FLAGS += $(AVRDUDE_VERBOSE)
AVRDUDE_FLAGS += $(AVRDUDE_ERASE_COUNTER)
AVRDUDE_FLAGS += $(AVRDUDE_EXIT_NO_RESET)
#---------------- Debugging Options ----------------
# For simulavr only - target MCU frequency.
DEBUG_MFREQ = $(F_CPU)
# Set the DEBUG_UI to either gdb or insight.
# DEBUG_UI = gdb
DEBUG_UI = insight
# Set the debugging back-end to either avarice, simulavr.
DEBUG_BACKEND = avarice
#DEBUG_BACKEND = simulavr
# GDB Init Filename.
GDBINIT_FILE = __avr_gdbinit
# When using avarice settings for the JTAG
JTAG_DEV = /dev/com1
# Debugging port used to communicate between GDB / avarice / simulavr.
DEBUG_PORT = 4242
32
# Debugging host used to communicate between GDB / avarice / simulavr, normally
# just set to localhost unless doing some sort of crazy debugging when
# avarice is running on a different computer.
DEBUG_HOST = localhost
#============================================================================
# Define programs and commands.
SHELL = sh
CC = avr-gcc
OBJCOPY = avr-objcopy
OBJDUMP = avr-objdump
SIZE = avr-size
AR = avr-ar rcs
NM = avr-nm
AVRDUDE = avrdude
REMOVE = rm -f
REMOVEDIR = rm -rf
COPY = cp
WINSHELL = cmd
# Define Messages
# English
MSG_ERRORS_NONE = Errors: none
MSG_BEGIN = -------- begin --------
MSG_END = -------- end --------
MSG_SIZE_BEFORE = Size before:
MSG_SIZE_AFTER = Size after:
MSG_COFF = Converting to AVR COFF:
MSG_EXTENDED_COFF = Converting to AVR Extended COFF:
MSG_FLASH = Creating load file for Flash:
MSG_EEPROM = Creating load file for EEPROM:
MSG_EXTENDED_LISTING = Creating Extended Listing:
MSG_SYMBOL_TABLE = Creating Symbol Table:
MSG_LINKING = Linking:
MSG_COMPILING = Compiling C:
MSG_COMPILING_CPP = Compiling C++:
MSG_ASSEMBLING = Assembling:
MSG_CLEANING = Cleaning project:
MSG_CREATING_LIBRARY = Creating library:
# Define all object files.
OBJ = $(SRC:%.c=$(OBJDIR)/%.o) $(CPPSRC:%.cpp=$(OBJDIR)/%.o) $(ASRC:%.S=$(OBJDIR)/%.o)
# Define all listing files.
LST = $(SRC:%.c=$(OBJDIR)/%.lst) $(CPPSRC:%.cpp=$(OBJDIR)/%.lst) $(ASRC:%.S=$(OBJDIR)/%.lst)
# Compiler flags to generate dependency files.
GENDEPFLAGS = -MMD -MP -MF .dep/$(@F).d
# Combine all necessary flags and optional flags.
# Add target processor to flags.
ALL_CFLAGS = -mmcu=$(MCU) -I. $(CFLAGS) $(GENDEPFLAGS)
ALL_CPPFLAGS = -mmcu=$(MCU) -I. -x c++ $(CPPFLAGS) $(GENDEPFLAGS)
33
ALL_ASFLAGS = -mmcu=$(MCU) -I. -x assembler-with-cpp $(ASFLAGS)
# Default target.
all: begin gccversion sizebefore build sizeafter end
# Change the build target to build a HEX file or a library.
build: elf hex eep lss sym
#build: lib
elf: $(TARGET).elf
hex: $(TARGET).hex
eep: $(TARGET).eep
lss: $(TARGET).lss
sym: $(TARGET).sym
LIBNAME=lib$(TARGET).a
lib: $(LIBNAME)
# Eye candy.
# AVR Studio 3.x does not check makes exit code but relies on
# the following magic strings to be generated by the compile job.
begin:
@echo
@echo $(MSG_BEGIN)
end:
@echo $(MSG_END)
@echo
# Display size of file.
HEXSIZE = $(SIZE) --target=$(FORMAT) $(TARGET).hex
ELFSIZE = $(SIZE) --mcu=$(MCU) --format=avr $(TARGET).elf
sizebefore:
@if test -f $(TARGET).elf; then echo; echo $(MSG_SIZE_BEFORE); $(ELFSIZE); \
2>/dev/null; echo; fi
sizeafter:
@if test -f $(TARGET).elf; then echo; echo $(MSG_SIZE_AFTER); $(ELFSIZE); \
2>/dev/null; echo; fi
# Display compiler version information.
gccversion :
@$(CC) --version
# Program the device.
program: $(TARGET).hex $(TARGET).eep
$(AVRDUDE) $(AVRDUDE_FLAGS) $(AVRDUDE_WRITE_FLASH) $(AVRDUDE_WRITE_EEPROM)
# Generate avr-gdb config/init file which does the following:
# define the reset signal, load the target file, connect to target, and set
34
# a breakpoint at main().
gdb-config:
@$(REMOVE) $(GDBINIT_FILE)
@echo define reset >> $(GDBINIT_FILE)
@echo SIGNAL SIGHUP >> $(GDBINIT_FILE)
@echo end >> $(GDBINIT_FILE)
@echo file $(TARGET).elf >> $(GDBINIT_FILE)
@echo target remote $(DEBUG_HOST):$(DEBUG_PORT) >> $(GDBINIT_FILE)
ifeq ($(DEBUG_BACKEND),simulavr)
@echo load >> $(GDBINIT_FILE)
endif
@echo break main >> $(GDBINIT_FILE)
debug: gdb-config $(TARGET).elf
ifeq ($(DEBUG_BACKEND), avarice)
@echo Starting AVaRICE - Press enter when "waiting to connect" message displays.
@$(WINSHELL) /c start avarice --jtag $(JTAG_DEV) --erase --program --file \
$(TARGET).elf $(DEBUG_HOST):$(DEBUG_PORT)
@$(WINSHELL) /c pause
else
@$(WINSHELL) /c start simulavr --gdbserver --device $(MCU) --clock-freq \
$(DEBUG_MFREQ) --port $(DEBUG_PORT)
endif
@$(WINSHELL) /c start avr-$(DEBUG_UI) --command=$(GDBINIT_FILE)
# Convert ELF to COFF for use in debugging / simulating in AVR Studio or VMLAB.
COFFCONVERT = $(OBJCOPY) --debugging
COFFCONVERT += --change-section-address .data-0x800000
COFFCONVERT += --change-section-address .bss-0x800000
COFFCONVERT += --change-section-address .noinit-0x800000
COFFCONVERT += --change-section-address .eeprom-0x810000
coff: $(TARGET).elf
@echo
@echo $(MSG_COFF) $(TARGET).cof
$(COFFCONVERT) -O coff-avr $< $(TARGET).cof
extcoff: $(TARGET).elf
@echo
@echo $(MSG_EXTENDED_COFF) $(TARGET).cof
$(COFFCONVERT) -O coff-ext-avr $< $(TARGET).cof
# Create final output files (.hex, .eep) from ELF output file.
%.hex: %.elf
@echo
@echo $(MSG_FLASH) $@
$(OBJCOPY) -O $(FORMAT) -R .eeprom -R .fuse -R .lock -R .signature $< $@
%.eep: %.elf
@echo
@echo $(MSG_EEPROM) $@
-$(OBJCOPY) -j .eeprom --set-section-flags=.eeprom="alloc,load" \
--change-section-lma .eeprom=0 --no-change-warnings -O $(FORMAT) $< $@ || exit 0
35
# Create extended listing file from ELF output file.
%.lss: %.elf
@echo
@echo $(MSG_EXTENDED_LISTING) $@
$(OBJDUMP) -h -S -z $< > $@
# Create a symbol table from ELF output file.
%.sym: %.elf
@echo
@echo $(MSG_SYMBOL_TABLE) $@
$(NM) -n $< > $@
# Create library from object files.
.SECONDARY : $(TARGET).a
.PRECIOUS : $(OBJ)
%.a: $(OBJ)
@echo
@echo $(MSG_CREATING_LIBRARY) $@
$(AR) $@ $(OBJ)
# Link: create ELF output file from object files.
.SECONDARY : $(TARGET).elf
.PRECIOUS : $(OBJ)
%.elf: $(OBJ)
@echo
@echo $(MSG_LINKING) $@
$(CC) $(ALL_CFLAGS) $^ --output $@ $(LDFLAGS)
# Compile: create object files from C source files.
$(OBJDIR)/%.o : %.c
@echo
@echo $(MSG_COMPILING) $<
$(CC) -c $(ALL_CFLAGS) $< -o $@
# Compile: create object files from C++ source files.
$(OBJDIR)/%.o : %.cpp
@echo
@echo $(MSG_COMPILING_CPP) $<
$(CC) -c $(ALL_CPPFLAGS) $< -o $@
# Compile: create assembler files from C source files.
%.s : %.c
$(CC) -S $(ALL_CFLAGS) $< -o $@
# Compile: create assembler files from C++ source files.
%.s : %.cpp
$(CC) -S $(ALL_CPPFLAGS) $< -o $@
# Assemble: create object files from assembler source files.
$(OBJDIR)/%.o : %.S
@echo
@echo $(MSG_ASSEMBLING) $<
$(CC) -c $(ALL_ASFLAGS) $< -o $@
36
# Create preprocessed source for use in sending a bug report.
%.i : %.c
$(CC) -E -mmcu=$(MCU) -I. $(CFLAGS) $< -o $@
# Target: clean project.
clean: begin clean_list end
clean_list :
@echo
@echo $(MSG_CLEANING)
$(REMOVE) $(TARGET).hex
$(REMOVE) $(TARGET).eep
$(REMOVE) $(TARGET).cof
$(REMOVE) $(TARGET).elf
$(REMOVE) $(TARGET).map
$(REMOVE) $(TARGET).sym
$(REMOVE) $(TARGET).lss
$(REMOVE) $(SRC:%.c=$(OBJDIR)/%.o)
$(REMOVE) $(SRC:%.c=$(OBJDIR)/%.lst)
$(REMOVE) $(SRC:.c=.s)
$(REMOVE) $(SRC:.c=.d)
$(REMOVE) $(SRC:.c=.i)
$(REMOVEDIR) .dep
# Create object files directory
$(shell mkdir $(OBJDIR) 2>/dev/null)
# Include the dependency files.
-include $(shell mkdir .dep 2>/dev/null) $(wildcard .dep/*)
# Listing of phony targets.
.PHONY : all begin finish end sizebefore sizeafter gccversion \
build elf hex eep lss sym coff extcoff \
clean clean_list program debug gdb-config
E Circuito de teste
O circuito da Figura 12 utilizado por alguns exemplos desta nota tcnica para ilustrar funcionalidades
do ATmega8. O mesmo pode ser montado em protoboard aproveitando-se o circuito de referncia da
Seo 3.1.2.
37
Figura 12: Circuito de teste com o microcontrolador, interface serial para PC e acionador por modu-
lao em largura de pulso para motor de corrente contnua com escovas
38