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); }O vídeo abaixo mostra o teste em uso, sofri um pouco com os botões.
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