單片機中斷全局變量保護方法


首先要明白這幾個知識點:關鍵字volatile的使用,原子操作,臨界區的使用。明白的直接跳到文中的4.全局變量的使用及保護處查看。

1.關鍵字volatile

關鍵字volatile用於告訴編譯器,說明被修身的變量可能會被意想不到地改變,防止編譯器對代碼進行優化。

比如如下程序:

1	ucNms=0x65;
2 ucNms=0x66;
3 ucNms=0x67;
4 ucNms=0x68;

上述4條語句,如果變量在聲明的時候(unsigned char ucNms;)沒有使用volatile,那么編譯器有可能對其優化,只編譯最后一條語句ucNms=0x68;(即忽略前三條語句,只產生一條機器匯編代碼);如果變量在聲明的時候(volatile unsigned char ucNms;)使用了volatile,則編譯器會逐一地進行編譯並產生四條相應的機器代碼(產生四條代碼)。

精確地說就是,編譯器在編譯這個變量語句時必須每次都小心地重新讀取這個變量的值,而不是使用保存在寄存器里的備份。所以下面幾個情況在聲明的時候需要用volatile關鍵字對其修飾:

1)並行設備的硬件寄存器(如:狀態寄存器)

2)一個中斷服務子程序中會訪問到的非自動變量(Non-automatic variables)

3)多線程應用中被幾個任務共享的變量

2.原子操作

原子操作可以理解為不被打斷的操作,可以是一個步驟的操作,也可以是多個步驟的操作,總之確保操作不被打斷。

3.臨界區

指的是一個訪問共用資源(例如:共用設備或是共用存儲器)的程序片段,而這些共用資源又無法同時被多個線程訪問的特性。


4.全局變量的使用及保護

單片機裸機編程,使用全局變量時,一般是一個或多個*.c文件(或模塊)中會使用到某個全局變量(假設為A),還有中斷中也會用到這個全局變量。這樣在使用時就要考慮變量的安全性。單片機裸機編程是前后台系統,如下圖:

 

 


單片機裸機編程前后台系統

首先要明白大循環(后台)對這個變量的訪問是依次的,不管全局變量A是在哪一個模塊或者*.c文件中,每一個時刻只有一個地方對變量A訪問。然后中斷和中斷嵌套程序中也會有對全局變量A的訪問。

於是就存在這樣的問題,大循環(后台)在訪問全局變量A時(比如說訪問到一半時),被中斷(前台)程序打斷並修改了全局變量A,這樣大循環(后台)程序再次對全局變量A訪問,就會導致訪問到的A存在不確定性。從而會影響程序的不正常運行。

這樣就可以很明確的知道,只要在大循環(后台)訪問A時,不讓中斷(前台)打斷其訪問即可。確保對A的訪問是原子操作。於是就有這樣的解決方法:

關中斷-->>全局變量A-->>開中斷

有的時候,如果訪問變量A的過程比較長,可以對全局變量A做一個副本拷貝a,用拷貝的a作為模塊處理的數據。於是就有了這樣:

關中斷-->>訪問全局變量A-->>副本拷貝a-->>開中斷->>操作副本拷貝a

這種復雜的情況也可以做一個鎖這樣做:

大循環(后台):

關中斷-->>上鎖-->>開中斷-->>訪問變量A-->>關中斷-->>解鎖-->>開中斷

中斷(前台):

如果是解鎖的,操作全局變量A,如果是上鎖的就不操作

當然,如果訪問全局變量A本身就是一個原子操作(比如一條指令就可以訪問完成),這樣也就不需要做開關中斷的處理了。


示例1:禁止中斷方法保護全局變量

大循環(后台)

	ET0=0; //禁止定時中斷
訪問全局變量A;
其他代碼部分;
ET0=1; //開啟允許定時中斷

定時器中斷(前台)

	操作全局變量A;

示例2:加鎖的方法保護全局變量

大循環(后台)

	ET0=0; //禁止定時中斷
Lock = 1;
ET0=1; //開啟允許定時中斷
訪問全局變量A;
其他代碼部分;
ET0=0; //禁止定時中斷
Lock =0;
ET0=1; //開啟允許定時中斷

定時器中斷(前台)

	If(lock ==0) 操作全局變量A;
else{;}

示例3:加鎖的方法保護全局變量

大循環(后台)

	Lock = 1;//若此條語句對應匯編指令是原子操作可以不用開關中斷保護此鎖
訪問全局變量A;
其他代碼部分;
Lock =0;//若此條語句對應匯編指令是原子操作可以不用開關中斷保護此鎖

定時器中斷(前台)

	If(lock ==0) 操作全局變量A;
else{;}

總結下:中斷全局變量盡量要用volatile修飾,中斷全局變量要原子操作訪問,要時刻明白中斷全局變量是臨界區資源,共享訪問時需要保護。

 

轉發自:http://www.360doc.com/content/19/0117/10/39315025_809417729.shtml#


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM