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 66 wyników

  1. Witam serdecznie. Prosze wybaczyc, ze bez pisze bez polskich znakow, ale teraz do rzeczy. Chce nawiazac komunikacje pc - mcu przez Ethernet. Pracuje na Nucleo F746ZG. Stworzylem projekt z pomoca CubeMX (v4.27.0) w ktorym uruchomilem lwIP i podstawowe protokoly (w tym UDP), jako IDE uzywam Eclipse OpenSTM32. Ustalenie IP mikrokontrolera wykonywane jest przez DHCP. Ping oraz echo UDP dziala bez problemu (wyslanie pakietu UDP z dowolnego pc w sieci skutkuje odeslaniem wiadomosci na ten sam adres ip oraz port). Moj problem zaczyna sie wowczas, gdy zmodyfikowalem funkcje udpecho_raw_recv() i chce umiescic inne dane w odsylanym pakiecie. udp_sendto(pcb, p, addr, port); /* dziala jak echo */ udp_sendto(pcb, ethTxBuffer_p_x, addr, port); /* wysyla dane z bufora */ Po przeslaniu zwykle okolo 10 pakietow z pc i uzyskaniu odpowiedzi od mcu z pakietem o innej tresci nagle mikrokontroler przestaje odpowiadac (obrazek screenshot_udp.jpg). Wyglada mi to na problem z buforem pbuf w funkcji udpecho_raw_recv(), lecz nie wiem jak sie za to zabrac. Czy ktos z Was ma moze doswiadczenie z lwIP i moglby mi podpowiedziec co z tym zrobic? Przegladalem wiele stron z podobnymi problemami, ale jednak opisane tam rozwiazania lub rady mi nie pomogly. Z gory dziekuje! Kod wyglada nastepujaco: Zmienne globalne: /* USER CODE BEGIN PV */ /* Private variables ---------------------------------------------------------*/ extern struct netif gnetif; static struct udp_pcb *udpPcb1_p; ip_addr_t ipaddress; static const char clientPacket_c[] = { 0x49, 0x20, 0x6c, 0x69, 0x6b, 0x65, 0x20, 0x63, 0x61, 0x74, 0x73, 0x2e }; static const char reply[] = { 0x67, 0x6f, 0x74, 0x20, 0x69, 0x74, 0x20, 0x62, 0x72, 0x6f }; /* USER CODE END PV */ Funkcje: static void udpecho_raw_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, struct ip_addr *addr, u16_t port) { static struct pbuf *ethTxBuffer_p_x; ethTxBuffer_p_x = pbuf_alloc(PBUF_TRANSPORT, sizeof(reply), PBUF_RAM); memcpy(ethTxBuffer_p_x->payload, reply, sizeof(reply)); udp_sendto(pcb, ethTxBuffer_p_x, addr, port); pbuf_free(ethTxBuffer_p_x); } /*-----------------------------------------------------------------------------------*/ void udpecho_raw_server_init(u16_t port) { struct udp_pcb *pcb; printf("%s() ..........\n", __func__); pcb = udp_new(); udp_bind(pcb, gnetif.ip_addr.addr, port); /* no need to loop forever */ udp_recv(pcb , udpecho_raw_recv, pcb); } W main() z rzeczy dodanych przeze mnie jest tylko: udpecho_raw_server_init(20); while(1) { MX_LWIP_Process(); }
  2. Hej, Realizuje ten kurs na stm32f429ZI (Nucleo 144). Jak do tej pory nie było problemów, czasem po prostu używałem innych portów i wszystko działało. Niestety nie tym razem. W moim przypadku chcę zaświecić diodą PB7 -> (w CUBE TIM4_CH2, pozostałe parametry zastosowałem tak jak jest opisane na kursie). Niestety po skompilowaniu wyskakiwał komunikat o niezadeklarowanej zmiennej Duty. Poniżej wklejam kod, tam też jest ta deklaracja zmiennej Duty, którą dodałem. Co jeszcze poprawić, żeby program zadziałał? /* 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 ---------------------------------------------------------*/ TIM_HandleTypeDef htim4; /* USER CODE BEGIN PV */ uint16_t Duty = 0; //deklaracja zmiennej Duty /* USER CODE END PV */ /* Private function prototypes -----------------------------------------------*/ void SystemClock_Config(void); static void MX_GPIO_Init(void); static void MX_TIM4_Init(void); /* USER CODE BEGIN PFP */ //Przerwanie wywolywane z czestotliwoscia 1KHz void HAL_SYSTICK_Callback(void) { static uint8_t InterruptPrescaler = 0; // licznik przerwan static uint8_t CzyRosnie = 1; // Flaga kierunku zliczania ++InterruptPrescaler; // Inkrementacja numeru przerwania // Jezeli wywolalo sie 40 przerwanie z rzedu if (InterruptPrescaler == 40) { InterruptPrescaler = 0; // wyzeruj licznik przerwan if (Duty == 100) // Jezeli wypelnienie jest rowne 100 CzyRosnie = 0; // Zmien kierunek zliczania w dol else if (Duty == 0) // Jezeli wypelnienie rowne 0 CzyRosnie = 1; // Zmien kierunek zliczania w gore if (CzyRosnie) // Jezeli zliczamy w gore ++Duty; // Inkrementuj wartosc wypelnienia else //Jezeli zliczamy w dol --Duty; // Dekrementuj wartosc wypelnienia } TIM4->CCR3 = Duty; // Wstawienie wyliczonej wartosci wypelnienia do // rejestru timera odpowiedzialnego za wypelnienie generowanego sygnalu PWM } /* 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_TIM4_Init(); /* USER CODE BEGIN 2 */ HAL_TIM_PWM_Start(&htim4, TIM_CHANNEL_2); /* 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_ON; RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI; RCC_OscInitStruct.PLL.PLLM = 8; RCC_OscInitStruct.PLL.PLLN = 100; RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2; RCC_OscInitStruct.PLL.PLLQ = 4; 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_PLLCLK; RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1; RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV4; RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2; if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_3) != HAL_OK) { Error_Handler(); } } /** * @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 = 4999; htim4.Init.CounterMode = TIM_COUNTERMODE_UP; htim4.Init.Period = 99; 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 Ports Clock Enable */ __HAL_RCC_GPIOA_CLK_ENABLE(); __HAL_RCC_GPIOB_CLK_ENABLE(); } /* 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****/
  3. Witam. Jestem początkujący więc z góry proszę o łagodne potraktowanie. Mam gotowy układ sterownika do z STM32 pracującym w sterowniku do drona Walkera Runner 250 Advance F3 SP Racing. Po zmianie konfiguracji w Betaflight Configurator układ zawiesił się i stracił komunikację z kompem. Proszę o informację w jaki sposób zresetować układ żeby wgrać firmware jeszcze raz. Próbowałem zewrzeć styk nRST do masy i na zwartym podłączyć ale nie przyniosło skutków. Czy macie jakieś pomysły? Proszę też o informację czy do aktualnego sterownika CP210x... jest konieczne wykonanie jeszcze jakiś operacji żeby chip STM32 stał się widoczny dla programu programującego. Próbowałem DfuSeDemo oraz UsbUpgradeTool. dzięki [ Dodano: 06-07-2018, 14:56 ] dodaje zdjęcie układu:
  4. Cześć, czy komuś udało się przerobić biblioteki dla tego wyświetlacza? https://botland.com.pl/pl/wyswietlacze-oled/4441-wyswietlacz-oled-niebieski-graficzny-13-b-128x64px-spii2c-proste-zlacza.html Próbowałam kilkakrotnie i pomimo wyeliminowania wszystkich warningów wyświetlacz nadal nie reaguje. W pliku SSD1306.h mam zdefiniowany SH1106. Nie wiem co robię źle
  5. Witam, próbuję uruchomić akcelerometr LIS3DHH ( https://www.st.com/en/mems-and-sensors/lis3dhh.html) na zestawie Nucleo F411RE (https://www.st.com/en/evaluation-tools/nucleo-f411re.html). Czujnik mam w postaci adaptera STEVAL-MKI180V1 (https://www.st.com/en/evaluation-tools/steval-mki180v1.html). Konfigurację dla mikrokontrolera generuję za pomocą CubeMX 5.0.1 z bibliotekami HAL dla rodziny STM32F4, w wersji 1.23.0. Próbę uruchomienia czujnika rozpocząłem od wykorzystania bibliotek: https://github.com/STMicroelectronics/STMems_Standard_C_drivers/tree/master/lis3dhh_STdC, a dokładnie od przykładu: read_data_simple.c. Po dużej liczbie nieudanych prób komunikacji, maksymalnie uprościłem przykład. Aktualnie próbuję odczytać wartość rejestru WHO_AM_I. Adres rejestru to: 0x0F. Podczas odczytu danych, bit SMB adresu powinien mieć wartość 1, więc modyfikuję adres rejestru do wartości 0x8F. Wartość rejestru WHO_AM_I powinna wynosić 0x11, a ja otrzymuję wartość 0x00. Wszystkie linie SPI są sprzętowo podciągnięte do plusa zasilania, za pomocą wewnętrznych rezystorów mikrokontrolera. Korzystam z SPI2. Jego konfiguracja to: CPOL = High, CPHA = 2 Edge, prędkość: 1.3125 Mbits/s. Sygnał CS jest generowany programowo. Poniżej przedstawiam fragment kodu źródłowego odpowiedzialnego za inicjalizację SPI oraz próbę odczytania rejestru WHO_AM_I. Inicjalizacja SPI: void MX_SPI2_Init(void) { hspi2.Instance = SPI2; hspi2.Init.Mode = SPI_MODE_MASTER; hspi2.Init.Direction = SPI_DIRECTION_2LINES; hspi2.Init.DataSize = SPI_DATASIZE_8BIT; hspi2.Init.CLKPolarity = SPI_POLARITY_HIGH; hspi2.Init.CLKPhase = SPI_PHASE_2EDGE; hspi2.Init.NSS = SPI_NSS_SOFT; hspi2.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_32; hspi2.Init.FirstBit = SPI_FIRSTBIT_MSB; hspi2.Init.TIMode = SPI_TIMODE_DISABLE; hspi2.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE; hspi2.Init.CRCPolynomial = 10; if (HAL_SPI_Init(&hspi2) != HAL_OK) { Error_Handler(); } } [Próba odczytu zawartości rejestru WHO_AM_I (zawarte w funkcji main): MX_GPIO_Init(); MX_SPI2_Init(); HAL_Delay(10); HAL_StatusTypeDef status; uint8_t reg = 0x0F; // Adres rejestru WHO_AM_I uint8_t bufp[3]; uint16_t len = 1; reg |= 0x80; // Informacja, ze przeprowadzany bedzie odczyt danych HAL_GPIO_WritePin(SPI_CS_GPIO_Port, SPI_CS_Pin, GPIO_PIN_RESET); // Aktywacja SPI status = HAL_SPI_Transmit(&LIS3DHH_HANDLE, ®, 1, 1000); // Wyslanie adresu do odczytu status = HAL_SPI_Receive(&LIS3DHH_HANDLE, bufp, len, 1000); // Odbior zawartosci adresu HAL_GPIO_WritePin(SPI_CS_GPIO_Port, SPI_CS_Pin, GPIO_PIN_SET); // Dezaktywacja SPI W załączniku przedstawiam przebiegi uzyskane z analizatora stanów logicznych, plik konfiguracyjny dla CubeMX oraz kod źródłowy programu testowego. Dodam, że testy przeprowadzałem na dwóch czujnikach, oraz dodatkowo na zestawie z mikrokontrolerem STM32F103 (blue PCB). Modyfikowałem na wiele sposobów konfigurację SPI oraz odczyt rejestrów. Efekt za każdym razem taki sam. Czy ktoś ma pomysł co robię nie tak, że za każdym razem otrzymuję wartość zero z rejestru WHO_AM_I? Test_LIS3DHH_F4.zip
  6. Dodając krok po kroku trochę automatyki w mieszkaniu powstał projekt i realizacja sterownika rolet zewnętrznych. Główne cechy urządzenia: obsługa 7 rolet zdalny dostęp z dowolnego miejsca na świecie sterowanie przez Wifi sterowanie przez Bluetooth sterowanie przez sieć CAN automatyczny pomiar czasu pracy poszczególnych rolet harmonogram otwierania/zamykania rolet sterowanie grupowe tworzenie scen pobieranie aktualnego czasu z serwera NTP Sterownik został podzielony na dwie części, pierwsza to płytka z przekaźnikami i zasilaniem, druga płytka to układ sterowania wraz z modułami komunikacyjnymi. Główne elementy wykorzystane w sterowniku to: STM32F103C8T6 jako moduł Bluepill Moduł Wifi ESP-12 Bluetooth HC-05 Największym wyzwanie okazało się wykrywanie zakończenia pracy rolety. Było to niezbędne do automatycznego pomiaru czasu pracy, które jest wykorzystywane do określania pozycji pośrednich. Na początku testowałem wykrywanie prądu z wykorzystaniem modułu ACS711, ale niewielki prąd pobierany przez roletę podczas pracy powodował niestabilne pomiary z układu ACS711. Drugim pomysłem było wykorzystanie przekładników prądowych. Pomiary były stabilne, ale to rozwiązanie odpadło ze względu na fizyczne rozmiary takich przekładników, potrzebowałem użyć ich aż siedem sztuk. Ostatecznie zastosowałem rozwiązanie polegające na spadku napięcia na diodach, które aktywuje transoptor PC814. Rolety które posiadam mają wewnętrzne zabezpieczenie przed podaniem napięcia na oba uzwojenia silnika (góra, dół), jednak tak zaprojektowałem układ, aby sprzętowo nie było to możliwe. Pokazane jest to na poniższym rysunku. Program został napisany w C++ z wykorzystanie Arduino Core. ESP-12 pełni rolę konwertera komunikacyjnego, od strony wifi oferuje RestApi, konwertuje otrzymane wiadomości/zapytania na komunikację uart i wysyła do głównego procesora STM32. Na drugim porcie uart w STM32 jest podobna komunikacja z wykorzystaniem modułu bluetooth. Moduł BT aktualnie służy do przeglądania bieżących logów. Ponadto moduł posiada opcję komunikacji z wykorzystaniem sieci CAN, jestem bardziej fanem rozwiązań przewodowych tam gdzie jest to możliwe. Jak w mieszkaniu pojawi się więcej elementów automatyki to będę chciał całość przepiąć na sieć CAN zamiast Wifi. Sterowanie modułem odbywa się jak wspomniałem wyżej zapytaniami REST, na Banana Pro posiadam domowy serwer www, dołożyłem do niego prostą stronę w PHP, która pozwala w wygodny sposób wysyłać zapytania do sterownika. Do połączenia się ze sterownikiem poza domową siecią wykorzystuje OpenVPNa.
  7. Witam wszystkich na forum. Od kilku dni posiłkując się starym i nowym kursem STM32F1 staram się przeportować z biblioteki StdPeriph na HAL program obsługujący czujnik HC-SR04, wykorzystujący przerwania i timery ( http://www.avislab.com/blog/stm32-exti/ ). Niestety program zawsze zwraca wartość pomiaru 0. Na 99% problem powoduje nieprawidłowa implementacja timera 3 lub błędnie napisane przerwanie służące do pomiaru długości sygnału Echo. Czy jest ktoś w stanie określić w którym miejscu jest błąd? Mój kod HAL: void sonar_init() { //Timer3 Echo __HAL_RCC_TIM3_CLK_ENABLE(); tim3.Instance = TIM3; tim3.Init.Prescaler = 64 - 1; tim3.Init.CounterMode = TIM_COUNTERMODE_UP; tim3.Init.ClockDivision = 0; tim3.Init.RepetitionCounter = 0; tim3.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE; HAL_TIM_Base_Init(&tim3); HAL_TIM_Base_Start_IT(&tim3); __HAL_RCC_GPIOC_CLK_ENABLE(); //Trigger Pin8 GPIO_InitTypeDef gpio; gpio.Pin = GPIO_PIN_8; gpio.Mode = GPIO_MODE_OUTPUT_PP; gpio.Speed = GPIO_SPEED_FREQ_LOW; HAL_GPIO_Init(GPIOC, &gpio); //Echo Pin9 GPIO_InitTypeDef GPIO_InitStruct; gpio.Pin = GPIO_PIN_9; gpio.Mode = GPIO_MODE_AF_PP; gpio.Speed = GPIO_SPEED_FREQ_LOW; HAL_GPIO_Init(GPIOC, &GPIO_InitStruct); HAL_NVIC_EnableIRQ(EXTI9_5_IRQn); } void EXTI9_5_IRQHandler(void) { HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_9); } void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin){ if(GPIO_Pin == GPIO_PIN_9){ if (HAL_GPIO_ReadPin(GPIOC, GPIO_PIN_9) != 0) { // Rising __HAL_TIM_SET_COUNTER(&tim3, 0); } if (HAL_GPIO_ReadPin(GPIOC, GPIO_PIN_9) == 0) { // Falling SonarValue = __HAL_TIM_GET_COUNTER(&tim3); } } } void sonar_start() { //10us TRIG int i; HAL_GPIO_WritePin(GPIOC, GPIO_PIN_8, GPIO_PIN_SET); //TRIG ON for(i=0;i<0x6400;i++); HAL_GPIO_WritePin(GPIOC, GPIO_PIN_8, GPIO_PIN_RESET); //TRIG OFF } unsigned int sonar_get() { unsigned long Sonar; // 354 Sound speed (mm/sec), 64000 - F_CPU, Result = mm Sonar = (354/2) * (unsigned long)SonarValue / (64000 / 64); return (unsigned int)Sonar; }
  8. Czy ma ktoś działającą bibliotekę do obsługi wyświetlacza ST7565 działającą pod STM32F103 lub podobnym?
  9. Witam, Chcialem sie was zapytac, czy ta funkcja jest poprawna? Czy takie rozwiazanie nie bedzie powodowac wyciekow pamieci? Czy rozmiar tablicy jest dobrze alokowany? char * subarray; char buffor[30]; uint8_t bufforElementsNumber = 0; char * getSubArray(int size, char array[]) { subarray = NULL; subarray = malloc(sizeof(char) * size); for (int i = 0; i < size; i++) { subarray[i] = array[i]; } return subarray; }
  10. Cześć, mam problem z komunikacją USART na stm32L452RE, poniżej zamieszczam kody, które napisałem przy pomocy znalezionych przykładów. Nie mam pojęcia czego tu jeszcze brakuje. Kod inicjalizacji USART: static void MX_USART2_UART_Init(void) { LL_USART_InitTypeDef USART_InitStruct; LL_GPIO_InitTypeDef GPIO_InitStruct; /* Peripheral clock enable */ LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_USART2); /**USART2 GPIO Configuration PA2 ------> USART2_TX PA3 ------> USART2_RX */ GPIO_InitStruct.Pin = USART_TX_Pin|USART_RX_Pin; GPIO_InitStruct.Mode = LL_GPIO_MODE_ALTERNATE; GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_VERY_HIGH; GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL; GPIO_InitStruct.Pull = LL_GPIO_PULL_NO; GPIO_InitStruct.Alternate = LL_GPIO_AF_7; LL_GPIO_Init(GPIOA, &GPIO_InitStruct); /* USART2 interrupt Init */ NVIC_SetPriority(USART2_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(),0, 0)); NVIC_EnableIRQ(USART2_IRQn); USART_InitStruct.BaudRate = 115200; USART_InitStruct.DataWidth = LL_USART_DATAWIDTH_8B; USART_InitStruct.StopBits = LL_USART_STOPBITS_1; USART_InitStruct.Parity = LL_USART_PARITY_NONE; USART_InitStruct.TransferDirection = LL_USART_DIRECTION_TX_RX; USART_InitStruct.HardwareFlowControl = LL_USART_HWCONTROL_NONE; USART_InitStruct.OverSampling = LL_USART_OVERSAMPLING_16; LL_USART_Init(USART2, &USART_InitStruct); LL_USART_ConfigAsyncMode(USART2); LL_USART_Enable(USART2); } Kod ciała przerwania USARTA: void USART2_IRQHandler(void) { /* USER CODE BEGIN USART2_IRQn 0 */ if(LL_USART_IsEnabledIT_TXE(USARTx_INSTANCE) && LL_USART_IsActiveFlag_TXE(USARTx_INSTANCE)) { /* TXE flag will be automatically cleared when writing new data in TDR register */ /* Call function in charge of handling empty DR => will lead to transmission of next character */ USART_TXEmpty_Callback(); } if(LL_USART_IsEnabledIT_TC(USARTx_INSTANCE) && LL_USART_IsActiveFlag_TC(USARTx_INSTANCE)) { /* Clear TC flag */ LL_USART_ClearFlag_TC(USARTx_INSTANCE); /* Call function in charge of handling end of transmission of sent character and prepare next charcater transmission */ USART_CharTransmitComplete_Callback(); } if(LL_USART_IsEnabledIT_ERROR(USARTx_INSTANCE) && LL_USART_IsActiveFlag_NE(USARTx_INSTANCE)) { /* Call Error function */ Error_Callback(); } /* USER CODE END USART2_IRQn 0 */ /* USER CODE BEGIN USART2_IRQn 1 */ /* USER CODE END USART2_IRQn 1 */ } Funkcje wykorzystane w powyższym przerwaniu: void USART_TXEmpty_Callback(void) { if(ubSend == (ubSizeToSend - 1)) { /* Disable TXE interrupt */ LL_USART_DisableIT_TXE(USARTx_INSTANCE); /* Enable TC interrupt */ LL_USART_EnableIT_TC(USARTx_INSTANCE); } /* Fill TDR with a new char */ LL_USART_TransmitData8(USARTx_INSTANCE, aStringToSend[ubSend++]); } void USART_CharTransmitComplete_Callback(void) { if(ubSend == sizeof(aStringToSend)) { ubSend = 0; /* Disable TC interrupt */ LL_USART_DisableIT_TC(USARTx_INSTANCE); /* Turn LED1 On at end of transfer : Tx sequence completed successfully */ //LED_On(); } } void Error_Callback(void) { __IO uint32_t isr_reg; /* Disable USARTx_IRQn */ NVIC_DisableIRQ(USARTx_IRQn); /* Error handling example : - Read USART ISR register to identify flag that leads to IT raising - Perform corresponding error handling treatment according to flag */ isr_reg = LL_USART_ReadReg(USARTx_INSTANCE, ISR); if (isr_reg & LL_USART_ISR_NE) { /* case Noise Error flag is raised : ... */ //LED_Blinking(LED_BLINK_FAST); } else { /* Unexpected IT source : Set LED to Blinking mode to indicate error occurs */ //LED_Blinking(LED_BLINK_ERROR); } } Na koniec użycie funkcji do wysłania danych w przerwaniu o low power LPTIM: void LPTIM1_IRQHandler(void) { /* USER CODE BEGIN LPTIM1_IRQn 0 */ /* Start USART transmission : Will initiate TXE interrupt after TDR register is empty */ LL_USART_TransmitData8(USARTx_INSTANCE, aStringToSend[ubSend++]); /* Enable TXE interrupt */ LL_USART_EnableIT_TXE(USARTx_INSTANCE); LL_LPTIM_ClearFLAG_ARRM(LPTIM1); LL_LPTIM_ClearFLAG_CMPM(LPTIM1); LL_LPTIM_ClearFlag_ARROK(LPTIM1); /* USER CODE END LPTIM1_IRQn 0 */ /* USER CODE BEGIN LPTIM1_IRQn 1 */ /* USER CODE END LPTIM1_IRQn 1 */ } Uprzejmie proszę o pomoc, bo nie mam pojęcia co tu jest nie tak. Za wszystkie odpowiedzi serdeczne dzięki.
  11. Posiadam płytkę STM32F407G-DISC1 oraz ekspander MCP23S08. Na podstawie kursu STM32F4 oraz STM32F1 próbuję zapalić diodę na wyjściu ekspandera. Korzystam z CUBEMX do konfiguracji mikrokontrolera oraz eclipse'a do programowania. Mam wrażenie, że wszystko robię w poprawny sposób, konfiguracja SPI jest zgodna z tą pokazaną w 9 części kursu STM32F1 a mimo to wyjścia ekspandera pozostają nieaktywne. Oczekuję, że zapali się dioda podpięta do pinu GP0. Poniżej dołączam mój kod: /* Includes ------------------------------------------------------------------*/ #include "main.h" #include "stm32f4xx_hal.h" /* USER CODE BEGIN Includes */ #define MCP_IODIR 0x00 #define MCP_OLAT 0x0a /* USER CODE END Includes */ /* Private variables ---------------------------------------------------------*/ SPI_HandleTypeDef hspi1; /* USER CODE BEGIN PV */ /* Private variables ---------------------------------------------------------*/ /* USER CODE END PV */ /* Private function prototypes -----------------------------------------------*/ void SystemClock_Config(void); static void MX_GPIO_Init(void); static void MX_SPI1_Init(void); /* USER CODE BEGIN PFP */ /* Private function prototypes -----------------------------------------------*/ void mcp_write_reg(uint8_t addr, uint8_t value) { uint8_t tx_buff[]={0x40, addr, value}; HAL_GPIO_WritePin(CS_GPIO_Port, CS_Pin, GPIO_PIN_RESET); HAL_SPI_Transmit(&hspi1, tx_buff, 3, HAL_MAX_DELAY); HAL_GPIO_WritePin(CS_GPIO_Port, CS_Pin, GPIO_PIN_SET); } /* USER CODE END PFP */ /* USER CODE BEGIN 0 */ /* USER CODE END 0 */ 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_SPI1_Init(); /* USER CODE BEGIN 2 */ mcp_write_reg(MCP_IODIR, ~0x01); /* USER CODE END 2 */ /* Infinite loop */ /* USER CODE BEGIN WHILE */ mcp_write_reg(MCP_OLAT, 0x01); while (1) { /* USER CODE END WHILE */ /* USER CODE BEGIN 3 */ } /* USER CODE END 3 */ } /** System Clock Configuration */ void SystemClock_Config(void) { RCC_OscInitTypeDef RCC_OscInitStruct; RCC_ClkInitTypeDef RCC_ClkInitStruct; /**Configure the main internal regulator output voltage */ __HAL_RCC_PWR_CLK_ENABLE(); __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1); /**Initializes the CPU, AHB and APB busses clocks */ RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI; RCC_OscInitStruct.HSIState = RCC_HSI_ON; RCC_OscInitStruct.HSICalibrationValue = 16; RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON; RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI; RCC_OscInitStruct.PLL.PLLM = 8; RCC_OscInitStruct.PLL.PLLN = 64; RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2; RCC_OscInitStruct.PLL.PLLQ = 4; if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) { _Error_Handler(__FILE__, __LINE__); } /**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_PLLCLK; RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV8; RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2; RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2; if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_0) != HAL_OK) { _Error_Handler(__FILE__, __LINE__); } /**Configure the Systick interrupt time */ HAL_SYSTICK_Config(HAL_RCC_GetHCLKFreq()/1000); /**Configure the Systick */ HAL_SYSTICK_CLKSourceConfig(SYSTICK_CLKSOURCE_HCLK); /* SysTick_IRQn interrupt configuration */ HAL_NVIC_SetPriority(SysTick_IRQn, 0, 0); } /* SPI1 init function */ static void MX_SPI1_Init(void) { /* SPI1 parameter configuration*/ hspi1.Instance = SPI1; hspi1.Init.Mode = SPI_MODE_MASTER; hspi1.Init.Direction = SPI_DIRECTION_2LINES; hspi1.Init.DataSize = SPI_DATASIZE_8BIT; hspi1.Init.CLKPolarity = SPI_POLARITY_LOW; hspi1.Init.CLKPhase = SPI_PHASE_1EDGE; hspi1.Init.NSS = SPI_NSS_SOFT; hspi1.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_4; hspi1.Init.FirstBit = SPI_FIRSTBIT_MSB; hspi1.Init.TIMode = SPI_TIMODE_DISABLE; hspi1.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE; hspi1.Init.CRCPolynomial = 10; if (HAL_SPI_Init(&hspi1) != HAL_OK) { _Error_Handler(__FILE__, __LINE__); } } /** Configure pins as * Analog * Input * Output * EVENT_OUT * EXTI */ static void MX_GPIO_Init(void) { GPIO_InitTypeDef GPIO_InitStruct; /* GPIO Ports Clock Enable */ __HAL_RCC_GPIOA_CLK_ENABLE(); __HAL_RCC_GPIOC_CLK_ENABLE(); __HAL_RCC_GPIOB_CLK_ENABLE(); __HAL_RCC_GPIOE_CLK_ENABLE(); /*Configure GPIO pin Output Level */ HAL_GPIO_WritePin(CS_GPIO_Port, CS_Pin, GPIO_PIN_RESET); /*Configure GPIO pin Output Level */ HAL_GPIO_WritePin(DC_GPIO_Port, DC_Pin, GPIO_PIN_RESET); /*Configure GPIO pin Output Level */ HAL_GPIO_WritePin(RESET_GPIO_Port, RESET_Pin, GPIO_PIN_RESET); /*Configure GPIO pin : CS_Pin */ GPIO_InitStruct.Pin = CS_Pin; GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; HAL_GPIO_Init(CS_GPIO_Port, &GPIO_InitStruct); /*Configure GPIO pin : DC_Pin */ GPIO_InitStruct.Pin = DC_Pin; GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; HAL_GPIO_Init(DC_GPIO_Port, &GPIO_InitStruct); /*Configure GPIO pin : RESET_Pin */ GPIO_InitStruct.Pin = RESET_Pin; GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; HAL_GPIO_Init(RESET_GPIO_Port, &GPIO_InitStruct); } /* USER CODE BEGIN 4 */ /* USER CODE END 4 */ /** * @brief This function is executed in case of error occurrence. * @param None * @retval None */ void _Error_Handler(char * file, int line) { /* USER CODE BEGIN Error_Handler_Debug */ /* User can add his own implementation to report the HAL error return state */ while(1) { } /* 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, ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */ /* USER CODE END 6 */ } #endif /** * @} */ /** * @} */ /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
  12. Witam wszystkich, jakiś czas temu przeniosłem się na procki STM32F1, sporo korzystałem z kursów Forbot więc postaram się także w jakiś sposób odwdzięczyć za czyjąś robotę. Dziś prezentuję moją implementację UARTa wspomaganą buforami FIFO i przerwaniami. Zaletą takiego rozwiązania jest, pod warunkiem nie wysyłania danych więcej niż szybkość transmisji, natychmiastowe wyjście z procedury wysłania bajtu, zaś przy odczycie danych, braku gubienia przychodzących bajtów jeżeli czytamy w zbyt długich odstępach czasu. Temat ten wielokrotnie pojawiał się tutaj w przykładach ale nigdzie nie znalazłem kompleksowego, zadowalającego mnie rozwiązania, prezentuję więc własne, może się komuś przydać albo udoskonalić. Moje rozwiązanie bazuje na HAL, jako implementacji FIFO użyłem kodu z wyguglanej kwerendy"Steve Karg Interrupt Safe Ring Buffer Library", chociaż w moim rozwiązaniu bezpieczeństwo na przerwania nie jest wymagane. Pomijając trywialne sprawy typu inicjalizacja FIFO, pinów, UARTA itd, zakładamy: UART_HandleTypeDef g_uart1; // poprawnie zainicjowany UART: 1) Odbieranie danych, założenia: FIFO_BUFFER g_rxFifo; // Bufor odbiorczy uint8_t g_rxBuffer; // Pomocniczy bajt do odbierania danych Inicjalizacjia, konieczne jest zainicjowanie odbierania na przerwaniach, najlepiej zrobić to zaraz przy inicjalizacji UARTa: HAL_UART_Receive_IT(&g_uart1, &g_rxBuffer, 1); Inicjalizuje to odbiór danych, 1 bajtu do buforu g_rxBuffer. Funkcja ta wraca od razu, rezultatem będzie zawołanie callbacka HAL_UART_RxCpltCallback który należy przekierować do poniższej funkcji: void serial1_RxCpltCallback() { FIFO_Put(&g_rxFifo, g_rxBuffer); HAL_UART_Receive_IT(&g_uart1, &g_rxBuffer, 1); } Funkcja ta wpisuje odebraną wartość do FIFO i natychmiast inicjuje odbieranie kolejnego bajtu. Funkcja do odbierania wygląda następująco, zwraca status: 0 - nie odebrano bajtu, 1 - odebrano bajt, przypisano pod podany wskaźnik. Niestety nie ma tutaj kontroli gdy odbieranie przepełni FIFO i zacznie gubić odbierane bajty, implementacja musi zapewniać w miarę sprawne odbieranie danych. Sprawę wyłączania i włączania przerwań opiszę później. uint8_t serial1_receive(uint8_t* byte) { __disable_irq(); if( FIFO_Empty(&g_rxFifo)) { __enable_irq(); return 0; } *byte = FIFO_Get(&g_rxFifo); __enable_irq(); return 1; } 2) Wysyłanie danych: FIFO_BUFFER g_txFifo; // Bufor nadawczy uint8_t g_txBuffer; // Pomocniczy volatile uint8_t g_txPending = 0; // Flaga informująca o trwającej transmisji bajtu. Zasada działania, początkowo txPending = 0 co oznacza że nic nie jest wysyłane, w takim przypadku przestawiamy ją na 1 i bajt danych wysyłamy bezpośrednio wołając HAL_UART_Transmit_IT, nie korzystając z fifo. Jednak zawołamy funkcję drugi raz zanim transmisja się zakończy i wywoła przewanie końca transmisji to txPending będzie miało wartość 1 co oznacza, że bajtu wysłać nie można i wpisujemy go do FIFO. Tutaj jeszcze sprawdzamy czy FIFO nie jest pełne, jeśli pełne go czekamy aż się zwolni i to jest jedyna możliwość gdy funkcja może trwać niespodziewania długo, ale dzięki temu jest gwarancja braku dropowania bajtów przy zbyt szybkiej transmisji. Jeśli komuś na tym nie zależy może usunąć pętlę while, pozostawiająć wykonanie FIFO_Put. void serial1_send(uint8_t byte) { __disable_irq(); if( g_txPending ) { while(!FIFO_Put(&g_txFifo, byte)) { __enable_irq(); __disable_irq(); } } else { g_txPending = 1; g_txBuffer = byte; HAL_UART_Transmit_IT(&g_uart1, &g_txBuffer, 1); } __enable_irq(); } Callback HAL_UART_TxCpltCallback należy przekierować do poniższej funkcji która działa w następujący sposób, jeśli fifo nie jest puste to pobiera z niego kolejny bajt i ponownie inicjuje transmisję na przewaniach, pozostając w stanie trwającej transmisji (txPending jest i pozostaje 1), natomiast jeśli fifo jest puste to oznacza to że nie ma już nic do transmisji i przestawiamy stan na txPending = 0. void serial1_TxCpltCallback() { if( !FIFO_Empty(&g_txFifo)) { g_txBuffer = FIFO_Get(&g_txFifo); HAL_UART_Transmit_IT(&g_uart1, &g_txBuffer, 1); } else { g_txPending = 0; } } 3) Słowo o włączaniu/wyłączaniu przerwań i innych niuansach, zauważmy że przy odbiorze danych kod HAL (funkcja HAL_UART_Receive_IT) jest wołana tylko z przerwania, natomiast przy wysyłaniu (funkcja) HAL_UART_Transmit_IT z przerwania bądź z programu głównego. Pisząc tą implementację tymczasowo odbieranie miałem w przedstawionej tutaj wersji zaś nadawanie jako klasyczne, blokujące HAL_UART_Transmit z programu głównego. I niestety pojawia się problem, gdy przerwanie HAL_UART_RxCpltCallback pojawi się w czasie trwającego, blokującego HAL_UART_Transmit gdyż HAL zaznacza ten obiekt jako locked i cokolwiek będziemy chcieli zrobić w czasie przerwania to nam się nie uda, dostaniemy status HAL_BUSY z HAL_UART_Receive_IT i transmisja stanie. Żaden z tutoriali poruszających transmisję UART na przerwaniach nie podaje tego niuansu a jest to akurat niezwykle istotne dla prawidłowego działania w dłuższym czasie. Rozwiązanie które przedstawiłem jest bezpieczne pod tym względem, każda funkcja kliencka wyłącza tymczasowo przerwania aby zabezpieczyć się przed tym problemem. 4) Ulepszenia. "Ręczne" fifo można przerobić na DMA, wysyłanie wielu bajtów można usprawnić pobierając z FIFO więcej niż jeden bajt, czego z pewnością prędzej czy później dokonam. Pozdrawiam, Remigiusz
  13. Czołem, mam pewien problem. Czytając reference manuala STM'a nie do końca rozumiem jak uruchomić przetwornik analogowo-cyfrowy pisząc na poziomie Low Layer ( założeniem projektu jest nie korzystać z bibliotek HAL'a). Jestem początkujący w programowaniu "bez HAL", dlatego proszę o wyrozumiałość i o pomoc/rady. Ustawienia ADC jakie wygenerowałem przy użyciu Cube'a wyglądają następująco: static void MX_ADC1_Init(void) { LL_ADC_InitTypeDef ADC_InitStruct; LL_ADC_REG_InitTypeDef ADC_REG_InitStruct; LL_ADC_CommonInitTypeDef ADC_CommonInitStruct; LL_GPIO_InitTypeDef GPIO_InitStruct; /* Peripheral clock enable */ LL_AHB2_GRP1_EnableClock(LL_AHB2_GRP1_PERIPH_ADC); /**ADC1 GPIO Configuration PC0 ------> ADC1_IN1 PC4 ------> ADC1_IN13 */ GPIO_InitStruct.Pin = LL_GPIO_PIN_0|LL_GPIO_PIN_4; GPIO_InitStruct.Mode = LL_GPIO_MODE_ANALOG; GPIO_InitStruct.Pull = LL_GPIO_PULL_NO; LL_GPIO_Init(GPIOC, &GPIO_InitStruct); /* ADC1 interrupt Init */ NVIC_SetPriority(ADC1_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(),0, 0)); NVIC_EnableIRQ(ADC1_IRQn); /**Common config */ ADC_InitStruct.Resolution = LL_ADC_RESOLUTION_12B; ADC_InitStruct.DataAlignment = LL_ADC_DATA_ALIGN_RIGHT; ADC_InitStruct.LowPowerMode = LL_ADC_LP_MODE_NONE; LL_ADC_Init(ADC1, &ADC_InitStruct); ADC_REG_InitStruct.TriggerSource = LL_ADC_REG_TRIG_SOFTWARE; ADC_REG_InitStruct.SequencerLength = LL_ADC_REG_SEQ_SCAN_DISABLE; ADC_REG_InitStruct.SequencerDiscont = LL_ADC_REG_SEQ_DISCONT_DISABLE; ADC_REG_InitStruct.ContinuousMode = LL_ADC_REG_CONV_SINGLE; ADC_REG_InitStruct.DMATransfer = LL_ADC_REG_DMA_TRANSFER_LIMITED; ADC_REG_InitStruct.Overrun = LL_ADC_REG_OVR_DATA_PRESERVED; LL_ADC_REG_Init(ADC1, &ADC_REG_InitStruct); LL_ADC_SetOverSamplingScope(ADC1, LL_ADC_OVS_DISABLE); ADC_CommonInitStruct.CommonClock = LL_ADC_CLOCK_ASYNC_DIV1; LL_ADC_CommonInit(__LL_ADC_COMMON_INSTANCE(ADC1), &ADC_CommonInitStruct); LL_ADC_EnableIT_EOC(ADC1); LL_ADC_DisableIT_EOS(ADC1); /**Configure Regular Channel */ LL_ADC_REG_SetSequencerRanks(ADC1, LL_ADC_REG_RANK_1, LL_ADC_CHANNEL_1); LL_ADC_SetChannelSamplingTime(ADC1, LL_ADC_CHANNEL_1, LL_ADC_SAMPLINGTIME_2CYCLES_5); LL_ADC_SetChannelSingleDiff(ADC1, LL_ADC_CHANNEL_1, LL_ADC_SINGLE_ENDED); } A ciało przerwania ADC tak: void ADC1_IRQHandler(void) { /* USER CODE BEGIN ADC1_IRQn 0 */ /* USER CODE END ADC1_IRQn 0 */ /* USER CODE BEGIN ADC1_IRQn 1 */ /* USER CODE END ADC1_IRQn 1 */ } Wstawiłem tylko wygenerowane fragmenty kodu, gdyż stwierdziłem że nie ma sensu wstawiać tu kodów wszystkich moich prób. Bardzo proszę o wskazanie mi, co mam gdzie wpisać, bądź jakich funkcji użyć, lub jeśli to nie problem napisać fragmenty uzupełniając powyższy kod, bo już sam nie wiem jak to mam zrobić. Za wszystkie odpowiedzi i pomoc bardzo dziękuję.
  14. Czołem koledzy, mam problem z Eclipse Version: Mars.2 Release (4.5.2) przygotowanego pod kurs STM32 F3 CUBE & HAL. Do programu wygenerowanego przez STM32CubeMX próbuję dołączyć własne pliki *.c i *.h source i header. Dodam, że robiłem takie rzeczy z powodzeniem dla Eclipse i AVR, nie przypominam sobie żadnych problemów. W tym wypadku ciągle dostaje błędy kompilacji m.in "no such file or directory" lub niewłaściwa liczba argumentów dla funkcji . Walczę z tym od kilku dni i mam wrażeniem, że nie będę potrafił prosto opisać moich problemów. Dlatego po prostu proszę was o wskazówkę. Jak właściwi załączyć do projektu CUBEMX w Eclipse pliki source i header *.c *.h zawierające moje własne funkcje. Dzięki za pomoc Zagadnienie rozwiązane, internety pomogły. http://www.openstm32.org/forumthread3284
  15. Witam, są to dopiero moje początki z STM32 Nucleo więc na wstępie proszę o wyrozumiałość. Posiadam model Nucleo 32 F042K6 oraz mostek L298n. Na mostku znajduje się 6 pinów ( ENA, In1, In2, In3, In4, ENB). Powiem na przykładzie arduino, gdy na ENA i ENB jest zworka prędkość jest albo 100% albo 0% w zależności od stanów. Gdy wyjmę zworki podłączałem te 2 piny do analogowych ( ENA, ENB), In'y do cyfrowych i wywoływałem funkcje w arduino: void forward(){ digitalWrite(in1, HIGH); digitalWrite(in2, LOW); analogWrite(ENA, 200); //wartosc od 100 do 255 digitalWrite(in3, HIGH); digitalWrite(in4, LOW); analogWrite(ENB, 200); } Było wszystko w porządku i właśnie o takie coś mi chodzi. Gdy znów wpiąłem zworki, podłączyłem 4 piny operujące stanami do Nucleo napisałem w STM Workbench, że silniki mają się kręcić do przodu oba też było dobrze: int main(void) { HAL_Init(); __HAL_RCC_GPIOB_CLK_ENABLE(); GPIO_InitTypeDef gpio; gpio.Pin = (GPIO_PIN_0 | GPIO_PIN_7 | GPIO_PIN_6 | GPIO_PIN_1); gpio.Mode = GPIO_MODE_OUTPUT_PP; gpio.Pull = GPIO_NOPULL; gpio.Speed = GPIO_SPEED_FREQ_LOW; HAL_GPIO_Init(GPIOB, &gpio); while (1) { HAL_GPIO_WritePin(GPIOB, GPIO_PIN_0, GPIO_PIN_SET); HAL_GPIO_WritePin(GPIOB, GPIO_PIN_7, GPIO_PIN_RESET); HAL_GPIO_WritePin(GPIOB, GPIO_PIN_6, GPIO_PIN_SET); HAL_GPIO_WritePin(GPIOB, GPIO_PIN_1, GPIO_PIN_RESET); } } Problem jest taki że nie mogę poradzić sobie z ustawieniem prędkości obrotowej w nucleo na tych dwóch pinach. Dodam że TIM2 Kanał 1 jest na pinie PA0 natomiast TIM2 kanał 1 jest na pinie PA6. Korzystałem z wielu poradników jednak w internecie nic konkretnego ( co byłoby dla mnie zrozumiałe ) nie znalazłem. Proszę o jakieś konkretne rozwiązania. Chciałbym sterować w zakresie mniej więcej takim jak arduino, albo najlepiej od 0 do 100.
  16. Mam pytanie dot. definicji(stm32h7xx_hal_gpio.h): #define GPIO_SPEED_FREQ_LOW ((uint32_t)0x00000000U) /*!< Low speed */ #define GPIO_SPEED_FREQ_MEDIUM ((uint32_t)0x00000001U) /*!< Medium speed */ #define GPIO_SPEED_FREQ_HIGH ((uint32_t)0x00000002U) /*!< Fast speed */ #define GPIO_SPEED_FREQ_VERY_HIGH ((uint32_t)0x00000003U) /*!< High speed */ Jakie one oznaczają wartości częstotliwości pracy portu GPIO dla płytki Nucleo-H743ZI?
  17. Warto może dodać odcinek o sygnałach zegarowych i procedurze uruchamiania mikrokontrolera. Treker // Posty zostały wydzielone z poniższego tematu:
  18. Witam serdecznie. Jestem początkującym w STM. Właśnie przechodzę z AVR. Chcę wysłać przez UART liczbę a dokładnie przekonwertować ją na stringa poleceniem itoa. Rok temu już to zrobiłem, ale w między czasie padł mi dysk i wszystko straciłem. Zrobiłem funkcję: void send_integer(uint8_t n){ char *s; itoa ( n, s, 10 ); send_string(s); } ale podczas kompilacji wywala mi błąd ..\Src\main.c:308:12: warning: 's' is used uninitialized in this function [-Wuninitialized] itoa ( n, *s, 10 );
  19. Witam serdecznie, jestem kompletnie nowy w temacie elektroniki i dopiero zaczynam z tym przygodę. Od jakiegoś czasu myślę nad tematem jakiejś prostej elektroniki, którą mógłbym zrobić na podanej w temacie płytce(narzucona odgórnie), ale nic nie przychodzi mi do głowy stąd mój post tutaj. Czy mógłby ktoś zasugerować mi jakiś pomysł na niezbyt zaawansowaną, acz też nie za prostą elektronikę którą mógłbym zrealizować na tej płytce? Do tej pory do głowy przyszedł mi tylko termometr, alkomat, zamek magnetyczny i to w sumie tyle. Czekam na jakiś odzew i z góry dziękuję
  20. Witam! Jestem początkujący, jeśli chodzi o zabawę z płytkami Nucleo, a można powiedzieć, że zostałem już rzucony na głęboką wodę. W tym semestrze na uczelni mam projekt z Układów Cyfrowych i Mikroprocesorów na takiej właśnie płytce. Razem z większością osób grupy zakupiliśmy płytkę F103RB, widziałem, że na stronie są kursy i poradniki krok po kroku związane z tą płytką, więc na pewno będzie to przydatne, jednak szukam pomysłu na coś bardziej rozbudowanego, niż zapalająca się dioda po naciśnięciu przycisku. Termometr (w jakiejkolwiek postaci) raczej odpada, bo moi znajomi już się na to rzucili. Myślałem o barometrze, wilgotnościomierzu lub nawet zegarze cyfrowym, tylko nie znam stopnia trudności tych rzeczy, ani też nie wiem za bardzo jak się za coś takiego zabrać, bo tak jak mówiłem, jestem zupełnie zielony. Prosiłbym o jakąś podpowiedź w sprawie pomysłów na powyższe projekty, albo nawet propozycje jakiś nowych przeze mnie nieopisanych. Z góry dziękuję za pomoc, będę bardzo wdzięczny!
  21. Witam serdecznie. Czy jest możliwość w Atolic TrueStudio utworzenia nowego projektu z całą biblioteką HAL bez użycia kreatora CubeMX? Wybierając File -> New -> C project, mam możliwość utworzenia projektu tylko z biblioteką StdLib, a chciałbym mieć pełen pakiet driverów HAL.
  22. Chce wykorzystać kod z artykułu wraz z przerwaniem TIM_IT_Update, problem w tym, że gdy mam zsetupowany kontroler przerwań NVIC, to program nie może wyjść z TIM2_IRQHandler() pomimo tego, że czyszcze flage przez IM_ClearITPendingBit(TIM2, TIM_IT_Update); Sam TIM2 działa bez zarzutu, i jestem w stanie migać diodą w pętli głównej programu, ale tylko gdy pominę setup NVIC w kodzie. Co może być powodem tego problemu? Kompilator? Program pisze pod STM32f103C8 na eclipsowym OpenSTM. /** ****************************************************************************** * @file main.c * @author Ac6 * @version V1.0 * @date 01-December-2013 * @brief Default main function. ****************************************************************************** */ #include "stm32f10x.h" void TIM2_IRQHandler() { if (TIM_GetITStatus(TIM2, TIM_IT_Update) == SET){ TIM_ClearITPendingBit(TIM2, TIM_IT_Update); if (GPIO_ReadOutputDataBit(GPIOC, GPIO_Pin_13)) GPIO_ResetBits(GPIOC, GPIO_Pin_13); else GPIO_SetBits(GPIOC, GPIO_Pin_13); } } int main(void){ GPIO_InitTypeDef gpio; TIM_TimeBaseInitTypeDef tim; NVIC_InitTypeDef nvic; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB | RCC_APB2Periph_GPIOC | RCC_APB2Periph_GPIOD, ENABLE); RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE); GPIO_StructInit(&gpio); gpio.GPIO_Pin = GPIO_Pin_13; gpio.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_Init(GPIOC, &gpio); TIM_TimeBaseStructInit(&tim); tim.TIM_CounterMode = TIM_CounterMode_Up; tim.TIM_Prescaler = 7200 - 1; tim.TIM_Period = 10000 - 1; TIM_TimeBaseInit(TIM2, &tim); TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE); TIM_Cmd(TIM2, ENABLE); // nvic.NVIC_IRQChannel = TIM2_IRQn; // nvic.NVIC_IRQChannelPreemptionPriority = 0; // nvic.NVIC_IRQChannelSubPriority = 0; // nvic.NVIC_IRQChannelCmd = ENABLE; // NVIC_Init(&nvic); while (1) { int timerValue = TIM_GetCounter(TIM2); if (timerValue > 1000) GPIO_WriteBit(GPIOC, GPIO_Pin_13, Bit_SET); else GPIO_WriteBit(GPIOC, GPIO_Pin_13, Bit_RESET); } }
  23. Witam. Mam problem, ponieważ napięcie na pinach ma tylko około 1V. Tak samo nie da się zaświecić diody wbudowanej LD2. Zmierzyłem napięcie i np. na pinach GPIOC napięcie ma około 1V. Dodam, że wcześniej było normalnie i mogłem z nich zasilić zwykłego LEDa. Czy coś się usmażyło?
  24. Cześć Chciałbym dowiedzieć się jak programować stm32 w LL. Jak do tego podejść?
  25. Od niedawna eksperymentuję z układami STM32 przy wykorzystaniu bibliotek HAL, narzędzia STM32CubeMX oraz środowiska AtollicSTUDIO. Nie znaczy to jednak, że nie mam doświadczenia z mikrokontrolerami - od kilku lat hobbystycznie programuję AVR-y i PIC32, zdarzało mi się także zajmować m.in. starszymi układami z rodziny 8051. Przejście na rodzinę STM32 wydawało mi się początkowo łatwe i bezbolesne, jednak teraz natknąłem się na dziwnego i mocno specyficznego buga, którego przyczyny nie jestem w stanie namierzyć. Przechodząc do meritum: Przeportowałem arduinową bibliotekę do obsługi modułów DCF77. Przepisałem ją w C, usunąłem nawiązania do bibliotek Arduino, zastępując je funkcjami standardowej biblioteki C, usunąłem też kilka błędów. Wygląda na to, że biblioteka działa - to znaczy przy dobrych warunkach propagacyjnych (szczególnie wieczorem) odbiera wiarygodnie wyglądające timestampy. Ponieważ bity parzystości używane przez DCF77 nie są dostatecznym zabezpieczeniem, biblioteka używa kilka sposobów sprawdzania poprawności odebranego czasu. Między innymi porównuje go z czasem systemowym. W oryginale była do tego używana jakaś biblioteka Arduino, ja użyłem time.h. Wiązało się to z koniecznością zdefiniowania własnej wersji funkcji time(), zwracającej czas systemowy z RTC w formie timestampa: time_t time (time_t * timer) { RTC_TimeTypeDef timeStruct; RTC_DateTypeDef dateStruct; struct tm dstTime; HAL_RTC_GetTime(&hrtc, &timeStruct, RTC_FORMAT_BIN); HAL_RTC_GetDate(&hrtc, &dateStruct, RTC_FORMAT_BIN); dstTime.tm_hour = timeStruct.Hours; dstTime.tm_min = timeStruct.Minutes; dstTime.tm_sec = timeStruct.Seconds; dstTime.tm_year = dateStruct.Year + 100; dstTime.tm_mon = dateStruct.Month - 1; dstTime.tm_mday = dateStruct.Date; return mktime(&dstTime); } W pętli głównej programu znajduje się następujący fragment, odpowiedzialny z synchronizację czasu i jego wyświetlanie na LCD: if ( (tmptime = DCF77_getUTCTime()) ) { printf("Time updated: %lu\r\n", tmptime); setRealTimeClock(tmptime); lastupdate = tmptime; } if (rtcTickFlag) { tmptime = time(NULL); tmupd = gmtime((const time_t*)&tmptime); snprintf(buffer, sizeof(buffer)-1, "%02d:%02d:%02d", tmupd->tm_hour, tmupd->tm_min, tmupd->tm_sec); PCD_GotoXYFont(1,1); PCD_Str(FONT_1X, (uint8_t*)buffer); snprintf(buffer, sizeof(buffer)-1, "%02d-%02d-%02d", tmupd->tm_mday, (tmupd->tm_mon)+1, (tmupd->tm_year)-100); PCD_GotoXYFont(1,2); PCD_Str(FONT_1X, (uint8_t*)buffer); if (lastupdate != 0) { tmupd = gmtime((const time_t*)&lastupdate); PCD_GotoXYFont(1,4); PCD_Str(FONT_1X, (uint8_t*)"Updated:"); snprintf(buffer, sizeof(buffer)-1, "%02d:%02d:%02d", tmupd->tm_hour, tmupd->tm_min, tmupd->tm_sec); PCD_GotoXYFont(1,5); PCD_Str(FONT_1X, (uint8_t*)buffer); snprintf(buffer, sizeof(buffer)-1, "%02d-%02d-%02d", tmupd->tm_mday, (tmupd->tm_mon)+1, (tmupd->tm_year)-100); PCD_GotoXYFont(1,6); PCD_Str(FONT_1X, (uint8_t*)buffer); } PCD_Upd(); rtcTickFlag = 0; } Funkcja setRealTimeClock() wygląda następująco: void setRealTimeClock (time_t tm) { RTC_TimeTypeDef timeStruct; RTC_DateTypeDef dateStruct; struct tm *dstTime; dstTime = gmtime(&tm); timeStruct.Hours = dstTime->tm_hour; timeStruct.Minutes = dstTime->tm_min; timeStruct.Seconds = dstTime->tm_sec; dateStruct.Year = (dstTime->tm_year)-100; dateStruct.Month = (dstTime->tm_mon)+1; dateStruct.Date = dstTime->tm_mday; HAL_RTC_SetTime(&hrtc, &timeStruct, RTC_FORMAT_BIN); HAL_RTC_SetDate(&hrtc, &dateStruct, RTC_FORMAT_BIN); } Na początku wszystko zdaje się działać prawidłowo. Układ startuje, RTC odlicza czas. Gdy pojawiają się odpowiednie warunki, moduł DCF77 zaczyna odbierać ramki i ustawia zegar. Na wyświetlaczu pojawia się właściwy czas UTC, jak również informacja o momencie ostatniej synchronizacji. Przez jakiś czas wszystko gra. Jednak w pewnym momencie dzieje się coś dziwnego. Aktualnie wyświetlany czas rozjeżdża się o jakieś osiem godzin do przodu. Na przykład wczoraj o 20.00 UTC pokazywał godziną 4.00 UTC dnia następnego. Żeby było jeszcze dziwniej informacja o ostatnio odebranej ramce wciąż pokazuje właściwy czas. Nie wiem na którym etapie pojawia się przekłamanie. Do konwersji czasu na formę tekstową używam przecież tych samych funkcji, Gdyby problem związany był z RTC albo moja funkcją time(), to przecież kolejne synchronizacje nie byłyby możliwe - biblioteka DCF77 wychwytywałaby sporą różnicę pomiędzy czasem systemowym i odebranym. W takim wypadku po odebraniu dwóch kolejnych prawidłowych ramek uznałaby, że czas systemowy jets zły i tak czy inaczej ustawiła RTC. Tymczasem na wyświetlaczu pojawiają się informacje o kolejnej udanej synchronizacji, a aktualny czas i tak jest wyświetlany błędnie... Ktoś ma pojęcie o co może chodzić? W załączniku przesyłam kompletny projekt, w razie gdyby przytoczone powyżej fragmenty kodu źródłowego okazały się niewystarczające. DCF77_LCD.zip
×
×
  • Utwórz nowe...