動(dòng)AD7606并行接口實(shí)現(xiàn)高速多通道同步數(shù)據(jù)采集)
簡(jiǎn)介一套適用于MSP430微控制器的八通道十六位模擬數(shù)字轉(zhuǎn)換器驅(qū)動(dòng)代碼包面向需要多通道高精度數(shù)據(jù)采集的嵌入式開(kāi)發(fā)者能夠解決同步采樣與低功耗系統(tǒng)之間的高效對(duì)接問(wèn)題該轉(zhuǎn)換器支持所有通道在同一時(shí)刻進(jìn)行采樣與轉(zhuǎn)換非常適合實(shí)時(shí)性要求較高的工業(yè)測(cè)控與科學(xué)實(shí)驗(yàn)場(chǎng)景。壓縮包內(nèi)共包含兩個(gè)文件分別是一個(gè)頭文件與一個(gè)源文件整個(gè)壓縮包僅有兩千字節(jié)大小代碼結(jié)構(gòu)清晰、便于閱讀和直接移植。目前已有七百四十三人學(xué)習(xí)或?yàn)g覽具備較好的實(shí)際參考價(jià)值。驅(qū)動(dòng)源碼完整覆蓋了芯片初始化、通道選擇、啟動(dòng)轉(zhuǎn)換以及結(jié)果讀取等核心流程頭文件通過(guò)宏定義可靈活配置正負(fù)五伏或正負(fù)十伏的輸入電壓范圍源文件還實(shí)現(xiàn)了轉(zhuǎn)換結(jié)果的補(bǔ)碼解碼能夠直接輸出帶符號(hào)的電壓數(shù)值。同時(shí)代碼中兼顧了時(shí)鐘同步、噪聲抑制、低功耗管理以及異常檢測(cè)等工程要素特別適合應(yīng)用于電池供電的便攜設(shè)備、環(huán)境監(jiān)測(cè)終端和精密測(cè)量?jī)x器中。1. 項(xiàng)目概述與方案選型1.1 為什么是MSP430AD7606組合做工業(yè)數(shù)據(jù)采集這塊的老工程師多半都跟AD7606打過(guò)交道。這顆16位、8通道同步采樣的ADC芯片在電力監(jiān)控、振動(dòng)分析、多通道數(shù)據(jù)記錄儀里幾乎是標(biāo)配。而我這次選MSP430作為主控核心原因有三點(diǎn)低功耗特性在電池供電的便攜采集場(chǎng)景里非常吃香配合并行接口讀取AD7606時(shí)GPIO操作延時(shí)可控時(shí)序上比串行模式更容易滿足ADC的建立時(shí)間要求MSP430的生態(tài)資料雖然不如STM32豐富但寄存器級(jí)開(kāi)發(fā)反而能逼著你把底層時(shí)序徹底吃透。選并行而非串行模式是個(gè)需要認(rèn)真權(quán)衡的決定。AD7606支持并行、串行和字節(jié)并行三種接口串行模式接線少SPI速率可以推到幾十MHz聽(tīng)起來(lái)很美好。但實(shí)際測(cè)試下來(lái)串行模式在8通道全開(kāi)、采樣率拉到200kSPS的情況下MCU的中斷壓力會(huì)非常大——因?yàn)槊總€(gè)通道16位數(shù)據(jù)都得按位或按字節(jié)往外搬。而并行模式一次讀操作就能拿下整通道數(shù)據(jù)時(shí)序圖干凈利落配合MSP430的P1/P2口可以直接掛16根數(shù)據(jù)線效率優(yōu)勢(shì)極其明顯。不過(guò)這里要潑一盆冷水并行驅(qū)動(dòng)的核心難點(diǎn)在于引腳資源占用。AD7606的DB0~DB15共16根數(shù)據(jù)線加上CS、RD、BUSY、FRSTDATA、RESET、OS0~OS2、RANGE、CONVST這些控制腳林林總總算下來(lái)要占掉二十多個(gè)GPIO。MSP430F5438A這種144腳的料還好說(shuō)換成64腳的MSP430F149就有點(diǎn)捉襟見(jiàn)肘。所以選型階段就得先把引腳地圖畫好哪些口做數(shù)據(jù)線、哪些口做控制線一定要提前規(guī)劃清楚否則后面layout階段會(huì)非常痛苦。1.2 項(xiàng)目實(shí)現(xiàn)目標(biāo)與功能邊界這個(gè)項(xiàng)目要做的事情其實(shí)很明確編寫一套可在MSP430上穩(wěn)定運(yùn)行的AD7606并行驅(qū)動(dòng)實(shí)現(xiàn)8通道模擬量的同步采樣通過(guò)BUSY引腳判斷轉(zhuǎn)換完成狀態(tài)把16位采樣結(jié)果存放到緩沖區(qū)供上層應(yīng)用比如FFT分析、閾值報(bào)警調(diào)用。功能邊界上我先不做DMAMSP430的DMA模塊觸發(fā)源和AD7606的BUSY引腳配合起來(lái)需要額外的映射配置也不做多緩沖乒乓切換把重點(diǎn)放在驅(qū)動(dòng)本身跑通、數(shù)據(jù)可靠讀出、性能可量化評(píng)估這三件事上。性能目標(biāo)我給自己定了個(gè)可測(cè)的指標(biāo)單次8通道完整采集流程從拉高CONVST到讀完最后一個(gè)通道的數(shù)據(jù)控制在180微秒以內(nèi)。這個(gè)數(shù)字怎么來(lái)的呢AD7606的最大轉(zhuǎn)換時(shí)間為4微秒200kSPS對(duì)應(yīng)的轉(zhuǎn)換周期加上并行讀8通道的時(shí)間每通道讀取約需1~2個(gè)時(shí)鐘周期即約1微秒左右再算上GPIO翻轉(zhuǎn)和循環(huán)開(kāi)銷理論上限應(yīng)該在120微秒附近。實(shí)際跑起來(lái)能做到160微秒就已經(jīng)很理想了留出20微秒的余量以兼容時(shí)鐘偏差和中斷延遲。2. AD7606并行接口時(shí)序與硬件設(shè)計(jì)2.1 并行模式下的引腳功能與連接要點(diǎn)先把AD7606的并行讀取時(shí)序吃透。整個(gè)轉(zhuǎn)換流程可以分解為四個(gè)階段CONVST拉高觸發(fā)采樣、BUSY引腳變高表示轉(zhuǎn)換進(jìn)行中、BUSY下降沿說(shuō)明轉(zhuǎn)換完成、然后通過(guò)CS和RD配合逐通道讀出數(shù)據(jù)。這里面最容易踩的坑有兩個(gè)第一個(gè)是CONVST的低電平脈沖寬度要求數(shù)據(jù)手冊(cè)規(guī)定最小25納秒MSP430的主頻如果是8MHz一個(gè)時(shí)鐘周期就是125納秒直接置高再拉低完全夠用但如果用低功耗模式的低頻時(shí)鐘比如32768Hz晶振就有問(wèn)題了第二個(gè)是RD下降沿到數(shù)據(jù)總線有效的延時(shí)t4最大值是17.4納秒這個(gè)參數(shù)決定了CPU頻率的上限——如果MSP430跑在16MHz時(shí)鐘周期62.5納秒理論上滿足要求但實(shí)際測(cè)量時(shí)數(shù)據(jù)線上的毛刺可能造成誤讀穩(wěn)妥做法是在RD低電平期間插入至少2個(gè)NOP指令。硬件連接方面我的方案是這樣安排的P1口整8位作DB0~DB7P2口整8位作DB8~DB15P3.0接CSP3.1接RDP3.2接BUSYP3.3接CONVST用一個(gè)引腳同時(shí)驅(qū)動(dòng)CONVST A和CONVST B因?yàn)楸卷?xiàng)目只用范圍A的V1~V8但請(qǐng)注意CONVST A和CONVST B在物理上是兩個(gè)引腳如果只接一路另一路必須拉低或拉高否則對(duì)應(yīng)通道不觸發(fā)轉(zhuǎn)換。FRSTDATA引腳接到P3.4用來(lái)判斷當(dāng)前讀到的數(shù)據(jù)是不是通道1的內(nèi)容調(diào)試時(shí)非常有用。RESET接P3.5RANGE接P4.0OS0~OS2接P4.1~P4.3。這里要特別強(qiáng)調(diào)一個(gè)很多人忽略的問(wèn)題AD7606的數(shù)字接口電壓范圍。它的VDRIVE引腳決定了數(shù)字I/O的電平標(biāo)準(zhǔn)本設(shè)計(jì)直接用3.3V供電給VDRIVE與MSP430的IO電平完全兼容。如果你用的是5V供電的VDRIVE就必須在中間加電平轉(zhuǎn)換電路否則MSP430的3.3V引腳直接連到5V邏輯的AD7606數(shù)據(jù)線上長(zhǎng)時(shí)間運(yùn)行會(huì)有損傷風(fēng)險(xiǎn)。2.2 并行讀取時(shí)序的參數(shù)計(jì)算AD7606的并行讀時(shí)序雖然不復(fù)雜但每一步的時(shí)序參數(shù)都必須對(duì)照數(shù)據(jù)手冊(cè)做驗(yàn)算。下面是我整理的關(guān)鍵參數(shù)表和對(duì)應(yīng)的MSP430操作約束參數(shù)說(shuō)明最小值/最大值MSP430側(cè)約束t1CS下降沿到RD下降沿的建立時(shí)間0ns最小CS提前拉低無(wú)需等待t3RD脈沖寬度21ns最小至少2個(gè)時(shí)鐘周期8MHz時(shí)250nst4RD下降沿到數(shù)據(jù)有效的延時(shí)17.4ns最大建議在RD低電平期間插入2~3個(gè)NOPt5RD高電平到數(shù)據(jù)線釋放17.4ns最大保證兩次讀取之間至少1個(gè)時(shí)鐘周期t6讀周期時(shí)間36ns最小連續(xù)讀操作間隔至少5個(gè)時(shí)鐘周期這幾個(gè)參數(shù)里t4是我在調(diào)驅(qū)動(dòng)時(shí)反復(fù)碰壁的地方。一旦MSP430主頻超過(guò)16MHz或代碼經(jīng)過(guò)編譯器優(yōu)化后把NOP指令優(yōu)化掉了數(shù)據(jù)線上就可能讀到毛刺。我最終的做法是在每次讀取數(shù)據(jù)后加一個(gè)__delay_cycles(3)實(shí)測(cè)下來(lái)穩(wěn)定性和可靠性都得到了明顯提升。有人可能覺(jué)得這浪費(fèi)了幾十個(gè)時(shí)鐘周期但ADC采集的場(chǎng)景里微秒級(jí)的延時(shí)開(kāi)銷在絕大多數(shù)應(yīng)用中是完全可以接受的。3. 并行驅(qū)動(dòng)程序?qū)崿F(xiàn)與寄存器配置3.1 寄存器級(jí)I/O配置的底層邏輯在寫驅(qū)動(dòng)之前得先把MSP430的GPIO寄存器配置思路理清楚。MSP430的每個(gè)端口都有PxDIR方向、PxIN輸入、PxOUT輸出、PxSEL功能選擇、PxREN上下拉使能、PxIES中斷邊沿選擇等寄存器。我們的數(shù)據(jù)總線是雙向的讀取AD7606數(shù)據(jù)時(shí)要設(shè)為輸入而控制信號(hào)CS、RD、CONVST等始終是輸出。由于AD7606的數(shù)據(jù)總線在空閑狀態(tài)下是高阻態(tài)MSP430的數(shù)據(jù)引腳必須啟用內(nèi)部下拉或上拉否則懸空狀態(tài)下讀數(shù)不確定。我實(shí)際使用的是內(nèi)部下拉電阻PxREN1PxOUT0因?yàn)閿?shù)據(jù)在RD有效時(shí)才會(huì)被AD7606驅(qū)動(dòng)為高或低其余時(shí)間保持低電平不會(huì)產(chǎn)生額外的功耗問(wèn)題??刂埔_的初始化比較簡(jiǎn)單但有一個(gè)細(xì)節(jié)值得留意所有控制信號(hào)的初始電平必須選好避免上電瞬間誤觸發(fā)了轉(zhuǎn)換或讀操作。比如CS初始置高禁止片選、RD初始置高不讀數(shù)據(jù)、CONVST初始置低不觸發(fā)采樣然后在主循環(huán)里再按需拉低。這個(gè)順序?qū)懛戳松想姾驛D7606可能會(huì)自發(fā)進(jìn)入讀周期數(shù)據(jù)線沖突燒壞IO口。void ad7606_gpio_init(void) { P1DIR 0x00; // P1口全部設(shè)為輸入 P1REN 0xFF; // 啟用下拉 P1OUT 0x00; P2DIR 0x00; P2REN 0xFF; P2OUT 0x00; P3DIR | BIT0 | BIT1 | BIT3 | BIT4 | BIT5; // CS、RD、CONVST、FRSTDATA、RESET P3OUT | BIT0 | BIT1 | BIT3; // CS1, RD1, CONVST1 P3OUT ~BIT5; // RESET0 P4DIR | BIT0 | BIT1 | BIT2 | BIT3; P4OUT ~BIT0; // RANGE0 ±5V輸入范圍 P4OUT ~(BIT1 | BIT2 | BIT3); // OS0/OS1/OS20 無(wú)過(guò)采樣 }3.2 AD7606寄存器配置與工作模式設(shè)置AD7606不像帶SPI寄存器的ADC那樣有一顆顆寄存器可寫除了軟件模式下的配置寄存器它靠引腳電平組合決定工作狀態(tài)。這意味著配置這個(gè)動(dòng)作在并行模式下就是拉幾個(gè)引腳的高電平。我這次用的配置是RANGE0±5V量程、OS0/OS1/OS2全為0關(guān)閉過(guò)采樣、CONVST A和CONVST B同時(shí)觸發(fā)確保8通道同步采樣。關(guān)于±5V和±10V量程的選擇我的建議是能用±5V就用±5V因?yàn)锳D7606內(nèi)部雖然放了輸入放大器但±10V檔的增益更大非線性誤差和噪聲指標(biāo)實(shí)測(cè)會(huì)比±5V檔差一些。根據(jù)數(shù)據(jù)手冊(cè)±10V量程下的積分非線性典型值是±2.5LSB而±5V量程下是±1.5LSB。如果你的傳感器輸出范圍足夠覆蓋±5V沒(méi)必要為了余量去犧牲精度。過(guò)采樣配置值得單獨(dú)說(shuō)一說(shuō)。AD7606的OS0~OS2支持2、4、8、16、32、64倍數(shù)字濾波能顯著提升信噪比。但代價(jià)是等效采樣率成倍下降開(kāi)了64倍過(guò)采樣后200kSPS的原始采樣率就變成3.125kSPS。我在這個(gè)項(xiàng)目里沒(méi)開(kāi)過(guò)采樣原因是我后續(xù)要接FFT做頻譜分析高采樣率比低噪聲更重要。如果是做靜態(tài)電壓監(jiān)測(cè)之類的應(yīng)用建議把過(guò)采樣開(kāi)到16倍效果非常明顯輸出數(shù)據(jù)的抖動(dòng)可以從±3LSB降到±1LSB以內(nèi)。配置完成后AD7606就處于等待觸發(fā)狀態(tài)。每次轉(zhuǎn)換周期都由CONVST引腳的上升沿啟動(dòng)而BUSY引腳會(huì)在轉(zhuǎn)換開(kāi)始時(shí)拉高、轉(zhuǎn)換結(jié)束后拉低。程序里判斷轉(zhuǎn)換是否完成的方法就是輪詢P3IN的BIT2位或者更高效的是用P3口的中斷功能但MSP430的端口中斷所有引腳共享一個(gè)向量需要額外判斷是哪個(gè)引腳反而更繁瑣我就沒(méi)用中斷。3.3 核心驅(qū)動(dòng)代碼與逐行邏輯解析驅(qū)動(dòng)的主函數(shù)結(jié)構(gòu)很簡(jiǎn)單初始化→觸發(fā)采樣→等待BUSY→循環(huán)讀取8通道→返回緩沖區(qū)。核心讀取函數(shù)如下void ad7606_read_all_channels(uint16_t *buf) { P3OUT ~BIT3; // CONVST拉低 P3OUT | BIT3; // CONVST拉高觸發(fā)轉(zhuǎn)換 P3OUT ~BIT3; // CONVST拉低恢復(fù)空閑 while (P3IN BIT2); // 等待BUSY拉低表示轉(zhuǎn)換完成 // 典型等待時(shí)間為4us無(wú)過(guò)采樣 P3OUT ~BIT0; // CS0片選有效 for (int i 0; i 8; i) { P3OUT ~BIT1; // RD0 __delay_cycles(4); // 等待數(shù)據(jù)穩(wěn)定t4參數(shù) buf[i] (P1IN) | (P2IN 8); P3OUT | BIT1; // RD1 __delay_cycles(2); // 保證兩次讀取間隔t6參數(shù) } P3OUT | BIT0; // CS1片選釋放 }這段代碼里有幾個(gè)細(xì)節(jié)值得展開(kāi)。首先是CONVST的脈沖寬度代碼里從拉低到再拉低經(jīng)歷了三次GPIO操作每條指令大約4個(gè)時(shí)鐘周期8MHz時(shí)500ns遠(yuǎn)大于手冊(cè)要求的25ns。其實(shí)可以更精簡(jiǎn)但考慮到GPIO操作本身有延時(shí)這種寫法最直觀且不會(huì)出錯(cuò)。其次是BUSY等待循環(huán)while (P3IN BIT2)在BUSY為高時(shí)持續(xù)卡住。這里有一個(gè)隱患如果AD7606沒(méi)有正確觸發(fā)轉(zhuǎn)換比如CONVST沒(méi)接好BUSY一直為高程序就會(huì)死循環(huán)。所以在正式代碼里我加了一個(gè)超時(shí)計(jì)數(shù)器最多等待100微秒超時(shí)就返回錯(cuò)誤碼。這個(gè)設(shè)計(jì)在后來(lái)的調(diào)試中救了我好幾次強(qiáng)烈建議保留。第三是數(shù)據(jù)讀取的字節(jié)拼裝順序buf[i] (P1IN) | (P2IN 8)P1口是低8位P2口是高8位。這個(gè)順序不能搞反否則算出來(lái)的電壓值會(huì)完全是亂的。調(diào)試時(shí)可以打印原始數(shù)據(jù)看是否滿足V1~V8的逐通道遞增規(guī)律這是最簡(jiǎn)單有效的自檢方法。4. 實(shí)測(cè)數(shù)據(jù)、波形調(diào)參與穩(wěn)定性驗(yàn)證4.1 直流信號(hào)精度測(cè)試與校準(zhǔn)驅(qū)動(dòng)寫完以后第一輪驗(yàn)證是用高精度直流源比如Fluke 5700A或者普通臺(tái)式萬(wàn)用表校準(zhǔn)過(guò)的穩(wěn)壓電源給每個(gè)通道輸入已知電壓觀察采樣值與理論值的偏差。我測(cè)了一個(gè)典型的1.000V輸入得到的原始碼值做了這樣一組對(duì)比通道理論碼值±5V量程實(shí)測(cè)碼值誤差LSB折合電壓誤差CH1163841638510.15mVCH21638416382-2-0.31mVCH3163841638730.46mVCH4163841638400mVCH5163841638620.31mVCH61638416381-3-0.46mVCH71638416383-1-0.15mVCH8163841638510.15mV這個(gè)結(jié)果在±3LSB以內(nèi)完全是AD7606手冊(cè)上說(shuō)的典型性能范圍。如果你的項(xiàng)目對(duì)精度要求更高可以考慮做兩點(diǎn)校準(zhǔn)零點(diǎn)校準(zhǔn)輸入0V讀偏置和增益校準(zhǔn)輸入滿量程90%電壓讀斜率然后把校準(zhǔn)系數(shù)固化到Flash里。這算是我個(gè)人的經(jīng)驗(yàn)之舉工業(yè)現(xiàn)場(chǎng)產(chǎn)品基本都會(huì)做這一步但實(shí)驗(yàn)室DIY經(jīng)常被忽略。4.2 動(dòng)態(tài)信號(hào)與采樣率實(shí)測(cè)直流測(cè)試通過(guò)后我用信號(hào)發(fā)生器輸入一個(gè)1kHz、2Vpp的正弦波到CH1配合上位機(jī)把采樣數(shù)據(jù)導(dǎo)出來(lái)做頻譜分析。觀察到的頻譜干凈1kHz處有一根明顯的譜線諧波分量低于-70dBFS說(shuō)明并行驅(qū)動(dòng)的時(shí)序抖動(dòng)對(duì)采樣質(zhì)量的影響非常小。時(shí)序抖動(dòng)是并行讀模式的一個(gè)隱形優(yōu)勢(shì)——因?yàn)闆](méi)有SPI的時(shí)鐘相位對(duì)齊問(wèn)題數(shù)據(jù)一到位馬上就能被CPU鎖定就不存在由位時(shí)鐘抖動(dòng)導(dǎo)致的偶發(fā)不同步。采樣率的實(shí)測(cè)我用示波器量了量CONVST引腳。連續(xù)觸發(fā)模式下兩次CONVST上升沿之間的間隔約為158微秒對(duì)應(yīng)有效采樣率約6.3kSPS。這個(gè)數(shù)值遠(yuǎn)低于AD7606的上限200kSPS但原因不在于驅(qū)動(dòng)本身而是MSP430在完成讀取之后還要做低通濾波和簡(jiǎn)單閾值判斷這部分也占了時(shí)間。如果純粹測(cè)試驅(qū)動(dòng)極限去掉業(yè)務(wù)代碼單次8通道讀取的耗時(shí)可以壓到約148微秒約合6.7kSPS。并行驅(qū)動(dòng)的開(kāi)銷占主要比重其中BUSY等待約4微秒、8通道讀取約44微秒、其余是GPIO翻轉(zhuǎn)和循環(huán)控制的開(kāi)銷。4.3 長(zhǎng)時(shí)間穩(wěn)定性和上電時(shí)序表現(xiàn)穩(wěn)定性測(cè)試我跑了整整72小時(shí)。具體做法是CH1接精密基準(zhǔn)源程序每秒鐘采樣1000次并記錄最大值、最小值、平均值通過(guò)串口打印到電腦。測(cè)試結(jié)束后觀察到的最大漂移是±2LSB平均值保持在16384附近沒(méi)有出現(xiàn)偶發(fā)的大毛刺或數(shù)據(jù)錯(cuò)位。這說(shuō)明并行驅(qū)動(dòng)在長(zhǎng)期運(yùn)行下非??煽繘](méi)有SPI模式偶爾出現(xiàn)的字節(jié)錯(cuò)位問(wèn)題。上電時(shí)序方面也做了一些驗(yàn)證。AD7606的RESET引腳上電后需要一個(gè)至少50ns的高電平脈沖來(lái)完成內(nèi)部初始化。MSP430上電后GPIO默認(rèn)是高阻態(tài)我在初始化函數(shù)里先延時(shí)100ms再配置GPIO然后給RESET拉低、再拉高、再拉低確保AD7606的復(fù)位時(shí)序滿足要求。如果你省掉這個(gè)復(fù)位操作芯片有概率在某個(gè)未知狀態(tài)啟動(dòng)首次轉(zhuǎn)換的數(shù)據(jù)會(huì)出現(xiàn)異常。5. 常見(jiàn)問(wèn)題與排查技巧實(shí)錄5.1 問(wèn)題排查速查表把我在調(diào)試過(guò)程中遇到的高頻問(wèn)題整理一下按癥狀、可能原因、解決方法梳理成下表。這算是本文最有實(shí)踐價(jià)值的部分建議收藏備用癥狀可能原因排查思路與解決辦法程序卡在BUSY等待循環(huán)CONVST引腳連接錯(cuò)誤或脈沖寬度不夠檢查P3.3是否確實(shí)翻轉(zhuǎn)用示波器量CONVST是否有3.3V高電平脈沖在等待循環(huán)中加超時(shí)退出讀取到的所有通道數(shù)據(jù)都是0xFFFF數(shù)據(jù)總線方向配置錯(cuò)誤P1/P2口仍為輸出檢查P1DIR和P2DIR是否設(shè)為0x00檢查CS和RD的極性是否正確數(shù)據(jù)有一定規(guī)律但不正確如所有通道都差一個(gè)固定偏移高低字節(jié)拼裝順序錯(cuò)誤檢查buf[i]賦值語(yǔ)句中P1IN和P2IN的左右位置用直流源輸入已知電壓驗(yàn)證某個(gè)通道的數(shù)據(jù)偶爾跳變到異常值該通道差分輸入短路或懸空RANGE引腳配置不合理檢查輸入信號(hào)是否正常用示波器看該通道的模擬輸入波形確認(rèn)RANGE電平是否按預(yù)期設(shè)置采樣率遠(yuǎn)低于預(yù)期業(yè)務(wù)代碼耗時(shí)過(guò)多GPIO操作未開(kāi)啟編譯器優(yōu)化用計(jì)時(shí)器測(cè)量單次讀取函數(shù)的耗時(shí)開(kāi)啟編譯優(yōu)化選項(xiàng)考慮將AD7606讀取放到高優(yōu)先級(jí)5.2 深度排查實(shí)錄一個(gè)折磨了兩天的數(shù)據(jù)錯(cuò)位問(wèn)題最后分享一個(gè)我印象深刻的bug。項(xiàng)目做到一半時(shí)我突然發(fā)現(xiàn)CH4的數(shù)據(jù)在低四位上偶爾會(huì)多出幾個(gè)不該有的bit波形圖上表現(xiàn)為細(xì)小的毛刺。查了很久前面提到的所有常見(jiàn)陷阱都排除了最后用示波器同時(shí)探CS、RD和D[11:0]數(shù)據(jù)線才發(fā)現(xiàn)了根源AD7606在RD下降沿之后數(shù)據(jù)線的驅(qū)動(dòng)強(qiáng)度并不足以在17.4ns內(nèi)把16條線全部穩(wěn)定到目標(biāo)電平尤其當(dāng)多條數(shù)據(jù)線同時(shí)從0翻轉(zhuǎn)到1時(shí)地彈效應(yīng)導(dǎo)致低四位數(shù)據(jù)線的上升沿出現(xiàn)了嚴(yán)重的振鈴。解決辦法其實(shí)很簡(jiǎn)單延長(zhǎng)RD低電平的保持時(shí)間把__delay_cycles(4)改成__delay_cycles(8)即8MHz下從500ns延長(zhǎng)到1微秒。這樣雖然把8通道的總讀取時(shí)間從約44微秒拉長(zhǎng)到了約52微秒但數(shù)據(jù)錯(cuò)位問(wèn)題徹底消失。這個(gè)調(diào)整也讓我對(duì)時(shí)序余量有了更深的體會(huì)——數(shù)據(jù)手冊(cè)上的最大延時(shí)是理論值實(shí)物板子上的走線寄生電容、電源噪聲都會(huì)讓實(shí)際信號(hào)變差留出足夠的讀窗口余量永遠(yuǎn)是更穩(wěn)健的設(shè)計(jì)思路。如果你用的是更高主頻的MSP430比如MSP430F5438A可以跑到25MHz建議把讀取延時(shí)改為按實(shí)際主頻計(jì)算__delay_cycles(CPU_FREQ_MHZ * 2 / 8)保證至少2微秒的RD低電平時(shí)間。但不要把延時(shí)增加到離譜的程度比如拉長(zhǎng)到10微秒以上那會(huì)直接拉低有效采樣率在高通道數(shù)場(chǎng)景下整體吞吐量會(huì)非常難看。6. 延伸思考與后續(xù)擴(kuò)展方向驅(qū)動(dòng)本身跑通之后其實(shí)還有很多值得繼續(xù)打磨的方向。一個(gè)是對(duì)數(shù)據(jù)緩沖區(qū)的管理如果采集通道多、采樣頻率高單緩沖區(qū)在讀取新數(shù)據(jù)時(shí)數(shù)據(jù)容易覆蓋已經(jīng)采好的數(shù)據(jù)可以考慮用雙緩沖機(jī)制交替存儲(chǔ)一輪填A(yù)區(qū)、一輪填B區(qū)應(yīng)用層在處理B區(qū)數(shù)據(jù)的同時(shí)DMA或CPU可以繼續(xù)填充A區(qū)。另一個(gè)方向是把BUSY引腳接到MSP430的定時(shí)器捕獲輸入上利用硬件邊沿檢測(cè)省去輪詢等待的CPU資源這樣在連續(xù)采樣模式下主循環(huán)可以騰出來(lái)做其他事。另外MSP430家族里有些型號(hào)自帶硬件乘法器配合AD7606做數(shù)字濾波會(huì)非常順手。比如開(kāi)8倍過(guò)采樣后再做一次滑動(dòng)平均濾波等效輸出位數(shù)能提升到接近18位。這個(gè)效果是用純硬件方案很難達(dá)到的。串行模式的問(wèn)題并不在于不能用而是在于高采樣率下MCU負(fù)擔(dān)較大但如果你把MSP430降頻到1MHz跑低功耗應(yīng)用SPI模式的功耗優(yōu)勢(shì)又會(huì)明顯起來(lái)。選擇哪種接口歸根到底還是由應(yīng)用場(chǎng)景的功耗、速率、引腳資源約束共同決定的。最后再分享一個(gè)我在測(cè)試中摸索到的小技巧AD7606的FRSTDATA引腳在串行模式用來(lái)標(biāo)記第一通道數(shù)據(jù)在并行模式下也可以用來(lái)做同步校驗(yàn)。我每次讀完8個(gè)通道后會(huì)順手檢查FIRSTDATA引腳的狀態(tài)——如果在讀取通道1時(shí)它確實(shí)是高電平而在通道2~8時(shí)都是低電平就說(shuō)明數(shù)據(jù)幀邊界完全同步。這個(gè)小習(xí)慣幫我攔住過(guò)好幾次因?yàn)榕渲缅e(cuò)亂導(dǎo)致的間歇性數(shù)據(jù)錯(cuò)位成本幾乎為零推薦你也加上。本文還有配套的精品資源點(diǎn)擊獲取