ATmega328

MICROCONTROLADOR – CURSO TÉCNICO EM MECATRÔNICA

Microcontrolador Atmel ATmega328

O microcontrolador ATmega328 da Atmel é utilizado nos Arduinos mais recentes. É um microcontrolador de 8 bits, com arquitetura Harvard modificada. Neste post e nos próximos veremos algumas de suas características.

Um Pouco Sobre a Família AVR

O ATmega328 pertence à família AVR da Atmel. Todos os modelos desta família compartilham uma arquitetura e conjunto de instruções básicas, particularmente os grupos tinyAVR (microcontroladores ATtiny), megAVR (os ATmega) e XMEGA (os Atxmega).Os primeiros modelos de Arduino usavam o ATmega8 (com 8K de memória Flash), que posteriormente foi substituído pelo ATMega168 (com 16K de Flash e maiores recursos de entrada e saída) e finalmente pelo ATMega328 (com 32K de Flash). A versão DIP destes três modelos compartilham a mesma pinagem (porém o ATMega168 e ATMega328 permitem alguns usos diferentes dos pinos). O Arduino Mega 2560 usa o ATMega2560 com 256K de Flash e uma capacidade muito maior de entrada e saída.

O Diagrama de Blocos

A figura abaixo, extraída do datasheet, mostra os principais blocos do microcontrolador

Reparar as ligações separadas entre a CPU e as memórias Flash e SRam. O uso de vias de dados separadas para programa e dados é uma característica da arquitetura Harvard. Na família AVR as duas vias tem largura de 8 bits e a memória Flash pode ser usada para armazenar dados constantes (daí ser uma arquitetura Harvard modificada).

Entretanto, somente instruções armazenadas na Flash podem ser executadas (não é possível executar código que esteja na SRam).

Como outros microcontroladores AVR, o ATMega328 possui ainda uma memória do tipo EEProm, porém esta memória está ligada na via de conexão aos periféricos e portanto não é acessada pelas instruções normais de acesso a memória.

Além da EEProm podem ser vistos as três portas de E/S digital (PORTs B, C e D), os três timers (TCx, dois de 8 bits e um de 16 bits), o conversor A/D, o comparador analógico e as interfaces seriais SPI, TWI (compatível com I2C) e USART.

CPU

O coração (ou o cérebro?) de um microcontrolador é a sua CPU. No caso do ATmega328, temos uma CPU AVR do tipo “enhanced core“. Vejamos algumas de suas características.

A Arquitetura Interna da CPU

Novamente notamos a separação das vias de acesso à Flash e SRam, típicas das arquiteturas Harvard e derivadas.

No lado da Flash temos o Program Counter (que aponta para a próxima instrução). O AVR possui um pipelinede um nível, no qual enquanto uma instrução é executada a seguinte é carregada. Isto possibilita executar as instruções mais simples em um único ciclo de clock. Embora a Flash seja endereçada byte a byte, as instruções são compostas por uma ou duas palavras de 16 bits (ocupando portando duas ou quatro posições da Flash).

A família AVR possui uma generosa coleção de 32 registradores de uso geral, todos de 8 bits. Os seis últimos registradores podem ser usados aos pares como três registradores de 16 bits (X, Y e Z) para endereçamento indireto da memória.

A Unidade Lógica Aritmética (ALU) trabalha com 8 bits; obtêm os operandos dos registradores e coloca o resultado no primeiro operando (exceto na multiplicação). Todas as operações lógicas e aritméticas são executadas em um ciclo, exceto pela multiplicação que demora dois ciclos.

Memória Interna de Dados

A memória interna de dados é composta pelos registradores de uso geral, os registradores de entrada e saída (que controlam os periféricos internos) e a memória SRam propriamente dita.

No Atmega328 os registradores podem ser acessados nas primeiras 32 posições de memória e os registradores de E/S nas 64 posições seguintes, com a SRam começando no endereço 0x60.

Reparar que na figura não temos a pilha nem o seu ponteiro (SP). No AVR a pilha reside na memória SRam e o seu ponteiro são dois registradores de E/S.

