Skocz do zawartości

DeadGeneratio

Użytkownicy
  • Zawartość

    92
  • Rejestracja

  • Ostatnio

  • Wygrane dni

    3

DeadGeneratio zajął 1. miejsce w rankingu.
Data osiągnięcia: 21 lutego 2024.

Treści użytkownika DeadGeneratio zdobyły tego dnia najwięcej polubień!

Ostatnio na profilu byli

Blok z ostatnio odwiedzającymi jest wyłączony i nie jest wyświetlany innym użytkownikom.

Osiągnięcia użytkownika DeadGeneratio

Entuzjasta

Entuzjasta (7/19)

  • To już rok!
  • Wschodząca gwiazda
  • Odkrywca (podanie odp. na własne pytanie)
  • Za 25 postów
  • Pilny student

Odznaki

27

Reputacja

  1. Witam szanowne grono, ostatnio w pracy natrafiłem na nieciekawy problem nie zgadzajacych się poziomów napięć - niektóre czujniki działały na 5V (dwa czujniki Halla w siłowniku liniowym, zasilanym na 24V), niektóre na 12V jak stacja pogodowa RG9, a niektóre poprawnie na 24V, tak jak sterownik PLC tego oczekuje. Problematyczne były nie tylko poziomy napięć, a także maksymalne dopuszczone obciążenie prądowe wyjścia czujników, a także różne budowy wyjść - od zwykłego tranzystora NPN, po wyjścia z otwartym kolektorem. Co za tym idzie, nie wszędzie dopuszczone będzie stosowanie przekaźnika w formie przekształtnika poziomu sygnału, gdzie czujnik będzie sterował cewką przekaźnika, a sygnał logicznie już dostosowany do zakresu napięć sterownika, będzie poprowadzony stykami NO bądź NC. Dodatkowym problemem także byłoby wykorzystanie takiego przekaźnika przy czujnikach Halla w siłowniku - jak się okazało, nie są to czujniki krańcowe informujące o dotarciu tłoczyska na początek bądź koniec zakresu ruchu, a działały na zasadzie enkodera A/B, generując sygnał przy obrocie śruby, z wypełnieniem 180 stopni i przesunięciem między sobą 90 stopni. Rozwiązaniem tego problemu okazały się układy scalone ULN200X, które przedstawię poniżej: ULN2002A, Input Voltage: 14-25V, PMOS ULN2003A, Input Voltage: 5V TTL, CMOS ULN2004A, Input Voltage: 6-15V, CMOS, PMOS Trzy powyższe układy scalone w opakowaniu DIP16, umożliwiają pełna konwersję napięcia z zakresu 5-25V to maksymalnie 50V, tak wynika z noty katalogowej, w moim przypadku były to 24V. Mają ciekawy sposób sterowania - mianowicie układy te nie potrzebują doprowadzenia napiecia zasilającego, ponieważ zwierają tranzystory do masy, zadaniem użytkowniak jest doprowadzenie zasilania przez rezystory podciągające, co umożliwia na uzyskanie rozmaitych napięć wyjściowych, należy pamiętać przy wykorzystaniu tych układów, że odwracają one logikę - podanie sygnału na wejściu powoduje zwarcie tranzystora do masy, powodując uzyskanie stanu logicznego równego 0 na wyjściu. Wiem, że układy te są zaprojektowanie głównei do sterowania elektroniką, o zdecydowanie większych poborach prądu - Continous Collector Current = 500mA, a także posiadają Vce stosunkowo wysokie bo około 1.1V, jednak jako tani układ scalony, który można nabyć za około złotówkę, stają się idealnym wręcz konwerterem poziomów logicznych, gdzie jedynym problemem może być spadek napięcia Vce, nie pozwala to na wykorzystanie takiego układu w roli konwertera do mikrokontrolerów pracujących przy bardzo niskich poziomach napięć, praktycznie wszystko poniżej TTL 5V, czyli CMOS 5V, TTL 3.3V itd. W roli konwertera sygnału dla sterownika PLC, gdzie zakres napięcia wejściowego jest stosunkowo szeroki, spisuje się na medal. Poniżej przedstawiam schemat elektryczny dla dowolnego z wcześniej rozpisanych układów, z drabinkami rezystorów, umożliwiających utworzenie połączenia pull-up oraz pull-down dla wejść, czyli czujników, a także drabinka rezystorów do utworzenia połączenia pull-up na wyjściu, które jest niezbędne do funkcjonowania konwertera. Oraz schemat płytki PCB, którą puściłem do druku, i wykorzystałem w projekcie. Wygląd płytki w modelu 3D: Dodatkowo jako załącznik projekt z KiCada w wersji 9.0. Jestem ciekawy waszych opinii LevelConverter.zip
  2. Ja zacząłbym od zrobienia podstawowych pomiarów bez podłączania zasilania. Czy między fazą a neutralnym od mostka gretza jest zwarcie. Nie powinno być. Czy linia + i - po mostku gretza także ma zwarcie, to przy okazji jak już pomiary są także robione. Aby się upewnić, można ustawić multimetr na test diody i sprawdzić każdą z diód
  3. Upewniłem się co do rozmiarów MP1584EN, okazuje się, że sąsiadujące piny są w rozstawie 2.54mm, ale rozmieszczenie ich na płytce już nie jest wielokrotnością 2.54. Poprawiłem wymiary i zlecam płytkę do wydruku. Dziękuję jeszcze raz wszystkim
  4. Pierwszy raz generuję plik gerber, utworzyło mi się dużo osobnych warstw. Płytka będzie typowo do jednego silnika krokowego, o prądzie 1A, z możliwością programowej zmiany kierunku obrotów, stąd decyzja o pozostaniu przy złączu XH (silnik krokowy swoją drogą, który zamówiłem ma takie złącze). Zworki usunąłem, faktycznie nie doczytałem, że są rezystory podciągające. Ścieżki pogrubione, nawet jeśli nie będę miał 4A, nie zaszkodzi mieć grubsze. A odnośnie złącza zasilania i gniazda ARK 5.08, napięcie zasilające to będzie 20V z zasilacza z power delivery, Zwykłe takie złącze nie wystarczy do zasilenia płytki? Dziękuję wam wszystkim za pomysłi i rady jak i uwagi DRV8255-.zip
  5. Nie sprawdziłem nawet czy KiCAD ma jakiś pomiar odległości. Dopasowanie zdęcia do realnej wielkości brzmi najlepiej z tych opcji, jak będę miał czas upewnię się, że wszystko jest dobrze zmierzone.
  6. Cześć wszystkim, to moja pierwsza przygoda z projektowaniem płytki PCB. Czy możecie rzucić okiem, czy model wygląda w miarę poprawnie? DRC krzyczy tylko o nakładających się liniach na soldermasce z oznaczeniami komponentów, czego nie będzie na płytce, i jednej uciętej linii w miejscu gdzie jest otwór montażowy. Linki do poszczególnych elementów: Przetwornica step-down: https://pl.aliexpress.com/item/1005005870392716.html?spm=a2g0o.order_list.order_list_main.17.1c531c24zOwn9d&gatewayAdapt=glo2pol Sterowniki do silnika: https://pl.aliexpress.com/item/1005006199405206.html?spm=a2g0o.order_list.order_list_main.56.1c531c24sBLCat&gatewayAdapt=glo2pol Najważniejsze pytanie - jak w miarę szybko i dokładnie policzyć odległości między pinami? Mierzyłem to w paincie kopiując piny i dokładając obok aż uzyskałem liczbę odsunięcia, ale kiedyś może taka metoda się zemścić. Skośnoocy koledzy nie udostępniają bardzo często dokładnych rysunków, a dopóki nie ma sie takiego modułu na stanie, własnoręczne zmierzenie jest niemożliwe.
  7. To już zależy od tego w jaki sposób mikrokontrolery mają działać. Możesz to zrobić metodą poolingu, przerwania bądź DMA, tak samo na obu jak i różnymi metodami na obu. To co chcesz zastosować zależy tylko i wyłącznie od tego co oczekujesz - jeśli zależy Ci na jak najmniejszym obciążeniu procesora, to idziesz w kierunku DMA. Jak chcesz mieć program prosty jak budowę cepa, który nie będzie wykonywał zaawansowanych algorytmów, to wystarczy pooling. Tutaj masz link do kursu z rodziny L4: https://forbot.pl/blog/kurs-stm32l4-komunikacja-przez-uart-debugger-stm32-uart-id46577
  8. Myślę, że najprostszym sposobem będzie wykorzystanie UARTu
  9. Trochę obowiązków się nazbierało, dopiero wczoraj usiadłem do elektroniki. Części z Chin przyszły, w tym nowy PCM1808 - zielona płytka to nowy, fioletowa to stary. Poprawa jakości sygnału natychmiastowa, do tego wyprowadzone złącze Jack przy nieco wyższej cenie. Zdecydowanie polecam na ten moment, jeżeli ktoś będzie budował system DSP, komplet PCM1808 oraz PCM5102, które kosztują w zależności od sprzedawcy około 30 zł łącznie, w porównaniu z wcześniej używanym PMOD I2S2 za jakieś 150/200 zł. Obecnie projekt rusza dalej, zaimplementowałem już fft, teraz czas na sterowanie diodami ws. Potem zrobienie customowej płytki PCB, zakup drewna i zrobienie stosownej obudowy.
  10. Dzień dobry, mam pytanie odnośnie modułu PN532. Podłączyłem go po SPI do stm32 w trybie full duplex i badam jego dziwne zachowanie analizatorem logicznym. Wysyłając proste ramki otrzymuję kompletny brak odpowiedzi na linii MISO, a linia MOSI czasami zawiera takie dziwne rzeczy, że nie wiem co o tym myśleć. Tutaj ramka wake-up: Nie spodziewam się odpowiedzi więc nie ustawiam stm na tryb odbierania. Chwilę po tym ustawiam moduł na szukanie kart w pobliżu: Także nie spodziewam się odpowiedzi. I przechodzę do sprawdzenia wersji firmware: Tutaj zaczyna dziać się magia. Wysyłam D4 02, a następnie ustawiam na odczyt. I zamiast odczytać cokolwiek, na linii MOSI pojawiają się powtórzone komendy w odwrotnej kolejności, pomieszane - D4 14 01 itd. Na lini MISO odpowiedzi na temat firmware nie otrzymałem, a dalej robi się jeszcze ciekawiej. D4 4A 01 00 wyszukuje karty w okolicy, więc naturalnym jest, że po nadaniu komendy, przestawiam się na tryb nasłuchu. I dostaję po chwili kompletny szum danych na lini MOSI, a linia MISO pozostaje głucha. Każde kolejne sprawdzenie wygląda już lepiej, bo komendy się nie powtarzają jak w powyższym przypadku: Jednak odpowiedzi nie dostaję takiej jaką bym chciał, bo powinno zwrócić ramkę o ilości urządzeń znalezionych czyli 0 itd. Ktoś wie dlaczego pojawia się taki syf na liniach transmisyjnych? Plik main.c: /* USER CODE BEGIN Header */ /** ****************************************************************************** * @file : main.c * @brief : Main program body ****************************************************************************** * @attention * * Copyright (c) 2024 STMicroelectronics. * All rights reserved. * * This software is licensed under terms that can be found in the LICENSE file * in the root directory of this software component. * If no LICENSE file comes with this software, it is provided AS-IS. * ****************************************************************************** */ /* USER CODE END Header */ /* Includes ------------------------------------------------------------------*/ #include "main.h" /* Private includes ----------------------------------------------------------*/ /* USER CODE BEGIN Includes */ #include "PN532.h" #include "string.h" /* 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 ---------------------------------------------------------*/ SPI_HandleTypeDef hspi1; /* USER CODE BEGIN PV */ uint8_t firmware[4]; // Tablica na dane o firmware uint8_t cardUID[7]; // Bufor na UID karty volatile uint8_t responseReady = 0; // Flaga wskazująca na gotowość odpowiedzi uint8_t response[20]; // Bufor odpowiedzi z PN532 /* 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 */ /* USER CODE END PFP */ /* Private user code ---------------------------------------------------------*/ /* USER CODE BEGIN 0 */ // Funkcja do skanowania w poszukiwaniu kart NFC // Funkcja do listowania pasywnych tagów NFC (karty) i odczytu UID void PN532_InListPassiveTarget() { uint8_t command[] = { 0xD4, 0x4A, 0x01, 0x00 }; // Komenda InListPassiveTarget uint8_t response[20]; // Bufor na odpowiedź // Wysyłanie komendy PN532_SendCommand_IT(command, sizeof(command)); while (!txComplete); // Oczekiwanie na zakończenie transmisji // Odbieranie odpowiedzi PN532_ReadData_IT(response, sizeof(response)); while (!rxComplete); // Oczekiwanie na zakończenie odbioru // Przetwarzanie odpowiedzi if (response[0] == 0xD5 && response[1] == 0x4B) { // Poprawna odpowiedź, tag (karta) został wykryty uint8_t numTags = response[7]; // Liczba wykrytych tagów if (numTags > 0) { uint8_t uidLength = response[12]; // Długość UID karty uint8_t uid[uidLength]; memcpy(uid, &response[13], uidLength); // Skopiowanie UID do bufora } } } /* 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_SPI1_Init(); /* USER CODE BEGIN 2 */ HAL_Delay(100); PN532_Wakeup(); PN532_GetFirmwareVersion(firmware); /* USER CODE END 2 */ /* Infinite loop */ /* USER CODE BEGIN WHILE */ while (1) { /* USER CODE END WHILE */ /* USER CODE BEGIN 3 */ PN532_InListPassiveTarget(); HAL_Delay(100); } /* 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_PWREx_ControlVoltageScaling(PWR_REGULATOR_VOLTAGE_SCALE1); /** Initializes the RCC Oscillators according to the specified parameters * in the RCC_OscInitTypeDef structure. */ 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 buses 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 SPI1 Initialization Function * @param None * @retval None */ static void MX_SPI1_Init(void) { /* USER CODE BEGIN SPI1_Init 0 */ /* USER CODE END SPI1_Init 0 */ /* USER CODE BEGIN SPI1_Init 1 */ /* USER CODE END SPI1_Init 1 */ /* 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_32; hspi1.Init.FirstBit = SPI_FIRSTBIT_MSB; hspi1.Init.TIMode = SPI_TIMODE_DISABLE; hspi1.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE; hspi1.Init.CRCPolynomial = 7; hspi1.Init.CRCLength = SPI_CRC_LENGTH_DATASIZE; hspi1.Init.NSSPMode = SPI_NSS_PULSE_ENABLE; if (HAL_SPI_Init(&hspi1) != HAL_OK) { Error_Handler(); } /* USER CODE BEGIN SPI1_Init 2 */ /* USER CODE END SPI1_Init 2 */ } /** * @brief GPIO Initialization Function * @param None * @retval None */ static void MX_GPIO_Init(void) { GPIO_InitTypeDef GPIO_InitStruct = {0}; /* USER CODE BEGIN MX_GPIO_Init_1 */ /* USER CODE END MX_GPIO_Init_1 */ /* GPIO Ports Clock Enable */ __HAL_RCC_GPIOF_CLK_ENABLE(); __HAL_RCC_GPIOA_CLK_ENABLE(); /*Configure GPIO pin Output Level */ HAL_GPIO_WritePin(SS_GPIO_Port, SS_Pin, GPIO_PIN_SET); /*Configure GPIO pin : SS_Pin */ GPIO_InitStruct.Pin = SS_Pin; GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; HAL_GPIO_Init(SS_GPIO_Port, &GPIO_InitStruct); /* USER CODE BEGIN MX_GPIO_Init_2 */ /* USER CODE END MX_GPIO_Init_2 */ } /* USER CODE BEGIN 4 */ // Callback wywoływany po zakończeniu transmisji void HAL_SPI_TxCpltCallback(SPI_HandleTypeDef *hspi) { if (hspi->Instance == hspi1.Instance) { txComplete = 1; // Ustawiamy flagę zakończenia transmisji PN532_Unselect(); // Kończymy transmisję (CS na high) } } // Callback wywoływany po zakończeniu odbioru danych void HAL_SPI_RxCpltCallback(SPI_HandleTypeDef *hspi) { if (hspi->Instance == hspi1.Instance) { rxComplete = 1; // Ustawiamy flagę zakończenia odbioru PN532_Unselect(); // Kończymy odbiór (CS na high) } } /* 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 */ __disable_irq(); 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 /* USE_FULL_ASSERT */ Mój utworzony plik PN532.h: #include "stm32g4xx_hal.h" extern SPI_HandleTypeDef hspi1; #define PN532_SPI_CS_PIN GPIO_PIN_4 #define PN532_SPI_CS_PORT GPIOA #define PN532_SPI_READY_TIMEOUT 100 #define PN532_CMD_GETFIRMWAREVERSION 0x02 #define PN532_CMD_SAMCONFIGURATION 0x14 volatile uint8_t txComplete = 0; volatile uint8_t rxComplete = 0; uint8_t spiResponseBuffer[20]; void PN532_Select() { HAL_GPIO_WritePin(PN532_SPI_CS_PORT, PN532_SPI_CS_PIN, GPIO_PIN_RESET); } void PN532_Unselect() { HAL_GPIO_WritePin(PN532_SPI_CS_PORT, PN532_SPI_CS_PIN, GPIO_PIN_SET); } void PN532_SendCommand_IT(uint8_t *cmd, uint8_t cmdlen) { PN532_Select(); txComplete = 0; HAL_SPI_Transmit_IT(&hspi1, cmd, cmdlen); } void PN532_ReadData_IT(uint8_t *buffer, uint8_t length) { PN532_Select(); rxComplete = 0; HAL_SPI_Receive_IT(&hspi1, buffer, length); } void PN532_Wakeup(void) { uint8_t wakeupCommand[] = { 0x55, 0x55, 0x00, 0x00, 0x00 }; PN532_SendCommand_IT(wakeupCommand, sizeof(wakeupCommand)); while (!txComplete) ; HAL_Delay(10); uint8_t samConfigCommand[] = { 0xD4, 0x14, 0x01, 0x14, 0x01 }; PN532_SendCommand_IT(samConfigCommand, sizeof(samConfigCommand)); while (!txComplete) ; HAL_Delay(100); } void PN532_GetFirmwareVersion() { uint8_t command[] = { 0xD4, 0x02 }; uint8_t response[12]; PN532_SendCommand_IT(command, sizeof(command)); while (!txComplete) ; PN532_ReadData_IT(response, sizeof(response)); while (!rxComplete) ; }
  11. Zrobiłem bypass na hardwarze, podłączyłem bezpośrednio wyjście ADC na wejście DAC przy zachowaniu tych samych sygnałów zegarowych itd. De facto na jednym half duplexie zrobiłem upośledzoną wersję full duplexu, jeśli można to tak to nazwać. Przy wykorzystaniu CS5343 jako adc nie miałem żadnych zniekształceń dźwięku. Korzystając z PCM1808 muzyka znowu brzmi jak by przeszła przez filtr dolno przepustowy. Nie widzę nic w DS tego układu dlaczego może tak się dziać. Dopóki nie ogarnę sprzętu, nie ma sensu nawet rozpoczynać pisania programu
  12. Trochę siedziałem nad RM od tego stma - w przypadku ramki 32 bitowej, są odbierane dwie próbki po 16 bitów. Więc odbierając to w taki sposób, rx_buf[0] oraz [1] powinni być traktowane jako jedna zmienna, oczywiście w programie do scalenia. Do wysyłki należy rozdzielić to na dwie części tak Jan było odebrane. Ale spróbuję najpierw zmniejszyć rozdzielczość do 16 bitów jak wrócę do domu i zobaczę wtedy jak dane będą wyglądać
  13. Dzień dobry, uporałem się z ostatnim problemem dotyczącym wolnego analizatora. Obecnie siedzę nad problemem, dlaczego dźwięk po przejściu z PCM1808 na PCM5102 zachowuje się jak by przeszedł przez filtr dolnoprzepustowy. Odkryłem analizatorem logicznym, że czasami próbki się zgadzają, a czasami nie. Czy ktoś spotkał się kiedyś z takim problemem? /* USER CODE BEGIN Header */ * Copyright (c) 2024 STMicroelectronics. * All rights reserved. * * This software is licensed under terms that can be found in the LICENSE file * in the root directory of this software component. * If no LICENSE file comes with this software, it is provided AS-IS. * ****************************************************************************** */ /* 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 ---------------------------------------------------------*/ I2S_HandleTypeDef hi2s2; I2S_HandleTypeDef hi2s3; DMA_HandleTypeDef hdma_spi2_rx; DMA_HandleTypeDef hdma_spi3_tx; TIM_HandleTypeDef htim2; /* USER CODE BEGIN PV */ uint16_t tx_buf[8]; uint16_t rx_buf[8]; /* USER CODE END PV */ /* Private function prototypes -----------------------------------------------*/ void SystemClock_Config(void); void PeriphCommonClock_Config(void); static void MX_GPIO_Init(void); static void MX_DMA_Init(void); static void MX_I2S2_Init(void); static void MX_TIM2_Init(void); static void MX_I2S3_Init(void); /* USER CODE BEGIN PFP */ /* USER CODE END PFP */ /* Private user code ---------------------------------------------------------*/ /* USER CODE BEGIN 0 */ void PCM1808_Init(void) { HAL_GPIO_WritePin(GPIOB, GPIO_PIN_14, GPIO_PIN_RESET); HAL_GPIO_WritePin(GPIOD, GPIO_PIN_8, GPIO_PIN_RESET); HAL_GPIO_WritePin(GPIOD, GPIO_PIN_9, GPIO_PIN_RESET); } /* 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(); /* Configure the peripherals common clocks */ PeriphCommonClock_Config(); /* USER CODE BEGIN SysInit */ /* USER CODE END SysInit */ /* Initialize all configured peripherals */ MX_GPIO_Init(); MX_DMA_Init(); MX_I2S2_Init(); MX_TIM2_Init(); MX_I2S3_Init(); /* USER CODE BEGIN 2 */ PCM1808_Init(); HAL_TIM_Base_Start_IT(&htim2); HAL_I2S_Receive_DMA(&hi2s2, rx_buf, 4); HAL_I2S_Transmit_DMA(&hi2s3, tx_buf, 4); /* USER CODE END 2 */ /* Infinite loop */ /* USER CODE BEGIN WHILE */ while (1) { /* USER CODE END WHILE */ /* USER CODE BEGIN 3 */ } /* USER CODE END 3 */ } 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_SCALE1); /** Initializes the RCC Oscillators according to the specified parameters * in the RCC_OscInitTypeDef structure. */ RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE; RCC_OscInitStruct.HSEState = RCC_HSE_ON; RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON; RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE; RCC_OscInitStruct.PLL.PLLM = 4; RCC_OscInitStruct.PLL.PLLN = 168; 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 buses 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_5) != HAL_OK) { Error_Handler(); } } void PeriphCommonClock_Config(void) { RCC_PeriphCLKInitTypeDef PeriphClkInitStruct = { 0 }; /** Initializes the peripherals clock */ PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_I2S; PeriphClkInitStruct.PLLI2S.PLLI2SN = 123; PeriphClkInitStruct.PLLI2S.PLLI2SR = 2; if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct) != HAL_OK) { Error_Handler(); } } static void MX_I2S2_Init(void) { /* USER CODE BEGIN I2S2_Init 0 */ /* USER CODE END I2S2_Init 0 */ /* USER CODE BEGIN I2S2_Init 1 */ /* USER CODE END I2S2_Init 1 */ hi2s2.Instance = SPI2; hi2s2.Init.Mode = I2S_MODE_MASTER_RX; hi2s2.Init.Standard = I2S_STANDARD_PHILIPS; hi2s2.Init.DataFormat = I2S_DATAFORMAT_24B; hi2s2.Init.MCLKOutput = I2S_MCLKOUTPUT_ENABLE; hi2s2.Init.AudioFreq = I2S_AUDIOFREQ_44K; hi2s2.Init.CPOL = I2S_CPOL_LOW; hi2s2.Init.ClockSource = I2S_CLOCK_PLL; hi2s2.Init.FullDuplexMode = I2S_FULLDUPLEXMODE_DISABLE; if (HAL_I2S_Init(&hi2s2) != HAL_OK) { Error_Handler(); } /* USER CODE BEGIN I2S2_Init 2 */ /* USER CODE END I2S2_Init 2 */ } static void MX_I2S3_Init(void) { /* USER CODE BEGIN I2S3_Init 0 */ /* USER CODE END I2S3_Init 0 */ /* USER CODE BEGIN I2S3_Init 1 */ /* USER CODE END I2S3_Init 1 */ hi2s3.Instance = SPI3; hi2s3.Init.Mode = I2S_MODE_MASTER_TX; hi2s3.Init.Standard = I2S_STANDARD_PHILIPS; hi2s3.Init.DataFormat = I2S_DATAFORMAT_24B; hi2s3.Init.MCLKOutput = I2S_MCLKOUTPUT_ENABLE; hi2s3.Init.AudioFreq = I2S_AUDIOFREQ_44K; hi2s3.Init.CPOL = I2S_CPOL_LOW; hi2s3.Init.ClockSource = I2S_CLOCK_PLL; hi2s3.Init.FullDuplexMode = I2S_FULLDUPLEXMODE_DISABLE; if (HAL_I2S_Init(&hi2s3) != HAL_OK) { Error_Handler(); } /* USER CODE BEGIN I2S3_Init 2 */ /* USER CODE END I2S3_Init 2 */ } static void MX_TIM2_Init(void) { /* USER CODE BEGIN TIM2_Init 0 */ /* USER CODE END TIM2_Init 0 */ TIM_ClockConfigTypeDef sClockSourceConfig = { 0 }; TIM_MasterConfigTypeDef sMasterConfig = { 0 }; /* USER CODE BEGIN TIM2_Init 1 */ /* USER CODE END TIM2_Init 1 */ htim2.Instance = TIM2; htim2.Init.Prescaler = 0; htim2.Init.CounterMode = TIM_COUNTERMODE_UP; htim2.Init.Period = 4294967295; htim2.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1; htim2.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_ENABLE; if (HAL_TIM_Base_Init(&htim2) != HAL_OK) { Error_Handler(); } sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL; if (HAL_TIM_ConfigClockSource(&htim2, &sClockSourceConfig) != HAL_OK) { Error_Handler(); } sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET; sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE; if (HAL_TIMEx_MasterConfigSynchronization(&htim2, &sMasterConfig) != HAL_OK) { Error_Handler(); } /* USER CODE BEGIN TIM2_Init 2 */ /* USER CODE END TIM2_Init 2 */ } /** * Enable DMA controller clock */ static void MX_DMA_Init(void) { /* DMA controller clock enable */ __HAL_RCC_DMA1_CLK_ENABLE(); /* DMA interrupt init */ /* DMA1_Stream3_IRQn interrupt configuration */ HAL_NVIC_SetPriority(DMA1_Stream3_IRQn, 0, 0); HAL_NVIC_EnableIRQ(DMA1_Stream3_IRQn); /* DMA1_Stream5_IRQn interrupt configuration */ HAL_NVIC_SetPriority(DMA1_Stream5_IRQn, 0, 0); HAL_NVIC_EnableIRQ(DMA1_Stream5_IRQn); } static void MX_GPIO_Init(void) { GPIO_InitTypeDef GPIO_InitStruct = { 0 }; /* USER CODE BEGIN MX_GPIO_Init_1 */ /* USER CODE END MX_GPIO_Init_1 */ /* GPIO Ports Clock Enable */ __HAL_RCC_GPIOC_CLK_ENABLE(); __HAL_RCC_GPIOH_CLK_ENABLE(); __HAL_RCC_GPIOA_CLK_ENABLE(); __HAL_RCC_GPIOB_CLK_ENABLE(); __HAL_RCC_GPIOD_CLK_ENABLE(); /*Configure GPIO pin Output Level */ HAL_GPIO_WritePin(FMY_GPIO_Port, FMY_Pin, GPIO_PIN_RESET); /*Configure GPIO pin Output Level */ HAL_GPIO_WritePin(GPIOD, MD1_Pin | MD0_Pin, GPIO_PIN_RESET); /*Configure GPIO pin : FMY_Pin */ GPIO_InitStruct.Pin = FMY_Pin; GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; HAL_GPIO_Init(FMY_GPIO_Port, &GPIO_InitStruct); /*Configure GPIO pins : MD1_Pin MD0_Pin */ GPIO_InitStruct.Pin = MD1_Pin | MD0_Pin; GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; HAL_GPIO_Init(GPIOD, &GPIO_InitStruct); /* USER CODE BEGIN MX_GPIO_Init_2 */ /* USER CODE END MX_GPIO_Init_2 */ } /* USER CODE BEGIN 4 */ void HAL_I2S_RxHalfCpltCallback(I2S_HandleTypeDef *hi2s) { /* int l_in = (((int) rx_buf[0] << 16) | rx_buf[1]) >> 8; int r_in = (((int) rx_buf[2] << 16) | rx_buf[3]) >> 8; int l_out = l_in; int r_out = r_in; tx_buf[0] = (l_out >> 8) & 0xFFFF; tx_buf[1] = l_out & 0xFFFF; tx_buf[2] = (r_out >> 8) & 0xFFFF; tx_buf[3] = r_out & 0xFFFF; */ for (int i = 0; i < 4; i++) { tx_buf[i] = rx_buf[i]; } } void HAL_I2S_RxCpltCallback(I2S_HandleTypeDef *hi2s) { /* int l_in = (((int) rx_buf[4] << 16) | rx_buf[5]) >> 8; int r_in = (((int) rx_buf[6] << 16) | rx_buf[7]) >> 8; int l_out = l_in; int r_out = r_in; tx_buf[4] = (l_out >> 8) & 0xFFFF; tx_buf[5] = l_out & 0xFFFF; tx_buf[6] = (r_out >> 8) & 0xFFFF; tx_buf[7] = r_out & 0xFFFF; */ for (int i = 4; i < 8; i++) { tx_buf[i] = rx_buf[i]; } } /* USER CODE END 4 */ void Error_Handler(void) { /* USER CODE BEGIN Error_Handler_Debug */ /* User can add his own implementation to report the HAL error return state */ __disable_irq(); while (1) { } /* USER CODE END Error_Handler_Debug */ } #ifdef USE_FULL_ASSERT 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 /* USE_FULL_ASSERT */
  14. Cześć, posiadam analizator logiczny zdolny rozpędzić się do 48 MHz. Jednak przy pracy z interfejsem I2S jest to zbyt mało. Czy ktoś wie jak można rozwiązać ten problem? Chcę dobrze przejrzeć oscylogramy aby dowiedzieć się, czy czasami PCM1808 nie traci synchronizacji przez co nie wysyła danych, a do tego potrzebuje dokładnego analizatora. Czy po za kupnem jakiegoś działającego do 200/300/500MHz, można coś innego wymyśleć? Zdjęcie poniżej poglądowe: MCK czasami skacze, PLLI2S jest nie do zaobserwowania, SCK także czasami ma swoje problemy. Swoją drogą, mam obecnie GPIO ustawione jako medium speed. Czy jest to odpowiednia prędkość dla tych pinów? Pacjent to STM32F407VET6
  15. Problem rozwiązany, chińscy przyjaciele wykorzystali to, że BMP280 oraz BME280 mają ten sam rozkład rejestrów umożliwiający kompatybilność. Tylko dlatego działa mi odczyt temperatury oraz ciśnienia, wilgoci natomiast nie uzyskam nigdy ponieważ otrzymałem BMP280.
×
×
  • Utwórz nowe...