MDK中用C++開發STM32

来源:https://www.cnblogs.com/conscience-remain/archive/2020/05/07/12841096.html
-Advertisement-
Play Games

​作者:良知猶存 轉載授權以及圍觀:歡迎添加微信:Allen-Iverson-me-LYN 前言 最近想開發一段單片機的代碼,代碼本身有很多的重覆元素,這重覆定義的一些結構體使用起來有些繁瑣,所以就想用C++開發,C++的繼承 模板類可以很容易的解決這些問題。因為在單片機運行,習慣用MDK或者IAR ...


​作者:良知猶存

轉載授權以及圍觀:歡迎添加微信:Allen-Iverson-me-LYN

前言

    最近想開發一段單片機的代碼,代碼本身有很多的重覆元素,這重覆定義的一些結構體使用起來有些繁瑣,所以就想用C++開發,C++的繼承 模板類可以很容易的解決這些問題。因為在單片機運行,習慣用MDK或者IAR這些軟體。但是這些軟體都是預設C開發的,用C++開發需要重新配置,有些麻煩。但是我還是試了試,做了一個小demo供大家參考。

代碼文件我傳到我的github中去了,大家有興趣可以參考一下

https://github.com/conscience-still/MDK-Cplusplus--LED

一、STM32CubeMX生成底層代碼

    因為是做一個demo,不需要很複雜,就用cubemx生成了一個簡單的串口和IO控制的MDK代碼,用了精簡的LL庫,具體實現就不講了,詳細操作可以看我博客CubeMX配置的一些文章。我的博客名是:良知猶存

 

二、進行IDE的C++配置(去掉C環境的配置)

1.首先打開MDK軟體,去掉use microlib 勾選,這個一個C的依賴庫,但比標準的庫小,它可以減少C代碼的大小。CubeMX生成的文件預設選擇此項。因為這個精簡庫不支持C++,所以我們需要去掉此項功能。

2.Options for Target 再點C/C++  在下邊的Misc Controls 中輸入—cpp

 

3.去掉C99 mode選項

三、代碼中C++的編寫註意

   1. IDE中的編譯器的這個工程時候,當文件尾碼是C的時候IDE會使用C編譯器進行編譯,如果文件尾碼是CPP則IDE使用C++編譯器進行編譯,工程包含的頭文件是使用C++編譯器進行編譯的,不過頭文件聲明的還是C文件的符號,所以IDE會無法正確編譯鏈接。此時我們應該將頭文件所有聲明C符號的部分用預編譯巨集加extern "C" { }的形式包含起來,告訴編譯器該段要使用C編譯器進行編譯。只包含需要進行C編譯的部分即可

#ifndef __MAIN_H#define __MAIN_H#ifdef __cplusplusextern "C" {#endif/* Includes ------------------------------------------------------------------*/#include "stm32f0xx_ll_crs.h"#include "stm32f0xx_ll_rcc.h"#include "stm32f0xx_ll_bus.h"#include "stm32f0xx_ll_system.h"#include "stm32f0xx_ll_exti.h"#include "stm32f0xx_ll_cortex.h"#include "stm32f0xx_ll_utils.h"#include "stm32f0xx_ll_pwr.h"#include "stm32f0xx_ll_dma.h"#include "stm32f0xx_ll_usart.h"#include "stm32f0xx_ll_gpio.h"#ifdef __cplusplus}#endif

 2.設置需要C++編譯的文件,這時候有兩種方法實現。

   1>.在代碼文件的界面,選擇文件右擊選擇Option for Files "你點擊的文件",然後設置file type為需要的C++

   2>.直接將文件改為.cpp文件,重新添加,此時候IDE自動進行C++編譯

 

第二種方法簡單快捷,但是第一種方法雖然麻煩,但是有個好處,我們不需要修改文件名稱,這樣STM32CubeMX下一次生成代碼就不會在生成相應名稱的C代碼了。

 

 3.將中斷服務函數添加 extern "C" 的標識,因為C++中無法直接識別中斷函數,所以用C的方法進行設備編譯。而在Cpp文件中引入C的部分代碼,需要進行extern "C" { }進行修飾,否則不能通過編譯鏈接。

 

四、C++實現時候遇到的情況

​   1.寫了個類沒有註意到寫成了虛函數,其他處也沒有繼承定義這個虛函數,導致編譯錯誤,為什麼把這個問題寫出來呢,就是因為MDK中C++的報錯沒怎麼遇到過,我查了挺長時間,才發現這個問題的。

 

c++test\c++test.axf: Error: L6218E:Undefined symbol vtable for STM32_TEST::TestGPIO (referred from main.o). 

把類中的虛函數改為定義好的函數即可。

 

2.因為我把串口初始化都放在類中實現,我想進行類的構造的時候進行串口數據的列印,但是網上查詢得知,MDK不支持std的流列印輸出,所以我就用sub和super補丁函數,進行系統main函數執行前進行串口的初始化。

 

這是一種特殊模式:用於有一個已經存在且不能被改變的函數 的情況。使用這兩個模式可以幫原函數打補丁。如存在一個函數foo();

 

$Sub$ $foo :定義的新功能函數,在foo()函數之前/後使用$Sub$$foo 可以添加一些新的程式代碼。

 

$Super$ $foo :就是原始的未修補的foo函數,使用這個$Super$ $foo函數將直接跳轉到foo()函數。


具體教程可以看ARM官網的資料學習哈,http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0377g/pge1362065967698.html。

