Skocz do zawartości

Przeszukaj forum

Pokazywanie wyników dla tagów 'stm32'.

  • Szukaj wg tagów

    Wpisz tagi, oddzielając przecinkami.
  • Szukaj wg autora

Typ zawartości


Kategorie forum

  • Elektronika i programowanie
    • Elektronika
    • Arduino i ESP
    • Mikrokontrolery
    • Raspberry Pi
    • Inne komputery jednopłytkowe
    • Układy programowalne
    • Programowanie
    • Zasilanie
  • Artykuły, projekty, DIY
    • Artykuły redakcji (blog)
    • Artykuły użytkowników
    • Projekty - roboty
    • Projekty - DIY
    • Projekty - DIY (początkujący)
    • Projekty - w budowie (worklogi)
    • Wiadomości
  • Pozostałe
    • Oprogramowanie CAD
    • Druk 3D
    • Napędy
    • Mechanika
    • Zawody/Konkursy/Wydarzenia
    • Sprzedam/Kupię/Zamienię/Praca
    • Inne
  • Ogólne
    • Ogłoszenia organizacyjne
    • Dyskusje o FORBOT.pl
    • Na luzie
    • Kosz

Szukaj wyników w...

Znajdź wyniki, które zawierają...


Data utworzenia

  • Rozpocznij

    Koniec


Ostatnia aktualizacja

  • Rozpocznij

    Koniec


Filtruj po ilości...

Data dołączenia

  • Rozpocznij

    Koniec


Grupa


