_Pasha 0 30 января, 2010 Опубликовано 30 января, 2010 · Жалоба Она зараза большая становится, когда много данных нужно ремапить, да и нудно её редактировать (хоть всё уже и так через макросы зафигачено). 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; Вот видите - у меня тот же бардак :) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
demiurg_spb 0 30 января, 2010 Опубликовано 30 января, 2010 · Жалоба 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'ов). Написал макросы для ассигнования этих типов и всё получилось читабельно и вменяемо (хоть работы проделано немало). Вот видите - у меня тот же бардак :)Ага, нормально:-) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
_Pasha 0 31 января, 2010 Опубликовано 31 января, 2010 · Жалоба И про то, что есть 5 отдельных адресных пространств ... Мама помоги!!!! Поток ввода/вывода - это мама? или папа? :) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
demiurg_spb 0 31 января, 2010 Опубликовано 31 января, 2010 · Жалоба Поток ввода/вывода - это мама? или папа? :)Они родимые:-) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
maik-vs 0 31 января, 2010 Опубликовано 31 января, 2010 · Жалоба А что мешает отслежить состояние флага перед записью в UDR? Если паузы между байтами недопустимы, прерывание UDRE используется для загрузки следующего байта, пока текущий передаётся. Если паузы допустимы - UDRE пофиг и не используется. Смысл читать его ПЕРЕД записью? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
kool 0 31 января, 2010 Опубликовано 31 января, 2010 · Жалоба Речь шла о флаге TXC. И о возможности отслеживания разрывов: Если же флаг сбрасывать при загрузке UDR, то вы не сможете отследить те самые разрывы между байтами, которые могут быть критичны. Если паузы недопустимы, то считывание его перед записью в UDR как раз позволяет проанализировать, была ли пауза при передаче. И принимать дальнейшее решение о том, что писать (или не писать) в UDR. Одно только использование UDRE еще не дает гарантию, что пауз не будет. Особенно при большИх скоростях. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
sitafern 0 31 января, 2010 Опубликовано 31 января, 2010 · Жалоба Пользуюсь простым алгоритмом при реализации Modbus RTU (потолок скорости 115200). Назначения: 1. Буфер приёмника/передатчика (первый байт - счётчик). 2. 1 РОН для счётчика "долгих" циклов. 3. 2 РОНа для хранения CRC16. 4. Функция подсчёта CRC "на лету". 5. Функция записи в буфер записывает последними в буфер 2 байта CRC16. 6. Функция передачи данных подсчитывает CRC16 "на лету". Собственно проверка: 1. "Длинный" счётчик =0? Да. 2. РОНы контрольной суммы =0? Да. Резюме: данные "уехали" без проблем. ;====================================================================== ============= ; ЗАДАЧА 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 Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться