Dimmer на STM32

Baks
Baks аватар
Offline
Зарегистрирован: 11.01.2016

Всем добра!

нужно управлять диммером на СТМ32 контроллере. пишу в ардуино IDE.

накидал скетч первый серьезный, и как не странно не работает :)

схема диммера собственного изготовления такая https://forum.cxem.net/uploads/monthly_2018_04/dimm.png.ad23626ebc703607bc55c16a90c08521.png

только с диодным мостом и pc817

вот скетч 

volatile int count = 0;
volatile int flag = 0;
volatile int dim = 0
 //int old_flag = 0

#define Z_PIN PA1 // пин на линии EXTI1 dim 
#define Triak_PIN PA6
void setup()
{
  pinMode(Z_PIN, INPUT_PULLDOWN);
  pinMode(Triak_PIN, OUTPUT); //  

  Timer3.pause(); // останавливаем таймер перед настройкой
  Timer3.setPeriod(40); // время в микросекундах (500мс)
  Timer3.attachInterrupt(TIMER_UPDATE_INTERRUPT, func_tim_3); // активируем прерывание по таймеру
  Timer3.refresh(); // обнулить таймер 
  Timer3.resume(); // запускаем таймер
  
    attachInterrupt(Z_PIN, func_interrup, FALLING); // инициализация  прерывания zero-cross
}

void loop() 
{
  digitalWrite(Triak_PIN, flag);	
  dim = 110;
 // dim = dim + 1;
}

void func_tim_3() // обработчик прерывания по переполнению таймера
{
	count = count +1;
   //digitalWrite(Triak_PIN,1);
   if (count>= dim)
     {
	   flag = 1;
       Timer3.pause(); // останавливаем таймер
     }
	 else
	 {
	   flag = 0;
	 }
} 

void func_interrup() // обработчик   прерывания zero-cross
{
  count = 0;
  Timer3.refresh(); // обнулить таймер 
  Timer3.resume(); // запускаем таймер
}

как должен работать:

1. ловим переход через 0, включаем таймер.

2. таймер тикает через с интервалом 40 микросекунд, а в обработчике увеличиваем счетчик.

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

4. в лупе при поднятом флаге открываем семистр и отключаем таймер,

5. ждем переход через 0 и снова включаем таймер когда сработает внешнее прерывание.

Цикл повторяется.

вроде ничего сложного и все понятно, но не работает.... питаю плату диммера от 3.3в. если подать 3.3в на семистр , лампа светит.  задаю дим число до 146 лампа светит, а если задаю 147  и более то не светит совсем

Прошу помощи..... 

Komandir
Онлайн
Зарегистрирован: 18.08.2018

ИМХО что то с задержками - пока таймер отсчитывает, приходит прерывание от детектора нуля и таймер обнуляется. 

Baks
Baks аватар
Offline
Зарегистрирован: 11.01.2016

никто не запускал димер на плате стм32  ?

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

кто знает отзавитесь

b707
Offline
Зарегистрирован: 26.05.2017

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

а насчет того, почему dim 147 и выше не работает - думаю Komandir близок к истине. Вы детектируете ноль по логическому уровню на пине? - это очень неточный метод, LOW на пине не совпадает с нулем на синусоиде

Baks
Baks аватар
Offline
Зарегистрирован: 11.01.2016

да я понимаю что не совпадет, хвостики не в счет. а самое интересное что по такому прицыпу у меня на ардуинке 2 димера работают, один на инкубаторе а второй на брудере уже как 2 года.

а тут в чем засада никк не пойму...

Komandir
Онлайн
Зарегистрирован: 18.08.2018

Осциллограф поможет - надо глянуть как выглядит сигнал.

Baks
Baks аватар
Offline
Зарегистрирован: 11.01.2016

