eddy_em: (Костерок)
[personal profile] eddy_em
Наконец-то дошли руки допилить "псевдоаппаратный" 1-wire (сосфорж,
гитхаб).
Реализация довольно простая: через таймер TIM2 и DMA, разве что сброс происходит через прерывание (но эта процедура выполняется один раз перед отправкой пакета данных, так что не страшно). Канал 4 таймера TIM2 используется одновременно как выход и вход: TIM2_CH4 работает в режиме ШИМ-выхода, а TIM2_CH3 — в режиме ШИМ-захвата. Соответственно, используются два буфера DMA: канал 7 DMA1 последовательно заполняет из буфера передачи регистр TIM2_CCR4 (этот регистр буферизуется, чтобы его содержимое обновлялось лишь по окончанию передачи предыдущего байта); канал 1 DMA1 по событию захвата CCR3 считывает содержимое TIM2_CCR3 в другой буфер.
По истечению захвата DMA генерирует прерывание, внутри обработчика которого отключается все ненужное и устанавливается флаг готовности принятых данных. Дальше уже обработчик анализирует буфер и выдает нужную информацию (использую простейший конечный автомат, который по завершению приема запускает функцию-обработчик, для нее выделена отдельная глобальная переменная).

"Высокоуровневые" функции для 1-wire почти неизменными были взяты из реализации на STM8 (но там я из-за отсутствия DMA делал все на прерываниях). А вот с низкоуровневыми я помучился... Это уже сейчас кажется, что вроде бы ничего там страшного нет, но поначалу были сложности реализации.
Таймер TIM2 работает на частоте 1МГц, в его регистр TIM2_ARR при сбросе заносится 1000 (1мс), а при передаче данных — 100 (100мкс — средняя длительность передачи бита данных). Регистр TIM2_CCR4 при сбросе имеет значение 500, при передаче данных — 10 (передача единицы) или 60 (передача нуля), при приеме данных — 5.
Соответственно, при удачном сбросе генерируемый датчиками нулевой импульс приводит к тому, что в TIM2_CCR3 заносится значение больше 550 (обычно где-то 650). Если же значение меньше этой барьерной величины (т.е. 500), делаем вывод, что датчиков на шине нет.
Передача данных происходит в соответствии с рекомендованными в даташите длительностями импульсов. Прием инициируется короткой (на 5мкс) подтяжкой шины данных к нулю, а дальше уже датчик "дотягивает" импульс до нужного значения (если длительность импульса меньше 10мкс, то передается единица, иначе передается нуль).

Базовый функционал я реализовал на своей китайской макетке с STM32F103RBT6 (собственно, сниппеты из репозитория stm32samples под нее и пишутся). Реализовано: считывание идентификатора датчика с занесением уникальных идентификаторов в буфер (до 8 датчиков); запуск (широковещательный) измерения температуры; опрос всех датчиков с сохраненными в буфере идентификаторами (если датчик только один, посылается широковещательная команда).
Температура вычисляется в десятых долях градуса Цельсия (т.к. DS18S20 позволяет измерять с точностью не лучше ±0.5°C, а DS18B20 — не лучше ±0.125°C). Для различия DS18S20 и DS18B20 я проверяю байт[4] "блокнота" (scratchpad): у DS18S20 он равен 0xFF, а DS18B20 хранит там конфигурационный регистр, старший бит которого всегда равен нулю. В принципе, этим регистром можно изменять разрядность DS18B20, но я пока это не буду реализовывать: все равно нет смысла опрашивать датчики чаще, чем раз в полминуты, так что 750мс будет длиться преобразование или же 93.75мс — безразлично.
Если при опросе N датчиков не было обнаружено определенного, то будет возвращено значение ERR_TEMP_VAL, равное 200000 (что явно выходит за пределы возможностей датчика).

Теперь все это нужно прикрутить к ИК-контроллеру, чтобы иметь возможность замерять "теплые" температуры (скажем, по разности температур стенок криостата и окружающего воздуха можно судить о глубине вакуума в криостате).

P.S. Странно: не могу сделать hg push, Опять какие-то косяки с сосфоржем...

Неясно

Date: 2015-07-22 09:08 am (UTC)
From: [identity profile] Валентин Большешапов (from livejournal.com)
В функции
void run_dmatimer(){
....
adc_disable_dma(ADC1); // turn off DMA & ADC
adc_off(ADC1);
....
}
вы отключаете ацп и больше нигде не включаете. Для чего это делается ? или линия помимо 1-wire используется для ацп? или обязательно надо dma1 освободить?

Re: Неясно

