1. 程式人生 > >STM32 C++ 底層封裝的嘗試[1]

STM32 C++ 底層封裝的嘗試[1]

現在在伊頓公司實習,用的是freescale的mpc563處理器。開發流程大致是:應用層在Matlab建模,然後通過matlab的code generation自動生成程式碼,得到應用層的*.cpp和*.h檔案。然後手打底層程式碼,同樣是*.h和*.cpp檔案。然後寫Makefile,matlab掉指令碼,gmake下調wind river的diab編譯器,編譯出*.32b檔案。就相當於微控制器的*.hex檔案。然後download到控制器裡去。

然後學長創業的公司,用的dsp28335,也是全部用c++。

因此意識到c++在底層也是有一定的應用前景的。

因而就有了封裝stm32底層驅動類的想法。

大致的構思是:

保留stm32原有的官方C語言庫。在C語言庫基礎上,將一些1初始化工作 2一些不常修改的配置 3一些需要查手冊的配置都封裝到庫裡。下面細講。

1、初始化工作。STM32的外設的初始化非常類似。大部分都是:使能時鐘,配置IO口,配置外設對應的功能。選擇是否開中斷和DMA。

2、不常修改的配置。比如串列埠通訊,資料長度基本都是8,停止位1,無校驗位。大部分時候波特率都在115200。因此把這些都設定為預設引數。在初始化時將省去大量工作

3、需要查手冊的配置。還是串列埠通訊,比如TX1 RX1 基本都用PA9 PA10, 定時器選定了通道就選定了IO口,每次查手冊效率低。直接封裝到類裡邊,雖然耗flash,初始化時多佔點時間,但是開發效率高。

其實優劣無所謂,主要還是想練練手,也能儘快讀懂公司的底層的程式碼的實現。

現在實現的架構如下:

1、對於除中斷和DMA的外設,都由基類CPeriph派生來。CPeriph包含了建構函式,外設的初始化函式,DMA 和中斷的指標。

2、對於所有中斷,即INTE,都由CInte_Base派生來。CInte_Base的本質是NVIC_IRQChannel_。即這個中斷類是針對哪條中斷線的。其次還包含了一個NvicConfig()函式。對於所有的外設的cpp檔案,還應派生出一個對應的針對該類的CInte_Periph。裡面包含該外設自己特有的中斷配置函式。

3、對於所有DMA,都由CDma_Base派生來。CDma_Base的本質是DMAy_Channelx_,即DMA通道。與INTE不同的地方在於:對於一個外設,比如串列埠,USART1,它只可能有一條中斷線,但有可能有多個DMA通道,比如Txd通道和Rxd通道。因此我們需要可變數量的DMA物件(可變長度:連結串列),並且可以根據需要操作改物件(類似map的key和item)。因此,在CPeriph.cpp檔案,還封裝了一個類,叫做CDmaKit。 Kit類的命名來自伊頓HCM底層資料結構的命名,原理上和map類似,即輸入一個列舉變數key(DMA通道),返回一個物件的引用item(DMA類)。而Kit是基於雙向連結串列的,加入一個節點時,即add(key, item)。按照C++ stl 的做法,理論上map的搜尋是通過紅黑二叉樹實現的,在stm32裡重寫一個對我來說太難了。按照伊頓HCM的做法,Kit尋找一個item是通過遍歷連結串列,匹配Key來實現的。重寫一個難度不大。因此參照伊頓的程式碼寫了一個CDmaKit。大致的操作就是DMA.add(key, item)新增一個DMA通道。 然後DMA.handle(key), 返回Key所對應的DMA通道的物件,可以進行該DMA通道重啟等操作。而Key為外設的DMA通道列舉值,比如對USART,分別為TXD和RXD,這兩個列舉量在CUsart中定義。那麼此時可以看到CDmaKit是模板類Kit<T>繼承而來的。這個T表示Kit中的item的資料型別。那麼如果對於串列埠,即應該是CDma_Usart,若是定時器,則是CDma_Timer。因此在每個外設的cpp檔案下,還需要有一個繼承自CDma_Base的CDma_Periph類。

