Witam.
Pisze program sterujący pracą silników krokowych. Pisałem cały czas tak program by mieć konktrolę nad prędkością każdego z silników osobno (chodzi o to że silniki mają różne przekładnie a chce by wszytskie elementy poruszały się z tą samą prędkością obrotową więc prędkość ustala się raz w programie i się jej później nie zmienia)
Zastosowałem przerwanie w którym są 4 wartości są to takie liczniki które liczą w górę i jeden za każdym przerwaniem jeżeli konkretny licznik osiągnie założoną wartość mozna wykonać przełączenie tranzystorów i tym samym poruszyć silnikiem. Na początek przerwania wpisuję liczbę do licznika który wywołuje to przerwanie luczniki jest 8-bitowy więc żeby przerwanie wywoływało się przykładowo co 200 µs wpisałem na początek do licznika TCNT0 = 54; niestety jeżeli ustawię wartość mniejszą niż 218 program nie działa to znaczy przerwanie się wykonuje ale chyba nie wykonywana jest dalsza część programu nie wiem dlaczego? podajce cały kod programu:
Dodano po 1 [godziny] 36 [minuty]:
Odkryłem coś jeszcze bardziej dziwnego, podłączyłem sobie oscyloskop by sprawdzić co się dzieje wewnątrz tego przerwania. Wstawiłem do wewnątrz przerwania komendę odpowiedzialną za zmianę stanu jednego z wyjść nazwałem to LED_TOGGLE , bo początkowo była tam dioda
ale ja podłaczyłem tam oscyloskop i dla powtewierdzenia wyniki również częstotliwościomierz. I wyniki są bardzo dziwne !!
Zmianiałem początkową wartość timera czyli wpisywałem różne wartości do TCNT0, no i tu wielkie zaskoczenie bo wraz ze wzrostem wartośi poczatkowej licznika przerwanie powinno wykonywać się coraz częściej bo bliżej było do przepełnienia a tu zaskoczenie bo zmieniałem wartość TCNT0 i nic się nie zmieniało zawsze wychodziło że stan wysoki (lub niski nieważne) trwa 255µs aż do wartości TCNT0=211 jak wpisałem TCNT0=212 to wartość ta od razu zmniejszyła się do 65µs czy ktoś możne mi wyjaśnić dlaczego tak się dzieje? 65µs nie zmieniało się aż do wartości maksymalnej czyli TCNT0=255
Pisze program sterujący pracą silników krokowych. Pisałem cały czas tak program by mieć konktrolę nad prędkością każdego z silników osobno (chodzi o to że silniki mają różne przekładnie a chce by wszytskie elementy poruszały się z tą samą prędkością obrotową więc prędkość ustala się raz w programie i się jej później nie zmienia)
Zastosowałem przerwanie w którym są 4 wartości są to takie liczniki które liczą w górę i jeden za każdym przerwaniem jeżeli konkretny licznik osiągnie założoną wartość mozna wykonać przełączenie tranzystorów i tym samym poruszyć silnikiem. Na początek przerwania wpisuję liczbę do licznika który wywołuje to przerwanie luczniki jest 8-bitowy więc żeby przerwanie wywoływało się przykładowo co 200 µs wpisałem na początek do licznika TCNT0 = 54; niestety jeżeli ustawię wartość mniejszą niż 218 program nie działa to znaczy przerwanie się wykonuje ale chyba nie wykonywana jest dalsza część programu nie wiem dlaczego? podajce cały kod programu:
#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>
#include <avr/signal.h>
/////// SILNIK 1 ////////////////
#define TRA0_ON PORTB |= _BV(0);
#define TRA0_OFF PORTB &= ~_BV(0);
#define TRA1_ON PORTB |= _BV(1);
#define TRA1_OFF PORTB &= ~_BV(1);
#define TRA2_ON PORTB |= _BV(2);
#define TRA2_OFF PORTB &= ~_BV(2);
#define TRA3_ON PORTB |= _BV(3);
#define TRA3_OFF PORTB &= ~_BV(3);
/////// SILNIK 2 ////////////////
#define TRA4_ON PORTB |= _BV(4);
#define TRA4_OFF PORTB &= ~_BV(4);
#define TRA5_ON PORTB |= _BV(5);
#define TRA5_OFF PORTB &= ~_BV(5);
#define TRA6_ON PORTB |= _BV(6);
#define TRA6_OFF PORTB &= ~_BV(6);
#define TRA7_ON PORTB |= _BV(7);
#define TRA7_OFF PORTB &= ~_BV(7);
/////// SILNIK 3 ////////////////
#define TRA8_ON PORTD |= _BV(0);
#define TRA8_OFF PORTD &= ~_BV(0);
#define TRA9_ON PORTD |= _BV(1);
#define TRA9_OFF PORTD &= ~_BV(1);
#define TRA10_ON PORTD |= _BV(2);
#define TRA10_OFF PORTD &= ~_BV(2);
#define TRA11_ON PORTD |= _BV(3);
#define TRA11_OFF PORTD &= ~_BV(3);
///// LEDY //////
#define LED_ON PORTC |= _BV(0);
#define LED_OFF PORTC &= ~_BV(0);
#define LED_TOGGLE PORTC ^= _BV(0);
volatile uint16_t overflow_ADC=0;
volatile uint8_t overflow1=0;
volatile uint8_t overflow2=0;
volatile uint8_t overflow3=0;
volatile uint16_t overflow_ADC_max=500;
volatile uint8_t overflow1_max=200;
volatile uint8_t overflow2_max=10;
volatile uint8_t overflow3_max=30;
volatile char sw0=0;
volatile char sw1=0;
volatile char sw2=0;
volatile char sw3=0;
volatile char sw4=0;
volatile char sw5=0;
volatile uint16_t value;
SIGNAL (SIG_OVERFLOW0)
{
TCNT0 = 54; // Załaduj wartość początkową do timera0 218
overflow1++;
overflow2++;
overflow3++;
overflow_ADC++;
LED_TOGGLE;
}
int main (void)
{
ADCSRA = _BV(ADEN)|_BV(ADIE)|_BV(ADSC)|_BV(ADPS0)|_BV(ADPS1)|_BV(ADATE); // ustaw przetwornik ADC
DDRA = 0; // Ustawienie rejestru A jako wejście (PRZYCISKI)
DDRB = 255; // Ustawienie rejestru B jako wyjście na silnik
DDRD = 255; // Ustawienie rejestru D jako wyjście na silniki
DDRC = 255; // Ustawienie rejestru C jako wyjście LED
TIMSK = _BV(TOIE0); // włącz obsługę przerwań wywołane timerem 0
unsigned char stan1 = 3;
unsigned char stan2 = 3;
unsigned char stan3 = 3;
unsigned int value; // zmienna przechowująca stan wyjścia przetwornika ADC
unsigned int zakres=150; // wartośc po jakiej ma nastąpić załączenie
TCCR0 |= (1 << CS00); //Ustawia timer0 bez preskalera
ADMUX = 0; // wybierz kanał 0 przetwornika ADC
sei(); // włącz obsługę przerwań
while(1) // Program główny
{
//////////////////////////////////////////////////// Sprawdzanie przetwornika ADC ///////////////////////
if(overflow_ADC>=overflow_ADC_max)
{
ADMUX = 0; // wybierz kanał 0 przetwornika ADC
value = ADCW;
if(value<=zakres)
{
sw0=1;
sw1=0;
}
else
{
if(value>=1023-zakres)
{
sw0=0;
sw1=1;
}
else
{
sw0=0;
sw1=0;
}
}
ADMUX = 1; // wybierz kanał 1 przetwornika ADC
value = ADCW;
if(value<=zakres)
{
sw2=1;
sw3=0;
}
else
{
if(value>=1023-zakres)
{
sw2=0;
sw3=1;
}
else
{
sw2=0;
sw3=0;
}
}
ADMUX = 2; // wybierz kanał 2 przetwornika ADC
value = ADCW;
if(value<=zakres)
{
sw4=1;
sw5=0;
}
else
{
if(value>=1023-zakres)
{
sw4=0;
sw5=1;
}
else
{
sw4=0;
sw5=0;
}
}
overflow_ADC=0;
}
//////////////////////////////////////////////////// SILNIK 1 ///////////////////////
if(overflow1>=overflow1_max) // silnik 1
{
if(sw1 != 0) //jeżeli przycisk 1 wciśnięty //jeżeli przycisk 1 wciśnięty
{
stan1++;
if(stan1==5)
stan1=1;
}
if(sw0 != 0) //jeżeli przycisk 1 wciśnięty //jeżeli przycisk 1 wciśnięty
{
stan1--;
if(stan1==0)
stan1=4;
}
switch(stan1)
{
case 1 :
TRA0_ON;
TRA1_OFF;
TRA2_OFF;
TRA3_OFF;
break;
case 2 :
TRA0_OFF;
TRA1_OFF;
TRA2_ON;
TRA3_OFF;
break;
case 3 :
TRA0_OFF;
TRA1_ON;
TRA2_OFF;
TRA3_OFF;
break;
case 4 :
TRA0_OFF;
TRA1_OFF;
TRA2_OFF;
TRA3_ON;
break;
}
overflow1=0;
}
//////////////////////////////////////////////////// SILNIK 2 ///////////////////////
if(overflow2>=overflow2_max) // silnik 2
{
if(sw2 != 0) //jeżeli przycisk 1 wciśnięty
{
stan2++;
if(stan2==5)
stan2=1;
}
if(sw3 != 0) //jeżeli przycisk 1 wciśnięty
{
stan2--;
if(stan2==0)
stan2=4;
}
switch(stan2)
{
case 1 :
TRA4_ON;
TRA5_OFF;
TRA6_OFF;
TRA7_OFF;
break;
case 2 :
TRA4_OFF;
TRA5_OFF;
TRA6_ON;
TRA7_OFF;
break;
case 3 :
TRA4_OFF;
TRA5_ON;
TRA6_OFF;
TRA7_OFF;
break;
case 4 :
TRA4_OFF;
TRA5_OFF;
TRA6_OFF;
TRA7_ON;
break;
}
overflow2=0;
}
//////////////////////////////////////////////////// SILNIK 3 ///////////////////////
if(overflow3>=overflow3_max) // silnik 3
{
if(sw4 != 0)
{
stan3++;
if(stan3==5)
stan3=1;
}
if(sw5 != 0)
{
stan3--;
if(stan3==0)
stan3=4;
}
switch(stan3)
{
case 1 :
TRA8_ON;
TRA9_OFF;
TRA10_OFF;
TRA11_OFF;
break;
case 2 :
TRA8_OFF;
TRA9_OFF;
TRA10_ON;
TRA11_OFF;
break;
case 3 :
TRA8_OFF;
TRA9_ON;
TRA10_OFF;
TRA11_OFF;
break;
case 4 :
TRA8_OFF;
TRA9_OFF;
TRA10_OFF;
TRA11_ON;
break;
}
overflow3=0;
}
} //zamyka while
} //zamyka main
Dodano po 1 [godziny] 36 [minuty]:
Odkryłem coś jeszcze bardziej dziwnego, podłączyłem sobie oscyloskop by sprawdzić co się dzieje wewnątrz tego przerwania. Wstawiłem do wewnątrz przerwania komendę odpowiedzialną za zmianę stanu jednego z wyjść nazwałem to LED_TOGGLE , bo początkowo była tam dioda
SIGNAL (SIG_OVERFLOW0)
{
TCNT0 = 54; // Załaduj wartość początkową do timera0 218
overflow1++;
overflow2++;
overflow3++;
overflow_ADC++;
LED_TOGGLE;
} Zmianiałem początkową wartość timera czyli wpisywałem różne wartości do TCNT0, no i tu wielkie zaskoczenie bo wraz ze wzrostem wartośi poczatkowej licznika przerwanie powinno wykonywać się coraz częściej bo bliżej było do przepełnienia a tu zaskoczenie bo zmieniałem wartość TCNT0 i nic się nie zmieniało zawsze wychodziło że stan wysoki (lub niski nieważne) trwa 255µs aż do wartości TCNT0=211 jak wpisałem TCNT0=212 to wartość ta od razu zmniejszyła się do 65µs czy ktoś możne mi wyjaśnić dlaczego tak się dzieje? 65µs nie zmieniało się aż do wartości maksymalnej czyli TCNT0=255
