Witam.
To mój pierwszy post na forum. Mam na Imię Bartek i, jako samouk, elektroniką zajmuję się czysto amatorsko i hobbystycznie.
Konstruuję spowalniacz do serw modelarskich, lecz napotkałem problem, z którym borykam się od dłuższego czasu. Aktualnie, aby zidentyfikować istotę problemu, "zdegradowałem" swoje docelowe rozwiązanie do następującej postaci (zmontowane na płytce uruchomieniowej):
Otóż problem jest następujący:
Za pomocą timera0 w ATtiny13 chcę mierzyć czas dodatniego impulsu pojawiającego się na nóżce odpowiadającej za INT0 mikrokontrolera. Aby podnieść rozdzielczość mierzonego czasu, timer wykonuje po kilka cykli. Docelowo będę mierzył ilość tych cykli, lecz na razie za każdym przepełnieniem timera przełączam stan na PB2. Także gdy występuje przerwanie na INT0 stan pinu PB2 jest przełączany (na przemian stan wysoki - stan niski). Ponieważ nie mam oscyloskopu, przebiegi rejestruję za pomocą wejścia LINE IN karty dźwiękowej komputera (wiem że powinienem podłączyć układ przez dzielnik 1:4, lecz myślę że obecne rozwiązanie nie ma wpływu na pracę układu i rezystory 1k w szeregu wystarczają). Niestety z zarejestrowanego przebiegu wynika, że timer nie zawsze się uruchamia, a gdy się już uruchamia to z dużym opóźnieniem (jako załącznik do tego postu dodałem pełny zarejestrowany przebieg w formacie wav):
Co może być tego przyczyną? Pewnie popełniłem jakiś "czeski" błąd lecz do tej pory go nie wychwyciłem i liczę na Waszą pomoc.
Oto plik Makefile którego używam:
oraz wsad do mikrokontrolera:
To mój pierwszy post na forum. Mam na Imię Bartek i, jako samouk, elektroniką zajmuję się czysto amatorsko i hobbystycznie.
Konstruuję spowalniacz do serw modelarskich, lecz napotkałem problem, z którym borykam się od dłuższego czasu. Aktualnie, aby zidentyfikować istotę problemu, "zdegradowałem" swoje docelowe rozwiązanie do następującej postaci (zmontowane na płytce uruchomieniowej):
Otóż problem jest następujący:
Za pomocą timera0 w ATtiny13 chcę mierzyć czas dodatniego impulsu pojawiającego się na nóżce odpowiadającej za INT0 mikrokontrolera. Aby podnieść rozdzielczość mierzonego czasu, timer wykonuje po kilka cykli. Docelowo będę mierzył ilość tych cykli, lecz na razie za każdym przepełnieniem timera przełączam stan na PB2. Także gdy występuje przerwanie na INT0 stan pinu PB2 jest przełączany (na przemian stan wysoki - stan niski). Ponieważ nie mam oscyloskopu, przebiegi rejestruję za pomocą wejścia LINE IN karty dźwiękowej komputera (wiem że powinienem podłączyć układ przez dzielnik 1:4, lecz myślę że obecne rozwiązanie nie ma wpływu na pracę układu i rezystory 1k w szeregu wystarczają). Niestety z zarejestrowanego przebiegu wynika, że timer nie zawsze się uruchamia, a gdy się już uruchamia to z dużym opóźnieniem (jako załącznik do tego postu dodałem pełny zarejestrowany przebieg w formacie wav):
Co może być tego przyczyną? Pewnie popełniłem jakiś "czeski" błąd lecz do tej pory go nie wychwyciłem i liczę na Waszą pomoc.
Oto plik Makefile którego używam:
# makefile written by Bartosz Kilian
MCU=attiny13
CC=avr-gcc
OBJCOPY=avr-objcopy
# options for programmer
PARTNO=t13
PROGRAMMER=stk200
FUSEBIT_L=0x79
FUSEBIT_H=0xFF
# optimize for size:
INCLUDEDIR=/usr/local/atmel/avr/include
CFLAGS=-mmcu=$(MCU) -Wall -Wstrict-prototypes -Os -mcall-prologues -I$(INCLUDEDIR)
#-------------------
all: main.hex
#-------------------
main.hex : main.out
$(OBJCOPY) -R .eeprom -O ihex main.out main.hex
main.out : main.o
$(CC) $(CFLAGS) -o main.out -Wl,-Map,main.map main.o
main.o : main.c
$(CC) $(CFLAGS) -Os -c main.c
main.asm:
$(CC) $(CFLAGS) main.c -S -o main.s
# you need to erase first before loading the program.
# load (program) the software into the eeprom:
load: main.hex
avrdude -p $(PARTNO) -c $(PROGRAMMER) -P /dev/parport0 -i 2 -U flash:w:main.hex -U lfuse:w:$(FUSEBIT_L):m -U hfuse:w:$(FUSEBIT_H):m
clean:
rm -f *.o *.map *.out
#-------------------
oraz wsad do mikrokontrolera:
/*********************************************
File : main.c
Author : Bartosz Kilian bkilian@interia.pl
Chip type : ATtiny13
Clock frequency : 4.8 MHz (set the value of define F_CPU)
*********************************************/
// defines section
// definitions for MCU Clock Frequency; adapt the MCU clock frequency in Hz to your target
#ifndef F_CPU
#define F_CPU 4800000UL
#endif
// includes section
// interrupts
#include <avr/interrupt.h>
// function bodies
/*************************************************************************
Interrupt: External Interrupt Request 0
Purpose: called when a change occurs on INT0 pin depending on ISC01 and ISC00 bits in MCUCR
**************************************************************************/
ISR(INT0_vect)
{
if (MCUCR & (1 << ISC00))
{ // The rising edge generated an interrupt request
// Reset counter register
TCNT0 = 0;
// Start counting
// set prescaler division factor
// CS00, CS01: select clock from prescaler: frequency = F_CPU / 8;
// at F_CPU=4.8MHz Tmin=0,00166ms Tmax = Tmin * 2^8 = 0,4266...ms
// T=1.0ms : TCNT0 = 2 timer cycles + 88
// T=1.5ms : TCNT0 = 3 timer cycles + 133
// T=2.0ms : TCNT0 = 4 timer cycles + 177
TCCR0B |= (1 << CS01);
//Set The falling edge of INT0 generates an interrupt request.
MCUCR &= (~(1 << ISC00));
}
else
{ // The falling edge generated an interrupt request
// Stop counting
TCCR0B &= (~(1 << CS01));
//Set The rising edge of INT0 generates an interrupt request.
MCUCR |= (1 << ISC00);
}
// toggle PORTB pin 2
PINB |= (1 << PINB2);
}
/*************************************************************************
Interrupt: Timer/Counter Overflow
Purpose: called when an overflow occurs in Timer/Counter0 (timer reaches TOP)
**************************************************************************/
ISR(TIM0_OVF_vect)
{
// toggle PORTB pin 2
PINB |= (1 << PINB2);
}
/*
* @brief Main function body
* @return none
*/
int main(void)
{
// Set Port B pin 2 as output
DDRB = (1 << DDB2);
// Enable pull-up resistor at Port B pin 1 input
PORTB |= (1 << PORTB1);
// Init Timer/Counter0
// COM0x1=0 and COM0x0=0 : Normal port operation, OC0A and OC1B disconnected.
// WGM02=0 and WGM01=0 and WGM00=0 : Timer/Counter Mode of Operation: Normal
// CS02=0 and CS01=0 and CS00=0 : Timer/Counter stopped
TCCR0A &= (~((1 << COM0A1) | (1 << COM0A0) | (1 << COM0B1) | (1 << COM0B0) | (1 << WGM01) | (1 << WGM00)));
TCCR0B &= (~((1 << WGM02) | (1 << CS02) | (1 << CS01) | (1 << CS00)));
// Init Interrupt on INT0
// Set The rising edge of INT0 generates an interrupt request.
MCUCR |= (1 << ISC01) | (1 << ISC00);
// External Interrupt Request 0 Enable
GIMSK |= (1 << INT0);
// Enable Interrupt on Timer/Counter Overflow
TIMSK0 |= (1 << TOIE0);
sei(); // enable interrupts
while(1);
return 0;
}
