stm32f103c8(b) много вопросов

Ответить
asvhmao
Рядовой
Сообщения: 16
Зарегистрирован: 15.03.2024{, 00:10}
Репутация: 4
Откуда: Краснодар
Имя: сергей

stm32f103c8(b) много вопросов

#1

Сообщение asvhmao » 24.04.2024{, 19:44}

На сегодня пока вопрос по настройке таймера TIM1, позже ещё наверное много будет других.

В какой-то из тем, тут, попались пользовательские блоки с настройками шима. Один блок в начале не оценил, позже поменял своё мнение. Там был настроен первый канал. Решил добавить каналы 2-4, с инверсией, дет-тайм, выравнивание по середине. Три канала работают, четвёртый молчит.

Где промахнулся с настройками, или что-то не дописал, пока не разобрался. Изучаю регистры всего пару дней, может у кого по более опытный глаз и укажет на правильное решение вопроса?

IMG_20240424_002801.jpg
IMG_20240426_024510.jpg
Сам блок думаю смысла нет прикреплять, т.к. с ошибками и сырой. Текст ардуины положил под споилер.
Начальную версию брал тут:

viewtopic.php?f=77&t=8630&p=125766&hili ... m1#p125766

.
СпойлерПоказать

Код: Выделить всё

#include "flprogUtilites.h"
int16_t Timperiod;
int16_t PWM_1;
int16_t PWM_2;
int16_t PWM_3;
int16_t PWM_4;
int16_t Fr;
bool Q;
#define RCC_BASE 0x40021000
#define RCC_APB2ENR ((volatile uint32_t *)(RCC_BASE+0x18))
#define GPIOA_BASE 0x40010800
#define GPIOA_CRH ((volatile uint32_t *)(GPIOA_BASE+0x04))
#define GPIOB_BASE 0x40010C00
#define GPIOB_CRH ((volatile uint32_t *)(GPIOB_BASE+0x04))
#define TIM1_BASE 0x40012C00
#define TIM1_CNT ((volatile uint32_t *)(TIM1_BASE+0x24))
#define TIM1_CR1 ((volatile uint32_t *)(TIM1_BASE+0x00))
#define TIM1_CCMR1 ((volatile uint32_t *)(TIM1_BASE+0x18))
#define TIM1_CCMR2 ((volatile uint32_t *)(TIM1_BASE+0x1C))
#define TIM1_CCER ((volatile uint32_t *)(TIM1_BASE+0x20))
#define TIM1_PSC ((volatile uint32_t *)(TIM1_BASE+0x28))
#define TIM1_ARR ((volatile uint32_t *)(TIM1_BASE+0x2C))
#define TIM1_CCR1 ((volatile uint32_t *)(TIM1_BASE+0x34))
#define TIM1_CCR2 ((volatile uint32_t *)(TIM1_BASE+0x38))
#define TIM1_CCR3 ((volatile uint32_t *)(TIM1_BASE+0x3C))
#define TIM1_CCR4 ((volatile uint32_t *)(TIM1_BASE+0x40))
#define TIM1_BDTR ((volatile uint32_t *)(TIM1_BASE+0x44))
uint16_t test= 0;
uint16_t PWMcontrol= 0;
#define TIM1_CCER ((volatile uint32_t *)(TIM1_BASE+0x20))
#define TIM1_PSC ((volatile uint32_t *)(TIM1_BASE+0x28))
#define TIM1_ARR ((volatile uint32_t *)(TIM1_BASE+0x2C))
#define TIM1_CCR1 ((volatile uint32_t *)(TIM1_BASE+0x34))
#define TIM1_CCR2 ((volatile uint32_t *)(TIM1_BASE+0x38))
#define TIM1_CCR3 ((volatile uint32_t *)(TIM1_BASE+0x3C))
#define TIM1_CCR4 ((volatile uint32_t *)(TIM1_BASE+0x40))
#define TIM1_BDTR ((volatile uint32_t *)(TIM1_BASE+0x44))
int16_t _gtv2;
void setup()
{
    *RCC_APB2ENR |= 0x00000805;
    *GPIOA_CRH &= 0xFFFF0000;
    *GPIOA_CRH |= 0x0000BBBB;
    *GPIOB_CRH &= 0x000FFFFF;
    *GPIOB_CRH |= 0xBBB00000;
    *TIM1_ARR = Timperiod;
    *TIM1_CCMR1 = 0x00006868;
    *TIM1_CCMR2 = 0x00006868;
    *TIM1_CCER = 0x00001557;
    *TIM1_PSC = 72;
    *TIM1_BDTR = 0x00008000;
    *TIM1_CR1 = 0x00000061;
    *TIM1_CCR1 = 0x5;
    *TIM1_CCR2 = 0x5;
    *TIM1_CCR3 = 0x5;
    *TIM1_CCR4 = 0x5;
}
void loop()
{
    //Плата:1
    Timperiod = 255;
    PWM_1 = (255)-((map((_gtv2), (0), (4095), (0), (255))));
    PWM_2 = (map((_gtv2), (0), (4095), (0), (128)));
    PWM_3 = (map((_gtv2), (0), (4095), (0), (255)));
    PWM_4 = (map((_gtv2), (0), (4095), (0), (255)));
    *TIM1_ARR = Timperiod;
    PWMcontrol = PWM_1;
    PWMcontrol = constrain(PWM_1,0,Timperiod);
    *TIM1_CCR1 = PWMcontrol;
    PWMcontrol = PWM_2;
    PWMcontrol = constrain(PWM_2,0,Timperiod);
    *TIM1_CCR2 = PWMcontrol;
    PWMcontrol = PWM_3;
    PWMcontrol = constrain(PWM_3,0,Timperiod);
    *TIM1_CCR3 = PWMcontrol;
    PWMcontrol = PWM_4;
    PWMcontrol = constrain(PWM_4,0,Timperiod);
    *TIM1_CCR4 = PWMcontrol;
    // test= *TIM1_CNT;
// Fr=test;
    //   if (test >=PWMcontrol)
     //   {Q=false;}
     //   else
//    {Q=true;}
    _gtv2 =  (analogRead (197));
}
Последний раз редактировалось asvhmao 14.05.2024{, 19:19}, всего редактировалось 1 раз.