這裡插入解釋一下,為什麼外設的建構函式的初始化函式要分開:

由於外設的類例項化之後,通常要作為全域性變數。比如:串列埠COM1,我在main函式中要用COM1.printf(),在中斷函式中也要COM1.printf()。因此COM1必然是要作為全域性變數的。那麼全域性變數的宣告就必須在Main函式之外了。要知道在main函式之外的全域性變數,如果在不同的cpp檔案,其建構函式的執行順序是不可控的。如果我們在建構函式裡進行了很多重要的比如指標的操作,需要限定某幾個類的順序,那這樣將是無法實現的(因為順序不可控,可能出現指標指飛)。因此,這裡的實現是在建構函式裡做一些簡單的變數的初始化。主要的外設的初始化工作放在init()函式裡進行操作。而init()函式統一在main函式一開始執行。

此外,DMA和中斷為什麼使用指標:

由於並不是每個外設都要開啟中斷或者DMA,但是作為一個類,一既然要包含這個成員,那麼所有例項化物件都會有這個成員。為了突出DMA和INTE這兩個功能的選擇行,我選擇以指標的形式來實現。即如果需要開啟INTE,則在棧上new一個INTE出來使用。

相關推薦

STM32 C++ 底層封裝嘗試[1]

現在在伊頓公司實習,用的是freescale的mpc563處理器。開發流程大致是:應用層在Matlab建模,然後通過matlab的code generation自動生成程式碼,得到應用層的*.cpp和*.h檔案。然後手打底層程式碼,同樣是*.h和*.cpp檔案。然後寫Mak

STM32上實現NTFS之4:GPT分區表的C語言實現(1):主GPT表頭的實現

center mbr分區 sum 對齊 字節數 決定 容器 alt 水平 題外話:在荒廢了很久沒有更新之後……某日突然收到讀者的站內信!內容大體是詢問GPT分區表信息的讀取方式,筆者激動萬分之下,決定繼續解剖NTFS……其實GPT嚴格上不算是NTFS的內容, GPT和M

faster_rcnn c++版本的 caffe 封裝1

由於需要把FasterRCNN做的工程化,因此這裡需要對Caffe進行封裝。其實封裝聽起來感覺很高深的樣子,其實就是將自己在caffe上再呼叫的介面做成一個動態庫,同時將Caffe的庫連著Caffe的那些庫依賴一起做成自己工程的庫依賴就可以了。如果你只是直接使用Caffe的話,那麼到時候直接連結到caffe

C++發哥筆記(1):class的分離式寫法

頭文件 clu cpp obj inline this ++ 大括號 如果 把class的成員函數的定義寫在class之外,即class的大括號的外面。 例如, /////////// main.cpp //////////// class Object {   publi

c# mvc 封裝返回對象

color ttr pan wget trace led lob trac class 將所有返回JsonContent對象進行再次封裝 public class ResultFilterAttribute : System.Web.Mvc.ActionFilterAtt

