|
DMA и таймер в режиме захвата |
|
|
|
Jan 18 2012, 13:36
|
Участник

Группа: Участник
Сообщений: 18
Регистрация: 14-03-10
Из: BELARUS
Пользователь №: 55 953

|
Необходимо измерить смещение фазы между двумя сигналами. Использую 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);
} }
|
|
|
|
|
 |
Ответов
|
Jan 18 2012, 16:58
|
Участник

Группа: Участник
Сообщений: 57
Регистрация: 9-07-08
Из: Волгоградская обл
Пользователь №: 38 838

|
Цитата(LEVENVORF @ Jan 18 2012, 16:36)  Необходимо измерить смещение фазы между двумя сигналами. Использую STM32F103RC6T. Первый сигнал заведен на PC8, и настроено внешнее прерывание по этому входу, второй сигнал заведен на PB6 (TIM4_CH1). Алгоритм работы следующий: по переднему, восходящему фронту на PC8 срабатывает прерывание, в котором перезапускается таймер 4. По переднему восходящему фронту на PB6 происходит захват значение счетчика, по этому событию происходит передача по DMA значения из регистра ССR1 в буфер. Проблема в следующем: часть буфера заполняется некорректными значениями. Закономерности не выявил т.е. могут быть ошибки в начале, потом правильные данные, потом опять ошибки, а может быть наоборот. Пробовал по СС1 генерить не DMA запрос, а прерывание, и в нем вычитавать значение CCR1, тогда все работает, и значения корректные. Измеряемые сигналы пока беру с образцового генератора.
}[/code] пожалуста весь проектик в студию.
|
|
|
|
|
Jan 18 2012, 17:29
|
Участник

Группа: Участник
Сообщений: 18
Регистрация: 14-03-10
Из: BELARUS
Пользователь №: 55 953

|
Цитата(vvkka @ Jan 18 2012, 19:58)  пожалуста весь проектик в студию. Код 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); }
Сообщение отредактировал LEVENVORF - Jan 18 2012, 17:29
|
|
|
|
Сообщений в этой теме
LEVENVORF DMA и таймер в режиме захвата Jan 18 2012, 13:36  vvkka вобще то имел виду полную выклодку в той программе... Jan 18 2012, 19:08 Flexz Tim_Capture_Init() запускает DMA и ждет его оконча... Jan 18 2012, 19:51 LEVENVORF Цитата(Flexz @ Jan 18 2012, 22:51) Tim_Ca... Jan 19 2012, 14:52 Flexz Цитата(LEVENVORF @ Jan 19 2012, 17:52) Вс... Jan 20 2012, 06:26 LEVENVORF Цитата(Flexz @ Jan 20 2012, 09:26) В исхо... Jan 20 2012, 10:32 V_M_Luck Цитата(Flexz @ Jan 20 2012, 08:26) В исхо... Jan 20 2012, 07:13 skripach ЦитатаАлгоритм работы следующий: по переднему, вос... Jan 20 2012, 08:48 LEVENVORF Проблема решилась! Вся проблема в том, что зна... Jan 20 2012, 12:58
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|