|
Гарантия того, что по USART все данные ушли |
|
|
|
Jan 14 2010, 10:27
|
Участник

Группа: Участник
Сообщений: 19
Регистрация: 14-12-07
Из: Беларусь, Гомель
Пользователь №: 33 305

|
Здравствуйте, не могли бы вы разъяснить такую ситуацию? Перед входом в спящий режим мне нужно убедиться, что все данные ушли в линию. Для этого есть флаг ТХС. В даташите сказано: Флаг устанавливается в 1 после передачи всех битов посылки из сдвигового регистра передатчика при условии, что в регистр данных UDR не было загружено новое значение. Флаг сбрасывается аппаратно при выполнении подпрограммы обработки прерывания или программно, записью в него лог. 1
Прерываний я не активировал, т.е. получается что после первой передачи, когда данные ушли, и в буфер я данных для отсылки не заносил, этот флаг установится в 1 и больше никогда не сбросится? Если да, то получается, что после каждой передачи мне нужно программно сбрасывать этот бит?
|
|
|
|
|
 |
Ответов
(45 - 51)
|
Jan 30 2010, 03:05
|
;
     
Группа: Участник
Сообщений: 5 646
Регистрация: 1-08-07
Пользователь №: 29 509

|
Цитата(demiurg_spb @ Jan 29 2010, 21:26)  Она зараза большая становится, когда много данных нужно ремапить, да и нудно её редактировать (хоть всё уже и так через макросы зафигачено). 1. Написать приблуду и работать с Ёкселем в формате *.csv 2. Проблема, кстати, сходная с созданием таблицы редактирования/доступа к параметрам: зоопарк валидаторов, read-only/write-only/rw, источник или приемник данных (функция/ОЗУ/eeprom/flash), clear after use... Код typedef struct { // неявное задание правил доступа RO WO RW - метод == NULL size_t (*read)(void *src, size_t size);//если результат != заданному size, то ашипко size_t (*write)(void *dst, void *src, size_t size); } data_src_stream_t;
typedef struct { uint16_t log_addr; void *phy_addr; void *validator; // там же хранится инфа о размере void *stream; } remap_tbl_t; //........................................ struct Valid32_cnt //пример { uint8_t size;// всегда первым байтом пойдет как тэг uint32_t low; uint32_t high; } pause_tmr={4,120000,240000}; Про coil_read() или coil_write() Иногда проще все уложить в switch(), но лучше imho избавляться от двухбайтового оверхеда. Если нехватка флеша на таблицу - приходится все паковать в битовые поля. Код typedef struct { uint16_t log_addr; void *phy_addr;
uint8_t mate;// многоцелевой индекс - все, что не отображается в полях, потом делается через switch(remap.mate)
unsigned size:2;// elem size unsigned pool:4;// register pool unsigned perm_rd:1; unsigned perm_wr:1; } remap_t; Вот видите - у меня тот же бардак
|
|
|
|
|
Jan 30 2010, 10:46
|

неотягощённый злом
     
Группа: Свой
Сообщений: 2 746
Регистрация: 31-01-08
Из: Санкт-Петербург
Пользователь №: 34 643

|
Цитата(_Pasha @ Jan 30 2010, 06:05)  1. Написать приблуду и работать с Ёкселем в формате *.csv Тоже об этом думал, но пока что-то останавливает. Цитата 2. Проблема, кстати, сходная с созданием таблицы редактирования/доступа к параметрам: зоопарк валидаторов, read-only/write-only/rw, источник или приемник данных (функция/ОЗУ/eeprom/flash), clear after use... Схожая да не совсем. К параметрам меню не обращаются как к "raw big-endian 16-bit data", и не пытаются читать потоком данные например float или DWORD или BYTE или BIT. И "самое страшное" что могут обратится лишь к младшему или старшему полуслову float или DWORD, а про массивы я вообще молчу:-) И про то, что есть 5 отдельных адресных пространств SRAM, FLASH, EEPROM, DATAFLASH, RTC. Мама помоги!!!! Пока я это всё делал чуть не тронулся умом;-) А всё из-за этого &%@# modbus (нехорошего в общем и целом). С меню у меня всё достаточно красиво получилось (писал на Си в "стиле С++", некое наследование путём включения базового типа menu_item_t во всех потомков, ну и таки да, реализация методов доступа через switch (item_type) - так компактнее получилось, структуры практически без callback'ов). Написал макросы для ассигнования этих типов и всё получилось читабельно и вменяемо (хоть работы проделано немало). Цитата Вот видите - у меня тот же бардак  Ага, нормально:-)
--------------------
“Будьте внимательны к своим мыслям - они начало поступков” (Лао-Цзы)
|
|
|
|
|
Jan 31 2010, 14:54
|
Местный
  
Группа: Участник
Сообщений: 246
Регистрация: 4-12-06
Пользователь №: 23 101

|
Цитата(Александр Куличок @ Jan 21 2010, 01:47)  А что мешает отслежить состояние флага перед записью в UDR? Если паузы между байтами недопустимы, прерывание UDRE используется для загрузки следующего байта, пока текущий передаётся. Если паузы допустимы - UDRE пофиг и не используется. Смысл читать его ПЕРЕД записью?
|
|
|
|
|
Jan 31 2010, 21:31
|
Местный
  
Группа: Свой
Сообщений: 256
Регистрация: 6-03-06
Из: Украина, г. Винница
Пользователь №: 15 017

|
Речь шла о флаге TXC. И о возможности отслеживания разрывов: Цитата Если же флаг сбрасывать при загрузке UDR, то вы не сможете отследить те самые разрывы между байтами, которые могут быть критичны. Если паузы недопустимы, то считывание его перед записью в UDR как раз позволяет проанализировать, была ли пауза при передаче. И принимать дальнейшее решение о том, что писать (или не писать) в UDR. Одно только использование UDRE еще не дает гарантию, что пауз не будет. Особенно при большИх скоростях.
|
|
|
|
|
Jan 31 2010, 22:26
|
Участник

Группа: Участник
Сообщений: 25
Регистрация: 8-08-05
Пользователь №: 7 466

|
Пользуюсь простым алгоритмом при реализации Modbus RTU (потолок скорости 115200). Назначения: 1. Буфер приёмника/передатчика (первый байт - счётчик). 2. 1 РОН для счётчика "долгих" циклов. 3. 2 РОНа для хранения CRC16. 4. Функция подсчёта CRC "на лету". 5. Функция записи в буфер записывает последними в буфер 2 байта CRC16. 6. Функция передачи данных подсчитывает CRC16 "на лету". Собственно проверка: 1. "Длинный" счётчик =0? Да. 2. РОНы контрольной суммы =0? Да. Резюме: данные "уехали" без проблем. CODE ;====================================================================== ============= ; ЗАДАЧА 7 - Передача фрейма данных в хост-компьютер по USART0 по протоколу ModBusRTU ;=============================================================================== ==== PLC_7: sbrs rFlagPLC, flPLC_7 rjmp Exit_PLC_7
cbr rFlagPLC, (1<<flPLC_0) ; Запретить приём по USART0 на время передачи sbrc rFlagUSART, flReady0 ; Начальная инициализация была? rjmp lbLoadTxD0 ; Да ;------------------------------------------------------------------- ; Инициализация функции передачи данных ldi rFuncL, N115200 ;1. Делитель частоты UBRR0H:UBRR0L = 0x0007 out UBRR0L, rFuncL ;2. Асинхронный режим UMSEL = 0 out UBRR0H, rZero ;3. Контроль чётности UPM1 = 1, UPM0 = 0 ldi rFuncL, 0xA6 ;4. Один стоп-бит USBS = 0 out UCSR0C, rFuncL ;5. Формат кадра 8бит UCSZ1 = 1, UCSZ0 = 1 lds rCounter0, pCountUSART0 ; Количество передаваемых байт данных ldi XL, low(pAdressUSART0) ; Буфер передатчика начинается с адре- ldi XH, high(pAdressUSART0) ; са УСО
sbi UCSR0B, TXEN0 ; Включить передатчик USART0! sbr rFlagUSART, (1<<flReady0) ; PLC инициализирована ;--------------------------------------------------------------------------- ; Загрузка байта данных для передачи lbLoadTxD0: cpse rCounter0, rZero ; Все байты фрейма загружены? rjmp lbFrame0 ; Нет rjmp lbEndTxD0 ; Да lbFrame0: sbis UCSR0A, UDRE0 ; Надо загрузить байт для передачи? rjmp Exit_PLC_7 ; Нет.
ld rdUSART0, X+ ; Загрузить передаваемый байт out UDR0, rdUSART0 ; Собственно загрузить байт данных для передачи dec rCounter0 ; Уменьшаем счётчик передаваемых байт фрейма cbi UCSR0A, UDRE0 ; Сбросить флаг требования загрузки sbr rFlagUSART, (1<<flCRC160) ; Установить флаг требования подсчёта CRC16 ;--------------------------------------------------------------------------- ; Окончание функции передачи данных lbEndTxD0: sbis UCSR0A, TXC0 ; Ожидание передачи последнего байта rjmp Exit_PLC_7 ;------------------------------------------------------------------- ; Сброс передатчика USART0 clr rFuncL out UCSR0B, rFuncL ;------------------------------------------------------------------- ; Проверка регистров CRC16 на ошибку cpse rCRC160L, rZero rjmp lbTxDError0 cpse rCRC160H, rZero rjmp lbTxDError0 rjmp lbExitTxD0 ;------------------------------------------------------------------- lbTxDError0: ; Обработка ошибки подсчёта CRC16 "на лету" sbr rErrInter, (1<<flCRC16T0xD) lbExitTxD0: sbi UCSR0A, TXC0 cbr rFlagUSART, (1<<flEmpty0)+(1<<flReady0)+(1<<flCRC160)+(1<<flFrame0) cbr rFlagPLC, (1<<flPLC_7); Выключить функцию передачи данных по USART0 sbr rFlagPLC, (1<<flPLC_0); Включить функцию приёма данных по USART0 Exit_PLC_7: nop
|
|
|
|
|
  |
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|