Capítulo 5 Periféricos - UNICAMPattux/cap5_perif_completo.pdf · Capítulo 5 – Periféricos ......

62
Capítulo 5 Periféricos Prof. Romis Attux EA075 2015 Obs: Os slides são parcialmente baseados nos dos autores do livro texto

Transcript of Capítulo 5 Periféricos - UNICAMPattux/cap5_perif_completo.pdf · Capítulo 5 – Periféricos ......

Capítulo 5 – Periféricos

Prof. Romis Attux

EA075 – 2015

Obs: Os slides são parcialmente baseados nos dos autores do livro texto

Periféricos

Periféricos são dispositivos de hardware que, como o nome indicam, operam na periferia da CPU mesmo quando ocupam o mesmo chip.

Neste capítulo, discutiremos aspectos e exemplos de periféricos.

Timers

Timers são dispositivos que medem intervalos de tempo.

Eles podem gerar eventos em tempos específicos (imagine o

controle de um semáforo, por exemplo) ou podem marcar o

espaçamento temporal entre dois eventos externos (por

exemplo, entre a passagem de um carro por dois sensores).

Um timer mede o tempo por meio da contagem de pulsos de

um sinal de clock de duração definida. Por exemplo, se é

utilizado um clock de 1 microssegundo, a contagem de 2000

pulsos equivale a um intervalo de 2 milissegundos.

Contadores

Contadores, de certa forma, generalizam a noção de timer, pois permitem que sejam contados eventos a partir não só de um sinal de clock fixo, mas de um sinal de entrada qualquer.

Um contador pode ser usado para medir o número de pessoas que passam por um sensor, por exemplo.

Timers podem ser combinados com contadores para medir taxas (e.g. a taxa de giro da roda de um carro).

Timers

Basicamente, configuram-se as entradas de um timer e se

monitoram suas saídas.

Discutiremos a seguir alguns exemplos usuais.

O primeiro exemplo, mostrado na figura a seguir, possui um

contador interno de 16 bits (0 a 65535), que é incrementado a cada

pulso e cujo estado é indicado por ‘cnt’. Para que se tenha uma

medida de tempo, é preciso conhecer o valor do período de clock.

Se tivermos um clock de 100 MHz, teremos um período de 10 ns. O

timer, então teria um alcance (range) de 0 a 655,35 microssegundos

e uma resolução de 10 ns (menor intervalo de tempo mensurável).

Timer - Exemplo

16-bit up counter Clk

Cnt

Basic timer

Top

Reset

16

Timer - Exemplo

O timer contém ainda uma saída ‘top’ que indica

quando o valor máximo de contagem foi atingido,

o que representa uma espécie de overflow, já

que o estado retorna a zero.

Quando se usa o timer em conjunto com um

processador de propósito geral, pode-se ligar o

pino ‘top’ a um pino de interrupção, acionando

uma rotina de serviço que registra o número de

overflow, aumentando o range de contagem.

Muitos microcontroladores que contém timers

possuem interrupções próprias para eles,

distintas de interrupções externas.

Timer – Exemplo 2

O segundo timer que discutiremos também pode operar como contador. Isso se dá graças a um multiplexador que possui um bit de controle ‘mode’, o qual deixa passar um clock (modo de timer) ou um sinal de entrada genérico (modo de contador).

A figura a seguir ilustra esse timer.

Timer – Exemplo 2

16-bit up counter Clk

16

Cnt_in

2x1 mux

Mode

Timer/counter

Top

Reset

Cnt

Timer – Exemplo 3

Um terceiro tipo de timer permite que se defina um range de contagem específico (menor que o máximo) por meio de uma palavra ‘terminal_count’.

Por exemplo, se desejarmos contar apenas 300 ciclos, usamos esse número num comparador. Quando a contagem é atingida, gera-se um sinal ‘top’ e se faz o reset do contador.

A figura ilustra o esquema.

Timer – Exemplo 3

16-bit up

counter Clk

16

Terminal count

= Top

Reset

Timer with a terminal

count

Cnt

Timer – Exemplo 4

Seria possível utilizar também um contador reverso carregado com o valor terminal e que contasse até zero, quando seria então carregado com o valor terminal de novo. Nesse caso, a lógica de geração do sinal ‘top’ poderia ser feita simplesmente com uma porta NOR.

Timer – Exemplo 5

É possível usar um contador para operar com 16 e 32 bits lançando mão de dois contadores de 16 bits com o sinal de clock do segundo sendo o sinal ‘top’ do primeiro.

