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 aquiUma 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)