91欧美超碰AV自拍|国产成年人性爱视频免费看|亚洲 日韩 欧美一厂二区入|人人看人人爽人人操aV|丝袜美腿视频一区二区在线看|人人操人人爽人人爱|婷婷五月天超碰|97色色欧美亚州A√|另类A√无码精品一级av|欧美特级日韩特级

0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

【CW32無(wú)線抄表項(xiàng)目】W25Q_CW32_DMA簡(jiǎn)介

CW32生態(tài)社區(qū) ? 來(lái)源:CW32生態(tài)社區(qū) ? 作者:CW32生態(tài)社區(qū) ? 2026-03-31 21:41 ? 次閱讀
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

以前單片機(jī)搬運(yùn)數(shù)據(jù)(比如把串口收到的 100 個(gè)字節(jié)存進(jìn)數(shù)組),必須由 CPU 親自動(dòng)手:讀一個(gè)字節(jié)、存一個(gè)字節(jié)。搬磚的時(shí)候,CPU 沒(méi)法去算水表的流量,也沒(méi)法去管 4G 模塊。

DMA 就是一個(gè)‘專業(yè)的搬運(yùn)工’。 你只要告訴它:‘從哪搬(源)、搬到哪(目的)、搬多少(數(shù)量)’,然后 CPU 就可以去喝咖啡了,搬運(yùn)工作全交給 DMA 硬件電路自動(dòng)完成。等搬完了,它會(huì)敲敲門告訴 CPU:‘老板,活干完了?。ㄖ袛啵薄?/p>

階段一:CW32F030—DMA框圖

wKgZPGnLzu6AWUMsAAAjtKpduAU686.jpgwKgZPGnLzu6AY3jVAAB3srr3y6o337.jpg

一共三件事:誰(shuí)在干活?路怎么走?誰(shuí)在發(fā)號(hào)施令?

搬運(yùn)工小隊(duì):DMA 模塊 (Ch1 - Ch5)

在圖的最左側(cè),你會(huì)看到一個(gè)大方框,里面排著 Ch1 到 Ch5。這就是我們提到的 5 條獨(dú)立“傳送帶”。 比如 Ch1 的優(yōu)先級(jí)最高。如果你有 5 件事同時(shí)發(fā)生,DMA 會(huì)先緊著 Ch1 的活干。對(duì)于我們的項(xiàng)目,我們會(huì)占用其中兩條來(lái)負(fù)責(zé) SPI2 的收和發(fā)。

交通樞紐:Bus Matrix (總線矩陣)

圖中中心位置那個(gè)灰色的、帶有多個(gè)交叉點(diǎn)的長(zhǎng)條,這就是總線矩陣。它是單片機(jī)里的“立交橋”。

注意圖中有兩條并行的總線:AHB Bus (CPU) 和 AHB Bus (DMA)。

“大家發(fā)現(xiàn)了嗎?CPU 和 DMA 各有一條路通往總線矩陣。這意味著:當(dāng) DMA 在把數(shù)據(jù)從 SPI 搬往 SRAM 的時(shí)候,CPU 可以走另外一條路去執(zhí)行別的指令,互不干擾! 這就是為什么用了 DMA 后,單片機(jī)會(huì)變快的原因——因?yàn)橛袃蓚€(gè)‘人’同時(shí)在干活。”

貨源地與目的地:外設(shè)與存儲(chǔ)器

看圖的最右側(cè),那一排方塊就是數(shù)據(jù)要去的目的地。

AHB 設(shè)備:Flash(存程序)、SRAM(運(yùn)行數(shù)據(jù))、GPIO(點(diǎn)燈/按鍵)。

APB 設(shè)備:通過(guò)“AHB to APB 橋接器”連接的各種傳感器接口

避坑點(diǎn)“同一個(gè)橋下的設(shè)備,CPU 永遠(yuǎn)比 DMA 更有話語(yǔ)權(quán)?!?/strong> 如果兩個(gè)人都想訪問(wèn)同一個(gè)橋下的東西,DMA 得先給 CPU 讓路。

誰(shuí)在喊“開(kāi)工”? (DMA Requests)

注意看圖左側(cè)那兩條細(xì)細(xì)的箭頭:

Software (軟件觸發(fā)):CPU 直接下令:“現(xiàn)在,立刻,把這段數(shù)據(jù)拷走!”

Hardware (硬件觸發(fā)):外設(shè)(比如 SPI、UART)發(fā)信號(hào):“老板,我這兒攢夠 1 個(gè)字節(jié)了,快搬走吧!”

“對(duì)于我們的 SPI Flash 搬運(yùn),我們看的是下面的‘Hardware’箭頭。SPI2 會(huì)像敲門一樣給 DMA 發(fā)請(qǐng)求。”

階段三:邏輯分類(查閱 8.4 傳輸模式)

wKgZO2nLzu-AaWJCAAAx5DzGV9w489.jpg

邏輯分類——掌握 DMA 的 “搬運(yùn)套路”

開(kāi)關(guān) A:DMA_TRIGy.TYPE —— 誰(shuí)在喊“開(kāi)工”?

軟件觸發(fā) (TYPE=0)

話術(shù):這就好比你親自給搬運(yùn)工打電話:“喂,把這疊文件復(fù)印一下?!敝饕糜趦?nèi)存到內(nèi)存的數(shù)據(jù)拷貝。

