Conexão Atmega8. Sensor de distância URM37 - conexão ao AVR e computador (via USB)

O artigo discutirá como conectar LEDs a um microcontrolador, trabalhar com portas e escrever um programa em SI. O artigo destina-se principalmente a iniciantes que acabaram de aprender microcontroladores AVR.

Primeiro você precisa selecionar um microcontrolador. No meu caso é ATmega8535. Neste caso, você pode usar qualquer microcontrolador, pois esta tarefa pode ser facilmente implementada em qualquer microcontrolador. Você pode escrever um programa para um microcontrolador em Assembly, SI, Pascal e Bascom. Usei a linguagem SI, todas essas linguagens são diferentes.
A diferença específica entre C e Pascal pode ser vista abaixo.

//LED piscando void main() ( ddrB = 0b11111111; //configura as portas B para saída portB = 0b11111111; //por padrão tudo está desligado while(1) ( portB = ˜portB; //muda o estado do LED para o inverso delay_ms(100 ); //atraso em 100 milissegundos ) )

Programa Primeiro; começar ddrB:= $FF; //define a porta B como saída portB:= $FF; //nada está aceso por padrão while(1) do start portB:= not(portB); //muda o estado do LED para reverso delay_ms(100); //termina um pequeno atraso; fim.

Lista de radioelementos

Designação Tipo Denominação Quantidade ObservaçãoComprarMeu bloco de notas
U1 AVR MK 8 bits

ATmega8535

1 Para o bloco de notas
R1-R8 Resistor

220 Ohm - 1 kOhm

8 Para o bloco de notas
R9-R11 Resistor

10 kOhm

3 Para o bloco de notas
V1-V8 Diodo emissor de luz 8 Para o bloco de notas
Botão tato 3

Emulamos o circuito no programa Proteus, piscamos o LED e aprendemos a fazer o flash do nosso microcontrolador virtual. Certamente muitos leitores pensaram: “É possível piscar um LED usando um botão conectado ao MK?

Sim, claro que é possível. Muito fácil de implementar. Além disso, você pode emular um botão com ou sem fixação. Além disso, no programa Proteus, você pode usar os dois tipos de botões usando a mesma macro de botão idêntica. Em que casos isso pode ser útil? Por exemplo, precisamos selecionar os modos de operação do dispositivo. Vamos dar uma olhada em como implementar isso usando um microcontrolador e realizar a emulação no programa Proteus.


Para ter uma ideia clara de que realmente temos a opção de dois modos, montaremos um circuito simples com 4 LEDs com controle de um botão. Na primeira opção, o primeiro ao quarto LED acende alternadamente. Com a segunda opção é a mesma coisa, mas na ordem inversa, ou seja, da quarta para a primeira. A única coisa que quero esclarecer é que nosso botão é selecionado para ser pressionado ou liberado somente antes do início do efeito. Até que o efeito termine seu trabalho, o programa não responde ao pressionar ou soltar o botão.

Então, direto ao ponto. Esta é a aparência do nosso diagrama no programa Proteus (clique para ampliar):

Neste esquema já vemos diferenças daquele que coletamos no artigo anterior. No lado esquerdo do diagrama vemos as designações do botão e da fonte de alimentação de +5 volts.

Como já discutimos, tomamos energia e pousamos na aba “Terminal”. Nós os designamos Power e Ground, respectivamente.

Denotamos a fonte de alimentação do circuito por um triângulo com uma linha dividindo-a em altura. Perto, na figura, está a designação do botão. À direita do botão vemos um círculo vermelho preenchido com uma seta de duas pontas. Se você clicar nele durante a emulação, o botão ficará fixo e será pressionado constantemente. Após pressioná-lo novamente, a fixação é removida.


Antes de usar, precisamos selecionar um botão da biblioteca da mesma forma que as demais partes. Para fazer isso, digite a palavra “mas” no campo “Máscara”. Depois no campo “Resultados” a palavra “BOTÃO”:


Após isso, o botão aparecerá em nossa lista, junto com as peças selecionadas utilizadas no projeto.

Quais portas usamos no projeto? Abaixo na figura vemos linhas de saída das portas PA0, PB0, PB1, PB2 e PB3. Temos LEDs conectados à porta B e um botão à porta A.

Assim, quando pressionado, fechamos o circuito conectando +5 volts à porta PA0 e ao terminal superior do resistor. Por que temos um resistor instalado aqui? O fato é que o circuito do botão deve estar fechado. Depois de instalarmos o resistor, a corrente flui do positivo da fonte de alimentação através do botão, do resistor e posteriormente para o terra.

Basta considerar o valor do resistor igual a 200 Ohms. Assim, ao pressionarmos o botão, conectamos a porta PA0 a +5 volts de potência, e se sondarmos o pino PA0 quanto à presença ou ausência de tensão, podemos influenciar a execução do nosso programa.