Essa estrutura é chamada de estrutura de contadores em cascata.

A figura a seguir ilustra a estrutura.

Timer – Exemplo 5

16-bit up

counter Clk

16-bit up

counter

16

Cnt2

Top1

16/32-bit timer

Cnt1

16

Top2

Timer – Exemplo 6

Também é possível construir um timer com um prescaler, que pode realizar uma divisão do sinal de clock. Por exemplo, pode-se ter um sinal de clock de 10 ns de período e, com o prescaler, obter, 80 ns de período, aumentando o range de contagem e tornando a resolução mais grosseira.

A figura a seguir ilustra isso.

Timer – Exemplo 6

Time with prescaler

16-bit up

counter Clk Prescaler

Mode

Exemplo – Reaction Timer

Deseja-se projetar um timer que conte o tempo decorrido entre o acendimento de um LED e o momento em que um usuário aperta um botão.

A idéia geral é dada na seguinte figura.

indicator

light

reaction

button

time: 100 ms LCD

Exemplo – Reaction Timer

Utilizaremos um microcontrolador com um timer

de 16 bits embutido. O timer é incrementado a

cada ciclo de instrução, que corresponde, no

caso, a seis ciclos de clock. A frequência de

clock é de 12 MHz, de modo que um ciclo de

instrução equivale a 0,5 microssegundo.

Como o timer tem 16 bits, o range é de

65535*0,5s = 32,77 ms.

O timer não possui um prescaler, mas tem um

sinal ‘top’ e permite o carregamento de um valor

inicial de contagem qualquer.

Exemplo – Reaction Timer

O range do timer é menor que o tempo de

reação esperado (de alguns segundos).

Portanto, precisamos estender o range sem

contar com um prescaler ou um registrador de

contagem terminal.

Faremos o ajuste do valor inicial de contagem

para que haja overflow após 1 ms, e

monitoraremos o sinal ‘top’ para contar o número

de overflows ocorridos. Para gerar 1 ms, são

necessários 2000 ciclos de instrução. Portanto, o

valor inicial de contagem adequado é

65535 – 2000 = 63535.

Exemplo – Reaction Timer

/* main.c */

#define MS_INIT 63535

void main(void){

int count_milliseconds = 0;

configure timer mode

set Cnt to MS_INIT

wait a random amount of time

turn on indicator light

start timer

while (user has not pushed reaction button){

if(Top) {

stop timer

set Cnt to MS_INIT

start timer

reset Top

count_milliseconds++;

}

}

turn light off

printf(“time: %i ms“, count_milliseconds);

}

Exemplo – Reaction Timer

Note que há uma imprecisão, já que é preciso parar o timer, reiniciá-lo e começar de novo. Considera-se esse tempo desprezível em termos práticos.

Watchdog Timers

Watchdog timers são tipos especiais de timers.

Eles são configurados com um valor de tempo

real, mas, em vez de gerar um sinal a cada t

segundos, o timer é encerrado e gera um sinal

de falha caso um sinal não seja gerado para ele

no momento adequado.

Uma utilização comum desse tipo de timer é

para permitir que um sistema embarcado se

reinicie no caso de uma falha. Nesse caso,

colocam-se sinais de reset do watchdog no

código para evitar o timeout e conecta-se o pino

de falha no pino de reset do processador.

Watchdog Timers

Em sistemas nos quais o reset total não é uma

opção, pode-se configurar uma rotina de serviço

(associada a um pino de interrupção) que leve a

um pulo para uma parte segura do código.

Pode-se até mesmo adotar uma abordagem

híbrida, pulando para uma rotina de serviço,

registrando o erro, e partindo depois para o

reset.

Note que isso é importante, pois um sistema

embarcado nem sempre pode sofrer boot de

forma simples como um desktop.

UART

Uma UART (Universal Asynchronous Receiver / Transmitter) recebe dados seriais e os grava em paralelo (geralmente um byte). Ela também toma dados em paralelo e os transmite de maneira serial.

A comunicação serial é útil quando se quer comunicar bytes de dados entre dispositivos separados por distâncias longas ou quando os dispositivos possuem poucos pinos de entrada / saída disponíveis.

UART

Internamente, uma UART simples pode possuir alguns registradores de configuração, e dois processadores de operação independente, um para receber e o outro para transmitir.

O transmissor pode possuir um registrador, geralmente denominado buffer de transmissão, que guarda os dados a serem enviados. O registrador possui a capacidade de deslocamento, de modo que os bits podem ser enviados de maneira serial (um por vez).

