Skocz do zawartości

Pomocna odpowiedź

są poprawne i czy potem użycie w kodzie programu l_przod, spowoduje ustawienie 6 bitu i wyzerowanie 7 bitu?

Nie.

Nie można jednocześnie zerować i ustawiać bitów za jednym razem.

Może zrób sobie po prostu funkcje:

void l_przod(void)
{
PORTD |= (1<<6) ;   // ustawianie bitu 6
PORTD &= ~(1<<7);  // zerowanie bitu 7
}

Druga funkcja analogicznie.

  • Lubię! 1
Nie można jednocześnie zerować i ustawiać bitów za jednym razem.

A zabieg typu:

PORTD = ((PORTD & 0x3F) | (1<<6))

?

BTW, nie wiem czy jest to lepsze rozwiązanie od podanego przez Ciebie, mało czytelne, ale chyba skuteczne.

  • Pomogłeś! 1

No i jak by teraz zrobić z tego coś takiego

#define przod PORTD = (PORTD & 0x3F) | ((1<<6) | (0<<7)) 

to mamy quasi funkcję w jednej linijce?

Wydaje się działać, więc można za jednym zamachem wyzerować jeden bit i ustawić inny 😉

(0<<7) nie jest potrzebne. I tak na tym bicie jest 'zero'.

Myślę, że na początku przygody z 'C' to wystarczy, potem możesz zapoznać się z fukcjami 'inline'. Chociaż opinie o wyższości jednego rozwiązania nad drugim są podzielone.

(0<<7) musi zostać bo zamieniam wymiennie piny 6 i 7: 01 / 10 / 00 lub 11.

W takim przykładzie jak podałeś, działa to idealnie (póki co w symulatorze 😉 ).

#define F_CPU 16000000L

#include <avr/io.h> 
#include <avr/interrupt.h> 

#define l_przod PORTD = (PORTD & 0x3F) | ((1<<6) | (0<<7)) ;
#define l_tyl PORTD = (PORTD & 0x3F) | ((0<<6) | (1<<7)) ;

#define p_przod PORTC = (PORTC & 0x3F) | ((1<<6) | (0<<7)) ;
#define p_tyl PORTC = (PORTC & 0x3F) | ((0<<6) | (1<<7)) ;

int main(void) 
{
//konfiguracja portów
DDRB = 255; 	// wszystko OUT
DDRC = 255;		// wszystko OUT
DDRC &= 0xf8;	// zeruje bity 0..2, czyli PD0 - PD2 to IN
PORTC = 7;		// B00000111 - wejścia PD0-PD2 podciągnięte
DDRD = 0;		// wszystko IN
PORTD = 12;		// B00001100 - wejścia PD2, PD3 podciągnięte

//definicje zmiennych
int right_encoder = 0;
int left_encoder = 0;
int roznica_czujnikow = 0;
int left_to_go = 0;
int right_to_go = 0;

//konfiguracja PWM

while(1) 
	{
	l_przod;
	l_tyl;

	p_przod;
	p_tyl;
}
return 0;
}

Rozumiem, że chcesz zamienić bity 7 i 6. Jednak działania PORTD & 0x3F powoduje WYZEROWANIE dwóch najstarszych bitów w PORCIE D. (PORTD -> 0b00XXXXXX).

W takim przypadku pozostaje Ci tylko ustawienie '1' tam gdzie to konieczne. Oczywiście instrukcja (0<<7) niczego nie psuje, ale pokazuje, że nie do końca wiesz co się dzieje;)

Oczywiście masz rację 😃 ale już sobie to przeanalizowałem i przyswoiłem.

W ten sposób udało mi się po raz pierwszy zakręcić silnikami.

#define F_CPU 16000000L
#include <avr/io.h> 
#include <avr/interrupt.h> 
#include <util/delay.h> 

#define l_przod PORTD = (PORTD & 0x3F) | (1<<6)
#define l_tyl PORTD = (PORTD & 0x3F) | (1<<7)
#define l_stop PORTD = (PORTD & 0x3F)
#define p_przod PORTC = (PORTC & 0x3F) | (1<<7)
#define p_tyl PORTC = (PORTC & 0x3F) | (1<<6)
#define p_stop PORTC = (PORTC & 0x3F)

int main(void) 
{
//konfiguracja portów
DDRB = 255; 	// B11111111 - wszystko OUT
DDRC = 255;		// B11111111 - wszystko OUT
DDRC &= 0xf8;	// zeruje bity 0..2, czyli PD0 - PD2 to IN
PORTC = 7;		// B00000111 - wejścia PD0-PD2 podciągnięte
DDRD = 243;		// B11110011 - wszystko OUT, PD2, PD3 IN
PORTD = 12;		// B00001100 - wejścia PD2, PD3 podciągnięte

//definicje zmiennych
int right_encoder = 0;
int left_encoder = 0;
int roznica_czujnikow = 0;
int left_to_go = 0;
int right_to_go = 0;

//konfiguracja PWM
TCCR1A |= (1<<COM1A1) | (1<<COM1B1) | (1<<WGM11);
TCCR1B |= (1<<WGM12) | (1<<CS12); //prescaler 256

OCR1B=100;
OCR1A=100;

l_przod;
	_delay_ms(3000);
l_tyl;
	_delay_ms(3000);
l_stop;

p_przod;
	_delay_ms(3000);
p_tyl;
	_delay_ms(3000);
p_stop;

while(1) 
	{
}
return 0;
}