Forneci capturas de tela com o texto do nosso programa abaixo:


Assim, as diferenças do projeto anterior são que configuramos todos os 8 pinos da porta RA como entrada, configuramos os pinos da porta PB0 - PB3 como saída e PB4 - PB7 como entrada.


Então usamos um teste de condição em nosso programa “ se"


Assim, vemos na linha após “if”, entre colchetes, a condição de execução. O código abaixo é executado se tivermos um zero lógico, ou zero volts, na porta PA0. Este texto entre colchetes é a mudança de bit da porta. Analisaremos isso em um dos artigos a seguir, mas por enquanto basta acreditar que ao fazer isso estaremos votando no botão flexão. Então, entre chaves vem o texto do programa que será executado se a condição for verdadeira. Se a condição não for verdadeira, o programa continua a ser executado, ignorando o texto entre chaves.

Da mesma forma, usando a condição “if”, pesquisamos o botão em pressionando. Observe que o texto entre colchetes foi alterado. Isso significa que se tivermos uma unidade lógica na perna PA0, cumprimos a condição, ou seja, o texto entre colchetes. Ou seja, quando o botão é pressionado, os LEDs do primeiro ao quarto acendem e apagam um a um, e quando pressionado e mantido pressionado, os LEDs do quarto ao primeiro acendem e apagam. Assim, podemos influenciar a execução do programa pressionando um botão, pesquisando a presença de um zero lógico ou lógico nele

Além disso, que contém o arquivo “Sishnik”, HEX e o arquivo Proteus.

E aqui está o vídeo

Métodos de relógio

A forma canônica de cronometrar o MK é conectar um ressonador de quartzo aos pinos correspondentes (Fig. 18.11, a). A capacitância dos capacitores C1 e C2 em um caso típico deve ser de 22-36 pF (para inclusão de quartzo, consulte o Capítulo 15). A maioria dos modelos Tiny e Mega possuem uma configuração especial que permite regular o consumo. Quando este bit é definido como um (não programado), a amplitude de oscilação é reduzida, no entanto, a faixa de frequência possível e a imunidade geral a ruído são reduzidas, portanto, o uso deste modo não é recomendado (veja abaixo). Também pode ser utilizado um ressonador de quartzo de baixa frequência (por exemplo, um “clock” de 32.768 Hz), enquanto os capacitores C1 e C2 não precisam ser instalados, pois ao definir o slop para o valor O, os capacitores internos de 36 pF incluídos no MC estão conectados.

Em vez de quartzo, pode ser usado um ressonador cerâmico. O autor dessas linhas conseguiu operar o MK em frequências não padronizadas, usando uma indutância em miniatura em vez de quartzo na mesma conexão (com seu valor de 4,7 μH e capacidades de capacitor de 91 pF, a frequência é de cerca de 10 MHz).

Arroz. 18.11. Métodos de clock de um microcontrolador AVR usando: a - um ressonador de quartzo; b - gerador externo; c - correntes RC

Naturalmente, o MK também pode ser sincronizado a partir de um gerador externo (Fig. 18.11, b). Isso é especialmente conveniente quando você precisa sincronizar o MK com componentes externos ou ter uma frequência de clock muito precisa ao usar geradores apropriados (por exemplo, a série SG-8002 da Epson).

Pelo contrário, quando a precisão não é necessária, você pode usar um circuito LAN externo (Fig. 18.11, c). Neste circuito, a capacitância C1 deve ser de pelo menos 22 pF e o resistor R1 é selecionado na faixa de 3,3-100 ohms. Neste caso, a frequência é determinada pela fórmula F = 2/3 RC, CI não pode ser definido de forma alguma se você escrever um zero lógico na célula de configuração do SCR, conectando assim um capacitor interno de 36 pF.