нету ослика:(

вот нашел тут кое что, нашел тему  . люди делают на двух таймерах и вроди как все работает в фоновом режиме. даже код дали. только это совсем дебри для меня/

ссылка не реклама https://www.radiokot.ru/forum/viewtopic.php?f=59&t=133128&sid=dd2254d0fca1da5b217ebcdc33a8aa5c&start=60

Komandir
Онлайн
Зарегистрирован: 18.08.2018

 У СТМ32 очень много вариантов тактирования и в каких попугаях в итоге задается параметр в Timer3.setPeriod(40); не ясно. Причем это может зависеть и от среды, пакета ... ... ...

Baks
Baks аватар
Offline
Зарегистрирован: 11.01.2016

 

взято тут https://istarik.ru/blog/arduino/105.html

Оперируя предделителем и переполнением можно получать различные интервалы времени. Однако если нет желания заморачиваться с подсчётами, то можно функции setPrescaleFactor() и setOverflow() заменить одной функцией — setPeriod(), которая сделает всё сама, ей нужно только указать время в микросекундах …

мкс — микросекунда (1000000мкс = 1сек).

за 1 секунду прерывание срабатывает 100 раз (полуволны)

1 000 000 мкс /100 =10 000 тиков

чтобы получить 256 максимальное значение для регулирования надо 

10 000 тиков /256 = 39.0.... почти 40. вот и вышло отсюда.

получается таймеру надо по 40 мкс натикать 256 раз чтоб поймать следующее прерывание перехода через 0

я правильно это понимаю?

b707
Offline
Зарегистрирован: 26.05.2017

Baks пишет:

я правильно это понимаю?

еще важно понимать. что функция setPeriod() настраивает период не точно, а из имеющихся вариантов Прескалера и счетчика.

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

Timer3.getOverflow() и Timer3.getPrescaleFactor() и выведите в Монитор

Baks
Baks аватар
Offline
Зарегистрирован: 11.01.2016

один добрый человек поделился рабочим кодом для стм32 но с делеями.

попробовал и мой димер не заработал и на нем 

#include <LiquidCrystal_I2C.h>

LiquidCrystal_I2C lcd( 0x27, 16, 2 ); // set the LCD address to 0x27 for a 16 chars and 2 line display

#define AC_LOAD PA0      // PA0
#define ZC      PA1      // PA1
#define BTN_TIME 200

#define BTN_UP PB9
#define BTN_DN PB8

void setup()
{
  Serial.begin( 9600 );

  lcd.init();
  lcd.backlight();
  lcd.setCursor( 0, 1 );
  lcd.print( "Tacho: " );

  // Buttons
  pinMode( BTN_UP, INPUT_PULLUP );
  pinMode( BTN_DN, INPUT_PULLUP );

  // Dimmer
  pinMode( ZC, INPUT ); // Zero-cross
  pinMode( AC_LOAD, OUTPUT ); // Dimmer

  attachInterrupt( ZC, zero_cross_detect, RISING );

  attachInterrupt(  BTN_UP, btn_up, RISING );
  attachInterrupt(  BTN_DN, btn_dn, RISING );
}

unsigned long prev_btn_up = 0;
unsigned long prev_btn_dn = 0;

int dimming = 128;

void zero_cross_detect()
{
  if ( dimming == 128 )
    return;

  //Serial.println( "ZERO Cross" );
  int dimtime = (75 * dimming);  // For 60Hz =>65
  delayMicroseconds( dimtime );    // Off cycle

  digitalWrite( AC_LOAD, HIGH );     // triac firing
  delayMicroseconds( 20 );         // triac On propagation delay (for 60Hz use 8.33)
  /*
    while( digitalRead( PA1 ) == LOW ) {}
  */
  digitalWrite( AC_LOAD, LOW );      // triac Off
}

void btn_up()
{
  unsigned long c_time = millis();

  if ( c_time - BTN_TIME > prev_btn_up )
  {
    dim_up();
    prev_btn_up = c_time;
  }
}

void btn_dn()
{
  unsigned long c_time = millis();

  if ( c_time - BTN_TIME > prev_btn_dn )
  {
    dim_down();
    prev_btn_dn = c_time;
  }
}

int getPercent()
{
  int av = abs(dimming - 128) + 1;
  Serial.println( av );
  return av * 100 / 128;
}

void dim_up()
{
  dimming -= 1;

  if ( dimming < 1 )
    dimming = 1;

  Serial.println( dimming );
  lcd.setCursor( 0, 0 );
  lcd.print( "Power: " + String(getPercent()) + "%" );  
}

void dim_down()
{
  dimming += 1;
  if ( dimming > 128 )
    dimming = 128;

  Serial.println( dimming );
  lcd.setCursor( 0, 0 );
  lcd.print( "Power: " + String(getPercent()) + "%" );
}

void loop()
{
  //dimming = 100;
}

я чуть чуть подправил его (обьявление прерываний было другое) вечером уже попробую вывести на экран да еще и с этим кодом поработаю.

а вообще мысль закралась что я димер питаю от 3.3 воль а паял я его для 5 вольтового, может какой-то резистор не отрабатывает как надо.?

кстати код переписал и тоже не работает, лампа светится 

volatile bool LEDOn10 = 0;
volatile bool LEDOn11 = 0;
volatile bool LEDOn12 = 0;
volatile bool LEDOn13 = 0;
volatile bool LEDOn15 = 0;

volatile int count = 0;

#define Z_PIN PA1 // пин на линии EXTI1 dim 
#define Triak_PIN PA6

void setup()
{
  pinMode(Z_PIN, INPUT_PULLDOWN);
  pinMode(Triak_PIN, OUTPUT); //  

  
  Serial.begin(115200);


  Timer3.setMode(TIMER_CH2, TIMER_OUTPUT_COMPARE);

  Timer3.pause();
  Timer3.setPrescaleFactor(2769);// устанавливаем делитель
  Timer3.setOverflow(260); // счетчик считает от 0 до 14000

  Timer3.setCompare(TIMER_CH2, 120); // сравнение
  Timer3.attachInterrupt(TIMER_CH2, func_1);


  Timer3.attachInterrupt(TIMER_UPDATE_INTERRUPT, func_5); // прерывание по переполнению
  Timer3.resume();
  
  attachInterrupt(Z_PIN, func_interrup, FALLING); // инициализация  прерывания zero-cross
  
}

void loop() 
{}

void func_1(void) 
{ Timer3.pause();
 digitalWrite(Triak_PIN, LOW);  

} 

void func_interrup() // обработчик   прерывания zero-cross
{ 
  digitalWrite(Triak_PIN, HIGH);  
 // count = 0;
  Timer3.refresh(); // обнулить таймер 
  Timer3.resume(); // запускаем таймер
 
}

void func_5(void) 
{
  //Serial.println("Overflow"); 
  digitalWrite(PB13, (LEDOn15 = !LEDOn15));
}

 

nik182
Offline
Зарегистрирован: 04.05.2015

Это ж stm. Тут немножко другая идеалогия, отличная от avr. В лупе только запись в переменную задержки диммера любым способом. Сам диммер работает чисто аппаратно. Алгоритм примерно такой. В прерывании датчика пересечения нуля настраиваем два или четыре канала таймера соответственно если датчик на полу и полную волну. Первый и третий канал на задержку диммера в диапазонах 0-10 мс и 10-20 мс второй и четвёртый каналы на задерку диммера плюс длительность импульса запуска. Запускаем таймер однократно с нуля на длительность на единицу больше максимальной уставки каналов. В прерываниях каналов только управляем портом - первый третий уставливаем выход второй четвёртый снимаем. Для простоты процесса таймер тактируем мегагерцем и соответственно в каналы пишем значения от 1 до 10000 или от 10001 до 20000.

Baks
Baks аватар
Offline
Зарегистрирован: 11.01.2016
#include <TimerOne.h> 
//#include <CyberLib.h> 
volatile uint8_t tic ; 
uint8_t data; 
int startDimPin = 3; //первый диммер 
//int endDimPin = 12; //последний диммер 
int Dimmer; //количество диммеров минус 1 

void setup() { 


  //*********************Настраиваем порты на выход********************** 

 //for ( int i = startDimPin; i <= endDimPin; i++) //пройдемся циклом по портам 
 //{ 
    pinMode (startDimPin, OUTPUT); 
    digitalWrite(startDimPin, LOW); // гасим оответствующий пин 

    Dimmer = 10; //выставим яркость соответствующего диммера в 0 [i - startDimPin]
  //} 
  //CHANGE – прерывание вызывается при любом изменении значения на входе; 
  //RISING – вызов прерывания при изменении уровня напряжения с низкого (Low) на высокий(HIGH) 
  //FALLING – вызов прерывания при изменении уровня напряжения с высокого (HIGH) на низкий (Low) 
  attachInterrupt(0, detect_up, LOW);  // настроить срабатывание прерывания interrupt0 на pin 2 на низкий уровень 
  Timer1.initialize(40);              // Интервал срабатывания таймера в мкс 
  Timer1.attachInterrupt(halfcycle);   //будет вызыватся каждый раз при отсчете заданого времени 
  Timer1.stop(); 
  Serial.begin(115200); //инициализация порта 
  randomSeed(analogRead(0)); //псевдогенератор случайных чисел будет использовать шумы на аналог пин 0 
} 

//********************обработчики прерываний******************************* 
void halfcycle()  //прерывания таймера 
{ 
  tic--;  //счетчик 
 // for ( int i = startDimPin; i <= endDimPin; i++) 
  //{ 
    if (Dimmer  > tic ) 
      digitalWrite(startDimPin, HIGH); //управляем выходом (откроем семистор) 
 // } 
} 

void  detect_up()  // обработка внешнего прерывания. Сработает по переднему фронту 
{ 
  tic = 200;           //обнулить счетчик 
  Timer1.resume();   //запустить таймер 
  attachInterrupt(0, detect_down, HIGH);  //перепрограммировать прерывание на другой обработчик 
} 

void  detect_down()  // обработка внешнего прерывания. Сработает по заднему фронту 
{ 
  Timer1.stop(); //остановить таймер 
 //for ( int i = startDimPin; i <= endDimPin; i++) 
 // { 

    digitalWrite(startDimPin, LOW); 
 // } 
  tic = 200;     //обнулить счетчик 
  attachInterrupt(0, detect_up, LOW); //перепрограммировать прерывание на другой обработчик 

} 

void loop() { 
  { 

//********помигаем первым диммером рандомно******** 
    Dimmer  = random(10, 200); 
    //Задержка для более плавного эффекта мерцания 
    delay(1000); 

  } 
}  

проверил плату диммера, запустил от ардуино и запитал от 3.3в.. все отлично работает

значит плата в порядке, пошел разбираться с  кодом стм-ки

nik182 о если честно то я ничего не понял из вашего сообщения(кроми того что вся архитектура кода не правильная для стм-ки). хотя вам большое спасибо за труд, что ответили... ;

однако  на другом форуме читал следующее что можно сделать работу диммера в фоновом режиме, однако я на стм умею работать ножками дергать, или что-то простое и только в ардуино IDE, вот пытаюсь с таймером немнного разобраться. Но что-то мне подсказывает что в ардуино IDE нет возможности осуществить все что надо для димера.  

поправьте меня если я ошибаюсь?

вот что мне интересное попалось поделюсь.

Это можно сделать полностью аппаратно, 
на двух таймерах. Оба таймера настраиваете на однократную работу
(типа режим одновибратора). Первый таймер запускается по изменению
 уровня на пине (детектор перехода через ноль). Досчитав до нужного числа
 (задержка времени), запускает второй таймер.
 Второй таймер считает до некого числа и сбрасывается.
 Пока второй таймер не равен нулю на выходном пине держится лог.1
 (это тоже аппаратно все настраивается).
 Т.е. второй таймер задает ширину импульса на управляющий вывод симистора.

Будет все само работать, без затрат программных ресурсов.

взято тут https://www.radiokot.ru/forum/viewtopic.php?f=59&t=133128

нуи еще http://www.cyberforum.ru/arm/thread2354383.html

автор темы даже код похожий на мой написал)))

 

