תוכן עניינים:
וִידֵאוֹ: אוסצילוסקופ ארבע ביט: 6 שלבים
2024 מְחַבֵּר: John Day | [email protected]. שונה לאחרונה: 2024-01-30 09:16
זה פרויקט בשביל הכיף רק כדי לראות כמה רחוק במהירות אני יכול לדחוף תצוגת מטריקס MAX7219. ובמקום שזה ינהל את "משחק החיים", החלטתי לעשות עם זה "סקופ". כפי שתבינו מהכותרת, זהו אינו תחליף לאוסילוסקופ אמיתי:-).
מכיוון שאני לא מתכוון להשתמש בזה בצורה רצינית, לא אכין עבורו מעגל מודפס. אולי, רק אולי אני אשים אותו על קרש פרפ, אבל בינתיים הוא, ויישאר, על קרש לחם. כמו כן, אין מגבר כניסה/מחליש, עליך לספק אות בין 0 ל -3.3 וולט, אל תצא שלילי או מעל 3.3 וולט מכיוון שאתה עלול לגרום נזק למיקרו.
שלב 1: חומרה
זה זול, זול מאוד כאשר אתה קונה את החלקים בסין באמצעות ebay או אתרים דומים. הוא משתמש בלוח פיתוח STM32F103C8, המכונה לפעמים "כדור כחול" שרכשתי בסביבות 2 אירו (או דולר, הם בערך אותו ערך, סוף 2018), שני תצוגות מטריצה 8x8x4 עם שבבי MAX7219, קנו עבור 5 אירו ליחידה ומקודד סיבובי של כ -1 אירו.
דרוש כמובן ספק כוח המספק 3.3V בכמה מאות מיליאמפר אמפר. ווסת המתח בלוח הפיתוח STM32F103C8 אינו בשימוש, הוא אינו יכול לספק מספיק זרם לתצוגות. גיליון הנתונים של MAX7219 מציין כי מתח אספקת ההפעלה צריך להיות בין 4.0 ל -5.5 וולט אך הוא פועל היטב על 3.3 וולט, אולי לא כאשר אתה משתמש בו בסביבה חמה או קרה מאוד, אך בטמפרטורה של 20 צלזיוס הוא בסדר. ועכשיו אני לא צריך להשתמש בממירי רמות בין המיקרו-בקר ללוחות התצוגה.
שלב 2: בנה
כאשר אתה מסתכל על התמונה אתה עשוי לראות שאני משתמש בקווי החשמל על לוחות הלחם בצורה לא קונבנציונלית, שני הקווים מלמעלה הם המעקה החיובי ושניהם בחלק התחתון הם מסילת הקרקע. זו הדרך שבה אני רגיל לעשות את זה וזה עובד טוב, זה גורם לתצורה להיראות קצת יותר כמו הסכימות שאני מצייר. כמו כן, הכנתי הרבה לוחות קטנים עם חלקים שאפשר לחבר אותם ללוח כדי להאיץ את העניינים וכולם מוגדרים להשתמש בשתי הקווים העליונים כחיוביים ובקווים התחתונים כאדמה. כפי שאמרתי, הרזולוציה היא 4 ביט (16 רמות), וכפי שיש 4x8 נוריות אחת ליד השנייה יש רק 32 נקודות מדגם (נק '). השווה זאת עם Rigol Rigol DS1054Z (8 ביט ו -12 Mpts) ותראה שזה כמעט לא צעצוע. מהו רוחב הפס בפועל, אני לא יודע, בדקתי אותו עד 10kHz וזה עובד מצוין.
שלב 3: תוכניות
ה- IDE שאני משתמש בו הוא Atollic TrueStudio אשר מתחילת השנה (2018) אומצה על ידי ST Micro Electronics והוא זמין בחינם, ללא הגבלת זמן, ללא מגבלת גודל קוד, ללא מסכי נגינה. יחד איתו אני משתמש ב- STM32CubeMX, תוכנית שמספקת לי את קוד ההתחלה ומייצרת אתחול כל הציוד ההיקפי. ויש לו תצוגה של כל הפינים של המיקרו -בקר והשימוש בהם. גם אם אינך משתמש ב- STM32CubeMX ליצירת קוד, זה מאוד שימושי. דבר אחד שאני לא אוהב הוא ה- HAL שנקרא ברירת המחדל של STM32CubeMX. אני מעדיף את שיטת העבודה של LowLayer.
כדי לתכנת את המיקרו-בקר אני משתמש או במתכנת/ניפוי ST-Link מ- ST Micro Electronics או ב- J-Link מתוצרת Segger. שני המכשירים הללו אינם בחינם, אם כי ניתן לרכוש עותקים סיניים מהם בכמה יורו.
שלב 4: אודות הקוד
ה- MAX7219 פונים לנוריות במה שאני מכנה אופקית, 8 נוריות אחת ליד השנייה. עבור אוסצילוסקופ 8 נוריות זו על זו היו קלות יותר, אז הכנתי מאגר מסגרות פשוט שנכתב אליו עם נתונים בצורה אנכית, וקראתי אותו בצורה האופקית הנדרשת. ה- MAX7219 משתמש בקוד 16 ביט לכל 8 נוריות LED, כאשר הבייט הראשון משמש לכתובת השורה שנבחרה. ומכיוון שיש ארבעה מודולים אלה מוערמים זה ליד זה, כאשר התשומות שלהם מחוברות ליציאות המודול לפניו, עליך לשלוח את 16 הסיביות האלה ארבע פעמים כדי להגיע למודול האחרון. (אני מקווה שאני מבהיר את הדברים …) הנתונים נשלחים ל- MAX7219 באמצעות SPI, פרוטוקול פשוט אך מהיר מאוד. בזה ניסיתי, כמה מהר אתה יכול לשלוח את הנתונים ל- MAX7219. בסופו של דבר, חזרתי ל 9 מגה -הרץ ממש מתחת למהירות המקסימלית שגיליון הנתונים מציין.
אני משתמש בשניים מתוך ארבעת הטיימרים הזמינים של STM32F103C8, אחד לדור בסיס הזמן והשני לקריאת המקודד הרוטרי, הקובע את בסיס הזמן. TIMER3 מייצר את בסיס הזמן, הוא עושה זאת על ידי חלוקת השעון ב- 230, עדכון המונה כל 3.2 ארה"ב. מכשפים את המקודד הסיבובי שתוכל לבחור כדי לספור את המונה בין 2 פולסי שעון ועד 2000 פולסי שעון. נניח שאתה בוחר 100. לאחר מכן TIMER3 מייצר אירוע כל 320 ארה"ב. אירוע זה מפעיל את ה- ADC להקליט דגימה של אות הכניסה, וככל ש- 32 דוגמאות שצריך לקחת למסך אחד, זה יסתיים לאחר כ-. 10 mS. ב 10mS אתה יכול להתאים אורך גל אחד של 100 הרץ, או שניים של 200 הרץ, וכן הלאה. מעבר על 3 גלים למסך מקשה על זיהוי צורת הגל.
לכל השאר, אני יכול להפנות אותך רק לקוד, לא קשה לעקוב אחריו גם אם יש לך רק ניסיון עם Arduino. למעשה, אתה יכול להכין אותו דבר עם ארדואינו, אם כי אני בספק אם הוא יעבוד במהירות "כדור כחול". STM32F103C8 הוא מיקרו -בקר של 32 ביט שפועל במהירות 72 מגה -הרץ, יש לו שני ציוד היקפי SPI ו- ADC מהיר מאוד.
שלב 5: Main.h
#ifndef _MAIN_H _#הגדר _MAIN_H_
#כלול "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" #inc_h1 #ll_h1 כלול את "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
חיצוני "C" { #endif void _Error_Handler (char *, int);
#define Error_Handler () _Error_Handler (_ FILE_, _LINE_)
#ifdef _cplusplus} #endif
#endif
שלב 6: Main.c
#כלול חלל סטטי "main.h" LL_Init (void); void SystemClock_Config (void); חלל סטטי MX_GPIO_Init (void); חלל סטטי MX_ADC1_Init (void); חלל סטטי MX_SPI1_Init (void); חלל סטטי MX_SPI2_Init (void); חלל סטטי MX_TIM3_Init (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); void MAX7219_1_init (); void MAX7219_2_init (); voide erase_frame_buffer (void); void fill_frame_buffer (void); void display_frame_buffer (void); void set_timebase (void);
uint8_t_display_4 [4] [8]; // ארבעה בייטים לצד זה, שמונה ביחד
uint8_t תצוגה נמוכה יותר [4] [8]; // אלה שתי צורות של מסגרת-מאגר
uint8_t sample_buffer [32]; // buffer for de results 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 זקוק לזמן מה לאחר ההפעלה
MAX7219_1_init (); MAX7219_2_init ();
// LL_TIM_SetAutoReload (TIM3, 9);
בעוד (1)
{set_timebase (); מחק_מסגרת_אופייר (); fill_frame_buffer (); display_frame_buffer (); }}
void erase_frame_buffer (void)
{int8_t x; int8_t y;
עבור (x = 0; x <4; x ++) // kolom_bytes {
עבור (y = 0; y <8; y ++) // lijnen {upper_display [x] [y] = 0; // alle bitjes op nul lower_display [x] [y] = 0; }}}
void fill_frame_buffer (void)
{uint8_t y = 0; // מתח uint8_t tijd = 0; // tijd uint8_t display_byte; // שטרס 8 ביטים לצד אחד ואחד מזה 4 עלים על שורה אחת uint8_t display_bit;
עבור (tijd = 0; tijd <32; tijd ++) {display_byte = tijd / 8; display_bit = 7 - (זמן % 8);
y = sample_buffer [tijd];
אם (y> 7) // בתצוגה העליונה לכתוב
{upper_display [display_byte] [15-y] | = (1 << display_bit); } else // בתצוגה נמוכה יותר לכתוב {lower_display [display_byte] [7-y] | = (1 << display_bit); }}}
void display_frame_buffer (void)
{
uint8_t y; // acht lijnen boven elkaar (לכל תצוגה) uint16_t yl; // lijnnummer voor de MAX7219
עבור (y = 0; y <8; y ++) {yl = (y+1) << 8; // MAX7219 יש לימן בקיץ העליון של 8 סיביות ואן 16 סיביות
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;
מתג (timebase_knop)
{מקרה 0: LL_TIM_SetAutoReload (TIM3, 1999); לשבור; מקרה 1: LL_TIM_SetAutoReload (TIM3, 999); לשבור; מקרה 2: LL_TIM_SetAutoReload (TIM3, 499); לשבור; מקרה 3: LL_TIM_SetAutoReload (TIM3, 199); לשבור; מקרה 4: LL_TIM_SetAutoReload (TIM3, 99); לשבור; מקרה 5: LL_TIM_SetAutoReload (TIM3, 49); לשבור; מקרה 6: LL_TIM_SetAutoReload (TIM3, 19); לשבור; מקרה 7: LL_TIM_SetAutoReload (TIM3, 9); לשבור; מקרה 8: LL_TIM_SetAutoReload (TIM3, 4); לשבור; מקרה 9: LL_TIM_SetAutoReload (TIM3, 1); לשבור;
בְּרִירַת מֶחדָל:
LL_TIM_SetAutoReload (TIM3, 99); לשבור; }}
בטל MAX7219_1_init ()
{SPI1_send64 (0x0000, 0x0000, 0x0000, 0x0000); // nop SPI1_send64 (0x0C00, 0x0C00, 0x0C00, 0x0C00); // כיבוי ב- SPI1_send64 (0x0000, 0x0000, 0x0000, 0x0000); // nop SPI1_send64 (0x0F00, 0x0F00, 0x0F00, 0x0F00); // testmode off SPI1_send64 (0x0C01, 0x0C01, 0x0C01, 0x0C01); // כיבוי, פעולה רגילה SPI1_send64 (0x0900, 0x0900, 0x0900, 0x0900); // ללא פענוח 7seg, 64 פיקסלים SPI1_send64 (0x0A07, 0x0A07, 0x0A07, 0x0A07); // עוצמה 50% SPI1_send64 (0x0B07, 0x0B07, 0x0B07, 0x0B07); // כל השורות ב-}
בטל MAX7219_2_init ()
{SPI2_send64 (0x0000, 0x0000, 0x0000, 0x0000); // nop SPI2_send64 (0x0C00, 0x0C00, 0x0C00, 0x0C00); // כיבוי ב- SPI2_send64 (0x0000, 0x0000, 0x0000, 0x0000); // nop SPI2_send64 (0x0F00, 0x0F00, 0x0F00, 0x0F00); // testmode off SPI2_send64 (0x0C01, 0x0C01, 0x0C01, 0x0C01); // כיבוי, פעולה רגילה SPI2_send64 (0x0900, 0x0900, 0x0900, 0x0900); // ללא פענוח 7seg, 64 פיקסלים SPI2_send64 (0x0A07, 0x0A07, 0x0A07, 0x0A07); // עוצמה 50% SPI2_send64 (0x0B07, 0x0B07, 0x0B07, 0x0B07); // כל השורות ב-}
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);
בעוד (LL_SPI_IsActiveFlag_TXE (SPI1) == 0) {}
LL_SPI_TransmitData16 (SPI1, data2);
בעוד (LL_SPI_IsActiveFlag_TXE (SPI1) == 0) {}
LL_SPI_TransmitData16 (SPI1, data1);
בעוד (LL_SPI_IsActiveFlag_TXE (SPI1) == 0) {}
LL_SPI_TransmitData16 (SPI1, data0);
בעוד (LL_SPI_IsActiveFlag_BSY (SPI1) == 1) {}
LL_GPIO_SetOutputPin (GPIOA, LL_GPIO_PIN_4);
החזר 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);
בעוד (LL_SPI_IsActiveFlag_TXE (SPI2) == 0) {}
LL_SPI_TransmitData16 (SPI2, data2);
בעוד (LL_SPI_IsActiveFlag_TXE (SPI2) == 0) {}
LL_SPI_TransmitData16 (SPI2, data1);
בעוד (LL_SPI_IsActiveFlag_TXE (SPI2) == 0) {}
LL_SPI_TransmitData16 (SPI2, data0);
בעוד (LL_SPI_IsActiveFlag_BSY (SPI2) == 1) {}
LL_GPIO_SetOutputPin (GPIOB, LL_GPIO_PIN_12);
החזר LL_SPI_ReceiveData16 (SPI2); }
void ADC1_2_IRQHandler (void)
{סטטי uint8_t sample_counter; uint8_t טריגר; סטטי uint8_t הקודם_הדק;
אם (LL_ADC_IsActiveFlag_EOS (ADC1)! = אפס)
{if (sample_counter <32) {sample_buffer [sample_counter] = LL_ADC_REG_ReadConversionData32 (ADC1) / 256; if (sample_counter <32) sample_counter ++; אחר sample_counter = 0; } אחר {trigger = LL_ADC_REG_ReadConversionData32 (ADC1) / 256;
if ((trigger == 7) && (previous_trigger <trigger)) // gaat niet helemaal goed bij blokgolven… {sample_counter = 0; } previous_trigger = טריגר; }
LL_GPIO_TogglePin (GPIOC, LL_GPIO_PIN_13);
LL_ADC_ClearFlag_EOS (ADC1);
} }
חלל סטטי 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); אם (LL_FLASH_GetLatency ()! = LL_FLASH_LATENCY_2) Error_Handler (); LL_RCC_HSE_Enable (); בעוד (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 (); בעוד (LL_RCC_PLL_IsReady ()! = 1); LL_RCC_SetAHBPrescaler (LL_RCC_SYSCLK_DIV_1); LL_RCC_SetAPB1 מיון (LL_RCC_APB1_DIV_2); LL_RCC_SetAPB2Prescaler (LL_RCC_APB2_DIV_1); LL_RCC_SetSysClkSource (LL_RCC_SYS_CLKSOURCE_PLL); בעוד (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));
}
חלל סטטי 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);
}
חלל סטטי 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); }
חלל סטטי 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); }
חלל סטטי MX_TIM3_Init (void)
{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); }
חלל סטטי 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); }
חלל סטטי 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 (GPIOB, & GPIO_InitStruct); }
void _Error_Handler (קובץ char *, שורה int)
{בעוד (1) {}}
#ifdef USE_FULL_ASSERT
void assert_failed (קובץ uint8_t*, שורה uint32_t)
{} #endif
מוּמלָץ:
רובוט ארבע -מנוע המודפס בתלת -ממד: 13 שלבים (עם תמונות)
מודפס בתלת -ממד רובוט ארדואינו מופעל: מכלי ההוראה הקודמים, אתה כנראה יכול לראות שיש לי עניין עמוק בפרויקטים רובוטיים. לאחר ההוראה הקודמת שבה בניתי דו -ראשי רובוטי, החלטתי לנסות להכין רובוט מרובע שיכול לחקות בעלי חיים כמו כלב
כיצד לבצע ארבע מחשבון פונקציונלי בעלות עלות: 6 שלבים
כיצד להכין מחשבון פונקציונאלי ארבע עלות: מחשבונים משמשים לכולם בחיי היומיום. מחשבון פשוט יכול להיעשות באמצעות תוכנית C ++ המסוגלת להוסיף, לחסר, להכפיל ולחלק, שתי אופרנדים שהזין המשתמש. משפט if ו- goto משמש ליצירת מחשבון
כיצד להפעיל מנועי סרוו באמצעות מוטו: ביט עם מיקרו: ביט: 7 שלבים (עם תמונות)
כיצד להפעיל מנועי סרוו באמצעות מוטו: ביט עם מיקרו: ביט: אחת הדרכים להרחיב את הפונקציונליות של המיקרו: ביט היא להשתמש בלוח בשם moto: bit מאת SparkFun Electronics (כ-15-20 $). הוא נראה מסובך ויש לו הרבה תכונות, אבל לא קשה להפעיל ממנו מנועי סרוו. Moto: bit מאפשר לך
ארבע פשטידות - הפטל החדש של פטל 4 - פרויקט הבהרה וחגיגה !: 6 שלבים
ארבע פשטידות - הפטל החדש של פטל 4 - פרויקט הבהרה וחגיגה!: להלן סקירה מהירה של התוכן. מבוא ותצוגת וידיאו לראווה Pie Pi 3.14 עוגות
שעון מילים בן ארבע אותיות עם מחולל מילים של Akafugu וביטויים מעוררי השראה: 3 שלבים
שעון מילים בעל ארבע אותיות עם מחולל מילים של Akafugu וביטויים מעוררי השראה: זוהי הגרסה שלי לשעון המילה ארבע אותיות, רעיון שמקורו בשנות השבעים. השעון מציג סדרה של מילים בעלות ארבע אותיות הנוצרות מאלגוריתם של מחולל מילים אקראי או ממאגר מידע של ארבע אותיות קשורות