字壓力傳感器設(shè)計(jì):從信號(hào)鏈到標(biāo)定與顯示的工程實(shí)踐)
簡(jiǎn)介這份Word文檔面向電子信息、自動(dòng)化及測(cè)控專業(yè)的學(xué)生與工程技術(shù)人員圍繞基于80C51單片機(jī)的數(shù)字壓力傳感器設(shè)計(jì)展開(kāi)可用于課程設(shè)計(jì)、畢業(yè)設(shè)計(jì)或工業(yè)自控入門參考。內(nèi)容涵蓋電阻應(yīng)變片與壓電傳感器兩種敏感元件的方案對(duì)比、全橋測(cè)量電路、三運(yùn)放大電路、ADC0809模數(shù)轉(zhuǎn)換、LED數(shù)碼顯示以及RS-485通信接口與協(xié)議并給出電源電路、數(shù)據(jù)處理與溫度補(bǔ)償?shù)仍O(shè)計(jì)論證。資源包共1個(gè)doc文件約158KB為完整可編輯的Word版設(shè)計(jì)文檔結(jié)構(gòu)清晰、圖文并茂便于直接查閱或二次修改。目前已有43人學(xué)習(xí)下載適合需要快速獲取完整設(shè)計(jì)方案、理解傳感器信號(hào)采集與單片機(jī)處理流程的讀者參考借鑒。1. 從一顆 80C51 到數(shù)字壓力表為什么老架構(gòu)反而更適合入門很多人第一次接觸壓力測(cè)量腦子里冒出來(lái)的方案是買一個(gè)帶 I2C 輸出的數(shù)字壓力傳感器接上開(kāi)發(fā)板讀寄存器就完事。但如果你手上只有一顆 80C51或者你面對(duì)的是一個(gè)需要長(zhǎng)期穩(wěn)定運(yùn)行、成本壓到極致的工業(yè)現(xiàn)場(chǎng)思路就完全不一樣了?;?80C51 單片機(jī)的數(shù)字壓力傳感器設(shè)計(jì)核心不是堆算力而是用最少的資源把模擬信號(hào)采準(zhǔn)、把數(shù)字量算對(duì)、把顯示和通信做穩(wěn)。它解決的是“低成本、可標(biāo)定、能長(zhǎng)期跑”的問(wèn)題適合剛?cè)腴T的電子工程師、做課程設(shè)計(jì)的學(xué)生以及需要給老舊設(shè)備加數(shù)字顯示的現(xiàn)場(chǎng)維護(hù)人員。這顆芯片沒(méi)有硬件乘法器沒(méi)有浮點(diǎn)單元連 ADC 都要外掛但正因?yàn)橘Y源緊你才會(huì)被迫把每一個(gè)時(shí)鐘周期和每一字節(jié)內(nèi)存都算清楚。我見(jiàn)過(guò)太多人一上來(lái)就選帶 24 位 ADC 的 MCU結(jié)果連基準(zhǔn)電壓的溫漂都沒(méi)搞定數(shù)據(jù)跳得比心跳還快。80C51 方案反而逼你先搞明白信號(hào)鏈。2. 信號(hào)鏈怎么搭從壓阻橋到 80C51 能讀的數(shù)字2.1 壓力傳感器選型與模擬前端數(shù)字壓力傳感器的“數(shù)字”二字指的是最終輸出形式而不是敏感元件本身。絕大多數(shù)低成本方案用的還是壓阻式惠斯通電橋輸出差分電壓通常在幾十毫伏量級(jí)。以常見(jiàn)的表壓傳感器為例滿量程輸出可能是 50mV 到 100mV零點(diǎn)偏置卻可能有 ±20mV。這個(gè)信號(hào)直接進(jìn) ADC 會(huì)被噪聲淹沒(méi)所以模擬前端必須做兩件事差分放大和電平搬移。我一般會(huì)選一款儀表放大器比如 AD620 的國(guó)產(chǎn)替代型號(hào)增益電阻根據(jù)傳感器靈敏度和 ADC 參考電壓來(lái)算。假設(shè)傳感器靈敏度是 2mV/V供電 5V滿量程輸出就是 10mV。ADC 參考電壓 2.5V想要滿量程對(duì)應(yīng) 2.0V增益就是 200 倍。增益電阻公式是 Rg 49.4kΩ / (G-1)算下來(lái)約 248Ω。這個(gè)電阻要用精度 1% 的金屬膜電阻溫漂越小越好。電平搬移用一只運(yùn)放搭減法電路把差分放大后的信號(hào)抬到 ADC 量程中點(diǎn)。這里有個(gè)血淚經(jīng)驗(yàn)不要用單電源運(yùn)放直接處理接近地的信號(hào)輸出會(huì)失真。要么用雙電源要么選軌到軌輸入輸出的型號(hào)并且給負(fù)電源端加一個(gè)負(fù)壓產(chǎn)生電路。如果嫌麻煩可以直接選一款帶差分輸入和可編程增益的 ADC比如 HX711 這類專用于橋式傳感器的芯片它內(nèi)部就把放大和 ADC 做完了輸出直接是數(shù)字量80C51 只需要兩個(gè) IO 口模擬時(shí)序讀取。但 HX711 的更新率低適合靜態(tài)壓力測(cè)量動(dòng)態(tài)壓力就別想了。2.2 80C51 最小系統(tǒng)與 ADC 接口80C51 本身沒(méi)有 SPI 和 I2C 硬件模塊所有時(shí)序都要用 IO 口模擬。如果你選的是并行輸出的 ADC比如 ADC0809那就更方便直接掛在 P0 口和 P2 口上用外部中斷或者查詢方式讀。ADC0809 是 8 位、8 通道、逐次逼近型轉(zhuǎn)換時(shí)間約 100μs對(duì)于壓力測(cè)量綽綽有余。它的啟動(dòng)信號(hào)、地址鎖存、輸出使能都需要用 IO 口控制。最小系統(tǒng)包括晶振電路、復(fù)位電路和電源。晶振選 11.0592MHz 還是 12MHz如果要做串口通信11.0592MHz 能產(chǎn)生更準(zhǔn)的波特率誤差為 0。如果只做顯示和按鍵12MHz 計(jì)算定時(shí)器更方便。我一般用 11.0592MHz因?yàn)楹笃诩哟谏蟼鲾?shù)據(jù)時(shí)不用改硬件。復(fù)位電路用 10μF 電容加 10kΩ 電阻上電復(fù)位時(shí)間約 100ms足夠 80C51 初始化。EA 引腳接高電平使用內(nèi)部程序存儲(chǔ)器。ADC 的參考電壓直接決定測(cè)量精度。不要用 7805 的輸出當(dāng)基準(zhǔn)它的溫漂和噪聲都很大。至少要用 TL431 這類可調(diào)基準(zhǔn)源精度 0.5%溫漂 50ppm/℃。如果預(yù)算允許用 REF3025 這類專用基準(zhǔn)初始精度 0.05%溫漂 15ppm/℃?;鶞?zhǔn)電壓的穩(wěn)定性比 ADC 位數(shù)更重要8 位 ADC 配 0.05% 基準(zhǔn)有效精度能到 7 位以上16 位 ADC 配 5% 基準(zhǔn)實(shí)際精度可能只有 8 位。2.3 采樣時(shí)序與數(shù)字濾波80C51 讀 ADC 的時(shí)序必須嚴(yán)格按數(shù)據(jù)手冊(cè)來(lái)。以 ADC0809 為例啟動(dòng)轉(zhuǎn)換需要給 START 引腳一個(gè)正脈沖然后等待 EOC 變高再給 OE 高電平讀取數(shù)據(jù)。用查詢方式寫起來(lái)簡(jiǎn)單但占用 CPU 時(shí)間。用中斷方式把 EOC 反相后接到 INT0 或 INT1轉(zhuǎn)換完成觸發(fā)中斷在中斷服務(wù)程序里讀數(shù)據(jù)。采樣頻率不用太高壓力變化通常很慢。我一般設(shè) 10Hz 到 100Hz 的采樣率用定時(shí)器 0 產(chǎn)生 10ms 中斷在中斷里啟動(dòng) ADC下次中斷讀結(jié)果。這樣 CPU 占用率很低還能留出時(shí)間做顯示和按鍵掃描。數(shù)字濾波是必須的。8 位 ADC 的原始數(shù)據(jù)跳動(dòng)可能有 ±2LSB直接顯示會(huì)閃。最簡(jiǎn)單的辦法是滑動(dòng)平均開(kāi)一個(gè) 8 個(gè)元素的環(huán)形緩沖區(qū)每次新數(shù)據(jù)覆蓋最舊數(shù)據(jù)然后求平均。求平均時(shí)不要用浮點(diǎn)80C51 做浮點(diǎn)除法很慢。用移位代替除法8 個(gè)數(shù)據(jù)求和后右移 3 位就是平均值。如果數(shù)據(jù)跳動(dòng)還是大可以加中值濾波連續(xù)采 5 次去掉最大和最小剩下 3 個(gè)求平均。中值濾波對(duì)脈沖干擾特別有效比如電機(jī)啟停時(shí)產(chǎn)生的尖峰。// 滑動(dòng)平均濾波8 點(diǎn)用移位代替除法 unsigned char filter_buf[8]; unsigned char filter_idx 0; unsigned int filter_sum 0; unsigned char filter_avg(unsigned char new_data) { filter_sum - filter_buf[filter_idx]; // 減去最舊數(shù)據(jù) filter_buf[filter_idx] new_data; // 存入新數(shù)據(jù) filter_sum new_data; // 累加新數(shù)據(jù) filter_idx (filter_idx 1) 0x07; // 環(huán)形索引0-7循環(huán) return (unsigned char)(filter_sum 3); // 除以8右移3位 }這段代碼的關(guān)鍵在于 filter_sum 用 unsigned int因?yàn)?8 個(gè) 8 位數(shù)據(jù)求和最大 2040不會(huì)溢出。filter_idx 用按位與代替取模因?yàn)?8 是 2 的冪這樣寫編譯出來(lái)的代碼更短。每次調(diào)用返回平均值主循環(huán)里直接拿去顯示或計(jì)算壓力值。注意初始化時(shí)要把緩沖區(qū)清零否則上電后前 8 次采樣會(huì)混入隨機(jī)值。3. 標(biāo)定與壓力計(jì)算沒(méi)有浮點(diǎn)單元怎么算得準(zhǔn)3.1 兩點(diǎn)標(biāo)定法的實(shí)操步驟壓力傳感器的輸出和壓力值之間理論上是線性的但實(shí)際有零點(diǎn)偏置和靈敏度誤差。兩點(diǎn)標(biāo)定是最實(shí)用的方法在零壓力和滿量程壓力下各采一組數(shù)據(jù)算出斜率和截距。具體操作是先不給壓力等讀數(shù)穩(wěn)定后記錄 ADC 值記為 adc_zero然后加滿量程標(biāo)準(zhǔn)壓力記錄 adc_full。壓力計(jì)算公式就是P (adc - adc_zero) * P_full / (adc_full - adc_zero)其中 P_full 是滿量程壓力值比如 100kPa。這個(gè)公式里有一次除法和一次乘法80C51 做 16 位除法大概需要幾十個(gè)機(jī)器周期對(duì)于 10Hz 的采樣率完全夠用。但要注意 adc_full - adc_zero 不能太小否則除法誤差大。如果傳感器靈敏度低放大后的滿量程 ADC 變化量至少要有 100 個(gè)碼值對(duì)應(yīng) 8 位 ADC 就是 40% 量程。如果只有 20 個(gè)碼值標(biāo)定出來(lái)的精度會(huì)很差這時(shí)候要么加大增益要么換 12 位 ADC。標(biāo)定時(shí)要用標(biāo)準(zhǔn)壓力源不要用打氣筒加機(jī)械表湊合。機(jī)械表的精度通常只有 2.5% 滿量程標(biāo)出來(lái)的數(shù)字表不會(huì)比它更準(zhǔn)。如果實(shí)在沒(méi)有標(biāo)準(zhǔn)源可以用水柱法1 米水柱約 9.8kPa用卷尺量水位差精度能到 1%。但水柱法只適合低壓高壓還是得用活塞式壓力計(jì)。3.2 定點(diǎn)數(shù)運(yùn)算與查表法80C51 沒(méi)有浮點(diǎn)單元用 float 類型會(huì)調(diào)用庫(kù)函數(shù)代碼體積大、執(zhí)行慢。我一般用定點(diǎn)數(shù)把壓力值放大 10 倍或 100 倍用 unsigned int 或 unsigned long 存儲(chǔ)。比如壓力范圍 0 到 100.0kPa就用 0 到 1000 表示單位是 0.1kPa。計(jì)算時(shí)先乘后除避免中間結(jié)果溢出。如果壓力范圍不大查表法更快。把 ADC 值 0 到 255 對(duì)應(yīng)的壓力值預(yù)先算好存到 code 區(qū)運(yùn)行時(shí)直接查表。表的大小是 256 字節(jié)對(duì)于 80C51 的 4KB 程序空間來(lái)說(shuō)可以接受。查表法沒(méi)有計(jì)算誤差但標(biāo)定后要重新生成表。生成表可以用 Excel 或者 Python 腳本把公式算好導(dǎo)出成 C 數(shù)組。// 定點(diǎn)數(shù)壓力計(jì)算壓力單位 0.1kPa滿量程 1000 unsigned int adc_zero 20; // 零點(diǎn) ADC 值 unsigned int adc_full 230; // 滿量程 ADC 值 unsigned int p_full 1000; // 滿量程壓力 100.0kPa unsigned int calc_pressure(unsigned char adc) { unsigned long temp; if (adc adc_zero) return 0; if (adc adc_full) return p_full; temp (unsigned long)(adc - adc_zero) * p_full; temp temp / (adc_full - adc_zero); return (unsigned int)temp; }這段代碼里 temp 用 unsigned long因?yàn)?(adc - adc_zero) 最大 255乘以 1000 等于 255000超過(guò) 16 位范圍。除法用 32 位除以 16 位Keil C51 會(huì)調(diào)用庫(kù)函數(shù)執(zhí)行時(shí)間約 200 個(gè)機(jī)器周期在 11.0592MHz 下約 18μs對(duì) 10Hz 采樣率來(lái)說(shuō)微不足道。注意 adc_zero 和 adc_full 要存在非易失存儲(chǔ)器里比如 AT24C02這樣標(biāo)定一次就不用每次上電重來(lái)。3.3 溫度補(bǔ)償?shù)暮?jiǎn)化處理壓阻式壓力傳感器有溫漂零點(diǎn)溫漂和靈敏度溫漂都有。工業(yè)級(jí)傳感器內(nèi)部會(huì)做補(bǔ)償輸出已經(jīng)比較穩(wěn)定。但如果用的是裸片或者低成本傳感器溫漂可能達(dá)到 0.5%FS/℃。80C51 方案里加溫度補(bǔ)償最簡(jiǎn)單的辦法是外掛一顆數(shù)字溫度傳感器比如 DS18B20測(cè)環(huán)境溫度然后在軟件里做一階線性補(bǔ)償。補(bǔ)償公式P_corrected P_raw K_zero * (T - T_ref) K_span * (T - T_ref) * P_rawK_zero 和 K_span 需要實(shí)驗(yàn)測(cè)定。把傳感器放在溫箱里分別在 0℃、25℃、50℃ 下測(cè)零點(diǎn)和滿量程輸出算出系數(shù)。沒(méi)有溫箱的話可以用冰箱和熱水浴粗略測(cè)但精度沒(méi)法保證。如果溫度變化不大比如室內(nèi)環(huán)境 15℃ 到 35℃可以只做零點(diǎn)補(bǔ)償靈敏度補(bǔ)償忽略。DS18B20 用單總線80C51 模擬時(shí)序要小心讀寫時(shí)序的延時(shí)用 NOP 微調(diào)不同晶振頻率下要重新算。4. 顯示與通信把數(shù)字壓力值送出去4.1 數(shù)碼管驅(qū)動(dòng)與動(dòng)態(tài)掃描數(shù)字壓力表最直觀的顯示是 4 位數(shù)碼管顯示 0.0 到 100.0。共陽(yáng)數(shù)碼管用 P0 口輸出段碼P2 口輸出位選。動(dòng)態(tài)掃描頻率要大于 50Hz否則會(huì)閃。用定時(shí)器 1 產(chǎn)生 2ms 中斷每次中斷點(diǎn)亮一位4 位輪流刷新率 125Hz肉眼完全看不出閃爍。段碼表用 code 關(guān)鍵字存在程序存儲(chǔ)器共陽(yáng)和共陰的段碼不一樣寫代碼前先用萬(wàn)用表測(cè)一下。限流電阻每段一個(gè)220Ω 到 470Ω根據(jù)數(shù)碼管亮度調(diào)。位選三極管用 S8550 或 S8050注意共陽(yáng)數(shù)碼管的位選是低電平有效三極管要接成射極跟隨器還是集電極開(kāi)路取決于數(shù)碼管共陽(yáng)端的接法。// 共陽(yáng)數(shù)碼管段碼表0-9不帶小數(shù)點(diǎn) unsigned char code seg_code[] { 0xC0, 0xF9, 0xA4, 0xB0, 0x99, 0x92, 0x82, 0xF8, 0x80, 0x90 }; // 顯示緩沖區(qū)4 位分別對(duì)應(yīng)千、百、十、個(gè) unsigned char disp_buf[4] {0, 0, 0, 0}; // 定時(shí)器1中斷服務(wù)程序2ms 一次 void timer1_isr() interrupt 3 { static unsigned char pos 0; P2 0xFF; // 先消隱關(guān)閉所有位 P0 seg_code[disp_buf[pos]]; // 輸出段碼 P2 ~(1 pos); // 打開(kāi)當(dāng)前位低電平有效 pos (pos 1) 0x03; // 0-3 循環(huán) }這段代碼里 P2 先寫 0xFF 消隱再寫段碼最后打開(kāi)位選順序不能反否則會(huì)有鬼影。pos 用按位與循環(huán)和前面濾波代碼一個(gè)套路。disp_buf 里的數(shù)據(jù)在主循環(huán)里更新把壓力值拆成 4 位數(shù)字。拆位用除法和取余80C51 做 16 位除法稍慢但 10Hz 更新一次完全沒(méi)壓力。4.2 串口上傳與上位機(jī)協(xié)議如果需要把數(shù)據(jù)傳到電腦80C51 的串口是現(xiàn)成的。用定時(shí)器 1 做波特率發(fā)生器11.0592MHz 晶振下9600bps 的定時(shí)器初值是 0xFD。串口工作在模式 18 位數(shù)據(jù)可變波特率。發(fā)送用查詢方式就行壓力數(shù)據(jù)更新慢不用中斷。協(xié)議我一般用簡(jiǎn)單的 ASCII 幀幀頭 0xAA然后 4 字節(jié)壓力值 ASCII 碼最后 0x55 結(jié)尾。上位機(jī)收到后解析。ASCII 的好處是調(diào)試方便用串口助手直接能看。二進(jìn)制協(xié)議更緊湊但調(diào)試時(shí)得對(duì)著十六進(jìn)制看容易出錯(cuò)。// 串口發(fā)送一個(gè)字節(jié)查詢方式 void uart_send(unsigned char dat) { SBUF dat; while (!TI); // 等待發(fā)送完成 TI 0; // 清除發(fā)送標(biāo)志 } // 發(fā)送壓力值格式0xAA 4字節(jié)ASCII 0x55 void send_pressure(unsigned int p) { uart_send(0xAA); uart_send(p / 1000 0); // 千位 uart_send(p / 100 % 10 0); // 百位 uart_send(p / 10 % 10 0); // 十位 uart_send(p % 10 0); // 個(gè)位 uart_send(0x55); }發(fā)送前要確保 p 不超過(guò) 9999否則會(huì)發(fā)亂。如果壓力值可能超過(guò)先做限幅。串口發(fā)送和數(shù)碼管掃描都在主循環(huán)里調(diào)用注意不要互相阻塞。數(shù)碼管掃描在定時(shí)器中斷里串口發(fā)送在主循環(huán)兩者不沖突。5. 避坑與排查80C51 壓力表最容易翻車的 5 個(gè)地方5.1 ADC 讀數(shù)跳動(dòng)大顯示最后一位亂閃現(xiàn)象壓力穩(wěn)定時(shí)數(shù)碼管最后一位在 0 和 1 之間跳或者跳動(dòng)超過(guò) 3 個(gè)碼值。原因基準(zhǔn)電壓不穩(wěn)、模擬地和數(shù)字地混在一起、濾波不充分。80C51 的 IO 口翻轉(zhuǎn)時(shí)會(huì)產(chǎn)生電流尖峰通過(guò)地線耦合到模擬部分。解決基準(zhǔn)源加 10μF 鉭電容和 0.1μF 陶瓷電容退耦位置盡量靠近基準(zhǔn)芯片。模擬地和數(shù)字地單點(diǎn)連接在 ADC 下方用 0Ω 電阻或磁珠連接。軟件上把滑動(dòng)平均從 8 點(diǎn)加到 16 點(diǎn)或者加中值濾波。如果還跳檢查傳感器信號(hào)線是否太長(zhǎng)用屏蔽線并單端接地。5.2 標(biāo)定后線性度差中間點(diǎn)誤差大現(xiàn)象零點(diǎn)和滿量程都準(zhǔn)但 50% 壓力時(shí)誤差超過(guò) 2%。原因傳感器本身非線性或者放大器在中間電平處失真。也可能是 ADC 的積分非線性INL指標(biāo)差。解決先查傳感器數(shù)據(jù)手冊(cè)的非線性指標(biāo)如果傳感器本身非線性就 1%那系統(tǒng)不可能優(yōu)于 1%。如果是放大器問(wèn)題檢查輸出是否在軌到軌范圍內(nèi)中間電平處是否進(jìn)入非線性區(qū)。ADC 的 INL 通常 8 位的是 ±0.5LSB影響不大。如果要求高用三點(diǎn)標(biāo)定把中間點(diǎn)也納入用分段線性插值。5.3 上電后數(shù)碼管顯示亂碼或全亮現(xiàn)象一上電所有段都亮或者顯示無(wú)意義的字符。原因80C51 上電復(fù)位時(shí)間不夠IO 口狀態(tài)不確定?;蛘?disp_buf 未初始化里面是隨機(jī)值。解決復(fù)位電路電容加大到 22μF確保復(fù)位時(shí)間大于 100ms。在 main 函數(shù)開(kāi)頭先把 disp_buf 清零P0 和 P2 寫 0xFF 消隱。如果還亂檢查 EA 引腳是否接高程序是否從 0000H 開(kāi)始執(zhí)行。有時(shí)候是晶振沒(méi)起振用示波器看 XTAL2 引腳有沒(méi)有波形。5.4 串口通信丟包或亂碼現(xiàn)象上位機(jī)收到的數(shù)據(jù)偶爾多一個(gè)字節(jié)或少一個(gè)字節(jié)或者全是亂碼。原因波特率誤差大、地線沒(méi)接、發(fā)送時(shí)被中斷打斷。解決11.0592MHz 晶振下 9600bps 誤差為 0如果用了 12MHz 晶振誤差約 8.5%會(huì)丟包。檢查串口線是否共地TX 和 RX 不要接反。發(fā)送函數(shù)里 while(!TI) 是死等如果發(fā)送時(shí)來(lái)了中斷TI 標(biāo)志可能被意外清除。解決辦法是在發(fā)送前關(guān)中斷發(fā)送完再開(kāi)中斷或者用中斷方式發(fā)送。5.5 長(zhǎng)期運(yùn)行后壓力值漂移現(xiàn)象跑幾個(gè)小時(shí)或幾天后零壓力時(shí)顯示不為零慢慢變大或變小。原因基準(zhǔn)電壓溫漂、傳感器溫漂、放大器失調(diào)電壓漂移。也可能是電源紋波導(dǎo)致 ADC 參考不穩(wěn)。解決基準(zhǔn)源換低溫漂型號(hào)傳感器如果溫漂大就加溫度補(bǔ)償。放大器選低失調(diào)漂移的比如 OP07 的失調(diào)漂移是 0.5μV/℃足夠用。電源加 LC 濾波7805 后面接 100μH 電感和 100μF 電容。軟件上可以加自動(dòng)零點(diǎn)跟蹤如果壓力值連續(xù) 1 分鐘小于滿量程的 1%就認(rèn)為當(dāng)前是零點(diǎn)自動(dòng)更新 adc_zero。但這個(gè)方法有風(fēng)險(xiǎn)如果實(shí)際壓力就是很小會(huì)被誤判為零點(diǎn)。我一般只在開(kāi)機(jī)后前 10 秒做自動(dòng)零點(diǎn)之后鎖定。6. 進(jìn)階技巧用 80C51 的剩余資源做自診斷80C51 的 IO 口和定時(shí)器資源有限但做完壓力測(cè)量、顯示和串口后通常還能剩幾個(gè) IO。我習(xí)慣留一個(gè) IO 做傳感器斷線檢測(cè)一個(gè) IO 做超量程報(bào)警。斷線檢測(cè)的原理很簡(jiǎn)單在傳感器橋臂上并一個(gè)高阻值電阻正常時(shí)橋臂電阻低該點(diǎn)電壓被拉低斷線時(shí)橋臂開(kāi)路電壓被高阻拉高。用 ADC 讀這個(gè)電壓超過(guò)閾值就報(bào)警。另一個(gè)技巧是用定時(shí)器 2 做看門狗。80C51 沒(méi)有內(nèi)置看門狗但可以用定時(shí)器 2 的溢出中斷模擬。在主循環(huán)里定時(shí)喂狗如果程序跑飛定時(shí)器 2 溢出后觸發(fā)復(fù)位。具體做法是定時(shí)器 2 設(shè)成 100ms 溢出溢出中斷里把 RST 引腳拉低 10μs。主循環(huán)里每 50ms 清一次定時(shí)器 2 的計(jì)數(shù)器。如果程序卡死定時(shí)器 2 溢出系統(tǒng)復(fù)位。// 定時(shí)器2看門狗初始化100ms溢出 void wdt_init() { RCAP2H 0x3C; // 11.0592MHz 下 100ms 初值 RCAP2L 0xB0; TH2 0x3C; TL2 0xB0; ET2 1; // 使能定時(shí)器2中斷 EA 1; TR2 1; // 啟動(dòng)定時(shí)器2 } // 定時(shí)器2中斷溢出說(shuō)明程序跑飛復(fù)位 void timer2_isr() interrupt 5 { TF2 0; // 清除溢出標(biāo)志 // 拉低復(fù)位引腳需要硬件配合用一個(gè)IO口控制RST RST_PIN 0; // 等待復(fù)位 while(1); } // 主循環(huán)里喂狗 void wdt_feed() { TR2 0; // 停止定時(shí)器 TH2 0x3C; // 重裝初值 TL2 0xB0; TR2 1; // 重新啟動(dòng) }這個(gè)看門狗需要硬件上把 RST 引腳通過(guò)一個(gè)二極管或三極管接到某個(gè) IO 口不能直接接因?yàn)?80C51 的 RST 是高電平復(fù)位而 IO 口拉低是復(fù)位不了的。正確做法是用一個(gè) NPN 三極管基極接 IO 口集電極接 RST發(fā)射極接地。IO 口輸出高電平時(shí)三極管導(dǎo)通RST 被拉低但 80C51 的 RST 需要高電平復(fù)位所以這個(gè)電路反了。應(yīng)該用 PNP 三極管發(fā)射極接 VCC基極接 IO 口集電極接 RSTIO 口輸出低電平時(shí)三極管導(dǎo)通RST 得到高電平。這個(gè)細(xì)節(jié)容易翻車畫板子前先用萬(wàn)用表測(cè)一下。最后說(shuō)一個(gè)我自己的習(xí)慣每次改完代碼先不接傳感器用信號(hào)發(fā)生器給 ADC 輸入一個(gè)已知電壓看顯示值對(duì)不對(duì)。確認(rèn)信號(hào)鏈沒(méi)問(wèn)題了再接傳感器標(biāo)定。這樣能把硬件問(wèn)題和軟件問(wèn)題分開(kāi)省得來(lái)回猜。希望幫到你。本文還有配套的精品資源點(diǎn)擊獲取