找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索
查看: 3557|回復(fù): 0
收起左側(cè)

單片機(jī)程序如何做穩(wěn)定的經(jīng)驗1

[復(fù)制鏈接]
ID:44609 發(fā)表于 2020-12-16 13:47 | 顯示全部樓層 |閱讀模式
1.中斷和 main函數(shù)或其子函數(shù) 里不要同時有同一外設(shè)模塊信號的操作,如對74hc595的操作,對HT1621B的操作的信號線必須是有序的,而不能穿插,否則容易錯亂或花屏
2.中斷里標(biāo)志位變化時,回main函數(shù)或其子函數(shù)后盡量再判斷標(biāo)記位,否則容易導(dǎo)致遺傳上次標(biāo)志位的作用,而沒有及時發(fā)現(xiàn)中斷返回后標(biāo)志位已改變,而導(dǎo)致程序混亂
3.類似于信號量臨界區(qū)的穩(wěn)定性處理
4.對所有死等待如等待某標(biāo)志位 ,做超時退出處理,防止卡死
5.所有數(shù)組下標(biāo)盡量在訪問數(shù)組前都做下標(biāo)是否越界判斷
5b.做除零異常判斷,如果分母為零就不除
5c.注意:如果程序里有很多個定時器或多個高速外部中斷在工作,而且定時頻率都很高,那么如果棧空間分配很小,那么很容易發(fā)生嵌套的多層次搶占中斷而在進(jìn)入中斷函數(shù)時發(fā)生局部變量分配儲存空間時失敗即堆棧溢出,而導(dǎo)致死機(jī)和卡死!,盡量
把功能用分支if做到1個定時器中斷里,少用定時器,并盡可能減小定時器頻率,并盡可能加大棧初始化空間,如stm32單片機(jī)里 .s 文件里的一些定義
6.對于一些潛在的不穩(wěn)定因素(甚至1-2個月才出現(xiàn)一次故障),比如網(wǎng)絡(luò)忙時包ID的先后次序發(fā)生變異,而導(dǎo)致if xxxx.id>old.id 永遠(yuǎn)無法再成立而卡死
7.多機(jī)通信盡量用單向通信,比如主從模式,主機(jī)發(fā)包輪詢查詢并從機(jī)返回結(jié)果模式,雙向的全雙工通信模式的穩(wěn)定性比較差
8.所有按鈕處理必須做按鈕去抖動算法,甚至不是阻塞式延時式的去抖動算法,而是狀態(tài)機(jī)時的異步流程方式的過濾掉按得過快的2次按鈕事件間隔,比如200ms內(nèi)再無按鈕事件且按鈕已沒按住才算按了1次,而且最好加個104電容在按鈕里并聯(lián)
9.多機(jī)主從通信盡量用 目的機(jī)ID+通信協(xié)議版本號+分包的子包ID序號(如1-10)+子包總數(shù)+本子包數(shù)據(jù)長度+上次包的全局ID+crc32校驗,方式來處理重復(fù)包,30ms內(nèi)沒收到從機(jī)反饋數(shù)據(jù)則重發(fā)包(比如重發(fā)4-6次)來處理丟包,并當(dāng)上次包的全局ID大于一定值時發(fā)清零包ID的cmd包來復(fù)位ID計數(shù),但要判斷從機(jī)先收到大點的ID的包的情況
10.網(wǎng)口通信比usb通信穩(wěn)定,usb在干擾時容易掉線
11.TF卡只適合做只讀的fat32文件系統(tǒng)應(yīng)用,如要常寫入,最好配合 W25q64來固定分片方式的無fat32文件系統(tǒng)式的寫入,因為TF卡常寫入,容易寫壞文件系統(tǒng)格式,比如意外掉電時等
12.對于一些串口接口的模塊,如果波特率用得太大,則單片機(jī)容易串口中斷響應(yīng)不過來,而發(fā)生嵌套的異常串口中斷,或丟串口數(shù)據(jù),導(dǎo)致通信不穩(wěn)定,波特率最好低點!
13.單片機(jī)程序的架構(gòu)最好做成異步式的狀態(tài)機(jī)式的虛擬多線程方式,不要用任何阻塞式的死等待和延時,延時也要做成狀態(tài)機(jī)里的某個狀態(tài)的delay的異步非阻塞式的累加,加到一定值才進(jìn)入下1個狀態(tài)碼,異步方式比阻塞式的方式的穩(wěn)定性要好,處理實時性也高,多級菜單的屏幕顯示和按鍵處理也可以用狀態(tài)機(jī)式的異步流程,有個狀態(tài)碼指示當(dāng)前菜單的第1級選擇項號,選擇深度,第2級選擇項號。。。。
14.相同的類似的屬于同一功能概念下的處理過程最好集成到一個函數(shù)里做分支判斷,而不要把1個功能分散到很多個函數(shù)里,這樣代碼比較難維護(hù)和二次修改
15.可以抽象為1個功能或1個流程體內(nèi)的東西最好歸納法和抽象法抽象一下,不要做成if分支遍歷和窮舉所有情況方式,就像要做成矢量圖,而不是像素圖,抽象概括后的代碼寫法更有簡潔性,更
有可維護(hù)性和穩(wěn)定性!
15b.復(fù)雜度盡量做成可配置數(shù)組里的數(shù)據(jù),用配置數(shù)據(jù)來展開對代碼的控制,而不是把復(fù)雜度全部映射到代碼if分支等分支上,就像要做成矢量圖,而不是像素圖,就像一個圖形圓在可配置數(shù)組里(矢量圖里)是 yuan_type和sin cos,而若是代碼分支法,則是一堆關(guān)于圓的點陣

