dados
Prof.MSc.Rodrigo Maximiano Antunes de Almeida
Universidade Federal de Itajubá
Teórica:
Local ⇒ Sala
Horário ⇒ 15:45-17:35
Laboratório:
Local ⇒ Sala K.1.9 LMSII (laguinho)
Horário ⇒ P1: 8:20-10:10, P2-10:10-12:00
*Levar a placa
Datas Importantes:
Prova 01 ⇒ 31/08
Prova 02 ⇒ 07/12
Exame ⇒ 14/12
Referência circular (rev)
A função LerTemperatura() faz um teste: se o valor for maior que
um patamar chama a função EnviaSerial() com o código 0x30.
1
#include "serial.h"
2char
LerTemperatura(
void
);
3void
AjustaCalor(
char
val);
A função LerSerial() receber um valor e repassa para a função
AjustaCalor().
1
#include "temp.h"
2char
LerSerial(
void
);
3void
EnviaSerial(
char
val);
Referência circular (rev)
#include “serial.h” char LerTemperatura(void); void AjustaCalor(char val);
temp.h
#include “temp.h” char LerSerial(void); void EnviaSerial(char val);
serial.h
#include “serial.h” char LerTemperatura(void); void AjustaCalor(char val);
Referência circular (rev)
Solução: criar uma estrutura de controle para pré compilação.
1
#ifndef TAG_CONTROLE
2#define TAG_CONTROLE
3
//todo o conteúdo do arquivo vem aqui.
4Referência circular(rev)
Solução: criar uma estrutura de controle para pré compilação.
#infdef TEMP_H #define TEMP_H #include “serial.h” char LerTemperatura(void); void AjustaCalor(char val); #endif
temp.h
#infdef SERIAL_H #define SERIAL_H #include “temp.h” char LerSerial(void); void EnviaSerial(char val); #endifserial.h
#infdef TEMP_H //tag já definida, //pula o conteúdo #endiftemp.h
Construindo nosso stdio
Criar a função printf para o LCD
Salvar dentro da biblioteca stdio
Reconhecer o nal da string
Reconhecer quebra de linha
Construindo nosso stdio
1
void
printf(
char
msg[
16
])
2{
3
char
i, j;
4
for
(i=
0
; i<
16
; i++)
5
{
6
if
(msg[i]==
0
)
//procura fim da string
7
{
8return
;
9}
10else
11{
12EnviaDados(msg[i]);
13}
14}
15}
Construindo nosso stdio
1
if
(msg[i]==
0
)
//procura fim da string
2{
3
return
;
4}
5
else if
(msg[i]=='\n')
//procura quebra de linha
6{
7
EnviaComando(
0xC0
);
//segunda linha
8}
9
else
10{
11
EnviaDados(msg[i]);
12}
Construindo nosso stdio
Construindo nosso stdio
1
#include "stdio.h"
2#include "lcd.h"
3
4
static char
temp[
16
] =
"
"
;
5static char
p=
0
;
Construindo nosso stdio
1else if
((msg[i]=='\n')){
2
if
(linha==
2
){
3
EnviaComando(
0x01
);
//primeira linha
4EnviaComando(
0x80
);
//primeira linha
5
for
(j=
0
;j<p;j++){
//envia temp p/ primeira linha
6
EnviaDados(temp[j]);
7
}
8
}
9
EnviaComando(
0xC0
);
//segunda linha
10p=
0
;
//resta dados
11
for
(j=
0
;j<
16
;j++){
//limpa temp
12
temp[j] =
' ';
13}
14linha=
2
;
15}
16else
{
17EnviaDados(msg[i]);
18temp[p] = msg[i];
19p++;
20}
Tipos de dados em C
Tipos de dados em C
Tipo
Bits
Bytes
Faixa de valores
char
8
1
-128 à 127
int
16
2
-32.768 à 32.767
oat
32
4
3,4 x 10
-38
à 3,4 x 10
38
Conversão Binário, Decimal, Hexadecimal
Os dados são sempre armazenados no formato binário
Os bits tem signicados diferentes dependendo do tipo de dado
Para números não inteiros existe perda de informação
1
float
x =
0
;
2while
(x !=
4
)
3
{
4
printf(
"i"
);
//apenas para debug
5
x +=
0.4f
;
Conversão Binário, Decimal, Hexadecimal
Conversão Binário-decimal
Dividir o número por 2
Anotar o valor do resto (0 ou 1)
Se o valor é maior que 0 voltar ao número 1
Escrever os valores obtidos através do passo 2 de trás para
frente.
Conversão Binário, Decimal, Hexadecimal
Exercicio 01) Converter os números
18
513
73
60
Conversão Binário, Decimal, Hexadecimal
Número 18:
18
2
=
9, resto 0
9
2
=
4, resto 1
4
2
=
2, resto 0
2
2
=
1, resto 0
1
2
=
0, resto 1
Conversão Binário, Decimal, Hexadecimal
A representação de números negativos é feita através do MSB
0 = positivo
1 = negativo
Conversão Binário, Decimal, Hexadecimal
Complemento de dois
Denir tamanho da palavra
Achar o representação em binário positiva com a mesma
magnitude
Inverter todos os bits
Conversão Binário, Decimal, Hexadecimal
Números fracionários (ponto utuante)
São divididos em expoente, mantissa e sinal
Sinal ocupa apenas um bit, como nos inteiros
A mantissa representa os algarismos signicativos
O expoente representa a magnitude
Conversão Binário, Decimal, Hexadecimal
Base Hexadecimal
Possui 16 "unidades"diferentes.
10 algarismos mais 6 letras
Facilita escrita de valores binários
Conversão Binário, Decimal, Hexadecimal
Dec
Bin
Hex
Dec
Bin
Hex
0
0000
0
8
1000
8
1
0001
1
9
1001
9
2
0010
2
10
1010
A
3
0011
3
11
1011
B
4
0100
4
12
1100
C
5
0101
5
13
1101
D
6
0110
6
14
1110
E
7
0111
7
15
1111
F
Conversão Binário, Decimal, Hexadecimal
Exercicio 02) Converter os números
18
10
- 10010
2
513
10
- 1000000001
2
73
10
- 1001001
2
60
10
- 111100
2
-15
10
- 1111001
2_8bits
Conversão Binário, Decimal, Hexadecimal
Exercicio 02) Converter os números
como: 18
10
= 1-0010
2
1
2
= 1
16
0010
2
= 2
16
logo :
Modicadores de tamanho e sinal
Modicadores de tamanho e sinal
Tipo
Bytes
Excursão máxima
unsigned char
1
0 à 255
signed char
1
-128 à 127
unsigned int
2
0 à 65.535
signed int
2
-32.768 à 32.767
long int
4
-2.147.483.648 à 2.147.483.647
unsigned long int
4
0 à 4.294.967.295
Modicadores de Acesso
Modicadores de Acesso
1
#define X (*(near unsigned char*)0xF83)
2void
main(
void
) interrupt
0
3
{
4
while
(X!=X);
Modicadores de Acesso
Compilando o código anterior temos em assembler:
1
// Starting pCode block
2S_Teste__main
code
3_main:
4
.line
19
// Teste.c
while (X!=X);
5Modicadores de Acesso
1
#define X (*(volatile near unsigned char*)0xF83)
2void
main(
void
) interrupt
0
3
{
4
while
(X!=X);
Modicadores de Acesso
1S_Teste__main
code
// Starting pCode block
2_main:
3
_00105_DS_:
4
.line
19
// Teste.c
while (X != X);
5
MOVLW
0x83
//primeira parte do endereço
6
MOVWF
r0x00
7
MOVLW
0x0f
//segunda parte do endereço
8
MOVWF
r0x01
9
MOVFF
r0x00, FSR0L
10
MOVFF
r0x01, FSR0H
11
MOVFF
INDF0, r0x00
//realiza primeira leitura
12
MOVLW
0x83
//primeira parte do endereço
13
MOVWF
r0x01
14
MOVLW
0x0f
//segunda parte do endereço
15
MOVWF
r0x02
16
MOVFF
r0x01, FSR0L
17
MOVFF
r0x02, FSR0H
18
MOVFF
INDF0, r0x01
//realiza segunda leitura
19
MOVF
r0x00, W
20
XORWF
r0x01, W
21
BNZ
_00105_DS_
//faz o teste para igualdade
Modicadores de Acesso
Utilização de const:
1
#define X (*(volatile const near unsigned char*)0xF83)
2//inicio do programa
3
void
main(
void
) interrupt
0
4{
5
X =
3
;
6
}
A compilação resulta em erro:
Modicadores de Posicionamento
Modicadores de Posicionamento
Existem dois modicadores de posicionamento
near
far
Não são padronizadas pela ISO C(99)
Indicam ao compilador a região em que a variável deve ser
colocada
near - região de acesso mais rápido
Modicador de persistência
Modicador de persistência
A persistência de uma variável pode ser assegurada com o
modicador static
Padronizada pela ISO C(99)
Garante que não haverá perda de informação na variável
Uma região de memória é reservada apenas para a variável em
questão
1
//cria um contador persistente que é
2//incrementado a cada chamada de função
3int
ContadorPersistente(
int
reseta){
4char
variavel_persistente;
Modicador de persistência
1
//cria um contador persistente que é
2//incrementado a cada chamada de função
3int
ContadorPersistente(
int
reseta)
4{
5
static char
variavel_persistente;
6if
(reseta)
7{
8variavel_persistente =
0
;
9}
10else
11{
12return
(variavel_persistente++);
13}
14return
-
1
;
15}
Operações Aritiméticas
Operações Aritiméticas
1
void
main (
void
)
2{
3
char
var08;
4int
var16;
5long int
var32;
6
float
pont16;
7
double
pont32;
8
var8 =
var8 + var16;
// 1
9var8 =
var8 + var8;
// 2
10var16 = var8 * var8;
// 3
11var32 = var32 / var16;
// 4
12var32 = pont32 * var32;
// 5
13pont16 = var8 / var16;
// 6
14pont16 = pont32 * var32;
// 7
15pont16 =
40
/
80
;
// 8
16}
Função main()
Função main()
0x58
Testa A
0x57
30
0x56
A recebe
0x55
Limpa A
0x59
...
0x8D
Porta B
0x8C
Salva em
0x8B
50
0x8A
A recebe
0x8E
...
0x03
0x55
0x02
Pulo
0x01
0x8A
0x04
...
0x00
Pulo
Endereço Instrução
Função main()
Como indicar o ponto de início de um programa depende do
compilador.
Alocar main() em algum lugar disponível
No vetor de reset colocar um pulo para a função main
Para o SDCC isto é feito através do atributo interrupt 0 logo
após o nome da função.
1
void
main (
void
) interrupt
0
2{
Função main()
Atenção!
Para sistemas embarcados a função main é a primeira a ser
executada, portanto não pode receber parâmetro nenhum. Como
ela é a ultima a ser executada, também não existe a possibilidade
de retornar algum valor. Deve ser declarada como:
1
void
main (
void
) interrupt
0
2{
3
/...
4}
Função main()
1
void
main (
void
) interrupt
0
2{
3for
(;;)
4{
5//aqui entra o
6//código principal
7}
8}
1
void
main (
void
) interrupt
0
2{
3while
(
1
)
4{
5//aqui entra o
6//código principal
7}
8}
Rotinas de Tempo
Rotinas de Tempo
É muito comum necessitar que o microcontrolador que um tempo
sem fazer nada. Uma maneira de atingir esse objetivo é utilizar um
laço for.
unsigned char
i;
for
(i=
0
; i <
10
; i++);
Atenção!
Rotinas de Tempo
1
//código em assembler equivalente à for(i=0; i<10; i++);
2
MOVF
r0x00, W
//inicializa W com 0
(1 ciclo)
3
SUBLW
0x0a
//coloca o valor 10 (0x0a) no registro W (1 ciclo)
4
MOVWF
r0x00
//muda o valor de W para F
(1 ciclo)
5
_00107_DS_:
6
DECFSZ
r0x00, F
//decrementa F, se F>0 executa o próximo (1 ciclo)
7BRA
_00107_DS_
//"pula" para o lugar _00107_DS_
(2 ciclos)
Rotinas de Tempo
São gastos 3 passos para inicialização, cada um de 1 ciclo.
Cada iteração gasta 2 passos, um de 1 ciclo e um de 2 ciclos
Para um PIC a 8 MHz cada ciclo gasta 0,5 us
Se desejamos um tempo de x segundos são necessárias
2 ∗ 10
9
∗
x instruções.
Rotinas de Tempo
1
unsigned char
i, j, l;
2