Keil開發STM32單片機項目的三種方式

? ? STM32單片機相比51單片機,內部結構復雜很多,因此直接對底層寄存器編碼,相對復雜,這個需要我們了解芯片手冊,對于復雜項目,這些操作可能需要反復編寫,因此出現了標準庫的方式,對寄存器操作進行了封裝,操作相對簡單。隨著項目復雜度提升,又出現了封裝更厲害的一種庫HAL,這個需要借助STM32CubeMx工具來生成代碼。

? ? 簡單來說,STM32編碼有三種方式:

? ? 1、寄存器編碼。

? ? 2、標準庫操作編碼。

? ? 3、HAL庫操作編碼。

? ? 這三種方式各有優劣勢,寄存器編碼更偏向底層,方便我們熟悉單片機內部結構,開發效率相對較低,因為很多初始化,賦值操作需要反復編寫,使用HAL庫,可以減少大量代碼,提高了開發效率,但是不便于理解底層邏輯,需要非常熟練STM32單片機工作邏輯之后才好上手。

? ? 第一種寄存器編碼方式,構建項目可以直接新建一個普通項目,如下所示:

?

? ? 項目新建之后,什么也沒有,我們需要手動添加一個啟動文件和一個main.c文件到工程目錄:

?

? ? 我們在keil工具里面,通過添加現有項的方式將這兩個文件加到Source Group 1?中,如下所示:

? ? ?這個時候,編譯會報錯:

? ? 說是SystemInit符號未定義,其實是我們構建的項目代碼里面(main.c)中缺少SystemInit()方法,添加上就可以了。

? ? 這個項目只有兩個文件,一個是啟動文件,一個是主程序main.c。我們操作寄存器的代碼就在main.c中編寫,這里給出一個簡單的實現LED燈閃爍的示例代碼:

#define PERIPH_BASE ((unsigned int)0x40000000)
#define APB2PERIPH_BASE (PERIPH_BASE+ 0x10000)
#define GPIOA_BASE (APB2PERIPH_BASE+0x0800)
#define GPIOB_BASE (APB2PERIPH_BASE+0x0C00)
#define GPIOC_BASE (APB2PERIPH_BASE+0x1000)
#define GPIOD_BASE (APB2PERIPH_BASE+0x1400)
#define GPIOE_BASE (APB2PERIPH_BASE+0x1800)
#define GPIOF_BASE (APB2PERIPH_BASE+0x1C00)
#define GPIOG_BASE (APB2PERIPH_BASE+0x2000)#define GPIOA_ODR_Addr (GPIOA_BASE+12)
#define GPIOB_ODR_Addr (GPIOB_BASE+12)
#define GPIOC_ODR_Addr (GPIOC_BASE+12)
#define GPIOD_ODR_Addr (GPIOD_BASE+12)
#define GPIOE_ODR_Addr (GPIOE_BASE+12)
#define GPIOF_ODR_Addr (GPIOF_BASE+12)
#define GPIOG_ODR_Addr (GPIOG_BASE+12)#define BITBAND(addr,bitnum) ((addr & 0xF0000000) + 0x2000000 + ((addr&0xFFFFF)<<5) + (bitnum<<2))
#define MEM_ADDR(addr) *((volatile unsigned long *)(addr))
#define LED0 MEM_ADDR(BITBAND(GPIOA_ODR_Addr, 5))typedef struct
{volatile unsigned int CR;volatile unsigned int CFGR;volatile unsigned int CIR;volatile unsigned int APB2RSTR;volatile unsigned int APB1RSTR;volatile unsigned int AHBENR;volatile unsigned int APB2ENR;volatile unsigned int APB1ENR;volatile unsigned int BDCR;volatile unsigned int CSR;
}RCC_TypeDef;#define RCC ((RCC_TypeDef*)0x40021000)typedef struct
{volatile unsigned int CRL;volatile unsigned int CRH;volatile unsigned int IDR;volatile unsigned int ODR;volatile unsigned int BSRR;volatile unsigned int BRR;volatile unsigned int LCKR;
}GPIO_TypeDef;#define GPIOA ((GPIO_TypeDef*)GPIOA_BASE)void LEDInit(void)
{RCC->APB2ENR|=1<<2;GPIOA->CRL &= 0xFF0FFFFF;GPIOA->CRL |= 0x00300000;
}void Delay_ms(volatile unsigned int t)
{unsigned int i,j;for(j=0;j<t;j++)for(i=0;i<800;i++);
}void SystemInit(void)
{}int main(void)
{LEDInit();while(1){LED0 = 0;Delay_ms(500);LED0 = 1;Delay_ms(500);}
}

