|
1. З'єднання верхнього та нижнього рівнів У попередньому розділі ми говорили про використання АЦП і аналізували датчик температури на чипі. У реальних проєктах кількість сенсорів часто велика, і потрібно обробляти значну кількість даних конвертації. Переміщення цих даних створить велике навантаження на процесор. Щоб звільнити процесор і дати йому енергію для інших завдань, може стати в пригоді DMA (Direct Memory Access~ Наступний вступ взято з навчального посібника Zigbee Technology Practice: DMA — це скорочення від прямого доступу до пам'яті, що означає «прямий доступ до пам'яті». Це режим високошвидкісної передачі даних, у якому периферійні пристрої, такі як ADC/UART/RF трансивери та пам'ять, можуть обмінюватися даними безпосередньо під керуванням «DMA-контролера» без мінімального втручання процесора. Окрім невеликої обробки на початку та наприкінці передачі даних, процесор може виконувати й інші завдання під час передачі. Таким чином, CPU та ці дані працюють паралельно більшість часу. Внаслідок цього загальна ефективність системи може бути значно підвищена.
Як видно з вступу, DMA можна використовувати в багатьох ситуаціях. Цей експеримент передбачає лише найпростішу передачу DMA і має на меті продемонструвати загальне використання DMA. Щодо застосування ДМА в інших сценаріях, його буде реалізовано в комплексних експериментах у майбутньому. 2. Експеримент передачі DMA(1) Вступ до експериментуСимволи масивуsourceStringКонтент передається до масиву символів через DMAdestString, результат конвертації відображається на ПК через послідовний порт. (2) Блок-схема програми
(3) Експериментальний вихідний код і аналіз/*
Експериментальний опис: Вміст sourceString символічного масиву передається до масиву символів destString через DMA, а результат конвертації відображається на ПК через послідовний порт.
*/
#include
#define led1 P1_0
#define led2 P1_1
#define led3 P1_2
#define led4 P1_3
/*用于配置DMA的结构体
-------------------------------------------------------*/
#pragma бітполя=перевернуті
typedef Struct
{
Без підпису charSRCADDRH; //源地址高8位
Без підпису charSRCADDRL; //源地址低8位
Без підпису charDESTADDRH; //目的地址高8位
Без підпису charDESTADDRL; //目的地址低8位
Без підпису charVLEN :3; //长度域模式选择
Без підпису charЛЕНХ:5; //传输长度高字节
Без підпису charLENL :8; //传输长度低字节
Без підпису charРОЗМІР СЛОВА:1; //字节(byte)或字(word)传输
Без підпису charTMODE:2; //传输模式选择
Без підпису charТРИГ:5; //触发事件选择
Без підпису charSRCINC :2; //源地址增量:-1/0/1/2
Без підпису charDESTINC :2; //目的地址增量:-1/0/1/2
Без підпису charIRQMASK :1; //中断屏蔽
Без підпису charM8 :1; //7或8bit传输长度,仅在字节传输模式下适用
Без підпису charПРІОРИТЕТ:2; //优先级 }DMA_CFG; #pragma bitfields=за замовчуванням
/*系统时钟初始化
-------------------------------------------------------*/
Порожнечаxtal_init(Порожнеча)
{ SLEEP &= ~0x04; //都上电
поки(! (SLEEP &0x40)); //晶体振荡器开启且稳定 CLKCON &= ~0x47; Виберіть кристалічний осцилятор на 32 МГц СОН |=0x04;
}
/*LED初始化
-------------------------------------------------------*/
Порожнечаled_init(Порожнеча)
{ P1SEL =0x00; P1 — це звичайний порт введення/виведення P1DIR |=0x0F; P1.0 P1.1 P1.2 P1.3 вихід
led1 =1; //关闭所有LED led2 =1; led3 =1; led4 =1;
}
/*UART0通信初始化
-------------------------------------------------------*/
ПорожнечаUart0Init(Без підпису charStopBits,Без підпису charПаритет)
{ P0SEL |= 0x0C; //初始化UART0端口,设置P0.2与P0.3为外部设备IO口 PERCFG&= ~0x01; Виберіть UART0 як першу опціональну позицію, тобто RXD до P0.2 і TXD до P0.3
U0CSR =0xC0; Встановіть режим UART і увімкніть акцептор
U0GCR =11; U0BAUD =216; //设置UART0波特率为115200bps
U0UCR |= StopBits| Паритет; //设置停止位与奇偶校验
}
/*UART0发送数据
-------------------------------------------------------*/
Порожнеча Uart0Send(Без підпису charдані)
{
поки(U0CSR&0x01); //等待UART空闲时发送数据 U0DBUF = дані;
}
/*UART0发送字符串
-------------------------------------------------------*/
ПорожнечаUart0SendString(Без підпису char*s)
{
поки(*s !=0) //依次发送字符串s中的每个字符 Uart0Send(*s++);
}
/*主函数
-------------------------------------------------------*/
ПорожнечаГоловна(Порожнеча)
{ DMA_CFG dmaConfig; //定义配置结构体
Без підпису charsourceString[]="Я — ДжерелоСтрунка!"; //源字符串
Без підпису chardestString[розмір(джерелоРядок)] ="Я — найкраща Струна!"; //目的字符串
chari;
charпомилка=0;
xtal_init(); //系统时钟初始化 led_init(); Uart0Init(0x00,0x00); //UART初始化
Uart0SendString(sourceString); //传输前的原字符数组 Uart0SendString(destString); //传输前的目的字符数组
//配置DMA结构体 dmaConfig.SRCADDRH=(Без підпису char)((Без підпису int)&sourceString >>8); //源地址 dmaConfig.SRCADDRL=(Без підпису char)((Без підпису int)&sourceString);
dmaConfig.DESTADDRH=(Без підпису char)((Без підпису int)&destString >>8); //目的地址 dmaConfig.DESTADDRL=(Без підпису char)((Без підпису int)&destString);
dmaConfig.VLEN=0x00; //选择LEN作为传送长度
dmaConfig.LENH=(Без підпису char)((Без підпису int)розмір(sourceString) >>8); //传输长度 dmaConfig.LENL=(Без підпису char)((Без підпису int)розмір(sourceString));
dmaConfig.WORDSIZE=0x00; //选择字节(byte)传送
dmaConfig.TMODE=0x01; //选择块传送(block)模式
dmaConfig.TRIG=0; Немає тригера (можна розуміти як ручне спускання)
dmaConfig.SRCINC=0x01; //源地址增量为1
dmaConfig.DESTINC=0x01; //目的地址增量为1
dmaConfig.IRQMASK=0; //DMA中断屏蔽
dmaConfig.M8=0x00; //选择8位长的字节来传送数据
dmaConfig.PRIORITY=0x02; //传输优先级为高
DMA0CFGH=(Без підпису char)((Без підпису int)&dmaConfig >>8); //将配置结构体的首地址赋予相关SFR DMA0CFGL=(Без підпису char)((Без підпису int)&dmaConfig);
DMAARM=0x01; //启用配置
DMAIRQ=0x00; //清中断标志 МАРЕК=0x01; //启动DMA传输
поки(! (DMAIRQ&0x01)); //等待传输结束
для(i=0; i <розмір(джерелоString); i++) //校验传输的正确性 {
якщо(джерелоРядок!=destString) error++; }
якщо(помилка==0) //将结果通过串口传输到PC { Uart0SendString("Вірно!"); Uart0SendString(destString); //传输后的目的字符数组 }
інше Uart0SendString(«Помилка!»);
поки(1);
}
Основний процес використання ДМА такий:Налаштувати DMA → Увімкнути налаштування → Почніть передачу DMA → чекайте, поки завершиться трансфер DMA.Відповідно: (1) Налаштувати DMA: По-перше, потрібно налаштувати DMA, але конфігурація DMA є особливою: замість прямого призначення значень деяким SFR, вона визначає структуру зовнішньо, присвоює їй значення, а потім призначає високі 8 бітів першої адреси цієї структуриDMA0CFGH, що дає йому нижчі 8 цифрDMA0CFGL。 (Детальні інструкції щодо конфігурації, будь ласка, зверніться до китайського посібника CC2430) Поради щодо CC2430Є два моменти, які слід уточнити щодо визначення конфігураційних структур у наведеному вище вихідному коді: (1) Бітова область При визначенні цієї структури використовується багато двокрапок (:), а потім число, яке називається «бітовим полем»: Домен бітів означає, що інформація не повинна займати повний байт при збереженні, а займає лише кілька або один бінарний біт. Наприклад, при зберіганні перемикаючої величини існує лише два стани — 0 і 1, і можна використовувати однобітний бінарний код. Щоб зекономити місце для зберігання та спростити обробку, C надає структуру даних, яку називають «бітовим полем» або «бітовим полем». Так зване «бітове поле» ділить бінарні файли в байті на кілька різних областей і описує кількість бітів у кожній області. Кожен домен має доменне ім'я, що дозволяє виконувати операції за доменним ім'ям у програмі. Це дозволяє представляти кілька різних об'єктів у бінарному бітовому полі з байтами. (2) Абстрактні спільні функції Уважні читачі знайдуть, що призначення значення структурі часто передбачає присвоєння 16-бітного незнакового int-типу двом 8-бітним незнаковим значенням типу символу, а саме: dmaConfig.SRCADDRH=(Без підпису char)((Без підпису int)&sourceString >>8); //源地址 dmaConfig.SRCADDRL=(Без підпису char)((Без підпису int)&sourceString);
Для такого типу часто використовуваної функції можна абстрагувати її як загальну функцію, а саме: #define SET_WORD(destH,destL,word)
робити{ destH=(Без підпису char)((Без підпису int)слово >>8); destL=(Без підпису char)((Без підпису int)слово); }поки(0)
У майбутньому, коли потрібно виконати подібну операцію розщеплення, ви можете викликати її напряму, наступним чином: SET_WORD(dmaConfig.SRCADDRH, dmaConfig.SRCADDRL, &sourceString);
(2) Увімкнути конфігурацію: По-перше, перша адреса споруди&dmaConfigВерхні/низькі 8 біт призначаються SFR відповідно.DMA0CFGHіDMA0CFGL(де 0 позначає конфігурацію каналу 0, CC2430 містить 5 каналів DMA, тут використовується канал 0). ТакDMAARM.0Присвоїть значення 1, щоб увімкнути налаштування каналу 0 так, щоб канал 0 працював у робочому режимі. (3) Увімкнути передачу DMA:ПраворучDMAREQ.0Присвоїть значення 1 для початку трансляції DMA каналу 0. (4) Чекати на передачу DMA:Після передачі DMA каналу 0 спрацьовується переривання, і спрацьовується прапорець переривання каналу 0DMAIRQ.0буде автоматично встановлено на 1. Кожен символ двох рядків порівнюється, і результат верифікації надсилається на ПК. (4) Експериментальні результатиСпочатку відкрийте інструмент налагодження послідовних портів, а потім запустіть налагодження CC2430, і з'явиться наступний екран:
Ви знайдетеdestStringКонтент повністю розкритийsourceStringнаповненим. Готово~ 3. ВисновокЦей розділ знайомить із використанням DMA, хоча це дуже просто, але, думаю, ви зрозуміли основне застосування DMA, і також можете спокійно аналізувати його, коли стикаєтеся зі складними сценаріями використання в майбутньому. Незалежно від того, наскільки хороший десктоп, він зависає, і так само вбудована система неминуче застоюється. У наступному розділі ми представимо дуже ефективний метод систематичного скидання: watchdogs.
|