15c.按15點所說的抽象和歸納代碼后的代碼簡潔化和可維護(hù)性加大化,可以使代碼的條理和邏輯層次更加清晰,使更容易分析和預(yù)感到可能的bug和細(xì)節(jié)邏輯不嚴(yán)謹(jǐn),從而預(yù)防bug和不穩(wěn)定性bug,最終影響程序運行時穩(wěn)定性,所以bug是由思維決定的


16.看門狗在程序完工后最好加上去,軟件里的關(guān)鍵數(shù)據(jù)最好做RAM區(qū)多處備份,如備份10份,死機(jī)自動復(fù)位恢復(fù)后,檢查RAM區(qū)里備份里的各備份,重復(fù)次數(shù)最高的那幾份備份(且重復(fù)次數(shù)在6次以上)最可能為原始未被破壞的數(shù)據(jù),并做個ram標(biāo)志位檢查是上電復(fù)位,還是看門狗復(fù)位,復(fù)位后可以做不清除ram數(shù)據(jù),程序跑飛后,可以提前做些標(biāo)志位判斷,如跑飛到某處,可能某標(biāo)志位未被置位卻執(zhí)行到這,則可以自動判斷出是已跑飛,則自動軟件復(fù)位一次!

17.
單片機(jī)芯片的最近的外圍一圈上的單片機(jī)芯片vdd,gnd引腳附近必須多弄幾個0603封裝的貼片104電容來去干擾,pcb電源類走線的線寬必須要寬,至少0.4mm以上,甚至0.8mm以上,單片機(jī)芯片在pcb局部時盡量靠近電源芯片和供電芯片處

就單單才零點幾歐電阻的導(dǎo)線稍微長點來傳輸電源,比如20cm長,就會導(dǎo)致高頻雜波變多,所以導(dǎo)線末端務(wù)必加470uf以上的電解電容來去耦濾波,可以想象,在單片機(jī)引腳周圍1圈上也應(yīng)該最好加上幾個470uf電容和104電容環(huán)繞
;大功率pcb供電線走線千萬不要在單片機(jī)周圍走線或走過單片機(jī),一定要把大功率電源的輸入接口做在大功率電路部分的附近,避免電源線的長距離走線!,要走也不要在單片機(jī)外周走過!,且大功率pcb供電線走線要邊走線邊1路隔個幾段距離就加個104去耦電容



18.
如果是軟件模擬spi信號接口或i2c接口,那么字節(jié)發(fā)送函數(shù)里最好先禁止總中斷使能,發(fā)完后再開啟總中斷使能,否則容易不穩(wěn)定

19.
c8051f340單片機(jī)芯片工作時如果電源電壓比較低或有突然的電源脈沖浪涌干擾,容易使燒好的程序丟掉,穩(wěn)定性好像不怎么好,stm32單片機(jī)芯片或GD32芯片好像就好點,就沒這個問題!,推薦優(yōu)先選后者