nik182
Offline
Зарегистрирован: 04.05.2015
  LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_TIM2);
  LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_GPIOA);
  /**TIM2 GPIO Configuration  
  PA1   ------> TIM2_CH2 
  */
  GPIO_InitStruct.Pin = LL_GPIO_PIN_1;
  GPIO_InitStruct.Mode = LL_GPIO_MODE_FLOATING;
  LL_GPIO_Init(GPIOA, &GPIO_InitStruct);
  
  TIM_InitStruct.Prescaler = 719;
  TIM_InitStruct.CounterMode = LL_TIM_COUNTERMODE_UP;
  TIM_InitStruct.Autoreload = 500;
  TIM_InitStruct.ClockDivision = LL_TIM_CLOCKDIVISION_DIV1;
  LL_TIM_Init(TIM2, &TIM_InitStruct);
  LL_TIM_EnableARRPreload(TIM2);
  LL_TIM_SetOnePulseMode(TIM2, LL_TIM_ONEPULSEMODE_SINGLE);
  LL_TIM_SetTriggerInput(TIM2, LL_TIM_TS_TI2FP2);
  LL_TIM_SetSlaveMode(TIM2, LL_TIM_SLAVEMODE_TRIGGER);
  LL_TIM_CC_DisableChannel(TIM2, LL_TIM_CHANNEL_CH2);
  LL_TIM_IC_SetFilter(TIM2, LL_TIM_CHANNEL_CH2, LL_TIM_IC_FILTER_FDIV1);
  LL_TIM_IC_SetPolarity(TIM2, LL_TIM_CHANNEL_CH2, LL_TIM_IC_POLARITY_RISING);
  LL_TIM_DisableIT_TRIG(TIM2);
  LL_TIM_DisableDMAReq_TRIG(TIM2);
  LL_TIM_SetTriggerOutput(TIM2, LL_TIM_TRGO_UPDATE);
  LL_TIM_EnableMasterSlaveMode(TIM2);


  TIM_InitStruct.Prescaler = 71;
  TIM_InitStruct.CounterMode = LL_TIM_COUNTERMODE_UP;
  TIM_InitStruct.Autoreload = 500;
  TIM_InitStruct.ClockDivision = LL_TIM_CLOCKDIVISION_DIV1;
  LL_TIM_Init(TIM3, &TIM_InitStruct);
  LL_TIM_DisableARRPreload(TIM3);
  LL_TIM_SetClockSource(TIM3, LL_TIM_CLOCKSOURCE_INTERNAL);
  TIM_OC_InitStruct.OCMode = LL_TIM_OCMODE_ACTIVE;
  TIM_OC_InitStruct.OCState = LL_TIM_OCSTATE_DISABLE;
  TIM_OC_InitStruct.OCNState = LL_TIM_OCSTATE_DISABLE;
  TIM_OC_InitStruct.CompareValue = 499;
  TIM_OC_InitStruct.OCPolarity = LL_TIM_OCPOLARITY_LOW;
  LL_TIM_OC_Init(TIM3, LL_TIM_CHANNEL_CH1, &TIM_OC_InitStruct);
  LL_TIM_OC_DisableFast(TIM3, LL_TIM_CHANNEL_CH1);
  LL_TIM_SetOnePulseMode(TIM3, LL_TIM_ONEPULSEMODE_SINGLE);
  LL_TIM_SetTriggerInput(TIM3, LL_TIM_TS_ITR1);
  LL_TIM_SetSlaveMode(TIM3, LL_TIM_SLAVEMODE_TRIGGER);
  LL_TIM_DisableIT_TRIG(TIM3);
  LL_TIM_DisableDMAReq_TRIG(TIM3);
  LL_TIM_SetTriggerOutput(TIM3, LL_TIM_TRGO_RESET);
  LL_TIM_DisableMasterSlaveMode(TIM3);

  LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_GPIOA);
  /**TIM3 GPIO Configuration  
  PA6   ------> TIM3_CH1 
  */
  GPIO_InitStruct.Pin = LL_GPIO_PIN_6;
  GPIO_InitStruct.Mode = LL_GPIO_MODE_ALTERNATE;
  GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_LOW;
  GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL;
  LL_GPIO_Init(GPIOA, &GPIO_InitStruct);
  