Como todo microcontrolador que se preze, o ATmega328 possui uma boa coleção de periféricos internos. A plataforma Arduino se aproveita disto e disponibiliza quase todos os pinos do ATmega para os shields, como mostram as figuras abaixo

Entradas e Saídas Digitais

Dos 28 pinos do ATmega328, 23 podem ser usados como entrada ou saída digital (inclusive os que estão marcados como entradas analógicas na placa do Arduino). Todos os pinos possuem funções alternativas, por exemplo no Arduino utiliza funções como Reset, XTAL1 e XTAL2, limitando o uso destes pinos para E/S digital.

Os pinos de E/S digital estão organizados em três portas (PB, PC e PD), mas cada pino pode ser configurado independentemente como entrada e saída. Todos os pinos possuem um resistor de pull-up (também controlado independentemente) e diodos de proteção. Quando operando como saída, os pinos podem tanto gerar como receber uma corrente suficiente para acender um LED (até 40mA por pino).

Os 23 pinos de E/S digital podem também ser gerar uma interrupção quando ocorre mudança de sinal. É possível controlar a geração de interrupção pino a pino e ela independe do pino ter sido configurado como entrada ou saída.

Conversor Analógico Digital

O conversor analógico digital (ADC) possui 10 bits de resolução e possui 8 opções de entrada (6 no encapsulamento DIP normalmente usado no Arduino). Existem três opções de referência: a tensão de alimentação (fornecida em um pino separado, AVcc), uma referência interna de 1,1V ou um tensão externa (fornecida no pino ARef).

Comparador Analógico

Para aplicações que precisam testar um sinal analógico mas não precisam de toda a sofisticação da conversão analógico digital, o ATmega328 possui um módulo comparador analógico que pode gerar uma interrupção ou iniciar/parar um timer quando a voltagem na sua entrada positiva fica maior que a voltagem na sua entrada negativa.

Timers

O ATmega328 possui três timers: o Timer0, de 8 bits, o Timer1, de 16 bits, e o Timer2 de 8 bits. Os três timers podem ser usados para geração de sinais PWM, Timer1 e Timer2 possuem duas unidades de comparação e saída independentes, o Timer3 apenas uma.

Todo código a ser executado pelo ATmega328 precisa residir na memória Flash. Embora o usuário casual do Arduino não perceba, esta memória possui diversas excentricidades.

As Memórias Flash

De uma forma geral, as memórias do tipo Flash se caracterizam por não necessitarem de alimentação para manter seu conteúdo (são não voláteis) e permitirem a sua alteração ocasional.

A leitura da memória Flash não costuma envolver cuidados especiais (porém ela é mais lenta que a memória Ram). A operação de escrita é um pouco mais complexa e permite apenas mudar bits do estado '1' para o estado '0'. Para retornar os bits em '0' para '1' é necessária uma operação de apagamento, que é lenta e tipicamente afeta muitas posições de memória.

O número de escritas/apagamentos é limitado; a Atmel garante um mínimo de 10000 operações no ATmega328.

Usando Dados na Flash do ATmega328

Como dito no início, o ATMega328 só é capaz de executar instruções que estejam na Flash (consequência da sua arquitetura Harvard). Nada impede, é claro, de colocar bytes arbitrários na Flash. Entretanto, usar estes dados requer um procedimento especial. Afinal, na arquitetura Harvard, as vias de endereços e dados são separadas para Ram e Flash. No primeiros microcontroladores PIC, por exemplo, era impossível acessar diretamente o conteúdo da Flash; constante tinham que ser geradas executando código.

Felizmente o ATmega328 (e outros microcontroladores da família AVR) possuem a instrução LPM (Load Program Memory). Esta instrução copia o byte da Flash apontado pelo registrador Z para um registrador de uso geral (de onde pode ser escrito na Ram se necessário) e, opcionalmente, incrementa Z para apontar para a posição seguinte.

Gravando a Flash

Como colocar um programa inicialmente na Flash do ATmega328? Existem três maneiras básicas:

⦁ Programador paralelo externo: esta opção requer colocar +12V no pino de reset e fazer um "sapateado" complexo em vários outros pinos. É, portanto, mais adequado para a programação fora do circuito.