asvhmao
Рядовой
Сообщения: 16
Зарегистрирован: 15.03.2024{, 00:10}
Репутация: 4
Откуда: Краснодар
Имя: сергей

stm32f103c8(b) много вопросов

#2

Сообщение asvhmao » 04.05.2024{, 02:38}

Решил по играть с пользовательским блоком "энкодер" и с EEPROM stm32. Раз девятая версия позволяет такие радости, почему бы и не попробовать?
По быстрому наколхозил картинку, типо менюшки с тремя переменными памяти, для предзагруки настроек энкодера. Проверка результата показала, что память грузит правильно, а два других микса по очерёдности уехали в конец коридора, из-за чего настройки первого меню убежали на второе, второго на третье и так по кругу.
Лёгким движением Ctrl+C, Ctrl+V, в тексте ардуины, поменял очерёдность и всё заработало как и задумывалось.

Прикреплённый первый файл с этой ошибкой.
Текст под спойлером, с выделенными фрагментами, это то что я поменял местами очерёдность из проекта.
.
Энкодер_EEPROM.jpg
.
Энкодер_EEPROM.flp
(1.31 МБ) 6 скачиваний
СпойлерПоказать

Код: Выделить всё

#include "flprogUtilites.h"
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include "STM32encoder.h"
#include "flprogInternalEEPROM.h"
FLProgInternalEEPROM InternalEEPROM_41185707(7, 247);
LiquidCrystal_I2C _lcd1(0x27, 16, 2);
int _dispTempLength1=0;
boolean _isNeedClearDisp1;
bool en_enc;
int16_t Set;
uint8_t Set_dir;
int16_t Set_min;
int16_t Set_max;
bool en_Set;
int16_t pos_enc;
int16_t my_var;
bool Short_press;
bool Long_press;
STM32encoder enc(TIM2);
int16_t myVar= 0;
int16_t _gtv2;
int16_t _gtv3;
bool _gtv4;
int16_t _gtv6;
bool _gtv7;
int16_t _gtv8;
int16_t _gtv9;
bool _gtv10;
bool _gtv11;
bool _gtv13;
bool _dms1Q0 = 0;
bool _dms1Q1 = 0;
bool _dms1Q2 = 0;
int16_t _disp5oldLength = 0;
int16_t _disp1oldLength = 0;
bool _dms2Q0 = 0;
bool _dms2Q1 = 0;
bool _dms2Q2 = 0;
int16_t _disp4oldLength = 0;
int16_t _mux3;
int16_t _mux1;
int16_t _disp2oldLength = 0;
int16_t _mux2;
int16_t _disp3oldLength = 0;
bool _count1I = 0;
int16_t _count1_Value = 0;
void setup()
{
    Wire.begin();
    delay(10);
    InternalEEPROM_41185707.setIntegerStartValue(1, 0);
    InternalEEPROM_41185707.setIntegerStartValue(3, 2);
    InternalEEPROM_41185707.setIntegerStartValue(5, 23);
    InternalEEPROM_41185707.setSkippingEvents(0);
    InternalEEPROM_41185707.begin();
    _lcd1.init();
    _lcd1.backlight();
    enc.bind(&myVar, 1, 0, 100);
    enc.setButton(PA2);
}
void loop()
{
    InternalEEPROM_41185707.pool();
    if (_isNeedClearDisp1) 
    {
        _lcd1.clear();
        _isNeedClearDisp1= 0;
    }
    //Плата:1
    if (!(0)) 
    {
        _dispTempLength1 = ((((String("M ")) + ((String(_gtv6, DEC)))))).length();
        if (_disp1oldLength > _dispTempLength1) 
        {
            _isNeedClearDisp1 = 1;
        }
        _disp1oldLength = _dispTempLength1;
        _lcd1.setCursor(0, 0);
        _lcd1.print((((String("M ")) + ((String(_gtv6, DEC))))));
    }
     else 
    {
        if (_disp1oldLength > 0) 
        {
            _isNeedClearDisp1 = 1;
            _disp1oldLength = 0;
        }
    }
    if((_gtv6) == 0) 
    {
        _mux1 = ((InternalEEPROM_41185707.readInteger(1)));
    }
    if((_gtv6) == 1) 
    {
        _mux1 = ((InternalEEPROM_41185707.readInteger(3)));
    }
    if((_gtv6) == 2) 
    {
        _mux1 = ((InternalEEPROM_41185707.readInteger(5)));
    }
    _gtv9 = _mux1;

  //  =================================================================

 if((_gtv6) == 0) 
    {
        _mux2 = 0;
    }
    if((_gtv6) == 1) 
    {
        _mux2 = -10;
    }
    if((_gtv6) == 2) 
    {
        _mux2 = 5;
    }
    _gtv3 = _mux2;

//===================================================================

      if((_gtv6) == 0) 
    {
        _mux3 = 100;
    }
    if((_gtv6) == 1) 
    {
        _mux3 = 10;
    }
    if((_gtv6) == 2) 
    {
        _mux3 = 50;
    }
    _gtv2 = _mux3;  

//  =================================================================  
    en_enc = !(0);
    Set = _gtv9;
    Set_dir = 1;
    Set_min = _gtv3;
    Set_max = _gtv2;
    en_Set = _gtv7;
    if(en_enc) 
    {
        Short_press = 0;
        Long_press = 0;
        switch(enc.button())
        {
            case BTN_EVT_CLICK:
            Short_press = 1;
            break;
            case BTN_EVT_LONG:
            Long_press = 1;
            break;
        }
        if (en_Set) 
        {
            myVar = Set;
            my_var = myVar;
            enc.bind(&myVar, Set_dir, Set_min, Set_max);
        }
        if (enc.isUpdated())
        {
            pos_enc = enc.pos();
            my_var = myVar;
        }
    }
    _gtv4 = Long_press;
    _gtv7 = Short_press;
    _gtv8 = my_var;
    if (!(0)) 
    {
        _dispTempLength1 = ((((String("S ")) + ((String(_gtv8, DEC)))))).length();
        if (_disp2oldLength > _dispTempLength1) 
        {
            _isNeedClearDisp1 = 1;
        }
        _disp2oldLength = _dispTempLength1;
        _lcd1.setCursor(7, 0);
        _lcd1.print((((String("S ")) + ((String(_gtv8, DEC))))));
    }
     else 
    {
        if (_disp2oldLength > 0) 
        {
            _isNeedClearDisp1 = 1;
            _disp2oldLength = 0;
        }
    }

//=======================================================================================    
//    if((_gtv6) == 0) 
//    {
//        _mux2 = 0;
//    }
//    if((_gtv6) == 1) 
//    {
//        _mux2 = -10;
//    }
//    if((_gtv6) == 2) 
//    {
//        _mux2 = 5;
//    }
//    _gtv3 = _mux2;
//=======================================================================================
    
    if (_gtv10) 
    {
        InternalEEPROM_41185707.saveInteger(1, ((_gtv8)));
    }
    if (_gtv11) 
    {
        InternalEEPROM_41185707.saveInteger(3, ((_gtv8)));
    }    
    if (_gtv13) 
    {
        InternalEEPROM_41185707.saveInteger(5, ((_gtv8)));
    }
 //=======================================================================================           
    
    if((_gtv6 == 0))
    {
        _dms2Q0 = 1;
    }
    else 
    {
        _dms2Q0 = 0;
    }
    if((_gtv6 == 1))
    {
        _dms2Q1 = 1;
    }
    else 
    {
        _dms2Q1 = 0;
    }
    if((_gtv6 == 2))
    {
        _dms2Q2 = 1;
    }
    else 
    {
        _dms2Q2 = 0;
    }
    if (_dms2Q2) 
    {
        _dispTempLength1 = ((((String("E2 ")) + ((String(((InternalEEPROM_41185707.readInteger(5))), DEC)))))).length();
        if (_disp5oldLength > _dispTempLength1) 
        {
            _isNeedClearDisp1 = 1;
        }
        _disp5oldLength = _dispTempLength1;
        _lcd1.setCursor(0, 1);
        _lcd1.print((((String("E2 ")) + ((String(((InternalEEPROM_41185707.readInteger(5))), DEC))))));
    }
     else 
    {
        if (_disp5oldLength > 0) 
        {
            _isNeedClearDisp1 = 1;
            _disp5oldLength = 0;
        }
    }
    if (_dms2Q1) 
    {
        _dispTempLength1 = ((((String("E1 ")) + ((String(((InternalEEPROM_41185707.readInteger(3))), DEC)))))).length();
        if (_disp4oldLength > _dispTempLength1) 
        {
            _isNeedClearDisp1 = 1;
        }
        _disp4oldLength = _dispTempLength1;
        _lcd1.setCursor(0, 1);
        _lcd1.print((((String("E1 ")) + ((String(((InternalEEPROM_41185707.readInteger(3))), DEC))))));
    }
     else 
    {
        if (_disp4oldLength > 0) 
        {
            _isNeedClearDisp1 = 1;
            _disp4oldLength = 0;
        }
    }
    if (_dms2Q0) 
    {
        _dispTempLength1 = ((((String("E0 ")) + ((String(((InternalEEPROM_41185707.readInteger(1))), DEC)))))).length();
        if (_disp3oldLength > _dispTempLength1) 
        {
            _isNeedClearDisp1 = 1;
        }
        _disp3oldLength = _dispTempLength1;
        _lcd1.setCursor(0, 1);
        _lcd1.print((((String("E0 ")) + ((String(((InternalEEPROM_41185707.readInteger(1))), DEC))))));
    }
     else 
    {
        if (_disp3oldLength > 0) 
        {
            _isNeedClearDisp1 = 1;
            _disp3oldLength = 0;
        }
    }
 //=============================================================   
//    if (_gtv13) 
//    {
//        InternalEEPROM_41185707.saveInteger(5, ((_gtv8)));
//    }
//===================================================================        
    
//  if((_gtv6) == 0) 
//    {
//        _mux3 = 100;
//    }
//    if((_gtv6) == 1) 
//    {
//        _mux3 = 10;
//    }
//    if((_gtv6) == 2) 
//    {
//        _mux3 = 50;
//    }
//    _gtv2 = _mux3; 

//======================================================================    
    
    if((_gtv6 == 0))
    {
        _dms1Q0 = _gtv4;
    }
    else 
    {
        _dms1Q0 = 0;
    }
    if((_gtv6 == 1))
    {
        _dms1Q1 = _gtv4;
    }
    else 
    {
        _dms1Q1 = 0;
    }
    if((_gtv6 == 2))
    {
        _dms1Q2 = _gtv4;
    }
    else 
    {
        _dms1Q2 = 0;
    }
    _gtv13 = _dms1Q2;
    _gtv11 = _dms1Q1;
    _gtv10 = _dms1Q0;
    if (_gtv7)
    {
        if (! _count1I) 
        {
            _count1I = 1;
            _count1_Value = _count1_Value + 1;
        }
    }
     else 
    {
        _count1I = 0;
    }
    if(_count1_Value >= 3) 
    {
        _count1_Value = 0;
    }
    _gtv6 = _count1_Value;
}
.
Далее я решил, в проекте с ошибкой, перед выводом en_Set поставить кастыль в виде стандартного блока FTrig, удивительно, но опять же всё заработало как и должно было.
.
.
Энкодер_EEPROM_2.jpg
.
.
IMG_20240504_024722.jpg
.
Энкодер_EEPROM_2.flp
(1.33 МБ) 12 скачиваний
.
Короткое описание тестового проекта:

