logo elektroda
logo elektroda
X
logo elektroda
Adblock/uBlockOrigin/AdGuard mogą powodować znikanie niektórych postów z powodu nowej reguły.

[Rozwiązano] Brak migania diody na mikrokontrolerze STM32 C011: konfiguracja pinów GPIO i rejestry

Maniek275 20 Lis 2023 13:20 867 29
  • #1 20824381
    Maniek275
    Poziom 5  
    Posty: 22
    Ocena: 4
    Dzień dobry, postanowiłem zacząć przygodę z rejestrami na mikrokontrolerach, skupiam się obecnie na STM32 C011 z racji, że znam już jakieś solidne podstawy HALowskie. I dostałem już niczym strzał z liścia pierwszy problem - mianowicie dioda dołączona do mikrokontrolera na wyjściu nie chce mrugać. Z dokumentacji mikrokontrolera wraz z całą płytką wynika, że piny GPIO są bezpośrednio połączone z cortexem więc nie ma potrzeby uruchamiania żadnych szyn ABP ani AHB a jedynie linię zegarową dla portów GPIO. Tak też zrobiłem, dodałem do tego rejestry ustawiające pin PA12 jako wyjście, push-pull, z niską prędkością załączania (low-speed) oraz jako no pull-up oraz no pull-dwon. Dioda dołączona do wyjścia mikrokontrolera połączona jest z rezystorem do masy i jest na pewno sprawna bo sprawdzałem czy nie jest aby przepalona. Funkcję odmierzającą czas też mam więc zastanawiam się co mogło mi umknąć przy ustawianiu rejestrów. Dla pewności czy aby funkcja opóźniająca nic nie psuje, wcześniej zamiast Delay wstawiłem po dwie pętle for nic nie robiące z dużą wartością aby zmarnować trochę czasu procesora i także nie działało.

    Edit: dodałem manual do całej płytki

    Poniżej mój kod:
    
    #include <stdint.h>
    #include "stm32c011xx.h"
    
    __IO uint32_t Tick;
    
    void SysTick_Handler(void){
    	Tick++;
    }
    
    void Delay(uint32_t Delay_ms){
    	uint32_t StartTime = Tick;
    
    	while(Tick < (StartTime + Delay_ms)){
    
    	}
    }
    
    int main(void) {
    	SysTick_Config(12000);
    
    	//RCC I/O port clock enable register GPIOA
    	RCC->IOPENR |= RCC_IOPENR_GPIOAEN;
    
    	//Ustawienie PA12 OUTPUT
    	GPIOA->MODER |= GPIO_MODER_MODE12_0;
    	GPIOA->MODER &= ~( GPIO_MODER_MODE12_1);
    
    	// Ustawienie PA12 jako Push-pull
    	GPIOA->OTYPER |= GPIO_OTYPER_OT12;
    
    	// Ustawienie PA12 jako low speed
    	GPIOA->OSPEEDR |= GPIO_OSPEEDR_OSPEED12_0;
    	GPIOA->OSPEEDR &= ~(GPIO_OSPEEDR_OSPEED12_1);
    
    	// Ustawienie PA12 jako no pull-up i no pull-down
    	GPIOA->PUPDR &= ~(GPIO_PUPDR_PUPD12_0);
    	GPIOA->PUPDR &= ~(GPIO_PUPDR_PUPD12_1);
    
    	//Wejście do nieskończonej pętli
    	while (1) {
    		//Ustaw PA12 HIGH
    		GPIOA->BSRR = GPIO_BSRR_BS12;
    
    		Delay(500);
    
    		//Ustaw PA12 LOW
    		GPIOA->BSRR = GPIO_BSRR_BR12;
    		Delay(500);
    
    	}
    }
    
    Załączniki:
    • RM0490 STM32C0x1 Reference manual.pdf (9.34 MB) Musisz być zalogowany, aby pobrać ten załącznik.
  • #2 20824414
    jarekgol
    Poziom 40  
    Posty: 5176
    Pomógł: 644
    Ocena: 1146
    Robisz 2 razy to samo.
    Cytat:
    This is achieved by programming to ‘1’ the Bit Set/Reset Register (GPIOx_BSRR, or for reset only GPIOx_BRR) to select the bits to modify.

    Powinieneś użyć BSRR i BRR, przy czym to jest z RM dla STM32F103xx bo takimi się bawiłem.
    Ewentualnie rejestr BSRR jest podzielony na górną i dolną połówkę, górna do reset, dolna do set, więc pewnie jak zmienisz nazwę tego co tam do niego wpisujesz, to też pomoże.
  • #3 20824437
    Maniek275
    Poziom 5  
    Posty: 22
    Ocena: 4
    Właśnie w datasheecie, 157 strona dokładnie jest napisane, że rejestr dzieli się na dwie części. Bity 0-15 służą do wysterowania na logiczne 1 pinów od 0 do 15 poprzez wstawienie tam wartości logicznej 1, oraz bity 16-31 służą do wysterowania logicznie na 0 pinów od 0 do 15 także poprzez wstawienie tam wartości logicznej 1.
    Tabela rejestru GPIO z opisem funkcji bitów ustawiania i resetowania dla portów I/O.
    Chyba, że przyszło mi do głowy, że rejestr sam się nie czyści po ustawieniu tej jedynki. To wpisuję set PA12, potem reset PA12 ale te jedynki ciągle zostają. Chociaż poniżej jest napisane, że jeśli oba mają wpisaną jedynkę to BSx ma priorytet więc dioda i tak powinna być załączona cały czas.
    Edit: sprawdziłem dla pewności, modyfikacja while w taki sposób nic nie zmienia.
    while (1) {
    		//Ustaw PA12 HIGH
    		GPIOA->BSRR = ~(GPIO_BSRR_BR12);
    		GPIOA->BSRR = GPIO_BSRR_BS12;
    
    		Delay(500);
    
    		//Ustaw PA12 LOW
    		GPIOA->BSRR = ~(GPIO_BSRR_BS12);
    		GPIOA->BSRR = GPIO_BSRR_BR12;
    		Delay(500);
    
    	}


    Drugi edit: nie wpisuję dwa razy tego samego odnośnie pierwszego zdania - korzystam z tego rejestru podzielonego na dwie części, ale zmodyfikowałem kod aby wykorzystać do resetu rejestr BRR. Ta sama sytuacja.
    while (1) {
    		//Ustaw PA12 HIGH
    		GPIOA->BSRR = GPIO_BSRR_BS12;
    		Delay(500);
    
    		//Ustaw PA12 LOW
    		GPIOA->BRR = GPIO_BRR_BR12;
    		Delay(500);
    	}



    Stwierdziłem, że najpierw wypadałoby załączyć diodę LED a później się martwić jej wyłączeniem więc sprawdziłem też rejestr ODR zamiast BSRR, także zero reakcji diody.

    while (1) {
    		//Ustaw PA12 HIGH
    		GPIOA->ODR = GPIO_ODR_OD12;
    		Delay(500);
    
    		//Ustaw PA12 LOW
    		GPIOA->BRR = GPIO_BRR_BR12;
    		Delay(500);
    	}


    Przy rejestrze ODR jest nawet informacja, że dla kontrolowania pojedynczych portów bity OD mogą być indywidualnie modyfikowane właśnie przez rejestr BSRR.
  • #5 20824770
    jarekgol
    Poziom 40  
    Posty: 5176
    Pomógł: 644
    Ocena: 1146
    Źle popatrzyłem w twój kod i wygląda na to że miałeś inne literki do zapisu BSRR. Rozejrzę się z ciekawości po dokumentacji i może coś wymyślę.
    Na razie olej pętle i delaye, wpisz do ODR same jedynki i zakończ while(1);
    Zobacz diodę, ale zmierz też woltomierzem co się tam dzieje.
    Zastanów się też czy linker Ci nie nie dodaje jakiś wstępnych ustawień rejestrów / zegarów w ramach "start-upu".
  • #6 20824774
    Maniek275
    Poziom 5  
    Posty: 22
    Ocena: 4
    Tak, w drugim projekcie na poziomie HALa przy tych samych ustawieniach wyjścia GPIO PA12 jak na rejestrach ustawiłem program działa w pełni poprawnie. Ktoś wspomniał o optymalizacji pętli for po czym odpowiedź została usunięta - o co chodzi z tą optymalizacją? Jeśli pętla zostanie wstawiona do kodu ale w środku nic nie będzie się działo, czyli pętla będzie iteracyjnie się zwiększała bez efektu to zostanie pominięta? Jeśli o to chodzi to dodałem też do środka zmienną aby osobno się zwiększała po za samym uint32_t i, i działa tak samo, czyli nie działa.
  • #7 20824811
    jarekgol
    Poziom 40  
    Posty: 5176
    Pomógł: 644
    Ocena: 1146
    Maniek275 napisał:
    o co chodzi z tą optymalizacją? Jeśli pętla zostanie wstawiona do kodu ale w środku nic nie będzie się działo, czyli pętla będzie iteracyjnie się zwiększała bez efektu to zostanie pominięta?

    Tak się zdarza. Można dodać asemblerowe NOP do środka, lub zwiększać zmienna typu volatile.
  • #8 20824825
    simw
    Poziom 27  
    Posty: 758
    Pomógł: 94
    Ocena: 288
    To ja pisałem o pętli for, ale walnąłem innego "babola" i poszedł wpis do kosza :)
    Czy pętla for się wykonuje należy podejrzeć w pliku .list.
    Pisałem też o tym, czy jesteś pewien, że startup w okrojonej wersji masz poprawny, że w ogóle procesor startuje, system_init() wektory przerwań itd.

    Ja standardowo "golę" HALa, wygenerowanego przez CubeIDE, gdy mam pisać w bare metal, w ten sposób mam poprawnie zainicjowany system, oczywiście całość można też pchać przez własny makefile.
  • #9 20824849
    jarekgol
    Poziom 40  
    Posty: 5176
    Pomógł: 644
    Ocena: 1146
    Zdaje się w platformio można wybrać libopencm3 i startup już tam jest. Ja m.in tego używałem. Raz dla sportu napisałem coś w asm i walczyłem z gcc none-eabi i takimi tam, ale nie chciałbym do tego wracać. VSCode + platformio jest bardziej przyjazne, a da się w tym bez hala pisać.
  • #10 20824864
    Maniek275
    Poziom 5  
    Posty: 22
    Ocena: 4
    >>20824770
    Podłączyłem do oscyloskopu zamiast do woltomierza, jak szaleć to po całości. Przeszedłem krok po kroku po programie zarówno z diodą wpiętą do tego wejścia jak i bez, masa oscyloskopu do GND mikrokontrolera, sonda do pinu PA12. Oto co otrzymałem - dwa poniższe rysunki to w momencie przejścia z linijki ustawiania starszego bitu rejestru MODER do rejestru OTYPER.
    Ekran oscyloskopu z wykresami przebiegu napięcia. Zrzut ekranu z oscyloskopu pokazujący przebieg napięcia, z wyróżnionym poziomym odcinkiem sygnału, który gwałtownie się obniża.
    Kolejne zdarzenie miało miejsce dopiero w momencie przechodzenia z linijki ODR_OD12 na ODR_OD13.
    Zrzut ekranu z oscyloskopu z przebiegiem prostokątnym. Wykres sygnału na oscyloskopie z wyraźnym impulsem.

    Edit: zdecydowanie nie pasuje mi to co widzę na oscyloskopie, odłączyłem USB i ujemne napięcie się unormowało. Zaraz przeprowadzę pomiary jeszcze raz.

    Edit2: nie wiem dlaczego ale mając podłączony przewód USB do eksportu danych do laptopa miałem potężne zakłamania jak widać na tych czterech rysunkach. Na ten moment na wyjściu panuje niemalże idealna cisza więc bardzo fałszywy alarm, do każdego bitu w rejestrze ODR wpisałem jedynkę i nic się nie zmienia.
  • #11 20824878
    jarekgol
    Poziom 40  
    Posty: 5176
    Pomógł: 644
    Ocena: 1146
    No właśnie chciałem zapytać czemu to na minus idzie.
    O jakie ODR_OD13 chodzi? I jaki jest aktualnie program, bo wrzucałeś powyżej jakieś modyfikacje.
    Spróbuj zapisać jedynkę na port i nic nie zmieniać w pętlach. Jak będzie napięcie to obciąż opornikiem żeby sprawdzić czy to wyjście czy pullup wejścia.
    Co to za płytka? Jakieś nucleo? Bluepill? własna?

    ps. jak masz oscyloskop, to rozważ właczenie pinów MCO i je sobie obejrzyj.
  • #12 20824890
    Maniek275
    Poziom 5  
    Posty: 22
    Ocena: 4
    Oto kod:
    
    #include <stdint.h>
    #include "stm32c011xx.h"
    
    __IO uint32_t Tick;
    
    void SysTick_Handler(void) {
    	Tick++;
    }
    
    void Delay(uint32_t Delay_ms) {
    	uint32_t StartTime = Tick;
    
    	while (Tick < (StartTime + Delay_ms)) {
    
    	}
    }
    
    int main(void) {
    	SysTick_Config(12000);
    
    	//RCC I/O port clock enable register GPIOA
    	RCC->IOPENR |= RCC_IOPENR_GPIOAEN;
    
    	//Ustawienie PA12 OUTPUT
    	GPIOA->MODER |= GPIO_MODER_MODE12_0;
    	GPIOA->MODER &= ~( GPIO_MODER_MODE12_1);
    
    	// Ustawienie PA12 jako Push-pull
    	GPIOA->OTYPER |= GPIO_OTYPER_OT12;
    
    	// Ustawienie PA12 jako low speed
    	GPIOA->OSPEEDR |= GPIO_OSPEEDR_OSPEED12_0;
    	GPIOA->OSPEEDR &= ~(GPIO_OSPEEDR_OSPEED12_1);
    
    	// Ustawienie PA12 jako no pull-up i no pull-down
    	GPIOA->PUPDR &= ~(GPIO_PUPDR_PUPD12_0);
    	GPIOA->PUPDR &= ~(GPIO_PUPDR_PUPD12_1);
    	/*
    	uint32_t i, j = 0;
    	//Wejście do nieskończonej pętli
    	while (1) {
    		//Ustaw PA12 HIGH
    		GPIOA->ODR = GPIO_ODR_OD12;
    		for (i = 0; i < 99999; i++) {
    			j++;
    		}
    		j = 0;
    
    		//Ustaw PA12 LOW
    		GPIOA->BRR = GPIO_BRR_BR12;
    		for (i = 0; i < 99999; i++) {
    			j++;
    		}
    		j = 0;
    	}
    	*/
    	GPIOA->ODR = GPIO_ODR_OD1;
    	GPIOA->ODR = GPIO_ODR_OD2;
    	GPIOA->ODR = GPIO_ODR_OD3;
    	GPIOA->ODR = GPIO_ODR_OD4;
    	GPIOA->ODR = GPIO_ODR_OD5;
    	GPIOA->ODR = GPIO_ODR_OD6;
    	GPIOA->ODR = GPIO_ODR_OD7;
    	GPIOA->ODR = GPIO_ODR_OD8;
    	GPIOA->ODR = GPIO_ODR_OD9;
    	GPIOA->ODR = GPIO_ODR_OD10;
    	GPIOA->ODR = GPIO_ODR_OD11;
    	GPIOA->ODR = GPIO_ODR_OD12; [url=https://obrazki.elektroda.pl/5401406500_1700502107.png][img]https://obrazki.elektroda.pl/5401406500_1700502107_thumb.jpg[/img][/url] 
    	GPIOA->ODR = GPIO_ODR_OD13;
    	GPIOA->ODR = GPIO_ODR_OD14;
    	GPIOA->ODR = GPIO_ODR_OD15;
    }
    


    Bit dotyczący wysterowania poszczególnego pinu z portu GPIOA w tym wypadku 13, ale siało zakłócenia więc tutaj nie ma co nad tym dywagować, że się coś pojawiło.

    Płytka do WeActStudio STM32 C011F6P6. Poniżej wizualizacja płytki i schematy do niej.
    Płytka WeActStudio STM32 C011F6P6 z widocznymi wyprowadzeniami i elementami.
    Schemat płytki rozwojowej WeAct Studio STM32 C011F6P6

    >>20824878 odnośnie wystawienia zegara na MCO piny, dopiero zaczynam z rejestrami ale przeszukałem dokumentację, nie widzę nigdzie alternatywnych funkcji pinów jako to wyjście zewnętrzne. Ale co mnie zaciekawiło - w dokumentacji, na stronie 120 istnieją rejestry do konfiguracji MCO, mają one 3 bity dla przykładowo MCOPRE - zdjęcie poniżej. Z kolei w STMCubeIde mam do wyboru cztery bity i zastanawiam się teraz czy czasami plik z definicjami rejestrów nie jest błędny - zdjęcie także poniżej.
    Widok konfiguracji rejestru zegara RCC w STM32. Fragment dokumentacji rejestrów mikrokontrolera, dotyczący preskalera MCO z trzema bitami konfiguracyjnymi.
  • #13 20824940
    simw
    Poziom 27  
    Posty: 758
    Pomógł: 94
    Ocena: 288
    Opis funkcji alternatywnych masz w Datasheet, nie w RM
    Nie zapominaj też CubeMX, również stamtąd możesz wygenerować listę funkcji alt. do csv. Widok zegarów i mux'ów może być przydatna


    Schemat zegarów dla mikrokontrolera z różnymi źródłami taktowania.

    Dodano po 12 [minuty]:

    Ach jeszcze to
    PA12 współdzieli pin z z innymi pinami [PA10]
    Trzeba sprawdzić, co jest domyślnie po resecie
    Widzę, ze tu jest całkiem podobnie jak w F042F6P6

    Schemat połączeń mikrokontrolera STM32 z zaznaczonymi pinami PA11 i PA12.

    PA13 to po resecie SWD, więc dlatego tam były "śmieci".
    PA12 to jednak default na pinie po resecie.

    Fragment dokumentacji dotyczącej remapowania i konfiguracji pinów PA9, PA10, PA11, PA12, PA13 i PA14.
  • #14 20824978
    Maniek275
    Poziom 5  
    Posty: 22
    Ocena: 4
    Ustawiłem GPIO PA8 jako Alternate function, ale przypisanie już AF0 czyli wyjścia MCO jest już problematyczne.
    Brak migania diody na mikrokontrolerze STM32 C011: konfiguracja pinów GPIO i rejestry
    Powinienem wstawić tam cztery zera jako, że jest to AF0 czyli 0000, próbuję ustawić od razu wszystkie cztery bity jednocześnie jako zero i mam błąd jak na zdjęciu. Poszczególne ustawianie pojedynczych bitów wywołuje ten sam błąd. Do tego zastanawiam się dlaczego nie zgadza się tutaj nazwa rejestru GPIOA->AFR zamiast AFRL. Wstawiając AFRL nie wykrywa mi czegoś takiego.
  • #15 20824990
    simw
    Poziom 27  
    Posty: 758
    Pomógł: 94
    Ocena: 288
    Bo używasz maski, a nie bitu
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod


    Wg mnie powinieneś polecieć na kanał Salamona i popatrzeć jak tam C011 pokazywał na rejestrach.
    Wg mnie nie korzystasz z podpowiedzi chyba, nie zaglądasz do plików nagłówkowych Ctrl+LClick, to co wrzuciłem wyżej to właśnie skopiowane z nagłówka CMSIS

    Nie, bzdurę napisałem.
    Tam te rejestry są jako tablica.
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod
  • #16 20825011
    Maniek275
    Poziom 5  
    Posty: 22
    Ocena: 4
    Spróbowałem maski, ale też wspomniałem, że dokładnie takim samym błędem kończy się poszczególne ustawianie bitów jak robię to na całej reszcie rejestrów. Salmona widziałem, z tym, że on korzystał z STM32 C031, co prawda dokumentacja z której korzystał jak na razie pokrywa się, tak jemu sterowanie diodą zadziałało od razu, tak mi już nie działa. Inna sprawa też, że on sterował diodą, która w nucleo już jest wbudowana i sterowanie polegało na wysterowaniu mosfeta z podpiętym pull-upem, ja mam diodę na sztywno z rezystorem podpiętą PA12 - GND. Chociaż akurat to kto jak diodę ma to nie wiele zmienia, bo chodzi o uzyskanie czegokolwiek na wyjściu pinu.

    Edit: zacząłem pisać od razu w odpowiedzi na tamten post, wstawiając GPIOA->AFR[0] kod się skompilował. Po wgraniu na oscyloskopie cisza na pinie PA8. Poniżej cały zmodyfikowany kod, usunąłem funkcję od odmierzania czasu bo i tak jest bezużyteczna a zajmuje miejce.
    #include <stdint.h>
    #include "stm32c011xx.h"
    
    int main(void) {
    	
    	//RCC I/O port clock enable register GPIOA
    	RCC->IOPENR |= RCC_IOPENR_GPIOAEN;
    
    	//Ustawienie PA8 jako Alternate function
    	GPIOA->MODER |= GPIO_MODER_MODE8_0;
    	GPIOA->MODER |= GPIO_MODER_MODE8_1;
    
    	//Ustawienie PA8 jako MCO - AF0
    	GPIOA->AFR[0] &= ~(GPIO_AFRL_AFSEL0);
    
    	//Ustawienie PA12 OUTPUT
    	GPIOA->MODER |= GPIO_MODER_MODE12_0;
    	GPIOA->MODER &= ~(GPIO_MODER_MODE12_1);
    
    	// Ustawienie PA12 jako Push-pull
    	GPIOA->OTYPER |= GPIO_OTYPER_OT12;
    
    	// Ustawienie PA12 jako low speed
    	GPIOA->OSPEEDR |= GPIO_OSPEEDR_OSPEED12_0;
    	GPIOA->OSPEEDR &= ~(GPIO_OSPEEDR_OSPEED12_1);
    
    	// Ustawienie PA12 jako no pull-up i no pull-down
    	GPIOA->PUPDR &= ~(GPIO_PUPDR_PUPD12_0);
    	GPIOA->PUPDR &= ~(GPIO_PUPDR_PUPD12_1);
    	/*
    	while (1) {
    		GPIOA->ODR = GPIO_ODR_OD12;
    		GPIOA->BRR = GPIO_BRR_BR12;
    	}
    	*/
    	GPIOA->ODR = GPIO_ODR_OD1;
    	GPIOA->ODR = GPIO_ODR_OD2;
    	GPIOA->ODR = GPIO_ODR_OD3;
    	GPIOA->ODR = GPIO_ODR_OD4;
    	GPIOA->ODR = GPIO_ODR_OD5;
    	GPIOA->ODR = GPIO_ODR_OD6;
    	GPIOA->ODR = GPIO_ODR_OD7;
    	GPIOA->ODR = GPIO_ODR_OD8;
    	GPIOA->ODR = GPIO_ODR_OD9;
    	GPIOA->ODR = GPIO_ODR_OD10;
    	GPIOA->ODR = GPIO_ODR_OD11;
    	GPIOA->ODR = GPIO_ODR_OD12;
    	GPIOA->ODR = GPIO_ODR_OD13;
    	GPIOA->ODR = GPIO_ODR_OD14;
    	GPIOA->ODR = GPIO_ODR_OD15;
    }
    
  • #17 20825013
    simw
    Poziom 27  
    Posty: 758
    Pomógł: 94
    Ocena: 288
    Faktycznie to był C031
    Wróć jeszcze do ost. mojego wpisu, bo został zmodyfikowany.
    Niski rejestr L jest pod zerowym indeksem, H pod pierwszym.

    Dodano po 4 [minuty]:

    Najwyższa pora byś zdradził jak inicjalizujesz procka :)
    Jakiego środowiska używasz, jak dołączasz CMSIS, bo wg mnie to powinno działać.

    Dodano po 10 [minuty]:

    Choć nie do końca dobrze.
    Dla pinu PA8 powinieneś skorzystać z rejestru H
    PA8 to już 9 pin licząc od zera
    Tylko, że po resecie tam już będzie AF0
    Musisz jeszcze rejestr GPIOx_MODER skonfigurować.

    Fragment dokumentacji opisujący multiplekser funkcji alternatywnych dla pinów GPIO.
  • #18 20825042
    Maniek275
    Poziom 5  
    Posty: 22
    Ocena: 4
    Zacząłem od utworzenia projektu dawcy na HALu. Stamtąd skopiowałem folder Drivers -> CMSIS z całą zawartością w tym folderze. Wkleiłem go do pustego projektu gdzie teraz operuję na rejestrach, a następnie w properties, C/C++ General, Paths and Symbols wkleiłem ścieżkę do Drivers/CMSIS/Device/ST/STM32C0xx/Include oraz Drivers/CMSIS/Include. W zakładce C/C++ Build w zakładce MCU GCC Compiler, w zakładce Include Paths dodałem dokładnie to samo co wcześniej. W zakładce Preprocessor dodałem symbol STM32C011xx. Więcej nie pamiętam abym coś dodawał/zmieniał/usuwał.

    Edit: MODER wcześniej się znalazł - ustawiam dwie jedynki czyli alternate function.
    //Ustawienie PA8 jako Alternate function
    	GPIOA->MODER |= GPIO_MODER_MODE8_0;
    	GPIOA->MODER |= GPIO_MODER_MODE8_1;


    Edit2: faktycznie widzę błąd, to już chyba zmęczenie, poprawiłem to na rejestr H:
    //Ustawienie PA8 jako MCO - AF0
    	GPIOA->AFR[1] &= ~(GPIO_AFRH_AFSEL8_0);
    	GPIOA->AFR[1] &= ~(GPIO_AFRH_AFSEL8_1);
    	GPIOA->AFR[1] &= ~(GPIO_AFRH_AFSEL8_2);
    	GPIOA->AFR[1] &= ~(GPIO_AFRH_AFSEL8_3);

    Ale czy mógłbyś objaśnić dlaczego tutaj jest albo powinno być coś innego w nawiasach kwadratowych? AFR[0] zakładam, że jak odnosi się do rejestru L, a jak do rejestru H to AFR[1]?
  • #19 20825062
    simw
    Poziom 27  
    Posty: 758
    Pomógł: 94
    Ocena: 288
    No cóż bez płytki i proca nic chyba już nie wymyśle.
    Gdy dochodzę do takiej ściany, to zaczynam porównywać rejestry w debug'u na HALu do tego na rejestrach.

    Dodano po 6 [minuty]:

    Tak sobie wymyślili
    Musisz tam wpisywać do AFR[1].
    W pliku jest to dokładnie rozpisane

    Kod: C / C++
    Zaloguj się, aby zobaczyć kod
  • #20 20825117
    jarekgol
    Poziom 40  
    Posty: 5176
    Pomógł: 644
    Ocena: 1146
    A Ty masz ten procesor G jak w temacie czy C jak w dokumentacji którą załączyłeś?
    Zobacz może w tą od G ? Wg niej MCO włącza się w Clock configuration register (RCC_CFGR) czy trzeba jakieś AFIO to jeszcze spróbuję doczytać.
    Ok, czyli u mnie (nucleo z F103) trzeba było zadbać o zegar dla "alternate function", ale u Ciebie na rysunku zegarów nie jest to opisane. Być może jak włączysz podzielnik z 0 na 1 w tym rcc i skonfigurujesz te MCO na pin to wtedy się coś pokaże.
    Możesz też na próbę przepuścić to przez platformio, jest za darmo.
    Załączniki:
    • rm0444-stm32g0x1-advanced-armbased-32bit-mcus-stmicroelectronics.pdf (16.63 MB) Musisz być zalogowany, aby pobrać ten załącznik.
  • #21 20825120
    simw
    Poziom 27  
    Posty: 758
    Pomógł: 94
    Ocena: 288
    jarekgol napisał:
    A ty masz ten procesor G jak w temacie czy C jak w dokumentacji którą załączyłeś?

    G to nie może być, bo nie ma serii G011. Najniższa to G031, bodajże.
  • #22 20825155
    Maniek275
    Poziom 5  
    Posty: 22
    Ocena: 4
    C011. Dla pewności wrzucam zdjęcie.
    Zbliżenie mikroprocesora na płytce prototypowej z oznaczeniami pinów.
  • #23 20825159
    jarekgol
    Poziom 40  
    Posty: 5176
    Pomógł: 644
    Ocena: 1146
    @Maniek275 to popraw temat dla porządku. I spójrz wyżej bo coś tam pisałem jak nowe posty wpadły.
  • Pomocny post
    #24 20825289
    simw
    Poziom 27  
    Posty: 758
    Pomógł: 94
    Ocena: 288
    Czy działa Systick to łatwo sprawdzić w debuggerze.
    Zresztą wiele spraw można sprawdzić.
    Ja bym zaczął od tego czy właściwe rejestry podlegają zmianom.
    To nie jest nic trudnego, w krokowym trybie
    Też jaka wartość jest SystemCoreClock, to zmienna globalna.
    Może ląduje gdzieś w HardFault, zaraz po uruchomieniu.

    EDIT.
    Często problemem przy kopiowaniu plików, sa złe pliki.
    Należy sprawdzić plik startup "startup_stm32c011f6px.s" czy jest taki od właściwego pliku, no i plik linkera "STM32C011F6PX_FLASH.ld"
  • #25 20825410
    Maniek275
    Poziom 5  
    Posty: 22
    Ocena: 4
    W platformIO nie ma niestety C011.

    Odnośnie odczytywania rejestrów, o ile dobrze zrobiłem to wszędzie zastosowałem takie coś:
    RCC->IOPENR |= RCC_IOPENR_GPIOAEN; // odczytano bit = 1
    	if(RCC->IOPENR & RCC_IOPENR_GPIOAEN){
    		status = 1;
    	} else {
    		status = 2;
    	}
    	status = 0;

    Zapisałem sobie w komentarzach wartość statusu i wszędzie odczytałem, że w rejestrach są spodziewane wartości.

    Plik linkera wydaje mi się, że został samoczynnie wygenerowany, startup tak samo. W każdym razie znajdują się tam i nie widzę raczej powodu dlaczego miałyby być nieprawidłowe

    Natomiast odnośnie globalnej zmiennej SystemClockCore, nie potrafię jej zadeklarować w live expression ani w expression.

    Na próbę tworzę jeszcze jeden projekt i zastanawia mnie opcja executable i static library, wcześniej na 99% wybrałem pierwszą opcję. Reszta bez zmian.
    Zrzut ekranu opcji konfiguracji nowego projektu w platformIE.
    A tak wygląda świeżo utworzony projekt:
    Zrzut ekranu z widokiem projektu w STM32CubeIDE przedstawiający strukturę katalogów i plików.
  • #26 20825479
    jarekgol
    Poziom 40  
    Posty: 5176
    Pomógł: 644
    Ocena: 1146
    Masz łączność debugerem z tym prockiem? Daje radę wykonywać program krok po kroku? Bo w F103 dało się rejestry po prostu oglądać. Próbowałeś z tym MCO i ustawieniem podzielnika i oscyloskopem?
  • #27 20825483
    Maniek275
    Poziom 5  
    Posty: 22
    Ocena: 4
    Tak, łączność debugerem mam, odczytywałem rejestry i porównywałem sobie spodziewane wyniki z otrzymanymi. Krok po kroku również działa, wtedy co siało zakłócenia na USB dzięki niemu wiedziałem w którym momencie te dziwne sygnały mimo, że zakłócenia to jednak się pojawiły.

    Odnośnie MCO sprawdzę to jutro z rana bo głowa mi lekko paruje od tego.

    Dodano po 11 [godziny] 1 [minuty]:

    Chyba zapeszyłem wczoraj z tą łącznością. Kod napisałem, nie podoba mi się to, że w podpowiedziach mogłem wpisywać wartości do czterech bitów w rejestrze podczas gdy w dokumentacji są trzy pola bitów zarówno dla MCOPRE oraz MCOSEL. Napisałem zatem ten kod:
    // RCC clock configuration register, clock output prescaller - 1 = 000
     	RCC->CFGR &= ~(1 << 28);
     	RCC->CFGR &= ~(1 << 29);
     	RCC->CFGR &= ~(1 << 30);
    
     	// RCC clock configuration register, clock output selectror - SYSCLK = 001
     	RCC->CFGR |= (1 << 24);
     	RCC->CFGR &= ~(1 << 25);
     	RCC->CFGR &= ~(1 << 26);

    Ale mam teraz problem z wgraniem go. Sprawdziłem to na dwóch st-linkach na wszelki wypadek i za każdym razem zgłasza ten sam błąd:
    STMicroelectronics ST-LINK GDB server. Version 7.4.0
    Copyright (c) 2023, STMicroelectronics. All rights reserved.

    Starting server with the following options:
    Persistent Mode : Disabled
    Logging Level : 1
    Listen Port Number : 61234
    Status Refresh Delay : 15s
    Verbose Mode : Disabled
    SWD Debug : Enabled
    InitWhile : Enabled

    Failed to bind to port 61235, error code -1: No error
    Failure starting SWV server on TCP port: 61235
    Failed to bind to port 61234, error code -1: No error
    Failure starting GDB server: TCP port 61234 not available.
    Shutting down...
    Exit.

    Nie działa wgrywanie kodu zarówno na tym projekcie z rejestrami jak i na projekcie dawcy z HALem.
  • Pomocny post
    #28 20825962
    jarekgol
    Poziom 40  
    Posty: 5176
    Pomógł: 644
    Ocena: 1146
    Głupie pytanie, ale restartowałeś komputer? Bo wygląda jakby port tcp był zajęty i to teraz jest ewidentie problem z st linkiem, nie twoim programem. Zobacz w procesach czy już jakiś nie jest odpalony w tle, może coś się do autostartu w windowsie dodało.
  • #29 20826042
    Maniek275
    Poziom 5  
    Posty: 22
    Ocena: 4
    Akurat mądre pytanie, laptop był wyłączony w nocy. Nie resetowałem go zatem w monecie gdy błąd wystąpił, po resecie mam możliwość wgrania programu ale na wyjściu PA8 z tym kodem nie widzę nic na wyjściu. Postanowiłem w tym momencie calutką płytkę przejrzeć oscyloskopem i moje obserwacje na tą chwilę:

    Brak migania diody na mikrokontrolerze STM32 C011: konfiguracja pinów GPIO i rejestry
    PB7 - 0V
    OSCX IN - 0V
    OSCX OUT - 0V
    VDD - 3.39V
    VSS - 0V
    NRST - 3.45V
    PA0 - 0V
    PA1 - 0V
    PA2 - 0V
    PA3 - 0V
    PA4 - 0.96V
    PA5 - 0V
    PA6 - 0V
    PA7 - 0V
    PA8 - 0V
    PA11/PA9 - 0V
    PA12/PA10 - 0V
    PA13 - 3.33V
    PA14/BOOT - 0V
    PB6 - 0V

    Wejście stabilizatora liniowego 5.22V
    Wyjście stabilizatora liniowego 3.38V
    Wciśnięcie przycisku NRST zaniża napięcie z 3.3 do 0V czyli poprawnie
    Wciśnięcie przycisku PA14 powoduje wzrost napięcia z 0V do 3.3, czyli poprawnie
    Na rezystor przed diodą trafia 3.3V, za diodą mam już 0.9V, z racji, że pin PA4 nie jest skonfigurowany, nie ma przejścia do masy i dioda się nie zapala.
    Z racji, że na zasilaniu kryształu nie ma napięcia przyłożonego, nie może on generować sygnału więc logicznym jest brak sygnału zegarowego zewnętrznego
    Debugowanie mam wyłączone zatem na pinach PA13 ani PA14 nie uświadczę niczego, także w pełni poprawnie.
    Cały schemat przejrzałem i sprawdziłem, wszystko wygląda w pełni logicznie

    Dodano po 10 [minuty]:

    Czas na wielką magię. Skonfigurowałem pin PA4 dokładnie tak samo jak PA8 i magia. Dioda wbudowana w płytce zaczęła mrugać. Do odmierzania czasu użyłem prymitywnej pętli for, zarówno z zmienną volatile jak i bez jak ktoś wcześniej wspominał o optymalizacji, dioda dalej mruga. Bez konfiguracji clock output prescaller oraz selector dioda dalej mruga. Aktualnie kod wygląda w następujący sposób:
    #include <stdint.h>
    #include "stm32c011xx.h"
    
    int main(void) {
    
    	//RCC I/O port clock enable register GPIOA
    	RCC->IOPENR |= RCC_IOPENR_GPIOAEN;
    
    	//Ustawienie PA4 jako OUTPUT
    	GPIOA->MODER |= GPIO_MODER_MODE4_0;
    	GPIOA->MODER &= ~(GPIO_MODER_MODE4_1);
    
    	// Ustawienie PA4 jako Push-pull
    	GPIOA->OTYPER |= GPIO_OTYPER_OT4;
    
    	// Ustawienie PA4 jako low speed
    	GPIOA->OSPEEDR |= GPIO_OSPEEDR_OSPEED4_0;
    	GPIOA->OSPEEDR &= ~(GPIO_OSPEEDR_OSPEED4_1);
    
    	// Ustawienie PA4 jako no pull-up i no pull-down
    	GPIOA->PUPDR &= ~(GPIO_PUPDR_PUPD4_0);
    	GPIOA->PUPDR &= ~(GPIO_PUPDR_PUPD4_1);
    
    	uint32_t j = 0;
    	while (1) {
    		GPIOA->ODR = GPIO_ODR_OD4;
    		for (uint32_t i = 0; i < 99999; i++) {
    			j++;
    		}
    		j = 0;
    		GPIOA->BRR = GPIO_BRR_BR4;
    		for (uint32_t i = 0; i < 99999; i++) {
    			j++;
    		}
    		j = 0;
    	}
    }


    Program działa również z wcześniej wykorzystywanym rejestrem BSRR. Problem rozwiązany chociaż nie wiadomo gdzie był problem z pinem PA8.
  • #30 20826065
    Maniek275
    Poziom 5  
    Posty: 22
    Ocena: 4
    Zmiana portu z PA8 na PA4

Podsumowanie tematu

✨ Dyskusja dotyczy problemu z miganiem diody podłączonej do mikrokontrolera STM32 C011. Użytkownik skonfigurował piny GPIO, ale dioda nie reaguje. W odpowiedziach zasugerowano użycie rejestrów BSRR i BRR do ustawiania stanów pinów, a także sprawdzenie, czy rejestry są poprawnie inicjalizowane. Użytkownik testował różne metody, w tym użycie oscyloskopu do analizy sygnałów na pinach. Wskazano również na konieczność poprawnej konfiguracji rejestrów alternatywnych funkcji oraz sprawdzenia, czy system jest poprawnie zainicjowany. Problemy z zakłóceniami sygnału były również omawiane, a użytkownik podjął kroki w celu ich eliminacji.
Podsumowanie AI na podstawie dyskusji. Może zawierać błędy.
REKLAMA