UART

O receptor, por sua vez, também possui um registrador de deslocamento, que recebe serialmente os bits e “os paraleliza”.

Isso é ilustrado na figura a seguir.

embedded

device 1

0 0 1

1 0 1 1

Sending UART

1 0 0 1 1 0 1 1

Receiving UART

1 0 0 1 1 0 1 1

UART

Note que, para realizar o deslocamento na taxa apropriada (e configurada), a UART precisa de um timer.

O receptor monitora constantemente o pino de recepção (rx) buscando um bit de início. Esse bit é tipicamente sinalizado por uma transição de alto para baixo em rx. Quando o bit é detectado, o receptor começa a amostrar os dados em intervalos predeterminados, deslocando os bits para seu registrador.

UART

Se for configurado para isso, o receptor lê ainda um bit de paridade, que é usado para verificar se a informação recebida está correta. Por exemplo, se for usada paridade ímpar, o número de “1s” nos dados + bit de paridade deve ser ímpar. Também pode-se configurar a UART para lidar com paridade par ou para operar sem paridade.

Quando os dados são recebidos, a UART sinaliza e o processador lê o byte no registrador de recepção. Ele agora está apto a receber mais dados.

UART

O transmissor opera da seguinte forma. Primeiramente, ele envia um bit de transmissão em seu pino de transmissão (tx), sinalizando o início do processo.

Então ele desloca os dados para tx numa taxa pré-definida. Se necessário, ele adiciona um bit de paridade ao final, como já discutimos.

Nesse ponto, a UART sinaliza a seu processador que está pronta para transmitir mais dados.

UART - Protocolo

O protocolo usado por UART’s tem a seguinte estrutura. Primeiro define-se a baud rate, taxa de transmissão e recepção de bits. Também se especifica o número de bits de dados utilizado e o tipo de paridade. Por fim, o protocolo define o número mínimo de bits usados entre transmissões. Esses bits são importantes para que a UART possa se preparar para receber a informação quando ela vier.

UART - Protocolo

start bit data

end bit

1 0 0 1 1 0 1 1

UART – Baud Rate

A baud rate determina a taxa de transmissão / recepção entre UARTs. Taxas usuais incluem 2400, 4800, 9600 e 19200 bits/s.

A configuração da baud rate requer a escrita num registrador especial segundo regras pré-determinadas (que não discutiremos).

Seria possível realizar a transmissão nos moldes da UART em nível de software, mas isso consumiria tempo de computação sem necessidade.

Moduladores de Largura de

Pulso (PWMs) Um modulador de largura de pulso

(PWM) é um dispositivo que gera um sinal que repetidamente chaveia entre níveis baixo e alto.

Controla-se a duração do valor alto e do valor baixo indicando-se o período desejado e o duty cycle, a razão entre o tempo em que o sinal está em nível alto e seu período. Uma onda quadrada clássica tem duty cycle de 50%. A largura de pulso corresponde ao tempo em que este permanece em nível alto.

PWMs

clk

pwm_o

25% duty cycle – average pwm_o is 1.25V

clk

pwm_o

50% duty cycle – average pwm_o is 2.5V.

clk

pwm_o

75% duty cycle – average pwm_o is 3.75V.

PWMs - Aplicação

Um uso comum de PWMs é no controle da tensão média passada a dispositivos. Isso é feito por meio do controle do período e do duty cycle.

Suponhamos, por exemplo, que um motor DC tenha um número de rotações por minuto igual a 10 vezes o valor da tensão colocada em sua entrada. Para conseguir 125 rpm, precisaríamos de 1,25V, enquanto, para conseguir 250 rpm, precisaríamos de 2,5V.

PWMs - Aplicação

Para realizar o controle via PWM, utiliza-se o duty cycle para conseguir a tensão média desejada e adota-se um período pequeno o suficiente para não impactar no desempenho do motor.

Por exemplo, com um duty cycle de 25%, ter-se-ia uma tensão média de 1,25V e 125 rpm.

Também pode-se usar esse princípio em dimmers usados para iluminação.

PWMs - Aplicação

Outro uso clássico de PWM é na codificação de comandos para carros de controle remoto.

Nesse caso, diferentes duty cycles podem representar diferentes comandos (direita, esquerda etc.), e o receptor usa um timer para definir o comando recebido.

Controles de LCDs

LCDs (Liquid Crystal Displays) são dispositivos de baixos custo e consumo que são capazes de exibir textos e imagens. São amplamente usados em sistemas embarcados, uma vez que estes não possuem monitores como ocorre com os desktops.

