Assembly
• Específica para cada (família de) microcontrolador; • Mais próxima do hardware;
• Maior desempenho (tamanho de código e velocidade);
• Pouco amigável;
Linguagem C
• Genérica, pouco dependente do microcontrolador; • “Esconde” os detalhes do hardware;
• Menor desempenho (tamanho de código e velocidade);
Mundo Ideal
• Conhecer um pouco do hardware (arquitetura) do microcontrolador;
• Conhecer como os comandos em C são implementados em assembly;
Atualmente, os compiladores possuem níveis de otimização que geram programas muito eficientes;
VARIÁVEIS EM LINGUAGEM C
• As variáveis são posições de memória RAM usadas para guardar valores que serão usados pelo programa;
• Nas linguagens de programação, o nome dado a uma variável é um label especificando o endereço de memória onde a variável está alocada;
• A quantidade de memória usada depende do tipo da variável;
• Devido à pouca quantidade de memória RAM nos microcontroladores, é importante escolher os tipos das variáveis cuidando para otimizar a quantidade de memória usada;
VARIÁVEIS EM LINGUAGEM C
• Exemplo:
• Geralmente, em sistemas microcontrolados, o compilador tenta alocar as variáveis locais nos registradores internos da CPU.
int valor; .... valor = 0x23; 060 valor: DW 0 .... 100 LDI R20,0x23 101 STS 0x60,R20 valor = 0x23; LDI R20,0x23
VARIÁVEIS EM LINGUAGEM C
• Os registradores de dados e configuração dos periféricos internos são mapeados em memória. Assim, em linguagem C são tratados como variáveis “definidas” (Na verdade elas são pré-definidas nos arquivos .h de cada microcontrolador)
DDRD = 0x0F; PORTD |= (1<<PORTD0); LDI R24, 0x0F OUT 0x0A, R24 IN R24, 0x0B ORI R24, 0x01 OUT 0x0B, R24
VARIÁVEIS EM LINGUAGEM C
Tipo Memória Faixa de valores
char 1 byte -128 a +127
unsigned char 1 byte 0 a +255
short 2 bytes -32.768 a +32.767
short int 2 bytes -32.768 a +32.767
signed int 2 bytes -32.768 a +32.767
signed short 2 bytes -32.768 a +32.767
signed short int 2 bytes -32.768 a +32.767
unsigned int 2 bytes 0 a +65.535
unsigned short 2 bytes 0 a +65.535
VARIÁVEIS EM LINGUAGEM C
Tipo Memória Faixa de Valores
long 4 bytes -2.147.438.648 a +2.147.438.647
long int 4 bytes -2.147.438.648 a +2.147.438.647
signed long 4 bytes -2.147.438.648 a +2.147.438.647
signed long int 4 bytes -2.147.438.648 a +2.147.438.647
unsigned long 4 bytes 0 a +4.294.967.295
unsigned long int 4 bytes 0 a +4.294.967.295
float 4 bytes 1.2 × 10−38 a 3.4 × 10+38
VARIÁVEIS EM LINGUAGEM C
• O arquivo stdint.h possui a definição de tipos especificando a quantidade de bits da variável:
Tipo Memória Faixa de Valores Equivalente
int8_t 1 byte -128 a +127 char
uint8_t 1 byte 0 a 255 unsigned char
int16_t 2 bytes -32768 a +32767 int
uint16_t 2 bytes 0 a 65535 unsigned int
int32_t 4 bytes -2.147.438.648 a +2.147.438.647 long
uint32_t 4 bytes 0 a +4.294.967.295 unsigned long
• Assim, pode-se definir variáveis como:
VARIÁVEIS EM LINGUAGEM C
• Modificadores de Escopo:
• auto: define variáveis locais (é omitido, pois, por padrão as variáveis são definidas como locais);
• const: não permite que o valor da variável seja alterado;
• volatile: indica que a variável pode ser alterada por ações externas ao programa;
• static: em variáveis globais, faz com que a variável seja visível apenas dentro do arquivo em que ela foi definida. Em variáveis locais faz com que a variável mantenha seu valor
VARIÁVEIS EM LINGUAGEM C
• extern: indica que a variável foi declarada em outro arquivo de código e será usada neste arquivo;
• register: indica ao compilador que esta variável deve, preferencialmente ser alocada em um registrador da CPU. Isso faz que o acesso a variável seja mais rápido;
• Os modificadores de escopo são especificados antes da especificação do tipo da variável:
Exemplo:
Manipulando BITS
• Normalmente, num programa para microcontroladores, boa parte das operações são realizadas manipulando bits individuais em registradores;
• Por exemplo, para controlar um led ligado ao pino PB5 (pino 13 do arduino), temos que escrever somente no bit 5 do registrador PORTB. Os demais bits deste registrador devem permanecer inalterados.
• Em assembly existem as instruções:
• A linguagem C não prevê este tipo de operação . Para realiza-las, usamos máscaras:
PORTB |= (1<<PORTB5); // seta o bit 5 da porta PORTB PORTB &= ~ (1<<PORTB5); // reseta o bit b da porta PORTB
• Na operação PORTB |= (1<<PORTB5); supondo que o valor atual do PORTB seja 0b00010011, temos:
PORTB inicial 0 0 0 1 0 0 1 1
OU Máscara 0 0 1 0 0 0 0 0
• Na operação PORTB &= ~(1<<PORTB5); a máscara é invertida (pelo operando ~). Assim, supondo que o valor atual do PORTB seja 0b00110011, temos:
PORTB inicial 0 0 1 1 0 0 1 1
E Máscara 1 1 0 1 1 1 1 1
• Para facilitar o uso destas operações podemos definir macros no início do arquivo, por exemplo:
• Seta o bit b do registrador REG:
#define set_bit(REG,b) (REG|=(1<<b))
• Reseta o bit b do registrador REG:
#define clr_bit(REG,b) (REG&=~(1<<b))
• Retorna 0 se o bit b do registrador REG for 0 e retorna ≠ de 0 se o bit b do registrador REG for 1:
• Exemplo de uso:
set_bit(DDRB,5); // define pino PB5 como saida if(tst_bit(PORTB,PORTB5) // verifica se PB5 == 1
clr_bit(PORTB,PORTB5); // se sim, zera PB5 else