UCOS-III 系統移植

1. 移植前準備

1.1 源碼下載

UCOS-III Kernel Source? ?https://github.com/weston-embedded/uC-OS3.git

Micriμm CPU Source?:?https://github.com/weston-embedded/uC-CPU.git

Micriμm Lib Source: https://github.com/weston-embedded/uC-LIB.git?

1.2. 源碼介紹

1.2.1 源碼組織結構圖

1.2.2 源碼簡介

1)應用層模塊

2)BSP 與板子相關的BSP模塊 (需要移植) 主要為系統時鐘、時間戳相關API

3)μC-OS3/Source 內核源碼 與CPU無關的模塊

4)μC-OS3/Ports 與CPU相關的模塊 (需要移植 )

5)uC-CPU 與特定平臺CPU相關的模塊(由uc-cpu提供)

6)uC-LIB 與CPU無關的庫函數模塊

7) μC-OS3/Cfg 配置頭文件(需要配置的部分)

調用關系: UC/OS-III/Ports-->uC-CPU --> CPU_BSP

2. 移植配置列表

1)移植 uC-OS3 CPU 相關部分: os_cpu.h,?os_cpu_a.asm,? os_cpu_c.c

2)移植 uC/CPU 相關部分: cpu_a.asm , cpu_c.c

3)移植板級支持包(BSP) 部分: bsp.c ,bsp.h

4)配置UC/OS-III 以下部分:

?μC/OS-III 功能配置 (os_cfg.h)

μC/OS-III 堆棧、系統任務和其他數據大小 (os_cfg_app.h)

μC/OS-III 數據類型 (os_type.h)

具體配置參考: http://t.csdnimg.cn/GNZcY

3. 移植 uC-OS3 CPU

3.1 找到MCU使用的CPU架構

以GD32F303為例,翻閱其手冊,查找CPU對應的架構信息如下:

3.2 找到CPU架構對應的文件

????????在uC-OS3/Ports目錄下查找ARMv7-M,找到 ARMv7-M路徑: ARM-Cortex-M/ARMv7-M

3.3 開發編譯環境列表

ARM-Cortex-M/ARMv7-M 目錄下有4個文件夾,分別對應不同的編譯器

  • ARM: ARM公司提供的編譯器,如Keil MDK開發環境。
  • CCS: TI的Code Composer Studio編譯器。
  • GNU: GNU工具鏈(如GCC)
  • IAR: IAR 開發環境

3.4 使用Keil MDK編譯器

uC-OS3/Template/bsp_os_dt.c , 有以下系統時鐘相關接口需要移植:

BSP_OS_TickInit()     //初始化系統時鐘滴答定時器     
BSP_OS_TickISR()      //系統時鐘滴答中斷服務程序

uC-OS3/Ports/Template目錄里的os_cpu.h ,有以下上下文切換相關接口需要實現:???

void  OSCtxSw              (void);  // 任務級上下文切換,觸發PendSV異常
void  OSIntCtxSw           (void);  // 中斷上下文中進行任務切換,觸發PendSV異常
void  OSStartHighRdy       (void);  // 啟動最高優先級的就緒任務
void  OS_CPU_PendSVHandler (void);  // PendSV 異常處理程序,用切換當前任務的上下文到下一個準備就緒的任務 

查看MCU的CPU架構及所選開發環境對應的文件

uC-OS3/Ports/ARM-Cortex-M/ARMv7-M/os_cpu_c.c

uC-OS3/Ports/ARM-Cortex-M/ARMv7-M/ARM/os_cpu_a.asm

已實現上述的所有接口,如果原廠沒有實現的接口,則需要實現以上接口

3.4.1 BSP_OS_TickInit 接口實現

此函數接口用于初始化系統滴答定時器,設置操作系統時鐘中斷,該函數必須在 OSStart() 調用之后,并且在處理器初始化完成后調用。

優先級設置需要考慮系統中其他中斷的優先級配置,確保實時操作系統的滴答計時器中斷能夠按期觸發。

以下是偽代碼描述:

void BSP_OS_TickInit(CPU_INT32U freq) {Install the interrupt vector for the timer used to generate tick interrupts; // 安裝定時器中斷向量Configure the timer to generate interrupts at 'freq' Hz; // 配置定時器以產生指定頻率的中斷Enable timer interrupts; // 啟用定時器中斷
}

以下是ARM-Cortex-M/ARMv7-M/os_cpu_c.c已實現的接口:

