реклама на сайте
подробности

 
 
> STM32 UART<>DMA, шаг за шагом
Tanker
сообщение May 2 2012, 19:17
Сообщение #1


Участник
*

Группа: Участник
Сообщений: 34
Регистрация: 30-06-07
Пользователь №: 28 806



Здравствуйте!
IAR ARM 6.30.7 STM32F100
Делаю слейв Modbus RTU c RS485 интерфейсом. Всё было бы "ОК", но по 2-м UARTAM одновременно нужно работать, а при этом моя

реализация на прерываниях, начинает то на один то другой UART данные не до давать при интенсивном обмене с мастерами (ещё все АЦП задействованы на макс. скорости с прерываниями DMA по заверш. передачи оцифровки, но их отключение не помогает).
Решил сделать на связке UART-DMA.
Просмотрел на эту тему все топики здесь, погуглил, мануалы почитал... сделал - но очень зыбко работает моя реализация протокола, какой-то мелочи я не просекаю.

Для начала я хочу реализовать приём по-байтный, а отправку через DMA.
Начинается всё с приёма запроса от мастера, uart и драйвер настроен на приём:
1) принял байтик -> положил в буфер -> перезагрузил таймер (отсчёт frame end длительность 1,5-3 байт завершения пакета) и так каждый байтик, до срабатывания таймера (срабатывает когда пауза в 1,5-3 байта (как настрою))
2) таймер отсчитал framе end, сработало его прерывание -> останавливаю таймер-> блокирую приёмник UARTа (чтобы не реагировал на входящие)
3) разбор входящего сообщения (можно вынести из прерывания во внешний цикл и сигнализировать от пришедшем пакете через какие-нибудь битики) включает в себя проверку адреса слейва и контрольной суммы (потом делается более детальный разбор, но для начала самое-то)
4) реакция на входящее сообщение:
4.1) чужое или "по-дороге битое" -> перевод uart в режим ожидания входящих байт (исходное состояние)
4.2) достойное ответа -> формирование ответа в буфере
5) когда буфер заполнен ответом, запускаю таймер на отсчёт времени переключения драйвера из режима "приём" в режим "передача" (например для ADM2587E 2,5мкСек)
6) сработало прерывание таймера (драйвер переключился в "передача")->останавливаю таймер->настраиваю DMA на передачу подготовленного буфера и запускаю передачу DMA1_Channel7->CCR |= DMA_CCR7_EN; (всё, данные должны автоматом вылетать с ножки TX, до опустошения буфера)
7) по опустошению буфера срабатывает прерывание DMA_ISR_TCIFx (если разрешено)(или таймера USART_CR1_TCIE .. в этом есть вопрос ??) данные (как-бы) переданы и можно переключаться на приём
8) запускаю таймер на отсчёт времени переключения драйвера из режима "передача" в режим "приём"
9) сработало прерывание таймера (драйвер переключился в "приём")-> перевод uart в режим ожидания входящих байт (исходное состояние)

Трабл:
Сейчас получается, до п.7 всё норм.,запускаю DMA... бывает что весь буфер приходит (длина ответа в среднем 64 байта), а зачастую 1 байт (левый!!!) и срабатывает DMA или UART "Transmission Complete" (я с ними экспериментировал)

Ещё из наблюдений:
1) Если я разрешаю DMA_ISR_TCIFx (но при этом USART_CR1_TCIE запрещён) и запускаю DMA, то мне приходится к DMA1_Channelх->CNDTR дополнительно "+2" делать, но имею при этом лишний байт "0" он либо затирает последний значащий байт пакета данных (если CNDTR = кол-ву передаваемых байт), либо просто лишний (если CNDTR = кол-ву передаваемых байт + 2)


2) Если я разрешаю USART_CR1_TCIE (но DMA_ISR_TCIFx при этом запрещён или разрешён но просто чистит флаги) и запускаю DMA, то с DMA1_Channelх->CNDTR всё "ок" равно кол-ву передаваемых байт.

В общем надеюсь с вашей помощь найти решение своего трабла и увековечить тему "STM32 DMA UART" в FAQ опубликовав полученный рабочий код с каментами
Go to the top of the page
 
+Quote Post
 
Start new topic
Ответов
ohmjke
сообщение Jan 28 2014, 22:59
Сообщение #2


Частый гость
**

Группа: Участник
Сообщений: 116
Регистрация: 27-01-10
Из: СПб
Пользователь №: 55 094



ни у кого нет идей?
Go to the top of the page
 
+Quote Post
_Артём_
сообщение Jan 29 2014, 05:51
Сообщение #3


Гуру
******

Группа: Свой
Сообщений: 2 128
Регистрация: 21-05-06
Пользователь №: 17 322



Цитата(ohmjke @ Jan 29 2014, 00:59) *
DMA-контроллер сразу после включения соответствующего канала начинает считывать уже хранящийся байт в приёмном регистре юарта. А этот байт относится к другой, предыдущей, независимой от этой операции.
Мне нужно, чтобы передача начиналась только тогда, когда придёт новый байт данных - как сделать?
ни у кого нет идей?
Можно очистить приёмный буфер UART-а: например, прочитав байт из приёмного буфера перед стартом ДМА. Или сбросом флага приёма (что хуже). Или может быть запретом приёмника (правда, не знаю сделает ли UART STM32 сброс буфера при запрете приёмника).
Go to the top of the page
 
+Quote Post



Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 20th August 2025 - 11:13
Рейтинг@Mail.ru


Страница сгенерированна за 0.01379 секунд с 7
ELECTRONIX ©2004-2016