На прошлом занятии мы с вами начали плотно изучать DMA в контроллере STM32F1 и на практике, применяя возможности библиотеки HAL, нам удалось скопировать некоторое количество информации из одной области памяти в другую (MEM2MEM).
На данном уроке мы продолжим знакомство с DMA и ту же самую процедуру мы проделаем с применением уже возможностей другой библиотеки — LL, которая более гибкая, но взамен своей гибкости она уже возлагает требование наличия у нас более глубоких знаний об аппаратной реализации периферии. Поэтому, прежде чес приступить к проекту, мы продолжим изучение реализации DMA.
Скорее всего, полностью аппаратную реализацию периферии DMA мы в данном уроке также не изучим, потому что акцент будет сделан именно на режим передачи информации из одну область памяти в другую — (MEM2MEM).
В документации Reference Manual на контроллеры серии F1 нет подробного описания данного режима, но зато он вполне неплохо описан в аналогичной документации на контроллеры серии STM32F4, с которыми мы также с вами уже много работали, причём различия в режиме MEM2MEM между ними принципиального нет, так как он тоже здесь доступен в любом канале любого из двух контроллера DMA. Вот диаграмма, показывающая процесс передачи данных в режиме MEM2MEM
Различие с нашим контроллером STM32F1 будет только в наименовании регистров, так как у нас нет потоков, есть только каналы. Но принцип тот же.
Передача идёт через буфер, причём адрес источника заносится в регистр адреса периферии, в нашем случае будет DMA_CPARx, где x — номер используемого канала. Он используется здесь, видимо, потому, что нет двух раздельных регистров для адресов памяти. А вот для хранения адреса приёмника используется регистр адресации памяти, в нашем случае — DMA_CMARx, где x — также номер используемого канала.
Теперь, когда принцип передачи информации через DMA в режиме MEM2MEM немного понятен, можно приступить к изучению регистров и назначения их битов.
Начнём с регистра конфигурирования
Данный регистр существует в каждом канале двух контроллеров DMA.
В регистре все используемые биты работают как на чтение, так и на запись.
Назначение их следующее:
MEM2MEM (Memory to memory mode): регистр включения режима memory to memory
0 — режим MEM2MEM отключен
1 — режим MEM2MEM включен
Если режим отключен, то режим будет устанавливаться с помощью настройки направления передачи.
PL[1:0] (Channel priority level): битовое поле настройки приоритета канала
00 — Low (низкий)
01 — Medium (средний)
10 — High (высокий)
11 — Very high (очень высокий).
MSIZE[1:0] (Memory size): битовое поле настройки размерности данных в памяти (в случае использования режима MEM2MEM в приёмнике данных)
00 — 8 бит
01 — 16 бит
10 — 32 бита
11 — зарезервировано.
PSIZE[1:0] (Peripheral size): битовое поле настройки размерности данных в периферии (в случае использования режима MEM2MEM в источнике данных)
00 — 8 бит
01 — 16 бит
10 — 32 бита
11 — зарезервировано.
MINC (Memory increment mode): бит включения автоинкрементирования адреса памяти (в случае использования режима MEM2MEM адреса приёмника)
0 — автоинкрементирование отключено
1 — автоинкрементирование включено.
PINC (Peripheral increment mode): бит включения автоинкрементирования адреса периферии (в случае использования режима MEM2MEM адреса источника)
0 — автоинкрементирование отключено
1 — автоинкрементирование включено.
CIRC (Circular mode): бит включения циклического режима
0 — циклический режим отключен
1 — циклический режим включен.
DIR (Data transfer direction): бит настройки направления передачи данных
0 — передача данных из периферии в память (данное направление также включаем при использовании режима MEM2MEM)
1 — передача данных из памяти в периферию.
TEIE (Transfer error interrupt enable): бит включения прерываний в случае возникновения ошибки передачи данных
0 — прерывания отключены
1 — прерывания включены.
HTIE (Half transfer interrupt enable): бит включения прерываний по окончанию передачи половины передаваемых данных
0 — прерывания отключены
1 — прерывания включены.
TCIE (Transfer complete interrupt enable): бит включения прерываний по окончанию передачи всех данных
0 — прерывания отключены
1 — прерывания включены.
EN (Channel enable): бит включения канала
0 — канал отключен
1 — канал включен.
Следующий регистр — регистр состояния флагов прерываний
Биты данного регистра распределены по 4 на каждый канал, а так как каналов у нас максимум 7, то хватило одного регистра на все каналы.
В регистре все биты работают только на чтение. Флаги всех прерываний устанавливаются аппаратно, а сбрасываются программно в регистре DMA_IFCR.
Их назначение:
TEIFx (Channel x transfer error flag (x = 1 ..7)): флаг прерывания в случае возникновения ошибки передачи данных в канале
0 — ошибки передачи данных не происходило
1 — произошла ошибка передачи данных.
HTIFx (Channel x half transfer flag (x = 1 ..7)): флаг прерывания по окончанию передачи половины передаваемых данных
0 — окончания передачи половины передаваемых данных не происходило
1 — произошла передача половины передаваемых данных.
TCIFx (Channel x transfer complete flag (x = 1 ..7)): флаг прерывания по окончанию передачи всех данных
0 — окончания передачи данных не происходило
1 — произошло окончание передачи данных.
GIFx (Channel x global interrupt flag (x = 1 ..7)): флаг глобального прерывания
0 — событий TE, HT или TC не происходило
1 — произошло событие TE, HT или TC.
Следующий регистр — регистр сброса флагов прерываний
Подобно предыдущему регистру, биты данного регистра также распределены по 4 на каждый канал.
Все биты регистра доступны только на запись.
Их назначение:
CTEIFx (Channel x transfer error clear (x = 1 ..7)): сброс флага прерывания TEIF в регистре DMA_ISR
0 — не используется
1 — сброс флага.
CHTIFx (Channel x half transfer clear (x = 1 ..7)): сброс флага прерывания HTIF в регистре DMA_ISR
0 — не используется
1 — сброс флага.
CTCIFx (Channel x transfer complete clear (x = 1 ..7)): сброс флага прерывания TCIF в регистре DMA_ISR
0 — не используется
1 — сброс флага.
CGIFx (Channel x global interrupt clear (x = 1 ..7)): сброс флагов прерывания GIF, TEIF, HTIF и TCIF в регистре DMA_ISR
0 — не используется
1 — сброс флагов.
Следующий регистр — регистр количества передаваемых единиц информации (размерность единицы настраивается битовыми полями MSIZE и PSIZE регистра DMA_CCR)
Такой регистр существует для каждого канала. Все 16 используемых бит в нём содержат число, содержащее количество передаваемых единиц информации.
Следующий регистр — регистр адреса периферии для передачи данных (в случае использования режима MEM2MEM адреса источника)
Если битовое поле PSIZE регистра CCR соответствующего канала настроено на передачу 16-битных данных (полуслов), то бит 0 данного регистра DMA_CPARx игнорируется и значение адреса выравнивается до полуслова, а если PSIZE настроено на передачу 32-битных данных (слов), то игнорируются биты 0 и 1 и значение адреса уже выравнивается до слова.
Следующий регистр — регистр адреса памяти для передачи данных (в случае использования режима MEM2MEM адреса приёмника)
Если битовое поле MSIZE регистра CCR соответствующего канала настроено на передачу 16-битных данных (полуслов), то бит 0 данного регистра DMA_CMARx игнорируется и значение адреса выравнивается до полуслова, а если PSIZE настроено на передачу 32-битных данных (слов), то игнорируются биты 0 и 1 и значение адреса уже выравнивается до слова.
Вот, в принципе, и всё по регистрам DMA. Можно смело приступать к проекту.
Проект создадим из проекта урока 154, предназначенного для ведущего устройства с именем LL_SPI_MASTER и назовём его LL_DMA_MEM_TO_MEM.
Откроем проект в Cube MX и отключим сначала SPI1
Затем отключим ножку PA4
Включим в канале DMA1 канал 1 в режиме MEM2MEM и настроим размерность 16 бит, а также оставим инкрементирование адресов и приёмника и источника
Включим глобальные прерывания на канал DMA в NVIC
Включим использование библиотеки LL на DMA
Сгенерируем проект, откроем его в Keil, настроим программатор на автоперезагрузку, отключим оптимизацию и подключим к дереву проекту файл MAX7219 для индикатора.
В следующей части нашего урока мы мы напишем код, в котором скопируем данные из одного участка памяти в другой при помощи DMA.
Предыдущий урок Программирование МК STM32 Следующая часть
Отладочную плату STM32F103C8T6 можно приобрести здесь STM32F103C8T6
Программатор недорогой можно купить здесь ST-Link V2
Индикатор светодиодный семиразрядный с драйвером MAX7219
Смотреть ВИДЕОУРОК в RuTube (нажмите на картинку)
Смотреть ВИДЕОУРОК в YouTube (нажмите на картинку)
Добавить комментарий