硬件觸發(fā) (TYPE=1)

話術(shù):這就好比你在流水線上裝了個(gè)感應(yīng)器。SPI 接收到一個(gè)字節(jié),感應(yīng)器就響一下,搬運(yùn)工才動(dòng)一下。

開(kāi)關(guān) B:DMA_CSRy.TRANS —— 搬運(yùn)時(shí)的優(yōu)先級(jí)(重點(diǎn)!)

BULK 模式 (大批量傳輸, TRANS=0)

特點(diǎn)霸道、一次性干完、不許插隊(duì)。

比喻:就像一輛滿載的渣土車沖上高速,誰(shuí)也不讓,直到把貨卸完。

風(fēng)險(xiǎn):如果搬運(yùn)的數(shù)據(jù)量非常大(比如幾千個(gè)字節(jié)),DMA 會(huì)長(zhǎng)時(shí)間占用總線,導(dǎo)致 CPU 沒(méi)法訪問(wèn)內(nèi)存,你的程序看起來(lái)就像“假死”了一樣。

BLOCK 模式 (塊傳輸, TRANS=1)

特點(diǎn)禮貌、允許插隊(duì)、每搬一個(gè)就問(wèn)一下。

比喻:就像一個(gè)禮貌的快遞員,每過(guò)一個(gè)路口(搬完一個(gè)數(shù)據(jù)塊)都會(huì)停下來(lái)看看有沒(méi)有救護(hù)車(高優(yōu)先級(jí)的 CPU 指令或 DMA 通道)要先過(guò)。如果有,他先讓路。

優(yōu)點(diǎn):系統(tǒng)響應(yīng)速度快,不會(huì)讓 CPU 閑著。

在我們的水表網(wǎng)關(guān)項(xiàng)目中,我們應(yīng)該選擇 ‘硬件觸發(fā) BLOCK 傳輸模式’。

為什么?

因?yàn)槲覀冃枰浜?SPI2 的接收/發(fā)送信號(hào)(硬件觸發(fā))。

因?yàn)槲覀円?FreeRTOS。FreeRTOS 要求任務(wù)切換非??欤绻覀冇?BULK 模式一次性搬運(yùn)幾百個(gè)字節(jié),可能會(huì)導(dǎo)致 FreeRTOS 的高優(yōu)先級(jí)任務(wù)被‘堵在路口’進(jìn)不來(lái)。用 BLOCK 模式,能保證我們的 CPU 隨時(shí)能處理突發(fā)的 4G 通信或無(wú)線中斷。”

我們的 CW32 只有 8KB RAM,CPU 和 DMA 共享這條窄窄的內(nèi)存通道。如果 DMA 用 BULK(無(wú)間隙) 模式死死占住總線,CPU 就沒(méi)法從 RAM 里讀取 FreeRTOS 的任務(wù)指令,你的系統(tǒng)就會(huì)出現(xiàn)微小的“卡頓”。而圖中的 BLOCK 模式,利用這些微小的間隙,讓 CPU 和 DMA 實(shí)現(xiàn)了真正的并行工作

wKgZPGnLzu-AO24TAAA8IM--1SE875.jpg

起跑:SOFTSRC 信號(hào)的“發(fā)令槍”

硬件表現(xiàn):看最上面那根線 DMA_TRIGy.SOFTSRC。當(dāng) CPU 在寄存器里把這一位寫為 1 時(shí),電平瞬間拉高。

分析:這就是所謂的“軟件觸發(fā)”。不需要外設(shè)(如串口、SPI)給信號(hào),CPU 說(shuō)“開(kāi)始”,DMA 立即起跑。

呼吸:傳輸間隙(The Breather)

這是 BLOCK 模式最核心的硬件特征:

硬件表現(xiàn):觀察“傳輸間隙”和“數(shù)據(jù)傳輸時(shí)隙”。你會(huì)發(fā)現(xiàn),DMA 并不是一鼓作氣把所有數(shù)據(jù)搬完的,它每搬運(yùn)一個(gè)數(shù)據(jù)(比如從 SA 搬到 DA),就會(huì)停頓一下(傳輸間隙)。

為什么這么設(shè)計(jì)?“這就好比一個(gè)有禮貌的搬運(yùn)工。他每搬一箱貨,都會(huì)在路口停半秒,看看有沒(méi)有救護(hù)車(CPU 發(fā)出的緊急指令)要過(guò)。如果有,他就讓路,等救護(hù)車走了再搬下一箱。這就是 BLOCK 模式比 BULK 模式‘講理’的地方?!?/p>

關(guān)聯(lián)硬件:這個(gè)“停頓”就是手冊(cè)里提到的仲裁機(jī)制

算賬:地址與計(jì)數(shù)的“自動(dòng)加減法”

看圖底部的三組波形,這是 DMA 的“核心算法”在硬件上的體現(xiàn):

計(jì)數(shù)器倒計(jì)時(shí) (CNT):每經(jīng)過(guò)一個(gè)傳輸時(shí)隙,CNT 的值就從 3 變成 2,再變成 1。當(dāng)變?yōu)?0 時(shí),DMA 任務(wù)結(jié)束,自動(dòng)停止。

地址自增 (SRCADDR / DSTADDR)

