程序運行過程中,有些數被莫名修改了,在那里修改的?又是怎么修改的?
這個代碼我只想知道是否運行過,或者運行了多少次,但是不想讓程序停下來,或者僅打印調試信息,怎么辦?
當這個變量設置成某個數據后,我想讓程序自動暫停下來進行分析,怎么辦?
破碎機
以上問題的所有答案就在本節內容:
斷點窗口(KEIL).
本節內容將顛覆你之前對斷點調試的認知。這個調試技巧用了半年多,當時知道這個調試方法的時候特別興奮,感覺發現了新大陸。而這個調試技巧解決了不疑難雜癥,而前些天又擴展學習了這個技巧的功能,更是解決了好幾個一般調試方法很難解決的BUG。
我們知道常規的斷點調試是在想觀察那里的問題時就在對應的代碼地址設置斷點,并且一旦支等到斷點位置會讓程序自動暫停運行,此斷點調試功能確實為開發者解決BUG立下汗馬功勞,但是這種方式有很大的局限性,因為很多時候我們并不需要讓程序停下來。而只想知道是否在這段代碼運行過,或者說發生問題的位置根本不能停下來,否則就會讓整個系統功能出現問題。比如中斷處理函數的調試,程序一但停下了也就失去了所有中斷的后續響應;
比如兩個設備通信,一方采用常規斷點的方式調試,肯定會打斷正常的通信過程,而這可不是我們想要的,我們只想知道在收到或發送數據后得到環境快照,而并不想讓程序停下來。以上這些問題可以采用打印方式解決,但是打印調試也有很多弊端:
以串口為例:
1 你必須添加必要的打印和串口驅動代碼,如果你使用printf函數,你還得重定向(如果對空間要求高的話,你的知道使用printf差不多要占用1K大小代碼空間)。
2 如果打印效率比較低,9600和115200打印一個字符串耗時比較長,那么對于中斷頻率較高的函數就可能不適用了。如果使用printf函數,一堂得考慮函數是否可重入問題。
3 在代碼中引入調試代碼有風險,本來程序運行沒有問題,一旦引入調試代碼之后可能就出現了問題,這種情況對于擁有豐富開發經驗的人來說應該見怪不怪了。原因就在于打印輸出時間太久,打亂了程序運行的節奏(而這也是我推薦使用ITM調試的一個原因,因為它姝輸出效率比串口要高的多),或者打印函數本身有問題,也會導致程序運行出現問題。
4 調試完畢之后,必須把對應的調試代碼刪除(不管是刪除代碼還是使用宏,都要進行這一步)。不然會影響運行效率。而人是健忘的(也不能說健忘,可能只是因為專注于BUG本身,容易忘記其它細枝未節,而解決BUG之后的欣喜更可能忘記后續處理工作了)這個時候你可以嘗試用#warnning.但是這一步一堂是必不可少。
而以上問題的解決方案就是KEIL的斷點調試窗口!
首先打開KEIL進入程序調試狀態,并設置一斷點:

然后打開斷點管理窗口:
快捷鍵是CTRL+B.

可以看到如下窗口:

如果在程序里沒有設置斷點,在斷點管理窗口的最上端是沒有對勾的。
當然你也可以通過下面這種方式打開設置:

從這里你會發現,其實這個窗口就是用來管理設置的斷點兒。平常使用的設置斷點方法只是其中的一種特例罷了。
首先要知道的是,調試器支持的斷點數量是有限的,具體有多少視情況而定,一旦KEIL警告你設置斷點太多,那么就要刪除一些斷點了:

常規用法
1 代碼位置運行次數
有些時候我們想知道某些代碼的運行次數,比如進入中斷處理函數的次數,尋常的斷點設置方式必然會讓程序停止在中斷程序中,但有些時候我們不希望它停下來。這個時候 ,你只需要打開該窗口,找到已有的對應斷點位置,雙擊之后就可以看到類似下面的窗口:

此時,將Count的值設置的盡可能大一些,那么就可以讓程序運行多次之后才停止。
比如我們設置count的值為100次,那么必須在該代碼位置運行100次才會讓程序暫停。當設置完后點擊 define 后,就會詢問你是否需要重新定義,選擇 是發即可,

此時斷點變成了這樣:

后面的count=100表示剩余運行次數為100,運行100次后將停止程序。前面的00代表斷點號,E代表這是一個可執行斷點,0X080016B0代表代碼地址,后面的是源碼位置。
當這個斷點位置運行了2次,重新打開該窗口(刷新數據), 發現這個數變成了98,從而可以推算了同,已經運行了多少了。如果你想讓這段代碼運行2次后停止,那么你只需要一開始設置count的值為2即可。