Witam
Mam problem z programem odmierzającym czas. Mikrokontroler współpracuje z czujnikami ultradźwiękowymi.
Ogólne założenie programu jest takie że generuje paczkę 8 impulsów prostokątnych o częstotliwości 40KHz następnie 4ms na wyciszenie układu. Generowanie paczki wykonywane jest za pomocą Timera2 w trybie CTC.
Następnie za pomocą Timera1 powinien być mierzony czas od momentu wygenerowania pierwszego impulsu przez Timer2 do momentu pojawienia się echa, które z czujników ultradźwiękowych przekazywane jest na wejśie ICP Atmegi. Na podstawie czasu wyznaczana jest odległość (ten fragment programu działa nieprawidłowo)
Następnie otrzymany wynik wysyłany jest przez UART do komputera.
Dodam iż jestem początkującym programistą wiec proszę o wyrozumiałość. Generacja paczki i transmisja UART były sprawdzane na oscyloskopie i przebiegi wyglądają prawidłowo jednak pomiar czasu to lepiej nie mówić.
Z góry dziękuję za wszelaką pomoc
Kod programu:
#include <avr/io.h> // wejscia_wyjscia avr
#include <avr/interrupt.h> // bibloteka obslugi przerwan
#include <util/delay.h> // biblioteka opóźnieńs
#include <stdlib.h>
#define F_CPU 8000000UL // częstotliwość pracy procesora
#define BAUD 9600 // prędkość transmisji
#define dist 0.17
/****************************USART*******************************/
void InitUSART( void )
{
UBRRH = (unsigned char)(((F_CPU/(16UL*BAUD))-1)>>8); //Ustawiam predkosc USARTu
UBRRL = (unsigned char)((F_CPU/(16UL*BAUD))-1);
// Otwarcie kanalu odbioru i nadawania oraz przerwań od odbioru
UCSRB = (1<<RXEN)|(1<<TXEN)|(1<<RXCIE);
//URSEL=1 korzystanie z rejestru UCSC
//USBS=0 1 bit stopu
//UMP0=0 sprawdzanie parzystości wyłączone
//UCSZ0=3 8 bitów danych
//UMSEL=0 Asynchroniczne nadawanie
UCSRC = (1<<URSEL)|(0<<USBS)|(3<<UCSZ0);
}
void TransmitCHAR( unsigned char data ) // funkcja wysłania bajtu po RS232
{
while (!( UCSRA & (1<<UDRE))); // oczekiwanie na pusty buror
UDR = data; // wysyłanie danych
}
void TransmitSTRING(char *text) //funkcja wysłania danych po RS232
{
while(*text)
{
while (!( UCSRA & (1<<UDRE)));
UDR = *text;
text++;
}
}
void TransmitINT(int number)
{
char buffer[7];
itoa(number,buffer,10);
TransmitSTRING(buffer);
}
/****************************TIMER2******************************/
void InitCTC(void)
{
DDRB|=(1<<PB2)|(1<<PB3); //port B2, B3 jako wyjsciowe
DDRB&=~(1<<PB0); //port B0 jako wejsciowy
PORTB|=(1<<PB2); // Port B2 podciągnięty do zasilania
DDRD|=(1<<PD5);
PORTD|=(1<<PD5);
//ustawienia timera2 generatora CTC
//CS20=1 preskaler 1->1
//WGM21=1 tryb CTC
//COM20=1 zmiana stanu na przeciwny pinu OC2
TCCR2=(1<<WGM21)|(1<<CS20);
//czestotliwosc CTC 40kHz dla 99 działek
OCR2=0x63;
TIMSK|=(1<<OCIE2);
}
volatile uint8_t count;
ISR(SIG_OUTPUT_COMPARE2)
{
if (count==0) TCNT1=0;
count=count+1; //zwiększ licznik
if (count>0 && count<16) //8 okresów f=40khz = 200us prostokąt
{
TCCR2|=(1<<COM20);
TCCR2&=~(1<<COM21);
}
else if (count>=16 && count<336) //120 okresów o f=40khz =3ms 0
{
TCCR2|=(1<<COM21);
TCCR2&=~(1<<COM20);
}
else if(count==336) //powrót do ustawień początkowych
{
count=0;
TCCR2|=(1<<COM20);
TCCR2&=~(1<<COM21);
}
}
/****************************TIMER1******************************/
void InitICP( void )
{
//ICNC1=1 włączenie eliminacji szumów
//ICES1=1 wyzwolenie przechwytywania zboczem narastajacym
//CS1n preskaler 001->1,010->8, 011->64, 100->256, 101->1024
TCCR1B=(1<<ICNC1)|(1<<ICES1)|(1<<CS10);
//TICIE1 przerwanie od ICP
//TOIE1 przerwanie od przepełnienia licznika
TIMSK|=(1<<TICIE1)|(1<<TOIE1);
}
volatile int sensor;
volatile char flaga=0;
ISR(SIG_INPUT_CAPTURE1)
{
sensor=TCNT1;
flaga=1;
}
int main (void)
{
DDRD|=(1<<PD7)|(1<<PD6);
PORTD|=(1<<PD7)|(1<<PD6);
DDRB&=~(1<<PB1); // PORT PB1 jako wejściowy
PORTB|=(1<<PB1); // podciągnięcie do stanu wysokiego
InitUSART();
InitCTC();
InitICP();
sei();
while(1)
{
if (flaga==1)
{
flaga=0;
count=0;
sensor= sensor*dist;
TransmitINT(sensor);
TransmitCHAR(0x0A);
}
_delay_ms(50);
}
return(0);
}
Mam problem z programem odmierzającym czas. Mikrokontroler współpracuje z czujnikami ultradźwiękowymi.
Ogólne założenie programu jest takie że generuje paczkę 8 impulsów prostokątnych o częstotliwości 40KHz następnie 4ms na wyciszenie układu. Generowanie paczki wykonywane jest za pomocą Timera2 w trybie CTC.
Następnie za pomocą Timera1 powinien być mierzony czas od momentu wygenerowania pierwszego impulsu przez Timer2 do momentu pojawienia się echa, które z czujników ultradźwiękowych przekazywane jest na wejśie ICP Atmegi. Na podstawie czasu wyznaczana jest odległość (ten fragment programu działa nieprawidłowo)
Następnie otrzymany wynik wysyłany jest przez UART do komputera.
Dodam iż jestem początkującym programistą wiec proszę o wyrozumiałość. Generacja paczki i transmisja UART były sprawdzane na oscyloskopie i przebiegi wyglądają prawidłowo jednak pomiar czasu to lepiej nie mówić.
Z góry dziękuję za wszelaką pomoc
Kod programu:
#include <avr/io.h> // wejscia_wyjscia avr
#include <avr/interrupt.h> // bibloteka obslugi przerwan
#include <util/delay.h> // biblioteka opóźnieńs
#include <stdlib.h>
#define F_CPU 8000000UL // częstotliwość pracy procesora
#define BAUD 9600 // prędkość transmisji
#define dist 0.17
/****************************USART*******************************/
void InitUSART( void )
{
UBRRH = (unsigned char)(((F_CPU/(16UL*BAUD))-1)>>8); //Ustawiam predkosc USARTu
UBRRL = (unsigned char)((F_CPU/(16UL*BAUD))-1);
// Otwarcie kanalu odbioru i nadawania oraz przerwań od odbioru
UCSRB = (1<<RXEN)|(1<<TXEN)|(1<<RXCIE);
//URSEL=1 korzystanie z rejestru UCSC
//USBS=0 1 bit stopu
//UMP0=0 sprawdzanie parzystości wyłączone
//UCSZ0=3 8 bitów danych
//UMSEL=0 Asynchroniczne nadawanie
UCSRC = (1<<URSEL)|(0<<USBS)|(3<<UCSZ0);
}
void TransmitCHAR( unsigned char data ) // funkcja wysłania bajtu po RS232
{
while (!( UCSRA & (1<<UDRE))); // oczekiwanie na pusty buror
UDR = data; // wysyłanie danych
}
void TransmitSTRING(char *text) //funkcja wysłania danych po RS232
{
while(*text)
{
while (!( UCSRA & (1<<UDRE)));
UDR = *text;
text++;
}
}
void TransmitINT(int number)
{
char buffer[7];
itoa(number,buffer,10);
TransmitSTRING(buffer);
}
/****************************TIMER2******************************/
void InitCTC(void)
{
DDRB|=(1<<PB2)|(1<<PB3); //port B2, B3 jako wyjsciowe
DDRB&=~(1<<PB0); //port B0 jako wejsciowy
PORTB|=(1<<PB2); // Port B2 podciągnięty do zasilania
DDRD|=(1<<PD5);
PORTD|=(1<<PD5);
//ustawienia timera2 generatora CTC
//CS20=1 preskaler 1->1
//WGM21=1 tryb CTC
//COM20=1 zmiana stanu na przeciwny pinu OC2
TCCR2=(1<<WGM21)|(1<<CS20);
//czestotliwosc CTC 40kHz dla 99 działek
OCR2=0x63;
TIMSK|=(1<<OCIE2);
}
volatile uint8_t count;
ISR(SIG_OUTPUT_COMPARE2)
{
if (count==0) TCNT1=0;
count=count+1; //zwiększ licznik
if (count>0 && count<16) //8 okresów f=40khz = 200us prostokąt
{
TCCR2|=(1<<COM20);
TCCR2&=~(1<<COM21);
}
else if (count>=16 && count<336) //120 okresów o f=40khz =3ms 0
{
TCCR2|=(1<<COM21);
TCCR2&=~(1<<COM20);
}
else if(count==336) //powrót do ustawień początkowych
{
count=0;
TCCR2|=(1<<COM20);
TCCR2&=~(1<<COM21);
}
}
/****************************TIMER1******************************/
void InitICP( void )
{
//ICNC1=1 włączenie eliminacji szumów
//ICES1=1 wyzwolenie przechwytywania zboczem narastajacym
//CS1n preskaler 001->1,010->8, 011->64, 100->256, 101->1024
TCCR1B=(1<<ICNC1)|(1<<ICES1)|(1<<CS10);
//TICIE1 przerwanie od ICP
//TOIE1 przerwanie od przepełnienia licznika
TIMSK|=(1<<TICIE1)|(1<<TOIE1);
}
volatile int sensor;
volatile char flaga=0;
ISR(SIG_INPUT_CAPTURE1)
{
sensor=TCNT1;
flaga=1;
}
int main (void)
{
DDRD|=(1<<PD7)|(1<<PD6);
PORTD|=(1<<PD7)|(1<<PD6);
DDRB&=~(1<<PB1); // PORT PB1 jako wejściowy
PORTB|=(1<<PB1); // podciągnięcie do stanu wysokiego
InitUSART();
InitCTC();
InitICP();
sei();
while(1)
{
if (flaga==1)
{
flaga=0;
count=0;
sensor= sensor*dist;
TransmitINT(sensor);
TransmitCHAR(0x0A);
}
_delay_ms(50);
}
return(0);
}
