Bu makale makine çevirisi ayna makalesidir, orijinal makaleye geçmek için lütfen buraya tıklayın.

Görünüm: 8951|Yanıt: 0

Zigbee Yolculuğu (7): Birkaç önemli CC2430 temel deneyi - DMA iletimi

[Bağlantıyı kopyala]
Yayınlandı 30.10.2014 23:22:16 | | | |
1. Üst ve alt katların birbirine bağlanması

Önceki bölümde ADC'lerin kullanımından bahsetmiştik ve çip içi sıcaklık sensörünü örnekledik. Gerçek projelerde sensör sayısı genellikle çok fazladır ve büyük miktarda dönüşüm verisi işlenmesi gerekir. Bu veriyi taşımak CPU üzerinde çok fazla yük oluşturur. CPU'yu boşaltmak ve başka şeyler yapacak enerji vermek için DMA (Direct Memory Access) işe yarayabilir~

Aşağıdaki giriş Zigbee Teknoloji Uygulama Eğitimi'nden alınmıştır:

DMA, doğrudan belleğe erişimin kısaltmasıdır ve "doğrudan bellek erişimi" anlamına gelir. Bu, ADC/UART/RF vericileri ve bellek gibi çevresel birimlerin, "DMA kontrolcüsü" kontrolü altında çok az CPU müdahalesi olmadan veri alışverişi yapabildiği yüksek hızlı bir veri iletim modudur. Veri transferinin başında ve sonunda biraz işlem yapmanın yanı sıra, CPU transfer sırasında başka işler de yapabilir. Bu şekilde, CPU ve veri etkileşimleri çoğu zaman paralel çalışıyor. Sonuç olarak, sistemin genel verimliliği büyük ölçüde artırılabilir.

Girişten de görebileceğiniz gibi, DMA birçok senaryoda kullanılabilir. Bu deney yalnızca en basit DMA iletimi içerir ve DMA'nın genel kullanımını göstermeyi amaçlar. DMA'nın diğer senaryolarda uygulanmasına gelince, gelecekte kapsamlı deneylerde uygulanacaktır.

2. DMA iletim deneyi(1) Deneye giriş

Dizi karakterlerisourceStringİçerik, DMA aracılığıyla karakter dizisine aktarılırdestString, dönüşüm sonucu PC'de seri port üzerinden görüntülenir.

(2) Program akış şeması

(3) Deneysel kaynak kodu ve analiz/*
    Deneysel Açıklama: Karakter dizisi sourceString'in içeriği DMA üzerinden destString karakter dizisine aktarılır ve dönüşüm sonucu PC'de seri portu üzerinden görüntülenir.
*/

#include

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

/*用于配置DMA的结构体
-------------------------------------------------------*/
#pragma bitfield=ters
typedef yapı
{
  imzasız charSRCADDRH;           //源地址高8位
  imzasız charSRCADDRL;           //源地址低8位
  imzasız charDESTADDRH;         //目的地址高8位
  imzasız charDESTADDRL;         //目的地址低8位
  imzasız charVLEN :3;     //长度域模式选择
  imzasız charLENH :5;     //传输长度高字节
  imzasız charLENL :8;     //传输长度低字节
  imzasız charKELIME BOYUTU :1;     //字节(byte)或字(word)传输
  imzasız charTMODE :2;     //传输模式选择
  imzasız charTRIG :5;     //触发事件选择
  imzasız charSRCINC :2;     //源地址增量:-1/0/1/2
  imzasız charDESTINC :2;     //目的地址增量:-1/0/1/2
  imzasız charIRQMASK :1;     //中断屏蔽
  imzasız charM8 :1;     //7或8bit传输长度,仅在字节传输模式下适用
  imzasız charÖNCELIK :2;     //优先级
}DMA_CFG;
#pragma bitfields=varsayılan

/*系统时钟初始化
-------------------------------------------------------*/
Voidxtal_init(Void)
{
  UYKU &= ~0x04;            //都上电
  while(! (UYKU &0x40));     //晶体振荡器开启且稳定
  CLKCON &= ~0x47;            32MHz kristal osilatör seçin
  UYKU |=0x04;
}

/*LED初始化
-------------------------------------------------------*/
Voidled_init(Void)
{
  P1SEL =0x00;         P1 normal I/O portudur
  P1DIR |=0x0F;         P1.0 P1.1 P1.2 P1.3 çıkışı
  
  led1 =1;               //关闭所有LED
  led2 =1;
  led3 =1;
  led4 =1;
}

/*UART0通信初始化
-------------------------------------------------------*/
VoidUart0Init(imzasız charStopBits,imzasız charEşitlik)
{
   P0SEL |=  0x0C;                  //初始化UART0端口,设置P0.2与P0.3为外部设备IO口
   PERCFG&= ~0x01;                  İlk isteğe bağlı pozisyon olarak UART0'ı seçin, yani RXD'den P0.2'ye ve TXD'den P0.3'e
   
   U0CSR =0xC0;                    UART moduna ayar ve alıcıyı etkinleştir
   
   U0GCR =11;
   U0BAUD =216;                    //设置UART0波特率为115200bps
   
   U0UCR |= StopBits| Eşitlik;        //设置停止位与奇偶校验
}