При старте, в энкодере настройки по умолчанию, когда собирается проект. Шаг 1, мин 0, мах 100, позиция 0.
При коротком нажатии кнопки энкодера переходим в первое меню, с настройками мин -10, мах 10, позиция настроена в памяти EEPROM Set_E1, если правильно помню, то вроде 5 записывал.
Следующее короткое нажатие переход во второе меню, мин 5, мах 50, значение установки позиции Set_E2.
Третье нажатие возвращает в нулевое меню, а т.к. настройки начальные стёрли, то прописываются с помощью блоков Мих заново. Блок Set_E0 не обязателен, ставил просто для проверки, можно "0" прописать или использовать как третье меню, но уже без стартового.

Запись в память производится длинным нажатием кнопки энкодера.

Значения взяты произвольные, для примера, к реальным устройствам отношения не имеет.


====================================================================================
.
Прикреплю исходный энкодер, вместе с ссылкой на автора блока.
.
Энкодер_0.jpg
.
viewtopic.php?f=74&t=8461#p129506
.
Энкодер STM32.flp
(498.04 КБ) 3 скачивания
.

Решил немного расширить возможности.
Вполне себе полезная в хозяйстве деталька получилась. Добавил предварительную загрузку значений.
На выходе есть выводы "+" и "-", как дополнительная опция. Если крутить умеренно, работает нормально, при быстром вращении есть пропуски импульсов "+" и "-", относительно значений счётчика таймера. А может и счётчики в проекте не успевают зафиксировать быстрое вращение, глубоко не копал. В момент запуска МК, есть один ложный импульс вверх. Импульсы "+" и "-" не зависят от значения установок, при en_enc = 1, работают постоянно вместе с физическим энкодером.
.
Энкодер_plus_minus_3.jpg
.
На картинке 50 щелчков было вверх, 30 вниз, на счётчике остаток 20. Всё сходится.
.
IMG_20240509_235312.jpg
.
Энкодер_P_M_2.flp
(1011.38 КБ) 5 скачиваний
СпойлерПоказать