voidOS_CPU_SysTickInit(CPU_INT32U  cnts)
{CPU_INT32U  prio;CPU_INT32U  basepri;// 設置 BASEPRI 邊界basepri = (CPU_INT32U)(CPU_CFG_KA_IPL_BOUNDARY << (8u - CPU_CFG_NVIC_PRIO_BITS));CPU_REG_SYST_RVR = cnts - 1u;  // 設置重載寄存器// 設置 SysTick 處理程序的優先級prio = CPU_REG_SCB_SHPRI3;prio &= 0x00FFFFFFu;prio |= (basepri << 24u);CPU_REG_SCB_SHPRI3 = prio;// 啟用計時器CPU_REG_SYST_CSR |= CPU_REG_SYST_CSR_CLKSOURCE | CPU_REG_SYST_CSR_ENABLE;// 啟用計時器中斷CPU_REG_SYST_CSR |= CPU_REG_SYST_CSR_TICKINT;}

3.4.2 BSP_OS_TickISR 接口實現

此接口函數用于處理系統時鐘滴答(SysTick)中斷

以下是該函數的偽代碼描述:

BSP_OS_TickISR:OS_CTX_SAVE                ; 保存當前任務的上下文Disable Interrupts         ; 禁用中斷OSIntNestingCtr++          ; 增加中斷嵌套計數器if (OSIntNestingCtr == 1) {OSTCBCurPtr->StkPtr = SP ; 如果這是第一個中斷,保存任務堆棧指針}Clear tick interrupt       ; 清除滴答中斷標志OSTimeTick()               ; 調用OSTimeTick,通知發生了一個滴答OSIntExit()                ; 通知μC/OS-III中斷處理結束OS_CTX_RESTORE             ; 恢復任務的上下文Return from Interrupt/Exception ; 返回到被中斷的任務

以下是ARM-Cortex-M/ARMv7-M/os_cpu_c.c已實現的接口:

void OS_CPU_SysTickHandler(void)
{CPU_SR_ALLOC();CPU_CRITICAL_ENTER();OSIntEnter();  /* 通知uC/OS-III我們正在進入一個ISR */CPU_CRITICAL_EXIT();OSTimeTick();  /* 調用uC/OS-III的OSTimeTick() */OSIntExit();  /* 通知uC/OS-III我們正在離開ISR */
}

3.4.3 OSCtxSw 接口移植

該函數接口實現任務級上下文切換,以下是該函數的匯編實現偽代碼:

                             ; (1) 通過軟中斷調用OSCtxSw
OSCtxSw:OS_CTX_SAVE              ; (2) 保存當前任務的CPU上下文LDR     R0, =OSTCBCurPtrLDR     R0, [R0]STR     SP, [R0]         ; (3) 將當前任務的堆棧指針保存到其TCBBL      OSTaskSwHookLDR     R0, =OSPrioHighRdyLDR     R0, [R0]STR     R0, =OSPrioCurLDR     R0, =OSTCBHighRdyPtrLDR     R0, [R0]LDR     SP, [R0]         ; (4) 從新任務的TCB中獲取堆棧指針OS_CTX_RESTORE           ; (5) 恢復新任務的CPU上下文BX      LR               ; (6) 從中斷返回,恢復PC和SR

以下是ARM-Cortex-M/ARMv7-M/ARM/os_cpu_a.asm已實現的接口:

OSCtxSw
OSIntCtxSwLDR     R0, =NVIC_INT_CTRL      ; Trigger the PendSV exception (causes context switch)LDR     R1, =NVIC_PENDSVSETSTR     R1, [R0]BX      LR

3.4.4 OSIntCtxSw 接口移植

此函數用于在中斷上下文中進行任務切換,以下為該函數的匯編實現偽代碼:

在所有嵌套的ISR結束時由 OSIntExit() 調用
OSIntCtxSw:BL      OSTaskSwHookLDR     R0, =OSPrioHighRdyLDR     R0, [R0]STR     R0, =OSPrioCurLDR     R0, =OSTCBHighRdyPtrLDR     R0, [R0]LDR     SP, [R0]OS_CTX_RESTOREBX      LR

以下是ARM-Cortex-M/ARMv7-M/ARM/os_cpu_a.asm已實現的接口:

OSCtxSw
OSIntCtxSwLDR     R0, =NVIC_INT_CTRL      ; Trigger the PendSV exception (causes context switch)LDR     R1, =NVIC_PENDSVSETSTR     R1, [R0]BX      LR

3.4.5 OSStartHighRdy 接口移植

此函數用于啟動最高優先級的就緒任務,以下是該函數的匯編實現偽代碼:

OSStartHighRdy:BL      OSTaskSwHook                                      ; 調用任務切換鉤子函數LDR     R0, =OSTCBHighRdyPtr                              ; 獲取最高優先級任務的TCB指針LDR     R0, [R0]LDR     SP, [R0]                                          ; (1) 獲取最高優先級任務的堆棧指針OS_CTX_RESTORE                                            ; (2) 恢復新任務的CPU上下文BX      LR                                                ; (3) 從中斷返回,恢復PC和SR

以下是ARM-Cortex-M/ARMv7-M/ARM/os_cpu_a.asm已實現的接口:

OSStartHighRdyCPSID   I                                                   ; Prevent interruption during context switchMOV32   R0, NVIC_SYSPRI14                                   ; Set the PendSV exception priorityMOV32   R1, NVIC_PENDSV_PRISTRB    R1, [R0]MOVS    R0, #0                                              ; Set the PSP to 0 for initial context switch callMSR     PSP, R0MOV32   R0, OS_CPU_ExceptStkBase                            ; Initialize the MSP to the OS_CPU_ExceptStkBaseLDR     R1, [R0]MSR     MSP, R1BL      OSTaskSwHook                                        ; Call OSTaskSwHook() for FPU Push & PopMOV32   R0, OSPrioCur                                       ; OSPrioCur   = OSPrioHighRdy;MOV32   R1, OSPrioHighRdyLDRB    R2, [R1]STRB    R2, [R0]MOV32   R0, OSTCBCurPtr                                     ; OSTCBCurPtr = OSTCBHighRdyPtr;MOV32   R1, OSTCBHighRdyPtrLDR     R2, [R1]STR     R2, [R0]LDR     R0, [R2]                                            ; R0 is new process SP; SP = OSTCBHighRdyPtr->StkPtr;MSR     PSP, R0                                             ; Load PSP with new process SPMRS     R0, CONTROLORR     R0, R0, #2BIC     R0, R0, #4                                          ; Clear FPCA bit to indicate FPU is not in useMSR     CONTROL, R0ISB                                                         ; Sync instruction streamLDMFD    SP!, {R4-R11, LR}                                  ; Restore r4-11, lr from new process stackLDMFD    SP!, {R0-R3}                                       ; Restore r0, r3LDMFD    SP!, {R12, LR}                                     ; Load R12 and LRLDMFD    SP!, {R1, R2}                                      ; Load PC and discard xPSRCPSIE    IBX       R1

3.4.6 OS_CPU_PendSVHandler 接口實現

此接口函數用于引發上下文切換,以下是該函數的實現步驟和詳細代碼

獲取進程堆棧指針:將進程堆棧指針(PSP)保存到R0

保存剩余寄存器:將寄存器R4-R11和R14保存到進程堆棧

保存進程堆棧指針:將進程堆棧指針保存到當前任務的TCB中

調用OSTaskSwHook:執行任務切換鉤子函數

更新當前任務和準備就緒任務:更新當前任務的優先級和TCB指針

獲取新任務堆棧指針:從準備就緒任務的TCB中獲取堆棧指針,并將其加載到PSP中

恢復寄存器:從新任務堆棧恢復寄存器R4-R11和R14

恢復上下文:從異常返回,恢復剩余上下文

以下是ARM-Cortex-M/ARMv7-M/ARM/os_cpu_a.asm已實現的接口:

OS_CPU_PendSVHandler:CPSID   I                               ; 禁止中斷MOV32   R2, OS_KA_BASEPRI_Boundary      ; 設置BASEPRI優先級LDR     R1, [R2]MSR     BASEPRI, R1DSBISBCPSIE   IMRS     R0, PSP                         ; 獲取進程堆棧指針IF {FPU} != "SoftVFP"TST       R14, #0x10IT        EQVSTMDBEQ  R0!, {S16-S31}            ; 如果任務使用FPU,保存高位FPU寄存器ENDIFSTMFD   R0!, {R4-R11, R14}              ; 保存R4-R11和R14寄存器MOV32   R5, OSTCBCurPtr                 ; 保存當前任務的堆棧指針LDR     R1, [R5]STR     R0, [R1]MOV     R4, LR                          ; 保存LR寄存器值BL      OSTaskSwHook                    ; 調用任務切換鉤子函數MOV32   R0, OSPrioCur                   ; 更新當前任務優先級MOV32   R1, OSPrioHighRdyLDRB    R2, [R1]STRB    R2, [R0]MOV32   R1, OSTCBHighRdyPtr             ; 更新當前任務的TCB指針LDR     R2, [R1]STR     R2, [R5]ORR     LR, R4, #0x04                   ; 確保異常返回使用進程堆棧LDR     R0, [R2]                        ; 獲取新任務的堆棧指針LDMFD   R0!, {R4-R11, R14}              ; 恢復R4-R11和R14寄存器IF {FPU} != "SoftVFP"TST       R14, #0x10IT        EQVLDMIAEQ  R0!, {S16-S31}            ; 恢復高位FPU寄存器ENDIFMSR     PSP, R0                         ; 加載新的進程堆棧指針MOV32   R2, #0                          ; 恢復BASEPRI優先級CPSID   IMSR     BASEPRI, R2DSBISBCPSIE   IBX      LR                              ; 異常返回,將恢復剩余上下文ALIGNEND

4. 移植 uC/CPU

uC-CPU/BSP/Template/bsp_cpu.c 有以下CPU時間戳相關接口需要實現:

CPU_TS_TmrInit()   //CPU 時間戳計時器初始化
CPU_TS_TmrRd()     //獲取當前 CPU 時間戳計時器的計數值?
CPU_TS32_to_uSec() //將時間戳計數轉換為微秒
如果啟用了 CPU 時間戳或 CPU 中斷禁用時間測量功能,必須實現這些接口

uC-CPU/Template/cpu_a.asm 有以下接口需要實現:

CPU_IntDis     ;禁用中斷
CPU_IntEn      ;啟用中斷
CPU_SR_Save    ;保存CPU狀態寄存器
CPU_SR_Restore ;恢復CPU狀態寄存器
CPU_CntLeadZeros;計數前導零

uC-CPU/ARM-Cortex-M/ARMv7-M/ARM/cpu_a.asm 已實現上述接口

4.1 CPU_TS_TmrInit() 接口移植

該接口是CPU 時間戳計時器初始化函數 , 該計時器用于記錄精確的時間戳或測量 CPU 禁用中斷的時間。以下是基于GD32F303的實現代碼:

void  CPU_TS_TmrInit (void)
{CPU_INT32U  fclk_freq;fclk_freq = BSP_CPU_ClkFreq();BSP_REG_DEM_CR     |= (CPU_INT32U)BSP_BIT_DEM_CR_TRCENA;    /* Enable Cortex-M4's DWT CYCCNT reg.                   */BSP_REG_DWT_CYCCNT  = (CPU_INT32U)0u;BSP_REG_DWT_CR     |= (CPU_INT32U)BSP_BIT_DWT_CR_CYCCNTENA;CPU_TS_TmrFreqSet((CPU_TS_TMR_FREQ)fclk_freq);
}

4.2 CPU_TS_TmrRd 接口移植

該 函數用于獲取當前 CPU 時間戳計時器的計數值,以下是基于GD32F303的實現代碼:

CPU_TS_TMR  CPU_TS_TmrRd (void)
{CPU_TS_TMR  ts_tmr_cnts;ts_tmr_cnts = (CPU_TS_TMR)BSP_REG_DWT_CYCCNT;return (ts_tmr_cnts);
}

4.3 CPU_TS32_to_uSec 接口移植

該函數用于將時間戳計數轉換為微秒,以下是基于GD32F303的實現代碼:

CPU_INT64U  CPU_TS32_to_uSec (CPU_TS32  ts_cnts)
{CPU_INT64U  ts_us;CPU_INT64U  fclk_freq;fclk_freq = BSP_CPU_ClkFreq();ts_us     = ts_cnts / (fclk_freq / DEF_TIME_NBR_uS_PER_SEC);return (ts_us);
}

5. 移植驗證

5.1. 構建工程目錄

├── app // 應用程序

├── bsp // 板級支持包,包含系統需要移植的接口及硬件相關庫文件及接口

????????└── gd32f30x

????????????????├── bsp.c //需要移植的接口

????????????????├── bsp.h

????????????????├── gd32f30x_it.c

????????????????├── gd32f30x_it.h

????????????????├── gd32f30x_libopt.h

????????????????├── Library

????????????????├── mdk-project

├── uC-CFG //把 uC-CPU 及uC-OS3 需要配置的文件集中到此文件夾

├── uC-CPU

├── uC-LIB

└── uC-OS3

5.2??構建Keil工程?

5.3 編譯驗證

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/42208.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/42208.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/42208.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Nginx配置文件全解:從入門到設計

Nginx配置文件全解&#xff1a;從入門到架構設計 1. Nginx配置文件基礎 Nginx的主配置文件通常位于/etc/nginx/nginx.conf?。配置文件使用簡單的文本格式&#xff0c;由指令和指令塊組成。 1.1 基本語法規則 每個指令以分號(;)結束指令塊用大括號({})包圍配置文件支持使用…

多方SQL計算場景下,如何達成雙方共識,確認多方計算作業的安全性

安全多方計算在SQL場景下的限制 隨著MPC、隱私計算等概念的流行&#xff0c; 諸多政府機構、金融企業開始考慮參與到多方計算的場景中&#xff0c; 擴展數據的應用價值。 以下面這個場景為例&#xff0c; 銀行可能希望獲取水電局和稅務局的數據&#xff0c;來綜合計算得到各…

DolphinScheduler-3.1.9 資源中心實踐

前言 目前DolphinScheduler最新的穩定版本是 3.1.9 &#xff0c;基于此做些探索&#xff0c;逐漸深化學習路徑&#xff0c;以便于加深理解。 3.2.1 是最新的版本。目前的穩定版本是 3.1.9 基礎環境&#xff1a;Hadoop3.3, Java 8, Python3, MacOS14.2.1 一、本地偽分布式安裝…

學習筆記——動態路由——IS-IS中間系統到中間系統(開銷)

四、IS-IS開銷 1、IS-IS 開銷簡介 在IS-IS協議剛面世時&#xff0c;互聯網網絡結構還非常簡單&#xff0c;因此IS-IS早期的版本中只使用了6bit來描述鏈路開銷&#xff0c;鏈路開銷的取值范圍是1-63。一條路由的開銷范圍只有10bit&#xff0c;取值范圍是0-1023。 隨著計…

前端實現無縫自動滾動動畫

1. 前言: 前端使用HTMLCSS實現一個無縫滾動的列表效果 示例圖: 2. 源碼 html部分源碼: <!--* Author: wangZhiyu <w3209605851163.com>* Date: 2024-07-05 23:33:20* LastEditTime: 2024-07-05 23:49:09* LastEditors: wangZhiyu <w3209605851163.com>* File…

【ubuntu】安裝(升級)顯卡驅動,黑屏|雙屏無法使用問題解決方法

every blog every motto: You can do more than you think. https://blog.csdn.net/weixin_39190382?typeblog 0. 前言 ubuntu 安裝(升級)顯卡驅動&#xff0c;黑屏|雙屏無法使用問題解決方法 由于項目需要&#xff0c;對顯卡驅動進行升級。升級完就黑屏。。。。&#xff0…

Fast R-CNN(論文閱讀)

論文名&#xff1a;Fast R-CNN 論文作者&#xff1a;Ross Girshick 期刊/會議名&#xff1a;ICCV 2015 發表時間&#xff1a;2015-9 ?論文地址&#xff1a;https://arxiv.org/pdf/1504.08083 源碼&#xff1a;https://github.com/rbgirshick/fast-rcnn 摘要 這篇論文提出了一…

WordPress禁止用戶注冊某些用戶名

不管在任何網站&#xff0c;用戶注冊時都有一個屏蔽非法關鍵詞&#xff0c;就是禁止注冊某些用戶名&#xff0c;原因是因為防止用戶使用一些特定的用戶名&#xff0c;例如管理員、官方等用戶名&#xff0c;還有就是那些攻擊性的詞語了。 加網站添加了屏蔽非法關鍵詞&#xff0…

BAT-致敬精簡

什么是bat bat是windows的批處理程序&#xff0c;可以批量完成一些操作&#xff0c;方便快速。 往往我們可以出通過 winR鍵來打開指令窗口&#xff0c;這里輸入的就是bat指令 這里就是bat界面 節約時間就是珍愛生命--你能想象以下2分鐘的操作&#xff0c;bat只需要1秒鐘 我…

考慮數據庫粒度的設計-提升效率

目錄 概要 場景 設計思路 小結 概要 公開的資料顯示&#xff0c;數據庫粒度是&#xff1a;“在數據庫領域&#xff0c;特別是數據倉庫的設計中&#xff0c;粒度是一個核心概念&#xff0c;它直接影響到數據分析的準確性和存儲效率。粒度的設定涉及到數據的詳細程度和精度&…

【JVM基礎篇】Java的四種垃圾回收算法介紹

文章目錄 垃圾回收算法垃圾回收算法的歷史和分類垃圾回收算法的評價標準標記清除算法優缺點 復制算法優缺點 標記整理算法&#xff08;標記壓縮算法&#xff09;優缺點 分代垃圾回收算法&#xff08;常用&#xff09;JVM參數設置使用Arthas查看內存分區垃圾回收執行流程分代GC算…

【SpringBoot】IDEA查看spring bean的依賴關系

前因&#xff1a;在研究springcloud config組件時&#xff0c;我發現config-server包下的EnvironmentController可以響應客戶端的請求&#xff0c;但EnvironmentController并不在啟動類所在的包路徑下&#xff0c;所以我推測它是作為某個Bean方法在生效&#xff0c;尋找bean的依…

vue-router 源碼分析——9.別名

這是對vue-router 3 版本的源碼分析。 本次分析會按以下方法進行&#xff1a; 按官網的使用文檔順序&#xff0c;圍繞著某一功能點進行分析。這樣不僅能學習優秀的項目源碼&#xff0c;更能加深對項目的某個功能是如何實現的理解。這個對自己的技能提升&#xff0c;甚至面試時…

DAY1: 實習前期準備

文章目錄 VS Code安裝的插件C/CCMakeGitHub CopilotRemote-SSH收獲 VS Code 下載鏈接&#xff1a;https://code.visualstudio.com 安裝的插件 C/C 是什么&#xff1a;C/C IntelliSense, debugging, and code browsing. 為什么&#xff1a;初步了解如何在VS Code里使用C輸出…

https創建證書

需要下載httpd模塊&#xff1a;yum install httpd -y 前提需要先搭建一個虛擬主機來測試證書創建的效果&#xff0c;以下面www.hehe.com為例&#xff0c;可以參考創建&#xff1a; [rootlocalhost conf.d]# vim vhost.conf <directory /www> allowoverride none requi…

關于小愛同學自定義指令執行

1.前言 之前買了小愛同學音響&#xff0c;一直想讓其讓我的生活變得更智能&#xff0c;編寫一些程序來完成一些自動化任務&#xff0c;但是經過搜索發現&#xff0c;官方開發者平臺不能用了&#xff0c;尋找api階段浪費了我很長時間。最后在github 開源項目發現了倆個比較關鍵…

13.SQL注入-寬字節

SQL注入-寬字節 含義&#xff1a; MySQL是用的PHP語言&#xff0c;然后PHP有addslashes()等函數&#xff0c;這類函數會自動過濾 ’ ‘’ null 等這些敏感字符&#xff0c;將它們轉義成’ ‘’ \null&#xff1b;然后寬字節字符集比如GBK它會自動把兩個字節的字符識別為一個漢…

內容營銷專家劉鑫煒:網站排名需考慮哪些SEO優化技巧?

網站排名的SEO優化技巧包括&#xff1a; 1. 關鍵詞研究&#xff1a;了解目標受眾的搜索關鍵詞&#xff0c;將這些關鍵詞合理地應用在網站的標題、描述、正文和標簽中&#xff0c;有助于提高網站排名。 2. 內容優化&#xff1a;創建高質量、有價值的內容&#xff0c;可以吸引搜…

Qt源碼解析之QObject

省去大部分virtual和public方法后&#xff0c;Qobject主要剩下以下成員&#xff1a; //qobject.h class Q_CORE_EXPORT Qobject{Q_OBJECTQ_PROPERTY(QString objectName READ objectName WRITE setObjectName NOTIFY objectNameChanged)Q_DECLARE_PRIVATE(QObject) public:Q_I…

STM32-OC輸出比較和PWM

本內容基于江協科技STM32視頻內容&#xff0c;整理而得。 文章目錄 1. OC輸出比較和PWM1.1 OC輸出比較1.2 PWM&#xff08;脈沖寬度調制&#xff09;1.3 輸出比較通道&#xff08;高級&#xff09;1.4 輸出比較通道&#xff08;通用&#xff09;1.5 輸出比較模式1.6 PWM基本結…