Перейти к содержанию
    

Работа кольцевого буфера

Здравствуйте!

У меня есть несколько вопросов по работе кольцевого буфера и UART STM32F103.

1) Есть классический кольцевой буфер на 512 байт. По команде "Старт" он начинает заполняться в такой последовательности: в него записывается 38 байт, через 1,25 мс записывается 57 байт, через 1,25 мс снова 38, через 1,25 мс снова 57 байт и так далее в этой же последовательности.

Чтение из кольцевого буфера осуществляется каждую 1 мс. То каждую 1 мс приходит команда, определяется кол-во данных в буфере и передаются дальше.

Вопрос в том, как так получается, что в один прекрасный момент в буфере накапливается 38+57=95 байт? Я же читаю из буфера с большей частотой, чем пишу...

2) Когда задаю UART большое значение скорости (больше, чем 1,2 Мбит/с) иногда сбивается передача данных - не приходит прерывание Transmit Complete. Однако в даташите написано, что максимальная скорость 2,25 Мбит/с

3) Для передачи данных я использую прерывание Transmit Complete, но видел, некоторые используют флаг Tx Empty. Есть ли какая то принципиальная разница?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Вопрос в том, как так получается, что в один прекрасный момент в буфере накапливается 38+57=95 байт? Я же читаю из буфера с большей частотой, чем пишу...

Ну чудес-то не бывает. Либо пропуск чтения, либо запись происходит чаще.

2) Когда задаю UART большое значение скорости (больше, чем 1,2 Мбит/с) иногда сбивается передача данных - не приходит прерывание Transmit Complete. Однако в даташите написано, что максимальная скорость 2,25 Мбит/с

Значит, пропускаете прерывание. Наверное зависаете надолго в обрабротчике прерывания, или есть другие прерывания (не от UART).

3) Для передачи данных я использую прерывание Transmit Complete, но видел, некоторые используют флаг Tx Empty. Есть ли какая то принципиальная разница?

Да. TXE взводится, когда опустошается буфер передатчика. Сдвиговый регистр в это время ещё занят, и передача ещё идёт. А вот когда заканчивается передача из сдвигового регистра, то взводится флаг TC. Для передачи лучше использовать TXE.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Ну чудес-то не бывает. Либо пропуск чтения, либо запись происходит чаще.

Пропуск правда есть...я смотрел осциллографом. Перед тем как отправить 95 байт, запрос данных игнорируется.

Значит, пропускаете прерывание. Наверное зависаете надолго в обрабротчике прерывания, или есть другие прерывания (не от UART).

Зависаю не на долго, инкрементирую счетчик, отправляю байт и все. Другие прерывания есть, но такого же или меньшего приоритета. Например прерывание DMA такого же приоритета и зависаю я там 22 мкс, но какая разница сколько. По идее, прерывание Transmit Complete должно сколь угодно долго дожидаться...

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Вопрос в том, как так получается, что в один прекрасный момент в буфере накапливается 38+57=95 байт? Я же читаю из буфера с большей частотой, чем пишу...

Вы же не мгновенно записываете в буфер, так же и читаете из него (там еще медленнее, определяется скоростью передачи). Добавьте к 1 мс эти времена.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Вы же не мгновенно записываете в буфер, так же и читаете из него (там еще медленнее, определяется скоростью передачи). Добавьте к 1 мс эти времена.

Не совсем понял... Ну да, не мгновенно, 38 байт переписываются в буфер примерно 44 мкс, соответственно 57 байт - 66 мкс. Читать из буфера я должен с такой скоростью, чтобы успевать передавать данные до следующего запроса - то есть должен успевать все передать за 1 мс. Скорость нормальная, если бы не приходилось вдруг передавать 95 байт - на это уже скорости не хватает.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Читать из буфера я должен с такой скоростью, чтобы успевать передавать данные до следующего запроса - то есть должен успевать все передать за 1 мс. Скорость нормальная, если бы не приходилось вдруг передавать 95 байт - на это уже скорости не хватает.

Так сколько времени нужно на передачу 57 байтов?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Так сколько времени нужно на передачу 57 байтов?

На скорости 1,2 Мбит/с, на передачу одного бита уходит 0,84 мкс

Соответственно 57 байт х 11 бит = 627 бит

627*0,84=527 мкс

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

А времена эти, 1 мс, 1,25 мс вы жестко задаете, таймерами? Если в это время процессор занят записью или передачей, ждете, когда освободится, или ждете следующего срабатывания таймера?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

А времена эти, 1 мс, 1,25 мс вы жестко задаете, таймерами? Если в это время процессор занят записью или передачей, ждете, когда освободится, или ждете следующего срабатывания таймера?

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Для начала измените работу с УСАРТом на от TXE. Потому что ваши расчеты времени верны для непрерывного потока битов. А с ТС есть пустое время между байтами.

 

А 1 мс интервалы кто задает? По УСАРТУ принимаете команду?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Для начала измените работу с УСАРТом на от TXE. Потому что ваши расчеты времени верны для непрерывного потока битов. А с ТС есть пустое время между байтами.

Меня немного смущает кое что. Если я разрешу это прерывание в main

USART_ITConfig(USARTz, USART_IT_TXE, ENABLE);

Меня же тут же выкинет в обработчик этого прерывания, буфер то после сброса пуст, или оно только после отправки сработает?

 

А 1 мс интервалы кто задает? По УСАРТУ принимаете команду?

Да, по USART каждую 1 мс приходит команда - запрос данных. В теле данного прерывания я считаю кол-во данных и отправляю первый байт.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Я после настроек USART делаю

NVIC_ClearPendingIRQ(USART3_IRQn);

потом

NVIC_EnableIRQ(USART3_IRQn);

Не знаю, надо ли. Может, прерывание возникает при освобождении буфера, а не когда он пустой.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Я после настроек USART делаю

NVIC_ClearPendingIRQ(USART3_IRQn);

потом

NVIC_EnableIRQ(USART3_IRQn);

Не знаю, надо ли. Может, прерывание возникает при освобождении буфера, а не когда он пустой.

а потом, когда весь массив данных передали, запрещаете это прерывание?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Да, когда нужно послать массив, посылаю байт, разрешаю прерывание TXE. Остальные байты посылаются по прерыванию. При передаче последнего байта запрещаю прерывание TXE.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Да, когда нужно послать массив, посылаю байт, разрешаю прерывание TXE. Остальные байты посылаются по прерыванию. При передаче последнего байта запрещаю прерывание TXE.

+1

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
К сожалению, ваш контент содержит запрещённые слова. Пожалуйста, отредактируйте контент, чтобы удалить выделенные ниже слова.
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...