LEVENVORF 0 18 января, 2012 Опубликовано 18 января, 2012 · Жалоба Необходимо измерить смещение фазы между двумя сигналами. Использую STM32F103RC6T. Первый сигнал заведен на PC8, и настроено внешнее прерывание по этому входу, второй сигнал заведен на PB6 (TIM4_CH1). Алгоритм работы следующий: по переднему, восходящему фронту на PC8 срабатывает прерывание, в котором перезапускается таймер 4. По переднему восходящему фронту на PB6 происходит захват значение счетчика, по этому событию происходит передача по DMA значения из регистра ССR1 в буфер. Проблема в следующем: часть буфера заполняется некорректными значениями. Закономерности не выявил т.е. могут быть ошибки в начале, потом правильные данные, потом опять ошибки, а может быть наоборот. Пробовал по СС1 генерить не DMA запрос, а прерывание, и в нем вычитавать значение CCR1, тогда все работает, и значения корректные. Измеряемые сигналы пока беру с образцового генератора. Код приведен ниже: unsigned short CCR1_val[500]; void Tim_Capture_Init(void) { RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE); RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE); RCC_APB1PeriphResetCmd(RCC_APB1Periph_TIM4, DISABLE); DMA_InitTypeDef DMA_InitStructure; DMA_DeInit(DMA1_Channel1); DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&TIM4->CCR1; DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)&CCR1_val; DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC; DMA_InitStructure.DMA_BufferSize = 500; DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord; DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord; DMA_InitStructure.DMA_Mode = DMA_Mode_Circular; DMA_InitStructure.DMA_Priority = DMA_Priority_VeryHigh; DMA_InitStructure.DMA_M2M = DMA_M2M_Disable; DMA_Init(DMA1_Channel1, &DMA_InitStructure); TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; TIM_ICInitTypeDef TIM_ICInitStructure; TIM_TimeBaseStructure.TIM_Prescaler = 13; TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; TIM_TimeBaseStructure.TIM_Period = 0xFFFF; TIM_TimeBaseStructure.TIM_ClockDivision = 0; TIM_TimeBaseStructure.TIM_RepetitionCounter = 0; TIM_TimeBaseInit(TIM4, &TIM_TimeBaseStructure); TIM_PrescalerConfig(TIM4, 13, TIM_PSCReloadMode_Immediate); TIM_ICInitStructure.TIM_Channel = TIM_Channel_1; TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising; TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI; TIM_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1; TIM_ICInitStructure.TIM_ICFilter = 0; TIM_ICInit(TIM4, &TIM_ICInitStructure); /* TIM1 Update DMA Request enable */ TIM_DMACmd(TIM4, TIM_DMA_CC1, ENABLE); TIM_Cmd(TIM4, ENABLE); DMA_Cmd(DMA1_Channel1, ENABLE); while (!DMA_GetFlagStatus(DMA1_FLAG_TC1)); } void EXTI_init(void) { EXTI_InitTypeDef EXTI_InitStructure; NVIC_InitTypeDef NVIC_InitStructure; GPIO_EXTILineConfig(GPIO_PortSourceGPIOC, GPIO_PinSource8); /* Configure EXTI0 line */ EXTI_InitStructure.EXTI_Line = EXTI_Line8; EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt; EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising; EXTI_InitStructure.EXTI_LineCmd = ENABLE; EXTI_Init(&EXTI_InitStructure); /* Enable and set EXTI0 Interrupt to the lowest priority */ NVIC_InitStructure.NVIC_IRQChannel = EXTI9_5_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = Priority_EXTI; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); } void EXTI9_5_IRQHandler(void) { if(EXTI_GetITStatus(EXTI_Line8) != RESET) { TIM_GenerateEvent(TIM4, TIM_EventSource_Update); EXTI_ClearITPendingBit(EXTI_Line8); } } Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
vvkka 0 18 января, 2012 Опубликовано 18 января, 2012 · Жалоба Необходимо измерить смещение фазы между двумя сигналами. Использую STM32F103RC6T. Первый сигнал заведен на PC8, и настроено внешнее прерывание по этому входу, второй сигнал заведен на PB6 (TIM4_CH1). Алгоритм работы следующий: по переднему, восходящему фронту на PC8 срабатывает прерывание, в котором перезапускается таймер 4. По переднему восходящему фронту на PB6 происходит захват значение счетчика, по этому событию происходит передача по DMA значения из регистра ССR1 в буфер. Проблема в следующем: часть буфера заполняется некорректными значениями. Закономерности не выявил т.е. могут быть ошибки в начале, потом правильные данные, потом опять ошибки, а может быть наоборот. Пробовал по СС1 генерить не DMA запрос, а прерывание, и в нем вычитавать значение CCR1, тогда все работает, и значения корректные. Измеряемые сигналы пока беру с образцового генератора. }[/code] пожалуста весь проектик в студию. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
LEVENVORF 0 18 января, 2012 Опубликовано 18 января, 2012 (изменено) · Жалоба пожалуста весь проектик в студию. unsigned short CCR1_val[500]; void Tim_Capture_Init(void) { RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE); RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE); RCC_APB1PeriphResetCmd(RCC_APB1Periph_TIM4, DISABLE); DMA_InitTypeDef DMA_InitStructure; DMA_DeInit(DMA1_Channel1); DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&TIM4->CCR1; DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)&CCR1_val; DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC; DMA_InitStructure.DMA_BufferSize = 500; DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord; DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord; DMA_InitStructure.DMA_Mode = DMA_Mode_Circular; DMA_InitStructure.DMA_Priority = DMA_Priority_VeryHigh; DMA_InitStructure.DMA_M2M = DMA_M2M_Disable; DMA_Init(DMA1_Channel1, &DMA_InitStructure); TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; TIM_ICInitTypeDef TIM_ICInitStructure; TIM_TimeBaseStructure.TIM_Prescaler = 13; TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; TIM_TimeBaseStructure.TIM_Period = 0xFFFF; TIM_TimeBaseStructure.TIM_ClockDivision = 0; TIM_TimeBaseStructure.TIM_RepetitionCounter = 0; TIM_TimeBaseInit(TIM4, &TIM_TimeBaseStructure); TIM_PrescalerConfig(TIM4, 13, TIM_PSCReloadMode_Immediate); TIM_ICInitStructure.TIM_Channel = TIM_Channel_1; TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising; TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI; TIM_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1; TIM_ICInitStructure.TIM_ICFilter = 0; TIM_ICInit(TIM4, &TIM_ICInitStructure); /* TIM1 Update DMA Request enable */ TIM_DMACmd(TIM4, TIM_DMA_CC1, ENABLE); TIM_Cmd(TIM4, ENABLE); DMA_Cmd(DMA1_Channel1, ENABLE); while (!DMA_GetFlagStatus(DMA1_FLAG_TC1)); } void EXTI_init(void) { EXTI_InitTypeDef EXTI_InitStructure; NVIC_InitTypeDef NVIC_InitStructure; GPIO_EXTILineConfig(GPIO_PortSourceGPIOC, GPIO_PinSource8); /* Configure EXTI0 line */ EXTI_InitStructure.EXTI_Line = EXTI_Line8; EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt; EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising; EXTI_InitStructure.EXTI_LineCmd = ENABLE; EXTI_Init(&EXTI_InitStructure); /* Enable and set EXTI0 Interrupt to the lowest priority */ NVIC_InitStructure.NVIC_IRQChannel = EXTI9_5_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = Priority_EXTI; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); } void EXTI9_5_IRQHandler(void) { if(EXTI_GetITStatus(EXTI_Line8) != RESET) { TIM_GenerateEvent(TIM4, TIM_EventSource_Update); EXTI_ClearITPendingBit(EXTI_Line8); } } void main(void) { RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO | RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB | RCC_APB2Periph_GPIOC | RCC_APB2Periph_GPIOD, ENABLE); RCC_APB2PeriphResetCmd(RCC_APB2Periph_AFIO | RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB | RCC_APB2Periph_GPIOC | RCC_APB2Periph_GPIOD, DISABLE); GPIO_InitTypeDef GPIO_InitStructure; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6; GPIO_Init(GPIOB, &GPIO_InitStructure); GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8; GPIO_Init(GPIOC, &GPIO_InitStructure); Tim_Capture_Init(); EXTI_init(); while(1); } Изменено 18 января, 2012 пользователем LEVENVORF Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
vvkka 0 18 января, 2012 Опубликовано 18 января, 2012 (изменено) · Жалоба вобще то имел виду полную выклодку в той программе которой пишите. а то бывает ошибки в инициализации, так хоть проверить можно Изменено 18 января, 2012 пользователем vvkka Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Flexz 0 18 января, 2012 Опубликовано 18 января, 2012 · Жалоба Tim_Capture_Init() запускает DMA и ждет его окончания ДО настройки прерывания от внешней линии в EXTI_init() Просто поменяйте местами их вызовы . Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
LEVENVORF 0 19 января, 2012 Опубликовано 19 января, 2012 · Жалоба Tim_Capture_Init() запускает DMA и ждет его окончания ДО настройки прерывания от внешней линии в EXTI_init() Просто поменяйте местами их вызовы . Все равно не работает. EXTI прерывание просто перезапускает таймер, так что захват по СС1 все равно произойдет. Т.е. ложным может быть только первое срабатывание, а у меня неверное значение не только первое )))) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Flexz 0 20 января, 2012 Опубликовано 20 января, 2012 · Жалоба Все равно не работает. EXTI прерывание просто перезапускает таймер, так что захват по СС1 все равно произойдет. Т.е. ложным может быть только первое срабатывание, а у меня неверное значение не только первое )))) В исходном виду у вас прерывание вообще не происходит до полного окончания DMA трансфера. Вы измеряете интервал между импульсами на PB6, а не разность фаз, естественно результат неверен. Впрочем если вы предпочитаете ржать над советами - копайтесь сами. Успехов. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
V_M_Luck 0 20 января, 2012 Опубликовано 20 января, 2012 · Жалоба В исходном виду у вас прерывание вообще не происходит до полного окончания DMA трансфера. Вы измеряете интервал между импульсами на PB6, а не разность фаз, естественно результат неверен. Человек именно и измеряет разность фаз. И как по вашему прерывание от внешней линии зависит от DMA capture? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
skripach 6 20 января, 2012 Опубликовано 20 января, 2012 · Жалоба Алгоритм работы следующий: по переднему, восходящему фронту на PC8 срабатывает прерывание, в котором перезапускается таймер 4. По переднему восходящему фронту на PB6 происходит захват значение счетчика, по этому событию происходит передача по DMA значения из регистра ССR1 в буфер. Частота сигнала? Думаю запускать таймер в прерывании не правильно, от фронта до запуска таймера непонятно сколько времени пройдёт. Я бы объединил два сигнала какой-то мелкой логикой и на один вход захвата, ловить два фронта. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
LEVENVORF 0 20 января, 2012 Опубликовано 20 января, 2012 · Жалоба В исходном виду у вас прерывание вообще не происходит до полного окончания DMA трансфера. Вы измеряете интервал между импульсами на PB6, а не разность фаз, естественно результат неверен. Впрочем если вы предпочитаете ржать над советами - копайтесь сами. Успехов. В моем виде, когда инициализация таймера стоит перед инициализацией EXTI, глюки по DMA ТОЧНО ТАКИЕ ЖЕ, как и в том варианте, который предложили Вы. Первое измерение в моем варианте действительно может быть неверным. Но как только на PB6 придет импульс, произойдет захват, передача по DMA и инициализация EXTI. Так что все остальные циклы измерения должны быть верными. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
LEVENVORF 0 20 января, 2012 Опубликовано 20 января, 2012 · Жалоба Проблема решилась! Вся проблема в том, что значения буфера смотрел в Debug'e. И судя по всему входя в режим отладки переферия останавливается неодновременно. Т.е. NVIC, скорее всего, останавливался первым, тем самым переставал сбрасываться счетчик, а DMA c таймером продолжали работать. Частично заполняя буффер некорректными данными. Большое всем спасибо за помощь!!! Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться