Spisu treści:
Wideo: Oscyloskop czterobitowy: 6 kroków
2024 Autor: John Day | [email protected]. Ostatnio zmodyfikowany: 2024-01-30 11:31
Jest to projekt dla zabawy, aby zobaczyć, jak daleko mogę popchnąć wyświetlacz z matrycą punktową MAX7219. I zamiast uruchomić „grę w życie”, postanowiłem zrobić z nią „zakres”. Jak zrozumiesz z tytułu, nie jest to zamiennik prawdziwego oscyloskopu:-).
Ponieważ nie planuję używać tego w żaden poważny sposób, nie zrobię do tego płytki drukowanej. Może, może po prostu umieszczę go na desce perforowanej, ale na razie jest i zostanie na desce do krojenia chleba. Ponadto nie ma wzmacniacza/tłumika wejściowego, musisz dostarczyć sygnał między 0 a 3,3 V, nie należy przekraczać wartości ujemnej lub powyżej 3,3 V, ponieważ możesz uszkodzić mikrokontroler.
Krok 1: Sprzęt
To jest tanie, bardzo tanie, gdy kupujesz części w Chinach za pośrednictwem ebay lub podobnych witryn. Wykorzystuje płytkę rozwojową STM32F103C8, czasami nazywaną „niebieską pigułką”, którą kupiłem za około 2 euro (lub USD, są prawie tej samej wartości, koniec 2018 r.), dwa wyświetlacze z matrycą punktową 8x8x4 z układami MAX7219, kupione za 5 euro za sztukę i enkoder obrotowy około 1 euro.
Potrzebny jest oczywiście zasilacz dostarczający 3,3 V przy kilkuset miliamperach. Regulator napięcia na płytce rozwojowej STM32F103C8 nie jest używany, nie może zapewnić wystarczającego prądu dla wyświetlaczy. Arkusz danych dla MAX7219 określa, że napięcie zasilania powinno wynosić od 4,0 do 5,5 V, ale działa dobrze przy 3,3 V, być może nie, gdy używasz go w bardzo gorącym lub zimnym środowisku, ale przy 20 stopniach Celsjusza jest w porządku. A teraz nie muszę używać konwerterów poziomów między mikrokontrolerem a wyświetlaczami.
Krok 2: Zbuduj
Kiedy spojrzysz na zdjęcie, zobaczysz, że używam linii zasilających na płytkach stykowych w niekonwencjonalny sposób, obie linie na górze to szyna dodatnia, a obie na dole to szyna uziemiająca. Jest to sposób, w jaki jestem przyzwyczajony do tego i działa dobrze, dzięki czemu konfiguracja wygląda trochę bardziej jak schematy, które rysuję. Zrobiłem też wiele małych płytek z częściami, które mogę podłączyć do płytki prototypowej, aby przyspieszyć działanie i wszystkie są skonfigurowane tak, aby używać dwóch górnych linii jako dodatnich, a dolnych jako uziemienia. Jak wspomniałem, rozdzielczość wynosi 4 bity (16 poziomów), a ponieważ są diody 4x8 obok siebie, to tylko 32 punkty próbkowania (pts). Porównaj to z Rigol Rigol DS1054Z (8 bitów i 12Mpts), a zobaczysz, że nie jest to zabawka. Jaka jest rzeczywista przepustowość, nie wiem, przetestowałem ją do 10kHz i działa dobrze.
Krok 3: Programy
IDE, którego używam, to Atollic TrueStudio, które na początku tego roku (2018) zostało przyjęte przez ST Micro Electronics i jest dostępne za darmo, bez limitu czasu, bez limitu rozmiaru kodu, bez ekranów nag. Razem z nim korzystam z programu STM32CubeMX, który dostarcza mi kod startowy i generuje inicjalizację wszystkich peryferiów. I ma wyświetlacz wszystkich pinów mikrokontrolera i ich wykorzystania. Nawet jeśli nie używasz STM32CubeMX do generowania kodu, jest to bardzo przydatne. Jedna rzecz, której nie lubię, to tak zwany HAL, który jest domyślnym STM32CubeMX. Preferuję metodę pracy LowLayer.
Do programowania mikrokontrolera używam programatora/debuggera ST-Link firmy ST Micro Electronics lub J-Link firmy Segger. Oba te urządzenia nie są darmowe, choć chińskie kopie można kupić za kilka euro.
Krok 4: O kodzie
MAX7219 adresuje diody LED w sposób, który nazywam poziomym, 8 diodami obok siebie. Dla oscyloskopu 8 diod LED umieszczonych jedna na drugiej byłoby łatwiejsze, więc stworzyłem prosty bufor ramki, do którego zapisuje się dane w pionie i odczytuje w wymaganym poziomie. MAX7219 używa 16-bitowego kodu na 8 diod LED, gdzie pierwszy bajt jest używany do adresowania wybranej linii. A ponieważ są cztery takie moduły ułożone obok siebie, a ich wejścia są połączone z wyjściami modułu przed nim, musisz wysłać te 16 bitów cztery razy, aby dotrzeć do ostatniego modułu. (Mam nadzieję, że wszystko wyjaśnię…) Dane są wysyłane do MAX7219 za pomocą SPI, prostego, ale bardzo szybkiego protokołu. Eksperymentowałem z tym, jak szybko można przesyłać dane do MAX7219. W końcu przełączyłem się z powrotem na 9 MHz tuż poniżej maksymalnej prędkości określonej w arkuszu danych.
Używam dwóch z czterech dostępnych timerów STM32F103C8, jednego do generowania podstawy czasu, a drugiego do odczytu enkodera obrotowego, który ustawia podstawę czasu. TIMER3 generuje podstawę czasu, robi to dzieląc zegar przez 230, aktualizując licznik co 3,2 uS. Za pomocą enkodera obrotowego można wybrać, aby licznik liczył od 2 impulsów zegarowych do 2000 impulsów zegarowych. Powiedzmy, że wybierasz 100. TIMER3 generuje następnie ZDARZENIE co 320 uS. To ZDARZENIE wyzwala ADC, aby nagrać próbkę sygnału wejściowego, a ponieważ są 32 próbki do pobrania na jeden ekran, zakończy się to po około. 10 ms. W 10mS można dopasować jedną długość fali 100 Hz lub dwie 200 Hz i tak dalej. Przejście przez 3 fale na ekran sprawia jednak, że raczej trudno jest rozpoznać przebieg.
Co do reszty, mogę tylko odesłać cię do kodu, nie jest trudno go śledzić, nawet jeśli masz tylko trochę doświadczenia z Arduino. W rzeczywistości można zrobić to samo z Arduino, chociaż wątpię, czy działałoby to tak szybko, jak „niebieska pigułka”. STM32F103C8 to 32-bitowy mikrokontroler działający z częstotliwością 72 MHz, ma dwa urządzenia peryferyjne SPI i bardzo szybki ADC.
Krok 5: Główny.h
#ifndef _MAIN_H_#define _MAIN_H_
#include "stm32f1xx_ll_adc.h"
#include "stm32f1xx_ll_rcc.h" #include "stm32f1xx_ll_bus.h" #include "stm32f1xx_ll_system.h" #include "stm32f1xx_ll_exti.h" #include "stm32f1xx_ll_cortex.hll_.1xx"_include "stm32f1xx_ll_exti.h" include "stm32f1xx_ll_dma.h" #include "stm32f1xx_ll_spi.h" #include "stm32f1xx_ll_tim.h" #include "stm32f1xx.h" #include "stm32f1xx_ll_gpio.h"
#ifndef NVIC_PRIORITYGROUP_0
#define NVIC_PRIORITYGROUP_0 ((uint32_t)0x00000007) #define NVIC_PRIORITYGROUP_1 ((uint32_t)0x00000006) #define NVIC_PRIORITYGROUP_2 ((uint32_t)0x00000005) #define NVIC_PRIORITYGROUP_1 ((uint32_t)0x00000006) #define NVIC_PRIORITYGROUP_2 ((uint32_t)0x00000005)
#ifdef _cplusplus
extern "C" { #endif void _Error_Handler(char *, int);
#define Error_Handler() _Error_Handler(_FILE_, _LINE_)
#ifdef _cplusplus } #endif
#endif
Krok 6: Główny.c
#include "main.h" static void LL_Init(void); nieważny SystemClock_Config (nieważny); static void MX_GPIO_Init(void); pusta statyczna MX_ADC1_Init(unieważniona); statyczne void MX_SPI1_Init(void); pusta statyczna MX_SPI2_Init(unieważniona); pusta statyczna MX_TIM3_Init(unieważniona); pusta statyczna MX_TIM4_Init(unieważniona);
uint16_t SPI1_send64(uint16_t dane3, uint16_t dane2, uint16_t dane1, uint16_t dane0);
uint16_t SPI2_send64(uint16_t dane3, uint16_t dane2, uint16_t dane1, uint16_t dane0); nieważne MAX7219_1_init(); nieważne MAX7219_2_init(); void erase_frame_buffer(void); void fill_frame_buffer(void); void display_frame_buffer(void); void set_timebase(void);
uint8_t upper_display[4][8]; //vier bytes naast elkaar, acht onder elkaar
uint8_t lower_display[4][8]; //deze twee samen vormen de frame-buffer
uint8_t sample_buffer[32]; //bufor voor de resultaten van de ADC
int główny (unieważniony)
{ LL_Init(); Konfiguracja Zegara Systemowego(); MX_GPIO_Init(); MX_ADC1_Init(); MX_SPI1_Init(); MX_SPI2_Init(); MX_TIM3_Init(); MX_TIM4_Init();
LL_SPI_Włącz (SPI1);
LL_SPI_Włącz (SPI2);
LL_TIM_EnableCounter(TIM3);
LL_TIM_EnableCounter(TIM4);
LL_ADC_Włącz (ADC1);
LL_ADC_REG_StartConversionSWStart(ADC1); LL_ADC_EnableIT_EOS(ADC1);
LL_mOpóźnienie(500); //MAX7219 potrzebuje trochę czasu po włączeniu
MAX7219_1_init(); MAX7219_2_init();
//LL_TIM_SetAutoReload(TIM3, 9);
gdy (1)
{ set_timebase(); erase_frame_buffer(); fill_frame_buffer(); display_frame_buffer(); } }
void erase_frame_buffer(void)
{ int8_t x; int8_t y;
for (x = 0; x < 4; x++) //kolom_bajtów {
for (y = 0; y < 8; y++) //lijnen { upper_display[x][y] = 0; //wszystkie bity op nul lower_display[x][y] = 0; } } }
void fill_frame_buffer(void)
{ uint8_t y = 0; //napięcie uint8_t tijd = 0; //tijd uint8_t display_byte; //Steeds 8 bits naast elkaar en dat 4 maal op een lijn uint8_t display_bit;
for (tijd = 0; tijd < 32; tijd++) { display_byte = tijd / 8; bit_wyświetlania = 7 - (tijd % 8);
y = bufor_próbki[tijd];
if (y > 7) //w górnym wyświetlaczu schrijven
{ upper_display[display_byte][15-y] |= (1 << display_bit); } else //na niższym wyświetlaczu schrijven { lower_display[display_byte][7-y] |= (1 << display_bit); } } }
nieważne display_frame_buffer (nieważne)
{
uint8_t; //acht lijnen boven elkaar (na wyświetlacz) uint16_t yl; //liczba dla MAX7219
dla (y = 0; y < 8; y++) { yl = (y+1) << 8; //MAX7219 heeft lijnnummer w górnym 8-bitowym słowie z 16-bitowym słowem
SPI2_send64((yl | upper_display[0][y]), (yl | upper_display[1][y]), (yl | upper_display[2][y]), (yl | upper_display[3][y]));
SPI1_send64((yl | lower_display[0][y]), (yl | lower_display[1][y]), (yl | lower_display[2][y]), (yl | lower_display[3][y])); }
}
void set_timebase(void)
{ uint8_t timebase_knop;
timebase_knop = LL_TIM_GetCounter(TIM4)/2;
przełącznik (timebase_knop)
{ przypadek 0: LL_TIM_SetAutoReload(TIM3, 1999); przerwa; przypadek 1: LL_TIM_SetAutoReload(TIM3, 999); przerwa; przypadek 2: LL_TIM_SetAutoReload(TIM3, 499); przerwa; przypadek 3: LL_TIM_SetAutoReload(TIM3, 199); przerwa; przypadek 4: LL_TIM_SetAutoReload(TIM3, 99); przerwa; przypadek 5: LL_TIM_SetAutoReload(TIM3, 49); przerwa; przypadek 6: LL_TIM_SetAutoReload(TIM3, 19); przerwa; przypadek 7: LL_TIM_SetAutoReload(TIM3, 9); przerwa; przypadek 8: LL_TIM_SetAutoReload(TIM3, 4); przerwa; przypadek 9: LL_TIM_SetAutoReload(TIM3, 1); przerwa;
domyślny:
LL_TIM_SetAutoReload(TIM3, 99); przerwa; } }
nieważne MAX7219_1_init()
{ SPI1_send64 (0x0000, 0x0000, 0x0000, 0x0000); //nie SPI1_send64(0x0C00, 0x0C00, 0x0C00, 0x0C00); //zamknij na SPI1_send64 (0x0000, 0x0000, 0x0000, 0x0000); //nie SPI1_send64(0x0F00, 0x0F00, 0x0F00, 0x0F00); //tryb testowy wyłączony SPI1_send64(0x0C01, 0x0C01, 0x0C01, 0x0C01); //wyłączenie, normalne działanie SPI1_send64(0x0900, 0x0900, 0x0900, 0x0900); //brak dekodowania 7seg, 64 piksele SPI1_send64(0x0A07, 0x0A07, 0x0A07, 0x0A07); //intensywność 50% SPI1_send64(0x0B07, 0x0B07, 0x0B07, 0x0B07); //wszystkie wiersze na }
nieważne MAX7219_2_init()
{ SPI2_send64 (0x0000, 0x0000, 0x0000, 0x0000); //nie SPI2_send64(0x0C00, 0x0C00, 0x0C00, 0x0C00); //zamknij na SPI2_send64 (0x0000, 0x0000, 0x0000, 0x0000); //nie SPI2_send64(0x0F00, 0x0F00, 0x0F00, 0x0F00); //tryb testowy wyłączony SPI2_send64(0x0C01, 0x0C01, 0x0C01, 0x0C01); //wyłączenie, normalne działanie SPI2_send64(0x0900, 0x0900, 0x0900, 0x0900); //brak dekodowania 7seg, 64 piksele SPI2_send64(0x0A07, 0x0A07, 0x0A07, 0x0A07); //intensywność 50% SPI2_send64(0x0B07, 0x0B07, 0x0B07, 0x0B07); //wszystkie wiersze na }
uint16_t SPI1_send64(uint16_t dane3, uint16_t dane2, uint16_t dane1, uint16_t dane0)
{ LL_GPIO_ResetOutputPin (GPIOA, LL_GPIO_PIN_4);
LL_SPI_TransmitData16(SPI1, dane3);
podczas (LL_SPI_IsActiveFlag_TXE(SPI1) == 0) {}
LL_SPI_TransmitData16 (SPI1, dane2);
podczas (LL_SPI_IsActiveFlag_TXE(SPI1) == 0) {}
LL_SPI_TransmitData16 (SPI1, dane1);
podczas (LL_SPI_IsActiveFlag_TXE(SPI1) == 0) {}
LL_SPI_TransmitData16(SPI1, dane0);
podczas (LL_SPI_IsActiveFlag_BSY(SPI1) == 1) {}
LL_GPIO_SetOutputPin (GPIOA, LL_GPIO_PIN_4);
zwróć LL_SPI_ReceiveData16(SPI1); }
uint16_t SPI2_send64(uint16_t dane3, uint16_t dane2, uint16_t dane1, uint16_t dane0)
{ LL_GPIO_ResetOutputPin (GPIOB, LL_GPIO_PIN_12);
LL_SPI_TransmitData16(SPI2, dane3);
podczas (LL_SPI_IsActiveFlag_TXE(SPI2) == 0) {}
LL_SPI_TransmitData16(SPI2, dane2);
podczas (LL_SPI_IsActiveFlag_TXE(SPI2) == 0) {}
LL_SPI_TransmitData16(SPI2, dane1);
podczas (LL_SPI_IsActiveFlag_TXE(SPI2) == 0) {}
LL_SPI_TransmitData16(SPI2, dane0);
podczas (LL_SPI_IsActiveFlag_BSY(SPI2) == 1) {}
LL_GPIO_SetOutputPin (GPIOB, LL_GPIO_PIN_12);
zwróć LL_SPI_ReceiveData16(SPI2); }
nieważny ADC1_2_IRQHandler(nieważny)
{ statyczny uint8_t licznik_próbek; wyzwalacz uint8_t; statyczny uint8_t poprzedni_wyzwalacz;
jeśli (LL_ADC_IsActiveFlag_EOS(ADC1) != RESET)
{ if (licznik_próbki < 32) { bufor_próbki[licznik_próbek] = LL_ADC_REG_ReadConversionData32(ADC1) / 256; if (licznik_prób < 32) licznik_prób++; w przeciwnym razie licznik_próbek = 0; } else { wyzwalacz = LL_ADC_REG_ReadConversionData32(ADC1) / 256;
if ((wyzwalacz == 7) && (poprzedni_wyzwalacz < wyzwalacz)) //gaat niet helemaal goed bij blokgolven… { sample_counter = 0; } poprzedni_wyzwalacz = wyzwalacz; }
LL_GPIO_TogglePin (GPIOC, LL_GPIO_PIN_13);
LL_ADC_ClearFlag_EOS(ADC1);
} }
static void LL_Init(void)
{ LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_AFIO); LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_PWR);
NVIC_SetPriorityGrouping(NVIC_PRIORITYGROUP_4);
NVIC_SetPriority(MemoryManagement_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(), 0, 0)); NVIC_SetPriority(BusFault_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(), 0, 0)); NVIC_SetPriority(UsageFault_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(), 0, 0)); NVIC_SetPriority(SVCall_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(), 0, 0)); NVIC_SetPriority(DebugMonitor_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(), 0, 0)); NVIC_SetPriority(PendSV_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(), 0, 0)); NVIC_SetPriority(SysTick_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(), 0, 0));
LL_GPIO_AF_Remap_SWJ_NOJTAG();
}
void SystemClock_Config (nieważny)
{ LL_FLASH_SetLatency(LL_FLASH_LATENCY_2); if(LL_FLASH_GetLatency() != LL_FLASH_LATENCY_2) Error_Handler(); LL_RCC_HSE_Enable(); while(LL_RCC_HSE_IsReady() !=1); LL_RCC_PLL_ConfigDomain_SYS (LL_RCC_PLLSOURCE_HSE_DIV_1, LL_RCC_PLL_MUL_9); LL_RCC_PLL_Enable(); while(LL_RCC_PLL_IsReady() !=1); LL_RCC_SetAHBPrescaler(LL_RCC_SYSCLK_DIV_1); LL_RCC_SetAPB1Preskaler(LL_RCC_APB1_DIV_2); LL_RCC_SetAPB2Prescaler(LL_RCC_APB2_DIV_1); LL_RCC_SetSysClkSource (LL_RCC_SYS_CLKSOURCE_PLL); while (LL_RCC_GetSysClkSource() != LL_RCC_SYS_CLKSOURCE_STATUS_PLL); LL_Init1msTick(72000000); LL_SYSTICK_SetClkSource(LL_SYSTICK_CLKSOURCE_HCLK); LL_SetSystemCoreClock(72000000); LL_RCC_SetADCClockSource (LL_RCC_ADC_CLKSRC_PCLK2_DIV_6);
NVIC_SetPriority(SysTick_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(), 0, 0));
}
pusta statyczna MX_ADC1_Init(void)
{ LL_ADC_InitTypeDef ADC_InitStruct; LL_ADC_CommonInitTypeDef ADC_CommonInitStruct; LL_ADC_REG_InitTypeDef ADC_REG_InitStruct; LL_GPIO_InitTypeDef GPIO_InitStruct;
LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_ADC1);
GPIO_InitStruct. Pin = LL_GPIO_PIN_0;
GPIO_InitStruct. Mode = LL_GPIO_MODE_ANALOG; LL_GPIO_Init (GPIOA, &GPIO_InitStruct);
NVIC_SetPriority(ADC1_2_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(), 0, 0));
NVIC_EnableIRQ(ADC1_2_IRQn);
ADC_InitStruct. DataAlignment = LL_ADC_DATA_ALIGN_RIGHT;
ADC_InitStruct. SequencersScanMode = LL_ADC_SEQ_SCAN_DISABLE; LL_ADC_Init(ADC1, &ADC_InitStruct);
ADC_CommonInitStruct. Multimode = LL_ADC_MULTI_INDEPENDENT;
LL_ADC_CommonInit(_LL_ADC_COMMON_INSTANCE(ADC1), &ADC_CommonInitStruct);
ADC_REG_InitStruct. TriggerSource = LL_ADC_REG_TRIG_EXT_TIM3_TRGO;
ADC_REG_InitStruct. SequencerLength = 1; 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_NONE; LL_ADC_REG_Init(ADC1, &ADC_REG_InitStruct);
LL_ADC_SetChannelSamplingTime (ADC1, LL_ADC_CHANNEL_0, LL_ADC_SAMPLINGTIME_41CYCLES_5);
}
pusta statyczna MX_SPI1_Init(unieważniona)
{ LL_SPI_InitTypeDef SPI_InitStruct; LL_GPIO_InitTypeDef GPIO_InitStruct;
LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_SPI1);
GPIO_InitStruct. Pin = LL_GPIO_PIN_5|LL_GPIO_PIN_7;
GPIO_InitStruct. Mode = LL_GPIO_MODE_ALTERNATE; GPIO_InitStruct. Speed = LL_GPIO_SPEED_FREQ_HIGH; GPIO_InitStruct. OutputType = LL_GPIO_OUTPUT_PUSHPULL; LL_GPIO_Init(GPIOA, &GPIO_InitStruct);
//NVIC_SetPriority(SPI1_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(), 0, 0));
//NVIC_EnableIRQ(SPI1_IRQn);
SPI_InitStruct. TransferDirection = LL_SPI_FULL_DUPLEX;
SPI_InitStruct. Mode = LL_SPI_MODE_MASTER; SPI_InitStruct. DataWidth = LL_SPI_DATAWIDTH_16BIT; SPI_InitStruct. ClockPolarity = LL_SPI_POLARITY_LOW; SPI_InitStruct. ClockPhase = LL_SPI_PHASE_1EDGE; SPI_InitStruct. NSS = LL_SPI_NSS_SOFT; SPI_InitStruct. Szybkość transmisji = LL_SPI_BAUDRATEPRESCALER_DIV8; SPI_InitStruct. BitOrder = LL_SPI_MSB_FIRST; SPI_InitStruct. CRCCalculation = LL_SPI_CRCCALCULATION_DISABLE; SPI_InitStruct. CRCPoly = 10; LL_SPI_Init(SPI1, &SPI_InitStruct); }
pustka statyczna MX_SPI2_Init(unieważniona)
{ LL_SPI_InitTypeDef SPI_InitStruct; LL_GPIO_InitTypeDef GPIO_InitStruct;
LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_SPI2);
GPIO_InitStruct. Pin = LL_GPIO_PIN_13|LL_GPIO_PIN_15;
GPIO_InitStruct. Mode = LL_GPIO_MODE_ALTERNATE; GPIO_InitStruct. Speed = LL_GPIO_SPEED_FREQ_HIGH; GPIO_InitStruct. OutputType = LL_GPIO_OUTPUT_PUSHPULL; LL_GPIO_Init(GPIOOB, &GPIO_InitStruct);
//NVIC_SetPriority(SPI2_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(), 0, 0));
//NVIC_EnableIRQ(SPI2_IRQn);
SPI_InitStruct. TransferDirection = LL_SPI_FULL_DUPLEX;
SPI_InitStruct. Mode = LL_SPI_MODE_MASTER; SPI_InitStruct. DataWidth = LL_SPI_DATAWIDTH_16BIT; SPI_InitStruct. ClockPolarity = LL_SPI_POLARITY_LOW; SPI_InitStruct. ClockPhase = LL_SPI_PHASE_1EDGE; SPI_InitStruct. NSS = LL_SPI_NSS_SOFT; SPI_InitStruct. Szybkość transmisji = LL_SPI_BAUDRATEPRESCALER_DIV4; SPI_InitStruct. BitOrder = LL_SPI_MSB_FIRST; SPI_InitStruct. CRCCalculation = LL_SPI_CRCCALCULATION_DISABLE; SPI_InitStruct. CRCPoly = 10; LL_SPI_Init(SPI2, &SPI_InitStruct); }
pusta statyczna MX_TIM3_Init(void)
{ LL_TIM_InitTypeDef TIM_InitStruct;
LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_TIM3);
TIM_InitStruct. Preskaler = 229;
TIM_InitStruct. CounterMode = LL_TIM_COUNTERMODE_UP; TIM_InitStruct. Autoreload = 9; TIM_InitStruct. ClockDivision = LL_TIM_CLOCKDIVISION_DIV1; LL_TIM_Init(TIM3, &TIM_InitStruct);
LL_TIM_DisableARRPreload(TIM3);
LL_TIM_SetClockSource (TIM3, LL_TIM_CLOCKSOURCE_INTERNAL); LL_TIM_SetTriggerOutput (TIM3, LL_TIM_TRGO_UPDATE); LL_TIM_EnableMasterSlaveMode(TIM3); }
pusta statyczna MX_TIM4_Init(void)
{ LL_TIM_InitTypeDef TIM_InitStruct; LL_GPIO_InitTypeDef GPIO_InitStruct;
LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_TIM4);
GPIO_InitStruct. Pin = LL_GPIO_PIN_6|LL_GPIO_PIN_7;
GPIO_InitStruct. Mode = LL_GPIO_MODE_FLOATING; LL_GPIO_Init(GPIOOB, &GPIO_InitStruct);
LL_TIM_SetEncoderMode(TIM4, LL_TIM_ENCODERMODE_X2_TI1);
LL_TIM_IC_SetActiveInput(TIM4, LL_TIM_CHANNEL_CH1, LL_TIM_ACTIVEINPUT_DIRECTTI); LL_TIM_IC_SetPrescaler (TIM4, LL_TIM_CHANNEL_CH1, LL_TIM_ICPSC_DIV1); LL_TIM_IC_SetFilter(TIM4, LL_TIM_CHANNEL_CH1, LL_TIM_IC_FILTER_FDIV1); LL_TIM_IC_SetPolarity(TIM4, LL_TIM_CHANNEL_CH1, LL_TIM_IC_POLARITY_RISING); LL_TIM_IC_SetActiveInput(TIM4, LL_TIM_CHANNEL_CH2, LL_TIM_ACTIVEINPUT_DIRECTTI); LL_TIM_IC_SetPrescaler (TIM4, LL_TIM_CHANNEL_CH2, LL_TIM_ICPSC_DIV1); LL_TIM_IC_SetFilter(TIM4, LL_TIM_CHANNEL_CH2, LL_TIM_IC_FILTER_FDIV1); LL_TIM_IC_SetPolarity(TIM4, LL_TIM_CHANNEL_CH2, LL_TIM_IC_POLARITY_RISING);
TIM_InitStruct. Preskaler = 0;
TIM_InitStruct. CounterMode = LL_TIM_COUNTERMODE_UP; TIM_InitStruct. Autoreload = 19; TIM_InitStruct. ClockDivision = LL_TIM_CLOCKDIVISION_DIV1; LL_TIM_Init(TIM4, &TIM_InitStruct);
LL_TIM_DisableARRPreload(TIM4);
LL_TIM_SetTriggerOutput(TIM4, LL_TIM_TRGO_RESET); LL_TIM_DisableMasterSlaveMode(TIM4); }
pusta statyczna MX_GPIO_Init(void)
{ LL_GPIO_InitTypeDef GPIO_InitStruct;
LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_GPIOC);
LL_APB2_GRP1_EnableClock (LL_APB2_GRP1_PERIPH_GPIOD); LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_GPIOA); LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_GPIOB);
LL_GPIO_SetOutputPin (GPIOC, LL_GPIO_PIN_13);
LL_GPIO_SetOutputPin (GPIOA, LL_GPIO_PIN_4); LL_GPIO_SetOutputPin (GPIOB, LL_GPIO_PIN_12);
GPIO_InitStruct. Pin = LL_GPIO_PIN_13;
GPIO_InitStruct. Mode = LL_GPIO_MODE_OUTPUT; GPIO_InitStruct. Speed = LL_GPIO_SPEED_FREQ_LOW; GPIO_InitStruct. OutputType = LL_GPIO_OUTPUT_PUSHPULL; LL_GPIO_Init(GPIOC, &GPIO_InitStruct);
GPIO_InitStruct. Pin = LL_GPIO_PIN_4;
GPIO_InitStruct. Mode = LL_GPIO_MODE_OUTPUT; GPIO_InitStruct. Speed = LL_GPIO_SPEED_FREQ_HIGH; GPIO_InitStruct. OutputType = LL_GPIO_OUTPUT_PUSHPULL; LL_GPIO_Init(GPIOA, &GPIO_InitStruct);
GPIO_InitStruct. Pin = LL_GPIO_PIN_12;
GPIO_InitStruct. Mode = LL_GPIO_MODE_OUTPUT; GPIO_InitStruct. Speed = LL_GPIO_SPEED_FREQ_HIGH; GPIO_InitStruct. OutputType = LL_GPIO_OUTPUT_PUSHPULL; LL_GPIO_Init(GPIOOB, &GPIO_InitStruct); }
void _Error_Handler(char *plik, linia wewnętrzna)
{ póki(1) { } }
#ifdef USE_FULL_ASSERT
void attach_failed (plik uint8_t*, wiersz uint32_t)
{ } #endif
Zalecana:
Mini oscyloskop CRT z zasilaniem bateryjnym: 7 kroków (ze zdjęciami)
Mini oscyloskop CRT zasilany bateryjnie: Witam! W tej instrukcji pokażę, jak zrobić mini oscyloskop CRT zasilany bateryjnie. Oscyloskop jest ważnym narzędziem do pracy z elektroniką; możesz zobaczyć wszystkie sygnały płynące w obwodzie i rozwiązywać problemy
Oscyloskop z podwójnym śledzeniem: 11 kroków (ze zdjęciami)
Oscyloskop z podwójnym śledzeniem: Kiedy budowałem mój poprzedni mini oscyloskop, chciałem zobaczyć, jak dobrze mogę wykonać mój najmniejszy mikrokontroler ARM, STM32F030 (F030), i wykonał dobrą robotę. W jednym z komentarzy sugerowano, że „Niebieska pigułka” z STM32F103
Wizualizator sygnału kieszonkowego (oscyloskop kieszonkowy): 10 kroków (ze zdjęciami)
Wizualizator sygnału kieszonkowego (oscyloskop kieszonkowy): Witam wszystkich, wszyscy robimy tak wiele rzeczy każdego dnia. Do każdej pracy tam, gdzie potrzebne są narzędzia. To jest do robienia, mierzenia, wykańczania itp. Tak więc pracownicy elektronicy potrzebują narzędzi, takich jak lutownica, multimetr, oscyloskop itp
Stwórz własny oscyloskop (Mini DSO) za pomocą STC MCU w prosty sposób: 9 kroków (ze zdjęciami)
Zrób swój własny oscyloskop (Mini DSO) z STC MCU w prosty sposób: Jest to prosty oscyloskop wykonany z STC MCU. Możesz użyć tego Mini DSO do obserwowania przebiegu. Przedział czasu: 100us-500ms Zakres napięcia: 0-30V Tryb rysowania: Wektor lub kropki
DIY Mini oscyloskop: 13 kroków
DIY Mini Oscyloskop: Zbuduj ten mały oscyloskop. Zakres częstotliwości do 40KHz (pełny ekran 25uS) w 4 zakresach do wyboru. Napięcie wejściowe wynosi od 50mVpp do 50Vpp w 2 wybieralnych zakresach. Wzmocnienie można regulować w zakresie od 1 do 100. Akceptuje wejście AC lub DC. Przełącznik automatycznego wyzwalania