|
stm32 + абсолютный энкодер |
|
|
|
Oct 20 2014, 13:56
|
Частый гость
 
Группа: Участник
Сообщений: 97
Регистрация: 23-10-12
Пользователь №: 74 054

|
Здравствуйте уважаемые форумчане! Хотел спросить у вас совета. Есть абсолютный энкодер с 1024 отсчетами угла поворота и stm32 работающий на 72 МГц, данные с энкодера передаются на МК через 10 выводов. Вал энкодера соединен с валом двигателя через шестерню с передаточным числом 1/7. Была написана программа для определения угла поворота и передачи его на ПК через UART. Тут возникло две проблемы: 1. Данные на ПК иногда передаются не корректно; 2. Как преобразовать угол поворота энкодера в угол поворота двигателя. вот код: CODE #include "main.h" ////////////////////////////////////////////////////////////////////// int main(void){ init_timer(); init_gpio(); init_clock(); init_uart(); for(i = 0; i < 200000; i++); if(!RCC_CFGR_SWS_HSE){ GPIOA->ODR ^= GPIO_Pin_0; } Usart2_Send_String("Hello, world!"); //Передаем строку, сообщающую о готовности микроконтроллера к обмену данными NVIC_SetPriority(TIM3_IRQn, 1); while(1){ if(State == 1){ NVIC_DisableIRQ(TIM3_IRQn); State = 0; D0 = GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_6); D1 = GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_11); D2 = GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_10); D3 = GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_9); D4 = GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_8); D5 = GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_15); D6 = GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_14); D7 = GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_13); D8 = GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_12); D9 = GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_11); pos = D0 | (D1 << 1) | (D2 << 2) | (D3 << 3) | (D4 << 4) | (D5 << 5) | (D6 << 6) | (D7 << 7) | (D8 << 8) | (D9 << 9); if(pos <= convert.INT){ while(!(USART2->SR & USART_SR_TC)); //Проверяем установку флага TC - завершения предыдущей передачи USART_SendData(USART2, convert.CHAR[0]); for(i = 0; i < 100; i++); while(!(USART2->SR & USART_SR_TC)); //Проверяем установку флага TC - завершения предыдущей передачи USART_SendData(USART2, convert.CHAR[1]); pos = convert.INT; } NVIC_EnableIRQ(TIM3_IRQn); } for(i = 0; i < 100000; i++); } return 0; } void init_gpio(void){ GPIO_InitTypeDef gpio_cfgA, gpio_cfgB, gpio_cfgLED; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); GPIO_StructInit(&gpio_cfgA); GPIO_StructInit(&gpio_cfgB); GPIO_StructInit(&gpio_cfgLED); gpio_cfgA.GPIO_Mode = GPIO_Mode_IN_FLOATING; //GPIO_Mode_Out_PP; gpio_cfgA.GPIO_Pin = GPIO_Pin_12 | GPIO_Pin_11| GPIO_Pin_10 | GPIO_Pin_9 | GPIO_Pin_8 | GPIO_Pin_6; gpio_cfgA.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOA, &gpio_cfgA); gpio_cfgB.GPIO_Mode = GPIO_Mode_IN_FLOATING; //GPIO_Mode_Out_PP; gpio_cfgB.GPIO_Pin = GPIO_Pin_15 | GPIO_Pin_14| GPIO_Pin_13 | GPIO_Pin_12 | GPIO_Pin_11; gpio_cfgB.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOB, &gpio_cfgB); gpio_cfgLED.GPIO_Mode = GPIO_Mode_Out_PP; gpio_cfgLED.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1; gpio_cfgLED.GPIO_Speed = GPIO_Speed_2MHz; GPIO_Init(GPIOA, &gpio_cfgLED); } void init_timer(){ RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE); /* Не забываем затактировать таймер */ TIM_TimeBaseInitTypeDef timer_base; TIM_TimeBaseStructInit(&timer_base); timer_base.TIM_Prescaler = 720 - 1; /* Делитель учитывается как TIM_Prescaler + 1, поэтому отнимаем 1 */ timer_base.TIM_Period = 1; TIM_TimeBaseInit(TIM3, &timer_base); /* Настраиваем захват сигнала: - канал: 1 - счёт: по нарастанию - источник: напрямую со входа - делитель: отключен - фильтр: отключен */ TIM_ICInitTypeDef timer_ic; timer_ic.TIM_Channel = TIM_Channel_1; timer_ic.TIM_ICPolarity = TIM_ICPolarity_BothEdge; //TIM_ICPolarity_Rising; timer_ic.TIM_ICSelection = TIM_ICSelection_DirectTI; timer_ic.TIM_ICPrescaler = TIM_ICPSC_DIV1; timer_ic.TIM_ICFilter = 2; TIM_PWMIConfig(TIM3, &timer_ic); /* Эта функция настроит канал 1 для захвата периода, а канал 2 - для захвата заполнения. */ TIM_SelectInputTrigger(TIM3, TIM_TS_TI1FP1); /* Выбираем источник для триггера: вход 1 (PA6) */ TIM_SelectSlaveMode(TIM3, TIM_SlaveMode_Reset); /* По событию от триггера счётчик будет сбрасываться. */ TIM_SelectMasterSlaveMode(TIM3, TIM_MasterSlaveMode_Enable); /* Включаем события от триггера */ TIM_ITConfig(TIM3, TIM_IT_CC1, ENABLE); /* Разрешаем таймеру генерировать прерывание по захвату */ TIM_Cmd(TIM3, ENABLE); /* Включаем таймер */ NVIC_EnableIRQ(TIM3_IRQn); /* Разрешаем прерывания таймера TIM3 */ } void TIM3_IRQHandler(){ if (TIM_GetITStatus(TIM3, TIM_IT_CC1) != RESET) { TIM_ClearITPendingBit(TIM3, TIM_IT_CC1); /* Даём знать, что обработали прерывание */ State = 1; GPIOA->ODR ^= GPIO_Pin_1; } } Заранее спасибо!!!
Сообщение отредактировал IgorKossak - Oct 20 2014, 14:13
Причина редактирования: [codebox] для длинного кода, [code] - для короткого!!!
--------------------
|
|
|
|
|
 |
