|
1. Соединение верхнего и нижнего уровней В предыдущем разделе мы говорили об использовании АЦП и анализировали датчик температуры внутри чипа. В реальных проектах количество датчиков часто велико, и необходимо обрабатывать большое количество данных преобразования. Перемещение этих данных сильно нагружает процессор. Чтобы освободить процессор и дать ему энергию для других задач, DMA (Direct Memory Access) может пригодиться~ Следующее введение взято из учебника по практике технологий Zigbee: DMA — это сокращение от прямого доступа к памяти, что означает «прямой доступ к памяти». Это высокоскоростной режим передачи данных, при котором периферийные устройства, такие как ADC/UART/RF трансиверы и память, могут обмениваться данными непосредственно под управлением «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
{
Без подписания ЧарSRCADDRH; //源地址高8位
Без подписания ЧарSRCADDRL; //源地址低8位
Без подписания ЧарDESTADDRH; //目的地址高8位
Без подписания ЧарDESTADDRL; //目的地址低8位
Без подписания ЧарVLEN :3; //长度域模式选择
Без подписания ЧарЛЕНХ:5; //传输长度高字节
Без подписания ЧарLENL :8; //传输长度低字节
Без подписания ЧарРАЗМЕР СЛОВА:1; //字节(byte)或字(word)传输
Без подписания ЧарTMODE :2; //传输模式选择
Без подписания ЧарТРИГ:5; //触发事件选择
Без подписания ЧарSRCINC :2; //源地址增量:-1/0/1/2
Без подписания ЧарDESTINC :2; //目的地址增量:-1/0/1/2
Без подписания ЧарIRQMASK :1; //中断屏蔽
Без подписания ЧарM8 :1; //7或8bit传输长度,仅在字节传输模式下适用
Без подписания ЧарПРИОРИТЕТ: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(Без подписания ЧарStopBits,Без подписания ЧарПаритет)
{ 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(Без подписания Чарданные)
{
в то время как(U0CSR&0x01); //等待UART空闲时发送数据 U0DBUF = данные;
}
/*UART0发送字符串
-------------------------------------------------------*/
пустотаUart0SendString(Без подписания Чар*s)
{
в то время как(*s !=0) //依次发送字符串s中的每个字符 Uart0Send(*s++);
}
/*主函数
-------------------------------------------------------*/
пустотаОсновная(пустота)
{ DMA_CFG dmaConfig; //定义配置结构体
Без подписания ЧарsourceString[]=«Я — ИсточникСтруна!"; //源字符串
Без подписания ЧарdestString[размер(sourceString)] =«Я — самая Струна!"; //目的字符串
Чаря;
Чарошибка=0;
xtal_init(); //系统时钟初始化 led_init(); Uart0Init(0x00,0x00); //UART初始化
Uart0SendString(sourceString); //传输前的原字符数组 Uart0SendString(destString); //传输前的目的字符数组
//配置DMA结构体 dmaConfig.SRCADDRH=(Без подписания Чар)((Без подписания int)&sourceString >>8); //源地址 dmaConfig.SRCADDRL=(Без подписания Чар)((Без подписания int)&sourceString);
dmaConfig.DESTADDRH=(Без подписания Чар)((Без подписания int)&destString >>8); //目的地址 dmaConfig.DESTADDRL=(Без подписания Чар)((Без подписания int)&destString);
dmaConfig.VLEN=0x00; //选择LEN作为传送长度
dmaConfig.LENH=(Без подписания Чар)((Без подписания int)размер(sourceString) >>8); //传输长度 dmaConfig.LENL=(Без подписания Чар)((Без подписания 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=(Без подписания Чар)((Без подписания int)&dmaConfig >>8); //将配置结构体的首地址赋予相关SFR DMA0CFGL=(Без подписания Чар)((Без подписания int)&dmaConfig);
DMAARM=0x01; //启用配置
DMAIRQ=0x00; //清中断标志 DMAREQ=0x01; //启动DMA传输
в то время как(! (DMAIRQ&0x01)); //等待传输结束
для(i=0; я <размер(источник String); i++) //校验传输的正确性 {
если(sourceString!=destString) ошибка++; }
если(ошибка==0) //将结果通过串口传输到PC { Uart0SendString(«Верно!»); Uart0SendString(destString); //传输后的目的字符数组 }
Другое Uart0SendString(«Ошибка!»);
в то время как(1);
}
Основной процесс использования DMA:Настроить DMA → Включить конфигурацию → Начать перевод по DMA → ждать, пока завершится перевод DMA.Следующие: (1) Настроить DMA: Прежде всего, необходимо настроить DMA, но конфигурация DMA особенная: вместо прямого назначения значений некоторым SFR, она определяет структуру внешне, присваивает значения и затем назначает высокие 8 бит первого адреса этой структурыDMA0CFGH, давая ему более низкие 8 цифрDMA0CFGL。 (Для подробных инструкций по структуре конфигурации, пожалуйста, обратитесь к китайскому руководству CC2430) Советы по CC2430Есть два момента, которые нужно уточнить относительно определения конфигурационных структур в исходном коде, приведённом выше: (1) Битовая область При определении этой структуры используется много двоеточных (:), за которыми следует число, называемое «битовым полем»: Битовая область означает, что информация не обязана занимать полный байт при хранении, а занимает лишь несколько или один бинарный бит. Например, при хранении коммутирующей величины существует только два состояния — 0 и 1, и можно использовать однобитную бинарную систему. Чтобы сэкономить место в памяти и упростить обработку, C предоставляет структуру данных, называемую «битовым полем» или «битовым полем». Так называемое «битовое поле» делит бинарные данные в байте на несколько различных областей и описывает количество бит в каждой области. Каждый домен имеет доменное имя, позволяющее выполнять операции по доменному имени в программе. Это позволяет представить несколько различных объектов в бинарном битовом поле с байтами. (2) Абстрактные общие функции Внимательные читатели обнаружат, что присвоение значения структуре часто включает присвоение 16-битного значения незнакового int-типа двум 8-битным незнаковым значениям символа, следующим образом: dmaConfig.SRCADDRH=(Без подписания Чар)((Без подписания int)&sourceString >>8); //源地址 dmaConfig.SRCADDRL=(Без подписания Чар)((Без подписания int)&sourceString);
Для такого типа часто используемой функции можно абстрагировать его как общую функцию, следующим образом: #define SET_WORD(destH,destL,word)
делать{ destH=(Без подписания Чар)((Без подписания int)слово >>8); destL=(Без подписания Чар)((Без подписания int)word); }в то время как(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, и также сможете спокойно проанализировать её, столкнувшись со сложными сценариями использования в будущем. Как бы ни был хорош рабочий стол, он зависает, и встроенная система неизбежно застопорится. В следующем разделе мы представим очень эффективный метод систематического сброса: сторожевые собаки.
|