Skocz do zawartości

[C] [ATmega8][Delphi][BTM-222] - Czy konieczne są opóźnienia w transmisji?


Defozo

Pomocna odpowiedź

Witam!

Staram się wysłać komendy przez Bluetooth (za pośrednictwem BTM-222 przy prędkości 38400bps) do mikrokontrolera ATmega8 odnośnie zmiany PWM silników.

Z początku chciałem robić to tak:

ProgramowanieForm.ComPort1.WriteStr('2');
ProgramowanieForm.ComPort1.WriteStr('5');
ProgramowanieForm.ComPort1.WriteStr('5');
ProgramowanieForm.ComPort1.WriteStr('y');

Jednak okazało się, że bardzo często komendy nie docierały w pełni (np. zamiast "255y" dochodziło "25y").

Dlatego dodałem 28ms opóźnienia:

ProgramowanieForm.ComPort1.WriteStr('2');
sleep(28);
ProgramowanieForm.ComPort1.WriteStr('5');
sleep(28);
ProgramowanieForm.ComPort1.WriteStr('5');
sleep(28);
ProgramowanieForm.ComPort1.WriteStr('y');
sleep(28);

Przy takich opóźnieniach nie ma błędów w komunikacji, ale przy wysłaniu tej komendy tracę aż 118ms!

Jest to zdecydowanie za długo!

Program po stronie mikrokontrolera:

/*
* Samochodzik_Bluetooth.c
*
* Created: 2013-01-21 18:36:41
*  Author: Defozo
*/ 


#define F_CPU 8000000UL
#define FOSC 8000000UL// Clock Speed
#define BAUD 38400
//#define MYUBRR ((FOSC / 16 + BAUD / 2) / BAUD-1)
#define MYUBRR ( FOSC  + BAUD * 8UL  ) / (16UL * BAUD) -1
#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>

static int LeftValue = -1;
static int UpValue = -1;
static int RightValue = -1;
static int DownValue = -1;

static int cyfra;
static int aktualnaliczba;

void USART_Init( unsigned int ubrr)
{
/* Set baud rate */
UBRRH = (unsigned char)(ubrr>>8);
UBRRL = (unsigned char)ubrr;
/* Enable receiver and transmitter */
UCSRB = (1<<RXEN)|(1<<TXEN)|(1<<RXC);
/* Set frame format: 8data, 2stop bit */
UCSRC = (1<<URSEL)|(1<<USBS)|(3<<UCSZ0);
}

void USART_Transmit( unsigned char data )
{
/* Wait for empty transmit buffer */
while ( !( UCSRA & (1<<UDRE)) )
;
/* Put data into buffer, sends the data */
UDR = data;
}

unsigned char USART_Receive( void )
{
/* Wait for data to be received */
while ( !(UCSRA & (1<<RXC)) )
;
/* Get and return received data from buffer */
return UDR;
}

int main(void)
{
TCCR1A |= (1<<WGM10);                      // Fast PWM 8bit
TCCR1B |= (1<<WGM12);
TCCR1A |= (1<<COM1A1)|(1<<COM1B1) ;        //Clear OC1A/OC1B on Compare Match, set OC1A/OC1B at BOTTOM
TCCR1B |= (1<<CS10)|(1<<CS11);             // Preskaler = 64  fpwm = 488 Hz

//sterowanie prędkością silników
OCR1A = 0;         //kanał A = 0
OCR1B = 0;         //kanał B = 0

DDRB = 0xFF;
DDRD = 0xFF;
USART_Init(MYUBRR);
sei();
   while(1)
   {
	_delay_ms(1);
	/*if (!(bit_is_clear(PINC,3))) { //może trzeba skonfigurować jako wejście?
		_delay_ms(80);
		if (!(bit_is_clear(PINC,3))) {
			USART_Transmit('m');
		}			
	}*/
	if (cyfra >= '0' && cyfra <= '9') {
		aktualnaliczba = aktualnaliczba*10+cyfra - '0';
		cyfra = -1;
	}			
       if (LeftValue > 0)
       {
		PORTD = 0x00;
		PORTB = 0x00;
		PORTB = _BV(1) | _BV(2);
		PORTD = _BV(5) | _BV(7); //w lewo (PD5 + PD7)
		LeftValue = LeftValue-1;
       }
	if (UpValue > 0)
	{
		PORTB = 0x00;
		PORTD = 0x00;
		PORTB = _BV(1) | _BV(2) | _BV(0); //do góry (PB0 + PD6)
		PORTD = _BV(6); //do góry (PB0 + PD6)
		UpValue = UpValue-1;
	}
	if (RightValue > 0)
	{
		PORTD = 0x00;
		PORTB = 0x00;
		PORTB = _BV(0) | _BV(1) | _BV(2); //w prawo  (PB0 + PD5)
		PORTD = _BV(5); //w prawo (PB0 + PD5)
		RightValue = RightValue-1;
	}
	if (DownValue > 0)
	{
		PORTD = 0x00;
		PORTB = 0x00;
		PORTB = _BV(1) | _BV(2);
		PORTD = _BV(6) | _BV(7); //do tyłu (PD6 + PD7)
		DownValue = DownValue-1;
	}
	if (LeftValue == 0)
	{
		PORTD = 0x00;
		PORTB = 0x00;
		LeftValue = -1;
	}
	if (UpValue == 0)
	{
		PORTD = 0x00;
		PORTB = 0x00;
		UpValue = -1;
	}
	if (RightValue == 0)
	{
		PORTD = 0x00;
		PORTB = 0x00;
		RightValue = -1;
	}
	if (DownValue == 0)
	{
		PORTD = 0x00;
		PORTB = 0x00;
		DownValue = -1;
	}
   }
}