細(xì)節(jié)分析:圖中顯示地址從 SA變成了 SA+2,再變成 SA+4。

教學(xué)點(diǎn):“大家注意這個(gè) +2!這意味著我們現(xiàn)在搬運(yùn)的數(shù)據(jù)寬度是 16 位(半字)。如果是 8 位(字節(jié))搬運(yùn),這里就是 +1;如果是 32 位(字)搬運(yùn),這里就是 +4。DMA 硬件會(huì)自動(dòng)根據(jù)你的設(shè)置來(lái)計(jì)算下一個(gè)目的地在哪,完全不用你操心?!?/p>

wKgZO2nLzvCAIobpAABjRgN2L-Q879.jpgwKgZPGnLzvCATr9LAAA7mONwlzo302.jpg

信號(hào)驅(qū)動(dòng):從“發(fā)令槍”變成“敲門聲”

波形觀察:看第一行 硬件觸發(fā)請(qǐng)求信號(hào)。它不再是一個(gè)長(zhǎng)電平,而是一個(gè)個(gè)短脈沖

硬件分析:這些脈沖就是在 表 8-2 里選的那些“頻道”發(fā)出來(lái)的。

比喻:“比如你正在用 SPI 讀 Flash。SPI 硬件每收到一個(gè)字節(jié),就會(huì)‘敲一下門’(發(fā)一個(gè)脈沖信號(hào))。DMA 聽(tīng)到敲門聲,才動(dòng)一下,搬一個(gè)字節(jié)。這就是所謂的硬件同步?!?/p>

一步一停:受控的傳輸間隙

波形觀察:注意看 傳輸間隙。在硬件觸發(fā)模式下,間隙的時(shí)間長(zhǎng)短不由 DMA 決定,而是由外設(shè)決定。

要點(diǎn):如果 SPI 跑得慢,兩個(gè)脈沖之間的距離就大,間隙就長(zhǎng);如果 SPI 跑得快,間隙就短。

對(duì) FreeRTOS 的意義:由于存在這些間隙,CPU 始終有機(jī)會(huì)插手總線。即使你在搬運(yùn) 500 個(gè)節(jié)點(diǎn)的大數(shù)據(jù),系統(tǒng)也不會(huì)因?yàn)?DMA 占線而導(dǎo)致任務(wù)切換卡頓。

經(jīng)典的 外設(shè) -> 內(nèi)存 地址配置

觀察最下面的 SA(源地址)和 DA(目的地址)波形,這是教科書級(jí)的配置案例:

源地址 (SA) 自動(dòng)自增

現(xiàn)象:圖中 DMA_SRCADDRy 隨傳輸進(jìn)程從 SA 累加。

原理:我們要把 RAM 數(shù)組里準(zhǔn)備好的數(shù)據(jù)包按順序取出來(lái),所以地址必須自增。

目的地址 (DA) 保持不變

現(xiàn)象:圖中 DMA_DSTADDRy 始終固定在 DA。

原理:數(shù)據(jù)被搬運(yùn)到了外設(shè)的發(fā)送寄存器(如串口發(fā)送口)。外設(shè)寄存器地址是固定的,這就是所謂的“單點(diǎn)取貨口”。

軟件觸發(fā):通常用于“內(nèi)存 -> 內(nèi)存” (M2M)

對(duì)應(yīng)的就是圖 8-2。

場(chǎng)景:把數(shù)組 A 的數(shù)據(jù)拷貝到數(shù)組 B。

邏輯:源頭是內(nèi)存(自增),目的地也是內(nèi)存(自增)。

結(jié)果:你看到 SA和 DA 都在同步增長(zhǎng)(SA+1, DA+1...)。

硬件觸發(fā):通常用于“內(nèi)存 -> 外設(shè)” (M2P) 或 “外設(shè) ->內(nèi)存” (P2M)

對(duì)應(yīng)你看到的圖 8-5(發(fā)送場(chǎng)景)。

場(chǎng)景:把 RAM 里的數(shù)據(jù)包通過(guò)串口發(fā)出去。

邏輯:源頭是內(nèi)存(自增),目的地是串口發(fā)送寄存器(固定)。

結(jié)果:你看到 SA 在增長(zhǎng),而 DA 像根橫線一樣死死不動(dòng)。

三、 如果換成“硬件觸發(fā)讀取”,DA 也會(huì)加!

想象一下:如果你現(xiàn)在用 DMA 接收串口數(shù)據(jù)(P2M),情況就反過(guò)來(lái)了:

源地址 (SA):串口接收寄存器 固定(守株待兔)。

目的地址 (DA):RAM 接收數(shù)組 自增(按順序排隊(duì))。

結(jié)論:在硬件觸發(fā)的接收模式下,DA 是會(huì)自增的。所以,地址動(dòng)不動(dòng),完全取決于你搬運(yùn)的目標(biāo)是“一個(gè)點(diǎn)”還是“一排位置”。

wKgZO2nLzvGAdX6lAABt3L0UYOQ292.jpg

階段四:進(jìn)階技能(重點(diǎn)看 8.6 DMA 中斷)

大家想象一下,DMA 在后臺(tái)幫我們搬運(yùn) 512 字節(jié)的水表數(shù)據(jù)。CPU 不可能一直盯著它看(輪詢),那樣太累了。 我們希望:DMA 搬完了,或者搬運(yùn)出錯(cuò)了,能主動(dòng)‘敲敲 CPU 的門’(觸發(fā)中斷),告訴我們結(jié)果。這就是手冊(cè) 8.6 節(jié)講的內(nèi)容。

標(biāo)準(zhǔn)動(dòng)作:中斷的“三步走” (對(duì)照表 8-4)

很多初學(xué)者寫完中斷函數(shù)發(fā)現(xiàn)只進(jìn)去了一次,程序就死機(jī)了。這是因?yàn)闆](méi)搞清楚表 8-4 里的 “SOP(標(biāo)準(zhǔn)作業(yè)程序)”

第一步:開(kāi)門 (使能)

在初始化代碼里,你需要把開(kāi)關(guān)撥到 1:

想讓它搬完就報(bào)信?設(shè)置 TCIE = 1(Transfer Complete Interrupt Enable)。

想讓它出錯(cuò)就報(bào)警?設(shè)置 TEIE = 1(Transfer Error Interrupt Enable)。

第二步:進(jìn)屋 (中斷服務(wù)程序)

當(dāng)信號(hào)觸發(fā),CPU 會(huì)自動(dòng)跳進(jìn) DMA_IRQHandler(中斷函數(shù))。

第三步:打掃衛(wèi)生 (清除標(biāo)志位) —— 極其關(guān)鍵!

看表 最右邊一列:“設(shè)置 DMA_ICR.TCy 為 0”。

“這就好比敲門。DMA 把門敲響了,如果你進(jìn)屋處理完事情,不把那個(gè)門鈴關(guān)掉(清標(biāo)志位),CPU 就會(huì)認(rèn)為門一直在響,從而陷入死循環(huán),500 節(jié)點(diǎn)程序就卡死在這兒了!”

FreeRTOS 實(shí)戰(zhàn):如何讓 8KB RAM 飛起來(lái)?

在網(wǎng)關(guān)項(xiàng)目中,不需要在中斷函數(shù)里寫復(fù)雜的邏輯。用 “二值信號(hào)量 (Binary Semaphore)”

實(shí)戰(zhàn)邏輯:

任務(wù) A (讀水表):配置好 DMA,開(kāi)啟中斷,然后調(diào)用 xSemaphoreTake(xSem_DMA, portMAX_DELAY)。此時(shí)任務(wù) A 進(jìn)入阻塞(睡眠)狀態(tài),完全不占 CPU。

DMA 搬運(yùn):硬件自動(dòng)搬運(yùn),CPU 在跑別的任務(wù)(比如 4G 通訊)。

DMA 中斷:搬完了,進(jìn)入 DMA_IRQHandler。

釋放信號(hào)量:在中斷里清除標(biāo)志位,執(zhí)行 xSemaphoreGiveFromISR(xSem_DMA)。

喚醒:任務(wù) A 瞬間醒來(lái),處理數(shù)據(jù)。

初始狀態(tài):xSemaphoreCreateBinary 創(chuàng)建出來(lái)的信號(hào)量默認(rèn)就是 0。所以任務(wù)執(zhí)行到 xSemaphoreTake 時(shí)肯定會(huì)卡住,這正是我們想要的——讓它等中斷。

FromISR 的重要性:在中斷里嚴(yán)禁使用xSemaphoreGive。必須帶 FromISR,否則會(huì)導(dǎo)致系統(tǒng)內(nèi)核崩潰。

portYIELD_FROM_ISR:這一行非常關(guān)鍵。如果沒(méi)有它,雖然信號(hào)量給了,但系統(tǒng)可能要等到下一個(gè)“時(shí)鐘滴答(Tick)”才會(huì)切換任務(wù)。加上它,任務(wù) A 就能“秒醒”。

