Carregando Firmware na Placa
Um dos meus cuidados no projeto da placa foi garantir que todos os sinais necessários para a carga de firmware estivessem acessíveis no conector. O primeiro passo, portanto, foi fazer um cabo para ligação do meu ISBtinyISP (na verdade, qualquer carregador que tenha o conector padrão de 6 pinos):
Com o cabo feito, podemos fazer um teste rápido com o avrdude, confirmando que o ATtiny é reconhecido.
Felicidade é um Relé Pulsando
Para alimentar a placa e conectar as unidades é preciso um outro cabo:
O meu primeiro firmware é o equivalente a um LED piscando: um relé pulsando.
- #include <inttypes.h>
- #include <avr/io.h>
- #include <avr/interrupt.h>
- #include <avr/sleep.h>
- // Bits correspondentes aos pinos de E/S
- #define DDR_RELE DDRD
- #define PORT_RELE PORTD
- #define BIT_RELE _BV(PD5)
- // Programa Principal
- int main (void)
- {
- // Configura os pinos do rele
- DDR_RELE |= BIT_RELE;
- PORT_RELE &= ~BIT_RELE;
- // Configura o timer 0
- TCCR0A = 0; // Modo normal: overflow a cada 256 contagens
- TCCR0B = _BV(CS01) | _BV(CS00);// Usar clkIO/64: int a cada 64*256/16000 ms
- // = 1,024 ms
- TIMSK = _BV(TOIE0); // Interromper no overflow
- // Permite interrupções
- sei ();
- // Loop infinito
- for (;;)
- {
- set_sleep_mode(SLEEP_MODE_IDLE);
- sleep_mode();
- }
- }
- // Tratamento da interrupção do timer 0
- ISR (TIMER0_OVF_vect)
- {
- static uint16_t cntRele = 976;
- if (--cntRele != 0)
- return;
- cntRele = 976;
- PORT_RELE ^= BIT_RELE;
- }
Movendo a Cabeça
O segundo firmware testa os sinais de controle da unidade de disquete. O relê é usado para indicar quando ocorre a mudança de posição:
- #include <inttypes.h>
- #include <avr/io.h>
- #include <avr/interrupt.h>
- #include <avr/sleep.h>
- // Bits correspondentes aos pinos de E/S
- #define DDR_RELE DDRD
- #define PORT_RELE PORTD
- #define BIT_RELE _BV(PD5)
- #define DDR_DISQ DDRB
- #define PORT_DISQ PORTB
- #define PIN_DISQ PINB
- #define DIR_A _BV(PB7)
- #define STEP_A _BV(PB4)
- #define TRK0_A _BV(PB1)
- static uint8_t dirA = 1;
- static uint8_t stepA = 1;
- static uint8_t trkA = 79;
- // Programa Principal
- int main (void)
- {
- // Configura os pinos do rele
- DDR_RELE |= BIT_RELE;
- PORT_RELE &= ~BIT_RELE;
- // Configura os pinos de controle da unidade de disquete
- DDR_DISQ |= DIR_A | STEP_A; // DIR e STEP são saídas
- DDR_DISQ &= ~TRK0_A; // TRK0 é entrada
- PORT_DISQ |= DIR_A | STEP_A; // DIR e STEP em repouso no nível alto
- PORT_DISQ &= ~TRK0_A; // Sem pullup em TRK0
- // Configura o timer 0
- TCCR0A = 0; // Modo normal: overflow a cada 256 contagens
- TCCR0B = _BV(CS01) | _BV(CS00);// Usar clkIO/64: int a cada 64*256/16000 ms
- // = 1,024 ms
- TIMSK = _BV(TOIE0); // Interromper no overflow
- // Permite interrupções
- sei ();
- // Loop infinito
- for (;;)
- {
- set_sleep_mode(SLEEP_MODE_IDLE);
- sleep_mode();
- }
- }
- // Tratamento da interrupção do timer 0
- ISR (TIMER0_OVF_vect)
- {
- static uint8_t cntDisq = 100;
- if (--cntDisq == 0) // hora de mover
- {
- cntDisq = 100;
- PORT_DISQ ^= STEP_A; // pulsa STEP
- stepA ^= 1;
- if (stepA == 1) // andou um passo
- {
- if (dirA == 0) // avançando
- {
- if (++trkA == 79) // chegou ao fim
- {
- dirA = 1;
- PORT_DISQ |= DIR_A;
- PORT_RELE ^= BIT_RELE;
- }
- }
- else // recuando
- {
- if ((--trkA == 0) || ((PIN_DISQ & TRK0_A) == 0))
- { // chegou ao começo
- trkA = 0;
- dirA = 0;
- PORT_DISQ &= ~DIR_A;
- PORT_RELE ^= BIT_RELE;
- }
- }
- }
- }
- }
Ok, temos uma placa de controle funcionando! Agora é preciso fazer o firmware de controle e fazer o software que envia os comandos a partir do arquivo MIDI.
Nenhum comentário:
Postar um comentário