Skocz do zawartości

[C] Pierwsze kroki


rezolut

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
Link do komentarza
Share on other sites

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
Link do komentarza
Share on other sites

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 😉

Link do komentarza
Share on other sites

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

Link do komentarza
Share on other sites

Zarejestruj się lub zaloguj, aby ukryć tę reklamę.
Zarejestruj się lub zaloguj, aby ukryć tę reklamę.

jlcpcb.jpg

jlcpcb.jpg

Produkcja i montaż PCB - wybierz sprawdzone PCBWay!
   • Darmowe płytki dla studentów i projektów non-profit
   • Tylko 5$ za 10 prototypów PCB w 24 godziny
   • Usługa projektowania PCB na zlecenie
   • Montaż PCB od 30$ + bezpłatna dostawa i szablony
   • Darmowe narzędzie do podglądu plików Gerber
Zobacz również » Film z fabryki PCBWay

(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;
}
Link do komentarza
Share on other sites

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;)

Link do komentarza
Share on other sites

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.

Link do komentarza
Share on other sites

Dołącz do dyskusji, napisz odpowiedź!

Jeśli masz już konto to zaloguj się teraz, aby opublikować wiadomość jako Ty. Możesz też napisać teraz i zarejestrować się później.
Uwaga: wgrywanie zdjęć i załączników dostępne jest po zalogowaniu!

Anonim
Dołącz do dyskusji! Kliknij i zacznij pisać...

×   Wklejony jako tekst z formatowaniem.   Przywróć formatowanie

  Dozwolonych jest tylko 75 emoji.

×   Twój link będzie automatycznie osadzony.   Wyświetlać jako link

×   Twoja poprzednia zawartość została przywrócona.   Wyczyść edytor

×   Nie możesz wkleić zdjęć bezpośrednio. Prześlij lub wstaw obrazy z adresu URL.

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