戰(zhàn):從GPIO到ePWM/ADC/SCI的配置與調(diào)試指南)
簡介TMS320F28027 例程包面向TI C2000系列嵌入式開發(fā)者適合學(xué)習(xí)數(shù)字信號(hào)處理與實(shí)時(shí)控制的人員使用。內(nèi)容圍繞SCI、ADC、EPWM、TIMER、SPI五大外設(shè)展開涵蓋串口通信收發(fā)、模擬量采集、PWM波形生成、定時(shí)器中斷以及SPI主從機(jī)通信等典型場景代碼結(jié)構(gòu)清晰便于二次移植。資源包共1102個(gè)文件壓縮后34.57MB包含200余個(gè)頭文件、100余個(gè)C源文件以及匯編程序、CMD鏈接腳本、CCS工程配置文件、PDF/Word說明文檔等其中工程文件可直接導(dǎo)入CCS環(huán)境運(yùn)行調(diào)試。目前已有1547人學(xué)習(xí)下載。包內(nèi)另附28027口袋實(shí)驗(yàn)室相關(guān)資料提供從寄存器配置到中斷處理的完整示例代碼有助于開發(fā)者快速掌握F28027硬件資源使用與軟件編程技巧是不可多得的入門參考工具。 干了這么多年C2000系列要說最皮實(shí)耐用、性價(jià)比又高的入門芯片TMS320F28027絕對(duì)排得上號(hào)。很多人第一次摸這顆片子都是因?yàn)椤绊?xiàng)目里要用它做電機(jī)控制”或者“數(shù)字電源”然后老老實(shí)實(shí)去TI官網(wǎng)下一堆例程結(jié)果打開工程一臉懵——頭文件套頭文件、寄存器名字又臭又長、編譯鏈接報(bào)錯(cuò)看不懂。這篇文章我就把自己從“拿到例程”到“跑通外設(shè)”再到“移植到自己板子”的完整經(jīng)驗(yàn)捋一遍重點(diǎn)講講F28027的例程到底怎么讀、怎么改、怎么調(diào)希望能讓剛接觸這顆芯片的朋友少走點(diǎn)彎路。1. 先搞明白F28027的例程到底在說什么1.1 F28027 在C2000家族里的定位F28027屬于C2000 Piccolo系列主頻60MHz帶一個(gè)C28x內(nèi)核外加一個(gè)CLA協(xié)處理器。這顆芯片最大的特點(diǎn)就是“外設(shè)豐富、管腳少、價(jià)格友好”特別適合用在電機(jī)磁場定向控制、數(shù)字開關(guān)電源、逆變器這類需要實(shí)時(shí)計(jì)算的場合。和動(dòng)不動(dòng)幾百個(gè)引腳的F28379D相比F28027就是個(gè)小個(gè)子干大事的典型高性價(jià)比優(yōu)點(diǎn)非常突出。例程這東西說白了就是TI官方把寄存器操作封裝成一個(gè)個(gè)可運(yùn)行的模板工程。你拿到手的DSP2802x_Device.h、DSP2802x_Examples.h這些頭文件本質(zhì)上就是一份“寄存器地圖”。很多初學(xué)者栽跟頭不是因?yàn)樗麄儾粫?huì)寫代碼而是不知道這批頭文件里哪些是芯片自帶的、哪些是例程自己加的一改就改出編譯錯(cuò)誤。所以讀懂例程的第一步是先弄清楚工程里文件的層級(jí)關(guān)系。1.2 拿到例程包后我先干了這幾件事下載官方例程包現(xiàn)在統(tǒng)一叫C2000Ware以前叫controlSUITE后別急著編譯先按我說的做先看device和common兩個(gè)目錄它們存放芯片支持庫和外設(shè)驅(qū)動(dòng)這是所有例程的地基。再打開任意一個(gè)Example_2802xGpioToggle這類工程對(duì)照原理圖找出LED對(duì)應(yīng)的GPIO管腳確認(rèn)例程里操作的是哪個(gè)GPIO。最后查一遍DSP2802x_GlobalPrototypes.h里的函數(shù)聲明搞明白每個(gè)模塊對(duì)外提供哪些接口。這一步做完你對(duì)整個(gè)工程就有了整體概念。之后你面對(duì)的不再是一堆看不懂的宏定義而是一條“外設(shè)寄存器 → 驅(qū)動(dòng)庫 → main函數(shù) → 你的邏輯代碼”的清晰鏈路。2. 環(huán)境搭建與例程工程骨架2.1 CCS版本、編譯器與目標(biāo)芯片的匹配F28027的例程最早是在CCS 3.3時(shí)代寫的但現(xiàn)在CCS也更新到十幾版本了。我實(shí)測下來用CCS 7.4以上版本打開老例程基本沒問題關(guān)鍵是編譯器版本不能太激進(jìn)。老例程用的是TI v16.9.0及之前的編譯規(guī)則你如果非要用最新版編譯器可能有幾十條warning甚至error。建議直接把編譯器版本固定為v16.9.0 LTS省得跟版本較勁。新建或?qū)牍こ虝r(shí)注意把設(shè)備型號(hào)選成TMS320F28027仿真器選XDS100v2或XDS110。有個(gè)小坑CCS新建工程默認(rèn)鏈接的cmd文件可能指向F28069這類大Flash型號(hào)導(dǎo)入老例程時(shí)一定要檢查工程屬性里的linker文件路徑確保用的是F28027.cmd。否則編譯通過燒進(jìn)去卻是跑飛的。2.2 例程工程的目錄結(jié)構(gòu)和編譯流程一個(gè)標(biāo)準(zhǔn)F28027例程工程的目錄是這樣的Example_2802xGpioToggle/ |-- DSP2802x_common/ // 公共外設(shè)驅(qū)動(dòng) |-- DSP2802x_headers/ // 寄存器映射定義 |-- Example_2802xGpioToggle.c // 主程序 |-- Example_2802xGpioToggle.cmd // 鏈接命令 |-- 2802x_xxx_lnk.cmd // 或者用這個(gè)編譯流程其實(shí)不復(fù)雜先編譯公共驅(qū)動(dòng)庫再編譯主程序最后鏈接生成out文件。我特別提醒一句F28027的Flash是64KBRAM更大大約12KB例子工程一般放在Flash里跑。如果發(fā)現(xiàn)程序一上電不運(yùn)行優(yōu)先檢查cmd文件里的FLASH段和RAM段是否分配正確。3. 核心外設(shè)例程拆解照著改就能用3.1 GPIO例程看似簡單但寄存器操作是基礎(chǔ)GPIO例程是所有例程里最簡單的但它能幫你建立“寄存器操作”的基本功。F28027的GPIO分成了A、B兩組每組又有控制寄存器GPxMUX、GPxDIR、GPxDAT、GPxSET、GPxCLEAR、GPxTOGGLE等等。官方例程里最常用的點(diǎn)亮LED寫法是這樣EALLOW; GpioCtrlRegs.GPAMUX1.bit.GPIO0 0; // 配置為普通GPIO功能 GpioCtrlRegs.GPADIR.bit.GPIO0 1; // 方向設(shè)為輸出 EDIS; GpioDataRegs.GPASET.bit.GPIO0 1; // 置高電平這里有一個(gè)新手最常見的疑問為什么修改寄存器前要寫EALLOW? 因?yàn)門I在設(shè)計(jì)芯片時(shí)為了防止程序跑飛導(dǎo)致管腳誤動(dòng)作把一部分關(guān)鍵寄存器設(shè)為“受保護(hù)”狀態(tài)。只有執(zhí)行EALLOW指令后這些寄存器才允許寫操作寫完再通過EDIS恢復(fù)保護(hù)。這個(gè)習(xí)慣如果你在一開始就養(yǎng)成后面配置ePWM、ADC時(shí)能少踩很多坑。3.2 ePWM例程電機(jī)控制和數(shù)字電源的核心F28027的ePWM模塊是它最值得研究的外設(shè)。例程里常見的是Example_2802xEPwmUpDownAQ這類演示“增/減計(jì)數(shù)模式”的工程。我把它拆成三步來講第一步是配置時(shí)基。ePWM模塊的時(shí)鐘來自系統(tǒng)時(shí)鐘經(jīng)過預(yù)分頻后的TBCLK你要通過TBCTL寄存器設(shè)置計(jì)數(shù)模式up、down、up-down和分頻系數(shù)。比如系統(tǒng)時(shí)鐘60MHzTBCLK分頻系數(shù)為1那么向上計(jì)數(shù)模式下的開關(guān)頻率就是60MHz / (2 * TBPRD)。第二步是配置動(dòng)作限定。動(dòng)作限定模塊決定了“計(jì)數(shù)到多少時(shí)輸出高/低/翻轉(zhuǎn)”通過AQCTLA、AQCTLB寄存器實(shí)現(xiàn)。最常用的配置是計(jì)數(shù)到零時(shí)輸出高電平計(jì)數(shù)到比較值CMPA時(shí)輸出低電平——這樣就能輸出占空比可調(diào)的PWM波形。第三步是死區(qū)。驅(qū)動(dòng)電機(jī)全橋或半橋電路時(shí)上管和下管的開關(guān)之間必須插入死區(qū)時(shí)間否則極易炸管。通過DBCTL配置死區(qū)模式再將DBRED和DBFED設(shè)為你想要的死區(qū)周期數(shù)。例如死區(qū)時(shí)間200nsTBCLK周期16.67ns那死區(qū)寄存器值就約等于12。一句話總結(jié)ePWM例程不是用來調(diào)占空比的而是用來幫你熟悉“時(shí)基 → 計(jì)數(shù) → 比較 → 動(dòng)作 → 死區(qū)”這條完整鏈路的。把這五個(gè)環(huán)節(jié)吃透任何PWM需求你都能套用。3.3 ADC例程采樣時(shí)序與觸發(fā)源才是重點(diǎn)F28027內(nèi)置12位逐次逼近型ADC前端有多個(gè)模擬輸入通道內(nèi)部還有一個(gè)多路復(fù)用器。例程里通常用軟件觸發(fā)或ePWM觸發(fā)。我個(gè)人強(qiáng)烈建議用ePWM觸發(fā)因?yàn)殡姍C(jī)控制需要在固定的PWM周期點(diǎn)上同步采樣電流軟件觸發(fā)容易受中斷延遲影響。ADC觸發(fā)配置的核心代碼大致如下AdcRegs.ADCSOC0CTL.bit.TRIGSEL 5; // 選擇ePWM1作為SOC0觸發(fā)源 AdcRegs.ADCSOC0CTL.bit.CHSEL 0; // ADCINA0通道 AdcRegs.ADCSOC0CTL.bit.ACQPS 15; // 采樣窗口決定采樣保持電容充電時(shí)間 AdcRegs.ADCCTL1.bit.ADCPWDN 1; // 上電 AdcRegs.ADCCTL1.bit.ADCCLKPS 3; // 內(nèi)核分頻 AdcRegs.ADCCTL2.bit.CLKDIV2EN 1; // 再分頻保證ADCCLK不超限采樣窗口ACQPS很多人隨便填其實(shí)這里很有講究。采樣窗口太短電容沒充滿轉(zhuǎn)換結(jié)果就不準(zhǔn)窗口太長轉(zhuǎn)換吞吐率下降。我自己的經(jīng)驗(yàn)是信號(hào)源內(nèi)阻高時(shí)ACQPS盡量大一點(diǎn)保證采樣精度信號(hào)源是運(yùn)放強(qiáng)驅(qū)動(dòng)時(shí)15~20就夠用。ADC還有兩個(gè)容易忽視的點(diǎn)第一F28027的ADC參考電壓可以用內(nèi)部參考也可以外部注入例程默認(rèn)內(nèi)部3.3V參考這時(shí)ADC滿量程對(duì)應(yīng)電壓就是3.3V采集值換算公式是電壓 ADC結(jié)果 * 3.3 / 4096第二ADC結(jié)果寄存器保存的是“轉(zhuǎn)換完成”時(shí)的值連續(xù)采樣模式下要注意結(jié)果覆蓋問題最好在中斷里及時(shí)搬運(yùn)數(shù)據(jù)。3.4 SCI串口例程調(diào)試信息怎么打出來F28027的SCI模塊就是UART配套例程如Example_2802xSci_Echoback可以幫你調(diào)通串口通信。配置SCI首要的是波特率。F28027的SCI時(shí)鐘來自低速外設(shè)時(shí)鐘LSPCLK分頻后被BRR寄存器二次分頻BRR (LSPCLK / (8 * 波特率)) - 1; // 標(biāo)準(zhǔn)模式比如LSPCLK 30MHz希望波特率9600那BRR約等于389。計(jì)算時(shí)注意所得值要四舍五入并且實(shí)際波特率誤差最好控制在2%以內(nèi)否則長幀傳輸容易亂碼。在例程里收發(fā)數(shù)據(jù)放在中斷里處理比輪詢效率高得多。調(diào)試階段我不推薦在中斷里直接塞大量復(fù)雜的解析邏輯而是先用回環(huán)模式確定物理鏈路通不通再用中斷方式檢查每個(gè)字節(jié)收發(fā)是否正確。OK之后再加幀頭、幀尾、校驗(yàn)這樣的協(xié)議層邏輯。4. 調(diào)試技巧與深度踩坑實(shí)錄4.1 斷點(diǎn)、變量監(jiān)視和Graph工具一個(gè)都別省F28027例程自帶的printf輸出不太直觀CCS的Graph工具才是真正神器。比如你想觀察ADC采集的電流波形可以設(shè)置數(shù)組緩存采樣值然后通過Tools - Graph - Single Time把數(shù)組內(nèi)容以波形形式顯示出來。這種方法比斷點(diǎn)看單個(gè)變量高效太多能讓你一眼發(fā)現(xiàn)采樣數(shù)據(jù)是否異常波動(dòng)。在線調(diào)試時(shí)建議設(shè)置“硬件斷點(diǎn)”。F28027這類MCU的Flash運(yùn)行環(huán)境下軟件斷點(diǎn)可能被編譯器優(yōu)化掉或受流水線影響。實(shí)際操作中我通常是先在RAM中調(diào)試好多例子工程也有RAM版本的cmd文件跑通后再切換Flash版本這樣斷點(diǎn)更可靠下載速度也快。4.2 常見編譯與鏈接錯(cuò)誤排查我自己帶的人最常踩這幾個(gè)坑#10008符號(hào)重復(fù)定義多半是因?yàn)楣こ汤镏貜?fù)包含了DSP2802x_GlobalVariableDefs.c檢查工程屬性里的排除構(gòu)建文件。#10234內(nèi)存范圍越界這是cmd文件和實(shí)際Flash/RAM大小不匹配換錯(cuò)芯片型號(hào)的cmd就會(huì)出現(xiàn)。[E0002] Failure to execute大概率是編譯器版本不兼容把編譯器換成例程默認(rèn)的v16.9.0基本能解決。排查時(shí)先看輸出窗口第一條error信息別急著從最后一條看。編譯器經(jīng)常一連串報(bào)幾十個(gè)錯(cuò)誤但真正的源頭往往在最前面。4.3 硬實(shí)時(shí)任務(wù)中“printf”的替代方案F28027的UART如果直接調(diào)用printf輸出調(diào)試信息DD重點(diǎn)來了——printf是阻塞的幾十微秒的延時(shí)容易讓PWM中斷錯(cuò)過觸發(fā)導(dǎo)致控制時(shí)序抖動(dòng)。我在實(shí)際項(xiàng)目中基本不用printf而是自己寫一個(gè)極簡的“日志變量組”把想觀察的變量放進(jìn)一個(gè)全局結(jié)構(gòu)體然后通過SCI的FIFO中斷異步發(fā)送出去。通訊協(xié)議也簡單幀頭 變量地址 數(shù)據(jù) 校驗(yàn)。這樣既不干擾控制環(huán)又能實(shí)時(shí)監(jiān)控內(nèi)部狀態(tài)。5. 從例程到產(chǎn)品化的幾個(gè)關(guān)鍵心得最后再說點(diǎn)個(gè)人體會(huì)。F28027的例程最大的作用是幫你熟悉芯片和外設(shè)但它并不是一份可以直接投產(chǎn)的“標(biāo)準(zhǔn)答案”。官方例程為了展示通用性代碼里有很多開關(guān)選項(xiàng)你在真正量產(chǎn)的時(shí)候要做的第一件事就是“瘦身”刪掉不用的外設(shè)初始化關(guān)掉沒必要的GPIO復(fù)用把中斷優(yōu)先級(jí)理清楚。拿電機(jī)控制舉例官方例程里的ADC結(jié)果是直接放在數(shù)組里的并沒有加卡爾曼濾波或均值濾波。到了產(chǎn)品里這個(gè)數(shù)組可能就變成環(huán)形緩沖區(qū)ADC結(jié)果會(huì)經(jīng)過至少一次滑動(dòng)平均PWM更新頻率、電流環(huán)FOC計(jì)算周期都要重新統(tǒng)籌。例程給你的是“能跑”你要做的是“跑得穩(wěn)”。所以我給你的建議是花三天時(shí)間把GPIO、ePWM、ADC、SCI四個(gè)例程逐個(gè)跑通再花一周時(shí)間把你需要的功能組合在一起加上保護(hù)邏輯和故障診斷這時(shí)候你手里的代碼才真正屬于你的項(xiàng)目。最后再分享一個(gè)小技巧F28027的CLA協(xié)處理器是個(gè)寶藏它能在后臺(tái)并行執(zhí)行數(shù)學(xué)運(yùn)算主CPU只負(fù)責(zé)邏輯判斷和外設(shè)管理??上Т蠖鄶?shù)例程只給出CLA空跑模板沒有發(fā)揮它的價(jià)值。你如果做數(shù)字電源或者電機(jī)FOC建議仔細(xì)研究一下CLA怎么搬運(yùn)數(shù)據(jù)、怎么和主核握手算法效率會(huì)有質(zhì)的提升。本文還有配套的精品資源點(diǎn)擊獲取