Код: Выделить всё

#include "flprogUtilites.h"
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include "STM32encoder.h"
LiquidCrystal_I2C _lcd1(0x27, 16, 2);
int _dispTempLength1=0;
boolean _isNeedClearDisp1;
bool en_enc;
int16_t Set;
uint8_t Set_dir;
int16_t Set_min;
int16_t Set_max;
bool en_Set;
int16_t pos_enc;
int16_t my_var;
bool Short_press;
bool Long_press;
bool Plus;
bool Minus;
STM32encoder enc(TIM2);
int16_t myVar= 0;
bool reg_dir= 0;
bool reg_Plus= 0;
bool reg_Minus= 0;
bool _gtv1;
int16_t _disp3oldLength = 0;
int16_t _disp2oldLength = 0;
int16_t _disp1oldLength = 0;
bool _count2I = 0;
int16_t _count2_Value = 0;
bool _count1I = 0;
int16_t _count1_Value = 0;
void setup()
{
    Wire.begin();
    delay(10);
    _lcd1.init();
    _lcd1.backlight();
    enc.bind(&myVar, 1, 0, 100);
    enc.setButton(PA2);
}
void loop()
{
    if (_isNeedClearDisp1) 
    {
        _lcd1.clear();
        _isNeedClearDisp1= 0;
    }
    //Плата:1
    en_enc = (!(0));
    Set = 12;
    Set_dir = 1;
    Set_min = 0;
    Set_max = 100;
    en_Set = _gtv1;
    if(en_enc)
    {
        Short_press = 0;
        Long_press = 0;
        switch(enc.button())
        {
            case BTN_EVT_CLICK:
            Short_press = 1;
            break;
            case BTN_EVT_LONG:
            Long_press = 1;
            break;
        }
        if (en_Set)
        {
            myVar = Set;
            my_var = myVar;
            enc.bind(&myVar, Set_dir, Set_min, Set_max);
        }
        reg_Plus = 0;
        reg_Minus = 0;
        if (enc.isUpdated())
        {
            pos_enc = enc.pos();
            my_var = myVar;
            reg_dir = enc.dir();
            if (!(en_Set))
            {
                if (reg_dir)
                {
                    reg_Plus = 1;
                }
                if (!(reg_dir))
                {
                    reg_Minus = 1;
                }
            }
        }
        			Plus = reg_Plus;
        		      Minus = reg_Minus;
    }
    if (Minus)
    {
        if (! _count2I) 
        {
            _count2I = 1;
            _count2_Value = _count2_Value + 1;
        }
    }
     else 
    {
        _count2I = 0;
    }
    if (!(0)) 
    {
        _dispTempLength1 = (((String(_count2_Value, DEC)))).length();
        if (_disp3oldLength > _dispTempLength1) 
        {
            _isNeedClearDisp1 = 1;
        }
        _disp3oldLength = _dispTempLength1;
        _lcd1.setCursor(4, 1);
        _lcd1.print(((String(_count2_Value, DEC))));
    }
     else 
    {
        if (_disp3oldLength > 0) 
        {
            _isNeedClearDisp1 = 1;
            _disp3oldLength = 0;
        }
    }
    if (Plus)
    {
        if (! _count1I) 
        {
            _count1I = 1;
            _count1_Value = _count1_Value + 1;
        }
    }
     else 
    {
        _count1I = 0;
    }
    if (!(0)) 
    {
        _dispTempLength1 = (((String(_count1_Value, DEC)))).length();
        if (_disp2oldLength > _dispTempLength1) 
        {
            _isNeedClearDisp1 = 1;
        }
        _disp2oldLength = _dispTempLength1;
        _lcd1.setCursor(4, 0);
        _lcd1.print(((String(_count1_Value, DEC))));
    }
     else 
    {
        if (_disp2oldLength > 0) 
        {
            _isNeedClearDisp1 = 1;
            _disp2oldLength = 0;
        }
    }
    _gtv1 = Short_press;
    if (!(0)) 
    {
        _dispTempLength1 = (((String(my_var, DEC)))).length();
        if (_disp1oldLength > _dispTempLength1) 
        {
            _isNeedClearDisp1 = 1;
        }
        _disp1oldLength = _dispTempLength1;
        _lcd1.setCursor(0, 0);
        _lcd1.print(((String(my_var, DEC))));
    }
     else 
    {
        if (_disp1oldLength > 0) 
        {
            _isNeedClearDisp1 = 1;
            _disp1oldLength = 0;
        }
    }
}