Да. Описанный алгоритм взаимодействия таймеров возможен, только надо будет или полуволной датчик пересечения нуля делать или третий таймер припахивать для обеспечения четырёх каналов. Советую поставить генератор кода stm32 cubeMX. Там можно сконфигурировать всю перефирию и сгенерить код, который при добавлении всего одной строчки спокойно компилируется в ардуино иде при установленном аддоне от STM. А драйверами LL можно сделать любые действия с регистрами STM. В любом случае решение этой задачи требует знаний регистров таймеров из мануала. Без их изучения все телодвижения обречены на провал. Я попробую написать, но у меня в планах диммер должен управляться через USB, крутилку резистор, показывать на дисплее угол заданный и температуру, стабилизировать заданную температу объекта. Так что пару недель на это уйдет. Вот что куб сделал для двух таймеров. Посмотреть на названия макросов и подобрать аналогичные для аддона мапла. Сответственно РА1 вход полуволнового датчика пересечения нуля, РА6 выход 500 мкс на тиристор. Если в аддоне мапла не найдется сответственной функции надо эти функции писать на CMSYS или бросить этот путь как невозможный на текущем уровне знаний. 

Baks
Baks аватар
Offline
Зарегистрирован: 11.01.2016

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

#include "Wire.h"
#include "LiquidCrystal_I2C.h"

