Innehållsförteckning:
Video: Fyra bitars oscilloskop: 6 steg
2024 Författare: John Day | [email protected]. Senast ändrad: 2024-01-30 12:45
Det är ett för skojs skull-projekt bara för att se hur långt i hastigheter jag kunde skjuta en MAX7219-punktmatrisdisplay. Och istället för att låta det köra "livets spel" bestämde jag mig för att göra ett "omfång" med det. Som du förstår av titeln är detta inte en ersättning för ett riktigt oscilloskop:-).
Eftersom jag inte tänker använda detta på något seriöst sätt kommer jag inte att göra ett kretskort för det. Kanske, bara kanske jag lägger den på en perf-board men för tillfället är den, och kommer att förbli, på en breadboard. Det finns också ingen ingångsförstärkare/dämpare, du måste ge en signal mellan 0 och 3.3V, gå inte negativ eller över 3.3V eftersom du kan skada mikrokontrollen.
Steg 1: Hårdvara
Det är billigt, väldigt billigt när du köper delarna i Kina via ebay eller liknande sajter. Den använder en utvecklingsbräda STM32F103C8, ibland kallad ett "blått piller" som jag köpte för cirka 2 euro (eller USD, de är nästan samma värde i slutet av 2018), två 8x8x4 dot-matrisdisplayer med MAX7219-chips på, köpt för 5 euro per bit och en roterande kodare på cirka 1 euro.
Naturligtvis behövs en strömförsörjning som levererar 3,3V vid några hundra milliampere. Spänningsregulatorn på utvecklingsbordet STM32F103C8 används inte, den kan inte ge tillräckligt med ström för displayerna. Databladet för MAX7219 anger att matningsspänningen ska vara mellan 4,0 och 5,5 V men den går bra på 3,3 V, kanske inte när du använder den i en mycket varm eller kall miljö, men vid 20 Celsius är det bra. Och nu behöver jag inte använda nivåomvandlare mellan mikrokontrollen och bildskärmarna.
Steg 2: Bygg
När du tittar på bilden kan du se att jag använder kraftledningarna på brödbrädorna på ett icke -konventionellt sätt, båda linjerna ovanpå är den positiva skenan och båda på botten är markskenan. Det är så som jag är van vid att göra det och det fungerar bra, det får installationen att se lite mer ut som de scheman jag ritar. Jag har också gjort en massa små brädor med delar på som jag kan ansluta till brödbrädan för att påskynda saker och de är alla konfigurerade för att använda de två översta linjerna som positiva och de nedre linjerna som mark. Som jag sa är upplösningen 4 bit (16 nivåer), och eftersom det finns 4x8 lysdioder bredvid varandra finns det bara 32 samplingspunkter (poäng). Jämför det med en Rigol Rigol DS1054Z (8 bitar och 12 Mpts) så ser du att detta knappast är en leksak. Vad den egentliga bandbredden är, jag vet inte, jag har testat det upp till 10 kHz och det fungerar bra.
Steg 3: Program
IDE jag använder är Atollic TrueStudio som från början av detta år (2018) antogs av ST Micro Electronics och är tillgänglig gratis, ingen tidsbegränsning, ingen kodstorleksgräns, inga nag-skärmar. Tillsammans med det använder jag STM32CubeMX, ett program som förser mig med startkoden och genererar initialiseringen av alla kringutrustning. Och den har en display av alla stiften på mikrokontrollen och deras användning. Även om du inte använder STM32CubeMX för att generera kod, är detta mycket praktiskt. En sak jag inte gillar är den så kallade HAL som är standard för STM32CubeMX. Jag föredrar LowLayer -arbetsmetoden.
För att programmera mikrokontrollern använder jag antingen ST-Link programmerare/debugger från ST Micro Electronics eller J-Link som gjorts av Segger. Båda dessa enheter är inte gratis, även om du kan köpa kinesiska kopior av dem för några euro.
Steg 4: Om koden
MAX7219 adresserar lysdioderna på det jag kallar horisontellt, 8 lysdioder bredvid varandra. För ett oscilloskop hade 8 lysdioder ovanpå varandra varit enklare, så jag gjorde en enkel rambuffert som skrivs till data på ett vertikalt sätt och läste upp på det nödvändiga horisontella sättet. MAX7219 använder en 16 -bitars kod per 8 lysdioder, där den första byten används för att adressera den valda raden. Och eftersom det finns fyra av dessa moduler staplade bredvid varandra, med sina ingångar anslutna till modulens utgångar innan den, måste du skicka de 16 bitarna fyra gånger för att nå den sista modulen. (Jag hoppas att jag gör saker tydliga …) Data skickas till MAX7219 med SPI, ett enkelt men mycket snabbt protokoll. Det här är vad jag experimenterade med, hur snabbt kan du skicka data till MAX7219. Till slut bytte jag tillbaka till 9 MHz strax under den maximala hastighet som databladet anger.
Jag använder två av de fyra tillgängliga timern för STM32F103C8, en för generationen av tidsbasen och den andra för att läsa ut den roterande kodaren, som ställer in tidsbasen. TIMER3 genererar tidsbasen, den gör det genom att dela klockan med 230, uppdatera räknaren var 3,2 us. Häxa den roterande pulsgivaren som du kan välja för att ha räknaren från 2 klockpulser upp till 2000 klockpulser. Låt oss säga att du väljer 100. TIMER3 genererar sedan ett EVENT varje 320 us. Denna HÄNDELSE utlöser ADC för att spela in ett sampel av insignalen, och eftersom det är 32 samplar att ta för en skärm, kommer detta att slutföras efter cirka. 10 mS. I 10mS kan du passa en våglängd på 100 Hz, eller två på 200 Hz, och så vidare. Att gå över 3 vågor per skärm gör det dock ganska svårt att känna igen vågformen.
För resten kan jag bara hänvisa dig till koden, det är inte svårt att följa även om du bara har lite erfarenhet av en Arduino. Faktum är att du kan göra samma sak med en Arduino, även om jag tvivlar på att det skulle fungera lika snabbt som ett "blått piller". STM32F103C8 är en 32 -bitars mikrokontroller med 72 MHz, den har två SPI -enheter och en mycket snabb ADC.
Steg 5: Main.h
#ifndef _MAIN_H _#definiera _MAIN_H_
#inkludera "stm32f1xx_ll_adc.h"
#inkludera "stm32f1xx_ll_rcc.h" #include "stm32f1xx_ll_bus.h" #include "stm32f1xx_ll_system.h" #include "stm32f1xx_ll_exti.h" #include "stm32f1xx_ll_cortex.h" #inc_h1 #h32 " inkludera "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_3 ((uint32_t) 0x00000004) #define NVIC_PRIORITYGROUP_4 ((uint32_t) 0x00000003) #endif
#ifdef _cplusplus
extern "C" {#endif void _Error_Handler (char *, int);
#define Error_Handler () _Error_Handler (_ FILE_, _LINE_)
#ifdef _cplusplus} #endif
#endif
Steg 6: Main. C
#include "main.h" static void LL_Init (void); void SystemClock_Config (void); static void MX_GPIO_Init (void); statisk void MX_ADC1_Init (void); static void MX_SPI1_Init (void); static void MX_SPI2_Init (void); statiskt void MX_TIM3_Init (void); statiskt void MX_TIM4_Init (void);
uint16_t SPI1_send64 (uint16_t data3, uint16_t data2, uint16_t data1, uint16_t data0);
uint16_t SPI2_send64 (uint16_t data3, uint16_t data2, uint16_t data1, uint16_t data0); ogiltigt MAX7219_1_init (); ogiltigt MAX7219_2_init (); void erase_frame_buffer (void); void fill_frame_buffer (void); void display_frame_buffer (void); void set_timebase (void);
uint8_t övre_display [4] [8]; // vier bytes bredvid varandra, åtta under varandra
uint8_t lägre_display [4] [8]; // dessa två olika former av rambuffert
uint8_t sample_buffer [32]; // buffer for de resultaten van de ADC
int main (void)
{LL_Init (); SystemClock_Config (); MX_GPIO_Init (); MX_ADC1_Init (); MX_SPI1_Init (); MX_SPI2_Init (); MX_TIM3_Init (); MX_TIM4_Init ();
LL_SPI_Enable (SPI1);
LL_SPI_Enable (SPI2);
LL_TIM_EnableCounter (TIM3);
LL_TIM_EnableCounter (TIM4);
LL_ADC_Enable (ADC1);
LL_ADC_REG_StartConversionSWStart (ADC1); LL_ADC_EnableIT_EOS (ADC1);
LL_mDelay (500); // MAX7219 behöver lite tid efter att strömmen har slagits på
MAX7219_1_init (); MAX7219_2_init ();
// LL_TIM_SetAutoReload (TIM3, 9);
medan (1)
{set_timebase (); erase_frame_buffer (); fill_frame_buffer (); display_frame_buffer (); }}
void erase_frame_buffer (void)
{int8_t x; int8_t y;
för (x = 0; x <4; x ++) // kolom_bytes {
för (y = 0; y <8; y ++) // lijnen {upper_display [x] [y] = 0; // alla bitjes op nul lägre_display [x] [y] = 0; }}}
void fill_frame_buffer (void)
{uint8_t y = 0; // spänning uint8_t tijd = 0; // tijd uint8_t display_byte; // stadig 8 bitar bredvid varandra och att 4 maal på en linje uint8_t display_bit;
för (tijd = 0; tijd <32; tijd ++) {display_byte = tijd / 8; display_bit = 7 - (tijd % 8);
y = sample_buffer [tijd];
if (y> 7) // i övre displayen skriva
{upper_display [display_byte] [15-y] | = (1 << display_bit); } annat // i lägre displayskrivning {lägre_display [display_byte] [7-y] | = (1 << display_bit); }}}
void display_frame_buffer (void)
{
uint8_t y; // acht lijnen boven elkaar (per display) uint16_t yl; // lijnnummer voor de MAX7219
för (y = 0; y <8; y ++) {yl = (y+1) << 8; // MAX7219 har lijnnummer in the upper 8 bits van 16 bits word
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 | lägre_display [0] [y]), (yl | lägre_display [1] [y]), (yl | lägre_display [2] [y]), (yl | lägre_display [3] [y])); }
}
void set_timebase (void)
{uint8_t timebase_knop;
timebase_knop = LL_TIM_GetCounter (TIM4) / 2;
switch (timebase_knop)
{fall 0: LL_TIM_SetAutoReload (TIM3, 1999); ha sönder; fall 1: LL_TIM_SetAutoReload (TIM3, 999); ha sönder; fall 2: LL_TIM_SetAutoReload (TIM3, 499); ha sönder; fall 3: LL_TIM_SetAutoReload (TIM3, 199); ha sönder; fall 4: LL_TIM_SetAutoReload (TIM3, 99); ha sönder; fall 5: LL_TIM_SetAutoReload (TIM3, 49); ha sönder; fall 6: LL_TIM_SetAutoReload (TIM3, 19); ha sönder; fall 7: LL_TIM_SetAutoReload (TIM3, 9); ha sönder; fall 8: LL_TIM_SetAutoReload (TIM3, 4); ha sönder; fall 9: LL_TIM_SetAutoReload (TIM3, 1); ha sönder;
standard:
LL_TIM_SetAutoReload (TIM3, 99); ha sönder; }}
ogiltig MAX7219_1_init ()
{SPI1_send64 (0x0000, 0x0000, 0x0000, 0x0000); // nop SPI1_send64 (0x0C00, 0x0C00, 0x0C00, 0x0C00); // avstängning på SPI1_send64 (0x0000, 0x0000, 0x0000, 0x0000); // nop SPI1_send64 (0x0F00, 0x0F00, 0x0F00, 0x0F00); // testmode off SPI1_send64 (0x0C01, 0x0C01, 0x0C01, 0x0C01); // avstängning, normal drift SPI1_send64 (0x0900, 0x0900, 0x0900, 0x0900); // ingen 7seg -avkodning, 64 pixlar SPI1_send64 (0x0A07, 0x0A07, 0x0A07, 0x0A07); // intensitet 50% SPI1_send64 (0x0B07, 0x0B07, 0x0B07, 0x0B07); // alla rader på}
ogiltig MAX7219_2_init ()
{SPI2_send64 (0x0000, 0x0000, 0x0000, 0x0000); // nop SPI2_send64 (0x0C00, 0x0C00, 0x0C00, 0x0C00); // avstängning på SPI2_send64 (0x0000, 0x0000, 0x0000, 0x0000); // nop SPI2_send64 (0x0F00, 0x0F00, 0x0F00, 0x0F00); // testmode off SPI2_send64 (0x0C01, 0x0C01, 0x0C01, 0x0C01); // avstängning, normal drift SPI2_send64 (0x0900, 0x0900, 0x0900, 0x0900); // ingen 7seg -avkodning, 64 pixlar SPI2_send64 (0x0A07, 0x0A07, 0x0A07, 0x0A07); // intensitet 50% SPI2_send64 (0x0B07, 0x0B07, 0x0B07, 0x0B07); // alla rader på}
uint16_t SPI1_send64 (uint16_t data3, uint16_t data2, uint16_t data1, uint16_t data0)
{LL_GPIO_ResetOutputPin (GPIOA, LL_GPIO_PIN_4);
LL_SPI_TransmitData16 (SPI1, data3);
medan (LL_SPI_IsActiveFlag_TXE (SPI1) == 0) {}
LL_SPI_TransmitData16 (SPI1, data2);
medan (LL_SPI_IsActiveFlag_TXE (SPI1) == 0) {}
LL_SPI_TransmitData16 (SPI1, data1);
medan (LL_SPI_IsActiveFlag_TXE (SPI1) == 0) {}
LL_SPI_TransmitData16 (SPI1, data0);
medan (LL_SPI_IsActiveFlag_BSY (SPI1) == 1) {}
LL_GPIO_SetOutputPin (GPIOA, LL_GPIO_PIN_4);
returnera LL_SPI_ReceiveData16 (SPI1); }
uint16_t SPI2_send64 (uint16_t data3, uint16_t data2, uint16_t data1, uint16_t data0)
{LL_GPIO_ResetOutputPin (GPIOB, LL_GPIO_PIN_12);
LL_SPI_TransmitData16 (SPI2, data3);
medan (LL_SPI_IsActiveFlag_TXE (SPI2) == 0) {}
LL_SPI_TransmitData16 (SPI2, data2);
medan (LL_SPI_IsActiveFlag_TXE (SPI2) == 0) {}
LL_SPI_TransmitData16 (SPI2, data1);
medan (LL_SPI_IsActiveFlag_TXE (SPI2) == 0) {}
LL_SPI_TransmitData16 (SPI2, data0);
medan (LL_SPI_IsActiveFlag_BSY (SPI2) == 1) {}
LL_GPIO_SetOutputPin (GPIOB, LL_GPIO_PIN_12);
returnera LL_SPI_ReceiveData16 (SPI2); }
void ADC1_2_IRQHandler (void)
{statisk uint8_t sample_counter; uint8_t trigger; statisk uint8_t föregående_trigger;
om (LL_ADC_IsActiveFlag_EOS (ADC1)! = RESET)
{if (sample_counter <32) {sample_buffer [sample_counter] = LL_ADC_REG_ReadConversionData32 (ADC1) / 256; if (sample_counter <32) sample_counter ++; annars sample_counter = 0; } annat {trigger = LL_ADC_REG_ReadConversionData32 (ADC1) / 256;
if ((trigger == 7) && (previous_trigger <trigger)) // gaat niet helemaal goed bij blokgolven… {sample_counter = 0; } föregående_trigger = utlösare; }
LL_GPIO_TogglePin (GPIOC, LL_GPIO_PIN_13);
LL_ADC_ClearFlag_EOS (ADC1);
} }
statiskt tomrum 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 (void)
{LL_FLASH_SetLatency (LL_FLASH_LATENCY_2); if (LL_FLASH_GetLatency ()! = LL_FLASH_LATENCY_2) Error_Handler (); LL_RCC_HSE_Enable (); medan (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 (); medan (LL_RCC_PLL_IsReady ()! = 1); LL_RCC_SetAHBPrescaler (LL_RCC_SYSCLK_DIV_1); LL_RCC_SetAPB1Prescaler (LL_RCC_APB1_DIV_2); LL_RCC_SetAPB2Prescaler (LL_RCC_APB2_DIV_1); LL_RCC_SetSysClkSource (LL_RCC_SYS_CLKSOURCE_PLL); medan (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));
}
static void 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);
}
static void MX_SPI1_Init (void)
{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. BaudRate = 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); }
static void MX_SPI2_Init (void)
{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 (GPIOB, & 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. BaudRate = 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); }
statiskt tomrum MX_TIM3_Init (ogiltigt)
{LL_TIM_InitTypeDef TIM_InitStruct;
LL_APB1_GRP1_EnableClock (LL_APB1_GRP1_PERIPH_TIM3);
TIM_InitStruct. Prescaler = 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); }
statiskt void 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 (GPIOB, & 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. Prescaler = 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); }
static void 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 och 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 (GPIOB, & GPIO_InitStruct); }
void _Error_Handler (char *fil, int rad)
{while (1) {}}
#ifdef ANVÄND_FULL_ASSERT
void assert_failed (uint8_t* fil, uint32_t rad)
{} #endif
Rekommenderad:
Arduino Nano-MMA8452Q 3-Axis 12-bitars/8-bitars digital accelerometer Tutorial: 4 steg
Arduino Nano-MMA8452Q 3-Axis 12-bitars/8-bitars digital accelerometer Tutorial: MMA8452Q är en smart, lågeffekts, treaxlig, kapacitiv, mikromaskinell accelerometer med 12 bitars upplösning. Flexibla användarprogrammerbara alternativ tillhandahålls med hjälp av inbäddade funktioner i accelerometern, konfigurerbara till två avbrott
Raspberry Pi MMA8452Q 3-Axis 12-bitars/8-bitars digital accelerometer Python-handledning: 4 steg
Raspberry Pi MMA8452Q 3-Axis 12-bitars/8-bitars digital accelerometer Python-handledning: MMA8452Q är en smart, lågeffekts, treaxlig, kapacitiv, mikromaskinell accelerometer med 12 bitars upplösning. Flexibla användarprogrammerbara alternativ tillhandahålls med hjälp av inbäddade funktioner i accelerometern, konfigurerbara till två avbrott
Raspberry Pi MMA8452Q 3-Axis 12-bitars/8-bitars digital accelerometer Java-handledning: 4 steg
Raspberry Pi MMA8452Q 3-Axis 12-bitars/8-bitars digital accelerometer Java-handledning: MMA8452Q är en smart, lågeffekts, treaxlig, kapacitiv, mikromaskinell accelerometer med 12 bitars upplösning. Flexibla användarprogrammerbara alternativ tillhandahålls med hjälp av inbäddade funktioner i accelerometern, konfigurerbara till två avbrott
DIY MusiLED, musiksynkroniserade lysdioder med ett klick Windows och Linux-applikation (32-bitars och 64-bitars). Lätt att återskapa, lätt att använda, lätt att porta .: 3 steg
DIY MusiLED, musiksynkroniserade lysdioder med ett klick Windows och Linux-applikation (32-bitars och 64-bitars). Lätt att återskapa, lätt att använda, lätt att porta .: Detta projekt hjälper dig att ansluta 18 lysdioder (6 röda + 6 blå + 6 gula) till ditt Arduino-kort och analysera datorns ljudkortets realtidsignaler och vidarebefordra dem till lysdioderna för att tända dem enligt slageffekterna (Snare, High Hat, Kick)
Hur man gör en delad skärmvideo med fyra steg: 4 steg (med bilder)
Hur man gör en delad skärmvideo med fyra steg: Vi ser ofta samma person visa i en scen två gånger i ett tv -spel. Och så vitt vi vet har skådespelaren ingen tvillingbror. Vi har också sett att två sångvideor läggs på en skärm för att jämföra deras sångkunskaper. Detta är kraften i spl