|
1. Sammenkobling av øvre og nedre nivåer I forrige avsnitt snakket vi om bruk av ADC-er og tok prøver fra temperatursensoren på chipen. I faktiske prosjekter er antallet sensorer ofte stort, og en stor mengde konverteringsdata skal behandles. Å flytte disse dataene vil legge mye belastning på CPU-en. For å frigjøre CPU-en og gi den energi til andre ting, kan DMA (Direct Memory Access) være nyttig~ Følgende introduksjon er et utdrag fra Zigbee Technology Practice Tutorial: DMA er en forkortelse for direkte minnetilgang, som er «direkte minnetilgang». Dette er en høyhastighets dataoverføringsmodus der periferienheter som ADC/UART/RF-transceivere og minne kan utveksle data direkte under kontroll av "DMA-kontrolleren" uten minimal CPU-inngripen. I tillegg til å gjøre litt behandling i begynnelsen og slutten av dataoverføringen, kan CPU-en utføre annet arbeid under overføringen. På denne måten fungerer CPU-en og disse datainteraksjonene parallelt mesteparten av tiden. Som et resultat kan systemets totale effektivitet forbedres betydelig.
Som du kan se fra introduksjonen, kan DMA brukes i mange situasjoner. Dette eksperimentet involverer kun den enkleste DMA-overføringen og har som mål å demonstrere generell bruk av DMA. Når det gjelder anvendelsen av DMA i andre scenarioer, vil det bli implementert i omfattende eksperimenter i fremtiden. 2. DMA-overføringseksperiment(1) Introduksjon til eksperimentetArray-karakterersourceStringInnholdet overføres til karakterarrayet via DMAdestString, konverteringsresultatet vises på PC-en gjennom serieporten. (2) Programflytskjema
(3) Eksperimentell kildekode og analyse/*
Eksperimentell beskrivelse: Innholdet i tegnarrayet sourceString overføres til tegnarrayet destString via DMA, og konverteringsresultatet vises på PC-en via serieporten.
*/
#include
#define led1 P1_0
#define led2 P1_1
#define led3 P1_2
#define led4 P1_3
/*用于配置DMA的结构体
-------------------------------------------------------*/
#pragma bitfelt=omvendt
typedef Struct
{
Usignert CharSRCADDRH; //源地址高8位
Usignert CharSRCADDRL; //源地址低8位
Usignert CharDESTADDRH; //目的地址高8位
Usignert CharDESTADDRL; //目的地址低8位
Usignert CharVLEN :3; //长度域模式选择
Usignert CharLENH:5; //传输长度高字节
Usignert CharLENL :8; //传输长度低字节
Usignert CharORDSTØRRELSE:1; //字节(byte)或字(word)传输
Usignert CharTMODE:2; //传输模式选择
Usignert CharTRIG:5; //触发事件选择
Usignert CharSRCINC:2; //源地址增量:-1/0/1/2
Usignert CharDESTINC:2; //目的地址增量:-1/0/1/2
Usignert CharIRQMASK:1; //中断屏蔽
Usignert CharM8 :1; //7或8bit传输长度,仅在字节传输模式下适用
Usignert CharPRIORITET:2; //优先级 }DMA_CFG; #pragma bitfelt=standard
/*系统时钟初始化
-------------------------------------------------------*/
Tomromxtal_init(Tomrom)
{ SOV &= ~0x04; //都上电
mens(! (SØVN &0x40)); //晶体振荡器开启且稳定 CLKCON &= ~0x47; Velg en 32 MHz krystalloscillator SØVN |=0x04;
}
/*LED初始化
-------------------------------------------------------*/
Tomromled_init(Tomrom)
{ P1SEL =0x00; P1 er den vanlige I/O-porten P1DIR |=0x0F; P1.0 P1.1 P1.2 P1.3-utgang
led1 =1; //关闭所有LED led2 =1; led3 =1; led4 =1;
}
/*UART0通信初始化
-------------------------------------------------------*/
TomromUart0Init(Usignert CharStopBits,Usignert CharParitet)
{ P0SEL |= 0x0C; //初始化UART0端口,设置P0.2与P0.3为外部设备IO口 PERCFG&= ~0x01; Velg UART0 som første valgfrie posisjon, det vil si RXD til P0.2 og TXD til P0.3
U0CSR =0xC0; Sett til UART-modus og aktiver akseptoren
U0GCR =11; U0BAUD =216; //设置UART0波特率为115200bps
U0UCR |= StopBits| Paritet; //设置停止位与奇偶校验
}
/*UART0发送数据
-------------------------------------------------------*/
Tomrom Uart0Send(Usignert Chardata)
{
mens(U0CSR&0x01); //等待UART空闲时发送数据 U0DBUF = data;
}
/*UART0发送字符串
-------------------------------------------------------*/
TomromUart0SendString(Usignert Char*s)
{
mens(*s !=0) //依次发送字符串s中的每个字符 Uart0Send(*s++);
}
/*主函数
-------------------------------------------------------*/
Tomromhoved(Tomrom)
{ DMA_CFG dmaConfig; //定义配置结构体
Usignert CharsourceString[]="Jeg er kildeStrengen!"; //源字符串
Usignert ChardestString[sizeof(sourceString)] ="Jeg er destString!"; //目的字符串
Chari;
Charfeil=0;
xtal_init(); //系统时钟初始化 led_init(); Uart0Init(0x00,0x00); //UART初始化
Uart0SendString (sourceString); //传输前的原字符数组 Uart0SendString(destString); //传输前的目的字符数组
//配置DMA结构体 dmaConfig.SRCADDRH=(Usignert Char)((Usignert Int)&sourceString >>8); //源地址 dmaConfig.SRCADDRL=(Usignert Char)((Usignert Int)&sourceString);
dmaConfig.DESTADDRH=(Usignert Char)((Usignert Int)&destString >>8); //目的地址 dmaConfig.DESTADDRL=(Usignert Char)((Usignert Int)&destString);
dmaConfig.VLEN=0x00; //选择LEN作为传送长度
dmaConfig.LENH=(Usignert Char)((Usignert Int)sizeof(sourceString) >>8); //传输长度 dmaConfig.LENL=(Usignert Char)((Usignert Int)sizeof(sourceString));
dmaConfig.WORDSIZE=0x00; //选择字节(byte)传送
dmaConfig.TMODE=0x01; //选择块传送(block)模式
dmaConfig.TRIG=0; Ingen trigger (kan forstås som manuell triggering)
dmaConfig.SRCINC=0x01; //源地址增量为1
dmaConfig.DESTINC=0x01; //目的地址增量为1
dmaConfig.IRQMASK=0; //DMA中断屏蔽
dmaConfig.M8=0x00; //选择8位长的字节来传送数据
dmaConfig.PRIORITY=0x02; //传输优先级为高
DMA0CFGH=(Usignert Char)((Usignert Int)&dmaConfig >>8); //将配置结构体的首地址赋予相关SFR DMA0CFGL=(Usignert Char)((Usignert Int)&dmaConfig);
DMAARM=0x01; //启用配置
DMAIRQ=0x00; //清中断标志 DMAREQ=0x01; //启动DMA传输
mens(! (DMAIRQ&0x01)); //等待传输结束
for(i=0; i <sizeof(sourceString); i++) //校验传输的正确性 {
hvis(sourceString!=destString) feil++; }
hvis(feil==0) //将结果通过串口传输到PC { Uart0SendString("Korrekt!"); Uart0SendString(destString); //传输后的目的字符数组 }
ellers Uart0SendString("Feil!");
mens(1);
}
Den grunnleggende prosessen med å bruke DMA er:Konfigurer DMA → Aktiver konfigurasjon → Start DMA-overføringen → Vent til DMA-overføringen er ferdig.Følgende er henholdsvis: (1) Konfigurer DMA: Først og fremst må DMA konfigureres, men konfigurasjonen av DMA er spesiell: i stedet for å tildele verdier direkte til noen SFR-er, definerer den en struktur eksternt, tildeler den verdier, og tildeler deretter de høyeste 8 bitene av den første adressen til denne strukturenDMA0CFGH, noe som gir den lavere 8 sifreDMA0CFGL。 (For detaljerte instruksjoner i konfigurasjonsstrukturen, se den kinesiske manualen CC2430) CC2430-tipsDet er to punkter som må presiseres om definisjonen av konfigurasjonsstrukturer i kildekoden ovenfor: (1) Bitdomene Når denne strukturen defineres, brukes mange kolon (:)), etterfulgt av et tall som kalles "bitfelt": Bitdomene betyr at informasjon ikke trenger å oppta en hel byte når den lagres, men kun opptar noen få eller én binær bit. For eksempel, når du lagrer en switchingsstørrelse, finnes det bare to tilstander, 0 og 1, og du kan bruke én bits binær. For å spare lagringsplass og gjøre behandlingen enklere, tilbyr C en datastruktur kalt «bitfelt» eller «bitfelt». Det såkalte «bitfeltet» deler binærfilene i en byte inn i flere forskjellige regioner og beskriver antall biter i hver region. Hvert domene har et domenenavn, som tillater operasjoner per domenenavn i programmet. Dette gjør det mulig å representere flere forskjellige objekter i et byte-binært bitfelt. (2) Abstrakte fellesfunksjoner Oppmerksomme lesere vil oppdage at tildeling av en verdi til en struct ofte innebærer å tildele en 16-bits usignert int-type verdi til to 8-bits usignerte char-typeverdier, som følger: dmaConfig.SRCADDRH=(Usignert Char)((Usignert Int)&sourceString >>8); //源地址 dmaConfig.SRCADDRL=(Usignert Char)((Usignert Int)&sourceString);
For denne typen ofte brukte funksjon kan vi like gjerne abstrahere den som en generell funksjon, som følger: #define SET_WORD(destH,destL,ord)
gjøre{ destH=(Usignert Char)((Usignert Int)ord >>8); destL=(Usignert Char)((Usignert Int)ord); }mens(0)
I fremtiden, når du trenger å utføre en lignende splittingsoperasjon, kan du kalle den direkte, som følger: SET_WORD(dmaConfig.SRCADDRH, dmaConfig.SRCADDRL, &sourceString);
(2) Aktiver konfigurasjon: Først, den første adressen til strukturen&dmaConfigDe høye/lave 8 bitene tildeles henholdsvis SFRDMA0CFGHogDMA0CFGL(hvor 0 representerer konfigurasjonen for kanal 0, CC2430 inneholder 5 DMA-kanaler, kanal 0 brukes her). JaDMAARM.0Tildel verdien 1 for å aktivere konfigurasjonen av kanal 0 slik at kanal 0 er i arbeidsmodus. (3) Aktiver DMA-overføring:HøyreDMAREQ.0Tildel verdien 1 for å starte DMA-overføringen av kanal 0. (4) Vent på at DMA skal bli sendt:Etter at DMA-en til kanal 0 er sendt, vil avbruddet bli utløst, og avbruddsflagget til kanal 0 vil bli utløstDMAIRQ.0vil automatisk bli satt til 1. Hvert tegn i de to strengene sammenlignes deretter, og verifikasjonsresultatet sendes til PC-en. (4) Eksperimentelle resultaterFørst åpner du verktøyet for feilsøking av serielle porter, og starter deretter CC2430-feilsøkingen, og følgende skjerm vises:
Du vil finnedestStringInnholdet er fullstendig avslørtsourceStringFull. Ferdig~ 3. KonklusjonDenne delen introduserer bruken av DMA, selv om den er veldig enkel, men jeg tror du har forstått den grunnleggende bruken av DMA, og du kan også analysere den rolig når du møter komplekse bruksscenarier i fremtiden. Uansett hvor god en stasjonær PC er, vil den fryse, og på samme måte vil et innebygd system uunngåelig stagnere. I neste avsnitt vil vi introdusere en svært effektiv metode for systematisk tilbakestilling: vaktbikkjer.
|