LCDs – Princípios Básicos

LCDs de reflexão: a luz passa por uma placa polarizadora. Em seguida, a luz polarizada encontra o cristal líquido. Se uma região desse material é excitada, há um alinhamento de moléculas que permite à luz passar; caso contrário, a luz não passa. A luz que passa é refletida por um espelho e torna a região excitada iluminada.

LCDs de absorção: a operação é similar, mas, em vez de um espelho, usa-se uma película preta, o que faz com que a região excitada fique mais escura que o resto.

Exemplos - LCDs

Um dos LCDs mais simples é o display de sete segmentos. Cada um dos segmentos pode ser ligado ou desligado, permitindo a exibição de letras ou números.

Caso se deseje representar apenas os dígitos de 0 a 9, o papel do driver será apenas o de converter 4 bits em BCD numa série de sinais para ativar/desativar os segmentos.

Exemplos - LCDs

Um LCD de matriz de pontos (dot matrix) pode exibir caracteres

alfanuméricos ou outros símbolos.

Cada caractere emprega tipicamente uma matriz 8 x 5, e o LCD

driver converte os dados de entradas nos sinais para excitar os

pontos específicos.

Cada tipo de LCD pode exibir múltiplos caracteres; além disso, cada

caractere pode ser exibido de maneira direta ou inversa. O LCD

pode permitir que o caractere pisque ou pode exibir um cursor.

Funcionalidades desse tipo fazem com que seja interessante dispor

de um controlador de LCD, por exemplo, com oito entradas e um

enable.

Controlador

Para mandar um byte, são colocados os valores adequados nas oito entradas e aciona-se o enable.

O byte pode ser uma palavra de controle ou um dado (e.g. em ASCII) a ser exibido.

Exemplo – Inicialização de um

LCD Consideremos um microcontrolador

ligado a um controlador LCD, como mostrado na figura a seguir. O controlador recebe informações do microcontrolador, as decodifica e realiza as ações necessárias no LCD.

Exemplo – Inicialização de um

LCD

Exemplo – Inicialização de um

LCD Feita a sequência de inicialização, é possível mandar

palavras de controle ou dados a serem exibidos.

RS é colocado em nível baixo, quando se trata de uma

operação de controle. RS é colocada em nível alto para

indicar que os dados enviados devem ser exibidos. Toda

informação enviada deve ocorrer com o enable ativado. A

tabela exposta mostra as palavras de controle possíveis.

Feita a inicialização por meio dos códigos mostrados, opta-

se por uma interface de 8 bits, limpa-se o display, coloca-se o

cursor na posição inicial, e o cursor se move para a direita

enquanto os dados são exibidos.

Exemplo – Inicialização de um

LCD Agora, pode-se escrever no LCD.

Coloca-se RS = 1, e colocam-se os dados nas linhas DB7 – DB0. A função WriteChar aceita um caractere para escrita no LCD. A função EnableLCD(45) ativa o enable e age como um delay, de modo que o comando possa ser processado e executado.

Controladores de Keypad

Um keypad é um conjunto de botões que fornecem entradas para um sistema embarcado. São muito comuns em sistemas embarcados, que não costumam dispor de teclados à maneira de desktops.

Um keypad simples tem botões dispostos num arranjo M x N, como ilustrado a seguir.

Keypad

N1 N2

N3 N4

M1

M2

M3

M4

key_code

keypad controller

k_pressed

key_code

4

N=4, M=4

Controladores de Keypad

O dispositivo tem N saídas, cada uma correspondente a uma

coluna e M saídas, cada uma correspondente a uma linha.

Quando um botão é apertado, uma coluna e uma linha

assumem nível alto, e o comando é identificado.

Pode-se usar um controlador para fazer uma varredura das

linhas e colunas, como mostrado na figura anterior. Quando o

botão é apertado, o controlador retorna o código

correspondente ao botão (‘key_code’), e coloca o bit

k_pressed em nível alto. Esse bit pode ser lido em software

de tempos em tempos (polling) ou gerar uma interrupção.

Conversores Analógico-Digital

Um conversor analógico-digital (ADC, A/D, A2D) é um dispositivo que converte um sinal analógico num sinal digital. Um conversor digital analógico (DAC, D/A, D2A) faz o oposto.

Essas conversões são muito importantes, pois os sistemas embarcados interagem com um ambiente que gera diversos sinais analógicos, embora só consigam lidar com dados digitais.

Conversores A/D

