Наконец то свершилось. Я полностью переработал верстку блога и теперь в нем 2 языка. По умолчанию стоит английский. Я даже перевел одну статью. Переключается язык справа вверху.
Новый же канал будет посвящен анонсам новых материалов на сайте, а так-же небольшим обзорам интересных для меня вещей и новостей посвященных разработки электроники.
Следите за обновлениями, дальше точно будет что-то интересное.
Новый же канал будет посвящен анонсам новых материалов на сайте, а так-же небольшим обзорам интересных для меня вещей и новостей посвященных разработки электроники.
Следите за обновлениями, дальше точно будет что-то интересное.
Zenembed
Blog
Blog about hardware, electronics, coding.
🔥8
Сегодня занимался выпаиванием и тестированием вакуумно-люминесцентных индикаторов (VFD). Эти индикаторы излучают приятный синий свет и относительно легко подключаются. Для работы требуется два напряжения: 3-4 В на катод (около 150 мА) и 20-30 В на сетку и анод (менее 10 мА). Управление сегментом и сеткой осуществляется переключением 20 В. В отсутствие документации, пины определял методом перебора.
В планах создать часы с использованием этих индикаторов, так что следите за обновлениями!
В планах создать часы с использованием этих индикаторов, так что следите за обновлениями!
🔥5❤1⚡1
В продолжение ко вчерашнему посту.
Изначально я планировал выпаять дисплеи с помощью стола с подогревом. Однако выяснилось, что старые платы из гетинакса трескаются и лопаются при нагреве до 300 градусов. Не советую повторять мой опыт — теперь на моем нагревательном столе осталось пятно, которое я не могу оттереть. Хотя, возможно, проблема в канифоли, с помощью которой эти дисплеи были закреплены.
Изначально я планировал выпаять дисплеи с помощью стола с подогревом. Однако выяснилось, что старые платы из гетинакса трескаются и лопаются при нагреве до 300 градусов. Не советую повторять мой опыт — теперь на моем нагревательном столе осталось пятно, которое я не могу оттереть. Хотя, возможно, проблема в канифоли, с помощью которой эти дисплеи были закреплены.
😁1🤯1
Вышла отладка от OLIMEX - GateMate A1-EVB.
Данная борда базируется на GateMate CCGM1A1 FPGA. Эта fpga примечательна тем, что ее разработка поддерживается немецким правительством, а тулчейн можно полностью собрать из исходного кода. Наконец то наступило будущее без жирнющих и лагучих IDE.
Про работу с открытым стеком можно почитать у меня в блоге на примере FPGA от Lattice.
Данная борда базируется на GateMate CCGM1A1 FPGA. Эта fpga примечательна тем, что ее разработка поддерживается немецким правительством, а тулчейн можно полностью собрать из исходного кода. Наконец то наступило будущее без жирнющих и лагучих IDE.
Про работу с открытым стеком можно почитать у меня в блоге на примере FPGA от Lattice.
Сегодня на канале всем известного Мединцева вышло новое видео — Шаблоны и код. Обработка ситуаций периферийных блоков. Сразу заспойлерю: про шаблоны не будет сказано вообще ничего.
Но я не об этом. В видео обсуждается проблема: при управлении периферией часто нужно выполнять несколько действий, и в случае, если какое-то действие не проходит, прекратить выполнение. Данная проблема иллюстрируется следующим примером:
Далее предлагается действительно уникальное решение, которого я никогда не видел раньше — использование
Мне кажется данное решение странным, и я его не буду использовать, однако на вкус и цвет.
Тогда возникает логичный вопрос: что же использовать? Ответ на этот вопрос можно найти в самом неожиданном месте — в ядре Linux. Там данная проблема успешно решается уже как 30 лет. Для единообразия предлагаю посмотреть пример с
Обратите внимание, деинициализация будет проходить в обратном порядке относительно инициализации и ровно с того места, где возникла наша проблема. Это не единичный случай; этот паттерн используется повсеместно в ядре, в чем вы можете убедиться самостоятельно с помощью данного сервиса.
Вы можете возразить, что
Пара слов про вторую часть видео (я воздержусь от сомнений в чей-то адекватности). Вопрос интересный: можно ли делать бесконечную блокировку в коде? И я думаю, что да, но есть нюанс. Если мы работаем с устройством, сценарий которого подразумевает, что пользователь включает его, пользуется и выключает, я думаю, это вполне приемлемо. Мы можем проверить адекватность работы периферии один раз, когда устройство включается и собственно инициализирует эту периферию. В случае проблем в процессе работы пользователь может выключить и включить устройство и при старте увидеть сообщение о проблеме. Однако если к нашему девайсу не будет доступа и он должен работать месяцами без перезагрузки, тогда да, таймауты необходимы. Однако
Но я не об этом. В видео обсуждается проблема: при управлении периферией часто нужно выполнять несколько действий, и в случае, если какое-то действие не проходит, прекратить выполнение. Данная проблема иллюстрируется следующим примером:
if (HAL_SPI_Init(&hspi1) == HAL_OK)
{
if (HAL_SPI_Transmit(&hspi1, tdata, sizeof(tdata), 10) == HAL_OK)
{
if (HAL_SPI_Receive(&hspi1, rdata, sizeof(rdata), 10) == HAL_OK)
{
// xzhzxklxklkchlxzkclkzxl
}
}
}
Далее предлагается действительно уникальное решение, которого я никогда не видел раньше — использование
while и break:do
{
if (HAL_SPI_Init(&hspi1) != HAL_OK) break;
if (HAL_SPI_Transmit(&hspi1, tdata, sizeof(tdata), 10) != HAL_OK) break;
if (HAL_SPI_Receive(&hspi1, rdata, sizeof(rdata), 10) != HAL_OK) break;
// Полезное действие
}
while (0);
Мне кажется данное решение странным, и я его не буду использовать, однако на вкус и цвет.
Тогда возникает логичный вопрос: что же использовать? Ответ на этот вопрос можно найти в самом неожиданном месте — в ядре Linux. Там данная проблема успешно решается уже как 30 лет. Для единообразия предлагаю посмотреть пример с
SPI и для STM32 — функцию stm32_spi_transfer_one_dma. И что же там используется? goto. Почему я считаю, что данный вариант лучше? Он по умолчанию подразумевает, что вы не просто прерываете исполнение, а можете еще и деинициализировать то, что инициализировалось правильно до ошибки. Если показать это на примере из начала, то будет выглядеть так:if (HAL_SPI_Init(&hspi1) != HAL_OK)
goto SPI_INIT_ERROR;
if (HAL_SPI_Transmit(&hspi1, tdata, sizeof(tdata), 10) != HAL_OK)
goto SPI_TX_ERROR;
if (HAL_SPI_Receive(&hspi1, rdata, sizeof(rdata), 10) != HAL_OK)
goto SPI_RX_ERROR;
// Do something
return 0;
SPI_RX_ERROR:
SPI_TX_ERROR:
HAL_SPI_DeInit(&hspi1); // This is an example, I don't remember the exact name of the function.
SPI_INIT_ERROR:
return 1;
Обратите внимание, деинициализация будет проходить в обратном порядке относительно инициализации и ровно с того места, где возникла наша проблема. Это не единичный случай; этот паттерн используется повсеместно в ядре, в чем вы можете убедиться самостоятельно с помощью данного сервиса.
Вы можете возразить, что
goto небезопасно и ненадежно, а в ядро коммитят сверхлюди, куда нам до них. Но специально для вас у данной проблемы тоже есть решение там, где его никто не ждал — ESP IDF. Опять возьмем код, связанный с SPI (хотя немного косвенно) — функцию soft_spi_transfer. Специально для удобства пользователя goto завернули в макрос ESP_GOTO_ON_FALSE.Пара слов про вторую часть видео (я воздержусь от сомнений в чей-то адекватности). Вопрос интересный: можно ли делать бесконечную блокировку в коде? И я думаю, что да, но есть нюанс. Если мы работаем с устройством, сценарий которого подразумевает, что пользователь включает его, пользуется и выключает, я думаю, это вполне приемлемо. Мы можем проверить адекватность работы периферии один раз, когда устройство включается и собственно инициализирует эту периферию. В случае проблем в процессе работы пользователь может выключить и включить устройство и при старте увидеть сообщение о проблеме. Однако если к нашему девайсу не будет доступа и он должен работать месяцами без перезагрузки, тогда да, таймауты необходимы. Однако
libopencm3 не запрещает вам сделать это самостоятельно в случае необходимости, просто сделав проверку доступности SPI до того, как что-то в него писать.YouTube
Шаблоны и код. Обработка ситуаций периферийных блоков.
Любопытные размышления о шаблонах написания кода.
Подписывайтесь на канал в телеграмм - https://t.me/vladimir_medintsev
Подписывайтесь на канал в телеграмм - https://t.me/vladimir_medintsev
🔥6❤2
Иногда появляется желание позаниматься какой-то ерундой, поэтому сейчас собрал счетчик рабочего времени на дисплеях DL2416T и STM32F411, да еще и на бредборде. Код выкладывать не буду потому что там трешак:
HAL_GPIO_WritePin(LED_GPIO_Port, LED_Pin, 0);
HAL_Delay(500);
HAL_GPIO_WritePin(LED_GPIO_Port, LED_Pin, 1);
HAL_Delay(500);
sprintf(buff, "%2d-%02d-%02d", i / 3600, (i / 60) % 60, i % 60);
set_8char_display(buff);
i++;
❤🔥7🔥2🤩1
Компания ST добавила новую фичу в
Все скрины сделаны для
В чем собственно суть: теперь если в
Само собой данный пример не заработал, притом не
Без выбора данной галочки будет генерирована только BSP. Но что-же это такое?
В меню с контроллером ноги задействованные для
Хедеры
Складывается ощущение что кому-то платили за количество написанных строк кода. Собственно все остальные функции примерно такие-же.
Плюсы:
- Если в самой первой менюшке убрать все галочки то все будет как раньше, однако отключить генерацию функций для занятых портов больше нельзя.
- Если выбрать генерирование
Минусы:
- Программа которая генерируется как пример. не всегда работает.
- Эта функция работает только с кнопками, светодиодами и
- Какое то запредельное количество новых и не очень полезных макросов и дефайнов в проекте.
- Непонятно что делать с нашим уровнем BSP (тут подразумевается что это просто пример и не нужно его использовать в своих решениях, но если мы решим что-то взять? подгонять наш код стайл под это?)
- Кнопка использует линию прерывания, что если я не хочу ее использовать?
Если подводить итог: то я бы взял вот этот маленький кусочек в свой проект (думаю который всем и так известен), остальное же, не особо полезно.
CubeMX, теперь вы можете генерировать уровень BSP для всех новых плат nucleo. О чем я хочу рассказать.Все скрины сделаны для
NUCLEO-C031C6 но я проверил это еще на 2х платах из списка.В чем собственно суть: теперь если в
CubeMX выбрать Board, а не MCU то появится менюшка как на первой картинке. Там мы можем выбрать генерировать ли демонстрационный код и переферию, для которой мы хотим уровень BSP. Если выбрать первую галочку, то получим примерно следущее:/* -- Sample board code to send message over COM1 port ---- */
printf("Welcome to STM32 world !\n\r");
/* -- Sample board code to switch on leds ---- */
BSP_LED_On(LED_GREEN);
while (1)
{
/* -- Sample board code for User push-button in interrupt mode ---- */
if (BspButtonState == BUTTON_PRESSED)
{
/* Update button state */
BspButtonState = BUTTON_RELEASED;
/* -- Sample board code to toggle leds ---- */
BSP_LED_Toggle(LED_GREEN);
/* ..... Perform your action ..... */
}
}
Само собой данный пример не заработал, притом не
UART не кнопка, хотя-бы диод при старте загорается. (Я не стал глубоко лезть и разбираться где ошибка в генерации, не вижу в этом большого смысла, может быть когда нибудь исправят) Так-же попробовал NUCLEO-H7S3L8, на ней все сразу-же заработало. Без выбора данной галочки будет генерирована только BSP. Но что-же это такое?
В меню с контроллером ноги задействованные для
BSP будут помечены красным и не доступны для изменения, и изменение выбранной периферии тоже будет не доступно. Взглянем на получившийся код:Drivers/BSP
└── STM32C0xx_Nucleo
├── LICENSE.txt
├── stm32c0xx_nucleo.c
├── stm32c0xx_nucleo_conf_template.h
├── stm32c0xx_nucleo_errno.h
└── stm32c0xx_nucleo.h
Хедеры
.h представляют из себя набор бесконечных дефайнов, в сишном файле можно найти собственно реализацию функций BSP, например включение диода:int32_t BSP_LED_On(Led_TypeDef Led)
{
int32_t ret = BSP_ERROR_NONE;
if (Led != LED4)
{
ret = BSP_ERROR_WRONG_PARAM;
}
else
{
HAL_GPIO_WritePin(LED_PORT[Led], LED_PIN[Led], GPIO_PIN_SET);
}
return ret;
}
Складывается ощущение что кому-то платили за количество написанных строк кода. Собственно все остальные функции примерно такие-же.
Плюсы:
- Если в самой первой менюшке убрать все галочки то все будет как раньше, однако отключить генерацию функций для занятых портов больше нельзя.
- Если выбрать генерирование
BSP для serial порта то он сразу будет работать вместе с printf().Минусы:
- Программа которая генерируется как пример. не всегда работает.
- Эта функция работает только с кнопками, светодиодами и
UART (как писал выше, я проверил).- Какое то запредельное количество новых и не очень полезных макросов и дефайнов в проекте.
- Непонятно что делать с нашим уровнем BSP (тут подразумевается что это просто пример и не нужно его использовать в своих решениях, но если мы решим что-то взять? подгонять наш код стайл под это?)
- Кнопка использует линию прерывания, что если я не хочу ее использовать?
Если подводить итог: то я бы взял вот этот маленький кусочек в свой проект (думаю который всем и так известен), остальное же, не особо полезно.
#ifdef __GNUC__
int __io_putchar(int ch)
#else
int fputc(int ch, FILE *f)
#endif /* __GNUC__ */
{
HAL_UART_Transmit(&hcom_uart [COM_ActiveLogPort], (uint8_t *) &ch, 1, COM_POLL_TIMEOUT);
return ch;
}
🔥6❤1👍1
Сегодня хочу рассказать вам о "Открытом курсе по схемотехнике для начинающих" от ядра. Я просмотрел первые две и последнюю лекции, и вот основные моменты, которые мне показались важными:
- Курс предназначен для новичков в схемотехнике, поэтому опытные разработчики, скорее всего, не найдут для себя ничего нового.
- В рамках курса можно получить базовые знания о пассивных компонентах и немного о цифровых схемах.
- Большое внимание уделяется тому, как физически собирать схемы на макетных платах и какие проблемы могут возникнуть при этом.
- После изучения теории сразу предлагается закрепить знания на практике.
В целом, я рекомендую посвятить несколько вечеров просмотру этого курса, если вы только начинаете осваивать схемотехнику. Если вам понравится такой формат обучения, то советую также обратить внимание на книгу с аналогичным подходом (упомянута на последнем прикрепленном изображении). В книге сделан акцент на практическую часть и сборку схем на макетных платах, при этом примеров и упражнений значительно больше.
- Курс предназначен для новичков в схемотехнике, поэтому опытные разработчики, скорее всего, не найдут для себя ничего нового.
- В рамках курса можно получить базовые знания о пассивных компонентах и немного о цифровых схемах.
- Большое внимание уделяется тому, как физически собирать схемы на макетных платах и какие проблемы могут возникнуть при этом.
- После изучения теории сразу предлагается закрепить знания на практике.
В целом, я рекомендую посвятить несколько вечеров просмотру этого курса, если вы только начинаете осваивать схемотехнику. Если вам понравится такой формат обучения, то советую также обратить внимание на книгу с аналогичным подходом (упомянута на последнем прикрепленном изображении). В книге сделан акцент на практическую часть и сборку схем на макетных платах, при этом примеров и упражнений значительно больше.
❤6👍4