Ta članek je zrcalni članek strojnega prevajanja, kliknite tukaj za skok na izvirni članek.

Pogled: 8951|Odgovoriti: 0

Zigbee Journey (7): Več pomembnih osnovnih eksperimentov CC2430 - prenos DMA

[Kopiraj povezavo]
Objavljeno na 30. 10. 2014 23:22:16 | | | |
1. Povezava zgornje in spodnje ravni

V prejšnjem razdelku smo govorili o uporabi ADC-jev in vzorčili temperaturni senzor na čipu. V dejanskih projektih je število senzorjev pogosto veliko in treba obdelati veliko količino podatkov o pretvorbi. Premikanje teh podatkov bo močno obremenilo procesor. Da bi sprostili procesor in mu dali energijo za druge naloge, je DMA (Direct Memory Access) lahko zelo uporaben~

Naslednji uvod je odlomek iz Zigbee Technology Practice Tutorial:

DMA je okrajšava za neposreden dostop do pomnilnika, kar pomeni "neposreden dostop do pomnilnika". To je način hitrega prenosa podatkov, v katerem lahko periferne enote, kot so ADC/UART/RF oddajniki in pomnilnik, izmenjujejo podatke neposredno pod nadzorom "DMA krmilnika" brez minimalnega posega CPU-ja. Poleg nekaj obdelave na začetku in koncu prenosa podatkov lahko procesor med prenosom opravi tudi drugo delo. Na ta način CPU in te podatkovne interakcije večino časa delujejo vzporedno. Zaradi tega se lahko splošna učinkovitost sistema močno izboljša.

Kot lahko vidite iz uvoda, se DMA lahko uporablja v mnogih primerih. Ta eksperiment vključuje le najpreprostejši prenos DMA in si prizadeva prikazati splošno uporabo DMA. Kar zadeva uporabo DMA v drugih scenarijih, bo ta v prihodnosti uporabljena v obsežnih eksperimentih.

2. Eksperiment prenosa DMA(1) Uvod v eksperiment

Liki v poljusourceStringVsebina se prenese v polje znakov preko DMAdestString, rezultat pretvorbe se prikaže na računalniku preko serijskega priključka.

(2) Shema poteka programa

(3) Eksperimentalna izvorna koda in analiza/*
    Eksperimentalni opis: Vsebina znakovnega polja sourceString se prenese v polje znakov destString preko DMA, rezultat pretvorbe pa se prikaže na računalniku preko serijskega priključka.
*/

#include

#define vodil1 P1_0         
#define vod2 P1_1         
#define Led3 P1_2         
#define vodil 4 P1_3

/*用于配置DMA的结构体
-------------------------------------------------------*/
#pragma bitfields=obratno
typedef struct
{
  nepodpisano charSRCADDRH;           //源地址高8位
  nepodpisano charSRCADDRL;           //源地址低8位
  nepodpisano charDESTADDRH;         //目的地址高8位
  nepodpisano charDESTADDRL;         //目的地址低8位
  nepodpisano charVLEN :3;     //长度域模式选择
  nepodpisano charLENH :5;     //传输长度高字节
  nepodpisano charLENL :8;     //传输长度低字节
  nepodpisano charVELIKOST BESEDE :1;     //字节(byte)或字(word)传输
  nepodpisano charTMODE :2;     //传输模式选择
  nepodpisano charTRIGONOMETRIJA:5;     //触发事件选择
  nepodpisano charSRCINC :2;     //源地址增量:-1/0/1/2
  nepodpisano charDESTINC:2;     //目的地址增量:-1/0/1/2
  nepodpisano charIRQMASK :1;     //中断屏蔽
  nepodpisano charM8 :1;     //7或8bit传输长度,仅在字节传输模式下适用
  nepodpisano charPREDNOST:2;     //优先级
}DMA_CFG;
#pragma bitfields=privzeto

/*系统时钟初始化
-------------------------------------------------------*/
prazninaxtal_init(praznina)
{
  SPANJE &= ~0x04;            //都上电
  medtem ko(! (SPANJE &0x40));     //晶体振荡器开启且稳定
  CLKCON &= ~0x47;            Izberite 32MHz kristalni oscilator
  SPANJE |=0x04;
}

/*LED初始化
-------------------------------------------------------*/
prazninaled_init(praznina)
{
  P1SEL =0x00;         P1 je običajen vhodno-izhodni priključek
  P1DIR |=0x0F;         izhod P1.0 P1.1 P1.2 P1.3
  
  led1 =1;               //关闭所有LED
  led2 =1;
  led3 =1;
  led4 =1;
}

