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

pokk

Участник
  • Постов

    214
  • Зарегистрирован

  • Посещение

Весь контент pokk


  1. Пользователь выключил устройство, потом убрал сигнал, и заново его подал, сработал детектор сигнала и включил устройство, а оно должно быть выключено. Такая же ситуация может произойти если устройство выключилось по расписанию.
  2. Добрый день, подскажите как правильно разрулить работу устройства по нескольким событиям (из разных модулей) В общем задача такая есть устройство которое может включаться/выключаться по разным событиям 1) пользователь нажал кнопку в web (вкл/выкл) 2) Работа по расписанию (часы реального времени) 3) Защита (превышение параметра выкл, параметр в норме вкл) 4) Детектор сигнала (пропал сигнал выкл, появился сигнал вкл) Как разрулить что бы не было не предвиденного включения т.е пользователь или расписание выключило устройство, а после того как отработала защита либо сработал детектор как заблокировать включение устройства? Так же надо заблокировать сигнал включение из расписания если устройство выключил пользователь. Текущая реализация такая, в каждом модулей сделал свой Callback на событие, а установка всех Callback функций в одном файле в котором производиться логика работы по событиям + запись в журнал. Для разруливания событий думаю добавить в сообщение модуля включения приоритет, MsgDevice(MSG_OFF,1...4), и перед выполнением операции сохранять его, и при следующем включении анализировать сохраненное значение с новым. Как ещё можно это разрулить ?
  3. Ожидание stop I2c в stm32f407

    Правлю драйвер I2c он работает полностью на прерываниях. Создал задачу которая закидывает данные в LCD через PCF (адрес + 2 байта данных) Работало это по событиям START->ADDR->BTF(устанавливаю STOP)->BTF -> освобождаю задачу и запускал отправку следующих данных. Появились грабли, после старта устанавливался сразу стоп, пришел к выводу что это из за того что бит START для новой посылки устанавливался слишком рано, после последнего BTF но перед установкой STOP. Поставил ожидание сброса бита STOP в CR1 или флаг I2C_SR2_BUSYBUSY (что правильнее ?) больше таких граблей не встречал. Есть какие либо варианты кроме как в цикле его ждать?
  4. Пробовал тоже самое. Судя по тому после сбоя считываются единицы из сектора заполненного нулями сдается, что это будет происходит при считывании из любого другого сектора. В ПО присутствует бутлоадер, но по ВКЛ питанию он только CRC прошивки проверяет и переходит на неё.
  5. Просто жду завершение передачи. Это для установки строба //--------------------------------------------------- if(Receive!=0){ //vTaskDelay( 2 / portTICK_RATE_MS ); delay_ms(2); delay_us(550); Debug1_1 delay_us(150); Debug1_0 } Кстати при vTaskDelay( 2 / portTICK_RATE_MS ); гребенка битов сдвигается на другое место. Да так же и гребенку битов там вижу. Это от анализатора файл данных Kingst VIS Вот начало посылки Вот конец поссылки + гребенка единиц Эта целиком пакет считанный из сектора в который ранее записал все нули. Не как не могу понять как ПО только на чтение может ломать данные которые считываются из памяти. Раз 8-10 считываются данные правильно без этих единиц (тоже смотрю через анализатор) на том же ПО
  6. Комп новый не успел нечего такого наставить, убрал все что трее висит не поменялось. Открыл си файл через sublime text 3 там такого нету.
  7. Да не на всех макросах такое происходит, пока тестировал нашел такое что при выделение буквы в макросе или комментария перед выделенной возникает отступ, на пока не сбросишь выделение. PS: windows 10
  8. Схема стандартная CS(програмный) MISO MOSI CLK к процессору, разводка вдалеке от всяких реле и тд (реле уже отключил что бы не мешало). CS подтянут через 4.7кОм на +3.3в MISO MOSI CLK через 1.3 кОм на землю. Скорость 2МГц вместо 60-100, так что с фронтами все с запасом по даташиту наносекунду у меня микросекунды Да сектор стирал, иначе бы при каждом запуске CRC не сходилось бы. Протокол корректный, несколько дней работало потом начала конфигурация слетать, назначил разбираться..,все убрал из прошивки осталось 1 задача (FreeRtos ) для работы с памятью и то уже на основных функциях. В принципе даже одной функцией пользуюсь. //================================================================================================== /* * @Описание: Описание функции. * @Параметр: * @Возврат: Нету */ void A25L0xx_ReadBytes(uint32_t ReadAddr,uint8_t* pBuffer, uint32_t NumByteToRead){ if(NumByteToRead==0){return;} xSemaphoreTakeRecursive(MutexA25L0xx,portMAX_DELAY); TakeMutexSpi(); FLASH_CS_OFF(); //------------------------------------------------------------------------------- TempTransmitBuff[0]=0x03; TempTransmitBuff[1]=((ReadAddr & 0xFF0000) >> 16); TempTransmitBuff[2]=((ReadAddr & 0xFF00) >> 8); TempTransmitBuff[3]=(ReadAddr & 0xFF); //------------------------------------------------------------------------------- Send_Spi_dma(0,TempTransmitBuff,4,TYPE_TRANSMIT,USE_MINC); //------------------------------------------------------------------------------- Send_Spi_dma(pBuffer,&DUMMY,NumByteToRead,TYPE_RECEIVE,TRANSMIT_NOT_MINC); // Без инкримента данных на передачу //------------------------------------------------------------------------------- FLASH_CS_ON(); GiveMutexSpi(); xSemaphoreGiveRecursive(MutexA25L0xx); } Перед чтением ставил задержу в 2с на установку памяти не помогло. Вижу что из памяти считываются мои данные(id совпадает и в конце CRС правильно), но в некоторых местах там где должны быть нули появилась гребенка единиц, думаю и других местах тоже есть, просто пока их ещё не заметил. Под отладчиком все корректно работает. На втором канале строб на тех местах где появляются левые биты. Вот целиком вся задача (SysLogWrite отключены, ReadConfingFromMem это A25L0xx_ReadBytes + CRC ) ErrorMem.kvdat
  9. Записал в память(A25L032) структуру конфигурации, в 0 сектор одноразово. После написал другу программу которая только считываю конфигурацию и проверяет CRC, через 5-8 переключений питания срабатывает ошибка CRC, поймал этот момент на анализаторе вижу что поверх моих данных появились 16 единиц через 1 байт (0x0100010001000100...) и из за этого не сходиться CRC, откуда они взялись ? После переключения питания ещё раз, гребенка единиц пропадает до 5-8 переключений питания. Добавил в ПО дополнительную проверку, после того как CRC не совпала считываю ещё несколько раз структуру конфигурации (при каждом чтении на том же месте находиться гребенка единиц). После добавил считывание нулей из другого сектора (записанного заранее) между считывания конфигурации, увидел гребенку единиц при каждом чтении причем там где должен были быть нули увидел 4 гребенки через равный промежуток времени (длина структуры конфигурации около 1КБ ) Посмотрел осциллографом на левые биты, хорошие фронты явно их выдает память а не наводка. Почему память раз через раз выдает левые денные ?
  10. Очень раздражает непонятная опция в IAR когда ставишь курсор макрос а IAR в этом месте разрывает макрос (как табуляцией только её нету). Причем это срабатывает не везде и не всегда. Кто нибудь встречался с таким?
  11. Надо получать живые данные с другого процессора(по USART) и отобразить их на экране и на web странице. Так вот не могу определить, как лучше сделать 1) Сделать отдельную задачу которая будет периодически получать параметры и складывать их переменную а все остальные задачи буду считывать значение этой переменной, и отображать. 2) Считывание параметра поставить прямо в той задаче где он нужен + таймаут на выход если был сбой в протоколе связи. Время получения параметры около 20ms.
  12. Для передачи данных между процессорами использовал протокол с фиксированной длиной запросного пакета и ответного пакета. Для абстрагирования и переносимости протокола решил написать драйвер USART что бы прием передача происходила только через эти функции. Алгоритм драйвера закладывал такой прием / передача данных происходит через кэш буфер. Для передачи, данных в линию USART ложем данные в кэш (функцией DriverWriteUsart) и запускаем выдачу. Для приема данных в прерывании складываем их в кэш а в протоколе считываем данные из кэша функцией GetDataFromUsartCache(DRIVER_USART_ENCODER) В протоколе это выглядит так SendRequest формирует данные в пакет и ложит в кэш USART после чего данные от туда выдаются в линию с помощью DMA После отправки запроса устанавливаем драйвер на прием ответного пакета функцией DriverReadUsart() с указанием сколько байт будет занимать ответный пакет (с ожиданием приема данных через DMA) а дальше считываем GetDataFromUsartCache все что приняли с проверкой CRC. Теперь решил переделать протокол и ответный пакет расширился (ID,CMD,TYPE,LEN,<DATA>,CRC) где LEN длина данных и теперь я не могу использовать DriverReadUsart с ожиданием конкретного количества байт, так как количество байт неизвестно. Пока думаю в направление сделать выбор в драйвере USART использовать на прием DMA или прерывание, и в прерывание ложить данные в кэш. Но сейчас обработчик прерывание USART находиться в само нижнем уровне (протокол -> драйвер USART -> аппаратная настройка USART) и там обработчик нечего не знает об кэше USART
  13. Да вот это и меня мучило, не хотел вводить ещё одни модуль, но по ходу без него не как Заведу модуль InitTask В си файле будет void WaitInitTask(uint16_t event) // WaitInitTask(WAIT_EVENT_INIT_MEM | WAIT_EVENT_INIT_LCD) xEventGroupWaitBits(xEventAnyName,event, 0, pdTRUE, portMAX_DELAY); } В H файле #define WAIT_EVENT_INIT_MEM (1<<0) #define WAIT_EVENT_INIT_LCD (1<<1) Он будет иклудиться практически во все задачи. Надеюсь 8-16 бит хватит.
  14. Как правильно заблокировать задачу. Есть vTaskMenu, она с определенным интервалом запускает функции из модуля LCD на перерисовку экрана с учетом как было сконфигурировано устройство (данные во внешнем ПЗУ модуль mem) поэтому в момент включения устройства ставлю ожидание, на инициализации LCD и mem (MemWaitInitLcd() и WaitInitMem() находяться в соответственных модулях (LCD и Mem).) void vTaskMenu (void *pvParameters){ WaitInitLcd(); WaitInitMem(); xEventGroupSetBits(xEventMenuStart,WAIT_EVENT_INIT_MENU); while(1){ MsgDisplayUpdate((uint8_t*)LcdMsgShow.msg,TEXT_NORMAL); vTaskDelay( LcdMsgShow.time/ portTICK_RATE_MS ); } void WaitInitLcd(void){ xEventGroupSync(xCreatedEventLcdInit,0,WAIT_EVENT_INIT_LCD,portMAX_DELAY); } void WaitInitMem(void){ xEventGroupSync(xCreatedEventGroup,0,WAIT_EVENT_INIT_MEMORY,portMAX_DELAY); } Так вот проблема возникла, когда я случайно поменял местами WaitInitMem(); WaitInitLcd(); получилось из за того что WaitInitMem(); инициализируеться гораздо дольше за это время задача инициализации LCD уже отрабатывает и выставляет xEventGroupSetBits(xCreatedEventLcdInit,WAIT_EVENT_INIT_LCD); и после отработки WaitInitMem программа зависает на WaitInitLcd(); Знаю, что можно xEventGroupSync поставить ждать несколько флагов Но как это сделать в рамках трех модулей menu LCD и mem ? Где создать общую переменную xCreatedEvent.... (для всех задач ?)
  15. В даташите написано, что максимальный уровень выходного сигнала с ЦАП равен 5.6 В (p-p). Хотя питание 5В, но да ладно. Настроил ЦАП на частоту дискретизации 190 кГц, 24 бита и выдаю с него пилу (0-0xFFFFFF) На осциллографе вижу пилу с 2.7 в (p-p), как выжать с него заданный диапазон до 5 в (p-p) ? Пробовал крутить уровень канала, через SPI уровень сигнала уменьшается, но не увеличивается.
  16. Это актуально когда, надо большой размер данных проигнорировать, пока таких задач нету, а если и будет то настрою DMA на прием из буфера wiznet без инкремента памяти процессора.
  17. Ну вот поменяли, W5300 подключается только по параллельной шине, по этому что бы не городить большое количество линий адреса, они сделал доступ к буферу RX/TX через небольшой буфер FIFO. И доступ к указателям убрали.
  18. Нет нет, вы не правильно меня поняли, я имел ввиду когда принимаешь поток данных, в протоколе может быть номер какой это поток данных, и что бы один поток от другого отфильтровать, можно принять сначала шапку, посмотреть на этот номер и дальше принять решения считывать данные или нет, в w5500 такое можно сделать, а вот в w5300 увы что бы заигнорить пакет его надо считать целиком.
  19. Вот это прямо то что надо!!, это одна из основных причин сделать все по уму. Я хотел заложить чуть другую логику, считывание самого пакета переложить на задачу A и B. Для того что бы в задаче A можно было считывать не весь пакет, а только шапку пакета, и если она битая (либо по адресу пакета если есть такой внутри протокола), то игнорировать пакет целиком не копируя его в процессор, но по факту я таким пользовался только раз. И походу именно это не дает сделать универсально и разделить, работу через буфер. На передачу, все так же складываем в буфер и передает сигнал из задачи А в задачу О ?
  20. А если одна задача ждет одно событие (прием пакета), из разных сокетах, что бы при одновременно срабатывании прерывании можно было установить приоритет какой сокет первый обрабатывать.
  21. juvf, хорошая идея, по прерыванию запускать задачу обработки прерываний, а из неё уже передавать события в задачу обработки пакета сокетом. А как сделать так что бы в задача ждала одно событие из нескольких сокетах, типа ожидает событие "прием пакета" либо со второго сокета или с первого. В задаче обработке прерываний думаю сгруппировать событие следующим образом. Создать битовые группы на каждое событие свое, а внутри каждый бит будет указывать какой сокет вызвал это событие. Тогда я смогу, в udp server ждать прием с любых сокетов (2,3 или 6) и с заданным приоритетом вызвать задачу обработчика пакета данных. Только для TCP приодеться, много групп городить.
  22. Что-то не припомню можно ли так сделать в STM32, завтра гляну. Главный вопрос как с этим дальше работать. То ли в очередь сразу байт с набором событий записывать, то ли разобрать все биты из байта и их в очередь записывать. Либо вообще передавать только факт того что произошло прерывание (через xEventGroupSetBits), и уже на месте вычитывать из байт с событиями и принимать решения. В последний варианте конечно, будет происходить активация задачи даже не по своему что не очень нравиться.
  23. Добрый день, пишу модуль UDP сервера для wiznet 5300 подключенный по параллельной шине. Столкнулся с такой проблемой, при роботе с ним по выводу прерывании INT, процессор может потерять событие, принятие пакета сокетом. У w5300 есть 8 сокетов и если сокет принимает пакет UDP то выставляется логический уровень (1) на вывод прерывания (INT) и записывает событие в регистр прерываний сокета, так вот если во время прерывания wiznet примет пакет в другой сокет вывод INT так и будет находиться в единице, без переключения 1/0/1 и тем самым процессор может пропустить этот сигнал если он работает по прерыванию вывода INT, хотя в регистре прерывания другого сокета будет стоять бит приема. Но все же для максимальной реакции (в будущем планирую принимать UDP поток данных) приема UDP пакета, хочу заложить работу по прерыванию + периодический опрос размера данных в сокете. Модуль сервера UDP хочу заложить таким образом: 1) Есть основная задача (FreeRTOS), которая периодически проверяет размер данных в сокетах, именно в нескольких (которые настроены в режиме UDP), и если в каком из сокетов появились данные, то запускаем отдельную задачу на обработку этого пакета. Таким образом обработка пакетов на разных сокетах происходит независимо друг от друга. Для того что бы ожидать прерывание wiznet, на нескольких сокетах, решил в обработке прерывания их складывать с одну очередь а в главной задаче считывать эту очередь, а по таймауту производить опрос количество данных в сокете. Для, одного событие (приема), это логика заработало, но как добавилось событие (передача завершена), тут застрял. Уже думаю, в прерывании от wiznet, разбирать регистр прерываний wiznet на события и записывать их в разные очереди, но если взять TCP сокет там событий много.. каша, получиться. В общем как правильно обработать прерывание INT от wiznet и выдать сигналы на продолжение работы задачам, в разных режимах TCP, UDP . Главная задача получилась такая Обработка прерывания вышла так
  24. Что-то похожее пытался сделать, но тут же сразу возникла проблема Дело в том что у меня модуль АЦП выдает 2 ввида среднего значение по работа введется по нему. 1) Большое количество отсчетов (за 200ms) , для отображение параметра на экране 2) Парочку значений , для зашиты. Так вот что бы запустить функцию Protect она должна быть внутри функции GetDataFromAdc.
  25. Да именно так, это я и назвал смешивание логики работы. Примерно так, и есть и вот их хочу разделить на 2 независимых модуля, по крайне мере что бы первый работал независимо, есть модуль защиты или нет, АЦП же все равно. Для этого и хотел модуль защиты сделать в в виде отдельной задачи. На данный момент переработал, логику работы этих двух модулей и сделал следующее, создал структуру параметра такую: typedef __packed struct{ int32_t adc; //Текушее значение АЦП с учетом компенсации нуля !! uint32_t RealAdc; //Текушее значение АЦП без компенсации !! ParamMem_t mem; ParamCallback_t callback; ParamDec_t dec; uint8_t TypeParam; uint8_t NumInAdc; // физически номер канала АЦП Limit_t lim; uint8_t status; }ParamValue_t; И с выхода модуля ShareParam получаем: 1) Каждый параметр содержит свой АЦП 2) Расчитанно десятичное значение параметра в вольтах амперах ваттах, на основе коэфициента считанного из памяти в структуру mem (по включению). 2) Расчитанный статус параметра на основе, его порогов. 3) В случае перехода статуса параметра (нормы -> аварию, авария->норма) вызывает соответственный callback, который и находиться модуле защиты. И модуль защиты получился чисто из функций инициализации Callback параметров и самих Callback по требуемым параметрам + прерывание INT по выводам которые требуют обработку.
×
×
  • Создать...