Estou tentando usar o microcontrolador Timer1 do Atmel AVR, o AtMega328, usado no Arduino ou no ATTiny85, para emitir dois sinais de relógio que são imagens espelhadas um do outro. A frequência que estou tentando gerar é uma variável de 1 MHz a 2 MHz ou mais, que é muito alta para fazer isso usando o código para alternar os pinos de saída, a menos que eu queira fazer quase nada mais no controlador. Então, eu quero usar a saída do timer diretamente nos pinos associados. Estou usando o conjunto de ferramentas GCC, portanto não limitado por bibliotecas ou idioma do arduino.
O Timer1 no Atmega328 possui dois pinos associados e posso obter dois sinais idênticos de 1MHz a 2MHz. Embora a folha de dados pareça dizer que posso obter uma forma de onda invertida, ela está me confundindo. Também consigo obter dois sinais com ciclos de trabalho diferentes a 1 MHz, usando as configurações de PWM com Timer1, mas ambos os sinais aumentam ao mesmo tempo, o menor diminui mais cedo. Isso não serve ao meu projeto. Eu nem preciso da variação da largura de pulso PWM, só preciso de dois sinais idênticos do tipo "relógio" de fase oposta, isso é tudo.
Não estou pedindo que alguém escreva código para fazer isso, só preciso que alguém me diga qual modo / sinalizadores do timer devem fornecer uma forma de onda invertida simples em um dos dois pinos associados ao timer. Se possível, quero evitar o uso de um circuito inversor externo para uma das saídas, a menos que seja a única opção.
Se isso for possível no ATTiny, será ainda melhor. O ATTiny também possui 2 pinos associados a um timer, mas não tenho certeza de que tenha as mesmas opções que o ATMega.
Eu já tenho um cristal de 20 MHz e os capacitores conectados no PCB e o relógio de 20 MHz está funcionando de maneira confiável no ATMega328. No PCB ATTiny85, tenho um cristal de 8 MHz e isso também está funcionando de maneira confiável.
Por favor ajude. Obrigado.
ATUALIZAÇÃO : Existem algumas suposições inválidas nas respostas e comentários até agora, então talvez eu deva esclarecer: Observe que na minha postagem original afirmei que estou usando um relógio de 20 MHz, não 8 MHz , e também que não preciso de PWM .
O único modo que fornece uma frequência de saída suficientemente alta parece ser o modo CTC porque os modos PWM não estão funcionando para saída de 2 MHz. Existe uma maneira de inverter a saída A do temporizador 1 ou a saída B no modo CTC?
Agora mudei para um Arduino Uno padrão (ATMega328, 16 MHz) em vez de minha própria placa de 20 MHz para verificar meu código, e este é o meu código para um bom e estável relógio de 2 MHz no modo CTC dos pinos 9 e 10, o Timer 1 pinos de saída:
#define tick 9
#define tock 10
void setup() {
pinMode(tick, OUTPUT);
pinMode(tock, OUTPUT);
TCCR1A = _BV(COM1A0) | _BV(COM1B0) ; // activate both output pins
TCCR1B = _BV(WGM12)| 1; // set CTC mode, prescaler mode 1
// various frustrating attempts to invert OC1B failed. What do I put here?
OCR1A = 3; // set the counter max for 2 MHz
}
void loop() {
}
Os traços do osciloscópio para os dois pinos são idênticos e sincronizados. Como posso inverter um dos dois sinais? O modo invertido na folha de dados parece não fazer nada no modo CTC. Estou lendo a folha de dados incorretamente ou serei forçado a usar uma frequência mais baixa e o modo PWM, afinal?
Para adicionar uma pergunta específica de "recompensa" à minha consulta original:
Então, quais alterações eu preciso fazer no meu código acima, para que ele produza sinais perfeitamente invertidos nos pinos 9 e 11 na frequência mais alta possível para um relógio de 16 MHz , seja isso é 2 MHz ou não?
Por enquanto, continuarei com um Arduino Uno padrão, para que não haja um modo de erro sendo introduzido pela minha placa caseira, e para que qualquer pessoa com um arduino possa experimentar o meu código acima e confirmar que funciona como eu mencionei e não como eu. precisar!
Respostas:
Da folha de dados do ATtiny85:
A Tabela 11-5 mostra como definir o modo.
Você deseja um modo Fast PWM (modo 3 ou 7). Se você deseja alterar o ciclo de serviço, e isso soa como você deseja, você deseja o modo 7 e varia o ciclo de trabalho configurando OCRA.
A Tabela 11-3 mostra como definir o modo de saída de comparação para o modo Fast PWM.
Ou seja, você pode configurar a saída OC0A para baixa quando o valor do Timer == OCR0A e alta quando o valor do Timer == 0x00 configurando COM0A1: COM0A0 = 0b10. Ou vice-versa, definindo COM0A1: COM0A0 = 0b11. E da mesma forma para OC0B, OCR0B, COM0B0, COM0B1.
A frequência PWM é determinada pelo I / O Clock (8MHz soa para você) e pela configuração do seu pré-temporizador. E a equação é dada como f_clk_IO / (N * 256) para o modo Fast PWM.
Portanto, você pode usar OC0A para polaridade "normal" e OC0B para polaridade "invertida" configurando OCR0A e OCR0B para o mesmo valor e configurando COM0A1: COM0A0 = 0b10 e COM0B1: COM0B0 para 0b11.
ATUALIZAR
Como você deseja alternar a saída o mais rápido possível e estiver usando o Mega328 operando em 16 MHz, o modo de operação CTC permitirá obter uma frequência de comutação de:
f_OCnA = f_clk_IO / (2 * N * [1 + OCRnA) = 16e6 / (2 * 1 * [1 + 1]) = 4 MHz
O modo Fast PWM permite alternar o pino em:
f_OCnxPWM = f_clk_IO / (N * [1 + TOP]) = 16e6 / (1 * [1 + 1]) = 8MHz
Então, eu ainda acho que você quer o modo Fast PWM. Especificamente o Modo 3 com OCR0A = OCR0B = 0x80 para um ciclo de trabalho de 50%. E defina os bits COM0A para 0x3 e os bits COM0B para 0x2 para criar as duas formas de onda nas inversões OC0A e OC0B.
Atualização # 2 Mais o Mega328 Experimente o código do Arduino:
fonte
A família ATtinyX5 tem PLL por dentro, use-o como garotão.
Eu uso o PLL interno para alimentar o clock da CPU também e tenho 16Mhz sem o XTAL. Isso é precioso, pois você tem apenas 5 pinos. (Não conto o pino de redefinição). Também um PWM com PLL (OCR1B) é executado nos pinos XTAL com sua saída complementar opcional. Você só precisa ajustar os fusíveis para 16Mhz Xtalless ATtiny ... Ou apenas deixar a CPU rodar em 8Mhz, mas rodar o PWM com um relógio de 64Mhz sem trocar os fusíveis.
Você pode ter um relógio PWM de até 64 Mhz (mas com resolução de 1 bit). Ou 125Khz a 8 bits de resolução. Você pode reduzir a resolução PWM e aumentar a velocidade diminuindo o registro OCR1C.
Para 1 Mhz, você precisa definir OCR1C para 63. Para 2 Mhz, você precisa definir OCR1C para 31. Para 4 Mhz, você precisa definir OCR1C para 15. ...
Basta ativar a PLL com este código:
Agora você tem um relógio de 64 MHz nos PWMs "OCR1B0 / OCR1A0".
Além disso, você pode ajustar OCR1 [A / B] 0 e XOCR1 [A / B] 0 para saída espelhada.
Você precisa saber, o Dead Time Generator interromperá o PWM se você definir OCR1A = 1. Você precisa de valores mais altos que o tempo morto.
Saudações,
Erdem
fonte