ARTS 挑戰打卡的第8天 ---volatile 關鍵字在MCU中的作用,四個實例講解(Tips)

前言

(1)volatile 關鍵字作為嵌入式面試的常考點,很多人都不是很了解,或者說一知半解。
(2)可能有些人會說了,volatile 關鍵字不就是防止編譯器優化的嗎?有啥好詳細講解的?那么,我就反問一句,為什么要防止編譯器優化,編譯器優化什么?編譯器優化之后會產生什么問題?
(3)今天我就來詳細解答一下這些疑惑。

軟件延時所造成的bug

(1)在初學51單片機的時候,我們都是使用軟件延時,例如下面是STC89,12MHZ晶振的1ms的軟件延時。
(2)有些人說,這樣寫延時可以啊,沒有問題。但是,假如你在MSP430中這樣寫,一定會產生bug。你會發現,軟件延時沒效果。
(3)這個時候,有些人會告訴你,要讓CCS的編輯優化等級降低然后就可以了。
(4)這是為什么呢?如下代碼,編譯會發現,這就是讓兩個變量進行自減,于是編譯器自作主張,認為這是沒有意義的代碼,并且將其刪除。于是,你看匯編代碼會發現,這里沒有進行自減操作。
(5)但是,如果你加上volatile 關鍵字,就會發現,軟件延時能夠正常運行。這個是為什么呢?volatile 關鍵字會告訴編譯器,這個變量你沒有權限動,你不要擅自主張的進行優化。
(6)因此,我們可以知道,volatile 關鍵字其實就是告訴編譯器,不要對變量進行優化。

void Delay1ms()		//@12.000MHz
{unsigned char i, j;//加上volatile 關鍵字//volatile unsigned char i, j;i = 2;j = 239;do{while (--j);} while (--i);
}

外設寄存器被異步修改所產生的bug

(1)假設我們現在有一個外設寄存器叫做ExternalDevice ,這個寄存器會自動減少,地址為0x1000。(例如定時器的計數器就會自己增加或減少)
(2)現在我們要等ExternalDevice 寄存器值變成0的時候,再進行一些操作。
(3)但是你實際跑的時候會發現,這個地方要么無法阻塞,要么永遠阻塞。這是為什么呢?編譯器是不知道ExternalDevice這個變量是一個寄存器的,也不知道他最終是怎么變化的。所以他就會認為,這個地方是一個不變的變量進行反復判斷。他就會把while()這一行代碼刪除,認為是沒有意義的。
(4)于是我們需要加上volatile 告訴編譯器,這個東西你別動。

int main()
{//下面這三種寫法是等價的//int volatile *ExternalDevice = (uint8_t volatile *)0x1000;  //volatile int *ExternalDevice = (uint8_t volatile *)0x1000; //volatile int *ExternalDevice = (volatile uint8_t *)0x1000; int *ExternalDevice = (uint8_t *)0x1000;  // 假設外設寄存器的地址是 0x1000while(*ExternalDevice == 0); //等待這個外設寄存器的值變成0再進行操作
}

全局變量在中斷和正常運行的程序存在競爭問題

(1)比如群友給出一個這樣的代碼,發現一直無法實現點燈。感到非常的疑惑。
(2)這個地方就涉及到全局變量在中斷和正常運行的程序存在競爭問題。我們會發現,中斷程序和主函數里面都調用了全局變量a。但是,我們要知道,編譯器是無法知道運行態的情況的,他只能夠進行靜態優化
(3)比如這里,編譯器他會認為,變量a的賦值是0。然后主函數里面的while()判斷是判斷他是否為0。這個時候,他無法查看到串口中斷的情況,就會認為,你就是要進行一個死循環。所以,最終這個程序最終會卡死在while(a == 0);這里。
(4)因此我們要將a加上volatile 關鍵字。

在這里插入圖片描述

多線程共享變量

(1)當我們上了操作系統之后,都是會跑多線程的。
(2)但是跑多線程,就會存在一個問題,我們很可能會讓一個變量讓多個線程之間共享。例如,下面我們需要創建兩個線程,一個是GUI圖像顯示,一個是按鍵掃描。他們都需要共享要給變量key_num。這個時候,編譯器無法知道key_num什么時候會進行改變,所以他可能就會想,既然我不知道,我就不要他。所以,我們需要加上volatile 關鍵字,告訴編譯器,這里不要搞騷操作