20.
對于以太網(wǎng)網(wǎng)絡(luò)模塊芯片應(yīng)用,最好把這芯片的RST復(fù)位信號接到單片機(jī)上,并RST腳接個104電容(有時候干擾容易導(dǎo)致意外硬式復(fù)位,而反而不穩(wěn)定),這樣,網(wǎng)絡(luò)卡死時可以強(qiáng)制復(fù)位網(wǎng)卡芯片一次來修復(fù)

21.
lwip等網(wǎng)絡(luò)協(xié)議棧的某些版本有可能有內(nèi)存泄露bug,或長時間運行后卡死,最好做定時自動軟件復(fù)位單片機(jī)功能,來防止內(nèi)存泄露過度

22.
芯片上如果flash夠,最好做從服務(wù)器查詢新版BIN固件來自動升級單片機(jī)自身的hex固件功能(固件下載完要做CRC32校對),以及usb的固件升級功能,即net bootloader和usb bootloader,來應(yīng)對【做項目即使完成和驗收后,幾個月出現(xiàn)的bug要修復(fù),而措手不及】


23.
比如 休眠后喚醒時給PB1引腳1個高電平后不明原因的死機(jī),不一定是進(jìn)入未定義中斷,而是main函數(shù)之前bootloader對PB1響應(yīng):主程序進(jìn)入休眠態(tài),喚醒后 pb1為高,進(jìn)入bootloader態(tài),但bootloader里沒有重新初始化stm32 cpu的時鐘系統(tǒng)等,故卡死,雖然bootloader后跳轉(zhuǎn)到的main里有重新初始化stm32 cpu的時鐘系統(tǒng)等的代碼,但是已執(zhí)行不到


24.
密腳芯片單片機(jī)等ic焊接時上松香吸錫后,如果用酒精清洗,是否過幾個月后會發(fā)生引腳間松香,助焊劑等物質(zhì)發(fā)生變質(zhì)而短路?而不穩(wěn)定?

25.
故障實時監(jiān)測功能很重要。▊錇(zāi)1):比如某stm32版的帶網(wǎng)口的板子做個板子是否在線監(jiān)測和掉線時短信提醒功能,即每10秒鐘發(fā)送1個心跳包給服務(wù)器,如果服務(wù)器50秒內(nèi)沒收到某板子的任何心跳包,則此板子判為已掉線,并發(fā)送報警短信,email給對應(yīng)的技術(shù)員來通知處理和修復(fù)

26.
同一個安裝點上弄多個冗余板子,某塊故障時,另1塊自動切換到上線!,或雙電源,1個后備電池逆變電源,主電故障則自動切換到備電(備災(zāi)2)

27.
電源接插頭不要用圓孔的那種電源插座或usb接口插座,要用專用的接線端子母座和接線端子插頭(綠色方形的帶2針的那種,最好還帶上扣機(jī)制,插緊后自動上扣),否則電源不穩(wěn)或接觸不良,導(dǎo)致板子掉程序或其他異常,信號線也可以如此處理


28.
回流焊最后1段溫度曲線的達(dá)到最高溫度時如保持時間過長(推薦205度保持15秒,對于無鉛錫膏)導(dǎo)致錫膏被烤干,或錫膏過期了,就會導(dǎo)致出來后焊接效果不好,比如焊盤上錫的亮度不高,無光澤,太干燥,這時容易影響產(chǎn)品性能和加速日后的產(chǎn)品性能衰變

29.
eeprom寫入前不需要擦除整個扇區(qū),比如at24c02之類的,而單片機(jī)自帶的flash和w25q64等都是flash,寫入前如果不擦除整個扇區(qū),可能部分字節(jié)會寫錯字節(jié),而導(dǎo)致異常和不穩(wěn),或者做了擦除處理,但是寫某個數(shù)據(jù)時
未備份扇區(qū)里原數(shù)據(jù)而直接擦除扇區(qū),導(dǎo)致數(shù)據(jù)丟失,比如要寫入的數(shù)據(jù)數(shù)組跨越了2個扇區(qū)的邊界的情況

30.
盡量不要用一些外置的什么is62lv256+ls373方案的擴(kuò)展ram內(nèi)存方式,而要直接用自帶高ram大小的192K ram的單片機(jī),比如stm32f407或stm32f103zet,stm32103re ,gd32f103cb等,因為外擴(kuò)方式容易不穩(wěn)定,比如受焊接質(zhì)量,打板精度,環(huán)境濕度溫度,電源波動等影響
而不穩(wěn)


31.
遞歸函數(shù)盡量用while/for循環(huán)+棧或數(shù)組或鏈表的方式來替代,而不要做成多層次調(diào)用函數(shù)自身方式的遞歸,做也做成帶遞歸深度變量的,限制最大遞歸深度,否則容易堆棧溢出而死機(jī)

32.
當(dāng)要進(jìn)行可能的后果極其危險或非常重要,不能被任何干擾誤觸發(fā)的控制操作時(比如房屋爆破隊驅(qū)動炸藥點火的裝置,自動駕駛的緊急剎車制動驅(qū)動器,高壓總閘開關(guān)繼電器),務(wù)必要備份10份以上的
控制碼,如果只有1份控制碼,當(dāng)這份控制碼被強(qiáng)干擾信號改變內(nèi)存數(shù)據(jù)而變?yōu)閷?dǎo)致觸發(fā)的目標(biāo)控制碼時,就會誤動作,而如果是10份,會校驗所有10份控制完全一致后再打開控制,這樣只有1份或2份被干擾
后就不會誤動作了,所有內(nèi)存區(qū)的任何變量也都實時備份10份以上,這樣被干擾后可實時恢復(fù)正確的數(shù)據(jù)(殘留下的重復(fù)次數(shù)最多的那幾份且重復(fù)次數(shù)在6次以上即為未破壞數(shù)據(jù)),
當(dāng)10份備份中重復(fù)次數(shù)在6次以下,意外著系統(tǒng)也無法自己自我修復(fù),就會自動進(jìn)入崩潰狀態(tài)或自動軟式復(fù)位,
再進(jìn)行重要控制或驅(qū)動前,也檢查所有內(nèi)存區(qū)的各變量的實時備份的10份數(shù)據(jù),如果任何一個變量的10份備份中各數(shù)據(jù)間重復(fù)次數(shù)在6次以下,則意外著干擾太強(qiáng)了,系統(tǒng)已錯亂,則不繼續(xù)進(jìn)行重要控制或進(jìn)行驅(qū)動。
,進(jìn)行i/o控制的代碼最好在前面多加幾百行陷井代碼和判斷是否已被干擾弄崩潰的代碼,來盡可能減少意外直接跑飛到【進(jìn)行i/o控制的代碼】的概率,或者不用任何簡單的i/o來控制重要設(shè)備或高壓的重要設(shè)備,
而用i2c或spi接口的外圍驅(qū)動芯片來間接控制,且i2c或spi必須為軟件模擬,在i2c或spi的發(fā)字節(jié)函數(shù)里,每發(fā)1個比特就再判斷一次【是否已被干擾弄崩潰即檢查所有變量的10份備份是否還算完整和一致】,
這樣就非?煽亢头(wěn)定,不會被強(qiáng)干擾弄誤觸發(fā)了!


33.
在存在強(qiáng)電流,強(qiáng)功率,強(qiáng)電壓,強(qiáng)靜電,強(qiáng)射頻耦合傳遞,或可能有接觸式火花的地方盡量多的加光耦隔離來隔離信號控制計算處理部分和高壓信號驅(qū)動部分,如果一個系統(tǒng)上存在2個或以上獨立供電電源,
相互之間也必須完全隔離(GND等都不要接一起),用光耦耦合來傳遞控制,
繼電器盡量換為可關(guān)閉的晶閘管,或場效應(yīng)管,或其他大功率開關(guān)管,這些控制開斷時有【無火花】的優(yōu)點,防止繼電器通斷時的火花放電間隙導(dǎo)致的強(qiáng)干擾,如果實在要用繼電器,在繼電器的2觸點引出腳間接入RC去火花電路,
,并在繼電器的2觸點引出腳控制的真空電磁閥或電機(jī)等感應(yīng)負(fù)載上反向并聯(lián)入【1個高耐壓二極管+串1個0.5歐左右的大功率電阻】,以及并聯(lián)入1個體積大的104電容,來去除真空電磁閥或電機(jī)等在斷電瞬間產(chǎn)生的
反向電動勢,從而消除反向電動勢在繼電器觸點剛斷開時的微小間隙里產(chǎn)生火花,從而消除火花產(chǎn)生的強(qiáng)干擾來使單片機(jī)跑飛,死機(jī)或復(fù)位的后果,


,另外如果用繼電器,最好每個繼電器的VCC串1個10歐的電阻后再控制繼電器,這樣繼電器吸合時對電源的脈沖干擾小點!


34.
做編程項目或電子項目,務(wù)必做一個 發(fā)現(xiàn)的未解決的程序bug的備忘.txt ,及時記錄發(fā)現(xiàn)的偶爾出現(xiàn)的bug,和突然靈感里閃現(xiàn)的預(yù)感到的可能會出現(xiàn)的bug情況,以及要改進(jìn)的地方,
比如一些操作不變雞肋問題,穩(wěn)定性問題,都要及時記錄,因為如果每忘記1點點bug,都意味著可能日后會出現(xiàn)這個bug,即導(dǎo)致項目的徹底失敗,畢竟【一個項目的成功是靠堵住所有一些可能的細(xì)節(jié)蟲洞和雞肋來做到的】

35.
如果是在別人的開放平臺或接口上做程序,那么需要定期檢查所有情況都是否正常,比如即使今天全部正常,但是他們平臺也許早就換了接口版本,只是老用戶還是維持老版本接口,新訂購的用戶用我們isv軟件時卻已切換到新接口,不能用,卻發(fā)現(xiàn)不了

36.
字符串?dāng)?shù)組即二維的uchar數(shù)組,在定義時,前1個方括號索引字符串序號,后1個方括號索引當(dāng)前字符串的字符下標(biāo),比如u8 wavfile1n[7][15] 代表7個最長14個字符的字符串,方括號別弄反了,容易異常


37.
板子上電源處加的電解電容在1000uf以上時,容易上電時電容瞬間電流過大而導(dǎo)致開關(guān)電源發(fā)生短路保護(hù),如此循環(huán),而不易啟動


38.
EMI:pcb電源輸入部分增加共軛電感器抑制中高頻的共模噪聲,并加共模濾波電容(2個電容串聯(lián),2端接電源正負(fù),中間點接地)和差模濾波電容

39.
如果要抗雷擊浪涌,應(yīng)在電源輸入處并聯(lián)入動作電壓大于額定電壓2-3倍以上的壓敏電阻,并且電源輸入處pcb走線寬度要粗,并電源輸入處的壓敏電阻前的走線串聯(lián)入玻璃保險管的座的相關(guān)元件

40.
pcb信號線的走線盡量短而且寬: pcb布線時選擇合理的導(dǎo)線寬度 由于瞬變電流在印制線條上所產(chǎn)生的沖擊干擾主要是由印制導(dǎo)線的電感成分造成的,因此應(yīng)盡量減小印制導(dǎo)線的電感量。印制導(dǎo)線的電感量與其長度成正比,與其寬度成反比
晶振走線必須盡量短:           時鐘線、信號線也盡可能靠近地線,并且走線不要過長,以減小回路的環(huán)面積
信號線走線拐角應(yīng)采用圓弧形:   電路板上的印制線寬度不要突變,拐角應(yīng)采用圓弧形,不要直角或尖角。(9)時鐘線、信號線也盡可能靠近地線,并且走線不要過長,以減小回路的環(huán)面積。
保持環(huán)路面積最小,降低干擾對系統(tǒng)的影響,提高系統(tǒng)的抗干擾性能。并聯(lián)的導(dǎo)線緊緊放在一起,使用一條粗導(dǎo)線進(jìn)行連接,信號線緊挨地平面布線可以降低干擾。電源與地之間增加高頻濾波電容
采用完整的地平面設(shè)計,采用多層板設(shè)計,鋪設(shè)地層,便于干擾信號泄放。

41.
密腳芯片懷疑存在連焊時的處理技巧1:拖焊時務(wù)必放很多松香到吸錫銅絲線上,否則容易吸錫不徹底,而留下ic引腳間不穩(wěn)定性的短路問題,最后用99%濃度(不能含水多)的酒精擦去殘留的松香,并再烙鐵順引腳刮下來清理一遍酒精等


42.
盡量用全局變量或全局?jǐn)?shù)組變量替代局部變量,因為進(jìn)入函數(shù)時要不斷的分配局部變量,容易影響執(zhí)行效率和耗用完堆?臻g等;

