ATmega, Serial e 74HC595 - parte 2

Na postagem anterior mostrei a primeira forma do programa, nesta aqui no lugar dos delays (_delay_ms), usei o timer para gerar o clock para o HC595 e tratar os pulsos do byte e o latch. O ATMega382p possui três timers, dois de 8 bits e um de 16 bits, usei o de 16 bits apenas para manter as mesmas portas do programa anterior, já que usei o modo CTC (Clear Timer on Compare Match) para o clock e no timer de 16 bits ele usa a porta PB1 (OC1A) no pino 15 do CI. O OCR1A é o registrador onde é setado o valor que irá definir a frequência dos pulsos de saída gerado na porta PB1 (OC1A), para o timer de 16 bits este valor vai de 0 a 65535, para o de 8 bits logicamente de 0 a 255.
Neste modo CTC o contador vai  para 0 quando atingir o valor do OCR1A na subida do contador TCNT1 (Timer/Counter). Quanto menor este valor, menor o período e consequentemente maior a frequência, conforme a figura do datasheet abaixo:



Para este caso foi usado o clock padrão de fabrica de 1Mhz para o micro controlador e foi deixado o prescaler em 1. Para se encontrar qual a frequência que será gerada para o clock na porta PB1 em modo CTC é usada a formula abaixo retirada do datasheet:



Onde:

  • fOCnA será a frequência desejada
  • fclk é a frequência do clock (1Mhz)
  • N é o prescaler (1)
  • OCRnA foi usado 200.
Desta forma ficou uma frequência de 2487hz e período de 400ms para o OCR1A em 200. O HC595 segundo o datasheet, trabalha com uma frequência máxima em torno de 50Mhz, portanto a frequência utilizada está de acordo.

Para os pulsos dos dados ( 8 bits) foi usado a mesma ideia do código anterior (serialCaractere & 0b10000000), porem agora usando uma interrupção para cada bit. A interrupção usada é por comparação, desta forma a cada subida e a cada descida dos pulsos gerados no CTC em OC1A é gerada uma interrupção, mas para o HC595 trabalhar é necessário um bit ( 0 ou 1) somente na subida do pulso de clock, assim foi usado o artifício “if(contador%2 ==  0)” onde os bits são enviados na porta PB0 apenas na subida, ou valores pares para variável contador. Por fim no 16º pulso, ou oitavo de subida, é enviado na porta PB2 o pulso de subida de latch e na próxima interrupção (17ª) o de descida.

Para a interrupção funcionar é preciso setar no registrador TIMSK1, o bit OCIE1A que corresponde a interrupção por comparação “A”; CTC está setado para OC1A, lembra acima? Para habilitar a interrupção usa-se o sei(). Na função principal o comparador “if (comparador != serialCaracter)”, serve para as interrupções ocorrerem somente após ser digitado um novo valor e serem encerradas após o oitavo bit seguido do latch. As configurações do timer são bem simples e estão comentadas no código, o datasheet é uma boa fonte de informação sobre este assunto.




Na terceira e ultima parte do código a única diferença vai para a linha onde foi trocado o “if (serialCaractere & 0b10000000)” por “if (bit_is_set(serialCaractere, 7)”. O bit_is_set é uma macro que retorna verdadeiro caso o bit ( 0 a 7) definido esteja em 1 no byte. Exemplo, para bit_is_set(0b11010001, 5) irá retornar verdadeiro já que o 5º bit é um, já para bit_is_set(0b11010001, 4) irá retornar falso já que o 4º bit é 0.

Abaixo segue os dois códigos completos e o makefile.
Para rodar o makefile abra este arquivo, comente ou retire o comentário (#) desejado na parte MAIN = Serial_HC595_v1.c, selecione a interface usada em PROGRAMER_TYPE e a porta em PROGRAMER_ARGS caso não seja um USBASP. Depois basta rodar make flash, estando tudo na mesma pasta.


Referencias:
Make: AVR Programming
http://extremeelectronics.co.in/avr-tutorials/using-shift-registers-with-avr-micro-avr-tutorial/

Comentários