Teraz pora na liczenie impulsów enkoderów na INT1 i INT0. Gdyby ktoś miał jakieś sugestie.... 😃

[ Dodano: 25-03-2012, 16:42 ]

Okazuje się, że szukając w sieci i mając przed oczami notę procesora (pomocny jest też opis po polsku ) można całkiem szybko wejść w świat C.

Guru nie będę, ale udało mi się już dodać: reakcję na przyciski, obsługę przerwań INT0 i INT1, zliczających impulsy enkoderów oraz tymczasową obsługę wyświetlacza LCD.

#define F_CPU 16000000L
#include <avr/io.h> 
#include <avr/interrupt.h> 
#include <util/delay.h> 
#include "HD44780.h"

#define l_przod PORTD = (PORTD & 0x3F) | (1<<PD6)
#define l_tyl PORTD = (PORTD & 0x3F) | (1<<PD7)
#define l_stop PORTD = (PORTD & 0x3F)
#define p_przod PORTC = (PORTC & 0x3F) | (1<<PD7)
#define p_tyl PORTC = (PORTC & 0x3F) | (1<<PD6)
#define p_stop PORTC = (PORTC & 0x3F)

//definicje zmiennych
//zmienne obsługi silników
int right_encoder = 0;
int left_encoder = 0;
int roznica_czujnikow = 0;
int left_to_go = 0;
int right_to_go = 0;
//zmienne obsługi zegara0
int czas = 0;
//inne zmienne
char tekst [16];

ISR(INT0_vect)  //obsługa INT0
{       
left_encoder++;  
//LCD_GoTo(0,0);
//sprintf(tekst,"%u",left_encoder);
//LCD_WriteText(tekst);
}  
ISR(INT1_vect)  //obsługa INT1
{       
right_encoder++;  
//LCD_GoTo(0,1);
//sprintf(tekst,"%u",right_encoder);
//LCD_WriteText(tekst);
}
ISR(TIMER0_OVF_vect)
{ 
czas++;
if (czas>50)
{
	LCD_GoTo(0,0);
	sprintf(tekst,"%u",left_encoder);
	LCD_WriteText(tekst);
	left_encoder = 0;

	LCD_GoTo(0,1);
	sprintf(tekst,"%u",right_encoder);
	LCD_WriteText(tekst);
	right_encoder = 0;
	czas=0;
}
}

int main(void) 
{
setup();

while(1) 
	{


	if (!(PINC & 0x01) !=0)
	{
		LCD_Clear();
		l_przod;
		p_przod;
	}

	if (!(PINC & 0x02) !=0)
	{
		l_stop;
		p_stop;
	}

}
return 0;
}

int setup(void)
{
//konfiguracja portów
DDRB = 255; 	// B11111111 - wszystko OUT

DDRC = 255;		// B11111111 - wszystko OUT
DDRC &= 0xf8;	// zeruje bity 0..2, czyli PC0 - PC2 to IN
PORTC = 7;		// B00000111 - wejścia PC0-PC2 podciągnięte

DDRD = 243;		// B11110011 - wszystko OUT, PD2, PD3 IN
PORTD = 12;		// B00001100 - wejścia PD2, PD3 podciągnięte

//konfiguracja PWM
TCCR1A |= (1<<COM1A1) | (1<<COM1B1) | (1<<WGM11);
TCCR1B |= (1<<WGM12) | (1<<CS12); 								//prescaler 256
OCR1B=200;
OCR1A=200;

//konfiguracja przerwań INT0 i INT1
MCUCR &= ~((1<<ISC11) | (1<<ISC10) | (1<<ISC01) | (1<<ISC00));	//zerowanie rejestru kontroli
MCUCR |= ((1<<ISC11) | (1<<ISC10) | (1<<ISC01) | (1<<ISC00)); 	//INT1 zbocze rosnące, INT0 zbocze malejące
GICR |= (1<<INT1) | (1<<INT0);									//zezwolenie na przerwania INT1 i INT0
//konfiguracja TIMER0
TCNT0 = 0;														//wyzerowanie zegara
TCCR0 |= (1<<CS02) | (0<<CS01) | (1<<CS00);						//preskaler 1024
TIMSK |= (1<<TOIE0);											//zezwolenie na przerwanie po przepełnieniu

sei();															//globalne zezwolenie na przerwania

LCD_Initalize();
return 0;
}

Teraz tylko pozostaje tylko wymyślić sposób na porównanie w przerwaniu licznika impulsów i sterowanie PWM by były one równe i by zachowana była w miarę prostoliniowość jazdy robota.

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...