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条回答
flamma
1楼-- · 2019-12-13 19:32
原因是这种bit field的东西, 实际上还是用bit操作完成的,比如位与,位或。这样实际上大致会有3步。 1.把内存变量读入寄存器。2. 对寄存器位操作。3.把寄存器的数值保存到内存变量。这其中任何一步都可能被中断打断。 比如程序完成了第2步。被中断打断,中断改写了其中几位。然后程序恢复执行,继续执行第3布。中断改写的内容就丢失了。这种情况,用volatile是没有用处的。所以,要么你在写之前关闭中断,要么不要和中断同样写一个变量。你完全可以拆分成两个变量,一个程序写中断读,一个中断写程序读,这样只要加volatile标识就可以解决问题。
lingdianhao
2楼-- · 2019-12-13 21:03
很明显是读改写的问题。
lingdianhao
3楼-- · 2019-12-13 22:15
主程序,读了变量,改了变量,然后被中断,中断改了其他位,返回后主程序继续写,把中断的操作覆盖掉了。
xjtyOnly51
4楼-- · 2019-12-13 22:46
 精彩回答 2  元偷偷看……
mengtiantang
5楼-- · 2019-12-14 03:23
#pragma pack(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;     
#pragma pack()
外面加个这个你试下

一周热门 更多>