? ? 項目構建成功,不報錯就可以進行仿真,或者下載到單片機調試。

? ? 第二種方式,直接在Keil工具中構建STM32標準庫工程,不用額外拷貝標準庫文件到項目文件夾,然后添加現有項的方式加入組中,構建項目,選擇芯片系列之后,在彈出確認框這里可以選擇需要的庫:

? ? 這里勾選CMSIS->CORE,?Device->Startup , Device->StdPeriph Drivers->Framework,GPIO,RCC幾項。

? ? 自動生成的代碼結構如下所示:

? ? 這里面除了main.c是手動添加的,其余的都是通過keil自動生成的,如果你做過手動添加標準庫,那么就會很熟悉這里面的一些文件,stm32f10x_gpio.c,stm32f10x_rcc.c,startup_stm32f10x_ld.s,system_stm32f10x.c。

? ? 這里直接編譯會報錯:

? ? Error: L6218E: Undefined symbol assert_param (referred from misc.o).

? ? 這個問題是找不到assert_param這個函數,而這個函數是在stm32f10x_conf.h中,從上面的工程結構,我們看到代碼里面是有stm32f10x_conf.h這個頭文件的。解決辦法就是使用宏定義USE_STDPERIPH_DRIVER查找:

? ? 點擊魔法棒工具Options for?Targets,在彈出框中選擇c/c++,Define處輸入USE_STDPERIPH_DRIVER,Include Paths指定當前項目路徑下的RTE目錄即可。

? ? 最后可以編譯成功。

? ? 這里也給出一段讓LED閃爍的代碼。

#include "stm32f10x.h"void Delay()
{unsigned int i,j;for(i=0;i<1000;i++)for(j=0;j<1000;j++);
}void LED_Config()
{GPIO_InitTypeDef GPIO_InitStructure;                 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;      GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;             GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;     GPIO_Init(GPIOA, &GPIO_InitStructure);
}int main(void)
{LED_Config();while(1){GPIO_SetBits(GPIOA, GPIO_Pin_5);Delay();GPIO_ResetBits(GPIOA, GPIO_Pin_5);Delay();}
}

? ? PA5口作為電平輸出, 時鐘使能與GPIO初始化,都調用標準庫中的方法。

? ? 第三種構建STM32工程的方法需要借助STM32CubeMx工具,這個是免費的,安裝之后,可以圖形化界面操作,如下所示:

? ? 1)打開工具之后,新建工程,來到選擇芯片界面:

? ? 這里在Commecial Part Number這里輸入STM32F103會自動補全C6A,選中右側面板中的一個芯片雙擊,

? ?2)進入配置界面。

? ? 展開System Core菜單,默認選中SYS,我們點擊,在中間模式這里選擇Debug: Serial Wire。

? ? 然后,選中RCC

? ? 設置HSE/LSE為Crystal/Ceramic Resonator。改變之后,右側芯片會有變化。

? ? 接著,還要將芯片上的PA5端口作為GPIO_Output,點擊PA5,就會出現菜單選項,直接選擇即可。?

? ?3)工程位置及編譯工具設置

? ? 設置工程名,工程位置,Toolchain/IDE選擇MDK-ARM,版本選擇V5。

? ? 4)代碼生成。點擊GENERATE CODE按鈕。

? ? 5)生成的代碼,可以直接用Keil打開,結構如下:

?

? ? 連main.c都寫好了,直接編譯也沒有問題。我們要實現LED閃爍,只需要在while(1)循環體中增加如下代碼:

  while (1){/* USER CODE END WHILE */HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5, GPIO_PIN_RESET);HAL_Delay(200);HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5, GPIO_PIN_SET);HAL_Delay(200);/* USER CODE BEGIN 3 */}

? ? 這種方式生成的代碼,不僅幫我們做了很多工作,甚至連編譯準備都做好了,我們看看Options for Targets的c/c++選項:

?

? ?宏定義查找設置了,不用我們手動設置,另外編譯生成hex文件,也同樣幫我們勾選好了。