uint8_t key_num;
//線程1
void GUI()
{while(1){switch(key_num){case key_short_down://...break;case key_long_down://...break;case key_up://...break;}}
}
//線程2
void key_scanf()
{while(1){if(key_Pin == HIGH) key_num = key_up;else if(key_time < 2000) key_num = key_short_down;else  key_num = key_short_down;}
}
void main()
{register_task(GUI);register_task(key_scanf);while(1);
}

總結

(1)volatile 關鍵字本質就是編譯器防止優化。但是我們也要明白,為什么編譯器會進行優化。知道這個以后,我們才能夠更好的使用volatile 關鍵字。

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

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

相關文章

HashMap底層相關內容

HashMap的底層結構&#xff1a; 1.7之前 數組加鏈表&#xff0c;當兩個值進行插入的時候 采用頭插法進行插入&#xff0c;可能會造成死循環 1.8之后 數組加鏈表/紅黑樹&#xff0c;當兩個值進行插入的時候&#xff0c;采用尾插法進行插入&#xff0c;不會造成死循環 HashMap底…

xml轉map工具類

背景&#xff1a;最近遇到接口返回是xml&#xff0c;所以需要整一個轉換的工具類&#xff0c;方便后續其他xml處理。 依賴引入&#xff1a; <dependency><groupId>dom4j</groupId><artifactId>dom4j</artifactId><version>1.1</versi…

澎峰科技|邀您關注2023 RISC-V中國峰會!

峰會概覽 2023 RISC-V中國峰會&#xff08;RISC-V Summit China 2023&#xff09;將于8月23日至25日在北京香格里拉飯店舉行。本屆峰會將以“RISC-V生態共建”為主題&#xff0c;結合當下全球新形勢&#xff0c;把握全球新時機&#xff0c;呈現RISC-V全球新觀點、新趨勢。 本…

linux下nginx配置https和反向代理本地端口

1 修改配置文件/etc/nginx/sites-enabled/default 在配置文件中增加一個server用來做https端口監聽&#xff0c; ssl_certificate和ssl_certificate_key修改為自己申請的https認證文件 server{listen 443 ssl;server_name www.dogrich.net;#root /var/www/html;# 上面配置的…

《3D 數學基礎》12 幾何圖元

目錄 1 表達圖元的方法 1.1 隱式表示法 1.2 參數表示 1.3 直接表示 2. 直線和射線 2.1 射線的不同表示法 2.1.1 兩點表示 2.1.2 參數表示 2.1.3 相互轉換 2.2 直線的不同表示法 2.2.1 隱式表示法 2.2.2 斜截式 2.2.3 相互轉換 3. 球 3.1 隱式表示 1 表達圖元的方…

C語言的使用技巧--在IO操作中的移位和快速配置

在WB32F103&#xff08;ARM cortex m3內核&#xff0c;96Mhz&#xff09;的gpio初始化中有一段代碼&#xff0c;充分的結合了硬件特征并使用C語言的技巧來快速的配置對應的GPIO的功能&#xff0c;堪稱經典和楷模&#xff0c;代碼異常簡潔&#xff0c;執行速度快&#xff0c;配置…

【深度學習所有損失函數】在 NumPy、TensorFlow 和 PyTorch 中實現(2/2)

一、說明 在本文中&#xff0c;討論了深度學習中使用的所有常見損失函數&#xff0c;并在NumPy&#xff0c;PyTorch和TensorFlow中實現了它們。 (二-五)見 六、稀疏分類交叉熵損失 稀疏分類交叉熵損失類似于分類交叉熵損失&#xff0c;但在真實標簽作為整數而不是獨熱編碼提…

Python pycparser(c文件解析)模塊使用教程

文章目錄 安裝 pycparser 模塊模塊開發者網址獲取抽象語法樹1. 需要導入的模塊2. 獲取 不關注預處理相關 c語言文件的抽象語法樹ast3. 獲取 預處理后的c語言文件的抽象語法樹ast 語法樹組成1. 數據類型定義 Typedef2. 類型聲明 TypeDecl3. 標識符類型 IdentifierType4. 變量聲明…

語聚AI公測發布,大語言模型時代下新的生產力工具

語聚AI 公測發布 距離語聚AI內測上線已經過去近1個月。 這期間&#xff0c;我們共邀請了近百位資深用戶與行業專家加入語聚AI產品體驗。通過大家的熱情參與積極反饋&#xff0c;我們不斷優化并完善了語聚AI的功能與使用體驗。 經過研發團隊不懈的努力&#xff0c;今天語聚AI終…

【Leetcode】88.合并兩個有序數組

一、題目 1、題目描述 給你兩個按 非遞減順序 排列的整數數組 nums1 和 nums2,另有兩個整數 m 和 n ,分別表示 nums1 和 nums2 中的元素數目。 請你 合并 nums2 到 nums1 中,使合并后的數組同樣按 非遞減順序 排列。 注意:最終,合并后數組不應由函數返回,而是存儲在數…

梅賽德斯-奔馳將成為首家集成ChatGPT的汽車制造商

ChatGPT的受歡迎程度毋庸置疑。OpenAI這個基于人工智能的工具&#xff0c;每天能夠吸引無數用戶使用&#xff0c;已成為當下很受歡迎的技術熱點。因此&#xff0c;有許多公司都在想方設法利用ChatGPT來提高產品吸引力&#xff0c;賣點以及性能。在汽車領域&#xff0c;梅賽德斯…

代碼隨想錄算法訓練營第59天|動態規劃part16|583. 兩個字符串的刪除操作、72. 編輯距離、編輯距離總結篇

代碼隨想錄算法訓練營第59天&#xff5c;動態規劃part16&#xff5c;583. 兩個字符串的刪除操作、72. 編輯距離、編輯距離總結篇 583. 兩個字符串的刪除操作 583. 兩個字符串的刪除操作 思路&#xff1a; 思路見代碼 代碼&#xff1a; python class Solution(object):de…

[國產MCU]-BL602開發實例-I2C與總線設備地址掃描

I2C與總線設備掃描 文章目錄 I2C與總線設備掃描1、I2C介紹2、I2C驅動API介紹3、I2C使用實例I2C (Inter-Intergrated Circuit)是一種串行通訊總線,使用多主從架構,用來連接低速外圍裝置。 每個器件都有一個唯一的地址識別,并且都可以作為一個發送器或接收器。每個連接到總線的…

node-sass是什么

一、Sass&#xff08;Syntactically Awesome Style Sheets&#xff09; 是一種CSS預處理器&#xff0c;它擴展了CSS的功能并提供了更強大的樣式表語言。Sass允許開發人員使用變量、嵌套規則、混合&#xff08;Mixins&#xff09;、繼承等高級功能來編寫更簡潔、可維護的樣式代…

2023年國賽數學建模思路 - 案例:FPTree-頻繁模式樹算法

文章目錄 算法介紹FP樹表示法構建FP樹實現代碼 建模資料 ## 賽題思路 &#xff08;賽題出來以后第一時間在CSDN分享&#xff09; https://blog.csdn.net/dc_sinor?typeblog 算法介紹 FP-Tree算法全稱是FrequentPattern Tree算法&#xff0c;就是頻繁模式樹算法&#xff0c…

QT-Mysql數據庫圖形化接口

QT sql mysqloper.h qsqlrelationaltablemodelview.h /************************************************************************* 接口描述&#xff1a;Mysql數據庫圖形化接口 擬制&#xff1a; 接口版本&#xff1a;V1.0 時間&#xff1a;20230727 說明&#xff1a;支…

基于VUE3+Layui從頭搭建通用后臺管理系統(前端篇)九:自定義組件封裝下

一、本章內容 續上一張,本章實現一些自定義組件的封裝,包括文件上傳組件封裝、級聯選擇組件封裝、富文本組件封裝等。 1. 詳細課程地址: 待發布 2. 源碼下載地址: 待發布 二、界面預覽 三、開發視頻 基于VUE3+Layui從頭搭建通用后臺管

【軟件工程】內聚

概念 是指一個模塊內部個成分之間相互關聯程度的度量。也就是說&#xff0c;凝聚是對模塊內各處理動作組合強度的一種度量。很顯然&#xff0c;一個模塊的內聚越大越好。 偶然凝聚 一個模塊內的各處理元素之間沒有任何聯系&#xff0c;只是偶然地被湊到一起。這種模塊也稱為…

mov轉mp4格式怎么轉?

mov轉mp4格式怎么轉&#xff1f;眾所周知&#xff0c;MOV視頻格式是由蘋果公司推出的常用的視頻格式&#xff0c;能夠在蘋果軟件及設備上使用。但是&#xff0c;如果將其應用于其他軟件和設備上的話&#xff0c;可能會遇到文件無法正常播放的情況。在這個時候&#xff0c;我們需…

Linux MQTT智能家居項目(LED界面的布局設置)

文章目錄 前言一、LED界面布局準備工作二、LED界面布局三、邏輯實現總結 前言 上篇文章我們完成了主界面的布局設置那么這篇文章我們就來完成各個界面的布局設置吧。 一、LED界面布局準備工作 首先添加LED燈光控制的圖標。 將選擇好的LED圖標添加進來&#xff1a; 圖標可以…