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

 
 
 
Reply to this topicStart new topic
> Работа с обоими USART в ATMega64, подскажите пожалуйста с логикой
UniBomb
сообщение May 21 2009, 07:32
Сообщение #1


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

Группа: Свой
Сообщений: 148
Регистрация: 26-05-05
Пользователь №: 5 416



Добрый день. У меня есть девайс на 64-ой меге, в которой задействованы оба усарта. Реализован протокол ModBus RTU (самолично).

По описанию протокола все посылки данных начинаются и оканчиваются интервалом времени, равное времени приёма 3,5 символов. Не мудрствуя лукаво я реализовал это условие в лоб - при приёме первого символа мк уходит в прерывание и не выходит из него до тех пор, пока не примет всю посылку. До недавнего времени использовался только один усарт и всё было хорошо. Но вот буквально вчера возникла необходимость использования и второго усарта. Естетсвенно вышеописанный подход неверен, т.к. из-за большой частоты посыла запроса и соответсвенно получения ответа два прерывания по приёму данных мешают друг другу. Т.е. если в данный момент уже идёт приём данных по первому усарту и в это время начали приходить данные на второй усарт, то часть посылки со второго усарта просто теряется. Такого быть недолжно.... Сократил об прерывания до самого минимума:

Код
uint8_t data_recv0[128];
uint8_t cur_data_recv0;
/*...*/
ISR(SIG_UART0_RECV)
{
  data_recv1[cur_usart1_recv] = UDR0;
  cur_data_recv++;
}


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


Какие ещё есть решения? Кто как обходил эту ситуацию?

Go to the top of the page
 
+Quote Post
MrYuran
сообщение May 21 2009, 07:48
Сообщение #2


Беспросветный оптимист
******

Группа: Свой
Сообщений: 4 640
Регистрация: 26-12-07
Из: Н.Новгород
Пользователь №: 33 646



Цитата(UniBomb @ May 21 2009, 11:32) *
По описанию протокола все посылки данных начинаются и оканчиваются интервалом времени, равное времени приёма 3,5 символов. Не мудрствуя лукаво я реализовал это условие в лоб - при приёме первого символа мк уходит в прерывание и не выходит из него до тех пор, пока не примет всю посылку.

Посмотрите реализацию FreeModbus.(berlios.de)
По прерыванию от УАРТа байт просто кидается в буфер и обнуляется таймер таймаута (предварительно настроенный на 3,5 символа)
А вот по прерыванию таймера уже запускается первичная разборка пакета - CRC, адрес и т.д.
И вот если всё нормально (адрес соответствует, CRC в норме и т.д.), тогда выставляется флаг принятого пакета и функция ModPoll() в основном потоке анализирует пакет, запускает колбэк-функции и формирует ответ.

И вообще: ждать чего-то в прерывании - это не просто дурной тон, а ламерство в чистом виде.
В прерывании нужно делать самые неотложные вещи и выскакивать как можно скорее.


--------------------
Программирование делится на системное и бессистемное. ©Моё :)
— а для кого-то БГ — это Bill Gilbert =)
Go to the top of the page
 
+Quote Post
UniBomb
сообщение May 21 2009, 07:56
Сообщение #3


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

Группа: Свой
Сообщений: 148
Регистрация: 26-05-05
Пользователь №: 5 416



MrYuran, я думал так сделать, но у меня всего один свободный таймер остался. А с одним таймер на два усарта не очень то и получается...
Go to the top of the page
 
+Quote Post
MrYuran
сообщение May 21 2009, 08:12
Сообщение #4


Беспросветный оптимист
******

Группа: Свой
Сообщений: 4 640
Регистрация: 26-12-07
Из: Н.Новгород
Пользователь №: 33 646



Цитата(UniBomb @ May 21 2009, 11:56) *
MrYuran, я думал так сделать, но у меня всего один свободный таймер остался. А с одним таймер на два усарта не очень то и получается...

Наверняка есть "непрерывный" режим работы таймера, правда в АВР-ах таймеры вообще куцые и ублюдочные...
Таймер крутится по кругу, а в защёлках хранятся значения для разных событий. По прерыванию "передвигаете" значение в защёлке на дельтаТ и обрабатываете событие.
Сколько защёлок в таймере, столько разных событий можно на него повесить.


--------------------
Программирование делится на системное и бессистемное. ©Моё :)
— а для кого-то БГ — это Bill Gilbert =)
Go to the top of the page
 
+Quote Post
fantex
сообщение May 21 2009, 08:15
Сообщение #5


Участник
*

Группа: Свой
Сообщений: 54
Регистрация: 4-11-05
Пользователь №: 10 480



Алгоритм работы следующий:

Обработчику прерывания задается указатель на буфер приема и размер буфера.
С каждым принятым байтом указатель инкрементируестя, резмер буфера уменьшается.

В основном цикле программы проверяется изменение размера буфера. При каждом изменении запоминается время в миллисекундах. При отсутсвии изменений в течении заданного времени (3.5 символа) фиксируется окончание пакета, и дальше идет его обработка.
Go to the top of the page
 
+Quote Post
UniBomb
сообщение May 21 2009, 08:17
Сообщение #6


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

Группа: Свой
Сообщений: 148
Регистрация: 26-05-05
Пользователь №: 5 416



Да, насчёт таймера я был неправ... Сейчас попробую)))


зы: кстате, бонус вопрос. Если скорость обмена 38400Кбод/сек, то время приёма 3,5 символов будет (1/38400)*3,5 ?
Go to the top of the page
 
+Quote Post
fantex
сообщение May 21 2009, 08:29
Сообщение #7


Участник
*

Группа: Свой
Сообщений: 54
Регистрация: 4-11-05
Пользователь №: 10 480



В описании протокола Modbus написано, что при скоростях >= 19200 можно задать фиксированое время равное 1.75мс, то есть 1/19200*(кол-во бит в символе)*3.5
Go to the top of the page
 
+Quote Post
ReAl
сообщение May 21 2009, 08:37
Сообщение #8


Нечётный пользователь.
******

Группа: Свой
Сообщений: 2 033
Регистрация: 26-05-05
Из: Бровари, Україна
Пользователь №: 5 417



Цитата(UniBomb @ May 21 2009, 10:56) *
MrYuran, я думал так сделать, но у меня всего один свободный таймер остался. А с одним таймер на два усарта не очень то и получается...

Так нужен не таймер, а output compare модули с на таймере с подходящей ценой кванта (чтобы 3,5символа были короче периода переполнения и длинее хотя бы десяти квантов, а это 6000 крат диапазон). Причём для разных UART это могут быть OCR на разных таймерах.
"Все таймеры заняты" у меня бывало, но пару свободных OCR в меге64 обычно оставалось.


--------------------
Ну, я пошёл… Если что – звоните…
Go to the top of the page
 
+Quote Post
_Pasha
сообщение May 21 2009, 08:51
Сообщение #9


;
******

Группа: Участник
Сообщений: 5 646
Регистрация: 1-08-07
Пользователь №: 29 509



Можно использовать пустые посылки (драйвер передатчика RS-485 выключен), в прерывании TXC считаете до 4-х.

Кстати, 3,5 символа это 3,5*(число бит в кадре)/(скорость)

Тут еще подумал - можно подпрячь на TxD прерывание по изменению уровня, или (не  в 64-й) PCNx. Тогда, выдавая при 11 битах значение 0xC0, получим более точный тайминг, почти нужные 0,5 символа. Надо запомнить.
Go to the top of the page
 
+Quote Post

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

 


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


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