Важна не длина выходных, а умение ими пользоваться.

Меню навигации для мобильных

STM32 :: пытаемся разобраться

Автор zenon, 22 Окт., 2020, 00:20

« предыдущая - следующая »

Slabovik

#25
У них вроде конвертатор есть (фирмварь ST-link'а заменяют с возможностью восстановления обратно).
https://www.segger.com/products/debug-probes/j-link/models/other-j-links/st-link-on-board/
Надо пробовать, но я завис на лабораторнике, а тянуть несколько дел одновременно не получается.

upd: у китайцев J-Link имеется, вполне вменяемо. https://sysadmin.link/?p=2522
Общением на форуме подпитываю свою эгоистичную, склонную к самолюбованию сущность.

zenon

Ну вот, только я засел на линукс... опять перегружаться... :)
offtop:
Я пока собрал вот так (пидб), на выходе 4хtip35с.
... получилась неплохая полочка на столе... сверху ещё кусок фанеры, брутально короче. :)))
https://github.com/minamonra/

zenon

#27
Не, пока не могу/хочу ничего из того, что видел, да понимаю, что тыкаюсь в geany неэффективно... но нужна ли мне эффективность? Если мне всего-то и надо помигать, почитать ацп...
Перешил в j-link - опять какие-то лицензии... да епрст.
Мне надо, чтобы было просто и понятно, вот редактор, вот терминал, командная строка, make etc.
Взглянув очередной раз на Hal, куб, эклипс понял что пока они у меня вызывают стойкое отвращение, может что-нибудь изменится...
Вот например интерфейс ардуины - аж вздрагиваю, к тому, что на яве наверное никогда не привыкну.
Но это сугубо моё отношение на данный момент. :))
https://github.com/minamonra/

zenon

Решил посмотреть как через чтение пина работать будет, и будет ли вообще... :)
Источник (https://controllerstech.com/ir-remote-with-stm32/).
Моё видео (https://youtu.be/SJL2UuyYyBY).
Оно то конечно не для использования, так - побаловаться.
https://github.com/minamonra/

zenon

#29
Решил бороться со своими привычками, они - зло.
Ну сильная же штука segger, видно сразу, тут хоть часть от неё поиспользовать.
... и мимо usart никак не пройти, разбирался вчера и с тем и с тем, попутно освежив в памяти по диагонали разницу между uart и usart, опять-же плохая привычка оставлять разборки деталей на потом.
В итоге в segger запустил usart? (или uart :) ) по-простому передачу и прерывание на приём, можно было сразу с dma выдрать - примеров предостаточно, но это не наш подход.
Попробовал и в линукс и в вин, всё работает, терминал, дебаг etc.
Не разобрался пока как переменные в отслеживание добавить...
Код в процессе... лишних комментариев из разных мест много, не всё правильно.
Передаёт в терминал символы, при приёме любого зажигает на чуть-чуть светодиод.
https://github.com/minamonra/

Slabovik

#30
Вот ещё описание интересного инструмента от Segger https://habr.com/ru/post/259205/
и ссылка на официальную страничку https://www.segger.com/products/debug-probes/j-link/technology/about-real-time-transfer/
Насколько я понимаю, для использования нужно только включить библиотеку в код и пользоваться её функциями для вывода чего-то нужного для отладки.

зы: USART - более сложное устройство т.к. является синхронным.  Краткий болтологический ликбез: https://www.rlocman.ru/review/article.html?di=164400

Кстати, SPI - это типичный USART, I2C - тоже, как и множество других. Самый прикольный пример USART - манчестерский код, который можно было просто записывать на магнитофон, чем и пользовались для хранения программ во времена Радио-86 (гы: Spectrum этот код не использовал, из-за чего вывод-ввод на магнитофон у него был более унылым).

p.s. и просто оставлю чуток ссылок в копилку ликбеза: как прошить STM32

https://blog.kvv213.com/2020/01/kak-proshit-chip-stm32/
http://dimoon.ru/obuchalka/stm32f1/programmirovanie-stm32-chast-14-proshivaem-stm32-cherez-st-link.html
https://www.drive2.ru/b/2228288/
http://microsin.net/programming/arm/um1075-st-link-debugger-programmer-for-stm8-and-stm32.html
Ну а что, пусть будет  :)
Общением на форуме подпитываю свою эгоистичную, склонную к самолюбованию сущность.

zenon

