Публікації

CH32V003 - використання вбудованого операційного підсилювача

Зображення
Мікроконтролери CH32V003 (як і CH32V006) мають одну дуже цікаву апаратну фішку - вбудований операційний підсилювач (OPA). У цій статті я спробую розібратися та на практиці показати, як ним користуватися для вимірювання малих напруг: наприклад, знімати показники з різноманітних сенсорів чи струмових шунтів. Перш ніж переходити до пайки, варто трохи поглянути на архітектуру. Вбудований OPA має мультиплексовані входи — це означає, що він може програмно перемикатися і брати сигнал з різних пар пінів. Наприклад, у корпусі TSSOP20 доступні дві групи: нульова (PA1 — OPN0, PA2 — OPP0) та перша (PD0 — OPN1, PD7 — OPP1). Проте вихід завжди залишається один — це жорстко прив’язаний пін PD4 (OPO). З “молодшими” чіпами в корпусах SOP8 та SOP16 ситуація трохи інша. Механізм мультиплексування в самому кремнії залишився, але потрібні ніжки просто фізично не виведені назовні, тому варіантів для перемикання там фактично немає. (До речі, є цікавий нюанс: на SOP16 розробники фізично вивели пін OPP1, але...

Підключення поворотного енкодера до CH32V: теорія, осцилограми та код на С

Зображення
Трохи теорії Енкодер - це електромеханічний компонент, який допомагає електроніці визначати швидкість і напрямок обертання вала, а в деяких випадках — ще й точно фіксувати його кутову позицію. Отже, якщо у вашому проєкті є рухомі деталі і потрібно відстежувати їхні оберти або кут повороту, без цього датчика не обійтися. За прикладами не треба звертатися до складних промислових верстатів - у повсякденному житті ми стикаємося з енкодерами постійно. Коліщатко комп’ютерної миші, регулятор гучності в магнітолі, ручка вибору режимів у пральній машині - усе це зручні фізичні інтерфейси для взаємодії з технікою. Найпростіші з енкодерів вміють реєструвати лише рух. У випадку з мишею нам не важливо знати в якому положені коліщатко — ми просто крутимо його вгору чи вниз, щоб проскролити сторінку. Але для деяких процесів дійсно важлива точна позиція, і для цього використовуються більш складні абсолютні енкодери. Конструктивно ці датчики базуються на різних фізичних принципах. Усередині може б...

Wch Link програматори - яка між ними різниця?

Зображення
Wch-Link V1 Коли я вперше звернув увагу на мікроконтролери CH32V на AliExpress, то одразу взяв кілька різних плат: пару штук із CH32V003 та одну потужнішу з CH32V307. Проте одразу виникло логічне питання: як їх прошивати? Мій звичний ST-Link для цієї архітектури точно не підійшов би. Тому я просто знайшов у того ж продавця перший-ліпший програматор із маркуванням WCH і докинув його в замовлення. Це виявився WCH-Link v1, побудований на базі чипа CH549G. Які плюси в нього: - Відносно низька ціна: на розпродажах їх можна знайти від 2 доларів. Універсальність: він підтримує як мікроконтролери WCH на базі RISC-V, так і ARM-сумісні чипи в режимі DAP (хоча останнє я на практиці ще не перевіряв). Наявність вбудованого USB-UART: це надзвичайно зручно для відлагодження, і такої фічі мені часто бракувало в стандартному ST-Link. Однак не обійшлося й без мінусів, які стали для мене неприємним сюрпризом. Головний недолік — він не прошиває лінійку CH32V00x . Виявилося, що ці дешевші мікрок...

Програмний I2C проти апаратного: запускаємо U8x8 на CH32V003

Зображення
У проєкті з OLED-дисплеєм та мікроконтролером STM32F103 виниклопитання : чи можна це здешевити? Що, якщо використати CH32V003? Багато ніжок не потрібно, корпусу SOP16 вистачить. Головне питання — як він працюватиме з OLED SSD1306. Перевіримо це. Як я писав раніше, U8x8 має легко портуватися і може працювати з програмним I2C (bit-bang). Перенесення коду з CMSIS пройшло дуже швидко — кілька чашок кави, і приклад у мене запрацював. Ось код функції u8x8_gpio_and_delay_ch32v : uint8_t u8x8_gpio_and_delay_ch32v(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr) { switch(msg) { case U8X8_MSG_GPIO_AND_DELAY_INIT: RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); GPIO_InitTypeDef init = {0}; init.GPIO_Pin = GPIO_Pin_1 | GPIO_Pin_2; init.GPIO_Mode = GPIO_Mode_Out_OD; init.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOA, &init); break; case U8X8_MSG_DELAY_MILLI: De...