? ?使用HAL庫,自己編寫的代碼很少,但是理解起來需要花時間,默認操作做了什么,這里面隱含了哪些操作。? ?

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

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

相關文章

ES中倒排索引機制

在ES的倒排索引機制中有四個重要的名詞&#xff1a;Term、Term Dictionary、Term Index、Posting List。 Term&#xff08;詞條&#xff09;&#xff1a;詞條是索引里面最小的存儲和查詢單元。一段文本經過分析器分析以后就會輸出一串詞條。一般來說英文語境中詞條是一個單詞&a…

日期時間常用功能和函數

1 time 模塊 time 模塊提供了很多與時間相關的類和函數&#xff0c;下面我們介紹一些常用的。 1.1 struct_time 類 time 模塊的 struct_time 類代表一個時間對象&#xff0c;可以通過索引和屬性名訪問值。對應關系如下所示&#xff1a; 索引屬性值0tm_year&#xff08;年&a…

Docker容器與虛擬化技術:Docker資源控制、數據管理

目錄 一、理論 1.資源控制 2.Docker數據管理 二、實驗 1.Docker資源控制 2.Docker數據管理 三、問題 1.docker容器故障導致大量日志集滿&#xff0c;造成磁盤空間滿 2、當日志占滿之后如何處理 四、總結 一、理論 1.資源控制 (1) CPU 資源控制 cgroups&#xff0…

Java Vue Uniapp MES生產執行管理系統

本MES系統是一款B/S結構、通用的生產執行管理系統&#xff0c;功能強大&#xff01; 系統基于多年離散智造行業的業務經驗組建&#xff0c;主要目的是為國內離散制造業的中小企業提供一個專業化、通用性、低成本的MES系統解決方案。 聯系作者獲取

Linux(進程控制)

進程控制 進程創建fork函數初識fork函數返回值寫時拷貝fork常規用法fork調用失敗的原因 進程終止進程退出碼進程常見退出方法 進程等待進程等待必要性獲取子進程status進程等待的方法 阻塞等待與非阻塞等待阻塞等待非阻塞等待 進程替換替換原理替換函數函數解釋命名理解 做一個…

re學習(32)【綠城杯2021】babyvxworks(淺談花指令)

鏈接&#xff1a;https://pan.baidu.com/s/1msA5EY_7hoYGBEema7nWwA 提取碼&#xff1a;b9xf wp:首先找不到main函數&#xff0c;然后尋找特殊字符串&#xff0c; 交叉引用 反匯編 主函數在sub_3D9當中&#xff0c;但是IDA分析錯了 分析錯誤后&#xff0c;刪除函數 創建函數 操…

【Linux】多線程1——線程概念與線程控制

文章目錄 1. 線程概念什么是線程Linux中的線程線程的優點線程的缺點線程的獨立資源和共享資源 2. 線程控制Linux的pthread庫用戶級線程 &#x1f4dd; 個人主頁 &#xff1a;超人不會飛)&#x1f4d1; 本文收錄專欄&#xff1a;《Linux》&#x1f4ad; 如果本文對您有幫助&…

無腦入門pytorch系列(三)—— nn.Linear

本系列教程適用于沒有任何pytorch的同學&#xff08;簡單的python語法還是要的&#xff09;&#xff0c;從代碼的表層出發挖掘代碼的深層含義&#xff0c;理解具體的意思和內涵。pytorch的很多函數看著非常簡單&#xff0c;但是其中包含了很多內容&#xff0c;不了解其中的意思…

SpringBoot復習:(46)全局的bean懶加載是怎么實現的?

在application.properties中配置&#xff1a; spring.main.lazy-initializationtrue在運行SpringApplication的run方法時&#xff0c;代碼如下&#xff1a; 其中調用了prepareContext,prepareContext代碼如下&#xff1a; 當在配置文件中配置了spring.main.lazy-initializat…

JavaScript實現在線Excel的附件上傳與下載

摘要&#xff1a;本文由葡萄城技術團隊于CSDN原創并首發。轉載請注明出處&#xff1a;葡萄城官網&#xff0c;葡萄城為開發者提供專業的開發工具、解決方案和服務&#xff0c;賦能開發者。 前言 在本地使用Excel時&#xff0c;經常會有需要在Excel中添加一些附件文件的需求&am…