asvhmao
Рядовой
Сообщения: 16
Зарегистрирован: 15.03.2024{, 00:10}
Репутация: 4
Откуда: Краснодар
Имя: сергей

stm32f103c8(b) много вопросов

#3

Сообщение asvhmao » 14.05.2024{, 19:10}

Вопрос скорее самому себе, но всё же, может кто и присоединится к беседе.
Снова таймер, пусть будет тот же tim1, у него есть возможность предзагрузки и прерывания, по этому поводу.
Как это всё можно скрестить с flprog, stm32 и ардуино id?
Примеры с прерыванием, от изменения состояния на входе выводов, тоже лишними не будут.

По игрался со штатным блоком генератора, командааппаратом и с пользовательским блоком таймера, ничего, вроде даже что-то рисует.

.
3g5k3kem8e.jpg

ecoins
Полковник
Сообщения: 2973
Зарегистрирован: 12.02.2016{, 11:40}
Репутация: 455
Откуда: Шатура
Имя: Энвер

stm32f103c8(b) много вопросов

#4

Сообщение ecoins » 14.05.2024{, 20:50}

asvhmao писал(а):
14.05.2024{, 19:10}
Вопрос скорее самому себе, но всё же, может кто и присоединится к беседе.
Снова таймер, пусть будет тот же tim1, у него есть возможность предзагрузки и прерывания, по этому поводу.
Как это всё можно скрестить с flprog, stm32 и ардуино id?
Примеры с прерыванием, от изменения состояния на входе выводов, тоже лишними не будут.
Присоединюсь к беседе.
Таймеры вещь полезная и эффективная.
В случае с FLProg предстоит ответить на вопрос - это специализированный блок только для STM32 или другие контроллеры (AVR,ESP32,RP2040) тоже должны иметь аналогичные функции?
ESP32 (в разных разное количество таймеров) - таймеры используются в PWM. Надо предусмотреть конфликтные ситуации или выбор таймеров с захватом их требуемой функцией.
В STM32 часть таймеров задействованы в системных функциях и надо бы поисследовать ядра Arduino - на разных STM32 таймеры могут быть задействованы по разному.
---------------------------
И вопрос - а затем задействовать таймеры. Если для точности измерения времени, то есть уже задействованные ядром таймеры, они предоставляют достаточно большой набор возможностей.
Чтобы гарантировать точность периода управления например шаговым двигателем - да, наверное.
Чтобы избежать тормознутость блоков и библиотек - это не всегда поможет и полезно понимание работы каналов коммуникаций и протоколов обмена, там могут быть и конфликты...
----------------------------
STM32 разные давно тестируем - в явной форме прерывания от таймера не столь и востребованы.
Прерывания от входов - они реализованы в блоках или в библиотеках.
--------------------------
FLProg по идеологии близок к организации программируемых логических контроллеров (PLC)- там свои сложившиеся подходы к реализации проектов.
В отличии от распространенных PLC среда FLProg предоставляет могоплатформенность, открытость кода и возможность реализации библиотек и алгоритмов на C++.
Последнее подразумевает неплохое знание аппаратных возможностей процессора и его программного ядра в Arduino IDE.
---------------------------
Беседу поддержал.
С уважением, ecoins.

