Denne artikel er en spejling af maskinoversættelse, klik venligst her for at springe til den oprindelige artikel.

Udsigt: 8951|Svar: 0

Zigbee Journey (7): Flere vigtige CC2430 grundeksperimenter - DMA-transmission

[Kopier link]
Opslået på 30/10/2014 23.22.16 | | | |
1. Forbindelse mellem øvre og nedre niveauer

I det forrige afsnit talte vi om brugen af ADC'er og tog prøver af den indbyggede temperatursensor. I faktiske projekter er antallet af sensorer ofte stort, og en stor mængde konverteringsdata skal behandles. At flytte disse data vil lægge meget pres på CPU'en. For at frigøre CPU'en og give den energi til andre opgaver, kan DMA (Direct Memory Access) være nyttig~

Følgende introduktion er uddraget fra Zigbee Technology Practice Tutorial:

DMA er en forkortelse for direkte hukommelsesadgang, som betyder "direkte hukommelsesadgang". Dette er en højhastigheds datatransmissionstilstand, hvor perifere enheder som ADC/UART/RF-transceivere og hukommelse kan udveksle data direkte under kontrol af "DMA-controlleren" uden minimal CPU-indgriben. Ud over at udføre lidt behandling i begyndelsen og slutningen af dataoverførslen kan CPU'en udføre andet arbejde under overførslen. På denne måde arbejder CPU'en og disse datainteraktioner parallelt det meste af tiden. Som følge heraf kan systemets samlede effektivitet forbedres betydeligt.

Som du kan se fra introduktionen, kan DMA bruges i mange scenarier. Dette eksperiment involverer kun den simpleste DMA-transmission og har til formål at demonstrere den generelle anvendelse af DMA. Hvad angår anvendelsen af DMA i andre scenarier, vil det blive implementeret i omfattende eksperimenter i fremtiden.

2. DMA-transmissionseksperiment(1) Introduktion til eksperimentet

Array-figurersourceStringIndholdet overføres til karakterarrayet via DMAdestString, konverteringsresultatet vises på PC'en gennem den serielle port.

(2) Programflowdiagram

(3) Eksperimentel kildekode og analyse/*
    Eksperimentel beskrivelse: Indholdet af tegnarrayet sourceString overføres til tegnarrayet destString via DMA, og konverteringsresultatet vises på PC'en via den serielle port.
*/

#include

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

/*用于配置DMA的结构体
-------------------------------------------------------*/
#pragma bitfelter=omvendt
typedef Struct
{
  Usigneret CharSRCADDRH;           //源地址高8位
  Usigneret CharSRCADDRL;           //源地址低8位
  Usigneret CharDESTADDRH;         //目的地址高8位
  Usigneret CharDESTADDRL;         //目的地址低8位
  Usigneret CharVLEN :3;     //长度域模式选择
  Usigneret CharLENH :5;     //传输长度高字节
  Usigneret CharLENL :8;     //传输长度低字节
  Usigneret CharORDSTØRRELSE:1;     //字节(byte)或字(word)传输
  Usigneret CharTMODE :2;     //传输模式选择
  Usigneret CharTRIG :5;     //触发事件选择
  Usigneret CharSRCINC :2;     //源地址增量:-1/0/1/2
  Usigneret CharDESTINC :2;     //目的地址增量:-1/0/1/2
  Usigneret CharIRQMASK:1;     //中断屏蔽
  Usigneret CharM8 :1;     //7或8bit传输长度,仅在字节传输模式下适用
  Usigneret CharPRIORITET:2;     //优先级
}DMA_CFG;
#pragma bitfelter=standard

/*系统时钟初始化
-------------------------------------------------------*/
tomrumxtal_init(tomrum)
{
  SOV &= ~0x04;            //都上电
  mens(! (SØVN &0x40));     //晶体振荡器开启且稳定
  CLKCON &= ~0x47;            Vælg en 32MHz krystaloscillator
  SØVN |=0x04;
}

/*LED初始化
-------------------------------------------------------*/
tomrumled_init(tomrum)
{
  P1SEL =0x00;         P1 er den normale I/O-port
  P1DIR |=0x0F;         P1.0 P1.1 P1.2 P1.3 output
  
  led1 =1;               //关闭所有LED
  led2 =1;
  led3 =1;
  led4 =1;
}

/*UART0通信初始化
-------------------------------------------------------*/
tomrumUart0Init(Usigneret CharStopBits,Usigneret CharParitet)
{
   P0SEL |=  0x0C;                  //初始化UART0端口,设置P0.2与P0.3为外部设备IO口
   PERCFG&= ~0x01;                  Vælg UART0 som den første valgfrie position, det vil sige RXD til P0.2 og TXD til P0.3
   
   U0CSR =0xC0;                    Indstil til UART-tilstand og aktiver acceptoren
   
   U0GCR =11;
   U0BAUD =216;                    //设置UART0波特率为115200bps
   
   U0UCR |= StopBits| Paritet;        //设置停止位与奇偶校验
}

/*UART0发送数据
-------------------------------------------------------*/
tomrum  Uart0Send(Usigneret Chardata)
{
  mens(U0CSR&0x01);   //等待UART空闲时发送数据
  U0DBUF = data;
}

/*UART0发送字符串
-------------------------------------------------------*/
tomrumUart0SendString(Usigneret Char*s)
{
  mens(*s !=0)         //依次发送字符串s中的每个字符
    Uart0Send(*s++);
}

/*主函数
-------------------------------------------------------*/
tomrumhoved(tomrum)
{
  DMA_CFG dmaConfig;      //定义配置结构体
  
  Usigneret CharsourceString[]="Jeg er sourceString!";      //源字符串
  Usigneret ChardestString[sizeof(sourceString)] ="Jeg er destString!";  //目的字符串
  
  CharJeg;
  Charfejl=0;
  
  xtal_init();            //系统时钟初始化
  led_init();
  Uart0Init(0x00,0x00);   //UART初始化
  
  Uart0SendString (sourceString);         //传输前的原字符数组
  Uart0SendString(destString);           //传输前的目的字符数组
  
  //配置DMA结构体
  dmaConfig.SRCADDRH=(Usigneret Char)((Usigneret int)&sourceString >>8);     //源地址
  dmaConfig.SRCADDRL=(Usigneret Char)((Usigneret int)&sourceString);
   
  dmaConfig.DESTADDRH=(Usigneret Char)((Usigneret int)&destString >>8);      //目的地址
  dmaConfig.DESTADDRL=(Usigneret Char)((Usigneret int)&destString);
  
  dmaConfig.VLEN=0x00;         //选择LEN作为传送长度
  
  dmaConfig.LENH=(Usigneret Char)((Usigneret int)sizeof(sourceString) >>8);  //传输长度
  dmaConfig.LENL=(Usigneret Char)((Usigneret int)sizeof(sourceString));
  
  dmaConfig.WORDSIZE=0x00;     //选择字节(byte)传送
  
  dmaConfig.TMODE=0x01;        //选择块传送(block)模式
  
  dmaConfig.TRIG=0;            Ingen trigger (kan forstås som manuel triggering)
  
  dmaConfig.SRCINC=0x01;      //源地址增量为1
  
  dmaConfig.DESTINC=0x01;      //目的地址增量为1
  
  dmaConfig.IRQMASK=0;         //DMA中断屏蔽
   
  dmaConfig.M8=0x00;           //选择8位长的字节来传送数据
  
  dmaConfig.PRIORITY=0x02;     //传输优先级为高
  

  DMA0CFGH=(Usigneret Char)((Usigneret int)&dmaConfig >>8);   //将配置结构体的首地址赋予相关SFR
  DMA0CFGL=(Usigneret Char)((Usigneret int)&dmaConfig);
  
  DMAARM=0x01;                 //启用配置
  
  DMAIRQ=0x00;                 //清中断标志
  DMAREQ=0x01;                 //启动DMA传输
  
  mens(! (DMAIRQ&0x01));               //等待传输结束
  
  for(i=0; Jeg <sizeof(sourceString); i++)   //校验传输的正确性
  {
    hvis(sourceString!=destString)
      fejl++;
  }
  
  hvis(fejl==0)                          //将结果通过串口传输到PC
  {
    Uart0SendString("Korrekt!");
    Uart0SendString(destString);        //传输后的目的字符数组
  }
  ellers
    Uart0SendString("Fejl!");

  mens(1);
}

Den grundlæggende proces ved at bruge DMA er:Konfigurér DMAAktiver konfigurationStart DMA-overførslen → Vent på, at DMA-overførslen er færdig.Følgende er henholdsvis:

  (1) Konfigurér DMA: Først og fremmest skal DMA konfigureres, men konfigurationen af DMA er speciel: i stedet for direkte at tildele værdier til nogle SFR'er, definerer den en struktur eksternt, tildeler værdier til den og tildeler derefter de høje 8 bit af den første adresse i denne strukturDMA0CFGH, hvilket giver den 8 cifre lavereDMA0CFGL。 (For detaljerede instruktioner i konfigurationsstrukturen, se venligst CC2430 kinesiske manual)

CC2430 Tips
Der er to punkter, der skal præciseres om definitionen af konfigurationsstrukturer i kildekoden ovenfor:
(1) Bitdomæne
Når denne struktur defineres, bruges mange kolon (:) efterfulgt af et tal, som kaldes "bitfelt":
Bitdomænet betyder, at information ikke behøver at optage en hel byte, når den gemmes, men kun optager et par eller én binær bit. For eksempel, når man gemmer en switching-størrelse, er der kun to tilstande, 0 og 1, og du kan bruge en binær bit. For at spare lagerplads og gøre behandlingen lettere tilbyder C en datastruktur kaldet "bitfelt" eller "bitfelt". Det såkaldte "bitfelt" opdeler binære filer i en byte i flere forskellige regioner og beskriver antallet af bits i hver region. Hvert domæne har et domænenavn, hvilket tillader operationer efter domænenavn i programmet. Dette gør det muligt at repræsentere flere forskellige objekter i et byte-binært bitfelt.
(2) Abstrakte fælles funktioner
Opmærksomme læsere vil opdage, at tildeling af en værdi til en struktur ofte indebærer at tildele en 16-bit usigneret int-typeværdi til to 8-bit usignerede char-typeværdier, som følger:
dmaConfig.SRCADDRH=(Usigneret Char)((Usigneret int)&sourceString >>8);     //源地址
dmaConfig.SRCADDRL=(Usigneret Char)((Usigneret int)&sourceString);

For denne type ofte anvendte funktion kan vi lige så godt abstrahere den som en generel funktion, som følger:
#define SET_WORD(destH,destL,ord)
    gøre{
       destH=(Usigneret Char)((Usigneret int)ord >>8);     
       destL=(Usigneret Char)((Usigneret int)ord);
    }mens(0)

I fremtiden, når du skal udføre en lignende splittingsoperation, kan du kalde den direkte, som følger:
SET_WORD(dmaConfig.SRCADDRH, dmaConfig.SRCADDRL, &sourceString);


  (2) Aktiver konfiguration: Først, den første adresse til strukturen&dmaConfigDe høje/lave 8 bit tildeles henholdsvis SFRDMA0CFGHogDMA0CFGL(hvor 0 repræsenterer konfigurationen for kanal 0, CC2430 indeholder 5 DMA-kanaler, kanal 0 bruges her). JaDMAARM.0Tildel værdien 1 for at aktivere konfigurationen af kanal 0, så kanal 0 er i arbejdstilstand.

  (3) Aktiver DMA-transmission:HøjreDMAREQ.0Tildel værdien 1 for at starte DMA-transmissionen af kanal 0.

  (4) Vent på, at DMA'en bliver sendt:Efter DMA'en for kanal 0 er transmitteret, vil afbruddet blive udløst, og afbrydelsesflaget for kanal 0 vil blive udløstDMAIRQ.0vil automatisk blive sat til 1. Hvert tegn i de to strenge sammenlignes derefter, og verifikationsresultatet sendes til PC'en.

(4) Eksperimentelle resultater

Først åbner du det serielt port-fejlfindingsværktøj, og start derefter CC2430-fejlfindingen, og følgende skærm vil dukke op:

Du vil findedestStringIndholdet er fuldstændigt afsløretsourceStringfyldt.

Færdig~

3. Konklusion

Dette afsnit introducerer brugen af DMA, selvom det er meget simpelt, men jeg tror, du har forstået den grundlæggende anvendelse af DMA, og du kan også analysere det roligt, når du møder dets komplekse brugsscenarier i fremtiden.

Uanset hvor god en stationær computer er, vil den fryse, og tilsvarende vil et indlejret system uundgåeligt stagnere. I næste afsnit vil vi introducere en meget effektiv metode til systematisk nulstilling: vagthunde.






Tidligere:Zigbee Journey (6): Flere vigtige CC2430 grundeksperimenter - ADC enkeltprøvetagning
Næste:Zigbee Journey (8): Flere vigtige CC2430 grundlæggende eksperimenter - vagthunde
Ansvarsfraskrivelse:
Al software, programmeringsmaterialer eller artikler udgivet af Code Farmer Network er kun til lærings- og forskningsformål; Ovenstående indhold må ikke bruges til kommercielle eller ulovlige formål, ellers skal brugerne bære alle konsekvenser. Oplysningerne på dette site kommer fra internettet, og ophavsretstvister har intet med dette site at gøre. Du skal slette ovenstående indhold fuldstændigt fra din computer inden for 24 timer efter download. Hvis du kan lide programmet, så understøt venligst ægte software, køb registrering og få bedre ægte tjenester. Hvis der er nogen overtrædelse, bedes du kontakte os via e-mail.

Mail To:help@itsvse.com