Skocz do zawartości

[C] Buzzer, Pulse Width Modulation, ARM AT91SAM9263 wydobycie dźwięku i zmiana częstotliwości.


dafegon

Pomocna odpowiedź

Witam! 😉

Jestem początkującym programistą systemów wbudowanych, mam do czynienia z płytką z procesorem ARM AT91SAM9263 i generalnie chodzi o to, że mam za zadanie zaprogramować brzęczyk(buzzer) tak by wydawał z siebie dźwięk o różnych częstotliwościach.

I teraz tak, prosił bym Was o pomoc, gdyż nie rozumiem zbytnio jak ma to wszystko działać.

Wiem, że należy ten problem rozwiązać za pomocą Pulse Width Modulation, mam do dyspozycji dokumentację płytki oraz procesora.

Dodam, że program jest pisany w języku C.

Głównie chciałbym się dowiedzieć jak rozgryźć ten problem, jakich rejestrów użyć i jak je skonfigurować, by brzęczyk wydawał z siebie dźwięki o różnej częstotliwości. Oraz ogólnie zasadę działania tego brzęczyka.

Tutaj udostępniam dokumentację:

Dokumentacja w załączniku. :) 

Niestety nie mam zbytnio doświadczenia w tym temacie dlatego liczę na Waszą pomoc. 🙄

Z góry dzięki za każdą informację! Pozdrawiam.

dokumentacja_ARM.pdf

Link do komentarza
Share on other sites

Porywasz się na dość rozbudowany mikroprocesor, to nieco ambitne zadanie jak na początek. Jeśli planujesz wszystko pisać od podstaw, szanse są raczej niewielkie. Ale mam nadzieję, że oprócz dokumentacji samego procesora - którą podałeś w linku, masz coś jeszcze. Po pierwsze przydałaby się jakaś informacja o samej płytce, co to za model i co o niej wiesz.

Kolejna sprawa to kompilator oraz biblioteki i przykłady. Większość płytek ewaluacyjnych jest dostarczana z gotowymi programami, a to powinno znacznie ułatwić zadanie. Tylko musisz napisać coś więcej.

Link do komentarza
Share on other sites

Zgadzam się, jest to troszkę skomplikowane zadanie, jednak myślę, że z Waszą pomocą uda mi się to zadanie wykonać.

Oczywiście pisałem już kilka prostych programów np. na zaświecenie diodkami, reagowanie na naciśnięcie przycisku zaświeceniem/zgaszeniem diodki lub też zabawa z wyświetlaczem 7-segmentowym. 😉

System linux, kompilator gdb.

Korzystam z jednej biblioteki, którą również udostępnię:

Biblioteka AT91SAM9263.h w załączniku. :) 

Tutaj przykładowy program na wyświetlacz 7-segmentowy, odlicza od 00 do 99, reaguje na przycisk (wtedy odlicza "do tyłu"), wykorzystuje timer, nie używałem wtedy jeszcze biblioteki, definiowałem rejestry samemu:

#define LEWY 1<<28
#define PRAWY 1<<30
#define W7_A 1<<25
#define W7_B 1<<24
#define W7_C 1<<22
#define W7_D 1<<21
#define W7_E 1<<20
#define W7_F 1<<27
#define W7_G 1<<26
#define W7_DP 1<<23

#define PIOB_PER (volatile unsigned int * const) 0xFFFFF400
#define PIOB_OER (volatile unsigned int * const) 0xFFFFF410
#define PIOB_SODR (volatile unsigned int * const) 0xFFFFF430
#define PIOB_CODR (volatile unsigned int * const) 0xFFFFF434

#define PIOC_PUSR (volatile unsigned int * const) 0xFFFFF668
#define PIOC_PUER (volatile unsigned int * const) 0xFFFFF664
#define PMC_PCER (volatile unsigned int * const) 0xFFFFFC10
#define PIOC_PDSR (volatile unsigned int * const) 0xFFFFF63C
#define PIOC_PER (volatile unsigned int * const) 0xFFFFF600

#define BUTT2 (1 << 4)
#define CLK_PCDE (1 << 4)

#define PIT_MR (volatile unsigned int * const) 0xFFFFFD30
#define PIT_STATUS (volatile unsigned int * const) 0xFFFFFD34
#define PIT_PIVR (volatile unsigned int * const) 0xFFFFFD38
#define PIT_PIIR (volatile unsigned int * const) 0xFFFFFD3C

void delay(long int limit)
{
 volatile int i;
 for(i = 0; i < limit; ++i);
}

int main(void) {

*PIOC_PER = BUTT2;
*PIOC_PUSR = BUTT2;
*PIOC_PUER = BUTT2;
*PMC_PCER = CLK_PCDE;

*PIT_MR = (1 << 24)|1000000;


int c=0;
*PIOB_PER = (LEWY|PRAWY|W7_A|W7_B|W7_C|W7_D|W7_E|W7_F|W7_G);
*PIOB_OER = (LEWY|PRAWY|W7_A|W7_B|W7_C|W7_D|W7_E|W7_F|W7_G);
*PIOB_CODR = PRAWY;
*PIOB_CODR = LEWY;

int i=0;
int cz_jednosci;
int cz_dziesietna;

while(1)
{	
	cz_jednosci=i%10;
	cz_dziesietna=i/10;


	if(*PIT_STATUS == 0)
	*PIOB_CODR = PRAWY;
	*PIOB_SODR = LEWY;
	wyczysc();   
	funkcja(cz_jednosci);            
	//delay(2500);
	*PIOB_CODR = LEWY;
	*PIOB_SODR = PRAWY;
	wyczysc();
	funkcja(cz_dziesietna);
	//delay(2500); 		

	if(((*PIOC_PDSR & BUTT2) == 0))
	{
		i--;                 
		if(i<0) i=99;
	}else 
	{
		i++;
		if(i>99) i=0;
	}

	if(*PIT_STATUS == 1)
	{
		*PIT_PIIR;
	}  
}
}

