ELL7030 - Microprocessadores
Prof. Raimes Moraes
Compilador C para o 8051
1) Diretivas de Controle: controlam a atuação do compilador. Podem ser especificadas no comando de compilaçao (acima) ou no código do programa fonte através do comando
#pragma.
Ex: registerbank (n) => n assume valores de 0 a 3. Permite ao usuário indicar ao compilador o código a ser gerado para instruções que envolvem registradores. Sem esta declaração, o banco de registradores utilizado é o banco 0.
2.1 - Diretivas de Modelos de memória:
small: modelo default do compilador. Neste modelo, todas as variáveis residem na
memória interna do 8051. Vantagem: velocidade. Limitação: tamanho da memória interna.
compact: todas as variáveis residem em uma página (256 bytes) de memória externa de
dados. Esta limitação deve-se a utilização de endereçamento indireto através dos registradores R0 e R1 (@R0, @R1). Vantagem: maior espaço para variáveis. Desvantagem: menor velocidade.
large: todas as variáveis se encontram na memória externa de dados (64kB). Vantagem:
maior espaço para variáveis. Desvantagem: menor velocidade. 2) Tipos de Variáveis
Os seguintes tipos de dados com definição comum ao C existem:
- signed char (- 128 a 127) - unsigned char (0 a 255) - signed short (-32768 a 32767) - unsigned short (0 a 65535) - signed int (-32768 a 32767) - unsigned int (0 a 65535) - signed long (-2147483648 a 2147483647) - unsigned long (0 a 4294967295)
- float (±1.175494E-38 a ±3.402823+38)
Outras definições de tipos de dados para o C do 8051:
bit: (0 a 1) utilizado na declaração de variáveis e funções. Não pode ser declarado como
sbit: (0 a 1) utilizado para endereçar bits de variáveis criadas em bdata ou bits em SFR.
Ex: sbit defbit0 = dado ^ 0; sbit EA = 0xAF /* bit 7 do byte A8 (IE) */
sfr: (0 a 255) utilizado para associar nomes simbólicos à posições de memória dos
registradores especiais. Ex: sfr P0 = 0x80;
Variantes para sbit: sfr IE = 0xA8; sbit EA = IE ^ 7 ou sbit EA = 0xA8 ^ 7;
sfr16: (0 a 65535) utilizado para associar nomes simbólicos à posições de memória dos
registradores especiais onde o LSB antecede o MSB. Mais empregado em novos integrantes da família de microcontroladores. Ex: sfr16 mem = 0x82 /* DPL = 0x82; DPH = 0x83 */
3) Especificação de local de armazenamento para as variáveis criadas:
data: 128 posições de memória de dados interna (0 a 7Fh)
idata: memória de dados interna acessível por endereçamento indireto (80 a FFh). bdata: memória de dados interna acessível por endereçamento de bit ou byte (20 a 2Fh). code: memória de programa acessível por MOVC @A+DPTR.
xdata: memória de dados externa acessível por MOVX @DPTR. pdata: memória de dados externa acessível por MOVX @Rn.
Exemplo: code char menu[] = “Digite sua opção”;
Obs: Em caso de omissão da declaração do tipo de variável, o default dependerá da diretiva de modelo da memória.
4) Ponteiros
4.1 - Untyped Pointer: utilizados para acessar variáveis em qualquer região de memória. Ex: char *ponteiro;
4.2 - Typed Pointer: inclui a especificação da região de memória na declaração do ponteiro. Ex: char data *ponteiro;
5) Declaração de Funções
[ tipo_de_dado_a_retornar ] nome_da_função ( [parâmetros] ) [ modelo_de_memória ] [ interrupt n ] [ reentrant ] [ using n ]
Obs: elementos entre [] são opcionais.
[ tipo_de_dado_a_retornar ] => tipo de dado que a função retorna. Se não declarado, o
Os valores são retornados nos seguintes registradores:
Tipo de dado a retornar Registrador
void ---
bit Carry Flag
char, unsigned char R7
int, unsigned int R6 & R7 (MSB - LSB) long, unsigned long R4 - R7 (MSB - LSB)
float R4 - R7 (MSB - LSB)
[ parâmetros ] => parâmetros não são passados através da pilha, mas através de posições
fixas de memória. Isto se deve à limitação da quantidade de memória disponível para a pilha. Para a passagem de parâmetros via registradores, otimizando velocidade, a diretiva de controle REGPARMS deve ser declarada. Podem ser passados até 3 parâmetros neste modo. A diretiva NOREGPARMS tem função oposta à REGPARMS.
[ modelo_de_memória ] => o modelo default para a função é o determinado pela diretiva
de controle. Contudo, é possível especificar o modelo para uma função em particular entre as apresentadas no itém 2.1.
interrupt n => n assume valores de 0 a 3. Especifica a interrupção a ser respondida pela
função. O compilador automaticamente gera o vetor de interrupção na posição de memória correspondente que aponta para a função. Funções que atendem interrupções não podem possuir parâmetros ou retornar valores. Não devem ser chamadas fora de interrupções pois o compilador inclui a instrução RETI.
Número da Interrupção Descrição Endereço
0 Externa 0 03 h 1 Timer/Counter 0 0B h 2 Externa 1 13 h 3 Timer/Counter 1 1b h 4 Porta Serial 23 h Ex:
unsigned int contaseg; unsigned char segundo;
void timer0 (void) interrupt 1 using 2 { if (++contaseg == 4000) { segundo++; ontaseg = 0; } }
reentrant => função que pode ser compartilhada por diferentes processos
simultaneamente. Para cada chamada da função, uma nova pilha é criada na memória.
using n => n assume valores de 0 a 3. Especifica o banco de registradores a ser utilizado
pela função. Isto permite que a função utilize um banco diferente do programa principal, evitando que o conteúdo dos registradores tenha de ser salvo em pilha. Este comando automaticamente salva o atual banco em uso e o recupera ao final da execução da função. Não deve ser utilizado em funções que retornam valor em seus registradores.
Apêndice
A) Rotinas comuns ao ANSI C e ao C51
abs acos asin atan atan2
atof atoi atol calloc ceil
cos cosh exp fabs floor
free getchar gets isalnum isalpha
iscntrl isdigit isgraf islower isprint
ispunct isspace isupper isxdigit labs
log log10 longjmp malloc memchr
memcmp memcpy memmove memset modf
pow printf putchar puts rand
realloc scanf setjmp sin sinh
sprintf sqrt srand sscanf strcat
strchr strcmp strcpy strcspn strlen
strncat strncmp strncpy strpbrk strrchr
strspn tan tanh tolower toupper
va_arg va_end va_start
B) Rotinas pertecentes ao C51
cabs _crol_ _cror_ fprestore fpsave
_getkey init_mempool _irol_ _iror_ _lrol_
_lror_ memccpy _nop_ strpos strrpbrk
_toupper ungetchar
C) Representação de números de ponto flutuante (NPF)
Seja a seguinte representação de um número real em formato binário:
s 1. m m m m m m m m m m m m m m m m m m m m m m m E E E E E E E E onde: s indica se o número é positivo ou negativo,
m corresponde a elementos em representação binária da mantissa,
E corresponde a representação binária de valor que deve ser subtraídos de 127
para a determinação do expoente do número representado. Ex: Encontrar o valor decimal do número dado abaixo:
s 1. m m m m m m m m m m m m m m m m m m m m m m m 1 1. 1 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
E E E E E E E E 1 0 0 0 0 0 1 0
Expoente : 1 x 27 + 0 x 25 + + 0 x 24 + ....+ 1 x 21 + 0 x 20 - 127 = 130 -127 = 3 Ajuste da mantissa em função do expoente encontrado:
Obs: em formato binário, o expoente encontrado corresponde a um deslocamento de 3 bits para a esquerda
s 1 m m m . m m m m m m m m m m m m m m m m m m m m 0 1 1 0 0. 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 Mantissa: -(1 x 23 + 1 x 22 + 0 x 21 + 0 x 20 + 1 x 20 + 1 x 2-1 + 0 x 2-2 +...+ 0 x 2-23) = 12.5
O padrão IEEE-754 especifica que NPF’s são compostos por 4 bytes, divididos em mantissa e expoente. A mantissa corresponde a 23 bits de valor e um bit de sinal que indica se o número é positivo ou negativo (3 bytes). A representação de ponto flutuante estabelece que o número armazenado nos restantes 8 bits (0 a 255) deve ser subtraído de 127 para que o valor do expoente do NPF seja recuperado.
A informação essencial a ser armazenada resume-se em sinal, expoente e mantissa, ordenada nos seguintes passos para sua representação.
1) Reordenação da informação
s E E E E E E E (byte 0) E m m m m m m m (byte 1 - lsb)
m m m m m m m m (byte 2) m m m m m m m m (byte 3 - msb) 2) Armazenagem na memória m m m m m m m m (byte 3 - msb) m m m m m m m m (byte 2) E m m m m m m m (byte 1 - lsb) s E E E E E E E (byte 0)