A biblioteca avr-libc pode ser consultada neste link (pdf) (mas não é a versão mais atual) e no site da avr-libc onde existe também o manual em html (em particular veja os links Library Reference e User Manual). Exemplos completos apresentados em aula podem ser vistos neste diretório.
volatile int counter;
Exemplo: #include <avr/io.h> . . . DDRB= 0xff; // programa todos os pinos da porta B para saida PORTB |= curled; // liga curled na PORTA B (*) byte= PORTD // lê a PORTA D; equivale a: in rx, PORTDMacros adicionais para manipular e testar bits dos registradores de E/S, etc, estão disponiveis via comando #include<avr/sfr_defs.h> (avr-libc manual 6.17 p. 133-135); abaixo uma lista de macros extraída do manual:
Bit manipulation:
#define _BV(bit) (1 << (bit)) //0=< bit <7
Obs: o compilador gera uma máscara com apenas um bit ligado, correspondente ao numero do bit bit
IO register bit manipulation:
#define bit_is_set(sfr, bit) (_SFR_BYTE(sfr) & _BV(bit))
#define bit_is_clear(sfr, bit) (!(_SFR_BYTE(sfr) & _BV(bit)))
#define loop_until_bit_is_set(sfr, bit) do { } while (bit_is_clear(sfr, bit))
#define loop_until_bit_is_clear(sfr, bit) do { } while (bit_is_set(sfr, bit))
Um exemplo de uso:
#include <avr/io.h>
#include<avr/sfr_defs.h>
...
PORTB |= _BV(PB7); // coloca em 1 o bit 7 da PORTA B (máscara = 128 = 0x80)
PORTB &= ~_BV(PB4); // coloca em 0 o bit 4 da PORTA B (máscara = 11101111)
if(bit_is_set(PORTB,1)) // testa o bit 1 da PORTA B,
temp=1; // deve entrar aqui,
else
temp=0; // mas não aqui
Uma macro interessante para trocar os valores de duas variáveis usando o operador
ou exclusivo:
#define swap(a,b) ({a ^= b; b ^= a; a ^= b; })
Exemplo: #include <avr/io.h> #include <avr/pgmspace.h> char mystring[] PROGMEM= "ABCDEFGHI"; //esta cadeia vai ser gerada na área de programa char byte, char buffer[32]; // buffer na RAM para onde vamos copiar a cadeia ... strcpy_P(buffer, mystring); //copia a cadeia C (terminada por 0) para a RAM, ou então, byte= pgm_read_byte(&mystring[i]); //se quisermos obter apenas o i-ésimo byte de mystring
Exemplo:
#include <avr/io.h>
#include <avr/interrupt.h>
ISR(TIMER0_OVF_vect) // rotina de interrupção de overflow do Timer0
{ // veja um exemplo completo em ctimer0.c
....
....
} // retorna ao programa interrompido via reti
ISR(INT0_vect) //rotina de interrupção externa INT0
//veja um exemplo completo aqui
{
...
} // retorna ao programa interrompido via reti
Exemplo:
#include <avr/interrupt.h>
#include <avr/sleep.h>
...
cli();
if (some_condition) {
set_sleep_mode(SLEEP_MODE_IDLE); // configura o modo sleep no reg SMCR
sleep_enable(); //liga o bit SE no reg SMCR(habilita sleep)
sei(); // gera a instrução sei
sleep_cpu(); // gera a instrução sleep
sleep_disable(); // desliga o bit SE no registrador SMCR
}
#include <avr/eeprom.h> static __ATTR_PURE__inline__ uint8_t eeprom_read_byte (const uint8_t *__p) static __ATTR_PURE__inline__ uint16_t eeprom_read_word (const uint16_t *__p) static __ATTR_PURE__inline__ uint32_t eeprom_read_dword (const uint32_t *__p) static __inline__ void eeprom_read_block (void *__dst, const void *__src, size_t __n) static __inline__ void eeprom_write_byte (uint8_t *__p, uint8_t __value) static __inline__ void eeprom_write_word (uint16_t *__p, uint16_t __value) static __inline__ void eeprom_write_dword (uint32_t *__p, uint32_t __value) static __inline__ void eeprom_write_block (const void *__src, void *__dst, size_t __n)
Exemplos: int n; // inteiro com sinal de 16 bits uint_8 nsmall; // inteiro sem sinal de 8 bits, equivale a unsigned char unsigned int n; // inteiro sem sinal de 16 bits uint32_t p; // inteiro sem sinal de 32bits
Exemplo: #include <util/delay.h> _delay_loop_2(n); //até 262 ms numa CPU de 1 MHZ: parâmetro n de 16 bits decrementado até 0 _delay_loop_1(n); //até 768 us numa CPU de 1 MHZ: parâmetro n de 8 bits decrementado até 0
void reset(void) __attribute__((naked,section(".vectors")));
void reset(void){
asm("clr r1");
SP=RAMEND;
SREG=0;
asm("rjmp __ctors_end");
}
void rcall_main(void) __attribute__((naked,section(".init9")));
void rcall_main(void){
asm("rcall main");
asm ("rjmp .-2");
}
Compile e inspecione o código inv2.lss deste exemplo: inv2.c).
Observe que o efeito da diretiva void reset(void) __attribute__((naked,section(".vectors")));
é definir reset() como uma macro cujo código é inserido na seção .vectors que é
a 1ª a ser executada.
& bitwise AND
| bitwise OR
^ bitwise Exclusive OR
<< shift left
>> shift right
~ complemento de 1
Exemplos:
int n;
n = n << 2; // desloca n 2 bits para a esquerda (i. é multiplica n por 4)
n = n & 0xfe; // desliga o bit - significativo de n
n = n & 1; // obtém o bit - significativo de n
n = n | 1; // liga o bit menos significativo de n
Operador módulo (obtém o resto da divisão de dois inteiros:
m = n % 3;
(**) Infelizmente o arquivo .lss não dá os mesmos nomes às diversas sub-seções de inicialização que o manual da avr_libc (elas estão dentro da seção .txt e seu código precede ao da chamada da função main()):
(**) no rótulo __bad_interrupt dos vetores de interrupção não preenchidos existe uma instrução rjmp 0 (ou seja para a entrada do reset)