|
1. Propojení horní a dolní úrovně V předchozí části jsme mluvili o použití ADC a vzorkovali teplotní senzor na čipu. V reálných projektech je počet senzorů často velký a je třeba zpracovat velké množství konverzních dat. Přesun těchto dat by CPU hodně zatěžoval. Aby se CPU uvolnil a získal energii na jiné věci, může se hodit DMA (Direct Memory Access)~ Následující úvod je úryvek z Zigbee Technology Practice Tutorial: DMA je zkratka pro přímý přístup do paměti, což znamená "přímý přístup do paměti". Jedná se o režim vysokorychlostního přenosu dat, ve kterém periferní jednotky jako ADC/UART/RF transceivery a paměť mohou vyměňovat data přímo pod kontrolou "DMA řadiče" bez minimálního zásahu CPU. Kromě drobného zpracování na začátku a na konci přenosu dat může CPU během přenosu vykonávat i další práci. Tímto způsobem CPU a tyto datové interakce většinou fungují paralelně. Díky tomu lze celkovou účinnost systému výrazně zvýšit.
Jak je vidět z úvodu, DMA lze použít v mnoha situacích. Tento experiment zahrnuje pouze nejjednodušší přenos DMA a má za cíl demonstrovat obecné využití DMA. Pokud jde o aplikaci DMA v jiných scénářích, bude v budoucnu implementována v komplexních experimentech. 2. Experiment přenosu DMA(1) Úvod do experimentuPostavy polesourceStringObsah je přenášen do pole znaků přes DMAdestString, výsledek konverze se zobrazuje na PC přes sériový port. (2) Programový diagram
(3) Experimentální zdrojový kód a analýza/*
Experimentální popis: Obsah znakového pole sourceString je přenesen do znakového pole destString přes DMA a výsledek konverze se zobrazí na PC přes sériový port.
*/
#include
#define vedl1 P1_0
#define vedl2 P1_1
#define vedení3 P1_2
#define Led4 P1_3
/*用于配置DMA的结构体
-------------------------------------------------------*/
#pragma bitová pole=obrácené
typedef struct
{
nepodepsáno charSRCADDRH; //源地址高8位
nepodepsáno charSRCADDRL; //源地址低8位
nepodepsáno charDESTADDRH; //目的地址高8位
nepodepsáno charDESTADDRL; //目的地址低8位
nepodepsáno charVLEN :3; //长度域模式选择
nepodepsáno charLENH :5; //传输长度高字节
nepodepsáno charLENL :8; //传输长度低字节
nepodepsáno charVELIKOST SLOVA :1; //字节(byte)或字(word)传输
nepodepsáno charTMODE :2; //传输模式选择
nepodepsáno charTRIGONOMETRIE:5; //触发事件选择
nepodepsáno charSRCINC :2; //源地址增量:-1/0/1/2
nepodepsáno charDESTINC:2; //目的地址增量:-1/0/1/2
nepodepsáno charIRQMASK :1; //中断屏蔽
nepodepsáno charM8 :1; //7或8bit传输长度,仅在字节传输模式下适用
nepodepsáno charPRIORITA :2; //优先级 }DMA_CFG; #pragma bitfields=výchozí
/*系统时钟初始化
-------------------------------------------------------*/
prázdnotaxtal_init(prázdnota)
{ SPÁT &= ~0x04; //都上电
zatímco(! (SPÁT &0x40)); //晶体振荡器开启且稳定 CLKCON &= ~0x47; Vyberte krystalový oscilátor s frekvencí 32 MHz SPÁT |=0x04;
}
/*LED初始化
-------------------------------------------------------*/
prázdnotaled_init(prázdnota)
{ P1SEL =0x00; P1 je běžný I/O port P1DIR |=0x0F; P1.0 P1.1 P1.1 P1.2 P1.3 výstup
led1 =1; //关闭所有LED led2 =1; led3 =1; led4 =1;
}
/*UART0通信初始化
-------------------------------------------------------*/
prázdnotaUart0Init(nepodepsáno charStopBits,nepodepsáno charParita)
{ P0SEL |= 0x0C; //初始化UART0端口,设置P0.2与P0.3为外部设备IO口 PERCFG&= ~0x01; Vyberte UART0 jako první volitelnou pozici, tedy RXD na P0.2 a TXD na P0.3
U0CSR =0xC0; Nastavte režim UART a povolte akceptor
U0GCR =11; U0BAUD =216; //设置UART0波特率为115200bps
U0UCR |= StopBits| Parita; //设置停止位与奇偶校验
}
/*UART0发送数据
-------------------------------------------------------*/
prázdnota Uart0Send(nepodepsáno chardata)
{
zatímco(U0CSR&0x01); //等待UART空闲时发送数据 U0DBUF = data;
}
/*UART0发送字符串
-------------------------------------------------------*/
prázdnotaUart0SendString(nepodepsáno char*s)
{
zatímco(*s !=0) //依次发送字符串s中的每个字符 Uart0Send(*s++);
}
/*主函数
-------------------------------------------------------*/
prázdnotamain(prázdnota)
{ DMA_CFG dmaConfig; //定义配置结构体
nepodepsáno charsourceString[]="Jsem sourceString!"; //源字符串
nepodepsáno chardestString[velikostof(sourceString)] ="Jsem destString!"; //目的字符串
chari;
charerror=0;
xtal_init(); //系统时钟初始化 led_init(); Uart0Init(0x00,0x00); //UART初始化
Uart0SendString(sourceString); //传输前的原字符数组 Uart0SendString(destString); //传输前的目的字符数组
//配置DMA结构体 dmaConfig.SRCADDRH=(nepodepsáno char)((nepodepsáno int)&sourceString >>8); //源地址 dmaConfig.SRCADDRL=(nepodepsáno char)((nepodepsáno int)&sourceString);
dmaConfig.DESTADDRH=(nepodepsáno char)((nepodepsáno int)&destString >>8); //目的地址 dmaConfig.DESTADDRL=(nepodepsáno char)((nepodepsáno int)&destString);
dmaConfig.VLEN=0x00; //选择LEN作为传送长度
dmaConfig.LENH=(nepodepsáno char)((nepodepsáno int)velikostof(sourceString) >>8); //传输长度 dmaConfig.LENL=(nepodepsáno char)((nepodepsáno int)velikostof(sourceString));
dmaConfig.WORDSIZE=0x00; //选择字节(byte)传送
dmaConfig.TMODE=0x01; //选择块传送(block)模式
dmaConfig.TRIG=0; Žádná spoušť (lze chápat jako manuální spoušť)
dmaConfig.SRCINC=0x01; //源地址增量为1
dmaConfig.DESTINC=0x01; //目的地址增量为1
dmaConfig.IRQMASK=0; //DMA中断屏蔽
dmaConfig.M8=0x00; //选择8位长的字节来传送数据
dmaConfig.PRIORITY=0x02; //传输优先级为高
DMA0CFGH=(nepodepsáno char)((nepodepsáno int)&dmaConfig >>8); //将配置结构体的首地址赋予相关SFR DMA0CFGL=(nepodepsáno char)((nepodepsáno int)&dmaConfig);
DMAARM=0x01; //启用配置
DMAIRQ=0x00; //清中断标志 DMAREQ=0x01; //启动DMA传输
zatímco(! (DMAIRQ&0x01)); //等待传输结束
pro(i=0; i <velikostof(sourceString); i++) //校验传输的正确性 {
pokud(sourceString!=destString) error++; }
pokud(chyba==0) //将结果通过串口传输到PC { Uart0SendString("Správně!"); Uart0SendString(destString); //传输后的目的字符数组 }
jinak Uart0SendString("Chyba!");
zatímco(1);
}
Základní proces používání DMA je:Konfigurovat DMA → Povolit konfiguraci → Začněte převod DMA → Čekejte, až převod do DMA skončí.Následující jsou: (1) Konfigurovat DMA: Především musí být DMA konfigurována, ale konfigurace DMA je specifická: místo přímého přiřazování hodnot některým SFR definuje strukturu externě, přiřazuje jí hodnoty a poté přiřazuje vysokých 8 bitů první adresy této strukturyDMA0CFGH, což mu dává nižší 8 číslicDMA0CFGL。 (Pro podrobné instrukce ke struktuře konfigurace prosím viz čínský manuál CC2430) Tipy na CC2430Existují dva body, které je třeba upřesnit ohledně definice konfiguračních struktur ve zdrojovém kódu výše: (1) Bitová doména Při definování této struktury se používá mnoho dvojteček (:), následovaných číslem, které se nazývá "bitové pole": Bitová doména znamená, že informace nemusí při ukládání zabírat celý bajt, ale pouze několik nebo jeden binární bit. Například při ukládání přepínací veličiny existují pouze dva stavy, 0 a 1, a můžete použít binární jednobitovou hodnotu. Pro úsporu úložného prostoru a usnadnění zpracování poskytuje C datovou strukturu nazývanou "bitové pole" nebo "bitové pole". Takzvané "bitové pole" rozděluje binární soubory v bajtu do několika různých oblastí a popisuje počet bitů v každé oblasti. Každá doména má doménové jméno, což umožňuje operace podle doménového jména v programu. To umožňuje reprezentovat několik různých objektů v binárním bitovém poli bajtu. (2) Abstraktní společné funkce Pozorní čtenáři zjistí, že přiřazení hodnoty struktuře často zahrnuje přiřazení 16bitové hodnoty neznaménkového typu int dvěma 8bitovým hodnotám neznaménkového typu char, a to následovně: dmaConfig.SRCADDRH=(nepodepsáno char)((nepodepsáno int)&sourceString >>8); //源地址 dmaConfig.SRCADDRL=(nepodepsáno char)((nepodepsáno int)&sourceString);
U tohoto typu často používané funkce bychom ji mohli stejně tak abstrahovat jako obecnou funkci, a to následovně: #define SET_WORD(destH,destL,word)
dělat{ destH=(nepodepsáno char)((nepodepsáno int)slovo >>8); destL=(nepodepsáno char)((nepodepsáno int)slovo); }zatímco(0)
V budoucnu, kdykoli budete potřebovat provést podobnou operaci rozdělení, můžete ji přímo zavolat, a to následovně: SET_WORD(dmaConfig.SRCADDRH, dmaConfig.SRCADDRL, &sourceString);
(2) Povolit konfiguraci: Nejprve první adresa struktury&dmaConfigVysoký/nízký 8 bitů je přiřazen k SFRDMA0CFGHaDMA0CFGL(kde 0 představuje konfiguraci kanálu 0, CC2430 obsahuje 5 DMA kanálů, kanál 0 se používá zde). AnoDMAARM.0Přiřaďte hodnotu 1, aby bylo možné nastavit kanál 0 tak, aby kanál 0 byl v pracovním režimu. (3) Povolit přenos DMA:VpravoDMAREQ.0Přiřaďte hodnotu 1 pro zahájení DMA přenosu kanálu 0. (4) Čekat na přenos DMA:Po přenosu DMA kanálu 0 bude spuštěno přerušení a příznak přerušení kanálu 0DMAIRQ.0bude automaticky nastaveno na 1. Každý znak ze dvou řetězců je poté porovnán a výsledek ověření je odeslán PC. (4) Experimentální výsledkyNejprve otevřete nástroj pro ladění sériových portů a pak začněte ladit CC2430, a zobrazí se následující obrazovka:
Zjistíte, žedestStringObsah byl zcela odhalensourceStringnaplněný. Hotovo~ 3. ZávěrTato část představuje použití DMA, i když je velmi jednoduché, ale myslím, že jste pochopili základní využití DMA a můžete jej klidně analyzovat, až se v budoucnu setkáte s jeho složitými scénáři použití. Ať je desktop jakkoliv dobrý, zamrzne, a podobně i vestavěný systém nevyhnutelně stagnuje. V následující části představíme velmi účinnou metodu systematického resetu: hlídací psy.
|