Clickhouse基于文件復制寫入

背景 目前clickhouse社區對于數據的寫入主要基于文件本地表、分布式表方式為主&#xff0c;但缺乏大批量快速寫入場景下的數據寫入方式&#xff0c;本文提供了一種基于clickhouse local 客戶端工具分布式處理hdfs數據表文件&#xff0c;并將clickhouse以文件復制的方式完成寫入…

解決并發沖突:Java實現MySQL數據鎖定策略

在并發環境下&#xff0c;多個線程同時對MySQL數據庫進行讀寫操作可能會導致數據沖突和不一致的問題。為了解決這些并發沖突&#xff0c;我們可以采用數據鎖定策略來保證數據的一致性和完整性。下面將介紹如何使用Java實現MySQL數據鎖定策略&#xff0c;以及相關的注意事項和最…

開源低代碼平臺Openblocks

網友 HankMeng 想看低代碼工具&#xff0c;正好手上有一個&#xff1b; 什么是 Openblocks &#xff1f; Openblocks 是一個開發人員友好的開源低代碼平臺&#xff0c;可在幾分鐘內構建內部應用程序。 傳統上&#xff0c;構建內部應用程序需要復雜的前端和后端交互&#xff0c;…

如何保證微信小游戲存檔不丟失?

引言 微信小游戲的興起為玩家提供了一個輕松便捷的娛樂方式&#xff0c;然而&#xff0c;存檔丟失問題一直以來都是開發者和玩家關注的焦點。為了確保玩家的游戲體驗和投入能夠得到充分的保障&#xff0c;開發團隊需要采取一系列方法來保障微信小游戲存檔不丟失。本文將介紹一…

學習筆記十五:基于YUM文件運行POD應用

基于YUM文件運行POD應用 通過資源清單文件創建第一個Pod更新資源清單文件查看pod是否創建成功查看pod的ip和pod調度到哪個節點上假如pod里有多個容器&#xff0c;進入到pod里的指定容器查看pod詳細信息查看pod具有哪些標簽&#xff1a;刪除pod通過kubectl run創建Pod Pod資源清…

word之插入尾注+快速回到剛才編輯的地方

1-插入尾注 在編輯文檔時&#xff0c;經常需要對一段話插入一段描述或者附件鏈接等&#xff0c;使用腳注經常因占用篇幅較大導致文檔頁面內容雜亂&#xff0c;這事可以使用快捷鍵 ControlaltD 即可在 整個行文的末尾插入尾注&#xff0c;這樣文章整體干凈整潔&#xff0c;需…

【枚舉邊+MST+組合計數】CF1857G

Problem - 1857G - Codeforces 題意&#xff1a; 思路&#xff1a; 首先觀察一下樣例&#xff1a; 可以發現對于每一對點&#xff0c;貢獻是 s - 這對點對應的環的最大邊 1 那么這樣就有了 n^2 的做法 然后&#xff0c;根據慣用套路&#xff0c;枚舉樹上的點對問題可以轉…

Prometheus的搭建與使用

一、安裝Prometheus 官網下載地址&#xff1a;Download | Prometheus 解壓&#xff1a;tar -zxvf prometheus-2.19.2.linux-amd64.tar.gz重命名&#xff1a; mv prometheus-2.19.2.linux-amd64 /home/prometheus進入對應目錄&#xff1a; cd /home/prometheus查看配置文件&am…

淺析市面電商CRM系統|排單系統存在的不足

筆者做CRM尤其是電商CRM系統7年&#xff0c;相信我的分享能夠幫助大家對電商CRM有個清晰的認知。 系統本身是用來提升效率的&#xff0c;針對不少電商賣家或服務商&#xff0c;都有使用CRM系統來管理粉絲鏈接與營銷、銷售推廣等環節&#xff0c;來實現完整的CRM鏈路。尤其是在當…

OpenCV-Python中的圖像處理-傅里葉變換

OpenCV-Python中的圖像處理-傅里葉變換 傅里葉變換Numpy中的傅里葉變換Numpy中的傅里葉逆變換OpenCV中的傅里葉變換OpenCV中的傅里葉逆變換 DFT的性能優化不同濾波算子傅里葉變換對比 傅里葉變換 傅里葉變換經常被用來分析不同濾波器的頻率特性。我們可以使用 2D 離散傅里葉變…