#include "FreeRTOS.h"
#include "task.h"
#include "semphr.h"
#include "cw32f030_dma.h"
#include "cw32f030_uart.h"
// 1. 定義信號(hào)量句柄
SemaphoreHandle_t xSem_DMA_Complete = NULL;
// 模擬數(shù)據(jù)緩沖區(qū)
uint8_t MeterDataBuffer[64];
// ==========================================
// 任務(wù) A:水表數(shù)據(jù)處理任務(wù)
// ==========================================
void Task_WaterMeter(void *pvParameters) {
    // 創(chuàng)建二值信號(hào)量(初始為 0,即“沒(méi)票”)
    xSem_DMA_Complete = xSemaphoreCreateBinary();
    for(;;) {
        // --- 第一步:配置并啟動(dòng) DMA ---
        // 假設(shè)這里配置 DMA 從 SPI (PAN3031) 搬運(yùn)數(shù)據(jù)到 MeterDataBuffer
        // DMA_Cmd(DMA_CH1, ENABLE); 
        // --- 第二步:阻塞等待信號(hào)量 ---
        // portMAX_DELAY 表示一直等,直到 DMA 中斷把信號(hào)量交出來(lái)
        // 此時(shí)任務(wù)進(jìn)入“阻塞態(tài)”,CPU 會(huì)自動(dòng)去跑 4G 任務(wù),完全不浪費(fèi)電力
        if(xSemaphoreTake(xSem_DMA_Complete, portMAX_DELAY) == pdPASS) {

            // --- 第五步:任務(wù)喚醒,處理數(shù)據(jù) ---
            // 當(dāng)代碼運(yùn)行到這里,說(shuō)明 DMA 已經(jīng)搬完了!
            printf("DMA 搬運(yùn)完成,開(kāi)始解析水表數(shù)據(jù)...n");
            // 處理 MeterDataBuffer...
        }
    }
}
// ==========================================
// DMA 中斷服務(wù)函數(shù) (硬件自動(dòng)觸發(fā))
// ==========================================
void DMA_CH1_IRQHandler(void) {
    BaseType_t xHigherPriorityTaskWoken = pdFALSE;
    // --- 第三步:檢查并清除標(biāo)志位 ---
    if (DMA_GetITStatus(DMA_IT_TC1)) {
        DMA_ClearITPendingBit(DMA_IT_TC1); // 必須手動(dòng)清零,否則會(huì)死循環(huán)
        // --- 第四步:釋放信號(hào)量喚醒任務(wù) ---
        // 注意:中斷里必須使用 FromISR 后綴的函數(shù)
        xSemaphoreGiveFromISR(xSem_DMA_Complete, &xHigherPriorityTaskWoken);
        /*當(dāng)你在中斷里調(diào)用 xSemaphoreGiveFromISR 時(shí),
        FreeRTOS 內(nèi)核會(huì)做一件重要的事情:檢查被喚醒的任務(wù)(任務(wù) A)的優(yōu)先級(jí)。
        它的邏輯非常簡(jiǎn)單:“如果標(biāo)志位是 TRUE,就手動(dòng)觸發(fā)一次任務(wù)調(diào)度(Context Switch)?!?
        如果沒(méi)有這一行代碼,會(huì)發(fā)生什么?
        中斷結(jié)束,CPU 返回剛才被中斷的任務(wù)繼續(xù)跑。
        任務(wù) A 雖然醒了(處于就緒態(tài)),但必須等到下一個(gè)“系統(tǒng)時(shí)鐘滴答(Tick)”或者當(dāng)前任務(wù)主動(dòng)放棄 
        CPU 時(shí),內(nèi)核才會(huì)發(fā)現(xiàn)任務(wù) A 優(yōu)先級(jí)更高并進(jìn)行切換。
        這會(huì)帶來(lái) 毫秒級(jí) 的延遲,對(duì)于高速通訊來(lái)說(shuō)可能導(dǎo)致數(shù)據(jù)溢出

        // 如果喚醒的任務(wù)優(yōu)先級(jí)更高,立即進(jìn)行一次“任務(wù)切換”
        // 這樣任務(wù) A 能在中斷結(jié)束的一瞬間就開(kāi)始干活,沒(méi)有延遲*/

        portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
    }
}
// ==========================================
// 任務(wù) B:4G 通訊任務(wù) (模擬 CPU 忙碌)
// ==========================================
void Task_4G_Comm(void *pvParameters) {
    for(;;) {
        // 這里的邏輯在任務(wù) A 睡覺(jué)時(shí)依然在運(yùn)行
        // 比如不停地查詢 4G 模塊狀態(tài)、心跳包等
        printf("4G 任務(wù)正在運(yùn)行,不影響水表讀取...n");
        vTaskDelay(pdMS_TO_TICKS(1000));
    }
}
int main(void) {
    // 基礎(chǔ)硬件初始化...

    // 創(chuàng)建任務(wù)
    xTaskCreate(Task_WaterMeter, "Meter", 256, NULL, 3, NULL); // 優(yōu)先級(jí)高
    xTaskCreate(Task_4G_Comm,     "4G",    256, NULL, 2, NULL); // 優(yōu)先級(jí)中
    vTaskStartScheduler(); // 啟動(dòng)調(diào)度器
    while(1);
}

特性 二值信號(hào)量 (Binary) 計(jì)數(shù)型信號(hào)量 (Counting)
數(shù)值范圍 0 或 1 0 到 最大值 (用戶設(shè)定)
核心功能 同步 (Synchronization) 資源管理 (Resource Management)
通俗理解 “一個(gè)通知”:要么來(lái)了,要么沒(méi)來(lái) “一堆門票”:還剩幾張,被領(lǐng)了幾張
典型關(guān)系 1 對(duì) 1 1 對(duì) 多(或 N 次事件)

二值信號(hào)量:最強(qiáng)“同步鬧鐘”

正如 DMA 實(shí)戰(zhàn)邏輯里寫的,它最大的作用是“等一個(gè)信號(hào)”。

適用場(chǎng)合:?jiǎn)温酚布庠O(shè)完成、單一事件觸發(fā)。

網(wǎng)關(guān)項(xiàng)目舉例: 你的 4G 模塊發(fā)送。任務(wù) A 調(diào)用 AT+CIPSEND 后就 xSemaphoreTake 睡死。當(dāng)串口 DMA 真正搬運(yùn)完最后一個(gè)字符并收到 4G 模塊的 SEND OK 后,中斷給出一個(gè)信號(hào)量。任務(wù) A 瞬間醒來(lái)確認(rèn)結(jié)果。

特點(diǎn):任務(wù)只關(guān)心“發(fā)沒(méi)發(fā)完”,不關(guān)心發(fā)了多少次。

計(jì)數(shù)型信號(hào)量:高效“資源管家”

