STM32F1 MDK 4.72 遇到了怪問題 求救

2019-12-12 18:12发布


小弟再使用stm32F1 時,遇到了一個蠻怪的問題   想跟版上大神們求救                                
                                                                                                
1. 我宣告了這樣的變數                                                                          
                                                                                                
//==========================                                                                     
struct out00_bit_def{                                                                           
    u8  bit0               :1; // y00                                                            
    u8  bit1               :1; // y01                                                            
    u8  bit2               :1; // y02                                                            
    u8  bit3               :1; // y03                                                            
    u8  bit4               :1; // y04                                                            
    u8  bit5               :1; // y05                                                            
    u8  bit6               :1; // y06                                                            
    u8  bit7               :1; // y07                                                            
    }                                                                                            
                                                                                                
union{                                                                                          
    struct out00_bit_def bit;                                                                    
    u8  byte;                                                                                    
    }out00;                                                                                      
//==========================                                                                     
                                                                                                
2. 我在主程式中會使用下面的敘述,去改變 bit2 或 bit3 的狀態                                       
    out00.bit.bit2 = 1;                                                                          
    out00.bit.bit2 = 0;                                                                          
    out00.bit.bit3 = 1;                                                                          
    out00.bit.bit3 = 0;                                                                          
                                                                                                
3. 我在 timer中斷副程式中會使用下面的敘述,去改變 bit6 或 bit7 的狀態                             
    out00.bit.bit6 = 1;                                                                          
    out00.bit.bit6 = 0;                                                                          
    out00.bit.bit7 = 1;                                                                          
    out00.bit.bit7 = 0;                                                                          
                                                                                                
4. 很怪的問題是,當我程式RUN起來後,偶發性的會發生                                                
   中斷副程式有執行過改變 bit6 或 bit7 的狀態,但Memory中的bit卻沒有改變                     
   只有在timer中斷中執行改變的那些bit會出現異常
                                                  
   發生異常的情況像是中斷時執行out00.bit.bit6 = 1; 但執行後bit6沒有為1                           
                         或是中斷時執行 out00.bit.bit6 = 0; 但執行後bit6沒有為0                           

   主程式中所執行的bit狀態完全不會有異常                                                         
                                                                                                
5. 我猜測有可能是當主程式執行到類似 out00.bit.bit6 = 1; 這行程式時恰巧發生中斷,                  
   當主程式執行到 out00.bit.bit6 = 1; 時,雖然只是一行 C語法程式,但實際 CPU執行的行為依序是      
   a) 將記憶體中的 out00.byte 載入到 cpu的暫存器                                                
   b) 將這個 CPU暫存器的值 OR 0x40                                                               
   c) 將暫存器的值回寫到記憶體中 out00.byte                                                      
                                                                                                
   假設主程式執行到上面 a)動作之後,發生 timer中斷,timer中斷副程式中執行了 out00.bit.bit6 = 1;   
   然後結束中斷後回到主程式繼續從上面的 b)動作往下執行                                          
   因為這樣而發生了 timer中斷副程式中所作的動作無效(bit的狀態沒有被改變),                        
   事實上是timer中斷副程式的動作有執行 bit6狀態的改變了,只是回到主程式後又被覆蓋回先前的資料     
                                                                                                
6. 我為了要確認上面假設是對的,我宣告了另一個物件                                                
                                                                                                
   union{                                                                                       
       struct out00_bit_def bit;                                                                 
       u8  byte;                                                                                 
       }out01;                                                                                   
                                                                                                
   然後我在主程式中使用下面這樣的敘述去修改 bit2 或是 bit3的狀態                                 
    out01.bit.bit2 = 1;                                                                          
    out01.bit.bit2 = 0;                                                                          
    out01.bit.bit3 = 1;                                                                          
    out01.bit.bit3 = 0;                                                                          
                                                                                                
   也就是說,主程式中只能改變 out01.byte裡面的值 , timer中斷副程式中只能改變 out00.byte裡面的值   
   最終要拿出來使用的時候使用以下敘述                                                            
                                                                                                
   a = out00.byte | out01.byte;                                                                  
                                                                                                
   所得到的值就能夠正常,完全不會有"變更bit的狀態被 Lost"的事情發生                              
                                                                                                
   因為上面的測試,所以我猜測是因為主程式運行中,遇到timer中段所導致的問題
   
  A. 我在其他的單片機上從沒發生過這樣的問題
  B. 雖然目前用上面方法可以暫時規避問題,但如果我在主程式跟中斷成是中要操作相同的一個bit 還是會面臨同樣的問題

想問問板上各位大神們  有沒有遇過這樣的問題   何解?

                                                               
友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
该问题目前已经被作者或者管理员关闭, 无法添加新回复
11条回答
重庆酱油仔
1楼-- · 2019-12-12 22:45
加个volatile试试看?
love_ourdev
2楼-- · 2019-12-13 01:17
1,要把变量定义为volatile;
2,这种定义位操作实际上都是对同一个u8变量进行“读-改-写”操作,所以在中断和主循环中要保证互斥访问(最简单的互斥是“关中断-改变量-开中断”);
lvfv
3楼-- · 2019-12-13 03:39
都32bit的F1了,就不要用一个bit了……  咱不差那点空间。
Earthman
4楼-- · 2019-12-13 09:00
楼主改变思路不要用位域
用arm提供的bit-band
专门映射了一块区域,把bit映射到word,单周期的
yiminglei_2
5楼-- · 2019-12-13 13:44
 精彩回答 2  元偷偷看……
t24101
6楼-- · 2019-12-13 17:06
重庆酱油仔 发表于 2019-3-29 17:22
加个volatile试试看?

我試過宣告成

union{                                                                                          
    struct out00_bit_def bit;                                                                    
    u8  byte;                                                                                    
    }volatile out00;      

問題還是會發生

一周热门 更多>