26.02.2020, 13:34
|
|
Почётный гражданин KAZUS.RU
Регистрация: 27.01.2005
Адрес: Россия, КЧР, Нижний Архыз
Сообщений: 3,637
Сказал спасибо: 116
Сказали Спасибо 814 раз(а) в 591 сообщении(ях)
|
Re: FAQ по STM8
Сообщение от MikeF
|
if((CLK-›CSSR & CLK_CSSR_CSSD) == SET)
|
Ну так ложное же условие всегда будет, и компилятор тупо его выкинуть должен при нормальной оптимизации.
Потому что если в регистре REG установлен флаг FLAG, то (REG&FLAG)==FLAG! А этот SET == 1, т.е. условие (REG&FLAG)==SET будет выполняться, лишь если FLAG==1!
Можно вот как сделать:
Код:
|
if(!(CLK-›CSSR & CLK_CSSR_CSSD) == RESET) |
__________________
Союз Советских Социалистических Округов Северной Америки
|
|
|
|
26.02.2020, 14:00
|
|
Прописка
Регистрация: 14.04.2005
Сообщений: 116
Сказал спасибо: 12
Сказали Спасибо 18 раз(а) в 12 сообщении(ях)
|
Re: FAQ по STM8
Сообщение от eddy
|
А этот SET == 1
|
Видимо, но я думал что SET это любое число =!0, как написано в stm8s.h, но тут похоже enum сработал несмотря на прямое присваивание SET = !RESET и получилась 1.
|
|
|
|
26.02.2020, 14:07
|
|
Почётный гражданин KAZUS.RU
Регистрация: 27.01.2005
Адрес: Россия, КЧР, Нижний Архыз
Сообщений: 3,637
Сказал спасибо: 116
Сказали Спасибо 814 раз(а) в 591 сообщении(ях)
|
Re: FAQ по STM8
MikeF, нет, чтобы SET работал именно так, как хочется, нужно заводить макросы вида
Код:
|
#define ISSET(x) (x)
#define ISRESET(x) (!x) |
В этом случае можно будет проверять флаги так:
Код:
|
if(ISSET(reg & flag1))...
if(ISRESET(reg & flag2))... |
__________________
Союз Советских Социалистических Округов Северной Америки
|
|
|
|
13.03.2022, 08:40
|
|
Прописка
Регистрация: 14.04.2005
Сообщений: 116
Сказал спасибо: 12
Сказали Спасибо 18 раз(а) в 12 сообщении(ях)
|
Re: FAQ по STM8
Всем привет.
Столкнулся с неприятным моментом при отладке программы в STVD+Cosmic при использовании прерывания высшего уровня (TLI).
TLI используется в детекторе перехода сетевого напряжения через ноль соответственно постоянно срабатывает (раз в 10 мс), что и вызвало затруднение при отладке программы по шагам. Как это выглядит - программа исправно останавливается на установленном breakpoint, но при нажатии на кнопку Step into (да и любых других, например Step over) неизменно переходит в обработчик прерывания TLI, проходишь весь обработчик и снова попадаешь на breakpoint и так зацикливаешься.
С одной стороны понятно, но очень неудобно сделано, в обработчик таймера ведь не попадаешь постоянно хотя он вызывается ещё чаще (раз в 1 мс). Настроек в STVD для обхода этого момента не нашел, отключать TLI тоже не всегда возможно, т.к. алгоритм программы нарушается. Может кто-то сталкивался и есть рецепт?
Если изменить схему и использовать прерывание на порт A, например, то удастся уйти от этой проблемы?
|
|
|
|
15.05.2023, 07:14
|
|
Прохожий
Регистрация: 15.05.2023
Сообщений: 5
Сказал спасибо: 1
Сказали Спасибо 0 раз(а) в 0 сообщении(ях)
|
Re: FAQ по STM8
Уважаемые спецы!
Разбираюсь с периферией STM8L152C6 в составе STM8L-DISCOVERY.
Не работает ШИМ на первом и втором таймерах, на третьем таймере ШИМ идёт только со второго канала. Привёл настройки первого таймера, портов. Настройки второго и третьего таймера аналогичны, второй таймер дёргает прерывание, прерывание есть. На третьем таймере два канала настроены одинаково, но ШИМ идёт только со второго канала с вывода PD0.
Функция настройки первого таймера
void timinit ()
{
//Таймер1 - центрированная ШИМ
TIM1_CR1 = 0xA0; //счёт с автореверсом, таймер выключен
TIM1_CR2 = 0x00; //не используется
TIM1_SMCR = 0x00; //не используется
TIM1_ETR = 0x00; //не используется
TIM1_IER = 0x00; //прерывания не используются
TIM1_SR1 = 0x00; //очистка регистр статуса 1
TIM1_SR2 = 0x00; //очистка регистра статуса 2
TIM1_EGR = 0x00; //очистка регистра генерации прерываний
TIM1_CCMR1 = 0x68; //режим работы ШИМ1
TIM1_CCMR2 = 0x68; //режим работы ШИМ2
TIM1_CCMR3 = 0x68; //режим работы ШИМ3
//TIM1_CCMR4 = 0x68; //режим работы ШИМ4
TIM1_CCER1 = 0x55; //разрешаем выходы ШИМ1 и ШИМ2
TIM1_CCER2 = 0x05; //разрешаем выходы ШИМ3 и ШИМ4
TIM1_PSCRH = 0x00; //предделитель не используется
TIM1_PSCRL = 0x00; //предделитель не используется
TIM1_CCR1L = 0x00; //ШИМ1=0
TIM1_CCR1H = 0x00; //ШИМ1=0
TIM1_CCR2L = 0x00; //ШИМ2=0
TIM1_CCR2H = 0x00; //ШИМ2=0
TIM1_CCR3L = 0x00; //ШИМ3=0
TIM1_CCR3H = 0x00; //ШИМ3=0
//TIM1_CCR4L = 0x00; //ШИМ4=0
//TIM1_CCR4H = 0x00; //ШИМ4=0
TIM1_CNTRH = 0x00; //очистка счётчика
TIM1_CNTRL = 0x00; //очистка счётчика
TIM1_ARRH = 0x09; //
TIM1_ARRL = 0xC4; //коэффициент деления 2501!!!
TIM1_RCR = 0x00; //не используется
TIM1_BKR = 0x80; //разрешение главного выхода!!!
TIM1_DTR = 0x27; //защитная пауза 2 мкс
}
Настройки порта:
void portinit ()
{
//Порт D. выходы PD0 - PD5
PD_DDR = 0xBF; //выходы PD0 - PD5, PD7
PD_CR1 = 0xFF; //подтяжка PD6 к +5В
PD_CR2 = 0xBF; //нет прерываний, высокая скорость выходов
PD_ODR = 0x00; //очистка регистра выхода
}
Старт:
void start ()
{
TIM1_CR1 |= 0x01; //включаем таймер 1
TIM1_CCR1H = 0x05; //тест
TIM1_CCR2H = 0x05; //тест
TIM1_CCR3H = 0x05; //тест
}
Процедура инициализации писалась по референс-мануалу RM0031 и книге Матюшова.
|
|
|
|
15.05.2023, 15:03
|
|
Гражданин KAZUS.RU
Регистрация: 17.06.2008
Адрес: Украина
Сообщений: 720
Сказал спасибо: 363
Сказали Спасибо 801 раз(а) в 375 сообщении(ях)
|
Re: FAQ по STM8
RM0031 видимо читался не очень внимательно
Первое, что бросается в глаза (не вдаваясь в "магические" числа) :
- не видно, где разрешается тактирование таймера TIM1 (регистр CLK_PCKENR2) ;
- смотрите раздел(ы) 19.5.1, 19.3.2 о порядке записи в регистры TIMx_CCRi (вкратце: пишем оба байта - сначала старший, потом младший)
Пока что достаточно
P. S.
Для корректной отработки первого периода таймера/ШИМ перед запуском таймера не помешало бы актуализировать его настройки путём записи 1 в бит UG регистра TIM_EGR ( потом почистить флаги, если нужно ).
|
|
|
|
15.05.2023, 19:00
|
|
Прохожий
Регистрация: 15.05.2023
Сообщений: 5
Сказал спасибо: 1
Сказали Спасибо 0 раз(а) в 0 сообщении(ях)
|
Re: FAQ по STM8
У меня старший и младший байт пишутся в регистр предзагрузки, который после перехода через ноль пишется в регистр сравнения ШИМ.
Второй таймер дёргает прерывание, а у третьего один канал из двух одинаково настроенных исправно выдаёт ШИМ, впрочем, я про это уже писал.
void clkinit () //настройка тактирования
{
CLK_CKDIVR = 0x00; //отключаем все предделители тактового сигнала
CLK_PCKENR1 = 0x8F; //разрешаем тактирование ЦАП, таймеров 2, 3 и 4, а также I2C
CLK_PCKENR2 = 0x13;//разрешаем тактирование конроллера ПДП, таймера 1 и АЦП.
}
|
|
|
|
15.05.2023, 21:21
|
|
Гражданин KAZUS.RU
Регистрация: 17.06.2008
Адрес: Украина
Сообщений: 720
Сказал спасибо: 363
Сказали Спасибо 801 раз(а) в 375 сообщении(ях)
|
Re: FAQ по STM8
Предполагается, что никакая другая периферия не мешает работе TIM1 и никакая обвязка на плате не препятствует наблюдению сигналав ШИМ.
Повторюсь: таки для начала попробуйте соблюсти правила при записи в регистры CCRi :
Сообщение от j-Roger
|
записи в регистры TIMx_CCRi (вкратце: пишем оба байта - сначала старший, потом младший)
|
Цитата из документа:
Дорабатываем функцию start():
Код:
|
void start ()
{
TIM1_CR1 |= 0x01; //включаем таймер 1
TIM1_CCR1H = 0x05; //тест
TIM1_CCR1L = 0;
TIM1_CCR2H = 0x05; //тест
TIM1_CCR2L = 0;
TIM1_CCR3H = 0x05; //тест
TIM1_CCR3L = 0;
} |
Функция main():
Код:
|
{
clkinit();
portinit();
timinit();
start ();
while (1);
} |
И отписаться, что на выходах TIM1_CH1..3
P.S.
1) То же правило относительно CCRi касается и функции timinit()
2) Желательно также
Сообщение от j-Roger
|
P. S.
Для корректной отработки первого периода таймера/ШИМ перед запуском таймера не помешало бы актуализировать его настройки путём записи 1 в бит UG регистра TIM_EGR ( потом почистить флаги, если нужно ).
|
Например, функцию timinit() завершить строкой TIM1_EGR = 0x01;
Скорее всего и с другими таймерами такая же ситуация - несоблюдение порядка записи в 16-битные регистры
Последний раз редактировалось j-Roger; 16.05.2023 в 00:12.
Причина: дополнения
|
|
|
Сказали "Спасибо" j-Roger
|
|
|
16.05.2023, 07:53
|
|
Прохожий
Регистрация: 15.05.2023
Сообщений: 5
Сказал спасибо: 1
Сказали Спасибо 0 раз(а) в 0 сообщении(ях)
|
Re: FAQ по STM8
j-Roger, БЛАГОДАРЮ!!!
Да, действительно запись старший/младший байт оказалось критично, и я этот момент проморгал. Сейчас ШИМ на всех трёх каналах таймера есть. Смотрел осциллографом - центрированная ШИМ и защитная пауза тоже работают.
Второй и третий таймер работают также, но это я уже буду вечером разбираться.
UPD: нашёл ошибку в настройке порта - со второго и третьего таймера ШИМ тоже идёт.
Ещё один момент, если старший байт равен нулю, то можно спокойно писать только в младший байт.
Последний раз редактировалось Экспериментатор; 16.05.2023 в 08:06.
Причина: Дополнения
|
|
|
|
16.05.2023, 09:47
|
|
Гуру портала
Регистрация: 06.05.2005
Адрес: Краснодар, возле укротворного моря.
Сообщений: 19,056
Сказал спасибо: 2,562
Сказали Спасибо 11,889 раз(а) в 5,963 сообщении(ях)
|
Re: FAQ по STM8
Сообщение от Экспериментатор
|
если старший байт равен нулю, то можно спокойно писать только в младший байт
|
Привыкайте к порядку. Что можно - оптимизирует компилятор, а что нельзя - приведет к непредсказуемым последствиям. Это Вы уже успели почувствовать. Или еще не успели?!
__________________
Не бейте больно, ежели чо, ну не удержался... А вааще,
"Мы за все хорошее, против всей х..., По лугам некошеным чтобы шли ступни,
Чтобы миром правила правда, а не ложь, Мы за все хорошее, нас не на...!
..." (Ленинград)
Я не несу ответственности за свои действия в Вашей голове.
|
|
|
Эти 2 пользователя(ей) сказали Спасибо akegor за это сообщение:
|
|
|
Ваши права в разделе
|
Вы не можете создавать новые темы
Вы не можете отвечать в темах
Вы не можете прикреплять вложения
Вы не можете редактировать свои сообщения
HTML код Выкл.
|
|
|
Часовой пояс GMT +4, время: 09:48.
|
|