場(chǎng)景:假設(shè)你的網(wǎng)關(guān)有 3 個(gè)串口(UART1, 2, 3) 都可以用來(lái)上報(bào)數(shù)據(jù),但你只想同時(shí)開(kāi)啟 2 個(gè)以節(jié)省功耗。

用法:創(chuàng)建一個(gè)最大值為 2 的計(jì)數(shù)信號(hào)量。

任務(wù) 1 想發(fā)數(shù)據(jù):Take 掉一個(gè)(剩 1)。

任務(wù) 2 想發(fā)數(shù)據(jù):Take 掉一個(gè)(剩 0)。

任務(wù) 3 想發(fā)數(shù)據(jù):發(fā)現(xiàn)沒(méi)票了,在門口排隊(duì)(阻塞)。

任務(wù) 1 發(fā)完:Give 回一張票(剩 1),任務(wù) 3 立即拿票進(jìn)場(chǎng)。

還有一個(gè)隱藏選手:互斥量 (Mutex)

互斥量 (Mutex):帶有“優(yōu)先級(jí)繼承”機(jī)制。

適用場(chǎng)合:保護(hù)共享資源(比如 500 個(gè)節(jié)點(diǎn)共用的那個(gè) WaterPulseCount 全局大變量)。

區(qū)別:二值信號(hào)量通常由“外設(shè)給,任務(wù)拿”;互斥量則是“任務(wù) A 拿,任務(wù) A 釋放”。

階段五:實(shí)戰(zhàn)落地(查閱 8.7 & 8.8 寄存器列表)

wKgZPGnLzvGAZqmHAABwOqTWQT0150.jpg

一、 核心配置:決定“從哪搬、搬多少”

這三個(gè)寄存器是所有 DMA 傳輸?shù)幕僖粋€(gè)都跑不起來(lái)。

寄存器名稱 教學(xué)重點(diǎn) 為什么重要
DMA_SRCADDRy 源地址:貨在哪里? 告訴 DMA 數(shù)據(jù)的起始物理地址。
DMA_DSTADDRy 目的地址:往哪搬? 告訴 DMA 數(shù)據(jù)存放在哪里。
DMA_CNTy 傳輸數(shù)量:搬多少次? 重點(diǎn)提醒:它是個(gè)“倒計(jì)時(shí)器”,每搬一個(gè),值減 1,減到 0 就停。

wKgZO2nLzvKACML4AACCKnBWLAo407.jpg

二、DMA_CSRy (控制及狀態(tài)寄存器) —— 全場(chǎng)最核心

這是 DMA 通道的“大腦”。重點(diǎn)介紹其中的這幾個(gè)位:

EN (位 0):總開(kāi)關(guān)。配完所有參數(shù),最后再點(diǎn)火。

SIZE (位 7:6):你是搬 8 位的字節(jié)、還是 32 位的字?(對(duì)應(yīng)你的水表數(shù)據(jù)結(jié)構(gòu))。

SINC / DSTINC (位 4 / 5):地址要不要自增?(回憶我們之前分析的:外設(shè)不加,內(nèi)存加)。

TRANS (位 3):選擇 BLOCK 還是 BULK 模式。

wKgZPGnLzvOAUylgAACEfid6ToU835.jpg

三、DMA_TRIGy (觸發(fā)源控制寄存器) —— 全場(chǎng)最核心

TYPE (位 0):你是要“軟件點(diǎn)火”還是“硬件敲門”?

HARDSRC (位 7:2):也就是那張 表 8-2 里的頻道號(hào)。比如要用 SPI2 搬運(yùn),這里就得填入對(duì)應(yīng)的編碼。

wKgZO2nLzvOAO4UPAAAcujwukVI656.jpgwKgZPGnLzvSAMHsrAABVsNz6zQY216.jpgwKgZO2nLzvSAbVAtAABuCrFS0HA547.jpg

張表非常規(guī)律,從位 0 到位 17,其實(shí)就是 5 組相同的信號(hào)。每一路通道(Channel)都配有兩個(gè)“燈”:

燈 A:TC (Transfer Complete) —— 傳輸完成標(biāo)志

位地址:位 0, 4, 8, 12, 16(分別對(duì)應(yīng)通道 1, 2, 3, 4, 5)。

含義:這是“綠燈”。當(dāng) TC = 1 時(shí),表示這一批次的數(shù)據(jù)(你在 CNT 寄存器里設(shè)定的數(shù)量)已經(jīng)全部安全送達(dá)目的地。

實(shí)戰(zhàn)邏輯:在你的 500 節(jié)點(diǎn)項(xiàng)目中,當(dāng)讀取 Flash 的 DMA 完成時(shí),你會(huì)看到這個(gè)位變 1。

燈 B:TE (Transfer Error) —— 傳輸錯(cuò)誤標(biāo)志

位地址:位 1, 5, 9, 13, 17(分別對(duì)應(yīng)通道 1, 2, 3, 4, 5)。

含義:這是“紅燈”。正常情況下它應(yīng)該是 0。如果變成 1,說(shuō)明出事了!

報(bào)錯(cuò)原因:通常是地址指錯(cuò)了(越界)或者總線訪問(wèn)沖突。如果看到這個(gè)位亮了,就要去檢查 SRCADDR 和 DSTADDR 有沒(méi)有寫對(duì)。