void funkcja(int z)
{
*PIOB_CODR = (W7_A|W7_B|W7_C|W7_D|W7_E|W7_F|W7_G); // czyszczenie 7 segmentów
switch(z){
	case(0):	                      
		*PIOB_SODR = (W7_A|W7_B|W7_C|W7_D|W7_E|W7_F); // zero
		break;
	case(1):				                      
		*PIOB_SODR = (W7_B|W7_C); // jeden
		break;
	case(2):                      
		*PIOB_SODR = (W7_A|W7_B|W7_D|W7_E|W7_G); //dwa
		break;
	case(3):                  
		*PIOB_SODR = (W7_A|W7_B|W7_C|W7_D|W7_G); //trzy
		break;
	case(4):                   
		*PIOB_SODR = (W7_B|W7_C|W7_F|W7_G); // itd.
		break;
	case(5):                       
		*PIOB_SODR = (W7_A|W7_C|W7_D|W7_F|W7_G);
		break;
	case(6):                            
		*PIOB_SODR = (W7_A|W7_C|W7_D|W7_E|W7_F|W7_G);
		break;
	case(7):                              
		*PIOB_SODR = (W7_A|W7_B|W7_C);
		break;
	case(8):                        
		*PIOB_SODR = (W7_A|W7_B|W7_C|W7_D|W7_E|W7_F|W7_G);
		break;
	case(9):                            
		*PIOB_SODR = (W7_A|W7_B|W7_C|W7_D|W7_F|W7_G);                                      
		break;
}
}

void dbgu_print_ascii(const char* string){}

AT91SAM9263.h

Link do komentarza
Share on other sites

Pierwsza uwaga - nie podawaj linków do zewnętrznych serwerów, jeśli chcesz dodać załącznik, wyślij plik na serwer Forbota. Jak administrator wstanie to i tak pewnie się do tego przyczepi 🙂

gdb to debugger nie kompilator, ale zakładam, że używasz gcc jako kompilatora.

Żeby nie zadawać miliona pytań - do AT91SAM9263 znalazłem dokumentację płytkie ewaluacyjnej: http://www.microchip.com/DevelopmentTools/ProductDetails.aspx?PartNO=AT91SAM9263-EK

Dostępny jest obraz płyty CD, na nim kilka przykładów i początkowy projekt - zakładam, że to na nim bazujesz.

Wygląda na to, że Atmel nie przygotował biblioteki o jakiej myślałem, masz więc tylko definicje rejestrów i datasheet. To wystarczy, ale jest nieco więcej pracy. Przeczytałeś rozdział 38. z dokumentacji? Opisuje jak działa PWM na tym procesorze.

  • Lubię! 1
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

Jasne, właśnie zabieram się do ogarnięcia tego rozdziału, pewnie nie zrozumiem całości, gdyż jak pisałem wcześniej, nie siedzę w tym temacie zbytnio długo. 😖

Co do wstawiania linków - prawda, nie doczytałem regulaminu, postaram się wrzucić na serwer forbota, wybaczcie. 😉

Tak, kompilator gcc, pomyłeczka nastąpiła. 😋

Generalnie myślę, że program nie będzie długi, ale będzie trzeba ustawić zawiłą sprawę rejestrów, w odpowiedniej kolejności - to chyba największy problem, no i zrozumienie wszystkiego jak to ma działać po kolei.

Zaznaczę, że nie chodzi mi o jakieś zaawansowane sterowanie Buzzerem typu zagranie jakiejś melodii, jedynie chodzi mi o wydobycie dźwięku, następnie zmienieniu jego częstotliwości, by wydobyć inny dźwięk.

No i dzięki Ci za dotychczasowe zainteresowanie tematem i liczę na dalsze instrukcje! 😋 Dość mocno zależy mi na tym zadaniu. 🙂

Dobra, zabieram się do krótkiej lekturki 38. rozdziału.

Poprawiam linki, jeszcze raz sorki za to. 🙁

_______________

@edit:

Dobra mam chyba pierwszy krok, jaki trzeba wykonać, mianowicie muszę włączyć Power Management Controller zanim użyję PWMC, ponieważ PWMC nie posiada na stałe podłączonego sygnału zegarowego.

Będzie więc trzeba ustawić jedynkę w PMC Peripheral Clock Enable Register (PMC_PCER) na bicie 20, gdyż takie Peripheral ID posiada PWMC.

Kod:

#define PMC_PCER (volatile unsigned int * const) 0xFFFFFC10
#define PMC_PCER_PID20 (1 << 20) 

int main(void) { 
*PMC_PCER = PMC_PCER_PID20;

while(1){}

}

void dbgu_print_ascii(const char* string){}

To już coś mamy. 😋

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.