asvhmao
Рядовой
Сообщения: 16
Зарегистрирован: 15.03.2024{, 00:10}
Репутация: 4
Откуда: Краснодар
Имя: сергей

stm32f103c8(b) много вопросов

#5

Сообщение asvhmao » 14.05.2024{, 23:01}

ecoins, рад видеть вас в этом разделе и спасибо за поддержку беседы.

В данном примере буду применять только МК stm32f103cb(8), других нет и пока не планируются.
ecoins писал(а):
14.05.2024{, 20:50}
И вопрос - а затем задействовать таймеры.
Например таймер 1, у данной линейки МК, очень хорошо справляется с управлением трёхфазных двигателей и не только. (по картинке с ЛА это видно)
Частота предзагрузки таймера должна быть жёстко связана по времени с выбором табличного значения.
Задача для flprog нестандартная, но при определённых знаниях С++ (которыми пока не владеют) и покурив документацию на МК, думаю осуществима.
Далее есть у двигателей датчик определения положения ротора. На вход датчика подаётся два синусоидальных сигнала, с разницей по фазе в 90°. На выходе, в зависимости от положения ротора, плавающая по фазе третья синусоида. Период которой нужно ловить, относительно первых двух сигналов.
Ну это так к слову, не забивайте себе сильно голову. Цель сего действия ознакомление с возможностями среды и МК, а не готовое изделие, хотя....
Задачка настроить прерывание, обработать его и выполнить какое-то действие. А остальные телодвижения пусть таймеры делают, работа у них такая.
Самое частое прерывание будет с периодом в 200 мкс.

ecoins писал(а):
14.05.2024{, 20:50}
Прерывания от входов - они реализованы в блоках или в библиотеках.
Можно посмотреть примеры кода или названия блоков и библиотек?

========================================

Посмотрел "скоростной счётчик" в стандартных блоках, если не ошибаюсь, там изначально задействован таймер 2. Если буду одновременно применять его с пользовательским блоком "энкодер", который выше в сообщениях и у него по умолчанию так же стоит таймер 2, то на выходе получим кашу, правильно?
При компиляции этой каши, flprog молча отправил всё в ардуину, а ардуино выдала кучу ошибок (детально не разбирался пока с ними).

P.s. без каши дуина на скоростной счётчик тоже ошибку выдала, по позже буду разбираться, может я что-то не то сделал.
Последний раз редактировалось asvhmao 15.05.2024{, 03:46}, всего редактировалось 2 раза.

ecoins
Полковник
Сообщения: 2973
Зарегистрирован: 12.02.2016{, 11:40}
Репутация: 455
Откуда: Шатура
Имя: Энвер