c++ 函數(1

row 引用傳參 修飾 尋址 概念 pan 但是 clu 過去 函數中,數組如何傳參? 整個數組傳過去是不可以的。自然聯想到指針和引用。 因為數組指針本質上就是多重指針,所以以下三種傳參方式都是可以的: void print(const int*); v

C# SQL封裝(二)

c# sql封裝(二)接 C# SQL封裝(一)開始操作數據庫的測試 :using System;using System.Collections.Generic;using System.Linq;using System.Text;using DBDome.com;using DBDome.model;u

C# SQL封裝(一)

c# sql封裝(一)感謝軟謀徐老師的SQLHelper.as , 代碼如下(本人有所改動):using System; using System.Collections; using System.Collections.Generic; using System.Configuration; using

C/C++復習筆記(1)

href lis 優先級 轉換成 mar 符號 都是 排版 space 這是一篇針對學習《程序員面試寶典》過程中的筆記,這本書的質量先不去考量,他其中確實涉及了不少雖然編程過程中一般用不到但確實是有必要註意的東西,而且又是各個企業的歷史真題,總有值得學習的東西。 也算臨時

C程序設計語言1-9

color 設計 div 一個 urn etc col 輸入 空格 編寫一個將輸入復制到輸出的程序,並將其中連續的多個空格用一個空格代替。 #include <stdio.h> int main() { int c, k = 1; while

改善C#程序的建議1:非用ICloneable不可的理由

沒有 class 指正 -- height serial sha color opened 原文:改善C#程序的建議1:非用ICloneable不可的理由好吧,我承認,這是一個反標題,實際的情況是:我找不到一個非用ICloneable不可的理由。事實上,接口ICloneab

c#進階(1)—— Task Parallel Library 並行執行與串行執行

-128 serve 模擬 程序 www 操作 內存 兩個 1-1 本文參考的博文出處:http://www.cnblogs.com/stoneniqiu/p/4857021.html 總體說明: (1)、理解硬件線程和軟件線程   硬件線程也稱為邏輯內核,一個物理內核可以

CUDA C編程——NO.1

int ati perf images htm graph nes 語言 ram CUDA C編程 啥玩意是CUDA? CUDA? is a parallel computing platform and programming model invented by NVI

C語言小題1

輸入數據為一個數組的下標有一組特殊的數列a1,a2,...,其定義如下:a1=1,a2=2,...,a(n)=2*a(n-1)+a(n-2)。求第k個數項的值。要求:第一行是測試數據的組數,後面跟著n行輸入,每組測試數據占1行,包括一個正整數k(1<=k<1000000)。#include<

通過C學Python(1)關於語言、數值類型和變量

而在 有一種 float char 有用 運行時 復數運算 單獨的數 數值類型 強類型語言,不可能出現“程序執行出錯後仍可繼續執行,並且該錯誤導致的問題使後續執行可能出現任意行為”這類錯誤,這類錯誤的例子,如C裏的緩沖區溢出、Jump到錯誤地址。 弱類型語言,類型檢查更不嚴

C++復習】1.1基本概念

using arr 消息 開始 函數返回 執行函數 c++程序 不能 定義 1、C++對大小寫敏感; 2、查看運行結果 cin.get(); cin.get(); 使用兩行代碼使程序運行後暫停,而不是立即結束,出現閃退效果。 第一條cin.get()語句是在輸入並按En

C# CEF 封裝UserControl

nbsp des web bbr ring local log fse ngs using System; using System.Collections.Generic; using System.ComponentModel; using System.Dr

[0311]C++簡單程序設計-1

() 插入 mage enter eve 列表 課程 參考 表達式 南京信息工程大學實驗報告 實驗名稱 C++簡單程序設計-1 實驗日期 2018-3-13 得分 指導教師 耿學華 系 計軟院 專業 計嵌+軟嵌 年級 2017 級 班次 (1) 姓名 施昊陽 學號 2016

Ojective-C學習筆記(1

png 蘋果電腦 copyright 準備 開發 代碼 com 版本號 img 工欲善其事必先利其器,想要學習iOS開發,必須要有一些必要的設備才行。 準備工作: 一臺蘋果電腦,系統版本號10.13.4。安裝Xcode軟件,版本號9.3。以及一部蘋果手機。一切都準備好了,開

NetCore+Dapper WbpApi架構搭建(二):底層封裝

isnull lis sel .sql click defaults cts 數據庫 redis 看下我們上一節搭建的架構,現在開始從事底層的封裝 1、首先需要一個實體的接口IEntity 1 namespace Dinner.Dapper 2 { 3