/*UART0通信初始化
-------------------------------------------------------*/
prazninaUart0Init(nepodpisano charStopBits,nepodpisano charPariteta)
{
   P0SEL |=  0x0C;                  //初始化UART0端口,设置P0.2与P0.3为外部设备IO口
   PERCFG&= ~0x01;                  Izberite UART0 kot prvo opcijsko pozicijo, torej RXD na P0.2 in TXD na P0.3
   
   U0CSR =0xC0;                    Nastavite na način UART in omogočite sprejemnik
   
   U0GCR =11;
   U0BAUD =216;                    //设置UART0波特率为115200bps
   
   U0UCR |= StopBits| Enakost;        //设置停止位与奇偶校验
}

/*UART0发送数据
-------------------------------------------------------*/
praznina  Uart0Send(nepodpisano charpodatki)
{
  medtem ko(U0CSR&0x01);   //等待UART空闲时发送数据
  U0DBUF = podatki;
}

/*UART0发送字符串
-------------------------------------------------------*/
prazninaUart0SendString(nepodpisano char*s)
{
  medtem ko(*s !=0)         //依次发送字符串s中的每个字符
    Uart0Send(*s++);
}

/*主函数
-------------------------------------------------------*/
prazninamain(praznina)
{
  DMA_CFG dmaConfig;      //定义配置结构体
  
  nepodpisano charsourceString[]="Jaz sem sourceString!";      //源字符串
  nepodpisano chardestString[velikostof(sourceString)] ="Jaz sem destString!";  //目的字符串
  
  chari;
  charnapaka=0;
  
  xtal_init();            //系统时钟初始化
  led_init();
  Uart0Init(0x00,0x00);   //UART初始化
  
  Uart0SendString(sourceString);         //传输前的原字符数组
  Uart0SendString(destString);           //传输前的目的字符数组
  
  //配置DMA结构体
  dmaConfig.SRCADDRH=(nepodpisano char)((nepodpisano int)&sourceString >>8);     //源地址
  dmaConfig.SRCADDRL=(nepodpisano char)((nepodpisano int)&sourceString);
   
  dmaConfig.DESTADDRH=(nepodpisano char)((nepodpisano int)&destString >>8);      //目的地址
  dmaConfig.DESTADDRL=(nepodpisano char)((nepodpisano int)&destString);
  
  dmaConfig.VLEN=0x00;         //选择LEN作为传送长度
  
  dmaConfig.LENH=(nepodpisano char)((nepodpisano int)velikostof(sourceString) >>8);  //传输长度
  dmaConfig.LENL=(nepodpisano char)((nepodpisano int)velikostof(sourceString));
  
  dmaConfig.WORDSIZE=0x00;     //选择字节(byte)传送
  
  dmaConfig.TMODE=0x01;        //选择块传送(block)模式
  
  dmaConfig.TRIG=0;            Brez sprožilca (lahko se razume kot ročno sprožitev)
  
  dmaConfig.SRCINC=0x01;      //源地址增量为1
  
  dmaConfig.DESTINC=0x01;      //目的地址增量为1
  
  dmaConfig.IRQMASK=0;         //DMA中断屏蔽
   
  dmaConfig.M8=0x00;           //选择8位长的字节来传送数据
  
  dmaConfig.PRIORITY=0x02;     //传输优先级为高
  

  DMA0CFGH=(nepodpisano char)((nepodpisano int)&dmaConfig >>8);   //将配置结构体的首地址赋予相关SFR
  DMA0CFGL=(nepodpisano char)((nepodpisano int)&dmaConfig);
  
  DMAARM=0x01;                 //启用配置
  
  DMAIRQ=0x00;                 //清中断标志
  DMAREQ=0x01;                 //启动DMA传输
  
  medtem ko(! (DMAIRQ&0x01));               //等待传输结束
  
  za(i=0; i <velikostof(sourceString); i++)   //校验传输的正确性
  {
    če(sourceString!=destString)
      napaka++;
  }
  
  če(napaka==0)                          //将结果通过串口传输到PC
  {
    Uart0SendString("Pravilno!");
    Uart0SendString(destString);        //传输后的目的字符数组
  }
  else
    Uart0SendString("Napaka!");

  medtem ko(1);
}

Osnovni postopek uporabe DMA je:Konfiguracija DMAOmogoči konfiguracijoZačnite prenos DMA → počakajte, da se prenos zaključi.Naslednje so:

  (1) Konfiguracija DMA: Najprej je treba DMA konfigurirati, vendar je konfiguracija DMA posebna: namesto neposrednega dodeljevanja vrednosti nekaterim SFR-jem, definira strukturo zunanje, ji dodeli vrednosti in nato dodeli najvišjih 8 bitov prvega naslova te struktureDMA0CFGH, kar mu daje nižjih 8 števkDMA0CFGL。 (Za podrobna navodila v konfiguracijski strukturi glejte kitajski priročnik CC2430)

