Acest articol este un articol oglindă al traducerii automate, vă rugăm să faceți clic aici pentru a sări la articolul original.

Vedere: 8951|Răspunde: 0

Zigbee Journey (7): Mai multe experimente importante de bază CC2430 - transmisia DMA

[Copiază linkul]
Postat pe 30.10.2014 23:22:16 | | | |
1. Conectarea nivelurilor superioare și inferioare

În secțiunea anterioară, am discutat despre utilizarea ADC-urilor și am eșantionat senzorul de temperatură integrat pe cip. În proiectele reale, numărul senzorilor este adesea mare și o cantitate mare de date de conversie trebuie procesate. Mutarea acestor date va pune multă presiune pe CPU. Pentru a elibera CPU-ul și a-i oferi energia necesară pentru alte lucruri, DMA (Direct Memory Access) poate fi util~

Următoarea introducere este un fragment din Tutorialul de Practică Tehnologică Zigbee:

DMA este o abreviere pentru acces direct la memorie, care înseamnă "acces direct la memorie". Acesta este un mod de transmisie a datelor de mare viteză în care unități periferice precum transceiverele și memoria ADC/UART/RF pot schimba date direct sub controlul "controlerului DMA" fără intervenție limitată a CPU-ului. Pe lângă efectuarea unei mici procesări la începutul și sfârșitul transferului de date, CPU-ul poate face și alte activități în timpul transferului. Astfel, CPU-ul și aceste interacțiuni de date funcționează în paralel majoritatea timpului. Ca urmare, eficiența generală a sistemului poate fi semnificativ îmbunătățită.

După cum se vede din introducere, DMA poate fi folosit în multe situații. Acest experiment implică doar cea mai simplă transmisie DMA și își propune să demonstreze utilizarea generală a DMA. În ceea ce privește aplicarea DMA în alte scenarii, aceasta va fi implementată în experimente cuprinzătoare în viitor.

2. Experimentul de transmisie DMA(1) Introducere în experiment

Personaje din tablourisourceStringConținutul este transferat în matricea de caractere prin DMAdestString, rezultatul conversiei este afișat pe PC prin portul serial.

(2) Diagramă de flux a programului

(3) Cod sursă experimental și analiză/*
    Descriere experimentală: Conținutul site-ului sourceString al matricei de caractere este transferat către matricea de caractere destString prin DMA, iar rezultatul conversiei este afișat pe PC prin portul serial.
*/

#include

#define condus P1_0         
#define led2 P1_1         
#define led3 P1_2         
#define led4 P1_3

/*用于配置DMA的结构体
-------------------------------------------------------*/
#pragma câmpuri de biți=inversat
typedef struct
{
  nesemnat CharSRCADDRH;           //源地址高8位
  nesemnat CharSRCADDRL;           //源地址低8位
  nesemnat CharDESTADDRH;         //目的地址高8位
  nesemnat CharDESTADDRL;         //目的地址低8位
  nesemnat CharVLEN :3;     //长度域模式选择
  nesemnat CharLENH:5;     //传输长度高字节
  nesemnat CharLENL:8;     //传输长度低字节
  nesemnat CharDIMENSIUNEA CUVÂNTULUI :1;     //字节(byte)或字(word)传输
  nesemnat CharTMODE :2;     //传输模式选择
  nesemnat CharTRIG :5;     //触发事件选择
  nesemnat CharSRCINC :2;     //源地址增量:-1/0/1/2
  nesemnat CharDESTINC :2;     //目的地址增量:-1/0/1/2
  nesemnat CharIRQMASK :1;     //中断屏蔽
  nesemnat CharM8 :1;     //7或8bit传输长度,仅在字节传输模式下适用
  nesemnat CharPRIORITATE:2;     //优先级
}DMA_CFG;
#pragma câmpuri de biți=implicit

/*系统时钟初始化
-------------------------------------------------------*/
Voidxtal_init(Void)
{
  SOMN &= ~0x04;            //都上电
  în timp ce(! (SOMN &0x40));     //晶体振荡器开启且稳定
  CLKCON &= ~0x47;            Alege un oscilator cu cristal de 32MHz
  SLEEP |=0x04;
}

/*LED初始化
-------------------------------------------------------*/
Voidled_init(Void)
{
  P1SEL =0x00;         P1 este portul normal de I/O
  P1DIR |=0x0F;         Ieșire P1.0 P1.1 P1.2 P1.3
  
  a condus1 =1;               //关闭所有LED
  led2 =1;
  led3 =1;
  led4 =1;
}