Um sinal analógico é considerado contínuo em seus valores (temperatura, velocidade etc.), enquanto um sinal digital assume apenas valores pertencentes a um conjunto finito (codificado em bits).

Consideremos, por exemplo, um sinal analógico que vai de 0 a 7,5V. Desejamos representar qualquer valor nessa faixa usando 4 bits (0000 a 1111, com distribuição uniforme). A figura a seguir ilustra isso.

Conversores A/D

Conversão A/D

Apresentamos a seguir o processo de amostragem e conversão de um sinal analógico entre 1V e 4V, a título de exemplo.

Conversão D/A

Apresentamos agora o processo inverso, de conversão D/A, ou seja, de reconstrução de uma estimativa do sinal analógico a partir dos bits correspondentes.

Conversão A/D

De maneira mais geral (supondo tensão mínima

nula), podemos computar os valores digitais a

partir dos analógicos (e vice-versa) usando a

relação:

e / Vmax = d / (2n – 1)

No nosso exemplo, se tomássemos e = 3V,

n = 4 e Vmax = 7,5, teríamos d = 6, ou 0110.

A resolução do conversor é dada por

Vmax / 2n – 1, que, em nosso exemplo, vale 0,5 V.

Conversores D/A

A estrutura interna de conversores D/A é mais simples que a de conversores A/D. Um conversor D/A basicamente tem ‘n’ entradas binárias, uma entrada para ‘Vmax’ e uma saída analógica ‘e’.

Um circuito com resistores e um amplificador operacional pode realizar essa conversão sem maiores dificuldades teóricas.

Conversores A/D

Conversores A/D são criaturas mais complexas. Dada uma entrada ‘Vmax’ e uma entrada analógica ‘e’, como encontrar a palavra binária correta?

Não há, como no caso de um D/A, um circuito analógico simples para isso.

Uma idéia seria usar um D/A conectado a Vmax e fazer uma busca pela palavra que aproxima a tensão de entrada com precisão suficiente. Mas como fazer essa busca?

Conversores A/D

Uma possibilidade seria usar uma busca exaustiva sequencial, que requer, no pior caso, um número exponencial de comparações.

Outra possibilidade é fazer uma busca binária, ou busca por aproximações sucessivas. Nesse caso, divide-se o range de valores de tensão possíveis em dois e verifica-se em que metade a tensão de entrada se encontra. Repete-se o processo então para o intervalo reduzido e assim por diante, exigindo no máximo ‘n’ comparações.

Aproximações Sucessivas

Suponhamos um conversor com 8 bits e range de 0 a 15V. Qual será a palavra

código para 5V?

Primeiramente, vemos que a metade do intervalo é 7,5V. 5V está abaixo, o que

significa que seu primeiro bit (o mais significativo) será zero.

Em seguida, achamos o ponto médio entre 0 e 7,5V, que é 3,75V. 5V está acima,

e, portanto, seu segundo bit mais significativo será “1”.

O ponto médio agora é 5,625V, e 5V está abaixo, o que gera um bit “0”.

Agora precisamos achar o ponto médio entre 3,75V e 5,625V, que é 4,6875V.

Temos que 5V está acima do intervalo, o que gera um bit “1”.

Aproximações Sucessivas

Agora precisamos achar o ponto médio entre 4,6875V e 5,625V,

que é 5,15625V. 5V está abaixo, o que gera um bit “0”.

O próximo ponto médio é 4,921875V, que leva a um bit “1”.

A seguir, tem-se 5,0390625V, que gera um bit “0”.

Por fim, tem-se 4,98046875V, que gera o oitavo bit, “1”.

Tem-se então 01010101 = 85.

Pela fórmula dada antes, teríamos 5/15 = d/28 – 1, ou seja, 85.

Note que a divisão por dois é feita de maneira eficiente em binário

por meio de deslocamentos, o que é sugerido pela figura a seguir.

Aproximações Sucessivas

Clocks de Tempo Real

Um real-time clock (RTC) é responsável por guardar data e hora num sistema

embarcado.

RTCs contém, tipicamente, um oscilador controlado por um cristal, que gera um

sinal de clock estável para uma cascata de contadores.

O primeiro desses contadores, tipicamente, conta até a frequência do oscilador, o

que indica 1 segundo. Nesse ponto, ele gera um sinal que move um segundo

contador, que vai até 59. Este gera um pulso para o contador de minutos. A

contagem de horas, dias, meses e anos segue de maneira similar.

Uma bateria de backup garante o funcionamento do sistema mesmo quando o

sistema embarcado é desligado.