O primeiro teste foi desligar os conectores KK (pois o display compartilha pinos com o conector de programação), conectar um programador e confirmar que o avrdude consegue conversar com o ATtiny.
![]() |
Nesta foto os conectores KK estão conectado, o display não influi muito no programador |
O segundo teste usa um software que aciona os LEDs e buzzer conforme o pressionamento dos botões. No display é apresentado 12:34. O display deu um pouco de trabalho, pois parti do código que eu fiz para o MSP430 e não percebi que lá eu estava enviando primeiro o bit menos significativo e no ATtiny a única opção é enviar primeiro o mais significativo. Percebido isto, foi só inverter os valores enviados ao display. O software ficou assim:
- #include <inttypes.h>
- #include <avr/io.h>
- #include <util/delay.h>
- // Bits correspondentes aos pinos de E/S
- #define TEC1 _BV(PB0)
- #define TEC2 _BV(PB1)
- #define LED1 _BV(PA0)
- #define LED2 _BV(PA1)
- #define LED3 _BV(PA2)
- #define LED4 _BV(PA3)
- #define BUZZER _BV(PA7)
- // Pinos para comunicação I2C
- #define DDR_USI DDRA
- #define PORT_USI PORTA
- #define PIN_USI PINA
- #define PORT_USI_SDA PORTA6
- #define PORT_USI_SCL PORTA4
- #define PIN_USI_SDA PINA6
- #define PIN_USI_SCL PINA4
- // Endereços dos registradores do TM1637
- #define TM1637_I2C_COMM1 0x02 //0x40
- #define TM1637_I2C_COMM2 0x03 //0xC0
- #define TM1637_I2C_COMM3 0x01 //0x80
- // Rotinas para comunicação I2C
- void I2C_Init (void);
- void I2C_Start (void);
- uint8_t I2C_Write (uint8_t b);
- void I2C_Stop (void);
- // Programa Principal
- int main (void)
- {
- int passo1 = 0;
- int passo2 = 0;
- // Configura o port A
- DDRA |= LED1 | LED2 | LED3 | LED4 | BUZZER;
- PORTA = 0;
- // Configura o port B
- DDRB &= ~(TEC1 | TEC2);
- PORTB = TEC1 | TEC2;
- // Inicia I2C
- I2C_Init();
- // Inicia o TM1637
- I2C_Start ();
- I2C_Write (TM1637_I2C_COMM1);
- I2C_Stop ();
- I2C_Start ();
- I2C_Write (TM1637_I2C_COMM2);
- I2C_Write (0x60);
- I2C_Write (0xDB);
- I2C_Write (0xF2);
- I2C_Write (0x66);
- I2C_Stop ();
- I2C_Start ();
- I2C_Write (TM1637_I2C_COMM3 | 0xF0);
- I2C_Stop ();
- // Loop infinito
- for (;;)
- {
- if ((PINB & TEC1) == 0)
- {
- // Apertou botão 1
- switch (passo1)
- {
- case 0: // Acende LED1
- PORTA |= LED1;
- passo1 = 1;
- break;
- case 1: // Apaga LED1, acende LED3
- PORTA &= ~LED1;
- PORTA |= LED3;
- passo1 = 2;
- break;
- case 2: // Apaga LED3
- PORTA &= ~LED3;
- passo1 = 0;
- break;
- }
- // Dá um bip
- PORTA |= BUZZER;
- _delay_ms (300);
- PORTA &= ~BUZZER;
- // Espera soltar a tecla
- while ((PINB & TEC1) == 0)
- ;
- _delay_ms (100); // debounce
- }
- if ((PINB & TEC2) == 0)
- {
- // Apertou botão 2
- switch (passo2)
- {
- case 0: // Acende LED2
- PORTA |= LED2;
- passo2 = 1;
- break;
- case 1: // Apaga LED2, acende LED4
- PORTA &= ~LED2;
- PORTA |= LED4;
- passo2 = 2;
- break;
- case 2: // Apaga LED4
- PORTA &= ~LED4;
- passo2 = 0;
- break;
- }
- // Dá um bip
- PORTA |= BUZZER;
- _delay_ms (300);
- PORTA &= ~BUZZER;
- // Espera soltar a tecla
- while ((PINB & TEC2) == 0)
- ;
- _delay_ms (100); // debounce
- }
- }
- }
- // Inicia a USI no modo I2C
- void I2C_Init ()
- {
- USIDR = 0xFF;
- USICR = _BV(USIWM1) | _BV(USICS1) | _BV(USICLK); // Sem interrupções
- // Modo TWI
- USISR = _BV(USISIF) | _BV(USIOIF) | // Limpa flags e zera contador
- _BV(USIPF) | _BV(USIDC);
- DDR_USI |= _BV(PIN_USI_SDA) | _BV(PIN_USI_SCL); // colocar como saída
- PORT_USI |= _BV(PIN_USI_SDA) | _BV(PIN_USI_SCL); // repouso = high (solto)
- }
- // Sinaliza Start
- void I2C_Start ()
- {
- PORT_USI |= _BV(PIN_USI_SCL); // Solta SCL
- while ((PIN_USI & _BV(PIN_USI_SCL)) == 0) // Espera SCL alto
- ;
- _delay_us (4);
- PORT_USI &= ~_BV(PIN_USI_SDA); // Baixa SDA
- _delay_us (4);
- PORT_USI &= ~_BV(PIN_USI_SCL); // Baixa SCL
- PORT_USI |= _BV(PIN_USI_SDA); // Solta SDA
- }
- // Envia um uint8_t e lê o ACK ou NAK
- uint8_t I2C_Write (uint8_t b)
- {
- uint8_t temp;
- PORT_USI &= ~_BV(PIN_USI_SCL); // Baixa SCL
- USIDR = b; // Coloca dado no shift register
- USISR = _BV(USISIF) | _BV(USIOIF) | // Limpa flags e zera contador
- _BV(USIPF) | _BV(USIDC);
- do
- {
- _delay_us (4);
- USICR |= _BV(USICLK) | _BV(USITC); // Pulsa clock p/ cima
- while ((PIN_USI & _BV(PIN_USI_SCL)) == 0) // Espera SCL subir
- ;
- _delay_us (4);
- USICR |= _BV(USICLK) | _BV(USITC); // Pulsa clock p/ baixo
- } while ((USISR & _BV(USIOIF)) == 0); // Repete para todos os bits
- _delay_us (4);
- USIDR = 0xFF; // Solta SDA
- DDR_USI &= ~_BV(PIN_USI_SDA); // SDA passa a ser entrada
- USISR = _BV(USISIF) | _BV(USIOIF) | // Limpa flags e inicia contador
- _BV(USIPF) | _BV(USIDC) | // para ler 1 bit
- (0xE<<USICNT0);
- do
- {
- _delay_us (4);
- USICR |= _BV(USICLK) | _BV(USITC); // Pulsa clock p/ cima
- while ((PIN_USI & _BV(PIN_USI_SCL)) == 0) // Espera SCL subir
- ;
- _delay_us(4);
- USICR |= _BV(USICLK) | _BV(USITC); // Pulsa clock p/ baixo
- } while ((USISR & _BV(USIOIF)) == 0); // Repete para todos os bits
- temp = USIDR; // Lê a resposta
- USIDR = 0xFF; // Solta SDA
- DDR_USI |= _BV(PIN_USI_SDA); // SDA passa a ser saída
- return temp;
- }
- // Sinaliza Stop
- void I2C_Stop ()
- {
- PORT_USI &= ~_BV(PIN_USI_SDA); // Baixa SDA
- PORT_USI |= _BV(PIN_USI_SCL); // Solta SCL
- while ((PIN_USI & _BV(PIN_USI_SCL)) == 0) // Espera SCL alto
- ;
- _delay_us (4);
- PORT_USI |= _BV(PIN_USI_SDA); // Solta SDA
- _delay_us (4);
- }
Finalizada a montagem e os testes, é hora de fazer o software definitivo. Isto fica para o próximo post.
Nenhum comentário:
Postar um comentário