/*UART0通信初始化
-------------------------------------------------------*/
VoidUart0Init(nesemnat CharStopBits,nesemnat CharParitate)
{
   P0SEL |=  0x0C;                  //初始化UART0端口,设置P0.2与P0.3为外部设备IO口
   PERCFG&= ~0x01;                  Selectează UART0 ca prima poziție opțională, adică RXD către P0.2 și TXD către P0.3
   
   U0CSR =0xC0;                    Setează pe modul UART și activează acceptorul
   
   U0GCR =11;
   U0BAUD =216;                    //设置UART0波特率为115200bps
   
   U0UCR |= StopBits| Paritate;        //设置停止位与奇偶校验
}

/*UART0发送数据
-------------------------------------------------------*/
Void  Uart0Send(nesemnat Chardate)
{
  în timp ce(U0CSR&0x01);   //等待UART空闲时发送数据
  U0DBUF = date;
}

/*UART0发送字符串
-------------------------------------------------------*/
VoidUart0SendString(nesemnat Char*s)
{
  în timp ce(*s !=0)         //依次发送字符串s中的每个字符
    Uart0Send(*s++);
}

/*主函数
-------------------------------------------------------*/
Voidmain(Void)
{
  DMA_CFG dmaConfig;      //定义配置结构体
  
  nesemnat CharsourceString[]="Eu sunt sursaString!";      //源字符串
  nesemnat ChardestString[Dimensiunea(sourceString)] ="Eu sunt destString-ul!";  //目的字符串
  
  Chari;
  Chareroare=0;
  
  xtal_init();            //系统时钟初始化
  led_init();
  Uart0Init(0x00,0x00);   //UART初始化
  
  Uart0SendString(sourceString);         //传输前的原字符数组
  Uart0SendString(destString);           //传输前的目的字符数组
  
  //配置DMA结构体
  dmaConfig.SRCADDRH=(nesemnat Char)((nesemnat int)&sursăString >>8);     //源地址
  dmaConfig.SRCADDRL=(nesemnat Char)((nesemnat int)&sourceString);
   
  dmaConfig.DESTADDRH=(nesemnat Char)((nesemnat int)&destString >>8);      //目的地址
  dmaConfig.DESTADDRL=(nesemnat Char)((nesemnat int)&destString);
  
  dmaConfig.VLEN=0x00;         //选择LEN作为传送长度
  
  dmaConfig.LENH=(nesemnat Char)((nesemnat int)Dimensiunea(sursăString) >>8);  //传输长度
  dmaConfig.LENL=(nesemnat Char)((nesemnat int)Dimensiunea(sourceString));
  
  dmaConfig.WORDSIZE=0x00;     //选择字节(byte)传送
  
  dmaConfig.TMODE=0x01;        //选择块传送(block)模式
  
  dmaConfig.TRIG=0;            Fără declanșator (poate fi înțeles ca declanșare manuală)
  
  dmaConfig.SRCINC=0x01;      //源地址增量为1
  
  dmaConfig.DESTINC=0x01;      //目的地址增量为1
  
  dmaConfig.IRQMASK=0;         //DMA中断屏蔽
   
  dmaConfig.M8=0x00;           //选择8位长的字节来传送数据
  
  dmaConfig.PRIORITY=0x02;     //传输优先级为高
  

  DMA0CFGH=(nesemnat Char)((nesemnat int)&dmaConfig >>8);   //将配置结构体的首地址赋予相关SFR
  DMA0CFGL=(nesemnat Char)((nesemnat int)&dmaConfig);
  
  DMAARM=0x01;                 //启用配置
  
  DMAIRQ=0x00;                 //清中断标志
  DMAREQ=0x01;                 //启动DMA传输
  
  în timp ce(! (DMAIRQ&0x01));               //等待传输结束
  
  pentru(i=0; i <Dimensiunea(sourceString); i++)   //校验传输的正确性
  {
    dacă(sourceString!=destString)
      error++;
  }
  
  dacă(eroare==0)                          //将结果通过串口传输到PC
  {
    Uart0SendString("Corect!");
    Uart0SendString(destString);        //传输后的目的字符数组
  }
  altfel
    Uart0SendString("Eroare!");

  în timp ce(1);
}

Procesul de bază al utilizării DMA este:Configurează DMAActivează configurațiaÎncepe transferul DMA → Așteaptă să se termine transferul DMA.Următoarele sunt, respectiv:

  (1) Configurarea DMA: În primul rând, DMA trebuie configurat, dar configurația DMA este specială: în loc să atribuie direct valori unor SFR-uri, definește o structură extern, îi atribuie valori și apoi atribuie cei 8 biți superiori ai primei adrese a acestei structuriDMA0CFGH, oferindu-i un minim de 8 cifreDMA0CFGL。 (Pentru instrucțiuni detaliate în structura de configurare, vă rugăm să consultați manualul chinezesc CC2430)

Sfaturi CC2430
Există două aspecte de clarificat cu privire la definiția structurilor de configurare din codul sursă de mai sus:
(1) Domeniul biților
La definirea acestui struct, se folosesc multe două puncte (:), urmate de un număr, numit "câmp de biți":
Domeniul biților înseamnă că informația nu trebuie să ocupe un octet întreg atunci când este stocată, ci ocupă doar câțiva sau un bit binar. De exemplu, când stochezi o cantitate de comutare, există doar două stări, 0 și 1, și poți folosi un bit binar. Pentru a economisi spațiu de stocare și a facilita procesarea, C oferă o structură de date numită "câmp de biți" sau "câmp de biți". Așa-numitul "câmp de biți" împarte binarele dintr-un octet în mai multe regiuni diferite și descrie numărul de biți din fiecare regiune. Fiecare domeniu are un nume de domeniu, permițând operațiuni după nume de domeniu în program. Acest lucru permite reprezentarea mai multor obiecte diferite într-un câmp binar de octeți.
(2) Funcții comune abstracte
Cititorii atenți vor constata că atribuirea unei valori unei structuri implică adesea atribuirea unei valori de tip int nesemnat pe 16 biți către două valori de tip carax nesemnat pe 8 biți, după cum urmează:
dmaConfig.SRCADDRH=(nesemnat Char)((nesemnat int)&sursăString >>8);     //源地址
dmaConfig.SRCADDRL=(nesemnat Char)((nesemnat int)&sourceString);

Pentru acest tip de funcție frecvent folosită, putem la fel de bine să o abstractizăm ca funcție generală, după cum urmează:
#define SET_WORD(destH,destL,word)
    face{
       destH=(nesemnat Char)((nesemnat int)cuvântul >>8);     
       destL=(nesemnat Char)((nesemnat int)cuvânt);
    }în timp ce(0)

În viitor, ori de câte ori va trebui să efectuezi o operație similară de divizare, o poți numi direct, astfel:
SET_WORD(dmaConfig.SRCADDRH, dmaConfig.SRCADDRL, &sourceString);


  (2) Activarea configurării: Mai întâi, prima adresă a structurii&dmaConfigCei 8 biți high/low sunt atribuiți SFR, respectivDMA0CFGHșiDMA0CFGL(unde 0 reprezintă configurația pentru canalul 0, CC2430 conține 5 canale DMA, aici se folosește canalul 0). DaDMAARM.0Atribuiți valoarea 1 pentru a permite configurarea canalului 0, astfel încât canalul 0 să fie în modul de lucru.

  (3) Activarea transmisiei DMA:DreaptaDMAREQ.0Atribuiți valoarea 1 pentru a începe transmisia DMA a canalului 0.

  (4) Să aștepte transmiterea DMA:După ce DMA-ul canalului 0 este transmis, întreruperea va fi declanșată, iar flag-ul de întrerupere al canalului 0 va fi declanșatDMAIRQ.0va fi setat automat la 1. Fiecare caracter din cele două șiruri este apoi comparat, iar rezultatul verificării este trimis PC-ului.

(4) Rezultate experimentale

Mai întâi, deschideți unealta de depanare a porturilor seriale, apoi începeți depanarea CC2430, iar următorul ecran va apărea:

Vei găsidestStringConținutul a fost complet dezvăluitsourceStringplină.

Gata~

3. Concluzie

Această secțiune introduce utilizarea DMA, deși este foarte simplă, dar cred că ați înțeles utilizarea de bază a DMA și o puteți analiza calm atunci când veți întâlni scenarii complexe de utilizare în viitor.

Indiferent cât de bun este un desktop, acesta se va bloca, iar în mod similar, un sistem încorporat va stagna inevitabil. În următoarea secțiune, vom introduce o metodă foarte eficientă de resetare sistematică: watchdog-urile.






Precedent:Zigbee Journey (6): Câteva experimente importante de bază CC2430 - ADC eșantionare unică
Următor:Zigbee Journey (8): Câteva experimente importante de bază CC2430 - watchdogs
Disclaimer:
Tot software-ul, materialele de programare sau articolele publicate de Code Farmer Network sunt destinate exclusiv scopurilor de învățare și cercetare; Conținutul de mai sus nu va fi folosit în scopuri comerciale sau ilegale, altfel utilizatorii vor suporta toate consecințele. Informațiile de pe acest site provin de pe Internet, iar disputele privind drepturile de autor nu au legătură cu acest site. Trebuie să ștergi complet conținutul de mai sus de pe calculatorul tău în termen de 24 de ore de la descărcare. Dacă îți place programul, te rugăm să susții software-ul autentic, să cumperi înregistrarea și să primești servicii autentice mai bune. Dacă există vreo încălcare, vă rugăm să ne contactați prin e-mail.

Mail To:help@itsvse.com