ISR(USART_RXC_vect)
{
char wiadomosc=UDR;
//USART_Transmit(wiadomosc); //zostawić tylko na debugowanie
switch(wiadomosc)
{
	case 'q': //w lewo
		UpValue = 0;
		DownValue = 0;
		RightValue = 0;
		LeftValue = 200;
	break;

	case 'w': //do góry
		UpValue = 200;
		DownValue = 0;
		RightValue = 0;
		LeftValue = 0;
	break;

	case 'e': //w prawo
		UpValue = 0;
		DownValue = 0;
		RightValue = 200;
		LeftValue = 0;
	break;

	case 'r': //do tyłu
		UpValue = 0;
		DownValue = 200;
		RightValue = 0;
		LeftValue = 0;
	break;

	case 't': //przełącza światła
		DDRC ^= _BV(4) | _BV(5);
		PORTC ^= _BV(4) | _BV(5);
	break;

	case 'z': //przełącza światło lewe(?)
		DDRC ^= _BV(4);
		PORTC ^= _BV(4);
	break;

	case 'x': //przełącza światło prawe(?)
		DDRC ^= _BV(5);
		PORTC ^= _BV(5);
	break;

	case '0':
		cyfra = wiadomosc;
	break;

	case '1':
		cyfra = wiadomosc;
	break;

	case '2':
		cyfra = wiadomosc;
	break;

	case '3':
		cyfra = wiadomosc;
	break;

	case '4':
		cyfra = wiadomosc;
	break;

	case '5':
		cyfra = wiadomosc;
	break;

	case '6':
		cyfra = wiadomosc;
	break;

	case '7':
		cyfra = wiadomosc;
	break;

	case '8':
		cyfra = wiadomosc;
	break;

	case '9':
		cyfra = wiadomosc;
	break;

	case 'y':
		OCR1A = aktualnaliczba;
		aktualnaliczba = 0;
	break;

	case 'u':
		OCR1B = aktualnaliczba;
		aktualnaliczba = 0;
	break;

	case 'i': //do testów
		OCR1A = 255;
		OCR1B = 255;
	break;

	case 'o': //do testów
		OCR1A = 125;
		OCR1B = 125;
	break;

	case 'p': //do testów
		OCR1A = 0;
		OCR1B = 0;
	break;

	//testowy segment:
	case 'a':
		OCR1A = OCR1A-10;
	break;

	case 's':
		OCR1A = OCR1A+10;
	break;

	case 'd':
		OCR1B = OCR1B-10;
	break;

	case 'f':
		OCR1B = OCR1B+10;
	break;

	case 'g':
		PORTD &= ~_BV(6); //wyłącza prawy silnik przód (PD6)
		PORTD |= _BV(5); //prawy silnik tył (PD5)
	break;

	case 'h':
		PORTD &= ~_BV(7); //wyłącza lewy silnik tył (PD7)
		PORTB |=  _BV(0); //lewy silnik przód (PB0)
	break;

	case 'j':
		//PORTB |= _BV(1) | _BV(2);
		PORTB &= ~_BV(0); //wyłącza lewy silnik przód (PD7)
		PORTD |= _BV(7); //lewy silnik tył (PD7)
	break;

	case 'k':
		//PORTB |= _BV(1) | _BV(2);
		PORTD &= ~_BV(5); //wyłącza prawy silnik tył (PD5)
		PORTD |= _BV(6); //prawy silnik przód (PD6)
	break;

	/*case 'v': //software reset na potrzeby wgrania bootloadera
		cli();                  // wyłącz przerwania
		wdt_enable(0);  // ustaw watch-dog
		while(1);               // czekaj na RESET
	break;*/
}

}	

Czy jest jakiś sposób, by nie trzeba było stosować takich opóźnień?

Proszę o pomoc,
Defozo

Link do komentarza
Share on other sites

Bądź aktywny - zaloguj się lub utwórz konto!

Tylko zarejestrowani użytkownicy mogą komentować zawartość tej strony

Utwórz konto w ~20 sekund!

Zarejestruj nowe konto, to proste!

Zarejestruj się »

Zaloguj się

Posiadasz własne konto? Użyj go!

Zaloguj się »
×
×
  • Utwórz nowe...

Ważne informacje

Ta strona używa ciasteczek (cookies), dzięki którym może działać lepiej. Więcej na ten temat znajdziesz w Polityce Prywatności.