Finalmente, você pode ficar sem nenhum componente externo - use o gerador IG integrado, que pode operar em quatro frequências, aproximadamente iguais a 1, 2, 4 e 8 MHz. Este recurso é melhor usado em mods low-end (1x Tiny, disponível em um pacote de 8 pinos - então os pinos destinados à conexão de um ressonador ou oscilador externo podem ser usados ​​para outros fins, como portas de E/S regulares. Família clássica de oscilador RC embutido não tinha.

Por padrão, os MKs das famílias Tiny e Mega são configurados para funcionar com o oscilador embutido na frequência de 1 MHz (cksel = oooi), portanto, para operar em outros modos você precisa definir as células de configuração do cksel de acordo (ver Tabela 18.1). Como fazer isso na prática será discutido no Capítulo 19. O valor recomendado dessas células para ressonadores convencionais de 1 MHz e mais é todos uns nas células cksel e zero nas células sk.

Detalhes

Ao instalar as células, deve-se levar em consideração que o estado cksel = oooo (espelho em relação ao valor mais comumente usado para um ressonador de quartzo iiii) coloca o MK em modo clock a partir de um oscilador externo, e neste estado ele não pode nem mesmo ser programado sem aplicar uma frequência externa. Além disso, se você tentar definir o modo com um ressonador de baixa frequência, o MC de alta frequência não iniciará mais e nem todos os programadores serão capazes de trabalhar em frequências de clock tão baixas. Portanto, ao manipular células, e não apenas cksel, você precisa ser extremamente cuidadoso e ter uma boa ideia do que exatamente está instalando. Isso é discutido com mais detalhes no próximo capítulo.

Tabela 18.1. Configurando células de configuração CKSEL dependendo dos modos de relógio

Fonte do relógio

Frequência externa

Gerador /?C integrado

Oscilador RC integrado

Gerador /?C integrado

Oscilador RC integrado

Corrente RC externa

Cadeia C externa /?

Corrente RC externa

Corrente RC externa

Ressonador de baixa frequência

Tabela 16.1 (final)

Fonte do relógio

Ressonador cerâmico

Ressonador cerâmico

ressonador de quartzo

Ressonador de quartzo

Portas de E/S paralelas

As portas de E/S (repetimos que não devem ser confundidas com registros de E/S ou portas seriais MK para troca de informações com dispositivos externos) em diferentes modelos podem variar de 1 a 7. As portas são nominalmente de 8 bits, em alguns casos A capacidade de bits é limitada pelo número de pinos do pacote e pode ser inferior a oito. As portas são designadas pelas letras A, B, C, D, etc., e não necessariamente em ordem: em modelos inferiores pode haver, por exemplo, apenas portas B e D (como no ATtiny2313) ou geralmente apenas uma porta B (como no ATtinylx).

Para reduzir o número de contatos no gabinete, na grande maioria dos casos, os pinos externos correspondentes às portas, além de sua função principal (entrada/saída bidirecional), também possuem uma adicional. Observe que, exceto pelo pino Reset, se ele puder operar em um modo alternativo, nenhuma troca especial de pino de porta será necessária. Se, por exemplo, você inicializar uma porta serial UART em seu programa, então os pinos da porta correspondentes (por exemplo, no ATmega8335 são os pinos das portas PDO e PD1) funcionarão em uma função alternativa, como entrada e saída UART. Contudo, nos intervalos entre esse uso especial dos pinos, eles podem, em princípio, ser usados ​​como pinos bidirecionais comuns. Na prática, é necessário utilizar medidas de projeto de circuito para isolar funções umas das outras, por isso não é recomendado abusar desse recurso.

Os pinos da porta são suficientemente autônomos e seu modo pode ser definido independentemente um do outro. Por padrão, quando a energia é ligada, todos os dispositivos adicionais são desabilitados e as portas funcionam como entrada, e ficam no terceiro estado com alta velocidade (ou seja, com alta impedância de entrada). Trabalhar para a saída requer instruções especiais, para as quais no programa é necessário definir o bit correspondente à saída desejada no registrador de direção de dados (este registrador é designado DDRx, onde x é uma letra que designa uma porta específica, por exemplo, para porta A será ddra). Se o bit for redefinido (isto é, igual ao zero lógico), então a saída funciona como uma entrada (como por padrão); se estiver definido (isto é, igual a um zero lógico), então funciona como uma saída.

Para definir a saída para um estado, você precisa definir separadamente o bit correspondente no registro de dados da porta (denotado por portx) e, para configurá-lo como O, redefinir este bit. A direção de operação da saída (entrada-saída, registro DDRx) e seu estado (O-1, portx) não devem ser confundidos.

O registrador de dados portx é na verdade apenas um buffer de saída; tudo o que é gravado nele é imediatamente gerado. Mas se você definir o pino da porta para a entrada (ou seja, escrever um zero lógico no registrador de direção ddrx), como é feito por padrão, o registrador de dados portx desempenhará um papel ligeiramente diferente - definir seus bits para zero significa que a entrada está no terceiro estado com alta resistência, e configurá-la para um conectará um resistor “pull-up” com uma resistência de 35-120 kOhm ao terminal.

Notas nas margens

Na maioria dos casos, o resistor pull-up embutido não é suficiente para uma operação confiável - devido à interferência, o MC pode funcionar mal, e é melhor instalar um resistor externo adicional em paralelo com este interno, com resistência de 1 até 5 kOhm (em casos críticos de consumo, seu valor pode ser aumentado para 20-30 kOhm). Por exemplo, se você conectar um botão externo com dois pinos à entrada, que é comutada para terra, ou o pino funcionar em um “barramento comum” com dispositivos remotos (localizados em outra placa), ou o pino executar a função de um interrupção externa (veja abaixo), então esse resistor adicional deve ser conectado.

O procedimento para ler o nível em um pino de porta se ele estiver no estado de entrada não é totalmente trivial. É tentador ler dados do registro de dados portx, mas isso não fará nada - você lerá apenas o que escreveu lá anteriormente. E para ler o que realmente está disponível na entrada (diretamente na saída do microcircuito), outra possibilidade é oferecida. Para fazer isso, você precisa acessar algum array, que é denotado por pinx. O acesso é realizado da mesma forma que os bits individuais dos RVVs convencionais (ver Capítulo 19), mas o pinx não é um registro, é simplesmente um determinado intervalo de endereços, cuja leitura fornece acesso às informações dos elementos do buffer na entrada da porta. É claro que não é possível escrever algo nos endereços piNx.

Interrupções

Assim como nos PCs, as interrupções nos microcontroladores vêm em dois tipos. Mas se em um PC as interrupções são divididas em hardware (por exemplo, de um temporizador ou teclado) e software (na verdade não são interrupções, mas sub-rotinas escritas no BIOS - com a disseminação do Windows, esse conceito quase desapareceu da prática do programador), então no MK, naturalmente, todas as interrupções são de hardware e são divididas em internas e externas. Qualquer interrupção isoladamente, bem como a possibilidade de sua ocorrência em geral, carece de prévia autorização especial.

Deve ficar bem entendido que para inicializar qualquer interrupção, você precisa fazer quatro coisas no programa: habilitar as interrupções em geral (elas estão desabilitadas por padrão), depois habilitar esta interrupção específica, definir um dos modos disponíveis para ela e, finalmente , defina o vetor de interrupção: ponteiro para label , ao longo do qual o procedimento da sub-rotina do manipulador de interrupção está localizado. E, claro, depois disso você precisa escrever o próprio manipulador, caso contrário tudo isso acontecerá em vão. Isso é discutido com mais detalhes no Capítulo 19.

Interrupções internas podem surgir de qualquer dispositivo adicional ao núcleo do sistema - de temporizadores, de um comparador analógico, de uma porta serial, etc. Uma interrupção interna é um evento que ocorre no sistema e interrompe a execução do programa principal. O sistema de interrupção interna do AVR é ​​bastante extenso e representa o principal sistema de interação dos dispositivos com o núcleo do sistema, e voltaremos a esse assunto mais de uma vez.

O AVR MK possui pelo menos duas interrupções externas, INTO, INT1 (a maioria dos Megas possui uma terceira - ICHT2). Uma interrupção externa é um evento que ocorre quando um sinal aparece em uma das entradas projetadas especificamente para esse fim. Existem três tipos de eventos que causam uma interrupção e podem ser configurados no software: pode ser um nível de tensão baixo ou uma borda positiva ou negativa no pino correspondente. Curiosamente, as interrupções para todos esses eventos são executadas mesmo se o pino da porta correspondente estiver configurado como saída.

Vejamos brevemente os recursos de uso desses modos. Uma interrupção de baixo nível (o modo é definido por padrão, para inicializá-lo basta habilitar a interrupção correspondente) ocorre sempre que a entrada correspondente estiver baixa. “Todas as vezes” significa que realmente todas as vezes, ou seja, se um impulso negativo durar algum tempo, então o procedimento de processamento da interrupção, terminado, será repetido continuamente, impedindo o funcionamento do programa principal. Portanto, o esquema usual para utilizar este modo de interrupção externa é desativá-lo imediatamente após sua ocorrência (o procedimento de processamento, uma vez iniciado, será concluído uma vez) e habilitá-lo novamente somente quando a influência externa já deveria ter terminado (por exemplo, se é um pressionamento de botão, então deve ser permitido novamente pelo temporizador após um ou dois segundos).

Em contraste, as interrupções crescentes ou decrescentes são executadas uma vez. É claro que não há proteção contra salto de contato e não pode haver, porque o MK não é capaz de distinguir o salto de uma série de pulsos curtos. Se isso for crítico, você precisará tomar medidas externas para se proteger contra saltos ou usar o mesmo método da interrupção de nível - dentro do procedimento do manipulador de interrupção, desabilite a própria interrupção com o primeiro comando e depois de algum tempo em outro procedimento ( por temporizador ou por outro evento) para resolvê-lo novamente (este método de “anti-ressalto” é na verdade idêntico ao uso de um dispositivo de disparo único, consulte o Capítulo 15).

Detalhes

O leitor atento tem uma pergunta legítima: por que precisamos de um modo de interrupção de nível externo? O fato é que em todos os modelos ele é realizado de forma assíncrona - no momento em que aparece um nível baixo na saída do MK. É claro que a detecção de interrupção só pode ocorrer no final da instrução atual, portanto, pulsos muito curtos podem ser perdidos. Mas as interrupções INTO e INT1 no modo de controle de borda para a maioria dos modelos são determinadas ao contrário, apenas de forma síncrona - no momento da diferença nos níveis do sinal de clock do controlador, portanto, sua duração não deve ser menor que um período de clock . Mas isso não é o mais importante: em geral, não haveria diferença nesses modos se não fosse pelo fato de que o modo síncrono certamente requer a presença desse mesmo sinal de clock. Portanto, uma interrupção externa assíncrona, respectivamente, pode “acordar” um controlador que está em um dos modos de economia profunda de energia, quando o gerador de clock não está funcionando, mas o síncrono não. E MCUs comuns, como o AT90S8515 da família Classic (mas não seu mega-análogo!), só podem ser despertados do “sono” profundo por uma interrupção de nível externo, o que nem sempre é conveniente de usar. A maioria dos modelos da família Meda (dos modelos mais novos - exceto ATmegaS) possuem outra interrupção, INT2, que ocorre apenas nas arestas (não pode por nível), mas, diferentemente de INTO e INT1, de forma assíncrona. No ATtiny2313 (mas não em seu analógico “clássico”!) tal interrupção assíncrona pode ocorrer por um sinal de qualquer um dos 8 pinos da porta B. Isso aumenta significativamente a usabilidade do controlador no modo de economia de energia.

Contadores-temporizadores

A maioria dos AVR MKs tem dois ou três contadores temporizadores, um dos quais é de 16 bits e o restante é de 8 bits (em modelos Mega mais antigos, o número total de contadores pode ser de até 6). Todos os contadores têm a capacidade de pré-carregar valores e podem operar diretamente a partir da frequência do clock do processador (SC) ou a partir dela, dividido por 8, 64, 256 ou 1024 (em alguns casos por 16 e 32), bem como a partir de um sinal externo. Em geral, o design dos temporizadores no MK, como dissemos, é semelhante ao dos contadores 561HEU/14 (ver Capítulo 15), apenas a sua funcionalidade é significativamente expandida.

Na arquitetura AVR, os contadores de 8 bits recebem os números O e 2, e os de 16 bits recebem os números 1, 3 e assim por diante. Alguns contadores de 8 bits (geralmente o Timer 2, se houver dois deles) podem operar em modo assíncrono a partir de um gerador de clock separado e continuar a funcionar mesmo se o restante do MCU estiver em estado “suspenso”, o que permite eles para ser usado como um relógio em tempo real.

Ao usar contadores como contadores comuns de pulsos externos (e a reação é possível tanto na queda quanto na borda do pulso), a frequência dos pulsos contados não deve exceder metade da frequência do gerador de relógio MK (e com um meandro externo assimétrico, as instruções recomendam um valor ainda mais baixo da frequência limite - 0,4 do relógio). Isso se deve ao fato de que ao contar pulsos externos, suas bordas são detectadas de forma síncrona (nos momentos de borda positiva do sinal de clock). Além disso, vale considerar que o atraso na atualização do conteúdo do contador após a chegada de um pulso externo pode ser de até 2,5 períodos de clock.

Essas são limitações bastante fortes, portanto, por exemplo, usar um MK como medidor de frequência universal não é muito conveniente - é melhor projetar circuitos de alta velocidade usando lógica combinacional apropriada ou FPGAs (circuitos integrados lógicos programáveis).

Quando ocorre um estouro de contador, ocorre um evento que pode acionar uma interrupção correspondente. O contador Timer O de 8 bits é limitado por esta função em alguns casos. O temporizador 2, se presente, também pode disparar uma interrupção se o valor contado corresponder a algum valor predeterminado. Os contadores de 16 bits são mais “avançados” e podem causar interrupções quando coincidem com dois números A e B especificados independentemente. Nesse caso, os contadores podem ser zerados ou continuar contando, e pulsos podem ser gerados em pinos especiais (em hardware, sem participação do programa).

Além disso, os contadores de 16 bits podem “capturar” pulsos únicos externos em um pino especial. Neste caso, uma interrupção pode ser chamada e o conteúdo do contador é colocado em um determinado registro. O próprio contador pode ser zerado e começar a contar novamente ou simplesmente continuar a contagem. Este modo é conveniente para medir o período de um sinal externo ou para contar certos eventos irregulares (como a passagem de partículas em um contador Geiger). É importante que a fonte de tais eventos também possa ser um comparador analógico integrado, que é então usado como modelador de pulso.

Todos os contadores podem operar no chamado. Modos PWM, ou seja, como moduladores de largura de pulso (PWM) de 8, 9, 10 ou 16 bits e independentemente um do outro, o que permite a implementação de PWM multicanal. Na documentação técnica, muitas páginas são dedicadas a estes modos, devido à sua complexidade, versatilidade e incómodo. O uso mais simples desses modos para reprodução de áudio será brevemente discutido no Capítulo 22 em relação à sinalização de voz. Observe que a síntese de som não é a única ou mesmo a finalidade de maior prioridade dos modos PWM; eles também podem ser usados ​​para regular potência ou corrente (por exemplo, ao carregar baterias), controlar motores, retificação de sinal e conversão digital para analógico .

Além dos contadores-temporizador, todos os controladores AVR, sem exceção, possuem um temporizador Watchdog. Destina-se principalmente a retirar o MK do modo de economia de energia após um determinado intervalo de tempo, mas também pode ser utilizado para uma reinicialização de emergência do MK. Por exemplo, se o funcionamento do programa depende da chegada de sinais externos, então se eles forem perdidos (por exemplo, devido a uma quebra de linha), o MK pode “travar” e o temporizador Watchdog irá trazê-lo para fora deste estado.

Portas seriais

As portas seriais para troca de dados com dispositivos externos são o componente mais importante de qualquer MK, sem elas sua “comunicação” com o mundo exterior fica bastante limitada. Eles são chamados de sequenciais porque apenas um bit é transmitido por vez (em alguns casos, a transmissão e a recepção simultâneas são possíveis, mas ainda assim apenas um bit por vez). A vantagem mais importante das portas seriais sobre as paralelas (quando bytes inteiros ou tétrades nibbles são trocados simultaneamente) é a redução no número de conexões. Mas não é a única: paradoxalmente, as interfaces seriais dão uma vantagem significativa em relação às paralelas em altas velocidades, quando atrasos nas linhas começam a afetar a velocidade de transmissão. Este último não pode ser estritamente igual, e esta é uma das razões pelas quais as interfaces seriais estão começando a dominar (exemplos típicos são USB e FireWire em vez de COM, LPT e SCSI, ou Serial ATA em vez de IDE).

Em dispositivos microcontroladores com nossos volumes de dados, é claro, a velocidade de transferência nos preocupa em segundo lugar, mas o número de fios de conexão é um fator muito crítico. Portanto, todos os dispositivos externos que trataremos neste livro terão interfaces seriais.

Quase qualquer porta serial pode ser simulada em software usando pinos MK normais. Antigamente isso era feito mesmo no caso do mais popular desses noptoBs - UART. Porém, desde então, os MKs adquiriram portas seriais de hardware, o que, porém, não significa a necessidade de seu uso absoluto. A facilidade de simulação de software de portas seriais é outra vantagem.

De todos os tipos de portas que podem estar presentes em um MCU AVR, daremos especial atenção ao UART-Receptor-Transmissor Assíncrono Universal, “transceptor assíncrono universal”. UART é a parte principal de qualquer dispositivo que suporte o protocolo RS-232, mas não só (não é à toa que é “universal”) - por exemplo, os padrões industriais RS-485 e RS-422 também são implementados via UART , pois diferem do RS-232 apenas nos parâmetros elétricos e velocidades permitidas, e não na lógica geral de construção. Os computadores pessoais possuem uma porta COM que opera usando o mesmo protocolo RS-232, e o nó UART também é sua parte básica.

Portanto, o UART serve como principal forma de troca de dados entre o MK e um computador. Observe que a falta de uma porta COM na maioria dos modelos de PC modernos não é um obstáculo: existem adaptadores USB-COM para isso e uma placa adicional com portas COM pode ser inserida no modelo desktop.

Notas nas margens

Por que isso é tão importante para nós? O fato é que ao conectar o layout do dispositivo a um computador, mesmo que a troca de dados não seja fornecida pela funcionalidade do dispositivo, é muito mais fácil depurar o programa simplesmente inserindo temporariamente nos lugares certos do programa a operação de envio os valores dos registros envolvidos para o PC e recebê-los em tempo real usando algum programa emulador de terminal. Isso é muito mais conveniente do que dominar o volumoso AVR Studio e até mesmo vem com alguma placa de depuração cara. Portanto, meu conselho é fazer imediatamente uma placa de depuração contendo um conector de programação (veja o próximo capítulo) e um conversor de nível UART/RS-232 com um conector para conectar um cabo de modem nulo (veja o Capítulo 21).

Como usar o UART na prática é abordado no Capítulo 21. Além do UART, quase todos os MCUs AVR contêm a mais simples de todas as portas seriais - SPI (Serial Peripheral Interface). O princípio do dispositivo SPI foi mencionado no Capítulo 16. Sua simplicidade fundamental desempenhou um papel parcialmente ruim: é difícil encontrar dois dispositivos onde os protocolos SPI sejam completamente iguais; geralmente a troca por esta porta é acompanhada por um ou outro “ sinos e assobios”. Ressalta-se que a programação do AVR também é realizada via SPI, porém, em geral, esta interface e o SPI para troca de dados são coisas diferentes, embora na maioria dos casos possuam os mesmos pinos.

Mas neste livro, no Capítulo 21, veremos a interface I^C mais complexa, embora mais lenta, que é necessária com mais frequência, já que muitos dispositivos periféricos funcionam através dela.

Consideraremos alguns outros componentes da família MK AVR (por exemplo, ADCs) à medida que apresentamos circuitos específicos - ficará mais claro. Aqui terminaremos nossa longa introdução ao microcontrolador e passaremos à questão de como programá-lo.

Hoje tentaremos usar um microcontrolador mais simples ATtiny2313 e conecte a ele um display LCD de caracteres contendo duas linhas de 16 caracteres.

Conectaremos o display da maneira padrão de 4 bits.

Primeiro, vamos começar, é claro, pelo microcontrolador, pois já estamos bem familiarizados com o display das lições anteriores.

Vamos abrir a ficha técnica do controlador ATtiny2313 e vamos ver sua pinagem

Vemos que este controlador existe em dois tipos de gabinetes, mas como o obtive em um pacote DIP, consideraremos esta versão específica do gabinete e, em princípio, eles não diferem muito, exceto na aparência, então como o número de pernas é o mesmo - 20 cada.

Como existem 20 pernas em comparação com as 28 pernas do controlador ATMega8, nas quais temos trabalhado o tempo todo e continuaremos trabalhando, então, respectivamente, também haverá menos possibilidades.

Em princípio tudo o que o ATmega8 tinha está aqui, a única coisa é que tem menos garras de porta. Mas como a tarefa que temos pela frente é tentar conectá-lo através do barramento SPI a outro controlador, isso não nos deprime muito.

Existem algumas outras diferenças, mas são pequenas e iremos conhecê-las conforme necessário.

Vamos montar um circuito como este (clique na imagem para ampliar a imagem)

O display está conectado aos pinos da porta D. PD1 e PD2 estão nas entradas de controle e o restante está conectado aos pinos do módulo de display D4-D7.

Vamos criar um projeto com o nome TINY2313_LCD, transferir tudo para ele, exceto o módulo principal do projeto para conectar o display ao Atmega8.

É claro que algumas coisas precisarão ser refeitas. Para fazer isso, você precisa estudar cuidadosamente qual perna está conectada a quê. O barramento E do display está conectado ao PD2, e o barramento RS está conectado ao PD1, então vamos fazer alterações no arquivo lcd.h

#definire1PORTD|=0b0000 01 00 //define a linha E como 1

#definire0PORTD&=0b1111 10 11 //define a linha E como 0

#definirrs1PORTD|=0b00000 01 0 //define a linha RS como 1 (dados)

#definirrs0PORTD&=0b11111 10 1 //define a linha RS como 0 (comando)

Como podemos ver pela fonte em negrito, não tivemos mudanças tão drásticas.

Agora entradas de informações. Aqui usamos as pernas PD3-PD6, ou seja, elas estão deslocadas em 1 ponto em relação à conexão com o Atmega8, então também vamos corrigir algo no arquivo lcd.c em função enviar meio byte

PORTD&=0b 1 0000 111; // apaga informações nas entradas DB4-DB7, deixa o resto em paz

Mas isso não é tudo. Anteriormente deslocamos os dados transmitidos em 4, mas agora, devido às alterações acima, só teremos que deslocá-los em 3. Portanto, na mesma função também corrigiremos a primeira linha

c<<=3 ;

Essas são todas as mudanças. Concordo, eles não são tão bons! Isso é conseguido pelo fato de sempre tentarmos escrever código universal e usar substituições de macro. Se não tivéssemos dedicado tempo a isso de uma só vez, teríamos que corrigir o código em quase todas as funções da nossa biblioteca.

No módulo principal, não tocamos na inicialização da porta D; deixamos todo o módulo entrar no estado de saída, como na lição 12.

Vamos tentar montar o projeto e primeiro ver o resultado no Proteus, já que também fiz um projeto para ele, que também estará no arquivo anexo com o projeto para Atmel Studio

Tudo funciona muito bem para nós! É assim que você pode refazer rapidamente um projeto de um controlador para outro.

Proteus é muito bom, mas é sempre melhor observar detalhes reais. Todo o circuito foi montado em uma protoboard, pois não fiz nem montei uma placa de depuração para este controlador. Conectaremos o programador através de um conector padrão como este

Aqui está o diagrama completo

Tudo é padrão aqui. Resistor de pull-up para RESET, etc.

Agora, antes de atualizar o controlador no Avrdude, precisamos selecionar o controlador e ler sua memória flash

Em seguida, vá para a guia FUSÍVEIS e configure os fusíveis corretamente. Como não temos ressonador de quartzo, instalamos os fusíveis desta forma

Conectando um LED a uma linha de porta de E/S

Depois de estudar este material, no qual tudo é descrito detalhadamente com um grande número de exemplos, você poderá facilmente dominar e programar as portas de entrada/saída dos microcontroladores AVR.

  • Parte 2. Conectando o LED à linha da porta de E/S
  • Parte 3. Conectando o transistor à linha da porta de E/S
Consideraremos um exemplo em um microcontrolador ATMega8 .

Escreveremos o programa em Estúdio Atmel 6.0 .

Vamos emular o circuito em Proteus 7 Profissional .

O primeiro exemplo no estudo de microcontroladores é conectar e controlar um LED; este é o exemplo mais simples e óbvio. Este exemplo tornou-se um clássico no estudo de microcontroladores, como o programa “Hello World!”. ao aprender outras linguagens de programação.
A corrente máxima que cada porta de E/S pode passar é 40 mA.
A corrente máxima que cada linha de porta de E/S pode transportar é 20 mA.
Antes de conectar uma carga, incluindo um LED, às linhas da porta de E/S, você precisa saber que pode queimar o microcontrolador excedendo a carga permitida na linha da porta de E/S.
Para limitar a corrente que flui pelas linhas das portas de E/S do microcontrolador, é necessário calcular e conectar um resistor.

Fig: Pinagem do LED.

Fig: Conectando o ânodo LED ao microcontrolador.

Fig: Conectando o cátodo LED ao microcontrolador.

A resistência do resistor limitador de corrente conectado às linhas das portas de entrada/saída ao conectar um LED é calculada pela fórmula:

Onde:
- Contra- tensão de alimentação;
- VSP- queda de tensão na linha da porta I/O;
- Vd- queda direta de tensão no LED;
- EU IA- corrente contínua no LED;
- Kn- Coeficiente de confiabilidade do LED;

Exemplo:
- tensão de alimentação - 5V;
- queda direta de tensão no LED – 2B ;
10mA (Retirado da folha de dados para LED);
- coeficiente de confiabilidade dos robôs LED – 75% (Retirado da folha de dados para LED);
- queda de tensão na linha da porta de E/S – 0,5V (Retirado da folha de dados para o microcontrolador: Vol (baixa tensão de saída) – se a corrente fluir, e Voh (alta tensão de saída) – se a corrente fluir para fora);

Assim, o valor do resistor R = 166,66 Ohm, o valor de resistência mais alto mais próximo é selecionado.

Se a tensão direta do LED não for conhecida, a resistência pode ser calculada usando a lei de Ohm.

Onde:
- você- tensão aplicada a uma seção do circuito;
- EU

Exemplo:
4,5 V;
- corrente nominal da linha da porta de E/S – 20mA.

Tendo determinado o valor do resistor R, é necessário calcular a potência P, medido em watts, que será liberado no resistor na forma de calor quando a corrente flui no circuito.

Onde:
- você– tensão aplicada a uma seção do circuito;
- EU- corrente nominal da linha da porta I/O.

Exemplo:
- tensão aplicada a uma seção do circuito – 4,5 V;
- corrente direta no LED – 20mA.

Tendo calculado a potência alocada ao resistor, selecionamos o valor mais alto da potência do resistor mais próximo. Se a dissipação de energia do resistor for insuficiente, ele poderá falhar.

- conectar um ânodo LED de baixa potência à linha da porta I/O:

#incluir // Programa principal int main(void) ( // Configura as portas de entrada/saída DDRC = 0b11111111; // Configura todos os bits da porta C para o modo "Saída" PORTC = 0b11111111; // Define todos os bits da porta C para log "1" (A tensão na saída da porta é igual a Vcc) // Loop eterno while (1) ( ) )

- conectar um cátodo LED de baixa potência à linha da porta I/O:

// Inclui bibliotecas externas #include #incluir // Programa principal int main(void) ( // Configura as portas de entrada/saída DDRC = 0b11111111; // Configura todos os bits da porta C para o modo "Saída" PORTC = 0b00000000; // Define todos os bits da porta C para log "0" (A tensão na saída da porta é igual a GND) // Loop eterno while (1) ( ) )

- conectar um LED de baixa potência com ânodo e cátodo à linha da porta I/O:

// Inclui bibliotecas externas #include #incluir // Programa principal int main(void) ( // Configura as portas de entrada/saída DDRD = 0b11111111; // Configura todos os bits da porta D para o modo "Saída" PORTD = 0b11111111; // Define todos os bits da porta D para log "1" (Na saída da porta a tensão é igual a Vcc) DDRC = 0b11111111; //Coloca todos os bits da porta C no modo “Saída” PORTC = 0b00000000; //Coloca todos os bits da porta C no “0” lógico (Na saída da porta a tensão é igual a GND) // Loop eterno while (1) ( ) )