Создание собственной системы стабилизации
кстати, vis.asta, я так понял, что тоже AVR использует,
нет 32f4…
отпишусь - провёл эксперимент - после передачи показаний с гир акселя и магнитометра поставил точку останова, эта гадость сериалит мне уже абы что с переполнением, вот и вешается - буду разбиратся…
тут вся периферия F1 и F4 , у меня так сказать найдите 10 отличий, но блин этот код работает(проверял), а мой нет, что за беда не знаю, ибо затыкается не только уарт затыкается и i2c- просто перестаёт считывать данные с датчиков, да и с гиры тоже (с акселя данные есть всегда), попробовать что-ли туда прикрутить SPI и посмотреть что будет, правда с наскоку чёт не удалось собрать проект, но я особо не упирался не смотрел…
тут вся периферия F1 и F4
под эклипсом собрал, изначально он под Atollic, попробую адаптировать под своё железо посмотрю что будет, а то запёрся совсем…
воевал с версией 2_2 симптомы теже плюс cycleTime взбесился, что-то с математикой не то ибо если отключаю fpu Uart даже не пытается запустится - странно, наверно я где-то проект неправильно настраиваю. В проекте что лежит в git мелкоплата отрабатывает за 2600 новая за 730, а на “чистом” вие (без Калмана ) новая завелась на 3500😵
запустил эту же версию на мелкоплате - цикл тотже 3500 странно… ладно дело сейчас не в этом, блин что я делаю не так при переносе на F4:)
запустил эту же версию на мелкоплате - цикл тотже 3500 странно
У Ф4 частота выше настолько же, на сколько он быстрее. Если формирование millis() и micros() не испарвлено , то твои миллисекунды будут быстрее на соотношение частот процев 😃
Если формирование millis() и micros() не испарвлено
Исправлено и в отладчике смотрел - всё правильно, боюсь что-то или в прерываниях или в настройке самого проекта намудрил…
А теперь на пальцах, для особоодарённых - тоесть меня 😃
// cycles per microsecond
static volatile uint32_t usTicks = 0;
// current uptime for 1kHz systick timer. will rollover after 49 days. hopefully we won't care.
static volatile uint32_t sysTickUptime = 0;
static void cycleCounterInit(void)
{
RCC_ClocksTypeDef clocks;
RCC_GetClocksFreq(&clocks);
usTicks = clocks.SYSCLK_Frequency / 1000000; // ну тут, если не путаю, 8 - на обеих платах одинаково - от кварца в 8мГц отталкиваемся?
}
// SysTick
void SysTick_Handler(void) // откуда вызывается прерывание? незнаю :(
{
sysTickUptime++; // а один ли кГц?
}
// Return system uptime in microseconds (rollover in 70minutes)
uint32_t micros(void)
{
register uint32_t ms, cycle_cnt;
do {
ms = sysTickUptime;
cycle_cnt = SysTick->VAL;
} while (ms != sysTickUptime);
return (ms * 1000) + (168000 - cycle_cnt) / 168; // тот же кГц умноженый на 1000 вернули с поправкой на что? тактовую проца?
}
// Return system uptime in milliseconds (rollover in 49 days)
uint32_t millis(void)
{
return sysTickUptime; // ну и вернули тот-же кГц ?
}
[QUOTE=SergDoc;4177128]А теперь на пальцах, для особоодарённых - тоесть меня 😃
Сергей, вы столько уже провели времени в компиляторах, что давно бы уже разобрались с устройством и выбрали одну среду, а адаптировали под нее только чистую логику из других проектов. Вместо этого вы тратите многие часы борясь с чужими глюками 😃
clocks.SYSCLK_Frequency - это точно частота кварца, а не системной шины? Вообще частота кварца программно вроде недоступна. Только после прескалеров.
вроде как-то так:
RCC_Clocks->SYSCLK_Frequency = HSE_VALUE; // HSE_VALUE=8000000
вроде как-то так:
RCC_Clocks->SYSCLK_Frequency = HSE_VALUE; // HSE_VALUE=8000000
Итак, если коротко - HSI - это 8 МГЦ, внутренний RC генератор.
HSE - Это внешний генератор, в данном случае кварц.
SYSCLK - это системная частота. Она получается умножением кварца на PLL коэффициент. Скорее всего в вашем случае это 168МГц.
вот описание
То есть делить нужно не на 8М, а на 8М*PLLCLK. Так что подсказали вам похоже правильно - коэффициент неверный использовался.
ну да чёт не догнал сразу, о вот надо для 103-го нарыть такую и сравнить, а то я пользовался уже готовым system_stm32f10x.c , а тут сам собирал system_stm32f4xx.c
вот блин а к 103-му то и нет такой фишки 😦
небольшей разбор полётов:
это отсюда
#define DWT_CYCCNT ((volatile uint32 *)0xE0001004)
///////////////////////////////////////////////////////////////////////////////
uint32 uSClock(void) {
// TODO: no check for wraparound
register uint32 PrevTick, Tick, mS;
__disable_irq();
Tick = *DWT_CYCCNT;
PrevTick = sysTickCycleCounter;
mS = sysTickUptime;
__enable_irq();
return ((mS * 1000) + (Tick - PrevTick) / TicksuS);
} // uSClock
у меня же получается:
uint32_t micros(void)
{
register uint32_t ms, cycle_cnt;
do {
ms = sysTickUptime;
cycle_cnt = SysTick->VAL; // значение SysTick = 0хЕ000E010 ? SysTick->VAL = 0x00028831 ?
} while (ms != sysTickUptime);
return (ms * 1000) + (168000 - cycle_cnt) / 168; // а не нормально должно быть (ms*1000)+12 получается
}
остаётся вопрос по sysTickUptime …
отжигают на revo www.openpilot.org/juz-flies-the-revolution/
systick вырабатывает прерывание 1000 раз в секунду, значит всё верно 😦
Наткнулся на странную проблему SPI+DMA в режиме “CIRCULAR”, нужно последовательно вывести массив данных из 28-ти полуслов из памяти в SPI, все выводится НО если бит “0” во втором с конца массива элементе равен единице, передача зависает…,
т.е. передаю в 26-ом элементе 0x0001 - виснет, а при любом другом значении в этом элементе, буфер передается без проблем…
Пробовал менять длину буфера, но эффект тот же… (Прям мистика какая то! может я косяк линейки F303 нарыл?😃)
Кстати в фирменном архиве что то нет примеров про SPI, SPI+DMA?
А что именно виснет? я тоже ДМА с подвисоном не победил 😦
Кстати в фирменном архиве что то нет примеров про SPI, SPI+DMA?
Странно, циркуляр не пробловал для СПИ (у меня каждый считанный пакет по новой перезаряжается), у меня вполне уверенно работает
uint8_t DUSbuffer[10];
/* íàñòðîéêà ÏÄÏ ÄÓÑ */
void DUS_DMA_Init(void)
{
DMA_InitTypeDef DMA_InitStruct;
EXTI_InitTypeDef EXTI_InitStructure;
/* Íàñòðîéêà ÏÄÏ äëÿ ÄÓÑ */
SPI_Cmd (L3GD20_SPI, ENABLE); /* ðàçðåøàåì ðàáîòó ÑÏÈ */
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);
/* çàïîëíÿåì ñòðóêòóðó ÏÄÏ ïî óìîë÷àíèþ */
DMA_StructInit(&DMA_InitStruct);
DMA_InitStruct.DMA_PeripheralInc = DMA_PeripheralInc_Disable; /* ïîñòîÿííûé àäðåñ ïåðåôèðèè */
DMA_InitStruct.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;/* ðàçìåðíîñòü óñ-âà - áàéò */
DMA_InitStruct.DMA_MemoryInc = DMA_MemoryInc_Enable; /* ñ÷åò÷èê áóôåðà óâåëè÷èâàåòñÿ */
DMA_InitStruct.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte; /* ðàçìåðíîñòü áóôåðà - áàéò */
DMA_InitStruct.DMA_Mode = DMA_Mode_Normal; /* íîðìàëüíûé ðåæèì */
DMA_InitStruct.DMA_M2M = DMA_M2M_Disable; /* ìåæäó ïåðåôèðèåé è ÎÇÓ */
DMA_InitStruct.DMA_PeripheralBaseAddr = (uint32_t)&L3GD20_SPI->DR; /* çàäàäåì àäðåñ ïðèåìíèêà äàííûõ */
DMA_InitStruct.DMA_MemoryBaseAddr = (uint32_t)&DUSbuffer[0]; /* çàäàåì àäðåñ èñòî÷íèêà äàííûõ */
DMA_InitStruct.DMA_BufferSize = 9; /* óêàçûâàåì ÷èñëî ïåðåñûëàåìûõ äàííûõ */
/* ïðèìåíÿåì ñòðóêòóðó äëÿ çàïèñè */
DMA_InitStruct.DMA_Priority = DMA_Priority_Medium; /* ïðèîðåòåò çàïèñè ñðåäíèé */
DMA_InitStruct.DMA_DIR = DMA_DIR_PeripheralDST; /* ïîðò - ïðèåìíèê */
DMA_Init(DUS_DMA_Wr, &DMA_InitStruct);
/* ïðèìåíÿåì ñòðóêòóðó äëÿ ÷òåíèÿ */
DMA_InitStruct.DMA_Priority = DMA_Priority_High; /* ïðèîðåòåò ÷òåíèÿ âûñîêèé */
DMA_InitStruct.DMA_DIR = DMA_DIR_PeripheralSRC; /* ïîðò - èñòî÷íèê */
DMA_Init(DUS_DMA_Rd, &DMA_InitStruct);
/* ðàçðåøèòü çàïðîñ ÏÄÏ äëÿ ÑÏÈ */
SPI_I2S_DMACmd(L3GD20_SPI, SPI_I2S_DMAReq_Rx, ENABLE);
SPI_I2S_DMACmd(L3GD20_SPI, SPI_I2S_DMAReq_Tx, ENABLE);
/* òàêòèðóåì ïîðò */
RCC_AHBPeriphClockCmd(L3GD20_SPI_INT2_GPIO_CLK, ENABLE);
/* êîíôèãóðàöèÿ ïîäêëþ÷åíèÿ ê ïîðòàì */
SYSCFG_EXTILineConfig(L3GD20_SPI_INT2_EXTI_PORT_SOURCE,L3GD20_SPI_INT2_EXTI_PIN_SOURCE);
/* çàïðîñ ïðåðûâàíèÿ ïî ãîòîâíîñòè äàííûõ ÄÓÑ*/
EXTI_ClearITPendingBit(L3GD20_SPI_INT2_EXTI_LINE);
EXTI_InitStructure.EXTI_Line = L3GD20_SPI_INT2_EXTI_LINE;
EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising;
EXTI_InitStructure.EXTI_LineCmd = ENABLE;
EXTI_Init(&EXTI_InitStructure);
}
/* ðàçðåøàåì ðàáîòó ïåòëè ÄÓÑ */
void DUS_PetlyaInit(void)
{
/* ïåðåíàñòðîèì ÏÄÏ ÄÓÑà*/
DUS_DMA_Init();
/* ðàçðåøàåì ïðåðûâàíèÿ îò ÏÄÏ äëÿ êàíàëà ÷òåíèÿ */
DMA_ITConfig(DUS_DMA_Rd, DMA_IT_TC, ENABLE);
/* ðàçðåøèòü çàïðîñ ÏÄÏ äëÿ ÑÏÈ */
SPI_I2S_DMACmd(L3GD20_SPI, SPI_I2S_DMAReq_Rx, ENABLE);
SPI_I2S_DMACmd(L3GD20_SPI, SPI_I2S_DMAReq_Tx, ENABLE);
/* ðàçðåøàåì ðàáîòó ÏÄÏ */
DMA_Cmd (DUS_DMA_Rd, ENABLE); /* ñíà÷àëà ðàçðåøàåì ÷òåíèå(!!!!) */
DMA_Cmd (DUS_DMA_Wr, ENABLE);
/* íàñòðîéêà ïðåðûâàíèÿ ïîñëå ÏÄÏ */
NVIC_EnableIRQ(DMA1_Channel2_IRQn);
NVIC_SetPriority(DMA1_Channel2_IRQn, 2);
/* íàñòðîéêà ïðåðûâàíèÿ ïî ëèíèè ãîòîâíîñòè ÄÓÑ */
NVIC_EnableIRQ(L3GD20_SPI_INT2_EXTI_IRQn);
NVIC_SetPriority(L3GD20_SPI_INT2_EXTI_IRQn, 2);
/* òîëêíåì ïåòëþ ÄÓÑ */
DUS_Zapros();
}
/* çàïðåòèòü ðàáîòó ïåòëè ÄÓÑ */
void DUS_PetlyaDeInit(void)
{
__IO uint32_t L3GD20Timeout = L3GD20_FLAG_TIMEOUT;
/* çàïðåòèì ïðåðûâàíèÿ ïî ëèíèè ãîòîâíîñòè ÄÓÑ */
NVIC_DisableIRQ(L3GD20_SPI_INT2_EXTI_IRQn);
/* äîæäåìñÿ îêîí÷àíèÿ ÏÄÏ */
while (GPIO_ReadInputDataBit(L3GD20_SPI_CS_GPIO_PORT,L3GD20_SPI_CS_PIN)==Bit_RESET){
if((L3GD20Timeout--) == 0) L3GD20_TIMEOUT_UserCallback();
}
/* çàïðåòèì ðàáîòó ÏÄÏ */
DMA_Cmd (DUS_DMA_Wr, DISABLE); /* ñíà÷àëà çàïðåòèì çàïèñü(!!!!) */
DMA_Cmd (DUS_DMA_Rd, DISABLE);
/* çàïðåòèì ïðåðûâàíèÿ ïîñëå ÏÄÏ */
NVIC_DisableIRQ(DMA1_Channel2_IRQn);
}
/* çàïðîñ äàííûõ ÏÄÏ */
void DUS_Zapros(void)
{
if (DMA_GetCurrDataCounter(DUS_DMA_Rd)){
/* çàïðåòèì ïðåðûâàíèÿ ïî ëèíèè ãîòîâíîñòè ÄÓÑ */
NVIC_DisableIRQ(L3GD20_SPI_INT2_EXTI_IRQn);
return;
}
/* óñòàíîâèì âûáîð âåäîìîãî óñ-âà */
L3GD20_CS_LOW();
/* ñáðîñèì ôëàã çàâåðøåíèÿ öèêëà ÏÄÏ */
DMA_ClearFlag(DMA1_FLAG_GL2);DMA_ClearFlag(DMA1_FLAG_GL3);
/* íàñòðîèì àäðåñ è ðåæèì ïåðåäà÷è */
DUSbuffer[0]= L3GD20_OUT_TEMP_ADDR|READWRITE_CMD|MULTIPLEBYTE_CMD;
/* ïåðåçàðÿäêà ÏÄÏ */
DMA_SetCurrDataCounter(DUS_DMA_Rd,9);
DMA_SetCurrDataCounter(DUS_DMA_Wr,9);
/* ðàçðåøàåì ðàáîòó ÏÄÏ */
DMA_Cmd (DUS_DMA_Rd, ENABLE); /* ñíà÷àëà ðàçðåøàåì ÷òåíèå(!!!!) */
DMA_Cmd (DUS_DMA_Wr, ENABLE);
}
void DUS_EndDMASPITrans_ISR(void)
{
/* çàïðåòèì ðàáîòó ÏÄÏ */
DMA_Cmd (DUS_DMA_Wr, DISABLE); /* ñíà÷àëà çàïðåòèì çàïèñü(!!!!) */
DMA_Cmd (DUS_DMA_Rd, DISABLE);
/* ñíèìåì âûáîð óñ-âà ñ âåäîìîãî */
L3GD20_CS_HIGH();
/* îáíîâëÿåì äàííûå óc-â ÈÍÑ */
DUSDataRdy();
NVIC_EnableIRQ(L3GD20_SPI_INT2_EXTI_IRQn);
}
void DUS_TolkPetlu(void)
{ /* ïðèíóäèòåëüíûé çàïóñê ïî âíåøíèì ñèãíàëàì */
//if (GPIO_ReadInputData(GPIO_IMU) & IMU_DRDY_G)
EXTI_GenerateSWInterrupt(L3GD20_SPI_INT2_EXTI_IRQn);
// if (GPIO_ReadInputData(GPIO_IMU) & IMU_DRDY_A)
// EXTI_GenerateSWInterrupt(EXTI_Line0);
}
циркуляр не пробловал
У Вас “DMA_Mode_Normal” и “DMA_BufferSize = 9;” , если я правильно понимаю, то после одного “толчка” DMA, он передаст один байт из девяти и после девяти таких “толчков” выдаст флаг “трансфер комплит”…
А в “DMA_Mode_Circular” после одного “толчка” DMA автоматом сольет все 9 байт и поставит флаг…
Так вот виснет у меня на 26-м (при условии “1” мл.разр.!!!) из 28…
Прям чушь какая то, задача достаточно примитивная, а тут просто ступор, это я OSD делаю (видеостроку вывожу в порт), сначала понять не мог, а когда разобрался что дело в 1-ом бите (!) да еще именно в во втором с конца байте, тут мне совсем поплохело…(не могу понять логику происходящего)
Затупил… , в “нормал” моде весь буфер передается с одного толчка, просто надо каждый раз количество байт ставить заново…
Но суть проблемы не изменилась… Ладно еще, в моей задаче можно этот “чудо бит” обойти (всего лишь картинка), а если важные данные пересылать пакетно ? ?
вроде как-то так:
RCC_Clocks->SYSCLK_Frequency = HSE_VALUE; // HSE_VALUE=8000000
вот неплохая статейка касательно генерации тактовых частот easyelectronics.ru/arm-uchebnyj-kurs-taktovyj-gene…
вот еще возможно полезно будет easyelectronics.ru/opredelenie-tekushhej-taktovoj-…