43.
電源部分的正常和穩(wěn)定(比如電壓波紋小,高頻噪聲濾除率高,功率實足,抗突變的浪涌大電流能力強(qiáng))是單片機(jī)電路和控制電路穩(wěn)定工作的最重要的前

44.
像LM1086-3.3或LT1086-3.3,LMXXXXX....之類的貼片式三端穩(wěn)壓器,在貼片工藝完后并過回流焊爐后,由于焊盤上印刷錫膏時錫膏量不足或者三端穩(wěn)壓器引腳上翹會導(dǎo)致三端穩(wěn)壓器過回流焊爐焊接后存在虛焊或接觸不良,
所以應(yīng)該每次都手工補(bǔ)焊下來補(bǔ)點錫,否則容易不穩(wěn)定,或在電子產(chǎn)品運輸工程中脫焊而開路
sot23封裝的貼片三級管也容易引腳上翹而導(dǎo)致回流焊的焊接質(zhì)量不良而導(dǎo)致開路或虛焊(如在運輸過程中振動而脫焊)

45.
所以出廠前的24h老化測試和pcb帶電工作的高強(qiáng)度振動測試也很重要,來檢測是否有虛焊的現(xiàn)象(如在運輸過程中振動而脫焊)

46.
電源開關(guān)等不要用機(jī)械式的單刀雙擲式的那種微型撥動開關(guān),很容易損壞或接觸不良,最好做成自鎖式的那種按鈕式電源開關(guān)或船型開關(guān)


47.
注意場效應(yīng)管的前置驅(qū)動電壓放大級用的三極管的發(fā)射極最好是接地形式的而場效應(yīng)管G端接三極管的集電極再1個上拉電阻上拉到比如24V,否則如果NPN的發(fā)射極接G端時,當(dāng)三極管導(dǎo)通,
發(fā)射極的電壓最大也只有基極的電壓的大小,將無法良好的使場效應(yīng)管完全導(dǎo)通,比如IRF540N的Vgs需要10V左右才完全導(dǎo)通,另外應(yīng)該在G端對地并聯(lián)1個10V穩(wěn)壓管,因為一般Vgs也不能太大,20V左右最大了

不要用單片機(jī)IO口直接驅(qū)動場效應(yīng)管,因為一般場效應(yīng)管Vgs在10V左右才能完全導(dǎo)通和飽和,單片機(jī)io口電壓不夠,會驅(qū)動不良

48.
光耦存在壽命,所以盡量用非光耦的取代元件來做隔離,比如一些ic:
光耦中的發(fā)光二極管隨著時間推移而老化;比如開關(guān)電源反饋環(huán)路中光耦老化,傳輸比下降后可能引發(fā)故障。
不能用線性光耦作為模擬量傳感:通光耦產(chǎn)品手冊中對電流傳輸比只給出一個大概的范圍(從低到高可以差別一倍),而且沒有給出溫漂和老化的指標(biāo)。用于開環(huán)傳輸模擬量,精度是得不到保證的,所以導(dǎo)致過壓、過流,以致?lián)p壞

49.
74hc595的時鐘和數(shù)據(jù)線上要加阻容濾波的  這類IC  速度太高   對毛刺干擾特別敏感,而導(dǎo)致誤動作或屏幕錯亂

49a.
做電壓檢測電路時,比如測220V電壓或380V電壓,不要用線性光耦+1M電阻來降壓采樣,而要用微型工頻變壓器(鐵芯那種(非高頻磁芯))來降壓并整流采樣,因為光耦會老化和被擊穿(雷擊等意外),或有溫飄

50.
不要在任何中斷函數(shù)里調(diào)用1個需要等待另1種中斷函數(shù)來置位目標(biāo)所需標(biāo)志位才能結(jié)束的函數(shù)或代碼段,否則可能因為中斷優(yōu)先級的關(guān)系而導(dǎo)致這另1種中斷函數(shù)永遠(yuǎn)無法執(zhí)行而卡死在等待里,導(dǎo)致死機(jī)

51.
謹(jǐn)慎使用keil自帶的庫函數(shù)之sprintf和printf,容易出問題,比如卡死或內(nèi)存泄露

