A resposta aceita pelo jfpoilpret é muito bem escrita, perfeitamente válida e em 99% dos casos farei exatamente o que ele explica. As soluções dele estão dentro dos parâmetros definidos, portanto, devem funcionar muito bem. Mas o que é melhor do que " muito bem "? Perfeição! Afinal, a questão é gerar um valor exato. Como dito perto o suficiente, é bom na maioria dos casos (sem dúvida todos), e mesmo ao lidar com algo como um relógio quando 1 segundo precisa ser 1 segundo, você ainda precisa sofrer imperfeições nas partes herdadas.
O que vou sugerir nem sempre é possível. Em alguns casos, é possível, mas com muito mais trabalho e esforço do que neste caso. Vale a pena depender caso a caso. Meu objetivo é mostrar principalmente uma alternativa para futuras referências que é melhor em casos um tanto marginais. Isso foi escrito tendo em mente os usuários iniciantes do Arduino que não possuem uma vasta experiência em eletrônica.
Para pessoas mais avançadas, isso provavelmente parecerá muito detalhado e embotado. Mas acredito que essas mesmas pessoas provavelmente já sabem disso e não precisam dessa resposta. Isso também é aplicável a todos os microcontroladores, fabricantes e arquiteturas. Porém, para outros microcontroladores, você precisará consultar a folha de dados correta para descobrir os registros adequados e os nomes e valores de pré-escala.
No seu caso, você precisa de uma frequência específica e o mais interessante é que exatamente 56 kHz podem ser alcançados com muita facilidade (sem contar as imperfeições práticas das partes). Portanto, este também é um exemplo perfeito.
A geração de um sinal depende dos temporizadores e da fonte de clock do microcontrolador, conforme explicado pelo jfpoilpret. Sua resposta lida com o problema de apenas um ponto de vista e que está mexendo com temporizadores. Mas você também pode mexer com a fonte do relógio ou, melhor ainda, com sinergia e resultados impressionantes. Alterando os parâmetros do ambiente, neste caso invadindo o sistema e substituindo a fonte do relógio, podemos lidar com um problema específico com muito, muito mais facilidade e simplicidade.
Primeiro, para lembrar, devido à alternância do estado do pino, você precisa executar o ISR duas vezes mais que a frequência do sinal. Isso é 112.000 vezes por segundo. 56.000 e 16.000.000 não somam muito bem, como já apontado. Precisamos mudar a frequência do sinal ou a frequência do tato. Vamos lidar agora com uma frequência de sinal imutável e encontrar uma melhor velocidade de clock.
Seria mais simples escolher um relógio com uma ordem de magnitude maior que 56 kHz (ou 112 kHz, mas é praticamente o mesmo), pois você só adiciona zeros e esse tipo de matemática é mais simples para a maioria das pessoas. Infelizmente, tudo neste mundo é algum tipo de compromisso com alguma coisa. Nem todo valor vai funcionar.
O primeiro exemplo é com uma velocidade de gerador de tato muito baixa.
Se você escolher um relógio de 56.000 Hz, não poderá fazer nada, pois precisará ligar para o ISR a cada ciclo e não poderá fazer mais nada. É totalmente inútil. Se você escolher uma velocidade 10 vezes mais rápida (560 kHz), você terá 9 (10 ciclos para o temporizador atingir seu valor máximo - um ciclo para chamar a função ISR) ciclos de microcontrolador para fazer seu trabalho, e isso é possível e pode não ser suficiente. Você simplesmente precisa de mais poder computacional.
Se você escolher um valor muito alto por outro lado, como 56 MHz, o microcontrolador simplesmente não pode trabalhar com ele. É muito rápido. Portanto, simplesmente escolher o maior valor na loja também não será suficiente.
O Arduino Uno R3 original tem um relógio de estoque em 16 MHz, portanto, qualquer coisa mais lenta do que é garantida que funcione. O próximo valor que é uma ordem de magnitude maior que 56 e menor que 16 MHz é 5,6 MHz. Isso fará com que seja possível ligar para o ISR a cada 50 ciclos e criará a frequência de timer perfeita de 112.000 Hz. E seu sinal será exatamente 56 kHz. Você terá 49 ciclos de MCU para executar seu programa entre chamadas ISR, mas ainda é cerca de 1/3 da velocidade do relógio original. Pode-se usar 112 como base e usar um relógio de 11,2 MHz e isso dará cerca de 2/3 do ressonador de 16 MHz. A função ISR será chamada a cada 100 ciclos e ainda gerará um sinal perfeito de 56 kHz.
No entanto, existem dois grandes problemas com esses valores.
O primeiro problema depende muito de suas necessidades: Você sacrifica cerca de 1/3 (com 11,2 MHz) de sua potência computacional máxima para obter a frequência exata do sinal que usa um valor de registro fácil de encontrar (OCR iirc ). Você pode ficar bem com isso ou não.
O segundo problema é muito difícil : é muito fácil encontrar valores, mas muitas vezes eles simplesmente não existem como uma fonte de relógio fabricada. Esta é a página ressonadora da Farnell que simplesmente não possui 5,6 MHz e 11,2 MHz.
Para contornar isso, podemos examinar os valores disponíveis do ressonador e descobrir outra coisa que pode ser usada para gerar exatamente os valores desejados. Se dividirmos 56 por 4, obtemos 14 e, felizmente, existe um ressonador de 14 MHz. Isso nos fornece uma velocidade muito mais alta, mais potência e um valor de registro igualmente fácil de encontrar. Para chamar o ISR 112.000 vezes por segundo, precisamos colocar o valor decimal 124 ou hexadecimal 0x7C no registro OCR, portanto, contando 124 ciclos + 1 para chamar o ISR, obtemos o valor perfeito desejado.
NB
- ISR - rotina de serviço de interrupção (este é o código que é executado apenas nas interrupções geradas)
- O tamanho do seu programa depende do tamanho da memória! Não tem nada a ver com a velocidade do relógio e nada com a frequência com que você liga para o ISR.
Quando o microcontrolador inicia com o comando do programa, um contador é incrementado. Se uma interrupção for gerada, o ISR é chamado e esse valor é armazenado em um registro especial. Quando o código ISR é concluído, o valor do contador de programa é restaurado a partir desse registro especial e o programa continua de onde foi interrompido como se nunca tivesse acontecido.
Vou dar um exemplo extremamente estúpido. Se você é purista, eu o aviso: pode ocorrer sangramento no nariz e nos olhos.
Imagine que você tem que andar de algum lugar para outro lugar. As instruções da rota passo a passo são o seu programa principal e seus comandos. A rapidez com que você anda ou corre depende da sua "velocidade do relógio", mas não das instruções da rota (30 passos à frente, 1 volta 90 graus à esquerda, 10 passos à frente, 45 graus à direita, etc.). Eles são sempre os mesmos . Agora imagine uma criança ou um político local ganancioso e corrupto desamarrar seus sapatos de vez em quando. Este é o evento que gera uma interrupção. Então você pára após o último passo, ajoelha-se e amarra o sapato novamente. Este é o seu programa ISR.
Então você continua do lugar em que parou; você não começa do começo. Quando você anda sem se importar com o mundo e com o tempo todo, não se importa, mesmo que tenha que amarrar o sapato a cada dois passos. No entanto, se você fizer isso com restrições de tempo, como correr 100 metros nas Olimpíadas (ou correr contra um predador faminto de comer carne), parar e amarrar os sapatos pode ter consequências terríveis. O mesmo acontece com os microcontroladores. Mesmo se você executar apenas uma linha de código, seu programa continuará, embora lento. Se você não se importa com velocidade, não será um problema. Se você precisar dedicar algum tempo, como usar outras ações dependentes do timer, a interferência pode ser muito indesejada e problemática.
Menos é mais! Um relógio mais rápido nem sempre é melhor. Dispositivos com clock mais lento usam consideravelmente menos energia. Esse pode ser um ponto crucial em um dispositivo operado por bateria.
Os ciclos necessários são derivados destas fórmulas:
(velocidade do relógio / (valor do pré-calibrador * frequência de chamada ISR necessária)) - 1