Data hosted with ♥ by Pastebin.com - Download Raw - See Original
  1. /////////////////////////////////////////////////////////////////////////////////////////////////////
  2. // Serial e HC595 v3                                                                               //
  3. // Desenvolvido por Ronaldo R. Jr                                                                  //
  4. // 12/2015                                                                                         //
  5. // naldin.net at gmail                                                                             //
  6. // Referências:                                                                                    //
  7. // Livro Make: AVR Programming, Elliot Williams                                                    //
  8. // Web:                                                                                            //
  9. // http://extremeelectronics.co.in/avr-tutorials/using-shift-registers-with-avr-micro-avr-tutorial //
  10. /////////////////////////////////////////////////////////////////////////////////////////////////////
  11.  
  12. // ATMega328p trabalhando em 1Mhz
  13.  
  14. #include <avr/io.h>
  15. #include <util/delay.h>
  16. #include <util/setbaud.h>
  17. #include <avr/interrupt.h>
  18.  
  19. #define BAUD  9600               // setar o valor desejado
  20.  
  21. #define HC595_PORT   PORTB       // Definindo portas B
  22. #define HC595_DDR    DDRB        // Definindo direção das portas
  23.  
  24. #define HC595_DS_POS PB0         //Pino de dados (DS)
  25. #define HC595_SH_CP_POS PB1      // Pino do Clock (SH_CP)
  26.                                  // O clock está em PB1 setado pelo Timer1 modo CTC para OC1A
  27. #define HC595_ST_CP_POS PB2      //Pino do Latch (ST_CP)
  28.  
  29.  
  30. // Definindo variaveis
  31. uint8_t serialCaractere = 0xFF;
  32. uint8_t comparador = 0;
  33. int contador = 0;
  34.  
  35. // Configurando o clock e interrupção
  36. void ligaClock(void){
  37.     TCCR1A |= (1 << COM1A0);             // Modo alternado
  38.     TCCR1B |= (1 << WGM12);              // Modo CTC em OC1A (PB1)
  39.     TCCR1B |= (1 << CS10);               // Prescaler = 1
  40.     TIMSK1 |= (1 << OCIE1A);             // Habilita interrupcao de saida por comparacao
  41.    
  42.     sei(); // Habilita interrupção
  43. }
  44.  
  45. /*** Inicio tratamento serial ***/
  46.  
  47. // Setup da serial
  48. void iniciaUSART(void) {             // Necessario setar BAUD acima
  49.   UBRR0H = UBRRH_VALUE;              // Ja esta definido em setbaud.h
  50.   UBRR0L = UBRRL_VALUE;              // Ja esta definido em setbaud.h
  51.  
  52. // Habilita TX e RX da USART
  53.   UCSR0B = (1 << TXEN0) | (1 << RXEN0);
  54.   UCSR0C = (1 << UCSZ01) | (1 << UCSZ00);   // 8 bits de dados, 1 bit de parada
  55.  
  56.   #if USE_2X
  57.     UCSR0A |= (1 << U2X0);
  58.   #else
  59.     UCSR0A &= ~(1 << U2X0);
  60.   #endif
  61. }
  62.  
  63. void enviaByte(uint8_t dado) {
  64.   loop_until_bit_is_set(UCSR0A, UDRE0);      // Aguardar bit para enviar
  65.   UDR0 = dado;                               // Envia dado
  66. }
  67.  
  68. uint8_t recebeByte(void) {
  69.   loop_until_bit_is_set(UCSR0A, RXC0);       // Aguarda chegada de dados
  70.   return UDR0;                               // Retorna o dado em recebeByte
  71. }
  72.  
  73. void imprimeString(const char valorS[]) {    // Imprime uma palavra ou letra
  74.   uint8_t i = 0;
  75.   while (valorS[i]) {
  76.     enviaByte(valorS[i]);
  77.     i++;
  78.   }
  79. }
  80.  
  81. // Recebe na serial um numero que tenha mais de um caracter e concatena.
  82. // A serial envia apenas um caracter por vez, portanto para enviar 123 é enviado 1, depois 2, depois 3.
  83. // Esta função concatena os numeros e retona em um byte (uint8_t)
  84. uint8_t recebeNumero(void) {
  85.   char centenas = '0';
  86.   char dezenas = '0';
  87.   char unidades = '0';
  88.   char valorAtual = '0';
  89.   do {
  90.     centenas = dezenas;
  91.     dezenas = unidades;
  92.     unidades = valorAtual;
  93.     valorAtual = recebeByte();
  94.     enviaByte(valorAtual);
  95.   } while (valorAtual != '\r');   // aguarda o enter para continuar
  96.   return (100 * (centenas - '0') + 10 * (dezenas - '0') + unidades - '0');
  97. }
  98.  
  99. // Envia para serial o numero em decimal.
  100. // Para visualizar na serial um numero enviado 123 (ex.), é necessario separar cada caracter,
  101. // se for enviado o byte 123 a serial recebera o caracter { que é  o valor ascii convertido.
  102. void printByte(uint8_t byte) {           // Converte um byte em um texto decimal
  103.   enviaByte('0' + (byte / 100));         // Centenas
  104.   enviaByte('0' + ((byte / 10) % 10));   // Dezenas
  105.   enviaByte('0' + (byte % 10));          // Unidades
  106. }
  107.  
  108. /*** Fim tratamento serial ***/
  109. //=========================================================================//
  110. /*** Inicio tratamento HC595 ***/
  111.  
  112. // Setando saidas para Data(DS), Clock (SH_CP), Latch (ST_CP)
  113. void PortaOn(void) {
  114.    DDRB |= (1 << HC595_SH_CP_POS) | (1 << HC595_ST_CP_POS) | (1 << HC595_DS_POS);
  115. }
  116.  
  117. // Desabilitando portas
  118. void PortaOff(void) {
  119.    DDRB &= ~ (1 << HC595_SH_CP_POS) | (1 << HC595_ST_CP_POS) | (1 << HC595_DS_POS);
  120. }
  121.  
  122. // Enviando 8 bits serialmente
  123. void BitsHC595(void){
  124.     if(contador%2 == 0) {   // Somente envia os bits no contador de valor par. Na subida dos pulsos de clock
  125.         if (bit_is_set(serialCaractere, 7)){   // Se o oitavo (0 a 7) bit for 1 saida = high (1)
  126.          
  127.               HC595_PORT |= (1 << HC595_DS_POS);
  128.           }
  129.           else {                  // Senao saida = low (0)
  130.          
  131.               HC595_PORT &= ~(1 << HC595_DS_POS);
  132.           }
  133.           serialCaractere = serialCaractere << 1;  // Move o bit em direção ao MSB
  134.      }
  135.      
  136.      if (contador == 16){   // No pulso 16 do clock coloca a porta em 1 para o latch
  137.           HC595_PORT |= (1 << HC595_ST_CP_POS);
  138.      }
  139.      if (contador == 17){   // No pulso 17 do clock coloca a porta em 0 para o latch
  140.           HC595_PORT &= ~(1 << HC595_ST_CP_POS);
  141.           PortaOff();        // Desliga todas as portas
  142.           comparador = serialCaractere;   // Iguala comparador com valor atual e para interrupcoes
  143.      }
  144.      contador++;
  145. }
  146.  
  147. // Envia 1 bit em cada interrupção
  148. ISR(TIMER1_COMPA_vect) {
  149.       BitsHC595();
  150. }
  151.  
  152. /*** Fim tratamento HC595 ***/
  153.  
  154. int main(void) {
  155.     ligaClock();           // Inicializa o clock para HC595
  156.     iniciaUSART();         // Inicializa serial
  157.     imprimeString("Digite um valor entre 0 e ");
  158.    
  159.     while(1){
  160.         if (comparador != serialCaractere){  // Compara valor digitado com valor anterior
  161.             PortaOn();                       // Habilita as portas
  162.             OCR1A = 200;                     // Define frequencia do clock para HC 595. Em 200 periodo de 400uS freq 2500hz.
  163.             contador = 0;
  164.         }
  165.         printByte(serialCaractere);          // Imprime numero
  166.         imprimeString("\n");                 // Nova linha
  167.         serialCaractere = recebeNumero();    // Aguarda novo numero e grava em serialCaractere
  168.     }
  169. }