Aqui você vê as diferenças entre duas revisões dessa página.
Ambos lados da revisão anterior Revisão anterior Próxima revisão | Revisão anterior | ||
programacao-atmega328 [2018/10/17 20:57] amador |
programacao-atmega328 [2019/01/21 19:57] (atual) amador |
||
---|---|---|---|
Linha 3: | Linha 3: | ||
Nesta página são apresentados os conceitos básicos para programação de [[ATmega328|ATmega328 e ATmega328p]] utilizando programação em C e o compilador AVR-GCC. A programação é feita tipicamente em um Sistema Operacional Linux. | Nesta página são apresentados os conceitos básicos para programação de [[ATmega328|ATmega328 e ATmega328p]] utilizando programação em C e o compilador AVR-GCC. A programação é feita tipicamente em um Sistema Operacional Linux. | ||
- | Informações sobre a gravação de códigos aqui mostrados nos microcontroladores podem ser encontradas em [[Gravação ATmega328]]. | + | Informações sobre a compilação e gravação de códigos aqui mostrados nos microcontroladores podem ser encontradas em [[Gravação ATmega328]]. |
- | ---- | + | |
- | =====Instalação do Compilador===== | + | |
- | + | ||
- | Para distribuições de Linux baseadas em Debian (como o Ubuntu), a instalação do compilador é feita através da linha de comando: | + | |
- | <code>sudo apt-get install gcc-avr gdb-avr binutils-avr avr-libc</code> | + | |
- | Para distribuições de Linux baseadas em Arch, a instalação é feita a partir da linha de comando: | ||
- | <code>sudo pacman -S avr-gcc avr-gdb avr-binutils avr-libc</code> | ||
---- | ---- | ||
=====Portas Digitais===== | =====Portas Digitais===== | ||
Linha 19: | Linha 12: | ||
* Porta C, com 7 pinos; | * Porta C, com 7 pinos; | ||
* Porta D, com 8 pinos. | * Porta D, com 8 pinos. | ||
- | Contudo, não conseguimos trabalhar com pinos separadamente durante a programação, ficando restritos à configuração da porta inteira. Então precisamos fazer operações bit a bit que envolvam bytes representantes das portas (e não bits representantes dos pinos). | + | Contudo, não conseguimos trabalhar com pinos separadamente durante a programação, ficando restritos à configuração da porta inteira. Então precisamos fazer operações bit a bit que envolvam bytes representantes das portas e não bits representantes dos pinos (no que é conhecido como [[Máscara de bits]]). |
Para realizar as ações descritas abaixo, é necessário importar no código a biblioteca de entrada e saída do microcontrolador, ou seja, é necessário incluir no início do código: | Para realizar as ações descritas abaixo, é necessário importar no código a biblioteca de entrada e saída do microcontrolador, ou seja, é necessário incluir no início do código: | ||
- | <code>#include <avr/io.h></code> | + | <code c>#include <avr/io.h></code> |
====Direção do Pino==== | ====Direção do Pino==== | ||
Linha 30: | Linha 23: | ||
Um bit configurado como '0' significa que o pino correspondente será de entrada, e caso seja configurado como '1', será saída. Exemplo: caso queiramos que o pino B4 seja configurado como entrada, colocaremos '0' no bit 4 de DDRB; caso queiramos que seja saída, colocaremos '1' no bit 4 de DDRB. | Um bit configurado como '0' significa que o pino correspondente será de entrada, e caso seja configurado como '1', será saída. Exemplo: caso queiramos que o pino B4 seja configurado como entrada, colocaremos '0' no bit 4 de DDRB; caso queiramos que seja saída, colocaremos '1' no bit 4 de DDRB. | ||
+ | Desta forma, se formos configurar o pino C3 como entrada e o pino D7 como saída, usaremos os comandos | ||
+ | <code c> | ||
+ | DDRC &= ~(1<<DDC3); | ||
+ | DDRD |= (1<<DDD7); | ||
+ | </code> | ||
+ | Onde DDC3 e DDD7 são macros definidas pela biblioteca AVR e representam, respectivamente, 3 e 7. De forma semelhante, há DDB1, DDB5, DDC0 e DDD4. Os números puros poderiam ser usados no lugar das macros, mas elas são usadas para fins de legibilidade de código, pois explicitam qual pino está sendo configurado. | ||
+ | |||
+ | Informações sobre os operadores bit a bit e sobre as máscaras de bits podem ser encontradas [[https://www.embarcados.com.br/bits-em-linguagem-c/|aqui]]. | ||
+ | |||
+ | |||
+ | ====Entrada Digital==== | ||
+ | Depois que a direção de um pino foi configurada como entrada, o valor presente nele pode ser lido. Assim como na definição da direção da porta, as operações de leitura também são feitas usando bytes, então precisaremos usar a máscara de bits na posição desejada para ler apenas o valor de interesse. | ||
+ | |||
+ | Para ler o conteúdo de uma porta, usaremos os registradores PIN, sendo que há um registrador desse para cada porta: PINB, PINC e PIND. Além disso, usaremos uma variável do tipo ''unsigned char'' para receber o dado de uma porta, pois é a representação que temos de um byte "puro" na linguagem C. | ||
+ | |||
+ | Desta forma, se formos ler o conteúdo presente no pino C3, usaremos os comandos | ||
+ | <code c> | ||
+ | DDRC &= ~(1<<DDC3); | ||
+ | unsigned char valor; | ||
+ | valorLido = (PINC & (1<<PINC3)); | ||
+ | </code> | ||
+ | Onde PINC3 é uma macro de valor 3 semelhante às macros de DDR. | ||
+ | |||
+ | Uma coisa que vale notar é que, seguindo o código anterior, se houver sinal baixo na entrada C3, valorLido == 0. Contudo, se houver sinal alto na entrada C3, valorLido == 0b00001000 == 8. Isso não será problema caso valorLido seja usado como variável condicional, pois o C interpreta variável igual a 0 como Falso e variável diferente de 0 como Verdadeiro. Contudo, é preciso cuidado na hora de fazer comparações entre valores lidos de pinos ou caso deseja-se (por algum motivo obscuro) fazer operações matemáticas usando o valor. | ||
+ | |||
+ | |||
+ | ====Saída Digital==== | ||
+ | Depois que a direção de um pino foi configurada como saída, pode-se definir qual valor ele terá. Assim como na definição da direção da porta, as operações de escrita também são feitas usando bytes, então precisaremos usar a máscara de bits na posição desejada para escrever apenas no valor de interesse. | ||
+ | |||
+ | Para escrever em uma porta, usaremos os registradores PORT, sendo que há um registrador desse para cada porta: PORTB, PORTC e PORTD. Assim como na definição de direção do pino e na leitura do mesmo, há macros usadas para o número do pino a ser escrito, elas são como PB2, PC5 e PD0. | ||
+ | |||
+ | Desta forma, se quisermos escrever '1' no pino B0 e escrever '0' no pino D7, usaremos os comandos | ||
+ | <code c> | ||
+ | DDRB |= (1<<DDB0); | ||
+ | DDRD |= (1<<DDD7); | ||
+ | PORTB |= (1<<PB0); | ||
+ | PORTD &= ~(1<<PD7); | ||
+ | </code> | ||
+ | |||
+ | ---- | ||
+ | |||
+ | =====Facilitando a Vida===== | ||
+ | Muitas vezes é chato ficar fazendo as máscaras de bits na mão, então há maneiras de simplificar a programação. | ||
+ | |||
+ | ====_BV==== | ||
+ | A primeira delas é a macro de sistema ''_BV'', acrônimo de "Bit Value". Por exemplo, ''_BV(6)'' é igual a ''(1<<6)''. Desta forma, se quisermos configurar o pino D0 como saída, podemos escrever: | ||
+ | <code c> | ||
+ | DDRD |= (1<<DDD0); | ||
+ | //ou | ||
+ | DDRD |= _BV(DDD0); | ||
+ | </code> | ||
+ | E se quisermos configurar o pino B3 como entrada, podemos escrever: | ||
+ | <code c> | ||
+ | DDRB &= ~(1<<DDB3); | ||
+ | //ou | ||
+ | DDRD &= ~_BV(DDB3); | ||
+ | </code> | ||
+ | |||
+ | ====Macros extras==== | ||
+ | Além da macro ''_BV'', podemos definir nossas próprias macros. Algumas macros úteis que podem ser definidas no código são: [(siteEmbarcados>> | ||
+ | title : Bits em Linguagem C | ||
+ | publisher : Embarcados | ||
+ | url : https://www.embarcados.com.br/bits-em-linguagem-c/ | ||
+ | )] | ||
+ | |||
+ | <code c> | ||
+ | #define setBit(valor,bit) (valor |= (1<<bit)) // Define como '1' um bit em um byte | ||
+ | #define clearBit(valor,bit) (valor &= ~(1<<bit)) // Define como '0' um bit em um byte | ||
+ | #define toogleBit(valor,bit) (valor ^= (1<<bit)) // Inverte o valor de um bit | ||
+ | #define testBit(valor,bit) (valor & (1<<bit)) // Testa se um bit é '0' ou '1' | ||
+ | </code> | ||
+ | =====Referências===== | ||
+ | ~~REFNOTES~~ | ||