LiquidCrystal_I2C lcd( 0x27, 16, 2 ); // set the LCD address to 0x27 for a 16 chars and 2 line display

#define AC_LOAD PA0      // PA0
#define ZC      PA1      // PA1
#define BTN_TIME 200

#define BTN_UP PB9
#define BTN_DN PB8

void setup()
{
  Serial.begin( 9600 );

  lcd.begin();
  lcd.backlight();
  lcd.setCursor( 0, 1 );
  lcd.print( "Tacho: " );

  // Buttons
  pinMode( BTN_UP, INPUT );
  pinMode( BTN_DN, INPUT );

  // Dimmer
  pinMode( ZC, INPUT ); // Zero-cross
  pinMode( AC_LOAD, OUTPUT ); // Dimmer

  attachInterrupt( ZC, zero_cross_detect, RISING );

  attachInterrupt(  BTN_UP, btn_up, RISING );
  attachInterrupt(  BTN_DN, btn_dn, RISING );
}

unsigned long prev_btn_up = 0;
unsigned long prev_btn_dn = 0;

int dimming = 79;

void zero_cross_detect()
{
  if ( dimming == 128 )
    return;

  //Serial.println( "ZERO Cross" );
  int dimtime = (75 * dimming);  // For 60Hz =>65
  delayMicroseconds( dimtime );    // Off cycle

  digitalWrite( AC_LOAD, HIGH );     // triac firing
  delayMicroseconds( 20 );         // triac On propagation delay (for 60Hz use 8.33)
  /*
    while( digitalRead( PA1 ) == LOW ) {}
  */
  digitalWrite( AC_LOAD, LOW );      // triac Off
}