Пытаюсь понять как назначаются альтернативные функции.
Меня сейчас интересует таймер TIM1_CH1.
Даташит тут (https://www.st.com/resource/en/datasheet/stm32f030f4.pdf). Reference manual (https://www.st.com/resource/en/reference_manual/dm00091010-stm32f030x4-x6-x8-xc-and-stm32f070x6-xb-advanced-arm-based-32-bit-mcus-stmicroelectronics.pdf).
В сниппетсах это делается так:
GPIOA->MODER = (GPIOA->MODER & ~(GPIO_MODER_MODER8)) | (GPIO_MODER_MODER8_1);
GPIOA->AFR[1] |= 0x02;
у меня получилось методом непонятным... вот так:
GPIOA->MODER  |= GPIO_MODER_MODER8_1; 
GPIOA->AFR[1] |= (0x2 << 0*4);
Никак я с такими выкрутасами не разберусь... что и откуда берётся и как складываются две тетрады.
Для PA8 TIM1_CH1 это AF2. Весь байт значит у нас находится в GPIOA->AFR[2] судя из даташита... почему в примере AFR[1]?
И как получилось что он равен 0x02?
https://github.com/minamonra/

zenon

Дабы разобраться с битовыми операциями запустил отладку и смотрю что и куда.
В коде специально подробно для себя расписал...
Приёмник работает. :)
https://github.com/minamonra/

zenon

Эммм, начал искать vref у stm32f030, а его отдельного и нету. Он на vdda.
Цитата: undefinedVref- and Vref+ are only available as external pins on LQFP144, UFBGA132, LQFP100, UFBGA100, and TFBGA64 packages, otherwise they are bonded to Vssa and Vdda, respectively.
И куда же тогда точную опору ставить? На vdda/vssa? Какое напряжение тогда?
https://github.com/minamonra/

Slabovik

Если я правильно понимаю, VDDA ровно такой же, как и Vcc, просто питает он аналоговые цепи. Точность и "плывучесть" со всеми вытекающими напрямую зависит от точности и плывучести применённого стабилизатора питания (его можно индивидуально для VDDA забацать).

Для проведения точный измерений в таком случае всё-равно внешний АЦП с прецизионной опорой ставить, ну, или искать чип, где Ref выведен наружу...
Общением на форуме подпитываю свою эгоистичную, склонную к самолюбованию сущность.

zenon

VREF+ and VREF– inputs are available only on 100-pin packages.
Не понимаю я почему такая политика у них, вроде есть 12 бит... а тут так.
https://github.com/minamonra/

zenon