通道編號(hào) 成功看這里 (TC) 失敗看這里 (TE)
通道 1 位 0 位 1
通道 2 位 4 位 5
通道 3 位 8 位 9
通道 4 位 12 位 13
通道 5 位 16 位 17

大家看,這寄存器就像一排指示燈。如果你用的是通道 2(CH2)來(lái)傳串口數(shù)據(jù),你就盯著第 4 位看。一旦第 4 位變成了 1,就說(shuō)明你的數(shù)據(jù)已經(jīng)躺在內(nèi)存里等著你處理了!

注意

DMA_ISR 是“只讀”的

如果你在中斷服務(wù)程序里發(fā)現(xiàn)了 TC1 = 1,處理完業(yè)務(wù)后,你必須去 DMA_ICR(清除寄存器) 對(duì)應(yīng)的位寫一個(gè) 0。

后果警告:如果你不跑去 DMA_ICR 清除這個(gè)標(biāo)志,DMA_ISR 里的那個(gè) 1 就會(huì)一直亮著。單片機(jī)會(huì)認(rèn)為“怎么還沒(méi)處理完?”,然后瘋狂地重復(fù)進(jìn)入中斷,直到你的程序死機(jī)

為什么我們要學(xué) DMA_ISR?因?yàn)樵?FreeRTOS 里,我們不希望 CPU 浪費(fèi)時(shí)間去等。我們讓任務(wù)去‘睡覺(jué)’(掛起),等 DMA 搬完磚,硬件會(huì)自動(dòng)點(diǎn)亮 DMA_ISR 里的 TC 燈,觸發(fā)中斷。中斷里看一眼這個(gè)燈,確定沒(méi)問(wèn)題了,再發(fā)個(gè)信號(hào)量把任務(wù)叫醒。這種‘事畢報(bào)信’的機(jī)制,才是單片機(jī)在 8KB RAM 下還能高效運(yùn)行的秘密

在中斷服務(wù)函數(shù)(ISR)中干的事:

動(dòng)作:快進(jìn)快出。

職責(zé) 1:清除硬件中斷標(biāo)志位(滅燈)。

職責(zé) 2:釋放信號(hào)量或發(fā)送任務(wù)通知(報(bào)信)。

職責(zé) 3:如果喚醒的任務(wù)優(yōu)先級(jí)更高,觸發(fā)任務(wù)切換(上下文切換)。

在任務(wù)(Task)中干的事:

動(dòng)作:等待信號(hào)量(睡覺(jué))。

職責(zé) 1:拿到信號(hào)量后,處理真正耗時(shí)的業(yè)務(wù)邏輯(如解析數(shù)據(jù)包、存入 Flash、計(jì)算校驗(yàn)和)。

職責(zé) 2:處理完后重新配置下一輪的 DMA。

四、DMA_ICR中斷標(biāo)志清除寄存器 (Interrupt Clear Register)

寄存器全稱:中斷標(biāo)志清除寄存器 (Interrupt Clear Register)

它的核心作用:當(dāng) CPU 處理完 DMA 的中斷任務(wù)后,必須通過(guò)這個(gè)寄存器告訴硬件:“我已經(jīng)知道了,你可以把報(bào)告撤下去了?!?/p>

物理聯(lián)系:它和 DMA_ISR 是一一對(duì)應(yīng)的。ISR 負(fù)責(zé)告狀,ICR 負(fù)責(zé)撤訴。

權(quán)限密碼:為什么是 R1W0?

這張表里有一個(gè)非常獨(dú)特的權(quán)限說(shuō)明:R1W0

官方解釋

R1 (Read 1):無(wú)論當(dāng)前中斷是否發(fā)生,你用代碼去讀這個(gè)寄存器,它吐給你的數(shù)據(jù)全是 1(即 0xFFFFFFFF)。

W0: 清除通道標(biāo)志;W1: 無(wú)功能。

大白話翻譯:這是一個(gè)“寫 0 觸發(fā)”的機(jī)關(guān)。

如果你想清除通道 1 的完成標(biāo)志(TC1),你得往位 0 寫一個(gè)數(shù)字 0

如果你往這里寫 1,硬件會(huì)當(dāng)沒(méi)看見(jiàn),什么都不會(huì)發(fā)生。

提醒:這和很多單片機(jī)(如 STM32)“寫 1 清零”的習(xí)慣正好相反。

wKgZPGnLzvWAeCUpAABtDqAsy6E322.jpg

審核編輯 黃宇

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問(wèn)題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • 無(wú)線抄表
    +關(guān)注

    關(guān)注

    0

    文章

    40

    瀏覽量

    17435
  • CW32
    +關(guān)注

    關(guān)注

    1

    文章

    323

    瀏覽量

    1935