void btn_up()
{
  unsigned long c_time = millis();

  if ( c_time - BTN_TIME > prev_btn_up )
  {
    dim_up();
    prev_btn_up = c_time;
  }
}

void btn_dn()
{
  unsigned long c_time = millis();

  if ( c_time - BTN_TIME > prev_btn_dn )
  {
    dim_down();
    prev_btn_dn = c_time;
  }
}

int getPercent()
{
  int av = abs(dimming - 128) + 1;
  Serial.println( av );
  return av * 100 / 128;
}

void dim_up()
{
  dimming -= 1;

  if ( dimming < 1 )
    dimming = 1;

  Serial.println( dimming );
  lcd.setCursor( 0, 0 );
  lcd.print( "Power: " + String(getPercent()) + "%" );  
}

void dim_down()
{
  dimming += 1;
  if ( dimming > 128 )
    dimming = 128;

  Serial.println( dimming );
  lcd.setCursor( 0, 0 );
  lcd.print( "Power: " + String(getPercent()) + "%" );
}

void loop()
{
  //dimming = 100;
}

спасибо за развернутый ответ,

если честно не все понял, это поподробнее не затруднит Вас разжевать?

от что куб сделал для двух таймеров.
 Посмотреть на названия макросов и подобрать аналогичные для аддона мапла.
 Сответственно РА1 вход полуволнового датчика пересечения нуля,
 РА6 выход 500 мкс на тиристор. 