Ответов
|
Oct 21 2014, 09:05
|
Знающий
   
Группа: Участник
Сообщений: 643
Регистрация: 29-05-09
Из: Германия
Пользователь №: 49 725

|
Цитата(net @ Oct 21 2014, 09:35)  я имел ввиду что считывание может попасть на момент переключения - если запись в регистр данных с устройства не стробируется Вопрос в том, каково соотношение частот переключения и опроса. Можно ограничиться конкретным случаем и решить, что соотношение разительное, и процессор сто раз успеет. Вполне допустимый подход. Можно, однако, подойти обще и применить фильтрацию, которая исключит сбои и в случае, если завтра моторчик шустро раскрутится, а процессор будет напевать MP3 песенку. Мне в этой связи вспоминается статья (кажется на Хабре) об упавшей ракете Ariane: когда стали разбираться, нашли, что самоликвидация произошла из-за старого участка кода управления, который посчитал более выское ускорение модифицированных двигателей ракеты отклонением от нормы.
Сообщение отредактировал KnightIgor - Oct 21 2014, 09:06
|
|
|
|
Сообщений в этой теме
Alexsandr000 stm32 + абсолютный энкодер Oct 20 2014, 13:56      Alexsandr000 Цитата(net @ Oct 21 2014, 14:41) нееее - ... Oct 21 2014, 10:58       AHTOXA Цитата(Alexsandr000 @ Oct 21 2014, 16:58)... Oct 21 2014, 17:53      KnightIgor Цитата(net @ Oct 21 2014, 12:41) нееее - ... Oct 22 2014, 07:29 Alexsandr000 Это я сделал
CODE#include "main.h"
/////... Oct 21 2014, 05:14 KnightIgor Цитата(Alexsandr000 @ Oct 21 2014, 07:14)... Oct 21 2014, 07:07 Alexsandr000 сделал так, но теперь не пойму почему данные с UAR... Oct 21 2014, 09:14 Alexsandr000 Огромное всем спасибо!!!
Ну сбоить буд... Oct 22 2014, 08:13 Golikov A. что за бред?
если у вас на столе сбоит, на объекте... Oct 22 2014, 08:35 AHTOXA Цитата(Golikov A. @ Oct 22 2014, 14:35) Е... Oct 22 2014, 09:59 Alexsandr000 добавил проверку ошибки исчезли
Кодconvert.INT = p... Oct 22 2014, 09:59
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|