|
1. Ülemiste ja alumiste korruste ühendamine Eelnevas osas rääkisime ADC-de kasutamisest ja proovisime kiibil olevast temperatuuriandurist. Tegelikes projektides on andurite arv sageli suur ja töödeldakse suur hulk konverteerimisandmeid. Andmete liigutamine paneb protsessorile palju koormust. Protsessori vabastamiseks ja energia andmiseks võib DMA (Direct Memory Access) olla kasulik~ Järgmine sissejuhatus on võetud Zigbee tehnoloogia praktika juhendist: DMA on lühend sõnadest otsene mälu ligipääs, mis tähendab "otsene mälu ligipääs". See on kiire andmeedastuse režiim, kus perifeersed seadmed nagu ADC/UART/RF vastuvõtjad ja mälu saavad andmeid vahetada otse "DMA kontrolleri" kontrolli all ilma vähese protsessori sekkumiseta. Lisaks väikesele töötlemisele andmeedastuse alguses ja lõpus saab protsessor teha ka muud tööd. Nii töötavad protsessor ja andmeinteraktsioonid enamasti paralleelselt. Selle tulemusena saab süsteemi üldist efektiivsust oluliselt parandada.
Nagu sissejuhatusest näha, saab DMA-d kasutada paljudes olukordades. See katse hõlmab ainult kõige lihtsamat DMA edastamist ja selle eesmärk on demonstreerida DMA üldist kasutust. Mis puudutab DMA rakendamist teistes stsenaariumites, siis seda rakendatakse tulevikus ulatuslikes katsetes. 2. DMA ülekande eksperiment(1) Sissejuhatus eksperimendileMassiivi tegelasedsourceStringSisu kantakse üle tegelaste massiivi DMA kaududestString, konverteerimise tulemus kuvatakse arvutis seriaalpordi kaudu. (2) Programmi vooskeem
(3) Eksperimentaalne lähtekood ja analüüs/*
Eksperimentaalne kirjeldus: Tähemärgimassiivi sourceString sisu kantakse DMA kaudu märgimassiivi destString ning teisendustulemus kuvatakse arvutis seriaalpordi kaudu.
*/
#include
#define juhtis1 P1_0
#define juhtis2 P1_1
#define juhtis3 P1_2
#define juhtis4 P1_3
/*用于配置DMA的结构体
-------------------------------------------------------*/
#pragma bitiväljad=pööratud
typedef struktuur
{
Allkirjastamata charSRCADDRH; //源地址高8位
Allkirjastamata charSRCADDRL; //源地址低8位
Allkirjastamata charDESTADDRH; //目的地址高8位
Allkirjastamata charDESTADDRL; //目的地址低8位
Allkirjastamata charVLEN :3; //长度域模式选择
Allkirjastamata charLENH :5; //传输长度高字节
Allkirjastamata charLENL :8; //传输长度低字节
Allkirjastamata charSÕNASUURUS :1; //字节(byte)或字(word)传输
Allkirjastamata charTMODE :2; //传输模式选择
Allkirjastamata charTRIG :5; //触发事件选择
Allkirjastamata charSRCINC :2; //源地址增量:-1/0/1/2
Allkirjastamata charDESTINC :2; //目的地址增量:-1/0/1/2
Allkirjastamata charIRQMASK :1; //中断屏蔽
Allkirjastamata charM8 :1; //7或8bit传输长度,仅在字节传输模式下适用
Allkirjastamata charPRIORITEET:2; //优先级 }DMA_CFG; #pragma bitväljad=vaikimisi
/*系统时钟初始化
-------------------------------------------------------*/
tühixtal_init(tühi)
{ UNI &= ~0x04; //都上电
samal ajal(! (UNI &0x40)); //晶体振荡器开启且稳定 CLKCON &= ~0x47; Vali 32MHz kristall-ostsillaator UNI |=0x04;
}
/*LED初始化
-------------------------------------------------------*/
tühiled_init(tühi)
{ P1SEL =0x00; P1 on tavaline I/O port P1DIR |=0x0F; P1.0 P1.1 P1.2 P1.3 väljund
led1 =1; //关闭所有LED led2 =1; led3 =1; led4 =1;
}
/*UART0通信初始化
-------------------------------------------------------*/
tühiUart0Init(Allkirjastamata charStopBits,Allkirjastamata charPariteet)
{ P0SEL |= 0x0C; //初始化UART0端口,设置P0.2与P0.3为外部设备IO口 PERCFG&= ~0x01; Vali UART0 esimeseks valikuliseks positsiooniks, st RXD P0.2-ks ja TXD P0.3-ks
U0CSR =0xC0; Sea UART-režiimile ja luba vastuvõtja
U0GCR =11; U0BAUD =216; //设置UART0波特率为115200bps
U0UCR |= StopBits| võrdsus; //设置停止位与奇偶校验
}
/*UART0发送数据
-------------------------------------------------------*/
tühi Uart0Send(Allkirjastamata charandmed)
{
samal ajal(U0CSR&0x01); //等待UART空闲时发送数据 U0DBUF = andmed;
}
/*UART0发送字符串
-------------------------------------------------------*/
tühiUart0SendString(Allkirjastamata char*s)
{
samal ajal(*s !=0) //依次发送字符串s中的每个字符 Uart0Send(*s++);
}
/*主函数
-------------------------------------------------------*/
tühipea(tühi)
{ DMA_CFG dmaConfig; //定义配置结构体
Allkirjastamata charsourceString[]="Mina olen sourceString!"; //源字符串
Allkirjastamata chardestString[suurus(sourceString)] ="Mina olen destString!"; //目的字符串
chari;
charerror=0;
xtal_init(); //系统时钟初始化 led_init(); Uart0Init(0x00,0x00); //UART初始化
Uart0SendString(sourceString); //传输前的原字符数组 Uart0SendString(destString); //传输前的目的字符数组
//配置DMA结构体 dmaConfig.SRCADDRH=(Allkirjastamata char)((Allkirjastamata int)&sourceString >>8); //源地址 dmaConfig.SRCADDRL=(Allkirjastamata char)((Allkirjastamata int)&sourceString);
dmaConfig.DESTADDRH=(Allkirjastamata char)((Allkirjastamata int)&destString >>8); //目的地址 dmaConfig.DESTADDRL=(Allkirjastamata char)((Allkirjastamata int)&destString);
dmaConfig.VLEN=0x00; //选择LEN作为传送长度
dmaConfig.LENH=(Allkirjastamata char)((Allkirjastamata int)suurus(sourceString) >>8); //传输长度 dmaConfig.LENL=(Allkirjastamata char)((Allkirjastamata int)suurus(sourceString));
dmaConfig.WORDSIZE=0x00; //选择字节(byte)传送
dmaConfig.TMODE=0x01; //选择块传送(block)模式
dmaConfig.TRIG=0; Puudub päästik (võib mõista kui käsitsi käivitumist)
dmaConfig.SRCINC=0x01; //源地址增量为1
dmaConfig.DESTINC=0x01; //目的地址增量为1
dmaConfig.IRQMASK=0; //DMA中断屏蔽
dmaConfig.M8=0x00; //选择8位长的字节来传送数据
dmaConfig.PRIORITY=0x02; //传输优先级为高
DMA0CFGH=(Allkirjastamata char)((Allkirjastamata int)&dmaConfig >>8); //将配置结构体的首地址赋予相关SFR DMA0CFGL=(Allkirjastamata char)((Allkirjastamata int)&dmaConfig);
DMAARM=0x01; //启用配置
DMAIRQ=0x00; //清中断标志 DMAREQ=0x01; //启动DMA传输
samal ajal(! (DMAIRQ&0x01)); //等待传输结束
for(i=0; i <suurus(sourceString); i++) //校验传输的正确性 {
kui(sourceString!=destString) error++; }
kui(viga==0) //将结果通过串口传输到PC { Uart0SendString("Õige!"); Uart0SendString(destString); //传输后的目的字符数组 }
else Uart0SendString("Viga!");
samal ajal(1);
}
DMA kasutamise põhiprotsess on:Seadista DMA → Luba konfiguratsioon → Alusta DMA ülekannet → oota, kuni DMA ülekanne lõpeb.Järgnevad on vastavalt: (1) Seadista DMA: Esiteks tuleb DMA konfigureerida, kuid DMA konfiguratsioon on eriline: selle asemel, et määrata väärtusi otse mõnele SFR-ile, määratleb see välise struktuuri, määrab sellele väärtused ja seejärel määrab selle struktuuri esimese aadressi kõrged 8 bittiDMA0CFGH, andes sellele madalamad 8 numbritDMA0CFGL。 (Konfiguratsioonistruktuuri üksikasjalike juhiste saamiseks vaadake palun CC2430 hiina käsiraamatut) CC2430 näpunäitedLähtekoodis konfiguratsioonistruktuuride definitsiooni kohta tuleb selgitada kahte punkti: (1) Bittidomeen Selle struktuuri defineerimisel kasutatakse palju kooloneid (:), millele järgneb number, mida nimetatakse "bittiväljaks": Bitiddomeen tähendab, et info ei pea salvestamisel hõivama terve baiti, vaid vaid vaid mõne või ühe binaarse bitti. Näiteks lülitussuuruse salvestamisel on ainult kaks olekut, 0 ja 1, ning saad kasutada ühte bitti binaarset. Salvestusruumi säästmiseks ja töötlemise lihtsustamiseks pakub C andmestruktuuri, mida nimetatakse "bitiväljaks" või "bitiväljaks". Niinimetatud "bittiväli" jagab baiti binaarid mitmeks erinevaks piirkonnaks ja kirjeldab iga piirkonna bittide arvu. Igal domeenil on domeeninimi, mis võimaldab programmis domeeninime järgi toiminguid. See võimaldab esitada mitut erinevat objekti baidipõhises binaarses bitiväljas. (2) Abstraktsed ühised funktsioonid Tähelepanelikud lugejad leiavad, et struktuurile väärtuse määramine tähendab sageli 16-bitise allkirjastamata int tüübi määramist kahele 8-bitisele märgita tegelase tüübi väärtusele, järgmiselt: dmaConfig.SRCADDRH=(Allkirjastamata char)((Allkirjastamata int)&sourceString >>8); //源地址 dmaConfig.SRCADDRL=(Allkirjastamata char)((Allkirjastamata int)&sourceString);
Selle tüübi sageli kasutatava funktsiooni puhul võiksime selle abstraheerida üldise funktsioonina järgmiselt: #define SET_WORD(destH,destL,word)
tegema{ destH=(Allkirjastamata char)((Allkirjastamata int)sõna >>8); destL=(Allkirjastamata char)((Allkirjastamata int)sõna); }samal ajal(0)
Tulevikus, kui on vaja teha sarnast jagamisoperatsiooni, saad selle otse kutsuda, järgmiselt: SET_WORD(dmaConfig.SRCADDRH, dmaConfig.SRCADDRL, &sourceString);
(2) Konfiguratsiooni lubamine: Esiteks, struktuuri esimene aadress&dmaConfigKõrge ja madal 8 bitti määratakse vastavalt SFR-ileDMA0CFGHjaDMA0CFGL(kus 0 tähistab kanali 0 konfiguratsiooni, CC2430 sisaldab 5 DMA kanalit, siin kasutatakse kanalit 0). JahDMAARM.0Määra väärtuseks 1, et võimaldada kanali 0 seadistamine nii, et kanal 0 oleks töörežiimis. (3) DMA edastamise lubamine:ParemDMAREQ.0Määra väärtuseks 1, et alustada kanali 0 DMA edastust. (4) Oodake, kuni DMA edastatakse:Pärast kanali 0 DMA edastamist käivitub katkestus ja kanali 0 katkestuslipp käivitubDMAIRQ.0määratakse automaatselt väärtusele 1. Iga kahe stringi tähemärki võrreldakse ja kinnitustulemus saadetakse PC-le. (4) Eksperimentaalsed tulemusedEsmalt ava seriaalpordi silumistööriist ja seejärel alusta CC2430 silumist, ning ilmub järgmine ekraan:
Sa leiaddestStringSisu on täielikult avalikustatudsourceStringtäidetud. Tehtud~ 3. KokkuvõteSee osa tutvustab DMA kasutamist, kuigi see on väga lihtne, kuid arvan, et oled mõistnud DMA põhilist kasutust ning saad seda rahulikult analüüsida, kui tulevikus kogetakse selle keerukaid kasutusstsenaariume. Ükskõik kui hea lauaarvuti ka poleks, see hangub, ja samamoodi jääb manustatud süsteem paratamatult seisma. Järgmises osas tutvustame väga tõhusat süsteemse lähtestamise meetodit: valvekoerad.
|