Если в аддоне мапла не найдется сответственной функции надо эти функции писать на CMSYS 

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

посоветуйте еще что поставить к кубу, кто-то советует HAL, стоит для начинающего в стм?

Eще докладываю. пол дня мучений.

замерил Timer2.getOverflow() = 2880

Timer2.getPrescaleFactor() =1

вот скетч который тестировал, все поубирал оставил только подсчет тиков таймера в периоде между полуволнами


#include "Wire.h"
#include "LiquidCrystal_I2C.h"

// Set the LCD address to 0x27 for a 16 chars and 2 line display
LiquidCrystal_I2C lcd(0x27, 16, 2);


volatile int count = 0;
volatile int flag = 0;
volatile int dim = 0;
volatile  int dim_val = 130;

#define Z_PIN PA1 // пин на линии EXTI1 dim 
#define Triak_PIN PA2
 void setup()
{
  Serial.begin(9600);
  lcd.begin();
  lcd.backlight();
  lcd.setCursor(0, 0);
  lcd.print( "Hello" );
  
  pinMode(Z_PIN, INPUT);
  pinMode(Triak_PIN, OUTPUT); //  

  Timer2.pause(); // останавливаем таймер перед настройкой
 // Timer3.setPeriod(40); // время в микросекундах (500мс)
  Timer2.setPrescaleFactor(1); // устанавливаем делитель
  Timer2.setOverflow(2880); // переполнение
  Timer2.attachInterrupt(TIMER_UPDATE_INTERRUPT, func_tim_2); // активируем прерывание по таймеру
  Timer2.refresh(); // обнулить таймер 
  Timer2.resume(); // запускаем таймер
  
  attachInterrupt(Z_PIN, func_interrup, FALLING); // инициализация  прерывания zero-cross 
}

void loop() 
{
   lcd.setCursor( 0, 0);
   lcd.print( "gO=" ); // gO=2880
   lcd.print( Timer2.getOverflow() );
//dim_val = dim_val+1 ;
   dim_val = 130;
   lcd.setCursor( 0, 1 );
   lcd.print( dim );
   lcd.print( " gPF=" ); //gPF=1
   lcd.print( Timer2.getPrescaleFactor()  );
   delay(500);

}

void func_tim_2() // обработчик прерывания по переполнению таймера  
{
  count = count + 1;
  //if(count >= dim_val)
   //igitalWrite(Triak_PIN, 1);} 
} 

void func_interrup() // обработчик   прерывания zero-cross
{
  dim = count;
 //digitalWrite(Triak_PIN, 0); 
  count = 0;
}

в итоге это значение прыгает от 0 до 145, почему так не знаю (как-то таймер ведет себя не понятно). если посчитать количество полуволн за секунду получается примерно 100 +-2