⦁ Programador serial (SPI) externo: esta opção não requer tensões especiais e utiliza apenas três pinos (além do reset), sendo viável de ser usada sem retirar o ATmega328 do circuito.

⦁ Programação por software: através de instruções especiais é possível o firmware regravar a Flash.

Em todos os casos muitos cuidados especiais precisam ser tomados.

Arduino: O Bootloader

O arduino necessita ter um software chamado bootloader gravado no microcontrolador e o código executável (programa) gravado na flash.. Vamos agora juntar estas duas informações e ver em mais detalhes o que é e como funciona o Bootloader.

Uma vez que todo software a ser executado no AVR precisa estar na Flash, o programa feito na IDE do Arduino (sketch) precisa ser gravado lá. Para dispensar o uso de um gravador externo, a gravação da Flash é feita por um software que reside nela própria, o Bootloader. O Bootloader é o primeiro software executado pelo microcontrolador após um Reset (Boot) e carrega na Flash um software que recebe pela serial (loader).

O ATmega328 possui alguns recursos que facilitam (ou complicam?) isto:

⦁ A memória Flash pode ser dividida em duas seções, um bootloader (no final da memória, com 512, 1024, 2048 ou 4096 bytes) e uma aplicação (com o restante). Na seção do bootloader pode ser usada a instrução SPM, capaz de reprogramar toda a Flash.

⦁ Independente disto, existe uma outra divisão em duas seções de tamanho fixo, a RWW (Read While Write, os primeiros 28K) e a NRWW (No Read While Write, os últimos 4K). Enquanto está sendo feito um apagamento ou escrita na região RWW, código pode estar executando na região NRWW. No caso contrário, região NRWW sendo atualizada, o processador fica parado durante a operação.

⦁ Para fins de apagamento e gravação a Flash é dividida em páginas de 128 bytes. As operações afetam sempre uma página inteira.

Obs.: Os outros microcontroladores usados no Arduino tem recursos semelhantes, porém os números acima podem ser diferentes.

Em termos práticos, um software na seção bootloader pode executar sem parada enquanto a seção de aplicação é atualizada. A seção de bootloader pode se auto-atualizar, porém o processador ficará parado enquanto a operação de completa (e você não vai querer atualizar a página onde está sendo executada a instrução SPM).

No que diz respeito ao protocolo para receber o programa pela serial, o Bootloader utiliza um subconjunto do protocolo usado por um programador externo, o STK-500. Isto permite usar softwares padrão de programação no PC, a IDE do Arduino usa o Avrdude.

Ao longo dos anos o bootloader do Arduino passou por alterações, a versão atual é o chamado Optiboot (bootloader "otimizado"). A otimização consistiu em reduzir o tamanho para caber em 512 bytes, aumentar a velocidade na serial para 19200 e receber os dados de uma página enquanto a apaga.

Existe ainda um último ponto importante no bootloader: o seu disparo e o disparo da aplicação. Nas primeiras versões, o bootloader começava a sua execução quando era feito um reset e esperava por um certo tempo uma comunicação antes de iniciar a aplicação. Isto trazia dois inconvenientes: era preciso apertar o botão de reset antes de enviar um sketch e aguardar alguns segundos ao final da carga para ele começar a ser executado.

A primeira limitação foi contornada por hardware: ao detectar uma conexão na serial o microcontrolador é ressetado no Duemilinove e no Uno. Para o segundo inconveniente, o bootloader passou a distinguir a iniciação pelo sinal de reset da re-iniciação ao final da carga de um sketch. No segundo caso o bottoloader passa diretamente para a aplicação, não tentando estabelecer comunicação.

Com estas alterações podem ocorrer problemas quando a aplicação do Arduino utiliza comunicação serial. De um lado pode ocorrer uma re-iniciação devido a uma conexão (retirando o controle da aplicação e passando ao bootloader) e por outro o bootloader pode ficar tentando tratar uma comunicação destinada à aplicação e nunca passar o controle para ela.

Atmega328 (Download em pdf)