stm32f103c8(b) много вопросов

#6

Сообщение ecoins » 15.05.2024{, 02:34}

asvhmao писал(а):
14.05.2024{, 23:01}
Можно посмотреть примеры кода или названия блоков и библиотек?
1.Прерывания в FLProg по входам реализованы в блоке скоростного счетчика. Он делался давно для контроллеров AVR, код реализован не в отдельной библиотеке (сейчас так делается), а самом блоке. Сам код можно увидеть в скетче от проекта FLProg с блоком скоростного счетчика. На практике пробовал это блок давно - очень понравился своей функциональностью. Разработчик адаптирует его в новой версии (он важен для профессионального применения) и проведет испытания на STM32. Направлению STM32 разработчик уделяет особое внимание и считает эти контроллеры наиболее приемлемыми для профессионального использования.
2.В реализации ecoins прерывания по входу реализованы в блоке ультразвукового дальномера HC-SR04. Работает на всех платформах в том числе и на STM32. Есть особенности с последними чипами ESP32 - для них продолжается меняться ядро, в некоторых случаях критически. Ждем когда они окончательно перейдут на версию 3.x (пока это сделали только в Arduino IDE 2.x).
3.Ваш проект с энкодером скачал посмотрю. Если Вы продолжите проявлять практический интерес к STM32, ecoins постарается подключиться к этой работе и объединить усилия. У меня лично много накопившихся обязательств по системной работе, но постараюсь уделять внимание Вашей работе.
Спасибо.
С уважением, ecoins.

ecoins
Полковник
Сообщения: 2973
Зарегистрирован: 12.02.2016{, 11:40}
Репутация: 455
Откуда: Шатура
Имя: Энвер

stm32f103c8(b) много вопросов

#7

Сообщение ecoins » 15.05.2024{, 02:39}

asvhmao писал(а):
14.05.2024{, 23:01}
ecoins, рад видеть вас в этом разделе и спасибо за поддержку беседы.
Собрали и тестируем небольшую партию контроллеров FLProg на STM32
viewtopic.php?f=247&t=8064&start=1000#p129587
Пока всё очень и очень хорошо.

asvhmao
Рядовой
Сообщения: 16
Зарегистрирован: 15.03.2024{, 00:10}
Репутация: 4
Откуда: Краснодар
Имя: сергей

stm32f103c8(b) много вопросов

#8

Сообщение asvhmao » 15.05.2024{, 22:24}

Посмотрел разные блоки, включая сегодняшний от Айдара. У всех свои наименования. Если правильно понимаю, то это каждый сам себе библиотеки писал и к ним потом привязывал названия? Вторая строчка под сомнением, это не стандарт обращения к активации прерывания, по номеру, в данной версии ардуины?
MyTim9555176->attachInterrupt(func_tim9555176);

attachInterrupt(digitalPinToInterrupt (192), _SCT_1coutFunction, FALLING);

attachInterrupt(z_135224008.numIRQ, RT_HW_IRQ_SR04_handler_135224008,CHANGE);
.
==================================================================
.
ecoins писал(а):
15.05.2024{, 02:34}
Если Вы продолжите проявлять практический интерес к STM32, ecoins постарается подключиться к этой работе и объединить усилия. У меня лично много накопившихся обязательств по системной работе, но постараюсь уделять внимание Вашей работе.
Желание и интерес есть, времени и возможности заниматься не всегда бывает в достаточном объёме.
В любом случае, уже Вам спасибо за такую содержательную беседу.

aidar_i
Полковник
Сообщения: 3157
Зарегистрирован: 24.12.2016{, 16:55}
Репутация: 688
Откуда: Уфа
Имя: Айдар
Контактная информация:

stm32f103c8(b) много вопросов

#9

Сообщение aidar_i » 16.05.2024{, 08:01}

asvhmao писал(а):
15.05.2024{, 22:24}
MyTim9555176->attachInterrupt(func_tim9555176);

attachInterrupt(digitalPinToInterrupt (192), _SCT_1coutFunction, FALLING);

attachInterrupt(z_135224008.numIRQ, RT_HW_IRQ_SR04_handler_135224008,CHANGE);
Первая строка прерывание по таймеру, вторая и третья внешние прерывания

asvhmao
Рядовой
Сообщения: 16
Зарегистрирован: 15.03.2024{, 00:10}
Репутация: 4
Откуда: Краснодар
Имя: сергей

stm32f103c8(b) много вопросов

#10

Сообщение asvhmao » 16.05.2024{, 15:20}

aidar_i, это то понятно. Непонятно что точно в самом железе происходит, на самом низком уровне.
Из блока, который вчера выложили, взял эти прерывания, скрестил с блоком таймера из первого сообщения, прилепил к командоаппарату. Таблица от прерывания работает, на фиксированных значениях предделителя таймера. Само значение частоты, на лету, изменить пока не получилось. С подключением дисплея тоже всё в ступоре и крякозябла на выходе.