52.
LQFP64/LQFP48之類的密腳IC如果用拖焊法手動焊接,那么如果芯片在pcb上的每個引腳的焊盤的長度如果比較長,則很容易拖焊后在引腳的焊盤的靠芯片內(nèi)部方向處產(chǎn)生錫的殘留而導(dǎo)致2個引腳焊盤間的短路,所以
此法不穩(wěn)定,還是用鋼網(wǎng)刷錫膏+回流焊法比較可靠!




53.
ad采樣均值濾波法時應(yīng)該用:

               
                        chindex=0;
                        
                        
                        
                        
                        
                        
                          memcpy(&ch_vout1_lvbo_temp[0],&ch_vout1_lvbo[chindex][1],(junzhi_lvbo_count-1)*sizeof(float));
                        
                                memcpy(&ch_vout1_lvbo[chindex][0],&ch_vout1_lvbo_temp[0],(junzhi_lvbo_count-1)*sizeof(float));
                        
                        
                        ch_vout1_lvbo[chindex][(junzhi_lvbo_count-1)]=read_adc_value();
                        
                        
                if(ch_caiyang_alled[chindex]==0){
               
                        ch_vout1_lvbo_index1[chindex]++;
                        if(ch_vout1_lvbo_index1[chindex]>=(junzhi_lvbo_count)){
                                
                                ch_caiyang_alled[chindex]=1;
                        }
                        
                }
        

這樣的代碼機(jī)制,而不是插滿一次緩沖池后從頭開始覆蓋,而是不斷往前移1格來不斷的從緩沖池的末尾插入,而且memcpy時注意是(junzhi_lvbo_count-1)*sizeof(float)個字節(jié),而不是(junzhi_lvbo_count-1)個


54.
數(shù)字電源或開關(guān)電源的mos管的驅(qū)動級的信號輸入最好帶一級最大高電平時間限制的硬件式電路,比如最大允許高電平500us,來防止卡死時一直高電平而使mos一直導(dǎo)通而燒壞mos或高頻變壓器!


55.
注意臨界大小判斷時容易出現(xiàn)的bug:
        if((ch_vout1_zhankongbi_value1+diff_v1)<=max_zhankongbi1){
         ch_vout1_zhankongbi_value1=ch_vout1_zhankongbi_value1+diff_v1;               
        }

,這里,如果diff_v1很大,但是ch_vout1_zhankongbi_value1+diff_v1剛好只比max_zhankongbi1大1,那么就會陷入死循環(huán),永遠(yuǎn)無法達(dá)到max_zhankongbi1,而且不是只離max_zhankongbi1一點,容易使調(diào)節(jié)環(huán)在誤差比較大時卡死
,所以要加else來改為:
        if((ch_vout1_zhankongbi_value1+diff_v1)<=max_zhankongbi1){
                ch_vout1_zhankongbi_value1=ch_vout1_zhankongbi_value1+diff_v1;               
                 }else{
                ch_vout1_zhankongbi_value1=max_zhankongbi1;
                                                         
                 }


56.
數(shù)字電源的每次反饋調(diào)整pwn或每次pid調(diào)整時的調(diào)整間隔周期必須在相隔500us左右以上而不是1個while死循環(huán)里不停的調(diào)整,
而要用timer定時定間隔的調(diào)(所以輸出級的電解電容務(wù)必2200uF以上,來延長電壓突變緩沖時間),而且每次調(diào)整的誤差比例乘積因子必須要小,否則容易輸出電壓波紋很大!
控制輸出電壓波紋的關(guān)鍵是這500us內(nèi)不斷的采樣adc(可多次DMA式adc)來累加并在500us結(jié)束時取累加值的平均值來數(shù)字濾波,因為一般ad采樣電壓的波紋比較大


57.
keil中 3.11/6.1會被當(dāng)做小數(shù)來計算結(jié)果,如果是3/23,則結(jié)果為0,因為被當(dāng)做整數(shù)來處理,所以必須寫為(float)3.0/(float)23.0

58.
如果需要動態(tài)改變單片機(jī)定時器的定時周期,那么要注意周期定時值不能被改的太小,否則會導(dǎo)致不斷的高速的進(jìn)入定時中斷而卡死,要判斷和限制下


59.
【bug調(diào)試和發(fā)現(xiàn)bug原因,解決問題現(xiàn)象】的原則是【在相對系中尋找局部絕對系來作為支撐點,進(jìn)而慢慢全部覆蓋問題機(jī)制】,比如找?guī)讉確定點和可以差量法,對比法確定的程序現(xiàn)象和機(jī)理,然后再慢慢消元,減少變化量的個數(shù),盡量避免多個量
一起在變的問題框架,因為變量1多,要測試的樣本就成指數(shù)級增長!


