reg33 0 20 апреля, 2023 Опубликовано 20 апреля, 2023 (изменено) · Жалоба Добрый день. Пытаюсь подключить к stm32f103 энкодер. Энкодер планирую опрашивать в прерываниях по таймеру. Написал функцию int encoderCnt; int encoderState; void readEncoderState(){ if(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_7)!=encoderState){ if(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_6)!=encoderState){ encoderCnt++; printf ("%u \r\n",encoderCnt); } else { encoderCnt--; printf ("%u \r\n",encoderCnt); } } encoderState=HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_7); } она упорно только инкрементирует. Функция вызывается в прерываниях по таймеру с частотой 4 кГЦ. Что я делаю не так? За ранее благодарен. Изменено 21 апреля, 2023 пользователем haker_fox Для оформления кода есть кнопка <>. Для STM32 есть свой подраздел. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jcxz 242 20 апреля, 2023 Опубликовано 20 апреля, 2023 · Жалоба 23 минуты назад, reg33 сказал: Что я делаю не так? За ранее благодарен. printf() в прерываниях - это вообще зашквар. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
EdgeAligned 85 20 апреля, 2023 Опубликовано 20 апреля, 2023 (изменено) · Жалоба а может он нестандартный, с микрореализацией? 🙂 На STM32F103 есть таймеры. А в таймерах - есть режим аппаратного энкодера! Если эту тему изучить, то будет "вэри гут". Сигналы энкодера выглядят вот так (сигнал 0DINDX не учитывать) : следовательно, если смотреть в эту картинку и дешифровывать состояния входов, то можно написать логику энкодера. Изменено 20 апреля, 2023 пользователем EdgeAligned Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Basil13 3 20 апреля, 2023 Опубликовано 20 апреля, 2023 · Жалоба Если программно: Надо завести четыре переменные: текущее показание энкодера, прошлое показание энкодера, изменение, положение. И там и там могут быть 4 состояния. Создается массив результатов 4х4 (HALL[4,4]) всех возможных комбинаций. В этом массиве есть нули, +1, -1 и, допустим, 2(ошибка - энкодер сбился). изменение = HALL[текущее показание энкодера, прошлое показание энкодера]; if(изменение == 2){ошибка}; положение += изменение; После опроса и в самом начале прошлое показание энкодера = текущее показание энкодера; Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
mitya1698 18 20 апреля, 2023 Опубликовано 20 апреля, 2023 · Жалоба пару недель назад была тема и было вариантов 5 кода, с разной степенью эффективности посмотрите. пару недель назад была тема и было вариантов 5 кода, с разной степенью эффективности посмотрите. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
xvr 12 21 апреля, 2023 Опубликовано 21 апреля, 2023 · Жалоба On 4/20/2023 at 2:55 PM, reg33 said: if(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_6)!=encoderState){ Вместо этого поставьте On 4/20/2023 at 2:55 PM, reg33 said: if(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_6)){ Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
reg33 0 26 апреля, 2023 Опубликовано 26 апреля, 2023 (изменено) · Жалоба On 4/22/2023 at 1:04 AM, xvr said: Вместо этого поставьте не помогло. написал следующую функцию Spoiler void encoderState_1 () { if ((!HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_6)) && ( ! HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_7))){ statusEnc=0x00; } else if (HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_6) && ( ! HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_7))){ statusEnc=0x10; } else if (HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_6) && (HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_7))){ statusEnc=0x11; } else if ((!HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_6)) && (HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_7))){ statusEnc=0x01; } //-----inc if ((status_old_Enc == 0x01) && (statusEnc==0x00 )){ encoderCnt++; printf ("st_+00 \r\n"); } else if ((status_old_Enc == 0x00) && (statusEnc==0x10 )){ encoderCnt++; printf ("st_+10 \r\n"); } else if ((status_old_Enc == 0x10) && (statusEnc==0x11 )){ encoderCnt++; printf ("st_+11 \r\n"); } else if ((status_old_Enc == 0x11) && (statusEnc==0x01)){ encoderCnt++; printf ("st_+01 \r\n"); } //------ dec else if ((status_old_Enc == 0x00) && (statusEnc==0x01)){ encoderCnt--; printf ("st_-01 \r\n"); } else if ((status_old_Enc == 0x10) && (statusEnc==0x00 )){ encoderCnt--; printf ("st_-00\r\n"); } else if ((status_old_Enc == 0x11) && (statusEnc==0x10 )){ encoderCnt--; printf ("st_-10 \r\n"); } else if ((status_old_Enc == 0x01) && (statusEnc==0x11)){ encoderCnt--; printf ("st_-11 \r\n"); } else; status_old_Enc=statusEnc; } Все равно считает только в плюс. Подключил лог.анализатор к PIN 7 порта_A к GLK энкодера и PIN 6 порта_А к DT энкодера. Скрин с лог анализатора прилагаю Изменено 27 апреля, 2023 пользователем haker_fox Код нужно прятать в теги. А длинный код ещё и помещать в спойлер. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
mitya1698 18 26 апреля, 2023 Опубликовано 26 апреля, 2023 · Жалоба const uint16_t StepDir = 0x2442; uint16_t tmp = (EncState ^ ((GPIOA ->IDR) >> 6)) & 0b11; if((tmp == 0b01) || (tmp == 0b10)) { if(StepDir & (1<<(tmp | (EncState << 2)))) StepD++; else StepD--; } EncState ^= tmp; Этот код решительно не нравится из той темы? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Obam 38 26 апреля, 2023 Опубликовано 26 апреля, 2023 · Жалоба не помогло. написал следующую функцию ...Все равно считает только в плюс. Ну а какая проблема под отладчиком смотреть, что читается с порта, как меняется состояние и куда ветвится подпрограмма? Не надо быстро крутить, каждый переход будет виден. Кстати, зачем 4 раза (HAL_GPIO_ReadPin(GPIOA,..) читаются входы: один раз считал - получил "00" или "01", или "10", или "11". Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jcxz 242 26 апреля, 2023 Опубликовано 26 апреля, 2023 · Жалоба 10 минут назад, Obam сказал: Кстати, зачем 4 раза (HAL_GPIO_ReadPin(GPIOA,..) читаются входы: один раз считал - получил "00" или "01", или "10", или "11". Как зачем? Неужто не поняли? Естественно - чтобы в каких-то случаях (когда звёзды так сложились) в statusEnc получать случайное значение. Так как локальная автоматическая неинициализированная переменная внутри функции, имеет такое пакостное свойство. А если statusEnc - глобальная (хотя - на кой??? ), иногда получать предыдущее значение. PS: А printf() внутри ISR в этом коде недоразумении вас значит - нисколько не смутил? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Obam 38 26 апреля, 2023 Опубликовано 26 апреля, 2023 · Жалоба Как зачем? Неужто не поняли? Естественно - чтобы в каких-то случаях (когда звёзды так сложились) в statusEnc получать случайное значение. Так как локальная автоматическая неинициализированная переменная внутри функции, имеет такое пакостное свойство. Как-то, возможно, по простоте душевной, считал, что два бита из одного и того же порта вычитываются одной операцией, и пытался намекнуть об сём... И простите, (((-8Ж в void encoderState_1 () {бла-бла-бла} - не наблюдаю признаков обработчика прерывания ;-) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jcxz 242 26 апреля, 2023 Опубликовано 26 апреля, 2023 · Жалоба 1 час назад, Obam сказал: - не наблюдаю признаков обработчика прерывания 😉 Пронаблюдайте в первом сообщении. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Obam 38 27 апреля, 2023 Опубликовано 27 апреля, 2023 · Жалоба Вообще, да... но прошла, считай, неделя - и концепция ТСа могла смениться, и просветление нагрянуть (-; Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
mitya1698 18 27 апреля, 2023 Опубликовано 27 апреля, 2023 · Жалоба В 26.04.2023 в 23:17, Obam сказал: Кстати, зачем 4 раза (HAL_GPIO_ReadPin(GPIOA,..) читаются входы: один раз считал - получил "00" или "01", или "10", или "11". Кажется в хале нет ReadPort целиком :) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
reg33 0 27 апреля, 2023 Опубликовано 27 апреля, 2023 (изменено) · Жалоба 7 hours ago, Obam said: Вообще, да... но прошла, считай, неделя - и концепция ТСа могла смениться, и просветление нагрянуть (-; Вроде все сложилось. На мой взгляд самый объективный получился считает без пропусков, функция юзается в прерываниях 4кГц. void readEncoderState(){ if(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_7)!=encoderState){ if(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_6)!=encoderState){ encoderCnt++; printf ("%u \r\n",encoderCnt); } else { encoderCnt--; printf ("%u \r\n",encoderCnt); } } encoderState=HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_7); if(encoderCnt<=1) {encoderCnt=0;} if(encoderCnt>=30) {encoderCnt=30;} } опыта написания кода у меня мало, поэтому использовал printf (); для вывода в консоль. Изменено 27 апреля, 2023 пользователем haker_fox Для оформления кода есть кнопка <>. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться