Урок 176. CMSIS. STM32F1. DMA. MEM2MEM

В данном уроке мы попытаемся поработать с периферией DMA контроллера STM32F1. Мы попробуем скопировать некоторое количество информации из одной области памяти в другую (MEM2MEM).

Подобную процедуру мы с вами уже проводили в уроке 155 и уроке 156. Только в данных уроках мы использовали для этого библиотеки HAL и LL. А в данном уроке ту же самую процедуру мы проделаем с применением уже возможностей другой библиотеки — CMSIS.

Периферия DMA нами в предыдущих занятиях уже полностью изучена на аппаратном уровне, причём мы изучили и инициализацию данной периферии, хотя сами мы её не писали, нам в этом любезно помогал проектогенератор Cube MX. Тем не менее нам знаком порядок инициализации, а также порядок работы с периферией. Поэтому, в принципе, мы можем сразу же приступить к проекту.

Прежде чем приступим непосредственно к проекту, скажу ещё, что схему мы оставим без изменений и возьмём схему прошлого урока, например, для устройства SLAVE, хотя вполне можно взять и для MASTER, так как они абсолютно одинаковые. Логический анализатор сегодня не используем

 

 

Проект сделан из будет из проекта прошлого урока для ведущего устройства с именем CMSIS_SPI_MASTER и назван был CMSIS_DMA_MEM2MEM.

Откроем проект в Keil и из файла main.c удалим пока вот эти глобальные макросы, касающиеся модуля SPI1

 

#define CS1_RESET() SET_BIT(GPIOA->ODR,GPIO_ODR_ODR4)

#define CS1_SET() CLEAR_BIT(GPIOA->ODR,GPIO_ODR_ODR4)

#define SPI1_ENABLE() SET_BIT(SPI1->CR1, SPI_CR1_SPE);

 

Функцию SPI1_Init также удалим вместе с телом.

В функции main() удалим вот эти строки

 

SPI1_Init();

CS1_RESET();

SPI1_ENABLE();

Number_7219(87654321);

delay_ms(2000);

 

 

Также удалим всё из бесконечного цикла и удалим объявление локальной переменной r

 

uint16_t i, r;

 

Выше функции SPI2_Init добавим функцию инициализации периферии DMA1

 

 

Добавим в тело данной функции вот этот код

 

 

Думаю, здесь объяснять особо нечего, так как те же самые действия проводятся и в LL при автогенерации, тем не менее кратко поясню.

Сначала мы настроили направление передачи — из памяти в память посредством включения бита CCR1_MEM2MEM, затем выбрали приоритет, режим DMA, также настроили инкрементирование адреса и источника и приёмника, ширину данных (16 бит) и для приёмника и для источника, а также включили глобальные прерывания от модуля DMA1.

Вызовем данную функцию в main()

 

 

Добавим два буфера, один для передачи в периферию, другой для приёма из неё

 

 

 

В функции main() заполним буфер передачи декрементированными значениями от 1024 до 1

 

 

Далее добавим вот такой код

 

 

То же самое мы делали и когда работали с LL, только сейчас это всё переписано в свете требований CMSIS. Сначала мы отключили канал 1 канал DMA1, затем очистили флаги окончания передачи и ошибки, также занесли в регистр CNDTR1_NDT количество передаваемых данных — у нас будет 1024 полуслова. Затем мы занесли адрес приёмника и источника в соответствующие регистры канала 1, потом включили прерывания по событию окончания передачи пакета данных и по возникновению ошибки, и в конце включили канал, что и является сигналом к началу передачи по шине DMA1.

Добавим глобальную переменную для флага окончания передачи

 

 

В самом низу файла добавим функцию-обработчик прерываний от DMA1

 

 

Думаю, что здесь тоже всё ясно.

Если у нас произошло прерывание, мы попадаем в данную функцию. Если в этот момент взведен флаг полного окончания передачи, то мы его очищаем и устанавливаем наш пользовательский флаг fl, а если прочитался флаг ошибки, то можно предпринять какие-то действия по выявлению данной ошибки, но мы ничего не будем предпринимать, мы лишь вставим здесь инструкцию nop. И если у нас всё же что-то пойдёт не так, то мы сюда поставим точку останова и узнаем то, что мы попали именно сюда, а дальше уж будем разбираться, что у нас за ошибка.

Вернёмся в функцию main(), подождём установки нашего пользовательского флага, сбросим его и отобразим по очереди элементы приёмного буфера на индикаторе. Если через DMA1 передача пройдёт нормально, то мы увидим убавляющиеся числа от 1024 до 1

 

 

Соберём проект прошьём контроллер и посмотрим, как убавляются числа на нашем индикаторе

 

 

Если немного подождать, то счётчик наш досчитает в обратную сторону до 1.

Итак, на данном занятии мы научились управлять периферией DMA в контроллере STM32F1 в режиме MEM2MEM (передачи из памяти в память), воспользовавшись при этом функционалом библиотеки CMSIS.

Всем спасибо за внимание!

 

 

 

Исходный код

 

 

Отладочную плату STM32F103C8T6 можно приобрести здесь STM32F103C8T6

Программатор недорогой можно купить здесь ST-Link V2

Индикатор светодиодный семиразрядный с драйвером MAX7219

 

 

Смотреть ВИДЕОУРОК в RuTube (нажмите на картинку)

STM CMSIS. STM32F1. DMA. MEM2MEM

 

Смотреть ВИДЕОУРОК в YouTube (нажмите на картинку)

STM CMSIS. STM32F1. DMA. MEM2MEM

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *

*