Картинка работающего варианта. Верхние три пары - ШИМ по таблице. Самый нижний сигнал это:
void func_tim9555176()
{
Out_118167935_9555176 = !Out_118167935_9555176;
}
.
Sin_2.jpg
.

.
Sin_3.jpg
.
STM_32_sin_3.rar
(24.06 КБ) 5 скачиваний
============================================================================

Решил в обработчик прерывания таймера положить считалочку до 48. Теперь таблица в самом таймере и шагает по значению этой считалочки. С экраном и энкодером пока не проверял.
.
Sin_4.jpg
.
Tim1_1f_прерывания.flp
(563.37 КБ) 0 скачиваний
.
STM_32_sin_4.rar
(45.11 КБ) 0 скачиваний
.
СпойлерПоказать

Код: Выделить всё

#include "flprogUtilites.h"
int16_t F_set;
int16_t Timperiod;
bool Q;
int16_t Out1[]  =  {255, 254, 251, 245, 238, 229, 218, 205, 191, 176, 160, 144, 128, 111, 95, 79, 64, 50, 37, 26, 17, 10, 4, 1, 0, 1, 4, 10, 17, 26, 37, 50, 64, 79, 95, 111, 128, 144, 160, 176, 191, 205, 218, 229, 238, 245, 251, 254};
int16_t step_1= 0;
bool Out_118167935_60391659;
int oldT60391659= 0;
HardwareTimer *MyTim60391659= new HardwareTimer(TIM1);
bool q60391659;
#define RCC_BASE 0x40021000

#define RCC_APB2ENR ((volatile uint32_t *)(RCC_BASE+0x18))

#define GPIOA_BASE 0x40010800

#define GPIOA_CRH ((volatile uint32_t *)(GPIOA_BASE+0x04))

#define GPIOB_BASE 0x40010C00

#define GPIOB_CRH ((volatile uint32_t *)(GPIOB_BASE+0x04))

#define TIM1_BASE 0x40012C00

#define TIM1_CNT ((volatile uint32_t *)(TIM1_BASE+0x24))

#define TIM1_CR1 ((volatile uint32_t *)(TIM1_BASE+0x00))

#define TIM1_CCMR1 ((volatile uint32_t *)(TIM1_BASE+0x18))

#define TIM1_CCMR2 ((volatile uint32_t *)(TIM1_BASE+0x1C))

#define TIM1_CCER ((volatile uint32_t *)(TIM1_BASE+0x20))

#define TIM1_PSC ((volatile uint32_t *)(TIM1_BASE+0x28))

#define TIM1_ARR ((volatile uint32_t *)(TIM1_BASE+0x2C))

#define TIM1_CCR1 ((volatile uint32_t *)(TIM1_BASE+0x34))

#define TIM1_BDTR ((volatile uint32_t *)(TIM1_BASE+0x44))

uint16_t PWMcontrol= 0;   
#define TIM1_CCER ((volatile uint32_t *)(TIM1_BASE+0x20))

#define TIM1_PSC ((volatile uint32_t *)(TIM1_BASE+0x28))

#define TIM1_ARR ((volatile uint32_t *)(TIM1_BASE+0x2C))

#define TIM1_CCR1 ((volatile uint32_t *)(TIM1_BASE+0x34))

#define TIM1_BDTR ((volatile uint32_t *)(TIM1_BASE+0x44))

bool _gtv1;


void setup()
{

pinMode(17, OUTPUT); 
digitalWrite(17, 0); 



 
   MyTim60391659->pause(); // останавливаем таймер перед настройкой
      MyTim60391659->attachInterrupt(func_tim60391659);
    MyTim60391659->resume();

  *RCC_APB2ENR |= 0x0000080D;      

  *GPIOA_CRH &= 0xFFFFFFF0;
  *GPIOA_CRH |= 0x0000000B;        
  *GPIOB_CRH &= 0xFF0FFFFF;
  *GPIOB_CRH |= 0x00B00000; 
  *TIM1_ARR = Timperiod;               
  *TIM1_CCMR1 = 0x00006868;     
  *TIM1_CCMR2 = 0x00006868;
  *TIM1_CCER = 0x00001555;       
  *TIM1_PSC = F_set;                    
  *TIM1_BDTR = 0x000080E0;           
  *TIM1_CR1 = 0x00000061;           
  *TIM1_CCR1 = 0x5;                 
  

                
  



}
void loop()
{







//Плата:1
F_set = 57;
Timperiod = 255;
	*TIM1_PSC = F_set;
	*TIM1_ARR = Timperiod;    


 Q = Out_118167935_60391659;
_gtv1 = Q;
digitalWrite(17, _gtv1);







}

void func_tim60391659()
{
    Out_118167935_60391659 = !Out_118167935_60391659;

  if (Out_118167935_60391659)
    {
      step_1 = step_1 + 1;
     if(step_1 < 0) 
       {step_1 = 0;}
     if(step_1 >  47) 
       {step_1 = 0;}
       PWMcontrol = Out1[step_1];
*TIM1_CCR1 = PWMcontrol;  
    }
}


Ответить

Вернуться в «STM32»