Хм. Кнопки, может стоило в отдельнцю тему закинуть.
Набрёл на вот такое решение (https://www.microchip.su/showthread.php?p=76885#post76885).
Лучше конечно заранее один порт например отводить под кнопки, тогда его удобно целиком читать.
Но у меня немного в разнобой вышло, но адаптировать под stm код получилось.
button.h
#define BUTTON0     1<<0  // PA1
#define BUTTON1     1<<1  // PA2
#define BUTTON2     1<<2  // PA3
#define BUTTON3     1<<3  // PA4
#define BUTTON4     1<<4  // PA11
#define BUTTENC     1<<5  // PA5
#define BUTTONB     1<<6  // PA5
//#define BUTTONB     (1<< 1)  // PB5
//#define BUTTON7     (1<< 1)  // PB5
#define pin_BUTTON0     pin_read(GPIOA, 1<<1)
#define pin_BUTTON1     pin_read(GPIOA, 1<<2)
#define pin_BUTTON2     pin_read(GPIOA, 1<<3)
#define pin_BUTTON3     pin_read(GPIOA, 1<<4)
#define pin_BUTTON4     pin_read(GPIOA, 1<<11)
#define pin_BUTTENC     pin_read(GPIOA, 1<<5)
#define pin_BUTTONB     pin_read(GPIOB, 1<<1)

typedef struct
{
    unsigned char   ucPressed;            // Состояния кнопок
    unsigned char   ucJitter    : 3;      // Для подавления дребезга
    unsigned char   ucCounter   : 6;      // Для проверки удерживания
    unsigned char   ucHold;               // Состояние длительного удерживания
                                          // События:
    unsigned char   ucShort;              // Короткое нажатие и отпускание
    unsigned char   ucJustPressed;        // Кнопки только что нажаты
    unsigned char   ucJustReleased;       // Кнопки только что отпущены
    unsigned char   ucChanged;            // Состояние кнопок изменилось

} TBUTTONS;

extern volatile TBUTTONS m_Buttons;

void Task_Buttons (void);
button.c
void Task_Buttons (void)
{
    static  unsigned char s_ucPort;     // Предыдущее состояние портов
            unsigned char ucTemp;       

    ucTemp = 0x00;

    if (!pin_BUTTON0) ucTemp |= 0x01;
    if (!pin_BUTTON1) ucTemp |= 0x02;
    if (!pin_BUTTON2) ucTemp |= 0x04;
    if (!pin_BUTTON3) ucTemp |= 0x08;
    if (!pin_BUTTON4) ucTemp |= 0x10;
    if (!pin_BUTTENC) ucTemp |= 0x20;

    if (!pin_BUTTONB) ucTemp |= 0x40;
    //if (!pin_BUTTON7) ucTemp |= 0x80;

    ucTemp      ^= s_ucPort;            // Изменения с момента последнего выполнения
    s_ucPort    ^= ucTemp;              // Текущее состояние портов

    if (ucTemp)                         // Подавление дребезга
    {
        m_Buttons.ucJitter = 0;
        return;
    }
    //------------------------------------------------------------------------------
    
    m_Buttons.ucJitter++;
    ucTemp = s_ucPort ^ m_Buttons.ucPressed;// Маска изменения состояние

    if (!m_Buttons.ucJitter && ucTemp)      // Состояние изменилось, дребезг подавлен
    {
        //------------------------------------------------------------------------------
        //  Проверяем отпущенные кнопки
        //------------------------------------------------------------------------------
        
        if (m_Buttons.ucPressed & ucTemp)   // Есть отпущенные
        {
            m_Buttons.ucJustReleased    |=  ucTemp;
            m_Buttons.ucChanged         |=  ucTemp;
            m_Buttons.ucShort           |=  ucTemp;
            m_Buttons.ucShort           &= ~m_Buttons.ucHold;
            m_Buttons.ucHold            &= ~ucTemp;
        }   // if released
        //------------------------------------------------------------------------------
        //  Проверяем нажатые кнопки
        //------------------------------------------------------------------------------
        if ((m_Buttons.ucPressed ^ ucTemp) & ucTemp)    // Есть нажатые
        {
            m_Buttons.ucChanged         |=  ucTemp;
            m_Buttons.ucJustPressed     |=  ucTemp;
            m_Buttons.ucShort           &= ~ucTemp;
        }   // if pressed

        m_Buttons.ucPressed = s_ucPort;
        m_Buttons.ucCounter = 0;
    }   // if changed and debounced

    m_Buttons.ucCounter++;
    //------------------------------------------------------------------------------
    //  Проверяем длительное удерживание
    //------------------------------------------------------------------------------
    
    if (m_Buttons.ucCounter == 50)
    {
        m_Buttons.ucChanged |= m_Buttons.ucHold ^ m_Buttons.ucPressed;
        m_Buttons.ucHold = m_Buttons.ucPressed;
    }

}

Использование вышло вот таким:
void button_process(uint8_t i) // начало кнопок
{ if (buttms > ttms || ttms - buttms > i) {
  buttms = ttms; 
  Task_Buttons();

  if (m_Buttons.ucShort & BUTTONB) { m_Buttons.ucShort = 0; }
  if (m_Buttons.ucHold  & BUTTONB) { }

  if (m_Buttons.ucShort & BUTTON0) { m_Buttons.ucShort = 0; }
  if (m_Buttons.ucHold  & BUTTON0) { }

  if (m_Buttons.ucShort & BUTTON1) { m_Buttons.ucShort = 0; }
  if (m_Buttons.ucHold  & BUTTON1) { }

  if (m_Buttons.ucShort & BUTTON2) { m_Buttons.ucShort = 0; }
  if (m_Buttons.ucHold  & BUTTON2) { }

  if (m_Buttons.ucShort & BUTTON3) { m_Buttons.ucShort = 0; }
  if (m_Buttons.ucHold  & BUTTON3) { }

  if (m_Buttons.ucShort & BUTTON4) { time_setup();m_Buttons.ucShort = 0; }
  if (m_Buttons.ucHold  & BUTTON4) { }
  }
Функция button_process вызывается в main, в аргументе передаётся задержка, сколько раз в миллисекундах выполнить опрос.
Всё бы ничего, но вот как тут организовать повторы с инкриментом переменной при длительном удержании не могу понять... :)
https://github.com/minamonra/

zenon

Блин, ucPressed отлично на повторы работает, разобрался.
https://github.com/minamonra/

Slabovik

Я вот несколько дней кручу-верчу этот код и... реально туплю (поди совсем старый стал).
Мог бы ты пояснить, как именно он работает. Интересуют конечно не конкретные команды, а принцип.
Вообще, тема опроса кнопок довольно обширна. ВО времена ДОСа и мелких компов я тоже писал работу опрос клавиатуры. Можно пообсуждать.

Мастер, выделишь тему отдельно?
Общением на форуме подпитываю свою эгоистичную, склонную к самолюбованию сущность.

zenon

Ну, кроме объяснений, которые там (на микрочипе) сказать вряд-ли что смогу, я его просто адаптировал под stm.
Сам не до конца понимаю как это работает.
Да, дефайн (тоже где-то подсмотрен...) pin_read забыл.
Вот так:
#define pin_read(gpioport, gpios) (gpioport->IDR & (gpios) ? 1 : 0)
Порт можно прочитать целиком так:
Port=GPIOB->IDR;
https://github.com/minamonra/

zenon

Ещё на одно решение для кнопок попалось на глаза:
Вот тут (https://qna.habr.com/q/578105#answer_1327207).
Код скопировал с комментами.
↓ спойлер ↓
//Я, например, вот так сделал (для обработки коротких и длинных нажатий трёх кнопок):
uint8_t buttonFlags = 0; // буфер флагов зарегистрированных нажатий

// ОПРОС КНОПОК
void buttons_check(void)
{
  uint8_t buttonState = 0; // буфер для текущего состояния кнопок
  static uint8_t buttonPressCounter[] = { 0, 0, 0 }; // счётчики продолжительности нажатия кнопок
  buttonState = ( BUTTON0_STATE | BUTTON1_STATE << 1 | BUTTON2_STATE << 2 ) ^ 0x07;
  for ( uint8_t i = 0; i <= 2; i++ ) // для каждой из 3 кнопок проверяем:
  {
    if ( ((buttonState >> i) & 1) ) // если кнопка нажата
    {
      buttonPressCounter[i]++; // увеличиваем значение счётчика
      if ( buttonPressCounter[i] == 3 ) // если кнопка нажата около 50мс
      {
        buttonFlags |= ( 1 << i ); // фиксируем короткое нажатие
      }
      else if ( buttonPressCounter[i] == 95 ) // если кнопка нажата около 1.5 секунд
      {
        buttonFlags |= ( 1 << i ) | ( 1 << (i+3) ); // фиксируем длинное нажатие
        buttonPressCounter[i] = 80; // повторяем действие длинного нажатия при удерживании кнопки (примерно 4 раза в секунду)
      }
      else
      {
      buttonFlags &= ~( 1 << i ); // сбрасываем флаг короткого нажатия кнопки
      }
    }
    else // если кнопка отпущена
    {
      buttonPressCounter[i] = 0; // сбрасываем счётчик
      buttonFlags &= ~( ( 1 << i ) | ( 1 << (i+3)) ); // сбрасываем флаги нажатия кнопки
    }
  }
}
//Функция вызывается в теле обработчика прерывания по таймеру, перед функцией - обработчиком нажатий, 
//в зависимости от текущего состояния переменной buttonFlags, и там же, делаем другие нужные нам вещи,
//типа обновления информации на дисплее, и т.д.) Таким образом, всего одним таймером убиваем сразу всех зайцев :)
//P.S. Значения счётчиков - 3, 80 и 95 - с расчётом, что прерывание по таймеру срабатывает каждые 16мс.
//P.P.S. Если чё, сильно не пинять - я ни разу не программист, а так, балуюсь немножко ))
[свернуть]
Надо попробовать как оно работает.
https://github.com/minamonra/

zenon

#41
Ковыряю 1.77" TFT дисплей.
Переделал вот этот вариант (https://forum.easyelectronics.ru/viewtopic.php?f=35&t=13281&start=50), который изначально был для F4 на F0.
Проект тут (https://github.com/minamonra/my_stm_snippets/tree/main/F0/vitgo_st7735).
С переферией разобрался, пытаюсь понять как со шрифтами работать, пока не понял.
Вот интересная ссылка (http://www.rinkydinkelectronics.com/h_utft_fonts_101.php).

+++
↓ спойлер ↓
[свернуть]
https://github.com/minamonra/

zenon

Мы его душили - душили...
↓ спойлер ↓
[свернуть]
https://github.com/minamonra/