收藏 人收藏
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

    評(píng)論

    相關(guān)推薦
    熱點(diǎn)推薦

    CW32無(wú)線表項(xiàng)目】主控及射頻芯片介紹

    對(duì)于開(kāi)發(fā)者而言,CW32F030 的硬件設(shè)計(jì)在同類 M0+ 芯片中具有極強(qiáng)的競(jìng)爭(zhēng)力。
    的頭像 發(fā)表于 04-01 17:06 ?3800次閱讀
    【<b class='flag-5'>CW32</b><b class='flag-5'>無(wú)線</b><b class='flag-5'>抄</b><b class='flag-5'>表項(xiàng)目</b>】主控及射頻芯片介紹

    CW32移植Free-RTOS】CW32開(kāi)發(fā)者扶持計(jì)劃

    CW32配置Free-RTOS全過(guò)程,CW32開(kāi)發(fā)者扶持計(jì)劃
    的頭像 發(fā)表于 04-18 09:38 ?7503次閱讀
    【<b class='flag-5'>CW32</b>移植Free-RTOS】<b class='flag-5'>CW32</b>開(kāi)發(fā)者扶持計(jì)劃

    CW32快速開(kāi)發(fā)入門

    CW32快速開(kāi)發(fā)入門
    的頭像 發(fā)表于 04-24 18:56 ?3768次閱讀
    <b class='flag-5'>CW32</b>快速開(kāi)發(fā)入門

    項(xiàng)目展示】基于CW32的遙控循跡小車

    CW32循跡小車.zip_免費(fèi)高速下載|百度網(wǎng)盤-分享無(wú)限制? 一、概述 CW32循跡、遙控小車具有循跡和遙控兩種功能,小車的硬件模塊由CW32F030C8T6小藍(lán)板、智能小車控制底板、BT04-E
    的頭像 發(fā)表于 05-31 17:33 ?2597次閱讀
    【<b class='flag-5'>項(xiàng)目</b>展示】基于<b class='flag-5'>CW32</b>的遙控循跡小車

    CW32無(wú)線表項(xiàng)目W25Q+CW32程序示例

    /Armink/SFUD 一、程序分析 硬件總線映射(引腳與時(shí)鐘的“避坑點(diǎn)”) ? #define FLASH_SPIx CW_SPI2// 注意:CW32 中 SPI1 在 APB2 總線,而 SPI2 通常
    的頭像 發(fā)表于 03-31 21:29 ?4180次閱讀
    【<b class='flag-5'>CW32</b><b class='flag-5'>無(wú)線</b><b class='flag-5'>抄</b><b class='flag-5'>表項(xiàng)目</b>】<b class='flag-5'>W25Q+CW</b>32程序示例

    CW32 MCU有哪些系列?

    目前CW32 MCU有通用高性能MCU、安全低功耗MCU、無(wú)線射頻MCU等3個(gè)系列。其中射頻MCU集成了無(wú)線收發(fā)器,主要包括CW32R031(2.4GHz BLE-Lite)系列和
    發(fā)表于 11-12 07:34

    CW32開(kāi)發(fā)者扶持計(jì)劃#CW32 #芯片

    CW32
    CW32生態(tài)社區(qū)
    發(fā)布于 :2023年05月24日 16:56:14

    cw32和stm32的區(qū)別

    cw32和stm32的區(qū)別 CW32和STM32是兩種常見(jiàn)的單片機(jī),被廣泛應(yīng)用于各種電子設(shè)備中。在本文中,我們將深入探討CW32和STM32之間的區(qū)別和優(yōu)劣勢(shì)。 1. 硬件性能 硬件性能是衡量單片機(jī)
    的頭像 發(fā)表于 08-16 11:15 ?6491次閱讀

    cw32和gd32的區(qū)別

    cw32和gd32的區(qū)別 CW32和GD32是兩種不同的芯片系列,分別由WCH和GigaDevice公司推出,兩者有很多不同之處,下面我們來(lái)詳細(xì)介紹。 首先從CW32系列開(kāi)始,CW32
    的頭像 發(fā)表于 08-16 11:15 ?3348次閱讀

    基于CW32的無(wú)刷水泵方案

    基于CW32的無(wú)刷水泵方案
    的頭像 發(fā)表于 11-03 17:28 ?2024次閱讀
    基于<b class='flag-5'>CW32</b>的無(wú)刷水泵方案

    基于CW32熱敏電阻采集溫度應(yīng)用

    基于CW32熱敏電阻采集溫度應(yīng)用
    的頭像 發(fā)表于 10-25 16:45 ?1401次閱讀
    基于<b class='flag-5'>CW32</b>熱敏電阻采集溫度應(yīng)用

    CW32 PWM輸出功能介紹

    CW32 PWM輸出功能介紹
    的頭像 發(fā)表于 09-27 16:12 ?2320次閱讀
    <b class='flag-5'>CW32</b> PWM輸出功能介紹

    CW32實(shí)時(shí)時(shí)鐘(RTC)介紹

    CW32實(shí)時(shí)時(shí)鐘(RTC)介紹
    的頭像 發(fā)表于 10-24 15:36 ?2328次閱讀
    <b class='flag-5'>CW32</b>實(shí)時(shí)時(shí)鐘(RTC)介紹

    基于CW32的RC522刷卡模塊的應(yīng)用

    基于CW32的RC522刷卡模塊的應(yīng)用
    的頭像 發(fā)表于 11-02 14:53 ?2701次閱讀
    基于<b class='flag-5'>CW32</b>的RC522刷卡模塊的應(yīng)用

    基于CW32的物聯(lián)網(wǎng)應(yīng)用

    CW32】基于CW32的物聯(lián)網(wǎng)應(yīng)用
    的頭像 發(fā)表于 11-02 15:55 ?2064次閱讀
    基于<b class='flag-5'>CW32</b>的物聯(lián)網(wǎng)應(yīng)用