Да не, с настройками все отлично - проект оказался рабочим. Если перевести пины в режим IN FLOAT и подтяжку пина сделать внешнюю - резистором, все отлично работает. Похоже, это глюк такой. Тогда как ученые умы подключают к этому камню кнопки? Это же какое расточительство резисторов? Безобразие!
Кстати, энкодер оказался не очень честный - в некотором секторе дребезг контактов ощутим. Либо надо ставить конденсатор и оставлять, как есть. Либо отказываться от использования прерывания по спаду фронта и опрашивать пин по таймеру, чего очень не хотелось делать. Но вариант проверенный - придется.
Кстати, до этого пытался запустить прерывание, используя библиотеки ST. Вот инициализация:
Код:
|
int main(void)
{
GPIO_InitTypeDef GPIO_InitStruct;
NVIC_InitTypeDef NVIC_InitStructure;
EXTI_InitTypeDef EXTI_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB|RCC_AP B2Periph_GPIOC|RCC_APB2Periph_AFIO, ENABLE);
//LEDs init
GPIO_InitStruct.GPIO_Pin=BLUE_LED|GREEN_LED;
GPIO_InitStruct.GPIO_Mode=GPIO_Mode_Out_PP;
GPIO_InitStruct.GPIO_Speed=GPIO_Speed_10MHz;
GPIO_Init(GPIOC, &GPIO_InitStruct);
//Encoder Pins init
GPIO_InitStruct.GPIO_Pin=ENCODER_Q1_PIN|ENCODER_Q2 _PIN;
GPIO_InitStruct.GPIO_Mode=GPIO_Mode_IPU;
GPIO_InitStruct.GPIO_Speed=GPIO_Speed_10MHz;
GPIO_Init(ENCODER_GPIO, &GPIO_InitStruct);
/* Connect EXTI Line to Button GPIO Pin */
GPIO_EXTILineConfig(GPIO_PortSourceGPIOB, GPIO_PinSource0);
/* Configure EXTI line */
EXTI_InitStructure.EXTI_Line = EXTI_Line0;
EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;
EXTI_InitStructure.EXTI_LineCmd = ENABLE;
EXTI_Init(&EXTI_InitStructure);
/* Enable and set EXTI Interrupt to the lowest priority */
NVIC_InitStructure.NVIC_IRQChannel = EXTI0_IRQChannel;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriori ty = 0x0F;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x0F;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
while(1)
} |
Ничего не заработало вообще. Точнее прерывание вызывается, в файле stm32f10x_it.c добавлена процедура сброса:
void EXTI0_IRQHandler(void)
{
EXTI_ClearITPendingBit(EXTI_Line0);
EXTI0_Interrupt();
}
Но проц зависает. А где именно - выловить не могу. В дебаггере дохожу до цикла while(1), поворачиваю энкодер, проц куда-то отправляется чего-то делать, указатель исчезает и ничего не происходит. Помогает только RESET.
Вот еще хороший вопрос. Как и где обрабатывать прерывания - очень понятно. Не понятно совершенно, где искать, какие флаги сбрасывать. Это просто кошмар - любая элементарная задача начинается с поиска готового решения, чтобы передрать строчку кода.
Нельзя сразу было в stm32f10x_it.c флаги обозначить?
А вот рабочий как часы код для опроса энкодера по таймеру с защитой от дребезга:
Код:
|
void TIM1_UP_TIM16_IRQHandler (void)
{
if (((GPIOB-›IDR&GPIO_Pin_0)!=0)&button_pressed==0)
{
button_pressed=1;
if ((GPIOB-›IDR&GPIO_Pin_1)!=0){cnt++;flag=0xff;}else{cnt--;flag=0xff;}
}
if (((GPIOB-›IDR&GPIO_Pin_0)==0)&button_pressed!=0)
{
button_pressed=0;
}
TIM1-›SR &= ~(1‹‹0);
} |
Период таймера определяется максимальной скоростью вращения энкодера. Я поставил 10мс.
Такой код я бы не стал применять в измерительных энкодерах, когда пропуск одного зуба приведет к выходу из строя какого-нибудь привода.