Всем привет! Встала необходимость реализовать задержку в миллисекундах в микроконтроллере STM32F103C8T6. Перерыл интернет, ничего работоспособного не нашел, ни один код не работает у меня. Взял вот отсюда код задержки https://hubstub.ru/stm32/101-funkciya-z ... stm32.html, но Keil ругается. В чем может быть дело?
Что вообще за регистры CoreDebug_DEMCR_TRCENA_Msk, DWT_CTRL_CYCCNTENA_Msk, DWT ? В даташите не нашел инфы.
Нельзя миллисекундные задержки блокирующими делать! Надо разворачивать или конечные автоматы, или запускать таймер и заниматься своими делами, а как сработает прерывание таймера - выполнить требующийся короткий кусочек кода.
> CYCCNTENA
Это для микросекундных задержек, подсчет количества циклов системной шины. Только все равно строгой паузы не получится. Для строгой паузы есть таймеры. Вот пример коротенькой паузы. Но это - блажь. Не надо так делать. Там же можно увидеть еще более грубый пример - миллисекундных пауз. Так тем более делать нельзя!
Linux rules! Windows must die. Здравомыслящий человек добровольно будет пользоваться мастдаем лишь в двух случаях: под дулом автомата или под влиянием анального зонда. Я на гитхабе, в ЖЖ
Eddy_Em, не пойму почему до сих пор еще никто не озаботился написать нормальный рабочий код для милли - или секундных задержек? Смотришь примеры в инете, копируешь к себе в Keil, а ничего не работает, ошибки.... То библиотеки какие-то еще нужно, то регистры левые вылазят. Возникает мысль что у всех этих советчиков с "с рабочими задержками" что то с головой не в порядке, если уж рядовому начинающему прогеру не могут доступно донести инфу. Я в шоке!
201bazza писал(а):почему до сих пор еще никто не озаботился написать нормальный рабочий код для милли - или секундных задержек?
Потому что универсального решения в данном случае не существует: кому-то нравится в теле main проверять счетчик времени, а потом запускать нужную процедуру, а кто-то делает все на конечных автоматах (и по сути внутри обработки состояния автомата в состоянии PAUSE выполняется та же самая процедура). Для пущей точности можно паузу таймером делать: по прерыванию при окончании счета выставляем флаг, а далее - те же самые процедуры проверки.
Тупо как абдуринщики делать блокирующую паузу в полсекунды-секунду некошерно!
Linux rules! Windows must die. Здравомыслящий человек добровольно будет пользоваться мастдаем лишь в двух случаях: под дулом автомата или под влиянием анального зонда. Я на гитхабе, в ЖЖ
void DWT_Delay(uint32_t us) // microseconds
{
int32_t tp = DWT_Get() + us * (8000000/1000000); // вместо 8000000 должно стоять SystemCoreClock, но тогда Keil ругается на SystemCoreClock
while (DWT_Compare(tp));
}
void SendCameBit(int b)
{
DWT_Delay (320);
if (!b) GPIOC->ODR=GPIO_Pin_13;
DWT_Delay (320);
GPIOC->ODR=GPIO_Pin_13;
DWT_Delay (320);
GPIOC->ODR=0;
}
int main(void)
{
char Code [] = "100001111000011101010100";
if (!(DWT_CONTROL & 1))
{
SCB_DEMCR |= 0x01000000;
DWT_CYCCNT = 0;
DWT_CONTROL|= 1; // enable the counter
}
/* объявление инициализационной структуры (InitStructure), которая содержит все
параметры для настройки периферийного устройства в виде переменных-членов структуры */
GPIO_InitTypeDef GPIO_InitStructure;
/* подача на порт тактирования */
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);
/* переменные-члены структуры */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
/* вызываем функцию инициализации, куда передаем указатель на сформированную структуру */
GPIO_Init(GPIOC, &GPIO_InitStructure);
while (1)
{
for (int j=0;j<4;j++)
{
GPIOC->ODR=GPIO_Pin_13;
DWT_Delay (1); // вот тут программа встает и дальше не двигается. Светодиод на плате просто горит бесконечно
GPIOC->ODR=0;// посылаем стартовый импульс
for (int i=0;i<24;i++)
{
SendCameBit((int)Code ); // побитово перебираем и посылаем код
}
DWT_Delay (320);
}
GPIOC->ODR=0;
DWT_Delay (1000000); // сделать паузу после посылки на 1 с
}
}
По-хорошему, надо еще выключать счетчик, когда он не используется. Но это не очень важно. Вот еще. но у меня без этого 0xC5ACCE55 все работало.
Linux rules! Windows must die. Здравомыслящий человек добровольно будет пользоваться мастдаем лишь в двух случаях: под дулом автомата или под влиянием анального зонда. Я на гитхабе, в ЖЖ
[uquote="201bazza",url="/forum/viewtopic.php?p=3739177#p3739177"]Что вообще за регистры CoreDebug_DEMCR_TRCENA_Msk, DWT_CTRL_CYCCNTENA_Msk, DWT ? В даташите не нашел инфы.[/uquote]Плохо искали: http://infocenter.arm.com/help/topic/co ... l#cortexm3
Раздел "Data Watchpoint and Trace Unit".
Добавлено after 5 minutes 10 seconds:
[uquote="201bazza",url="/forum/viewtopic.php?p=3739230#p3739230"]Eddy_Em, не пойму почему до сих пор еще никто не озаботился написать нормальный рабочий код для милли - или секундных задержек?[/uquote]"Нормальный рабочий код" давно уже написан. Называется он "РТОС". Ибо - грамотные программисты ПО на ARM-ах в суперлупе не пишут.
jcxz, грамотные специалисты РТОС в любую дырку не суют!
Linux rules! Windows must die. Здравомыслящий человек добровольно будет пользоваться мастдаем лишь в двух случаях: под дулом автомата или под влиянием анального зонда. Я на гитхабе, в ЖЖ
Кто вас учил писать исполняемый код в заголовочных файлах и к тому же не подключать другие заголовочные файлы где находятся объявления регистров и их битов?
201bazza писал(а):Что вообще за регистры CoreDebug_DEMCR_TRCENA_Msk, DWT_CTRL_CYCCNTENA_Msk, DWT ? В даташите не нашел инфы.
Это из ядра ARM и не регистры, а их биты. Нужно подключить заголовочные файлы CMSIS.