Znaleziono 67 wyników

  1. Witajcie Realizuję komunikację pomiędzy mikroprocesorem STM32F411RE (NUCLEO) a modułem SIM800L. Wykorzystuję do tego interfejs UART. Inicjalizuję go poprzez bibliotekę HAL'a. Samą wymianę danych postanowiłem zrobić ręcznie, odwołując się bezpośrednio do rejestrów UART. Poniżej funkcja inicjalizacyjna: void uart_init(uint32_t baud) { uart_gpio.Pin = GPIO_PIN_9 | GPIO_PIN_10; //TX RX uart_gpio.Mode = GPIO_MODE_AF_PP; uart_gpio.Alternate = GPIO_AF7_USART1; uart_gpio.Speed = GPIO_SPEED_HIGH; uart_gpio.Pull = GPIO_PULLUP; HAL_GPIO_Init(GPIOA,&uart_gpio); usart.Instance = USART1; usart.Init.BaudRate = baud; usart.Init.Parity = USART_PARITY_NONE; usart.Init.StopBits = USART_STOPBITS_1; usart.Init.WordLength = USART_WORDLENGTH_8B; usart.Init.Mode = USART_MODE_TX_RX; HAL_USART_Init(&usart); } Sama komunikacja odbywa się w funkcji "sim_reception", w przerwaniu od timera mikroprocesora. #define SIM_TX_BUF_SIZE 32 #define SIM_RX_BUF_SIZE 32 volatile unsigned char sim_tx_buf[SIM_TX_BUF_SIZE]; volatile unsigned char sim_rx_buf[SIM_RX_BUF_SIZE]; volatile unsigned char sim_tx_len = 0; volatile unsigned char sim_rx_len = 0; enum { handshake, hdsh_resp }; volatile uint8_t sim_states = handshake; #define SIM_HNDSHK "AT\r\n" void sim_reception(void) { //RX //if Receiver not empty flag is set and we have space in rx buffer, we read byte while(USART1 -> SR & USART_SR_RXNE) { if(sim_rx_len < SIM_RX_BUF_SIZE) sim_rx_buf[sim_rx_len++] = USART1 -> DR; //after reading byte we increment buffer length else break; } //TX //if Transmitter empty flag is set and we have data in tx buffer, we send byte while(USART1 -> SR & USART_SR_TXE) { if(sim_tx_len != 0) { USART1 -> DR = sim_tx_buf[0];//send one byte sim_byte_up(sim_tx_buf); //shift one byte up } else break; } switch(sim_states) { case handshake: sim_tx_buf_put(SIM_HNDSHK); sim_states = hdsh_resp; break; case hdsh_resp: break; default: sim_states = handshake; break; } } Na razie chcę wysłać tylko jedno polecenie i odczytać odpowiedź modułu SIM800L. Krótko opiszę nadawanie, które działa bez zarzutu. Wywołuję funkcję "sim_tx_buf_put", która napełnia bufor komendą "SIM_HNDSHK", zdefiniowaną wyżej za pomocą #define. Funkcja bada ile miejsca mamy w buforze i czy wystarczy go jeszcze dla nowego polecenia. Jeśli tak to wstawia je bajt po bajcie i zwiększa odpowiednio zmnienną "sim_tx_len". Nie będe wstawiał kodu tej funkcji, ponieważ działa ona bardzo dobrze, nie mam z nią problemu. Wyżej w kodzie widać, że jest badany stan flagi "Transmitter Empty", gdy się ona pojawi i w buforze Tx są dane przystępuje się do wysyłania danych bajt po bajcie. Po każdym wysłanym bajcie wywoływana jest funkcja "sim_byte_up", która przesuwa bajty bufora "o jeden w górę", czyli sim_tx_buf[0] = sim_tx_buf[1], sim_tx_buf[1] = sim_tx_buf[2] itd. oraz zmniejsza wartość "sim_tx_len" o jeden, następnie wysyłany jest kolejny bajt i tak do opróżnienia bufora. Nadajnik działa jak należy, co pokazuje screenshot z analizatora stanów logicznych. Po wysłaniu wiadomości "AT\r\n" moduł SIM800L odsyła odpowiedź. Zatem flaga "Receiver Not Empty" powinna zostać aktywowana, bufor Rx jest pusty, tak więc coś powinno zostać zapisane w buforze. Jednak nic takiego się nie dzieje. Screenshoty z debugowania. W buforze Rx pojawia się tylko jeden bajt o wartości 127. Dalszych procedur odbioru nawet nie opracowałem, bo skoro w buforze odbiorczym nic nie ma... Nie bardzo wiem z czym jest związany ten problem, próbowałem wyprowadzić Tx i Rx we wszystkich możliwych konfiguracjach, jednak zawsze jest tak samo, nadajnik wysyła bez żadnego problemu a odbiornik nie może nic odczytać. Jeśli ktoś ma jakiś pomysł co może być przyczyną problemu i jak to rozwiązać to byłbym bardzo wdzięczny za pomoc Pozdrawiam mw
  2. Dzień dobry, Piszę program do swojego mikrokontrolera STM32F303VCT6, który wysyła sygnał sinusoidalny na rampie do sterowania laserem. Dodatkowo, ten sam mikrokontroler mierzy napięcie na fotodetektorze oraz mnoży te dwa sygnały - sinusoidalny i odbierany. Do tej pory wygląda na to, że wszystko działa. Potrzebuję jednak zaimplementować jeszcze filtr dolnoprzepustowy, który po wymnożeniu tych dwóch sygnałów, przefiltruje mi sygnał tak, aby na innym pinie skonfigurowanym pod przetwornik cyfrowo-analogowy "obetnie" mi żądane częstotliwości. Szukając w internecie implementacji takiego filtra nie uzyskałem satysfakcjonującej mnie odpowiedzi. Czy ktoś mógłby dokładnie wyjaśnić jak to zrobić? A może jest jakaś tego typu funkcja przy wykorzystaniu bibliotek HAL? Z góry dziękuję za pomoc!
  3. To mój pierwszy post na forum więc witam wszystkich Chociaż czytelnikiem jestem już od dawna;p Posiadam płytkę stm32f411re i próbuję przetestować akcelerometr jak w tytule(Był dołączony do kursu STM32F1). Do pomocy korzystałem z obu kursów STM32: F4 (HAL) oraz Kurs F1. Próbowałem już różnych konfiguracji interfejsu, różnych pinów itp. jednak ciągle nie mogę nawet odczytać rejestru WHO_AM_I. Konfiguracja I2C: static void MX_I2C1_Init(void) { hi2c1.Instance = I2C1; hi2c1.Init.ClockSpeed = 400000; hi2c1.Init.DutyCycle = I2C_DUTYCYCLE_2; hi2c1.Init.OwnAddress1 = 0; hi2c1.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT; hi2c1.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE; hi2c1.Init.OwnAddress2 = 0; hi2c1.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE; hi2c1.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE; if (HAL_I2C_Init(&hi2c1) != HAL_OK) { Error_Handler(); } } Adres układu: #define LSM303D_ADDR (0x3a << 1) (Próbowałem też 0x3c oraz opcji bez przesunięcia bitowego) Pętla główna: while (1) { HAL_I2C_Mem_Read(&hi2c1, LSM303D_ADDR, 0x0f, 1, &who_am_i, 1, 100); } Gdzie 0x0f to adres rejestru WHO_AM_I z dokumentacji zamieszczonej w kursie, a &who_am_i to adres zmiennej globalnej typu uint_8t. Dokumentacja LSM303D Układ zmontowany poprawnie, SDA i SCL podpinam pod piny ustawione w Cube, dodatkowo masa i 3v3 do Vin. Oczekiwana wartość rejestru to wg dokumentacji 0x49, jednak śledzenie zmiennej w STMStudio zawsze wskazuje 0. Zaznaczę jeszcze, że próbowałem też odczytywać konkretne wartości z akcelerometru po uprzedniej konfiguracji, ale nigdy nie zadziałało. Zakładam więc, że jest jakiś podstawowy problem z komunikacją układów, dlatego chcę zacząć od poprawnego odczytu who_am_i. Dajcie znać, jeśli czegoś brakuje w opisie. Dzięki.
  4. Mam teraz problem z ostatnim zadaniem. Wprawdzie mam inna plytke (stm32f303re) lecz poza innym maksymalnym taktowaniem zegara wydaje mi sie ze nie ma roznicy w wykorzystywanych funkcjach. Zmienilem odpowiednio wartosci prescaler. Tak wygladają wartości zmiennych: Zmienia sie tylko wartość Duty zaś reszta pozostaje niezmienna. KOd kopiowalem z pliku wprowadzajac potrzebne zmiany. I co najbardziej ciekawe wartości zaczynaja sie zmieniac gdy dotkne niektorych miejsc na plytce (np. styki piny do ktorych sa przypisane timery, ale nie tylko). Wartości zatrzymuje sie wtedy na przykladowo takich liczbach. Wyniki te poza procentem wypelnienia wydaja sie nawet poprawne, lecz ta jedna wartosc nie reaguje wogole na zmiany polozenia pokretla enkodera. Przede wszystkim nie mam pojecia dlaczego niektore miejsca reaguja na dotyk. Jesli to moze pomóc w rozwiazaniu tej zagadki moge zaznaczyc te punkty.
  5. Aktualnie pracuję nad tym kursem: https://forbot.pl/blog/kurs-stm32-f4-5-pomiar-napiecia-adc-dma-stmstudio-id13099 tylko na plytce stm32f303re Znalazłem w dokumentacji mikrokontrolera dane do przeliczania wyniku na stopnie celsjusza, nie wiem czy błąd jest w danych czy w czymś innym ale temperatura znacznie odbiega od tej jaka powinna wyjść według kursu. U mnie jest 40 stopni zas wedlug kursu powinna byc chyba zblizona do temperatury otoczenia. Czy ktos moze mi sprawdzic czy znalazlem poprawne dane i napisalem dobrze kod? Największe wątpliwości mam co do maksymalnego napiecia zasilania. Poniżej zamieszczam screeny ze znalezionymi danymi oraz kod.
  6. Chcę napisac program ktory bedzie zaswiecal stopniowo diode a nastepnie ja gasil w czasie 4s. Znalazlem w reference manual takie informacje na temat przerwania SysTick: więc ustawilem zegar procesora takim taktowaniem jak jest opisane Obliczylem rowniez ze aby dioda zaswiecala sie cyklicznie w czasie 4s trzeba aktualizowac stannapiecia PWM co 40cyklow przerwań, zas timer ustawilem tak aby sygnal PWM przyjmowal 100 wartosci posrednich. Po odpaleniu programu w debugerze wyskakuje mi jakis błąd ktorego nawet nie wiem jak interpretować. Zamieszczam rowniez kod, ktos moze bedzie wiedzial w czym jest problem. main.rar https://forbot.pl/blog/kurs-stm32-f4-8-zaawansowane-funkcje-licznikow-id13473 Robie ten kurs tylko na innym mikrokontrolerze, STM32F303re
  7. Cześć! od wielu dnia(tak) walczę z tym, co na AVRkach można było zrobić w 5 minut z notą katalogową. A mowa o multipleksowaniu wejść przetwornika ADC. Chciałbym w dodatku wykorzystać przerwania bądź DMA. Procek na jakim pracuję to STM32F030F4. W tym momencie konfiguracja wygląda jak na załączonym screenie. Natomiast kod wygląda tak: W sekcji UC(usercode) 2 mam dopisany start: /* USER CODE BEGIN 2 */ HAL_ADC_Start_IT(&hadc); /* USER CODE END 2 */ Natomiast w sekcji PFP dopisałem taką funkcję: /* USER CODE BEGIN PFP */ void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc){ reading[0] = HAL_ADC_GetValue(&hadc); } /* USER CODE END PFP */ Efekt? Nic nie działa. Odczyt z przetwornika to wciąż 0. Kiedy robiłem to pollingiem w pętli while, funkcja GetValue zwracała naprzemiennie(ale bez ładu) wyniki z 3 potencjometrów. Natomiast to słaba metoda. jak to ugryźć? Dodam, że w F0 jedyną metodą jest opcja ScanMode.
  8. Próbował może ktoś korzystać z STM32CubeIDE? Zgodnie z tym opisem to jest All-in-one. Czyli może w końcu wszystko działa tak jak powinno?
  9. Witam! Pewnie problem na zasadzie początkującego użytkownika STM32 ale co poradzę - wystąpił ! Mianowicie, mam podłączone 3 przyciski do STM32F103CBT6, przyciski podłączone z rezystorem pull-up i poprzez kondensator filtrujący. W procesorze włączony również pull-up na wejściu od przycisku. Reakcja na wciśnięcie (zbocze opadające) miała być uruchamiana z wykorzystaniem przerwań zewnętrznych. I tu pojawia się problem bo o ile program nie zajmuje się czymś innym albo tylko jakimiś drobnymi rzeczami to wszystko jest w porządku - reakcja następuje od razu. Jeśli tylko zacznę np. więcej rzeczy wyświetlać na OLEDzie to reakcja następuje losowo. Wszystkie przerwania mają priorytety i grupy ustawione na 0. Dodam, że sprawdzałem na oscyloskopie czy występują jakiekolwiek drgania styków - zbocze opadające jest gładziutkie, nie ma możliwości, ze tu coś jest nie halo. Program pisany w HALu tak jak w kursie Forbota. Jeśli będzie potrzeba to dodam listing. Dodatkowo również w ten sam sposób uruchomione są przerwania z zewnętrznego urządzenia i tam wszystko śmiga, no a na przyciskach nie chce - ciekawe. Proszę o jakieś sugestie co to może być, czy ktoś się z czymś spotkał.
  10. Cześć. Mam mały problem z modułem MPU9250, a konkretniej AK8963 (Magnetometr). Odczyt wartości zmierzonych przez akcelerometr i żyroskop nie sprawiły mi większych problemów i wszystko działa prawidłowo. Sprawa skomplikowała się kiedy zechciałem odczytać wartości zmierzone przez magnetometr. Ogólnie komunikacja z magnetometrem działa prawidłowo (WHO_AM_I itd.). Problem polega na tym, że po odczytaniu wartości z rejestrów HXL, HXH... cały czas otrzymuję wartość -1 dla każdej osi. Fragment kodu z inicjalizacją magnetometru: MPU9250_Error_code MPU9250_Magnetometer_Configuration(I2C_HandleTypeDef *I2Cx, struct MPU9250 *DataStructure) { uint8_t Byte_temp = 0x00; uint8_t Bytes_temp[3] = {0}; DataStructure->Magnetometer_addres = 0x0C << 1; // Case 2: Disable the I2C master interface Byte_temp = 0x00; if( HAL_I2C_Mem_Write(I2Cx, DataStructure->Device_addres, MPU9250_USER_CTRL, 1, &Byte_temp, 1, 1000) != HAL_OK ) { //HAL_GPIO_TogglePin(LD2_GPIO_Port, LD2_Pin); return MPU9250_Magnetometer_Config_FAIL; } // Case 3: Enable the bypass multiplexer Byte_temp = 0x02; if( HAL_I2C_Mem_Write(I2Cx, DataStructure->Device_addres, MPU9250_INT_PIN_CFG, 1, &Byte_temp, 1, 1000) != HAL_OK ) { //HAL_GPIO_TogglePin(LD2_GPIO_Port, LD2_Pin); return MPU9250_Magnetometer_Config_FAIL; } // Case 1: Is device connected ? if( HAL_I2C_IsDeviceReady(I2Cx, DataStructure->Magnetometer_addres, 1, 1000) != HAL_OK ) { //HAL_GPIO_TogglePin(LD2_GPIO_Port, LD2_Pin); return MPU9250_Magnetometer_Config_FAIL; } // Case 2: Who am i test if( HAL_I2C_Mem_Read(I2Cx, DataStructure->Magnetometer_addres, MPU9250_WIA, 1, &Byte_temp, 1, 1000) != HAL_OK ) { //HAL_GPIO_TogglePin(LD2_GPIO_Port, LD2_Pin); return MPU9250_Init_FAIL; } if( Byte_temp != 0x48 ) { //HAL_GPIO_TogglePin(LD2_GPIO_Port, LD2_Pin); return MPU9250_Init_FAIL; } // Case 4: Setup to fuse ROM access mode and 16-bit output Byte_temp = 0x1F; if( HAL_I2C_Mem_Write(I2Cx, DataStructure->Magnetometer_addres, MPU9250_CNTL1, 1, &Byte_temp, 1, 1000) != HAL_OK ) { //HAL_GPIO_TogglePin(LD2_GPIO_Port, LD2_Pin); return MPU9250_Magnetometer_Config_FAIL; } HAL_Delay(100); // Case 5: Read from the fuse ROM sensitivity adjustment values if( HAL_I2C_Mem_Read(I2Cx, DataStructure->Magnetometer_addres, MPU9250_ASAX | 0x80, 1, Bytes_temp, 3, 1000) != HAL_OK ) { //HAL_GPIO_TogglePin(LD2_GPIO_Port, LD2_Pin); return MPU9250_Magnetometer_Config_FAIL; } DataStructure->Magnetometer_ASAX = ( ( (Bytes_temp[0] - 128) * 0.5 ) / 128 ) + 1; DataStructure->Magnetometer_ASAY = ( ( (Bytes_temp[1] - 128) * 0.5 ) / 128 ) + 1; DataStructure->Magnetometer_ASAZ = ( ( (Bytes_temp[2] - 128) * 0.5 ) / 128 ) + 1; // Case 6: Reset to power down mode Byte_temp = 0x00; if( HAL_I2C_Mem_Write(I2Cx, DataStructure->Magnetometer_addres, MPU9250_CNTL1, 1, &Byte_temp, 1, 1000) != HAL_OK ) { //HAL_GPIO_TogglePin(LD2_GPIO_Port, LD2_Pin); return MPU9250_Magnetometer_Config_FAIL; } // Case 7: Enable continuous mode 2 and 16-bit output Byte_temp = 0x16; if( HAL_I2C_Mem_Write(I2Cx, DataStructure->Magnetometer_addres, MPU9250_CNTL1, 1, &Byte_temp, 1, 1000) != HAL_OK ) { //HAL_GPIO_TogglePin(LD2_GPIO_Port, LD2_Pin); return MPU9250_Magnetometer_Config_FAIL; } HAL_Delay(100); return MPU9250_Magnetometer_Config_OK; } Fragment kodu z odczytaniem zmierzonych wartości: MPU9250_Error_code MPU9250_Read_Magnetometer(I2C_HandleTypeDef *I2Cx, struct MPU9250 *DataStructure) { uint8_t Bytes_temp[7] = { 0x00 }; if( HAL_I2C_Mem_Read(I2Cx, DataStructure->Magnetometer_addres, MPU9250_HXL | 0x80, 1, Bytes_temp, 7, 1000) != HAL_OK ) { //HAL_GPIO_TogglePin(LD2_GPIO_Port, LD2_Pin); return MPU9250_Read_Magnetometer_FAIL; } DataStructure->Magnetometer_X = Bytes_temp[0] | Bytes_temp[1] << 8; DataStructure->Magnetometer_Y = Bytes_temp[2] | Bytes_temp[3] << 8; DataStructure->Magnetometer_Z = Bytes_temp[4] | Bytes_temp[5] << 8; return MPU9250_Read_Magnetometer_OK; }
  11. Hej, robiłem tą część kursu na płytce NUCLEO-F334R8 i mam problem z odczytem temperatury. W UserManual znalazłem takie wartości: AVG_slop = 0,0043 V25 = 1,43 https://www.st.com/resource/en/datasheet/stm32f334k4.pdf Rozdzial 6.3.23: Pomiar ADC zwraca mi wartosc w okolicach 1360, co daje wynik ok -77C... 0_o Czujnik zepsuty czy cos robie nie tak?
  12. Tradycyjna kostka do gry jest prosta w budowie, tania ale ma pewne wady. Potrafi potoczyć się w trudno dostępne miejsce. Kolejna wada jest hałas przez nią wytwarzany oraz fakt, że potrafi wpaść na planszę gry i przewrócić pionki. Wad tych pozbawiona jest kostka elektroniczna. W Internecie można znaleźć wiele konstrukcji, wszystkie jakie widziałem wyświetlają wynik losowania na diodach LED. Prezentowana konstrukcja posiada nowoczesny wyświetlacz OLED co pozwala na wyświetlanie różnorodnych grafik. Ponadto może zastąpić cztery kostki o praktycznie dowolnej liczbie liczbie ścian. Kostka została zbudowana na mikrokontrolerze STM32F103RBT8, który można znaleźć na płytkach STM32 NUCLEOSTM32-NUCLEO i innych dostępnych w Botlandzie . Można użyć taniej płytki "Blue pill". Prototyp został zamontowany na dedykowanej do tego PCB. Do wyświetlania grafiki służy kolorowy wyświetlacz OLED o rozdzielczości 96x64 np OLED 0,96". Grafika jest zapisana na karcie SD, dzięki czemu łatwo ją zmienić. Karta jest umieszczona w gnieździe podobnym do Gniazago karty SD z wyrzutnikiem tyle, że bez wyrzutnika. Na PCB przewidziano miejsce na pamięć DataFlash ale w prototypie nie jest ona używana. Jej przeznaczeniem była możliwość skopiowania grafiki z karty pamięci do DataFlash skąd mogą one bardzo szybko być wyświetlane na OLEDzie. Czas odczytu grafik z karty SD jest stosunkowo długi ale wystarczający do wyświetlania statycznych obrazów. Jeśli miałyby być wyświetlane grafiki (np. podczas losowania) to wykorzystanie DataFlasch będzie konieczne. Jak to działa? Naciśnięcie przycisku SET, wybudza mikrokontroler. Program sprawdza, czy reset spowodowany jest włączeniem zasilania czy wybudzeniem. Jeśli włączeniem zasilania wybiera kostkę numer 1 (na karcie SD można umieścić grafiki czterech kostek, każda do 250 ścian) ponadto inicjalizuje generator pseudolosu (ziarno). Jeżeli reset był wywołany wybudzeniem, ustawiana jest ostatnio używana kostka. W kolejnym kroku, przeszukiwane są pliki graficzne, na podstawie których, wiadomo ile ścian ma każda z czterech kostek. Po przeszukaniu plików pojawia się napis „Gotowy do gry” albo „SD Error” jeśli nie wykryto karty lub wymaganych plików graficznych. Przyciskami UP, DOWN, LEFT, RIGHT, można wybrać jedną z kostek, SET uruchamia losowanie. W czasie losowania, zależnie od tego czy znajduje się grafika reprezentująca wybraną kostkę (w prototypie „Orzeł czy reszka” i „Ruletka”) czy nie (w prototypie kostka 6 ścian, kostka 12 ścian), wyświetlana jest grafika lub migający ekran. Po zwolnieniu przycisku SET, po sekundzie, pojawia się wylosowana ściana kostki. Bezczynność przez dwie minuty spowoduje przejście kostki w stan uśpienia. Program został napisany w KEIL uV 5, zajmuje 31kB FLASH, 18kB RAM więc można go skompilować darmową wersją programu. Przy pisaniu softu, wspomagano się programem CubeMX. Program w dużej mierze korzysta z HAL tylko nieliczne fragmenty operują bezpośrednio na rejestrach mikrokontrolera. W pamięci mikrokontrolera stworzono bufor na dane wyświetlacza. Wszystkie operacje graficzne są wykonywane na nim, po czym wysyłana z wykorzystaniem DMA. Dzięki temu, transmisja zajmuje ok 12ms, w efekcie grafika na ekranie pojawia się niezauważalnie szybko. Zawartość karty SD stanową pliki graficzne w formacie BMP zapisane są w głównym katalogu. Nazwy plików kolejnych kostek zaczynają się od liter a, b, c, d. Cyfra za nazwą informuje o numerze ściany. Pierwsza kostka 6 ścian będzie wymagała plików: "a1.bmp" ... "a6.bmp". Ruletka to pliki:" b1.bmp" … "b37.bmp". Jeśli w czasie losowania ma pojawiać się grafika należy dodać plik z sufiksem 00, np.: "a00.bmp", "b00.bmp". Grafika w formacie BMP powinna mieć wymiary 94x64 piksele. Głębia kolorów 24-bit, bez kompresji. Grafika może mieć inne wymiary, jeśli będzie za duża, to zostanie obcięta, jeśli za mała, nie wypełni całego wyświetlacza. Do tworzenia /obróbki grafik w prototypie korzystano z Windows'owego Paint'a i programu IrfanView. W załączniku archiwum z programem i schemat. Kostka12.zip Protel Schematic.pdf
  13. Witam, Dopiero zaczynam przygodę z STM32. Mój problem polega na tym, że nie wiem za bardzo jak zapisać cały ciąg znaków do znaku końca lini w buforze mikrokontrolera. Wiem, że trzeba wykorzystać do tego tablicę, ale jak to zrobić to nie mam większego pojęcia. Jeśli ktoś może mi to wytłumaczyć będę wdzięczny.
  14. Cześć, to już któryś z kolei kurs na forbocie, który mi przypadł do gustu - przyjemny i wytłumaczony od deski do deski. Ja jednak używam płytki blue pill i mam problem z STM Studio - nie mogę nawiązać połączenia. Otrzymuję dwa komunikaty, jeden za drugim: "Error opening target connection" oraz "Failure opening connection with target". Zarówno ST-Link Utility jak i żaden debugger nie ma nawiązanego połączenia z płytką a jednak problem z połączeniem występuje. Używam ST-Link v2 i już w ST-Link utility miałem problem. O ile na początku wszystko działało bez problemu - połączenie z płytką i jej zaprogramowanie, tak już na drugi dzień wystąpił problem z połączeniem. Teraz po wybraniu Target -> Connect, muszę przez około 3 sekundy trzymać wciśnięty przycisk RESET na płytce i dopiero po jego zwolnieniu następuję połączenie, natomiast po zaprogramowaniu połączenie zostaje zerwane, mimo że program został poprawnie wgrany. Próbowałem powyższej metody w STM Studio, jednak wtedy, po zwolnieniu przycisku RESET, wyrzuca komunikat: "Acquisition stopped after 10 consecutive communication errors.". Dodam, że próbuję wgrać program odczytujący temperaturę z wbudowanego czujnika temperatury a konfiguracja w Cube odbyła się oczywiście pod mój mikrokontroler. Wszystkie narzędzia są zaktualizowane do najnowszej wersji, firmware w ST-Linku też. Ktoś się spotkał z podobnym problemem?
  15. Witam, Ostatnio zauważyłem problem podczas wgrywania programu dla mikrokontrolera STM32F429. Problem objawia się następująco: -Tworzę nowy projekt -> zapisuje, builduje, (nie ma błędów) -> wgrywam program poprzez Utility (wybierając plik z rozszerzeniem HEX) -> działa. - Biorę ten sam projekt i wprowadzam pewne modyfikacje (np. zmieniam częstotliwość w CUBE, wybieram inny pin itp, generalnie drobne zmiany) -> zapisuje, builduje (nie ma błędów) -> wgrywam, i niestety bez powodzenia. Załączam screena z Utility po nieudanej próbie wgrania kodu. Doszedłem do tego, że raczej wina leży po stronie Workbencha i niepoprawnie utworzonego pliku z rozszerzeniem HEX (plik ten jest praktycznie pusty, sprawdziałem go notatnikiem), ponieważ gdy chcę wgrać inny projekt wówczas wszystko działa poprawnie. Próbowałem odinstalować oprogramowanie i zainstalować od nowa. Nie pomogło. Czy ktoś spotkał się z czymś takim?
  16. Mam takie zapytanie bo uwaliłem stm i potrzebuje wymienić na nowy, które adresy pamięci są ważne żeby zrobić kopie 1:1? 0x0000 0000 - 0x0001 0000 i 0x0800 0000 - 0x0801 0000 czy coś jeszcze??
  17. Witam. Tworzę prostą aplikację pod Stm32CubeIDE z użycie kontrolera STM32F303 (z wbudowanym FPU). Trafiłem na dziwne problemy kiedy próbowałem użyć sprintf z włączonym wsparciem dla %f. Za każdym razem zamiast poprawnie sformatowanej liczby dostawałem bardzo długi ciąg cyfr. Znalazłem nawet na githubie jakąś inną implementację sprintf i to znowu często zamiast poprawnej wartości zwracało mi 0.00. W końcu okazało się, że problem jest z va_arg: void test(const char* format, ...) { va_list va; va_start(va, format); double arg1 = va_arg(va, double); char buf[102]; sprintf(buf, "a %.2f", arg1); va_end(va); } test("format", 0.1234); Zatrzymuje kod na linii z va_arg i widzę, że to zwraca głupoty. Obszedłem to przy pomocy takiego dziwnego rozwiązania: uint64_t doubleBinary = va_arg(va, uint32_t) | ((uint64_t)va_arg(va, uint32_t) << 32); double arg = *(double*)&doubleBinary; I tu dostaje poprawną wartość. Ale potem mam taki fragment (to z tego sprintf): static size_t _ftoa(out_fct_type out, char* buffer, size_t idx, size_t maxlen, double value, unsigned int prec, unsigned int width, unsigned int flags) { {... tu jakiś kod...} } //i wywołanie: uint64_t doubleAsInt = va_arg(va, uint32_t) | ((uint64_t)va_arg(va, uint32_t) << 32); double doubleAsDouble = *(double*)&doubleAsInt; idx = _ftoa(out, buffer, idx, maxlen, doubleAsDouble, precision, width, flags); format++; No i na tym _ftoa znowu jest problem bo zamiast wejść do procedury to kod wpada mi do: Default_Handler: Infinite_Loop: b Infinite_Loop Próbowałem wyłączyć FPU i skompilować wszystko na software. va_arg nadal nie działa ale nie ma tego crasha przy _ftoa. Potem uruchomiłem ten sam program pod starym EmBitz (GCC w wersji 5) i tam wszystko wydaje się działać bezbłędnie (na tyle na ile udało mi się sprawdzić). Przy czym te projekty nie są identycznie (mój kod jest taki sam ale to co jest generowane przez środowisko już na pewno nie). Ma ktoś pomysł jak to debugować i o co może chodzić? Nie jestem w tym specjalnie zaawansowany i skończyły mi się już pomysły. W internecie znalazłem jakieś szczątkowe informacje, że double ma 8 bajtów i z tym jest jakiś problem (niestety bez konkretów więc nic mi to nie dało).
  18. Dzień dobry wszystkim. Po około miesiącu używania STM32L053R8 postanowiłem ułatwić sobie życie za pomocą STM32CubeMX i migrować z SW4STM32 na TrueSTUDIO. Niestety TrueSTUDIO nie chciało ze mną współpracować, a co gorsza projekty, które pierwotnie działały w SW4STM32 po całej tej operacji odmówiły posłuszeństwa. Magistrala USART zaczęła działać w niezrozumiały dla mnie sposób, tj aby terminal odczytał dane poprawnie musiał mieć ustawiony baud_rate_term ~= baud_rate_uC/2. np(uC 115200 - term 57600 lub 56000) Dwie rzeczy, które zmieniałem w międzyczasie to: a) aktualizacja ST Link v2 do V2.J34.M25 b) konfiguracja PLL w STM32CubeMX Załączam screeny z konfiguracji oraz fragmenty kodu. Jeżeli był już taki post to przepraszam , ale nawet nie wiedziałem jakimi słowami klucz go szukać, i dziękuję z góry za każdą pomoc. Inicjalizacja UARTu: void MX_USART2_UART_Init(void) { huart2.Instance = USART2; huart2.Init.BaudRate = 115200; huart2.Init.WordLength = UART_WORDLENGTH_8B; huart2.Init.StopBits = UART_STOPBITS_1; huart2.Init.Parity = UART_PARITY_NONE; huart2.Init.Mode = UART_MODE_TX_RX; huart2.Init.HwFlowCtl = UART_HWCONTROL_NONE; huart2.Init.OverSampling = UART_OVERSAMPLING_16; huart2.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE; huart2.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT; if (HAL_UART_Init(&huart2) != HAL_OK) { Error_Handler(); } } void HAL_UART_MspInit(UART_HandleTypeDef* uartHandle) { GPIO_InitTypeDef GPIO_InitStruct = {0}; if(uartHandle->Instance==USART2) { /* USER CODE BEGIN USART2_MspInit 0 */ /* USER CODE END USART2_MspInit 0 */ /* USART2 clock enable */ __HAL_RCC_USART2_CLK_ENABLE(); __HAL_RCC_GPIOA_CLK_ENABLE(); /**USART2 GPIO Configuration PA2 ------> USART2_TX PA3 ------> USART2_RX */ GPIO_InitStruct.Pin = GPIO_PIN_2|GPIO_PIN_3; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Speed = GPIO_SPEED_LOW; GPIO_InitStruct.Alternate = GPIO_AF4_USART2; HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); /* USER CODE BEGIN USART2_MspInit 1 */ /* USER CODE END USART2_MspInit 1 */ } } Transmisja: void uart_write_line(UART_HandleTypeDef *huart, char *str) { HAL_UART_Transmit(huart, str, strlen(str), 1000); HAL_UART_Transmit(huart, "\r\n", 2, 1000); }
  19. Witam, moze odrazu do rzeczy. Chcial bym podlaczyc termistor ktory bedzie zasilany napieciem 5V. Czytalem ze STM32 dzialaja na logice 3,3V. Wiec tu moje pytanie czy nie spale uC przez to ze dam napiecie bliskie 5V na ADC tego kontrolera. Mysle tez nad konwerterem logicznym lub prostym dzielnikiem napiecie by wrazie potrzeby zmniejszyc napiecie. Moze ktos ma inne pomysly, jakies rady co to ADC STM32? Z gory dzieki. Pozdrawiam
  20. Dzień dobry Dokładnie postępując jak to jest pokazane w kursie napotkałem pewien problem. Jak wyżej ktoś pisał, można wgrywać plik .hex, więc tak też uczyniłem. Nie zauważyłem po drodze żadnych błędów, jednak nie zauważyłem aby jakakolwiek dioda zaświeciła się na niebiesko. Nie mam pojęcia gdzie może być błąd, spróbować postąpić z tym co pisali inni wyżej - zainstalować starszą wersję Cuba i wtedy spróbować?
  21. Witam wszystkich, Realizuje właśnie projekt, którego celem jest generowanie tonu o zadanej częstotliwości i określonym poziomie głośności. Do tego wykorzystuje przetwornik dac CS43L22 znajdujący się na płytce a jako wyjście złącze jack. Poniżej mój kod odpowiadający za stworzenie dyskretnego sinusa: void Build_sin(float F_Out) { float sample_dt = F_Out/F_SAMPLE; uint16_t sample_N = F_SAMPLE/F_Out; float sin_val; for(uint16_t i=0; i<sample_N; i++) { sin_val = sinf(2*PI*sample_dt*i); dataI2S[i*2] = (sin_val ); //prawy tor dataI2S[i*2 + 1] =(sin_val ); //lewy tor } Na wyjście przekazuję go za pomocą HAL_I2S_Transmit_DMA w następujący sposób: HAL_I2S_Transmit_DMA(&hi2s3, (uint16_t *)dataI2S, sample_N*2); Regulację głośności realizuję za pomocą funkcji SetVolume która wygląda w następujący sposób: void CS43_SetVolume(uint8_t volume) { int8_t tempVol = volume - 50; tempVol = tempVol*(127/50); uint8_t myVolume = (uint8_t )tempVol; DataReg[1] = myVolume; write_register(PASSTHROUGH_VOLUME_A,&DataReg[1]); write_register(PASSTHROUGH_VOLUME_B,&DataReg[1]); DataReg[1] = VOLUME_CONVERT_D(volume); write_register(CS43L22_REG_MASTER_A_VOL,&DataReg[1]); write_register(CS43L22_REG_MASTER_B_VOL,&DataReg[1]); } Macro VOLUME_CONVERT_D(vol) wygląda tak: (((volume) > 100)? 24:((uint8_t)((((volume) * 48) / 100) - 24))) Moje pytania są następujące: 1) W jaki sposób przekłada się poziom sygnału, stworzonego w funkcji Build_sin(), podawany na wyjście przetwornika na poziom głośności uzyskany w słuchawkach? 2) Czy w przypadku zmiany Master volume z powiedzmy 0 dB na -3 dB otrzymam na wyjściu sygnał audio pomniejszony o 3 dB względem wcześniejszego? Z góry dziękuje za odpowiedź i pozdrawiam
  22. Witam, Posiadam STM32 f429, nucleo 144. Chciałbym zrealizować program, który będzie wykonywał odczyt zmiennej (napięcia, stosując przetwornik ADC) cyklicznie, np co 2 sekundy. Poniżej wrzucam mój kod, w którym wywoływane jest przerwanie po każdym zakończeniu konwersji ADC. /* USER CODE BEGIN Header */ /** ****************************************************************************** * @file : main.c * @brief : Main program body ****************************************************************************** * @attention * * <h2><center>&copy; Copyright (c) 2019 STMicroelectronics. * All rights reserved.</center></h2> * * This software component is licensed by ST under BSD 3-Clause license, * the "License"; You may not use this file except in compliance with the * License. You may obtain a copy of the License at: * opensource.org/licenses/BSD-3-Clause * ****************************************************************************** */ /* USER CODE END Header */ /* Includes ------------------------------------------------------------------*/ #include "main.h" /* Private includes ----------------------------------------------------------*/ /* USER CODE BEGIN Includes */ /* USER CODE END Includes */ /* Private typedef -----------------------------------------------------------*/ /* USER CODE BEGIN PTD */ /* USER CODE END PTD */ /* Private define ------------------------------------------------------------*/ /* USER CODE BEGIN PD */ /* USER CODE END PD */ /* Private macro -------------------------------------------------------------*/ /* USER CODE BEGIN PM */ /* USER CODE END PM */ /* Private variables ---------------------------------------------------------*/ ADC_HandleTypeDef hadc1; ADC_HandleTypeDef hadc2; uint16_t adc1 = 0; //zmienna nieprzekonwertowana uint16_t adc2 = 0; //zmienna nieprzekonwertowanan float v1 = 0; //zmienna przekonwertowana dla 3,3 V float a1 = 0; //do pomiaru pradu TIM_HandleTypeDef htim4; /* USER CODE BEGIN PV */ /* USER CODE END PV */ /* Private function prototypes -----------------------------------------------*/ void SystemClock_Config(void); static void MX_GPIO_Init(void); static void MX_ADC1_Init(void); static void MX_ADC2_Init(void); static void MX_TIM4_Init(void); static void MX_GFXSIMULATOR_Init(void); /* USER CODE BEGIN PFP */ void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc){ // przerwanie adc1 = HAL_ADC_GetValue(&hadc1); v1 = (float)adc1 * 3.3f / 4096.0f; TIM4->CCR2 = adc1; // przypisanie wartosci adc1 do rejestru timera PWM adc2 = HAL_ADC_GetValue(&hadc2); a1 = ((float)adc2 * 3.3f / 4096.0f)/0.47; //0,47 taka rezystancja rezystora, prad z prawa Ohma if (v1 > 3.1) HAL_GPIO_WritePin(GPIOB, GPIO_PIN_0, GPIO_PIN_SET); else HAL_GPIO_WritePin(GPIOB, GPIO_PIN_0, GPIO_PIN_RESET); } /* USER CODE END PFP */ /* Private user code ---------------------------------------------------------*/ /* USER CODE BEGIN 0 */ /* USER CODE END 0 */ /** * @brief The application entry point. * @retval int */ int main(void) { /* USER CODE BEGIN 1 */ /* USER CODE END 1 */ /* MCU Configuration--------------------------------------------------------*/ /* Reset of all peripherals, Initializes the Flash interface and the Systick. */ HAL_Init(); /* USER CODE BEGIN Init */ /* USER CODE END Init */ /* Configure the system clock */ SystemClock_Config(); /* USER CODE BEGIN SysInit */ /* USER CODE END SysInit */ /* Initialize all configured peripherals */ MX_GPIO_Init(); MX_ADC1_Init(); MX_ADC2_Init(); MX_TIM4_Init(); MX_GFXSIMULATOR_Init(); /* USER CODE BEGIN 2 */ HAL_ADC_Start_IT(&hadc1); // wystartowanie przetworników ADC HAL_ADC_Start_IT(&hadc2); HAL_TIM_PWM_Start(&htim4, TIM_CHANNEL_2); //wystartowanie PWMa TIM4->CCR2 = 65535; /* USER CODE END 2 */ /* Infinite loop */ /* USER CODE BEGIN WHILE */ while (1) { /* USER CODE END WHILE */ /* USER CODE BEGIN 3 */ } /* USER CODE END 3 */ } /** * @brief System Clock Configuration * @retval None */ void SystemClock_Config(void) { RCC_OscInitTypeDef RCC_OscInitStruct = {0}; RCC_ClkInitTypeDef RCC_ClkInitStruct = {0}; /** Configure the main internal regulator output voltage */ __HAL_RCC_PWR_CLK_ENABLE(); __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE3); /** Initializes the CPU, AHB and APB busses clocks */ RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI; RCC_OscInitStruct.HSIState = RCC_HSI_ON; RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT; RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE; if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) { Error_Handler(); } /** Initializes the CPU, AHB and APB busses clocks */ RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2; RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_HSI; RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1; RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1; RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1; if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_0) != HAL_OK) { Error_Handler(); } } /** * @brief ADC1 Initialization Function * @param None * @retval None */ static void MX_ADC1_Init(void) { /* USER CODE BEGIN ADC1_Init 0 */ /* USER CODE END ADC1_Init 0 */ ADC_ChannelConfTypeDef sConfig = {0}; /* USER CODE BEGIN ADC1_Init 1 */ /* USER CODE END ADC1_Init 1 */ /** Configure the global features of the ADC (Clock, Resolution, Data Alignment and number of conversion) */ hadc1.Instance = ADC1; hadc1.Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV2; hadc1.Init.Resolution = ADC_RESOLUTION_12B; hadc1.Init.ScanConvMode = DISABLE; hadc1.Init.ContinuousConvMode = ENABLE; hadc1.Init.DiscontinuousConvMode = DISABLE; hadc1.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE; hadc1.Init.ExternalTrigConv = ADC_SOFTWARE_START; hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT; hadc1.Init.NbrOfConversion = 1; hadc1.Init.DMAContinuousRequests = DISABLE; hadc1.Init.EOCSelection = ADC_EOC_SINGLE_CONV; if (HAL_ADC_Init(&hadc1) != HAL_OK) { Error_Handler(); } /** Configure for the selected ADC regular channel its corresponding rank in the sequencer and its sample time. */ sConfig.Channel = ADC_CHANNEL_10; sConfig.Rank = 1; sConfig.SamplingTime = ADC_SAMPLETIME_480CYCLES; if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK) { Error_Handler(); } /* USER CODE BEGIN ADC1_Init 2 */ /* USER CODE END ADC1_Init 2 */ } /** * @brief ADC2 Initialization Function * @param None * @retval None */ static void MX_ADC2_Init(void) { /* USER CODE BEGIN ADC2_Init 0 */ /* USER CODE END ADC2_Init 0 */ ADC_ChannelConfTypeDef sConfig = {0}; /* USER CODE BEGIN ADC2_Init 1 */ /* USER CODE END ADC2_Init 1 */ /** Configure the global features of the ADC (Clock, Resolution, Data Alignment and number of conversion) */ hadc2.Instance = ADC2; hadc2.Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV2; hadc2.Init.Resolution = ADC_RESOLUTION_12B; hadc2.Init.ScanConvMode = DISABLE; hadc2.Init.ContinuousConvMode = ENABLE; hadc2.Init.DiscontinuousConvMode = DISABLE; hadc2.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE; hadc2.Init.ExternalTrigConv = ADC_SOFTWARE_START; hadc2.Init.DataAlign = ADC_DATAALIGN_RIGHT; hadc2.Init.NbrOfConversion = 1; hadc2.Init.DMAContinuousRequests = DISABLE; hadc2.Init.EOCSelection = ADC_EOC_SINGLE_CONV; if (HAL_ADC_Init(&hadc2) != HAL_OK) { Error_Handler(); } /** Configure for the selected ADC regular channel its corresponding rank in the sequencer and its sample time. */ sConfig.Channel = ADC_CHANNEL_11; sConfig.Rank = 1; sConfig.SamplingTime = ADC_SAMPLETIME_480CYCLES; if (HAL_ADC_ConfigChannel(&hadc2, &sConfig) != HAL_OK) { Error_Handler(); } /* USER CODE BEGIN ADC2_Init 2 */ /* USER CODE END ADC2_Init 2 */ } /** * @brief GFXSIMULATOR Initialization Function * @param None * @retval None */ static void MX_GFXSIMULATOR_Init(void) { /* USER CODE BEGIN GFXSIMULATOR_Init 0 */ /* USER CODE END GFXSIMULATOR_Init 0 */ /* USER CODE BEGIN GFXSIMULATOR_Init 1 */ /* USER CODE END GFXSIMULATOR_Init 1 */ /* USER CODE BEGIN GFXSIMULATOR_Init 2 */ /* USER CODE END GFXSIMULATOR_Init 2 */ } /** * @brief TIM4 Initialization Function * @param None * @retval None */ static void MX_TIM4_Init(void) { /* USER CODE BEGIN TIM4_Init 0 */ /* USER CODE END TIM4_Init 0 */ TIM_ClockConfigTypeDef sClockSourceConfig = {0}; TIM_MasterConfigTypeDef sMasterConfig = {0}; TIM_OC_InitTypeDef sConfigOC = {0}; /* USER CODE BEGIN TIM4_Init 1 */ /* USER CODE END TIM4_Init 1 */ htim4.Instance = TIM4; htim4.Init.Prescaler = 0; htim4.Init.CounterMode = TIM_COUNTERMODE_UP; htim4.Init.Period = 65535; htim4.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1; htim4.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE; if (HAL_TIM_Base_Init(&htim4) != HAL_OK) { Error_Handler(); } sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL; if (HAL_TIM_ConfigClockSource(&htim4, &sClockSourceConfig) != HAL_OK) { Error_Handler(); } if (HAL_TIM_PWM_Init(&htim4) != HAL_OK) { Error_Handler(); } sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET; sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE; if (HAL_TIMEx_MasterConfigSynchronization(&htim4, &sMasterConfig) != HAL_OK) { Error_Handler(); } sConfigOC.OCMode = TIM_OCMODE_PWM1; sConfigOC.Pulse = 0; sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH; sConfigOC.OCFastMode = TIM_OCFAST_DISABLE; if (HAL_TIM_PWM_ConfigChannel(&htim4, &sConfigOC, TIM_CHANNEL_2) != HAL_OK) { Error_Handler(); } /* USER CODE BEGIN TIM4_Init 2 */ /* USER CODE END TIM4_Init 2 */ HAL_TIM_MspPostInit(&htim4); } /** * @brief GPIO Initialization Function * @param None * @retval None */ static void MX_GPIO_Init(void) { GPIO_InitTypeDef GPIO_InitStruct = {0}; /* GPIO Ports Clock Enable */ __HAL_RCC_GPIOC_CLK_ENABLE(); __HAL_RCC_GPIOB_CLK_ENABLE(); __HAL_RCC_GPIOA_CLK_ENABLE(); /*Configure GPIO pin Output Level */ HAL_GPIO_WritePin(GPIOB, GPIO_PIN_0|GPIO_PIN_14, GPIO_PIN_RESET); /*Configure GPIO pins : PB0 PB14 */ GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_14; GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); } /* USER CODE BEGIN 4 */ /* USER CODE END 4 */ /** * @brief This function is executed in case of error occurrence. * @retval None */ void Error_Handler(void) { /* USER CODE BEGIN Error_Handler_Debug */ /* User can add his own implementation to report the HAL error return state */ /* USER CODE END Error_Handler_Debug */ } #ifdef USE_FULL_ASSERT /** * @brief Reports the name of the source file and the source line number * where the assert_param error has occurred. * @param file: pointer to the source file name * @param line: assert_param error line source number * @retval None */ void assert_failed(uint8_t *file, uint32_t line) { /* USER CODE BEGIN 6 */ /* User can add his own implementation to report the file name and line number, tex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */ /* USER CODE END 6 */ } #endif /* USE_FULL_ASSERT */ /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
  23. Hej, Praktycznie zawsze po kilkukrotnym wgraniu programu przez Utility następuje moment tak jakby "zawieszenia" możliwości wgrania programu z danego projektu. W sytuacji, gdy np chce sobie kilkukrotnie zmodyfikować program z kursu, tak +- za trzecim razem, gdy go wgrywam wyskakuje informacja (załączam screeny) i nie ma możliwości wgrania kodu. Do tej pory radziłem sobie z tym tak, że tworzyłem nowy projekt od początku, zaczynając od CUBE itd. (stary kasowałem) i wtedy znowu miałem kilka prób na wgrywanie programu. Dodam jeszcze, że wszystko poprawnie się kompilowało. Takie tworzenie projektu od nowa jest uciążliwe. Dlaczego tak się dzieje i jak temu zaradzić? Pozdrawiam
  24. Czy można wygenerować jeden impuls instrukcją HAL_TIM_OnePulse_Start_IT bez konieczności inicjowania impulsem zewnętrznym? Jak ewentualnie to ustawić w STM32CubeMX?
  25. Cześć, Zaczynam właśnie naukę programowania STM32 i chciałbym zrobić odtwarzacz audio. Posiadam płytkę STM32F411E-Disco, która jest wyposażona w DAC CS43L22. Planowałem wykorzystać interfejs I2C. Ze schematu układu odczytałem PB6 jako linie zegara i PB9 jako linie danych. Skonfigurowałem linie w programie STM32CubeMX. Znalazłem w dokumentacji adres urządzenia: 10010100 = 0x94(Write); 10010101 = 0x95(Read). Korzystam z bibliotek HAL, więc ustawiłem rejestr adresu CS43L22_ADDRESS (0x4A << 1). Następnie w pętli wykonuję: HAL_I2C_Mem_Write(&hi2c1, CS43L22_ADDRESS,CS43L22_REG_BEEP, 1, &beep,1,100); CS43L22_REG_BEEP to 0x1C na podstawie dokumentacji &beep jest wskaźnikiem na CS43L22_BEEP 0x74, które wg. dokumentacji powinno dawać na wyjściu dźwięk 1kHz trwający 1,5s. Niestety tak się nie dzieje. Bardzo proszę o pomoc. W którym miejscu popełniłem błąd? Z góry dziękuje za pomoc i wyrozumiałość. Pozdrawiam CS43L22_datasheet.pdf
×
×
  • Utwórz nowe...