Nasveti za CC2430
Obstajata dve točki, ki jih je treba pojasniti glede definicije konfiguracijskih struktur v izvorni kodi zgoraj:
(1) Bitna domena
Pri definiranju te strukture se uporablja veliko dvopičarjev (:), ki jim sledi številka, ki se imenuje "bitno polje":
Bitna domena pomeni, da informacije ob shranjevanju ne potrebujejo celotnega bajta, temveč le nekaj ali en binarni bit. Na primer, pri shranjevanju preklopne količine obstajata le dve stanji, 0 in 1, in lahko uporabite enobitno binarnost. Za prihranek prostora za shranjevanje in lažjo obdelavo C zagotavlja podatkovno strukturo, imenovano "bitno polje" ali "bitno polje". Tako imenovano "bitno polje" razdeli binarne datoteke v bajtu na več različnih regij in opisuje število bitov v vsakem območju. Vsaka domena ima svoje domensko ime, kar omogoča operacije po domenskem imenu v programu. To omogoča predstavitev več različnih objektov v bajtnem binarnem bitnem polju.
(2) Abstraktne skupne funkcije
Pozorni bralci bodo ugotovili, da dodeljevanje vrednosti strukturi pogosto vključuje dodelitev 16-bitne vrednosti nepredznanega tipa int dvema 8-bitnima vrednostima nepredznakovanega tipa, kot sledi:
dmaConfig.SRCADDRH=(nepodpisano char)((nepodpisano int)&sourceString >>8);     //源地址
dmaConfig.SRCADDRL=(nepodpisano char)((nepodpisano int)&sourceString);

Za tovrstno pogosto uporabljeno funkcijo jo lahko prav tako abstrahiramo kot splošno funkcijo, kot sledi:
#define SET_WORD(destH,destL,word)
    delati{
       destH=(nepodpisano char)((nepodpisano int)beseda >>8);     
       destL=(nepodpisano char)((nepodpisano int)beseda);
    }medtem ko(0)

V prihodnje, kadar boste morali izvesti podobno operacijo razcepljanja, jo lahko neposredno pokličete, kot sledi:
SET_WORD(dmaConfig.SRCADDRH, dmaConfig.SRCADDRL, &sourceString);


  (2) Omogoči konfiguracijo: Najprej prvi naslov strukture&dmaConfigVisokih/nizkih 8 bitov je dodeljenih SFRDMA0CFGHinDMA0CFGL(kjer 0 predstavlja konfiguracijo za kanal 0, CC2430 vsebuje 5 DMA kanalov, kanal 0 se uporablja tukaj). DaDMAARM.0Dodelite vrednost 1, da omogočite konfiguracijo kanala 0 tako, da je kanal 0 v delovnem načinu.

  (3) Omogočite prenos DMA:DesnoDMAREQ.0Dodelite vrednost 1 za začetek DMA prenosa kanala 0.

  (4) Počakati, da se DMA prenese:Po oddaji DMA kanala 0 se sproži prekinitev in sproži se zastavica prekinitve kanala 0DMAIRQ.0bo samodejno nastavljeno na 1. Vsak znak obeh nizov se nato primerja in rezultat preverjanja se pošlje PC-ju.

(4) Eksperimentalni rezultati

Najprej odprite orodje za razhroščevanje serijskih portov, nato začnite odpravljanje napak CC2430, in prikazal se bo naslednji zaslon:

Ugotovil bošdestStringVsebina je bila popolnoma razkritasourceStringpolna.

Končano~

3. Zaključek

Ta razdelek uvaja uporabo DMA, čeprav je zelo preprosta, vendar mislim, da ste razumeli osnovno uporabo DMA in jo lahko tudi mirno analizirate, ko boste v prihodnosti naleteli na njene kompleksne scenarije uporabe.

Ne glede na to, kako dober je namizni računalnik, se bo zamrznil, prav tako pa bo vgrajeni sistem neizogibno stagniral. V naslednjem razdelku bomo predstavili zelo učinkovito metodo sistematičnega ponovnega začetka: nadzornike.






Prejšnji:Zigbee Journey (6): Več pomembnih osnovnih eksperimentov CC2430 - ADC enojno vzorčenje
Naslednji:Zigbee Journey (8): Več pomembnih osnovnih eksperimentov CC2430 - watchdogs
Disclaimer:
Vsa programska oprema, programski materiali ali članki, ki jih izdaja Code Farmer Network, so namenjeni zgolj učnim in raziskovalnim namenom; Zgornja vsebina ne sme biti uporabljena v komercialne ali nezakonite namene, sicer uporabniki nosijo vse posledice. Informacije na tej strani prihajajo z interneta, spori glede avtorskih pravic pa nimajo nobene zveze s to stranjo. Zgornjo vsebino morate popolnoma izbrisati z računalnika v 24 urah po prenosu. Če vam je program všeč, podprite pristno programsko opremo, kupite registracijo in pridobite boljše pristne storitve. Če pride do kakršne koli kršitve, nas prosimo kontaktirajte po elektronski pošti.

Mail To:help@itsvse.com