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

MementoMori

Свой
  • Постов

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

  • Посещение

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


  1. Настроил таймер на ШИМ. Все хорошо, предустановленное значение записывается, на выходе получаю пропорциональный ШИМ. TIM_ClockConfigTypeDef sClockSourceConfig = {0}; TIM_MasterConfigTypeDef sMasterConfig = {0}; TIM_OC_InitTypeDef sConfigOC = {0}; /* USER CODE BEGIN TIM4_Init 1 */ /* USER CODE END TIM4_Init 1 */ htim4.Instance = TIM4; htim4.Init.Prescaler = 0; htim4.Init.CounterMode = TIM_COUNTERMODE_UP; htim4.Init.Period = 65535; htim4.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1; htim4.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE; if (HAL_TIM_Base_Init(&htim4) != HAL_OK) { Error_Handler(); } sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL; if (HAL_TIM_ConfigClockSource(&htim4, &sClockSourceConfig) != HAL_OK) { Error_Handler(); } if (HAL_TIM_PWM_Init(&htim4) != HAL_OK) { Error_Handler(); } sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET; sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE; if (HAL_TIMEx_MasterConfigSynchronization(&htim4, &sMasterConfig) != HAL_OK) { Error_Handler(); } sConfigOC.OCMode = TIM_OCMODE_PWM1; sConfigOC.Pulse = 0x7FFF; sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH; sConfigOC.OCFastMode = TIM_OCFAST_DISABLE; if (HAL_TIM_PWM_ConfigChannel(&htim4, &sConfigOC, TIM_CHANNEL_2) != HAL_OK) { Error_Handler(); } /* USER CODE BEGIN TIM4_Init 2 */ HAL_TIM_OC_Start_IT(&htim4, TIM_CHANNEL_2); HAL_TIM_Base_Start_IT(&htim4); /* USER CODE END TIM4_Init 2 */ HAL_TIM_MspPostInit(&htim4); Но стоит мне где-то в другом месте попытаться обновить канал extern TIM_HandleTypeDef htim4; TIM_OC_InitTypeDef sConfigOC = {0}; void SetBacklightBrightness(uint16_t brightness) { sConfigOC.OCMode = TIM_OCMODE_PWM1; sConfigOC.Pulse = brightness; sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH; sConfigOC.OCFastMode = TIM_OCFAST_DISABLE; if (HAL_TIM_PWM_ConfigChannel(&htim4, &sConfigOC, TIM_CHANNEL_2) != HAL_OK) { Error_Handler(); } } Генерация исчезает, на ножке все время ноль. Функция в другом файле вообще, поэтому htm4 объявлен как extern Заданное значение в sConfigOC.Pulse попадает, я проверял. Что я делаю не так?
  2. Не... получается по другому - мне обещают магарыч, а потом выясняется, что собираются его же со мной и употребить.
  3. А кто-нибудь может объяснить, в чем сакральный смысл такой недружественности интерфейса? То есть, пользователь должен не просто обьяснять микросхеме, чего он от нее хочет, но и проверять, правильно ли его поняли. Скажите, а в АЦП у STM32 таких фокусов случайно нет? Так, на будущее, если вдруг захочу Vref+ питать через делитель.
  4. Как бороться? Низкоомными резисторами делителя? Или питать от выхода регулируемого ldo? Чтобы он по обратной связи парировал подтяжку этого пина к земле?
  5. Друзья, еще один вопрос по этой микросхеме. Какая-то проблема с Vref. Вот схема подключения Так вот на Vref почему-то не половина VCC_3V3_LDO, а примерно 800 мВ. Причем не всегда, а после инициализации (с резистивным делителем все нормально, он сам по себе делит напряжение на 2, это проверялось). Опытным путем установлено, что пин VrefIN начинает тянуть напряжение вниз после того, как задействуется следующая функция Поясняю - в норме, на старте в конфигурационном регистре записано 0xFF, то есть все выходы притянуты к земле через внутренний резистор 10к. Если попытаться задать напряжение на выходах, то ничего не получится. При инициализации включаются усилители и с выходами можно работать. И вот как только я пишу в регистр нули - Vref падает до 800 мВ. А выходы ЦАП в этом диапазоне и работают, без нареканий. Если подавать Vdd на Vref напрямую, без делителя, то все в порядке. И на Vref, и, что самое главное, на выходах имеем диапазон от 0 до Vdd Читаю даташит дальше и вижу это И до этого встречалась информация, что минимальное Vref =1.8 вольт. А у меня делится 1:1, то есть 1.6 вольт. Вот, оно, нашел ошибку, решил было я. Как бы не так. Уменьшил один из двух 33к резисторов до 10 кОм, получил расчетное деление до 2.5 вольт, на практике - после инициализации - 1.83 вольт. Уменьшил оба резистора до 5.9 и 1.9 к соответвтенно. Расчетное Vref - 2.45 вольт. На практике - после инициализации - 2.32 вольт. Что за х....? Связано ли это как-то с тем, что, как указано на скриншоте выше, импеданс этого пина 12.5 кОм? Очень похоже, ибо уменьшение номиналов внешнего делителя уменьшает отклонение Vref от расчетного.
  6. Так если я все же иду на шаг с дублирование параметров в RAM, смысл этих танцев с отпусканием ползунка теряется. Можно сохранять не только ползунок, но и все остальные настройки текущей вкладки по выходу из неё. И не забивать мозг мыслями, что сохранять сразу, а что немного погодя. В общем, смысл мне понятен, мысли, как это реализовать, сформровались. Всем спасибо.
  7. Вы, похоже, упорно не желаете понимать... Не поверите, слайде у меня именно для настройки яркости, все как вы описывали. И реакция нужна немедленная. Писать при этом во флеш при смещении слайдера на каждый миллиметр - гробить флеш. Именно для того, чтобы "и рыбку съесть, и сковородку не помыть", я и описал третий вариант, с RAM, только он даёт возможность применять настройки мгновенно и при этом не насиловать flash.
  8. Не подумайте, я тоже так не собирался делать. Просто привел в качестве яркого примера. Наверное и я так же поступлю.
  9. Друзья, еще такой вопрос.... просто размышления. У кого какой опыт, потому что я взвешиваю варианты, все они мне кажутся равноценными и я как тот ослик меж двух мешков с овсом, не могу выбрать. 1. Храню настройки во флеш. Любой процесс, зависимый от настроек, обращается за параметрами во флеш. Если нужно изменить какой-то параметр - читаю весь блок в RAM, изменяю нужное в RAM, тут же записываю. Из плюсов этого подхода - измененные настройки тут же вступают в силу, все это происходит без лишних телодвижение пользователя. Из минусов - частая перезапись флеши - каждый щелчок по галочке - это стирание блока и его перезапись, из-за одной лишь настройки. Или пример похуже - двигаю слайдер от нуля до 255 - за один раз перезаписываю блок 255 раз.. 2. Настройки хранятся во флеш. Любой процесс, зависимый от настроек, обращается за параметрами во флеш. При изменении настроек они записываются во флеш только тогда, когда расставишь все галки и выходишь из меню настроек. То есть потыкал в 20-30 галок, вышел - сектор однократно стерся и однократно записался. Из плюсов - меньше расходуется ресурс флеш. Из минусов - нельзя сразу видеть результат изменения. Точнее можно, но для этого нужно понаделать костылей в программме. 3. Настройки хранятся во флеш. Сразу же при загрузке копируются в RAM. Любой процесс, зависимый от настроек, обращается за параметрами в RAM. При изменении настроек в первую очередь параметры меняются в RAM, а посему система немедленно начинает работать с новой настройкой. Содержимое Flash обновляется из RAM после выхода из меню настроек. Из плюсов - нет минусов, указанных в первых двух пунктах. Из минусов - некоторая громоздкость. Отсрочка сохранения настроек, вследствие чего они могут пропасть при пропадании питания. Мне кажется что я, выбирая из этих вариантов изобретаю велосипед, в то время, как все уже придумано до нас. Может быть уже есть устоявшийся и зарекомендовавший себя подход в этом вопросе? Поделитесь опытом? Кто как делает?
  10. Да, именно по этому и вывалило в хард, не в том месте включал memory-mapped.
  11. Есть такое дело, я любитель. Не стыдно не знать, стыдно не учиться. Мне стыдиться нечего.
  12. Спасибо, я уже допер, что писать мы туда не можем. По этому адресу мы можем только читать. Надо что-то поменять - делаем копию переменной в RAM (TEMP_SETTINGS), там редактируем и обратно (уже без использования первоначального указателя, в обычном режиме) пишем в QSPI. Вот такое #define QSPI_SETTINGS_PAGE_ADDR 0x90FFF000 tSettings *SETTINGS = (tSettings *)QSPI_SETTINGS_PAGE_ADDR; tSettings TEMP_SETTINGS; void QSPI_WriteSettings(void) { TEMP_SETTINGS=*SETTINGS; } Вываливает в HardFault....
  13. Сделал, предупреждение исчезло. Одна деталь..... в режиме MemoryMapped писать в qspi нельзя. На время записи этот режим надо отключать, а значит переменная по указанному адресу будет недоступна. Получается, нужно завести такую же переменную в RAM, скопировать в нее настройки, после чего выключить MemoryMappedMode и писать? P.S. Вот объявил я tSettings *SETTINGS = (tSettings *)QSPI_SETTINGS_PAGE_ADDR; Дальше пытаюсь получить доступ и что-то записать *SETTINGS.Parameter1=0xAA; Ругается компилятор ../Core/Src/main.c(185): error: #154: expression must have struct or union type У меня вопрос - SETTINGS - это указатель на адрес. Если я не объявлял никакой переменной перед этим, то операция "*SETTINGS= " по идее должна записать что-то по ранее указанному адресу? Ведь, насколько я знаю, если int a=10; int *ptr_to_a=&a; то "а=" равносильно "*ptr_to_a=", не так ли? Короче, если сформулировать ТЗ по-другому 1. В QSPI по адресу 0x90FFF000 записаны настройки. 2. Для того чтобы их читать, создаем указатель tSettings *SETTINGS = (tSettings *)QSPI_SETTINGS_PAGE_ADDR; 3. Захотим записать настройки - создаем в RAM переменную TEMP_SETTINGS, переносим в нее содержимое SETTINGS, отключаем MemoryMappedMode, скармливаем функции QSPI_WRITE содержимое TEMP_SETTINGS Вот как я сделал, знаю, что неправильно, подскажите, как надо typedef struct { char Parameter1; // 1 byte uint8_t Parameter2; // 1 byte uint16_t Parameter3; // 2 byte uint32_t Parameter4; // 4 byte } tSettings; #define QSPI_SETTINGS_PAGE_ADDR 0x90FFF000 tSettings *SETTINGS = (tSettings *)QSPI_SETTINGS_PAGE_ADDR; tSettings TEMP_SETTINGS; void QSPI_WriteSettings(void) { TEMP_SETTINGS=*SETTINGS; TEMP_SETTINGS.Parameter1=0xAA; TEMP_SETTINGS.Parameter2=0xBB; TEMP_SETTINGS.Parameter3=0xEECC; TEMP_SETTINGS.Parameter4=0xEEEEEEDD; uint8_t *source_addr = (void *)&TEMP_SETTINGS; QUADSPI->CR &= ~ QUADSPI_CR_EN; QUADSPI->CR |= QUADSPI_CR_EN; RESULT=BSP_QSPI_Erase_Block(QSPI_SETTINGS_PAGE_ADDR-0x90000000); RESULT3=BSP_QSPI_Write(source_addr, QSPI_SETTINGS_PAGE_ADDR-0x90000000, 256); BSP_QSPI_EnableMemoryMappedMode(); }
  14. Ладно, перенастроил я хранение настроек на QSPI. #define QSPI_SETTINGS_PAGE_ADDR 0x90FFF000 typedef struct { char Parameter1; // 1 byte uint8_t Parameter2; // 1 byte uint16_t Parameter3; // 2 byte uint32_t Parameter4; // 4 byte } tSettings; tSettings *settings_read = QSPI_SETTINGS_PAGE_ADDR; Работает, но при компиляции выдает предупреждение. ../Core/Src/main.c(185): warning: #144-D: a value of type "unsigned int" cannot be used to initialize an entity of type "tSettings *" Что не так и чем чревато?
  15. Должным образом и безопасно - это разные вещи. А если в настройках будет мусор, который, будучи воспринят, как параметр, выведет из строя оборудование? Или не даст возможности добраться до меню настроек (например выставит яркость подсветки дисплея в ноль) или выкинет программу в HardFault? Проверку корректности настроек и запись значений по умолчанию я сделаю в первую очередь.
  16. Как PP, с внутренней подтяжкой. Но при этом он AF - не забывайте. Что там происходит в недрах, я не знаю. Когда я настраивал этот вывод как OD принудительно - карта вообще не читалась. Но, полагаю, так же прочлась бы, если бы я припаял резистор.
  17. Не делал. Читал, что можно делать так, как написал ниже aaarrr, но руки не дошли. Стереотипы у меня... Никогда раньше не возникало необходимости во внешней памяти, несколько раз делал хранение настроек во внутренней.
  18. Я конечно могу перенести адрес основной программы, таблицы векторов прерываний. Но охота все же пойти по пути наименьшего сопротивления. Почитав остальные посты, я понял, что хранить настройки во внешней памяти не стыдно и, наверное буду хранить их в QSPI, благо она уже есть, ее с избытком и стирать там можно по 256 байт.
  19. Добрый день. Есть необходимость хранить настройки (около 200 байт) во внутренней Flash. Раньше я такое уже делал на F1 камнях и, насколько я помню, там можно было стереть страничку размером не более 1024 байт. То есть, нужно выбрать самую последнюю страничка, скрепя сердце, смириться с потерей целого килобайта ради возможности записать несколько байт, всего ничего. Ознакомившись с устройством памяти в F746 и поглядев примеры чтения-записи во флеш я удивился.... там страниц нет, есть сектора, причем последний - 256кб. И стирать его нужно целиком.... То есть, нужно записать пару сотен байт - четверть памяти долой? Может я чего не понял? Никак нельзя уменьшить размер стираемого блока? Или придется предварительно читать весь сектор и переписывать его заново, добавив настройки? Или бросить эту затею и писать в QSPI - там всего 256 байтами нужно жертвовать?
  20. Кидайте в меня, упертого неуча, помидорами.... Припаял резисторы - все заработало! Ради интереса отпаял потом все, кроме того, что на линии CMD - оказалось именно его и не хватало. А ведь я гнал от себя мысль, что дело именно в резисторах, полагал, что если данные читаются, значит дело не в них. А оно вон как....
  21. Удаление оного не решает проблемы.
  22. Давайте так... карта читает и пишет файлы, без нареканий. Длительно, большими объемами не проверял, но она работает. В моей длинной простынке (может ее тяжело читать?) я написал, что проблема возникает при вызове SD_PowerON Понимаете, я вам жалуюсь на то, что машина ездит нормально, после остановки долго заводится, потом снова едет нормально, а вы мне предлагаете проверить, не заклинило ли подшипник колеса.
×
×
  • Создать...