Jump to content

    

Spider

Свой
  • Content Count

    440
  • Joined

  • Last visited

Community Reputation

0 Обычный

About Spider

  • Rank
    В поисках истины
  • Birthday 10/03/1984

Старые поля

  • skype
    Array
  • Vkontakte
    Array
  • G+
    Array

Контакты

  • Сайт
    Array
  • ICQ
    Array
  • Yahoo
    Array

Информация

  • Город
    Array

Recent Profile Visitors

3352 profile views
  1. Появляется "джитер" в сигнале в этот момент :(
  2. Добрый день! Нацарапал прошивку для STM32F411, которая формирует ШИМ сигнал по содержимому в буфере. Значения в Таймер загружает DMA в кольцевом 2х буферном режиме. Пока грузится один буфер - основной цикл подготавливает второй буфер. И бывает так, что по окончании "полезного" сигнала буфер для DMA заполнен не полностью, ну к примеру DMA настроен на буфер в 512 отсчётов, а в очередной цикл буфер заполнился на 100 отсчётов и по окончании нужно остановить генерацию, т.е. выключить таймер. В очередном прерывании DMA (когда меняются местами буферы TCIFn) я могу определить что очередной "работающий" буфер короче ожидаемого, но вот как об этом сказать DMA? Если верить даташиту, то с запущенным DMA уже ничего не поделать, все манипуляции только после остановки. Но если я его остановлю, я получу "ошибки" в генерации выходного сигнала таймером. Варианты: 1. Забивать остаток не полного буфера "нейтральным" сигналом и останавливать DMA при очередном TCIFn после этого - "не полного" буфера. 2. "ловить" DMA на пол пути ещё одним таймером настроенным заранее в TCIFn из расчёта на кол-во отсчётов. Может как-то ещё?
  3. А нельзя в прерывании смотреть кто сейчас держит Mutex и от этого уже отталкиваться?
  4. Усыпляю проц в StandBy с последующим пробуждением по будильнику RTC. Настраиваю будильник, усыпляю, а про просыпается на 16 секунд позже запланированного. и всегда РОВНО на 16 секунд позже. т.е. чтобы мне получить корректное время пробуждения, я должен установить будильник на 16 секунд раньше и тогда получаю желаемый результат. Как так то? Привожу кусочек кода, максимально отчищеный по месту. uint32_t time; uint32_t date; uint32_t subsec; //Выгребаем время из RTC do { time = LL_RTC_TIME_Get(RTC); date = LL_RTC_DATE_Get(RTC); subsec = LL_RTC_TIME_GetSubSecond(RTC); } while (subsec != LL_RTC_TIME_GetSubSecond(RTC)); sec = __LL_RTC_CONVERT_BCD2BIN(__LL_RTC_GET_SECOND(time)); min = __LL_RTC_CONVERT_BCD2BIN(__LL_RTC_GET_MINUTE(time)); hour= __LL_RTC_CONVERT_BCD2BIN(__LL_RTC_GET_HOUR(time)); //Будем ставить будильник на 10 секунд sec+=10; //Тут конечно есть проверки на "переполнение", но для простоты примера этого достаточно. LL_RTC_DisableWriteProtection(RTC); CLEAR_BIT(PWR->CSR, PWR_CSR_EWUP); //Вроде как в Даташите написано, что наждо отключить будильник и дождаться его готовности к записи. LL_RTC_ALMA_Disable(RTC); do {} while (!LL_RTC_IsActiveFlag_ALRAW(RTC)); LL_RTC_ClearFlag_ALRA(RTC); //пишем новое время в будильник А LL_RTC_ALMA_ConfigTime(RTC, LL_RTC_ALMA_TIME_FORMAT_AM, __LL_RTC_CONVERT_BIN2BCD(hour), __LL_RTC_CONVERT_BIN2BCD(min), __LL_RTC_CONVERT_BIN2BCD(sec)); //Реагируем только на совпадение секунд, это отдельная тема LL_RTC_ALMA_SetMask(RTC, LL_RTC_ALMA_MASK_DATEWEEKDAY | LL_RTC_ALMA_MASK_HOURS | LL_RTC_ALMA_MASK_MINUTES); //Не реагируем на субсекунды LL_RTC_ALMA_SetSubSecondMask(RTC, 0); LL_RTC_ALMA_Enable(RTC); LL_RTC_EnableWriteProtection(RTC); //Вывожу в консольку фактическое значение будильника TRACE_INFO("RTC->ALRMAR: 0x%08X\r\n",RTC->ALRMAR); /* Enable the wake up pin */ SET_BIT(PWR->CSR, PWR_CSR_EWUP); //Всем спать. SET_BIT(PWR->CR, PWR_CR_PDDS | PWR_CR_CWUF | PWR_CR_CSBF); SET_BIT(SCB->SCR, ((uint32_t)SCB_SCR_SLEEPDEEP_Msk)); __WFI(); В результате проц проснётся НО! проснётся на 16 секунд позже запланированного. т.е. если в первых строка после пробуждения считать RTC время, то там ровно на 16 секунд больше чем записано в будильнике. Регистр RTC_ALRMAR при выводе в консольку имеет корректные значения на сколько я могу судить. Ну к примеру, выставил я время пробуждения 12:34:56, в регистре RTC_ALRMAR в младших битах значение 0x.....56 (BCD чтоб его так) но проснётся проц в 12:35:12 и в регистре RTC_TR, по мимо всего прочего будет 0x....12 (опять BCD). Как так то? Что я делаю не так?
  5. Спасибо, вроде разобрался. В итоге использую 3 прерывания: IDLE, HTC, TC. Обработчик во всех один и тот же. Вроде пока работает...
  6. Оно приходит спустя где-то 1,5 байта после приёма стоп бита последнего принятого байта.
  7. Всем привет! Что-то я делаю не так... цель моя - запустить DMA в кольцевом режиме для приёма данных с UART. Использую LL библиотеку от STM. Ожидаю получение IDLE прерывания от UART и как следствие чтение данных из DMA. Немного не допонимаю что делать с DMA в данный момент... Как понять сколько байт DMA положила в буфер? Как после обработки этих данных "объяснить" DMA что эти данные уже обработаны? Надо как-то сместить "начало" буфера? Чё-то я туплю :(
  8. Должен ли датчик в режиме термостата отвечать на Reset? Если отвечает, то он в 1-Wire режиме?
  9. Да, конечно пробовал. Отчётливо видно ответ на Reset. Вот только Длительность моего Reset не 480, а 520uS, но ведь в даташите указано как минимум 480, да и псевдо датчик отвечает на этот импульс. Далее идёт переключение на 115200 и отправка слотов с битами. Видно что ответов уже нет....
  10. Всем привет! Попросили тут разобраться со старой железкой у которой в качестве температурного датчика использовался DS1821 (тот который термостат ещё) в режиме 1-Wire сенсора. Исходников железки не сохранилось, а датчики сгорают, ломаются, теряются. И вот человек купил новые, а они не работают. Сел я посмотреть что с ними не так и не могу понять. Неужто паленые какие-то? Что имею: 1. STM32F103 проц 2. DS1821 из старых запасов, рабочая, 2 шт. 3. DS1821 из новой закупки (много) Написал примитивную прогу для опроса регистров DS1821 и вывода результатов в UART. Так вот старые отлично читаются и температуру кажут. А новые не очень. Вроде как на 1Wire Reset отвечает Presence ом. Но дальше сплошной FF FF FF.Немного практики: Логика работы из кучи обмусоливаний с форумов, т.е. Сначала ресет шины, потом команда. Например Чтение статуса: OW_Reset(); reg = OW_ReadRegister(0xAC); или чтение температуры: OW_Reset(); uint8_t reg = OW_ReadRegister(0xAA); Это всё работает со старыми датчиками, а с новыми ни в какую. ЧЯДНТ?
  11. Всем привет! Писал я писал прошивку и написал. Теперь захотелось сделать бутлоадер. Взял готовый бутлоадер, и подправил пару мест в своей прошивке: В Ld скрипте заменил FLASH (rx) : ORIGIN = 0x8000000, LENGTH = 128K на FLASH (rx) : ORIGIN = 0x8002000, LENGTH = 120K В system_stm32f1xx.c убрал строки: #ifdef VECT_TAB_SRAM SCB->VTOR = SRAM_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal SRAM. */ #else SCB->VTOR = FLASH_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal FLASH. */ #endif а добавил их в самом начале main() SCB->VTOR = FLASH_BASE + 0x2000; /* Vector Table Relocation in Internal FLASH. */ На этом казалось бы и всё. Если стартовать прошивку отладчиком - всё работает. Линковщик собирает адреса начиная с 0х08002000 и так далее. В таком случае Reset_Handler находится по смещению 0x0800db7c, а main() в 0x0800bb7c Теперь немного о способе запуска основного кода из Bootloader: Первое что делаю перед запуском это: - Останавливаю используемый бутлоадером SysTick таймер: SysTick->CTRL = SysTick->LOAD = SysTick->VAL = 0; - запрещаю прерывания: __asm volatile ("cpsid i"); Уже от отчаянья сбрасываю NVIC: NVIC->ICER[0] = 0xFFFFFFFF; NVIC->ICER[1] = 0xFFFFFFFF; NVIC->ICER[2] = 0xFFFFFFFF; NVIC->ICPR[0] = 0xFFFFFFFF; NVIC->ICPR[1] = 0xFFFFFFFF; NVIC->ICPR[2] = 0xFFFFFFFF; Отключаю периферию: RCC->APB1RSTR = 0; RCC->APB2RSTR = 0; RCC->APB1ENR = 0; RCC->APB2ENR = 0; Сбрасываю RCC: RCC_DeInit(); Далее стандартные шаги расчёта вектора перехода: pProgResetHandler = (void(*)(void))(*((blt_addr *)(*(FLASH_BASE+0x2000)+0x00000004))); //Тут получается 0x0800db7c - та же цифра что и .Reset_Handler __set_MSP(FLASH_BASE+0x2000); pProgResetHandler(); while(1); // Это строка вроде как никогда не достижима И вот тут самое интересное. Вектор переходит на .Reset_Handler и идёт исполнять его код, но к моменту когда надо прыгнуть на main() в отладке видно что строка имеет положенный ей вид: bl 0x0800bb7c и он даже прыгает туда, и попадает по нужному адресу, но о УЖАС в окне отладки совсем другой код. Какой-то вырванный из середины прошивки код. НО ОН ПО ЭТОМУ АДРЕСУ. а сам main() где-то в другом месте. Совсем в другом месте. Как так то? Что я делаю не так? И естественно исполняя этот код процессор попадает в жуткие состояния. Помогите чем нить :) ЗЫ. Основная прошивка построена на FreeRTOS, но я не могу связать FreeRTOS и это состояние, т.к. до неё дело даже не доходит.
  12. Всем привет. Вот понадобилось написать сенсор давления в BLE. Взял я CC2541 модуль для обучения себя любимого и на базе примера Температурного датчика запилил Environment service с датчиком давления. Всё бы ничего и всё работает. Теперь я хочу понять как экономить батарейку. есть такой чудный метод как osal_pwrmgr_device( PWRMGR_BATTERY ); но как он работает? Когда она уходит в сон и на какое время? опять же, как проредить потребление? Я подумал что можно отключать Advertise на какие-нить 2-3 минуты, затем его включать на 10-15 секунд и по новой. Особой "динамики" не требуется. В свою очередь если кто-то успел зацепиться в эти 10-15 секунд, то уже не отключаться до конца сессии. Так вот. если я взведу таймер средствами osal_start_timerEx() на какие-нить 2-3 минуты, будет ли это корректно? Уснёт ли она на это время пока я всё отключил и жду события от таймера? Если не уснёт, то как уснуть?