因為super與sub函數屬於c所以我們在cpp文件下需要添加extern“C”進行編譯才行,否則就要出現如下問題了,這些我都遇到過,給大家把雷趟了一遍。

 

 


3.最後的一個bug,STDIO的初始化。

本來一個簡單的C++程式就寫完了,主要就是運行環境,但是程式收錄進去之後無法工作,並且在硬體調試下明顯看到系統到了__main之後不知道跑哪裡去了,F5全速執行幾次程式才有機會正常運行,這就很奇怪了,後來在網上找資料,終於找到問題所在了,在以為博主的文章看到,他最後找到問題原來是:

事實上本人也找了近兩天的時間才找到解決辦法,一開始認為是heap和stack沒有初始化好,嘗試了好久均未成功,後來在網上得到啟發,這個問題是出在STDIO初始化上。

如果要使用C/C++標準庫就要對其STDIO進行Retarget的,很簡單,但卻是非常關鍵的一步,就是這麼一回事啦。

我按照他的操作然後程式就可以正常運行了,下載ARM官方的retarget文件,並加入到工程當中。下載鏈接:

http://infocenter.arm.com/help/topic/com.arm.doc.faqs/attached/3844/retarget.c

 

然後將裡面的串口讀寫按照我現有的硬體需求進行重寫就可以了。如下代碼所示:

char UART_read(void);void UART_write(char ch);    char UART_read(void){  return 0;}void UART_write(char ch){  while(!(USART2->ISR & USART_ISR_TXE)){};   USART2->TDR = ch;}

五、最後測試的一些體驗與感想

​  

    剛開始想用C++在MDK中開發是因為,有些個需求的功能C++特別符合,但是在調試這個demo過程中,發現使用的單片機容量太小,一個<iostream>頭文件的包含就讓一個只有串口加幾組IO控制的最小程式代碼膨脹到了32K,而去掉該頭文件,代碼縮小到了5K。

 

    代碼過大是c++的依賴項過多,而C++ 中模板類 、虛擬繼承 、STL庫等精華由於依賴的問題都不建議在單片機中用,代碼膨脹的時候單片機吃不住。所以C++雖好,可不一定適合小容量的單片機,大家需要按照自己的功能進行有效的使用C++,精簡使用的依賴,這個可以通過每次編譯的生成的.map文件進行增該刪,其次對於C++中記憶體以及代碼擴增一些基礎知識需要熟悉,負責很容易代碼膨脹,導致我們的程式無法在單片機使用。

 

 這就是我分享的在MDK用C++開發的demo,裡面代碼是實踐過的,如果大家有什麼更好的思路,歡迎分享交流哈。

更多分享,掃碼關註我

微信:Allen-Iverson-me-LYN


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 環境和工具 服務端電腦IP:192.168.1.130 客戶端電腦IP:192.168.1.120 1、在服務端電腦運行 "IoTClientTool" 2、運行 "Wireshark" 3、在客戶端電腦運行 "IoTClientTool" 4、Wireshark得到如下報文 報文分析,plc的連接 ...
  • 一次HTTP請求,就是一次標準IO操作。請求是I,是輸入;響應式O,是輸出。任何web開發框架,其實都是在乾這兩件事: + 接受請求併進行解析獲取參數 + 根據參數進行渲染並輸出響應內容 所以我們學習一個框架,我認為最首要的是知道如何從請求中獲取參數。http請求攜帶參數的地方主要有下麵幾個地方: ...
  • Ansible Tests 詳解與使用案例 主機規劃 添加用戶賬號 說明: 1、 運維人員使用的登錄賬號; 2、 所有的業務都放在 /app/ 下「yun用戶的家目錄」,避免業務數據亂放; 3、 該用戶也被 ansible 使用,因為幾乎所有的生產環境都是禁止 root 遠程登錄的(因此該 yun ...
  • 應用系統分散式構建運維 1+x初級,項目四 部署主從資料庫 基礎環境安裝 準備兩台主機 修改主機名 # hostnamectl set-hostname mysql1 # hostnamectl set-hostname mysql2 關閉防火牆及SELinux服務(兩個節點) # setenfor ...
  • nginx實際把http請求處理流程劃分為了11個階段,這樣劃分的原因是將請求的執行邏輯細分,以模塊為單位進行處理,各個階段可以包含任意多個http模塊並以流水線的方式處理請求。這樣做的好處是使處理過程更加靈活、降低耦合度。可以讓每個HTTP模塊可以僅僅專註於完成一個獨立,簡單的功能。而一個請求的完 ...
  • 安裝:yum install firewalld 1、firewalld的基本使用 啟動: systemctl start firewalld 查看狀態: systemctl status firewalld 禁用,禁止開機啟動: systemctl disable firewalld 停止運行: ...
  • [TOC] 前言 1.備份數據的意義 運維工作的核心簡單概括起來就是兩件事:第一個是保護公司的數據,第二個是讓網站能夠7 24小時提供服務。 雖然這兩件事情都很重要,但是相比較而言,丟失一部分數據和讓網站7 24小時提供服務,哪個更重要呢? 對於絕大多數企業來講,失去數據就相當於失去商機,失去產品, ...
  • 虛擬機 下安裝tools tools安裝後桌面會全屏,自適應屏幕 環境準備 虛擬機 "安裝虛擬機教程" linux系統 "ubuntu下載地址" 1. 虛擬機中點擊》虛擬機》安裝tool 2. 打開終端命令視窗(快捷鍵ctrl+alt+t) 3. 輸入su 擁有超級用戶的許可權(提示:第一次打開是沒有 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...