60.
c#上位機(jī)程序防卡頓經(jīng)驗1:
阻塞式的任務(wù)和代碼要全部在后臺線程里獨立運行,而不能在主界面的主線程里執(zhí)行,對于后臺線程里要跨線程操作主界面控件的,這段操作界面的代碼要用到Invoke,相當(dāng)于卡死界面一點時間,所以在
Invoke里調(diào)用的 Action<string> actionDelegate3 = (x) =>{。。。。}之類的里的代碼盡量執(zhí)行時間耗時極短,比如盡量把界面控件某狀態(tài)的死等待代碼不要放在Invoke的執(zhí)行體代碼里,
比如 while ((int)(webb1.Tag) == 0 || webb1.IsBusy == true) { System.Threading.Thread.Sleep(10); }這段等待webbrowers加載網(wǎng)頁完畢的代碼不要放在Invoke的執(zhí)行體代碼里,而放在
線程代碼里,即Invoke的執(zhí)行體代碼執(zhí)行完后的緊接著的下一句代碼再執(zhí)行 while ((int)(webb1.Tag) == 0 || webb1.IsBusy == true) { System.Threading.Thread.Sleep(10); }
,而Invoke的執(zhí)行體代碼里如果執(zhí)行webbrowers1.Navigate(aaa1.url);之類的,也會在打開網(wǎng)頁時卡頓一段時間界面,所以盡量改為異步方式的Navigate函數(shù),比如BeginNavigate()之類的

61.
C#里等待webbrowser是否加載網(wǎng)頁完成的穩(wěn)定可靠的檢測方法為:延時式再判斷累計法(注意:線程里讀webbrowser的Isbusy值時要用Invoke,否則容易出錯):

                      int kongxianed = 0;
                      while (true)
                      {

                          System.Threading.Thread.Sleep(100);
                          bool isbusy1=true;


                          Action<string> actionDelegate3a11 = (x) =>
                         {
                             isbusy1 = webb1.IsBusy;
                         };

                          webb1.Invoke(actionDelegate3a11, "");


                          if (isbusy1 != true)
                          {
                              kongxianed++;

                          }
                          else
                          {
                              kongxianed = 0;

                          }

                          if (kongxianed > 20)//如果2秒內(nèi)都無Busy狀態(tài)再出現(xiàn),那么極有可能網(wǎng)頁和其所有網(wǎng)頁子框架都已加載完成
                          {
                              break;

                          }


                      }


62.
c#里容易異常的地方和一些界面控制代碼外圍盡量包1層try ...catch,來防止崩潰出錯

63.
c#里object 不能直接隱式轉(zhuǎn)為int,而要先tostring()后再int.parse?


64.
js里的ajax里提交后盡量加&r="+Math.random()后綴來防止緩沖而不更新

65.
路徑可能變動的網(wǎng)頁里的帶背景img定義的css盡量不要放在網(wǎng)頁里,而放在一個外部css文件里,這樣圖片可以相對css文件來定義路徑

66.
對于ajax點擊鏈接執(zhí)行函數(shù)但不跳轉(zhuǎn),建議不要用href:void(0)...+onclick(兼容性不好,有些瀏覽器異常打開新窗口),而用div+onclick+div加手型鼠標(biāo)css
,而且onclick所在div要顯式定義好height和width,否則容易兼容性不好,而有的瀏覽器點擊無響應(yīng)!
Example:CSS鼠標(biāo)手型效果 <a href="#" style="cursor:hand">CSS鼠標(biāo)手型效果</a>
Example:CSS鼠標(biāo)手型效果 <a href="#" style="cursor:pointer">CSS鼠標(biāo)手型效果</a>
注:pointer也是小手鼠標(biāo),建

另外免費招單片機(jī)徒弟一起學(xué)習(xí)交流,看我頭像
回復(fù)

使用道具 舉報

您需要登錄后才可以回帖 登錄 | 立即注冊

本版積分規(guī)則

小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術(shù)交流QQ群281945664

Powered by 單片機(jī)教程網(wǎng)

快速回復(fù) 返回頂部 返回列表