Date: 2015-07-22 09:57 am (UTC)
From: [identity profile] eddy-em.livejournal.com
Это — "артефакт", в данном случае лучше закомментировать.
Дело в том, что в оригинале (IR_controller) у меня DMA1 еще для АЦП используется, поэтому нужно туда-сюда дергать настройки.

Re: Неясно

Date: 2015-07-22 04:49 pm (UTC)
From: [identity profile] Валентин Большешапов (from livejournal.com)
У меня тоже на дма1 только другом канале крутится ацп по кругу, но не думаю что одно другому должно мешать.

да и сорсфорж вроде же закрывается

Re: Неясно

Date: 2015-07-22 05:13 pm (UTC)
From: [identity profile] eddy-em.livejournal.com
В моем случае не получится разделить, т.к. и АЦП, и один из каналов таймера висят на одном и том же канале 1 ПДП1.

Re: Неясно

Date: 2015-07-22 05:36 pm (UTC)
From: [identity profile] Валентин Большешапов (from livejournal.com)
ломаю тут голову, с захватом раньше не приходилось сталкиваться, у вас реализовано на одной ноге,
TIM_CCMR2_CC3S_IN_TI4 именно это и позволяется связать внутренние подключение захвата 3 каналом с 4 го канала того де самого TIM ?
В случае если я хочу использовать две ноги, подключенную к TIM2CH3 как вход для сравнения с CH4, как в этом случае правильно написать? или достаточно просто инициализировать ногу как альт функцию ?
Edited Date: 2015-07-22 05:37 pm (UTC)

Re: Неясно

Date: 2015-07-22 05:55 pm (UTC)
From: [identity profile] eddy-em.livejournal.com
Достаточно указать, что канал три захватывает с ноги CH3. В даташите указано, что там за флаги. Соответственно, можно нужное определение взять из opencm3. Конечно, нужно и ногу должным образом проинициализировать (а то и ремап сделать, если используется не основной функционал).
Но зачем так разделять? Разве что, для освобождения DMA1ch1...

Хмм

Date: 2016-06-01 10:10 pm (UTC)
From: [identity profile] megaboy2k.livejournal.com
Не нашел в вашем репозитории исходников периферийных API

Re: Хмм

Date: 2016-06-02 05:31 am (UTC)
From: [identity profile] eddy-em.livejournal.com
Что такое "периферийные API"?

Re: Хмм

Date: 2016-06-02 11:56 am (UTC)
From: [identity profile] megaboy2k.livejournal.com
Имеются ввиду вызовы типа:
gpio_set_mode
rcc_periph_clock_enable
etc
В архиве stm32samples-master я их не нашел...

Re: Хмм

Date: 2016-06-02 12:06 pm (UTC)
From: [identity profile] eddy-em.livejournal.com
А, понял: имеется в виду настройка периферии.
У меня во всех проектах из репозитория stm32samples основная настройка идет в файле hardware_ini.c.
Но в данном случае настройка пинов 1-wire происходит в файле onewire.c. Вот же это:
gpio_set_mode(GPIOA, GPIO_MODE_OUTPUT_50_MHZ,
      GPIO_CNF_OUTPUT_ALTFN_OPENDRAIN, GPIO3);

а дальше настраиваются клоки, таймеры и DMA.

Естественно, я не совал их исходники к себе, т.к. это библиотека opencm3. Вот ее вики

Но т.к. она популярная, обычно в репозиториях дистрибутива уже есть, и вручную ее ставить не надо будет.
Edited Date: 2016-06-02 12:08 pm (UTC)

Re: Хмм

Date: 2016-06-02 12:14 pm (UTC)
From: [identity profile] megaboy2k.livejournal.com
Тады ясно, а то упоминания про opencm3 как бы еще нужно постараться, чтобы найти. Лучше бы про это упомянуть где то в статье.

Re: Хмм

Date: 2016-06-02 12:49 pm (UTC)
From: [identity profile] eddy-em.livejournal.com
А зачем его искать? Достаточно Makefile посмотреть и заголовки исходных файлов.

Я уже давно писал, что использую opencm3. Когда-то начинал с SPL, но это жуткая содомия — даже сами STM отказались от нее. Правда, вместо SPL они предложили HAL/Qube — полный [censored]!

Единственный вменяемый вариант, который остался — opencm3. И то, многие функции очень жирные, поэтому я предпочитаю напрямую регистрами пользоваться, а библиотечные функции использовать по-минимуму (скажем, на инициализации и в некритических частях).

P.S. В Readme из репозитория написано же: "These are my simple snippets for STM32 (compiled with libopencm3)". Так что, те, кто делает hg pull и читают Readme, увидят эту надпись.
Edited Date: 2016-06-02 12:51 pm (UTC)

Re: Хмм

Date: 2016-06-02 01:12 pm (UTC)
From: [identity profile] megaboy2k.livejournal.com
Интересно, посмотрим, что за зверь такой...
А от CubeMX у меня весьма позитивные впечатления. Сейчас делаю с его помощью один проект средних размеров, полет нормальный. Там главное держать боевые исходники и файл проекта отдельно после первой генерации кода и по мере необходимости в перегенерации кода, мерджить изменения вручную, юзаю WinMerge.
Некоторые HAL драйвера пришлось править немножко, например, для I2C.
Но таки править готовый и в принципе рабочий код таки намного легче, чем писать с нуля.
Вот интересно, в этой opencm3 для I2C используется таймаут операций и все ли операции происходят без блокирования текущего потока в цикле?
Очень часто через прерывания и DMA делают только собственно запись/чтение слов, а ожидание, например, освобождения шины почему то делают тупо в цикле, что есть фигня.

Re: Хмм

Date: 2016-06-02 02:48 pm (UTC)
From: [identity profile] eddy-em.livejournal.com
> А от CubeMX у меня весьма позитивные впечатления
Я картинки только видел — с меня хватило ☺
> Вот интересно, в этой opencm3 для I2C используется таймаут операций и все ли операции происходят без блокирования текущего потока в цикле?
С I2C на STM32 я еще не работал, в ближайшем будущем собираюсь заняться. В коде библиотеки (по крайней мере, той версии, что у меня сейчас) для работы с I2C ничего нет — только ненужные обертки над регистрами.
Но мне после STM8 (там довольно веселенькая errata по поводу I2C) это не страшно. В даташите все нормально расписано, так что можно спокойно будет все написать.
ЕМНИП, DMA в случае STM32F103 с I2C использовать не выйдет из-за глючности аппаратного I2C — только в прерываниях по таймеру или в режиме КА.
Собственно, через КА я и собираюсь реализовать работу с шиной.

Re: Хмм

Date: 2016-06-02 03:51 pm (UTC)
From: [identity profile] megaboy2k.livejournal.com
I2C в STM32F1xx прекрасно живет, с ограничениями ерраты уже давно научились бороться.
Я использую F4, там с I2C вообще все гладко

Посмотрел эту opencm3, а там больше половины файлов для stm32 просто пустые, даже не смешно. Впрочем, разработчик честно предупреждает: The API of the library is NOT yet considered stable! Please do not rely on it, yet!

Edited Date: 2016-06-02 04:47 pm (UTC)

Re: Хмм

Date: 2016-06-02 04:58 pm (UTC)
From: [identity profile] eddy-em.livejournal.com
> там больше половины файлов для stm32 просто пустые
Да и наплевать, мне оно не нужно: я эту библиотеку использую по-минимуму. Все равно основную долю работы делаю непосредственно на регистрах — это проще, чем ковыряться в исходниках библиотеки, выискивая, какие же функции надо вызывать для того-сего.

Полным-полно людей в сети пользуются libopencm3 на STM32. Потому что если не она, то придется самому все делать — в т.ч. заголовочные файлы писать (как я для STM8 делал, т.к. вообще ничего нет: sdcc умеет компилять, но никаких готовых заголовочных файлов не предоставляет), а это уж точно не смешно.

А еще opencm3 пользую из-за usb. Возможно, когда-нибудь руки до сети дойдут — там вроде тоже что-то есть.

Re: Хмм

Date: 2016-06-02 05:07 pm (UTC)
From: [identity profile] megaboy2k.livejournal.com
> Потому что если не она, то придется самому все делать
Странный вывод, чес говоря по API там большой разницы с Кубом не увидел.
Имхо, исключительно дело привычки, даже стиль кода примерно одинаковый.

Re: Хмм

Date: 2016-06-03 05:37 am (UTC)
From: [identity profile] eddy-em.livejournal.com
Даже если бы "куб" был идеальным, работать из-под виртуалбокса или вайна как-то некомильфо! Я уж и забыл, когда последний раз пользовался вантузячьими приложениями.

Re: Хмм

Date: 2016-06-03 11:39 am (UTC)
From: [identity profile] megaboy2k.livejournal.com
Чтобы работать с кубом, винда не нужна. CubeMX это опция, никто же не заставляет генерить код.

October 2025

S M T W T F S
   1234
567 89 1011
121314 15161718
19202122232425
2627 28293031 

Most Popular Tags

Style Credit

Expand Cut Tags

No cut tags
Page generated Feb. 27th, 2026 03:42 pm
Powered by Dreamwidth Studios