/*UART0发送数据
-------------------------------------------------------*/
Void  Uart0Send(imzasız charveriler)
{
  while(U0CSR&0x01);   //等待UART空闲时发送数据
  U0DBUF = veri;
}

/*UART0发送字符串
-------------------------------------------------------*/
VoidUart0SendString(imzasız char*s)
{
  while(*s !=0)         //依次发送字符串s中的每个字符
    Uart0Send(*s++);
}

/*主函数
-------------------------------------------------------*/
Voidmain(Void)
{
  DMA_CFG dmaConfig;      //定义配置结构体
  
  imzasız charsourceString[]="Ben kaynakDiziyim!";      //源字符串
  imzasız chardestString[boyutunun(sourceString)] ="Ben destString'im!";  //目的字符串
  
  chari;
  charerror=0;
  
  xtal_init();            //系统时钟初始化
  led_init();
  Uart0Init(0x00,0x00);   //UART初始化
  
  Uart0SendString(sourceString);         //传输前的原字符数组
  Uart0SendString(destString);           //传输前的目的字符数组
  
  //配置DMA结构体
  dmaConfig.SRCADDRH=(imzasız char)((imzasız int)&sourceString >>8);     //源地址
  dmaConfig.SRCADDRL=(imzasız char)((imzasız int)&sourceString);
   
  dmaConfig.DESTADDRH=(imzasız char)((imzasız int)&destString >>8);      //目的地址
  dmaConfig.DESTADDRL=(imzasız char)((imzasız int)&destString);
  
  dmaConfig.VLEN=0x00;         //选择LEN作为传送长度
  
  dmaConfig.LENH=(imzasız char)((imzasız int)boyutunun(sourceString) >>8);  //传输长度
  dmaConfig.LENL=(imzasız char)((imzasız int)boyutunun(sourceString));
  
  dmaConfig.WORDSIZE=0x00;     //选择字节(byte)传送
  
  dmaConfig.TMODE=0x01;        //选择块传送(block)模式
  
  dmaConfig.TRIG=0;            Tetik yok (manuel tetikleme olarak anlaşılabilir)
  
  dmaConfig.SRCINC=0x01;      //源地址增量为1
  
  dmaConfig.DESTINC=0x01;      //目的地址增量为1
  
  dmaConfig.IRQMASK=0;         //DMA中断屏蔽
   
  dmaConfig.M8=0x00;           //选择8位长的字节来传送数据
  
  dmaConfig.PRIORITY=0x02;     //传输优先级为高
  

  DMA0CFGH=(imzasız char)((imzasız int)&dmaConfig >>8);   //将配置结构体的首地址赋予相关SFR
  DMA0CFGL=(imzasız char)((imzasız int)&dmaConfig);
  
  DMAARM=0x01;                 //启用配置
  
  DMAIRQ=0x00;                 //清中断标志
  DMAREQ=0x01;                 //启动DMA传输
  
  while(! (DMAIRQ&0x01));               //等待传输结束
  
  için(i=0; i <boyutunun(sourceString); i++)   //校验传输的正确性
  {
    eğer(sourceString!=destString)
      hata++;
  }
  
  eğer(hata==0)                          //将结果通过串口传输到PC
  {
    Uart0SendString("Doğru!");
    Uart0SendString(destString);        //传输后的目的字符数组
  }
  else
    Uart0SendString("Hata!");

  while(1);
}

DMA kullanmanın temel süreci şudur:DMA'yı yapılandırmaYapılandırmayı etkinleştirDMA transferine başlayın → DMA transferinin bitmesini bekleyin.Aşağıdakiler sırasıyla şunlardır:

  (1) DMA'yı yapılandırmak: Öncelikle, DMA konfigürasyon edilmelidir, ancak DMA'nın yapılandırması özeldir: bazı SFR'lere doğrudan değer atmak yerine, bir yapıyı dışarıdan tanımlar, ona değerler atar ve ardından bu yapının ilk adresinin yüksek 8 bitini atarDMA0CFGH, daha düşük 8 haneli bir madde veriyorDMA0CFGL。 (Yapılandırma yapısındaki ayrıntılı talimatlar için lütfen CC2430 Çin kılavuzuna bakınız)

CC2430 İpuçları
Yukarıdaki kaynak kodda yapılandırma yapılarının tanımıyla ilgili iki açıklama noktası vardır:
(1) Bit alanı
Bu yapı tanımlanırken, birçok iki nokta (:)) kullanılır, ardından "bit alanı" olarak adlandırılan bir sayı gelir:
Bit alanı, bilginin depolandığında tam bir bayt kaplaması gerekmemesi, sadece birkaç veya bir ikili bit kaplaması anlamına gelir. Örneğin, bir anahtarlama büyüklüğü depolanırken, sadece iki durum vardır, 0 ve 1, ve bir bit ikili kullanılabilir. Depolama alanı tasarrufu ve işlemeyi kolaylaştırmak için C, "bit alanı" veya "bit alanı" adı verilen bir veri yapısı sağlar. Sözde "bit alanı" olarak adlandırılan bu yöntem, bayttaki ikili dosyaları birkaç farklı bölgeye böler ve her bölgedeki bit sayısını tanımlar. Her alan adının bir alan adı vardır ve programda alan adı ile işlemlere izin verir. Bu, birkaç farklı nesnenin baytlı ikili bit alanında temsil edilmesine olanak tanır.
(2) Soyut ortak fonksiyonlar
Dikkatli okuyucular, bir yapıya değer atamanın genellikle iki 8 bitlik işaretsiz karakter tipi değerine 16 bitlik imzasız bir int türü değeri atanmasını gerektirdiğini göreceklerdir:
dmaConfig.SRCADDRH=(imzasız char)((imzasız int)&sourceString >>8);     //源地址
dmaConfig.SRCADDRL=(imzasız char)((imzasız int)&sourceString);

Bu tür sıkça kullanılan fonksiyon için, bunu genel bir fonksiyon olarak soyutlaştırabiliriz, şu şekilde:
#define SET_WORD(destH,destL,kelime)
    yapmak{
       destH=(imzasız char)((imzasız int)kelime >>8);     
       destL=(imzasız char)((imzasız int)kelime);
    }while(0)

Gelecekte benzer bir bölme işlemi yapmanız gerektiğinde bunu doğrudan şu şekilde çağırabilirsiniz:
SET_WORD(dmaConfig.SRCADDRH, dmaConfig.SRCADDRL, &sourceString);


  (2) Yapılandırmayı etkinleştir: İlk olarak, yapının ilk adresi&dmaConfigYüksek/düşük 8 bit sırasıyla SFR'ye atanırDMA0CFGHveDMA0CFGL(burada 0, kanal 0 için yapılandırmayı temsil eder, CC2430 5 DMA kanalı içerir, burada kanal 0 kullanılır). EvetDMAARM.0Kanal 0'ın çalışma modunda olması için kanal 0'ın yapılandırmasını etkinleştirmek için 1 değeri atayın.

  (3) DMA iletimi etkinleştirin:SağDMAREQ.0Kanal 0'ın DMA iletimini başlatmak için 1 değeri atayın.

  (4) DMA'nın iletilmesini bekleyin:Kanal 0'ın DMA'sı iletildikten sonra, kesme tetiklenir ve kanal 0'ın kesme bayrağı tetiklenirDMAIRQ.0otomatik olarak 1'e ayarlanacak. İki dizinin her karakteri karşılaştırılır ve doğrulama sonucu PC'ye gönderilir.

(4) Deneysel sonuçlar

Öncelikle, seri port hata ayıklama aracını açın, ardından CC2430 hata ayıklamasını başlatın; aşağıdaki ekran belirecek:

BulacaksınızdestStringİçerik tamamen açıklandısourceStringdolmuş.

Bitti~

3. Sonuç

Bu bölüm DMA'nın kullanımını tanıtıyor, çok basit olsa da, temel kullanımını anladığınızı düşünüyorum ve gelecekte karmaşık kullanım senaryolarıyla karşılaştığınızda sakin bir şekilde analiz edebilirsiniz.

Bir masaüstü ne kadar iyi olursa olsun, donur ve benzer şekilde, gömülü bir sistem kaçınılmaz olarak durağan. Bir sonraki bölümde, sistematik sıfırlama için çok etkili bir yöntemi tanıtacağız: gözetici köpekler.






Önceki:Zigbee Yolculuğu (6): Birkaç önemli CC2430 temel deneyi - ADC tek örnekleme
Önümüzdeki:Zigbee Yolculuğu (8): Birkaç önemli CC2430 temel deneyi - gözcüler
Feragatname:
Code Farmer Network tarafından yayımlanan tüm yazılım, programlama materyalleri veya makaleler yalnızca öğrenme ve araştırma amaçları içindir; Yukarıdaki içerik ticari veya yasa dışı amaçlarla kullanılamaz, aksi takdirde kullanıcılar tüm sonuçları ödemelidir. Bu sitedeki bilgiler internetten alınmakta olup, telif hakkı anlaşmazlıklarının bu siteyle hiçbir ilgisi yoktur. Yukarıdaki içeriği indirmeden sonraki 24 saat içinde bilgisayarınızdan tamamen silmelisiniz. Programı beğendiyseniz, lütfen orijinal yazılımı destekleyin, kayıt satın alın ve daha iyi orijinal hizmetler alın. Herhangi bir ihlal olursa, lütfen bizimle e-posta yoluyla iletişime geçin.

Mail To:help@itsvse.com