Estou tentando entender o cronômetro do watchdog da série ATTinyX5. Então, as coisas que li fizeram parecer que você poderia usá-lo para fazer o programa fazer algo específico a cada N segundos, mas nunca realmente mostrou como. Outros fizeram parecer que ele só redefiniria o chip, a menos que algo no código redefinisse sua contagem enquanto isso (que parece ser o uso "normal").
Existe alguma maneira de usar o WDT como você faria com TIMER1_COMPA_vect ou similar. Percebi que ele tem um modo de tempo limite de 1 segundo e eu adoraria poder usá-lo para fazer algo acontecer a cada 1 segundo no meu código (e, de preferência, durma no meio).
* Atualização: * Desde que foi solicitado, estou me referindo à seção 8.4 da folha de dados do ATTinyX5 . Não que eu o entenda completamente, que é o meu problema ...
+1 por pensar fora da caixa. Polegares extras, se você adicionar um link à folha de dados do AVR.
Você certamente pode. De acordo com a folha de dados, o timer do watchdog pode ser configurado para redefinir o MCU ou causar uma interrupção quando acionado. Parece que você está mais interessado na possibilidade de interrupção.
O WDT é realmente mais fácil de configurar do que um temporizador normal, pelo mesmo motivo que é menos útil: menos opções. Ele roda em um relógio de 128kHz calibrado internamente, o que significa que seu tempo não é afetado pela velocidade do relógio principal do MCU. Ele também pode continuar sendo executado nos modos de sono mais profundo para fornecer uma fonte de ativação.
Analisarei alguns exemplos de dados, bem como algum código que usei (em C).
Arquivos e definições incluídos
Para começar, você provavelmente desejará incluir os dois arquivos de cabeçalho a seguir para que as coisas funcionem:
Além disso, eu uso a macro <_BV (BIT)> que é definida em um dos cabeçalhos padrão do AVR como a seguir (que pode ser mais familiar para você):
Quando o MCU é iniciado pela primeira vez, você normalmente inicializa a E / S, configura os temporizadores, etc. Em algum lugar aqui é um bom momento para garantir que o WDT não tenha causado uma redefinição porque poderia fazê-lo novamente, mantendo o programa em um loop instável.
Configuração WDT
Depois de configurar o restante do chip, refaça o WDT. A configuração do WDT requer uma "sequência programada", mas é realmente fácil de fazer ...
Obviamente, suas interrupções devem ser desativadas durante esse código. Certifique-se de reativá-los depois!
Rotina de serviço de interrupção WDT A próxima coisa a se preocupar é lidar com o WDT ISR. Isso é feito da seguinte maneira:
Em vez de colocar o MCU em repouso dentro do WDT ISR, recomendo simplesmente ativar o modo de suspensão no final do ISR e pedir ao programa PRINCIPAL que coloque o MCU em repouso. Dessa forma, o programa está realmente saindo do ISR antes que ele entre no modo de suspensão, e ele será ativado e retornará diretamente ao ISR do WDT.
WOW ... muito detalhado. Obrigado! Estou um pouco confuso com a seção sleep, onde você mostra o loop principal (se (MCUCR & _BV (SE)) {// Se o sono estiver ativado ... etc.) Estou confuso por que, na aparência principal, você desativar continuamente e ativar interrupções. E a parte na parte superior dessa seção (set_sleep_mode (SLEEP_MODE_PWR_DOWN);) Onde é que isso deve ser executado?
— 21713 Adam Haile
OK, a parte "set_sleep_mode (MODE)" deve estar na parte principal ANTES do loop principal, idealmente no outro código de inicialização em que você configura as portas de E / S, temporizadores, etc. Você realmente não precisa habilitar a opção_sleep (); nesse ponto, pois isso será feito após o seu primeiro gatilho WDT. DENTRO do loop principal, esse código de suspensão será executado apenas se a suspensão estiver ativada e não for totalmente necessário desativar / reativar as interrupções, apenas se você estiver executando o sleep_bod_disable (); Essa instrução IF inteira pode estar na parte inferior (mas ainda dentro) do loop MAIN após qualquer outro código que você estiver executando lá.
Ok ... isso faz mais sentido agora. Apenas última coisa que eu estou confuso sobre o que é essa "sequência temporizada" é ...
Nota lateral: Eu sei por que você gostaria de dormir, mas presumo que você não precise usar o WDT?
— 9118 Adam Haile #
Dê uma olhada nesta pequena seção da folha de dados: 8.4.1. Basicamente, para alterar o registro WDT, é necessário definir o bit de alteração e, em seguida, definir os bits WDTCR apropriados em tantos ciclos de clock. O código fornecido na seção Configuração do WDT faz isso ativando primeiro o bit de alteração do WD. E não, você não precisa usar a funcionalidade de suspensão com o WDT. Pode ser uma fonte de interrupção programada padrão por qualquer motivo que você desejar.
De acordo com a folha de dados, é possível. Você pode até ativar uma interrupção e a redefinição. Se os dois estiverem ativados, o primeiro tempo limite do watchdog acionará a interrupção, o que fará com que o bit Interrupt Enable seja desabilitado (interrupção desabilitada). O próximo tempo limite reiniciará sua CPU. Se você ativar a interrupção diretamente após a execução, o próximo tempo limite (novamente) acionará apenas uma interrupção.
Você também pode ativar a interrupção e não ativar a redefinição. Você precisará definir o bit WDIE toda vez que a interrupção for acionada.
Hmmm .... acho que faz sentido. Vou tentar. Eu sempre gosto de usar coisas para que eles não tinham a intenção :)
Na verdade, acho que é um design inteligente. Economiza um temporizador, mantendo a funcionalidade watchdog.
Esse tempo limite inicial do WDT e a interrupção subsequente também podem ser usados ​​com vantagem em alguns aplicativos que estão habilitando o WDT para a recuperação de interrupção real. Pode-se observar o endereço de retorno empilhado no WDT ISR para inferir o que o código estava tentando fazer quando ocorreu o "tempo limite inesperado".
Isso é muito mais fácil do que o sugerido acima e em outros lugares.
Desde que o WDTONfusível não esteja programado (não está programado por padrão), você precisará apenas ...
Defina o bit de ativação da interrupção do watchdog e o tempo limite no registro de controle do watchdog.
Ativar interrupções.
Aqui está um exemplo de código que executará um ISR uma vez a cada 16ms ...
É isso mesmo. Como nunca habilitamos a redefinição do watchdog, nunca precisamos mexer nas seqüências programadas para desativá-la. O sinalizador de interrupção do watchdog é limpo automaticamente quando o ISR é chamado.
Se você deseja um período diferente a cada 1 segundo, pode usar esses valores aqui para definir os bits apropriados em WDTCR...
Observe que você precisa executar a sequência cronometrada para alterar o tempo limite. Aqui está o código que define o tempo limite para 1 segundo ...
Não executar a sequência cronometrada durante a instalação salva uma linha de código - uma operação de leitura-modificação-gravação. A sequência inicial é recomendada na folha de dados "Se o Watchdog for ativado acidentalmente, por exemplo, por um ponteiro descontrolado ou condição de escurecimento" e o restante do meu código é específico para usar o WDT em combinação com um modo de suspensão, conforme solicitado por o OP. Sua solução não é mais simples, você apenas negligenciou o código recomendado / necessário da placa da caldeira.