Cuprins:
- Pasul 1: Hardware
- Pasul 2: Construiți
- Pasul 3: Programe
- Pasul 4: Despre cod
- Pasul 5: Main.h
- Pasul 6: Main.c
Video: Osciloscop cu patru biți: 6 pași
2024 Autor: John Day | [email protected]. Modificat ultima dată: 2024-01-30 11:45
Este un proiect pentru distracție doar pentru a vedea cât de departe în viteze aș putea împinge un afișaj cu matrice de puncte MAX7219. Și în loc să-l fac să ruleze „jocul vieții”, am decis să fac un „scop” cu el. După cum veți înțelege din titlu, acesta nu este un înlocuitor pentru un osciloscop real:-).
Deoarece nu intenționez să folosesc acest lucru într-un mod serios, nu voi crea o placă de circuite imprimate pentru acesta. Poate, doar poate îl voi pune pe o tablă de perf, dar deocamdată este, și va rămâne, pe o placă de calcul. De asemenea, nu există amplificator / atenuator de intrare, trebuie să furnizați un semnal între 0 și 3,3 V, nu treceți negativ sau peste 3,3 V, deoarece puteți deteriora microcontrolerul.
Pasul 1: Hardware
Este ieftin, foarte ieftin atunci când cumpărați piesele din China prin eBay sau site-uri similare. Folosește o placă de dezvoltare STM32F103C8, numită uneori „pastilă albastră” pe care am cumpărat-o cu aproximativ 2 euro (sau USD, sunt aproape aceeași valoare, la sfârșitul anului 2018), două afișaje cu matrice de puncte 8x8x4 cu cipuri MAX7219 pe ea, cumpărate pentru 5 euro bucata și codificator rotativ de aproximativ 1 euro.
Desigur, este necesară o sursă de alimentare care să furnizeze 3,3V la câteva sute de miliamperi. Regulatorul de tensiune de pe placa de dezvoltare STM32F103C8 nu este utilizat, nu poate furniza suficient curent pentru afișaje. Fișa tehnică pentru MAX7219 specifică tensiunea de alimentare de operare ar trebui să fie între 4,0 și 5,5 V, dar funcționează bine la 3,3 V, poate nu atunci când îl utilizați într-un mediu foarte cald sau rece, dar la 20 Celsius este bine. Și acum nu trebuie să folosesc convertoare de nivel între microcontroler și afișaje.
Pasul 2: Construiți
Când priviți imaginea, s-ar putea să vedeți că folosesc liniile de alimentare de pe panourile într-un mod neconvențional, ambele linii de sus sunt șina pozitivă și ambele de jos sunt șina de sol. Este modul în care sunt obișnuit să o fac și funcționează bine, face ca configurarea să arate un pic mai mult ca schemele pe care le desenez. De asemenea, am realizat o mulțime de plăci mici cu piese pe care le pot conecta la panou pentru a accelera lucrurile și toate sunt configurate pentru a utiliza cele două linii superioare ca pozitive și liniile inferioare ca sol. Așa cum am spus, rezoluția este de 4 biți (16 nivele) și, deoarece există 4x8 leduri una lângă cealaltă, există doar 32 de puncte de probă (puncte). Comparați-l cu un Rigol Rigol DS1054Z (8 biți și 12Mpts) și veți vedea că nu este o jucărie. Care este lățimea de bandă reală, nu știu, am testat-o până la 10 kHz și asta funcționează bine.
Pasul 3: Programe
IDE-ul pe care îl folosesc este Atollic TrueStudio, care a fost adoptat de la începutul acestui an (2018) de ST Micro Electronics și este disponibil gratuit, fără limită de timp, fără limită de dimensiune a codului, fără ecrane nag. Împreună cu acesta, folosesc STM32CubeMX, un program care îmi furnizează codul de pornire și generează inițializarea tuturor perifericelor. Și are un afișaj al tuturor pinilor microcontrolerului și a utilizării lor. Chiar dacă nu utilizați STM32CubeMX pentru generarea de cod, acest lucru este foarte la îndemână. Un lucru care nu-mi place este așa-numitul HAL, care este implicit STM32CubeMX. Prefer metoda de lucru LowLayer.
Pentru a programa microcontrolerul, folosesc fie programatorul / depanatorul ST-Link de la ST Micro Electronics, fie J-Link-ul realizat de Segger. Ambele dispozitive nu sunt gratuite, deși puteți cumpăra copii chinezești ale acestora pentru câțiva euro.
Pasul 4: Despre cod
MAX7219 se adresează LED-urilor în ceea ce eu numesc o formă orizontală, 8 leduri una lângă alta. Pentru un osciloscop, 8 LED-uri unul peste altul ar fi fost mai ușoare, așa că am creat un buffer de cadre simplu, care este scris cu date într-un mod vertical și citit în modul orizontal necesar. MAX7219 folosește un cod de 16 biți la 8 LED-uri, unde primul octet este utilizat pentru a adresa linia selectată. Și, deoarece există patru dintre aceste module stivuite unul lângă altul, cu intrările lor conectate la ieșirile modulului înainte de acesta, trebuie să trimiteți acei 16 biți de patru ori pentru a ajunge la ultimul modul. (Sper că clarific lucrurile …) Datele sunt trimise către MAX7219 folosind SPI, un protocol simplu, dar foarte rapid. La asta experimentam, cât de repede puteți merge în trimiterea datelor către MAX7219. În cele din urmă, am revenit la 9 MHz chiar sub viteza maximă specificată în foaia de date.
Folosesc două dintre cele patru temporizatoare disponibile ale STM32F103C8, unul pentru generarea bazei de timp și celălalt pentru citirea codificatorului rotativ, care setează baza de timp. TIMER3 generează baza de timp, o face împărțind ceasul la 230, actualizând contorul la fiecare 3,2 uS. Vrăjitorul codificatorului rotativ pe care îl puteți selecta pentru a avea numărarea contorului de la 2 impulsuri de ceas până la 2000 de impulsuri de ceas. Să presupunem că alegeți 100. TIMER3 generează apoi un EVENIMENT la fiecare 320 uS. Acest eveniment declanșează ADC să înregistreze un eșantion de semnal de intrare și, deoarece sunt 32 de eșantioane de luat pentru un ecran, acest lucru se va finaliza după aprox. 10 mS. În 10mS puteți încadra o lungime de undă de 100 Hz sau două de 200 Hz și așa mai departe. Trecând peste 3 unde pe ecran, este destul de greu să recunoaștem forma de undă.
În rest, vă pot referi doar la cod, nu este greu de urmat, chiar dacă aveți doar o experiență cu un Arduino. De fapt, ai putea face același lucru cu un Arduino, deși mă îndoiesc că ar funcționa la fel de repede ca o „pastilă albastră”. STM32F103C8 este un microcontroler pe 32 de biți care rulează la 72 MHz, are două periferice SPI și un ADC foarte rapid.
Pasul 5: Main.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.h" #include "#_inc" 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_3 ((uint32_t) 0x00000004) #define NVIC_PRIORITYGROUP_4 ((uint32_t) 0x00000003) # endif
#ifdef _plusplus
extern "C" {#endif void _Error_Handler (char *, int);
#define Error_Handler () _Error_Handler (_ FILE_, _LINE_)
#ifdef _cplusplus} #endif
#endif
Pasul 6: Main.c
#include "main.h" static void LL_Init (void); void SystemClock_Config (void); static void MX_GPIO_Init (nul); static void MX_ADC1_Init (nul); static void MX_SPI1_Init (nul); static void MX_SPI2_Init (nul); static void MX_TIM3_Init (nul); static void MX_TIM4_Init (nul);
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); nul MAX7219_1_init (); void MAX7219_2_init (); void erase_frame_buffer (nul); void fill_frame_buffer (nul); void display_frame_buffer (nul); void set_timebase (nul);
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]; // buffer voor de resultaten van de ADC
int main (nul)
{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 are nevoie de ceva timp după pornire
MAX7219_1_init (); MAX7219_2_init ();
// LL_TIM_SetAutoReload (TIM3, 9);
în timp ce (1)
{set_timebase (); erase_frame_buffer (); fill_frame_buffer (); display_frame_buffer (); }}
void erase_frame_buffer (nul)
{int8_t x; int8_t y;
pentru (x = 0; x <4; x ++) // kolom_bytes {
for (y = 0; y <8; y ++) // lijnen {upper_display [x] [y] = 0; // alle bitjes op nul lower_display [x] [y] = 0; }}}
void fill_frame_buffer (nul)
{uint8_t y = 0; // tensiune 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; display_bit = 7 - (tijd% 8);
y = sample_buffer [tijd];
if (y> 7) // în ecranul superior schrijven
{upper_display [display_byte] [15-y] | = (1 << display_bit); } else // in display jos schrijven {lower_display [display_byte] [7-y] | = (1 << display_bit); }}}
void display_frame_buffer (nul)
{
uint8_t y; // acht lijnen boven elkaar (per display) uint16_t yl; // lijnnummer voor de MAX7219
pentru (y = 0; y <8; y ++) {yl = (y + 1) << 8; // MAX7219 heeft lijnnummer in upper 8 bits van 16 bits woord
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 (nul)
{uint8_t timebase_knop;
timebase_knop = LL_TIM_GetCounter (TIM4) / 2;
comutare (timebase_knop)
{caz 0: LL_TIM_SetAutoReload (TIM3, 1999); pauză; cazul 1: LL_TIM_SetAutoReload (TIM3, 999); pauză; cazul 2: LL_TIM_SetAutoReload (TIM3, 499); pauză; caz 3: LL_TIM_SetAutoReload (TIM3, 199); pauză; cazul 4: LL_TIM_SetAutoReload (TIM3, 99); pauză; caz 5: LL_TIM_SetAutoReload (TIM3, 49); pauză; cazul 6: LL_TIM_SetAutoReload (TIM3, 19); pauză; caz 7: LL_TIM_SetAutoReload (TIM3, 9); pauză; caz 8: LL_TIM_SetAutoReload (TIM3, 4); pauză; caz 9: LL_TIM_SetAutoReload (TIM3, 1); pauză;
Mod implicit:
LL_TIM_SetAutoReload (TIM3, 99); pauză; }}
nul MAX7219_1_init ()
{SPI1_send64 (0x0000, 0x0000, 0x0000, 0x0000); // nop SPI1_send64 (0x0C00, 0x0C00, 0x0C00, 0x0C00); // oprire pe SPI1_send64 (0x0000, 0x0000, 0x0000, 0x0000); // nop SPI1_send64 (0x0F00, 0x0F00, 0x0F00, 0x0F00); // testmode off SPI1_send64 (0x0C01, 0x0C01, 0x0C01, 0x0C01); // oprire, funcționare normală SPI1_send64 (0x0900, 0x0900, 0x0900, 0x0900); // nu decodează 7seg, 64 pixeli SPI1_send64 (0x0A07, 0x0A07, 0x0A07, 0x0A07); // intensitate 50% SPI1_send64 (0x0B07, 0x0B07, 0x0B07, 0x0B07); // toate rândurile de pe}
nul MAX7219_2_init ()
{SPI2_send64 (0x0000, 0x0000, 0x0000, 0x0000); // nop SPI2_send64 (0x0C00, 0x0C00, 0x0C00, 0x0C00); // oprire pe SPI2_send64 (0x0000, 0x0000, 0x0000, 0x0000); // nop SPI2_send64 (0x0F00, 0x0F00, 0x0F00, 0x0F00); // testmode off SPI2_send64 (0x0C01, 0x0C01, 0x0C01, 0x0C01); // oprire, funcționare normală SPI2_send64 (0x0900, 0x0900, 0x0900, 0x0900); // nu decodează 7seg, 64 pixeli SPI2_send64 (0x0A07, 0x0A07, 0x0A07, 0x0A07); // intensitate 50% SPI2_send64 (0x0B07, 0x0B07, 0x0B07, 0x0B07); // toate rândurile de pe}
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);
while (LL_SPI_IsActiveFlag_TXE (SPI1) == 0) {}
LL_SPI_TransmitData16 (SPI1, data2);
while (LL_SPI_IsActiveFlag_TXE (SPI1) == 0) {}
LL_SPI_TransmitData16 (SPI1, data1);
while (LL_SPI_IsActiveFlag_TXE (SPI1) == 0) {}
LL_SPI_TransmitData16 (SPI1, data0);
while (LL_SPI_IsActiveFlag_BSY (SPI1) == 1) {}
LL_GPIO_SetOutputPin (GPIOA, LL_GPIO_PIN_4);
returnează 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);
while (LL_SPI_IsActiveFlag_TXE (SPI2) == 0) {}
LL_SPI_TransmitData16 (SPI2, data2);
while (LL_SPI_IsActiveFlag_TXE (SPI2) == 0) {}
LL_SPI_TransmitData16 (SPI2, data1);
while (LL_SPI_IsActiveFlag_TXE (SPI2) == 0) {}
LL_SPI_TransmitData16 (SPI2, data0);
while (LL_SPI_IsActiveFlag_BSY (SPI2) == 1) {}
LL_GPIO_SetOutputPin (GPIOB, LL_GPIO_PIN_12);
returnează LL_SPI_ReceiveData16 (SPI2); }
void ADC1_2_IRQHandler (nul)
{static uint8_t sample_counter; declanșator uint8_t; static uint8_t trigger_ anterior;
if (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 ++; else sample_counter = 0; } else {trigger = LL_ADC_REG_ReadConversionData32 (ADC1) / 256;
if ((trigger == 7) && (previous_trigger <trigger)) // gaat niet helemaal goed bij blokgolven … {sample_counter = 0; } anterior_trigger = declanșator; }
LL_GPIO_TogglePin (GPIOC, LL_GPIO_PIN_13);
LL_ADC_ClearFlag_EOS (ADC1);
} }
static nul LL_Init (nul)
{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 (); 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_SetAPB1Prescaler (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));
}
static void MX_ADC1_Init (nul)
{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 și & 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 și & 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 și & ADC_REG_InitStruct);
LL_ADC_SetChannelSamplingTime (ADC1, LL_ADC_CHANNEL_0, LL_ADC_SAMPLINGTIME_41CYCLES_5);
}
static void MX_SPI1_Init (nul)
{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 și & SPI_InitStruct); }
static void MX_SPI2_Init (nul)
{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 și & SPI_InitStruct); }
static void MX_TIM3_Init (nul)
{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 și & 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); }
static void MX_TIM4_Init (nul)
{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 (nul)
{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 și & 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 (fișier char *, linie int)
{while (1) {}}
#ifdef USE_FULL_ASSERT
void assert_failed (fișier uint8_t *, linie uint32_t)
{} #endif
Recomandat:
Raspberry Pi MMA8452Q 3-Axis Tutorial accelerator digital Python pe 12 biți / 8 biți: 4 pași
Raspberry Pi MMA8452Q 3-Axis 12-bit / 8-bit Accelerometru digital Python Tutorial: MMA8452Q este un accelerometru inteligent, de mică putere, cu trei axe, capacitiv, micromachined, cu 12 biți de rezoluție. Opțiuni flexibile programabile de utilizator sunt furnizate cu ajutorul funcțiilor încorporate în accelerometru, configurabile pentru două întreruperi
Glisor de cameră DIY motorizat din patru părți imprimate 3D: 5 pași (cu imagini)
Glisor de cameră DIY motorizat din patru piese imprimate 3D: Bună ziua, producătorilor, este producătorul moekoe! Astăzi vreau să vă arăt cum să construiți un glisor de cameră liniar foarte util bazat pe o șină V-Slot / Openbuilds, motor pas cu pas Nema17 și doar patru piese imprimate 3D . Acum câteva zile am decis să investesc într-o cameră mai bună pentru
Patru prăjituri - Noul Raspberry Pi 4 - Proiectul principal și celebrare !: 6 pași
Patru plăcinte - noul Raspberry Pi 4 - Proiecte importante și sărbători !: Mai jos o prezentare rapidă a conținutului. Prezentare și prezentare video Pie Pi 3.14 Pies Result
Proiectarea unui controler asociat asociat de cache simplu în patru direcții în VHDL: 4 pași
Proiectarea unui controler de cache asociativ setat în patru direcții în VHDL: În instructajul meu anterior, am văzut cum să proiectăm un controler de cache direct mapat simplu. De data aceasta, facem un pas înainte. Vom proiecta un controler cache asociativ simplu cu patru căi. Avantaj? Mai puțină rata de rate, dar cu prețul perfo
Cum să faci un videoclip pe ecran divizat cu patru pași: 4 pași (cu imagini)
Cum să faci un videoclip pe ecran divizat cu patru pași: Adesea vedem o aceeași persoană prezentată într-o scenă de două ori într-o piesă TV. Și din câte știm, actorul nu are un frate geamăn. De asemenea, am urmărit că două videoclipuri de cântat sunt plasate pe un ecran pentru a compara abilitățile lor de a cânta. Aceasta este puterea spl