前言
旋轉編碼器可以360度有段式 正/反轉及按壓點擊
- Vcc:可以5V/3V
- PUSH:按壓電關
- A:編碼器輸出相位A
- B:編碼器輸出相位B
此模組有預先上除彈跳電容,升壓電阻及接地電阻 比便方便使用
實際使用輸出的波形,一般不動作時相位A/B皆為High(高電位)
正轉一格,A相先變low隨即B相變low,然後A相拉high B相才拉high
反轉一格,B相先變low隨即A相變low,然後B相拉high A相才拉high
所以在程式上我是由AB相位的Rising edge(上升電位變化)觸發中斷事件,來偵測AB相的電位
- 正轉:A相觸發,AB相位的電位為10;然後B相觸發,AB相位的電位為11
- 反轉:B相觸發,AB相位的電位為01;然後A相觸發,AB相位的電位為11
判斷AB相值為10時正轉,01為反轉;其餘數值不予理會
操作環境
- Board:32F072BDISCOVERY
- IDE:STM32CubeIDE
- Code:STM32CubeMX
MCU I/O配置
- Input(上升中斷觸發):PC13 (Phase A)
- Input(上升中斷觸發):PC14 (Phase B)
- UART:UART1(TX PA9,RX PA10)(用來輸出旋鈕正反轉加減計數數值)
1. STM32CubeMX
選二個帶中斷觸發的Input,這裡用PC13 PC14,
GPIO mode設為 External Interrupt Mode with Rising edge trigger detection
確認NVIC裡的 EXTI line 4 to 15 interrupts有被勾選, IO中斷才會啟動
2. STM32CubeIDE
為UART添加printf的宣告
main.c
/* USER CODE BEGIN PV */
#ifdef __GNUC__
/* With GCC/RAISONANCE, small printf (option LD Linker->Libraries->Small printf
set to 'Yes') calls __io_putchar() */
#define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
#else
#define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
#endif /* __GNUC__ */
PUTCHAR_PROTOTYPE
{
/* Place your implementation of fputc here */
/* e.g. write a character to the USART1 and Loop until the end of transmission */
HAL_UART_Transmit(&huart1, (uint8_t *)&ch, 1, HAL_MAX_DELAY);
return ch;
}
/* USER CODE END PV */
增加函式PhaseAB()來偵測AB相位正反轉,正轉時回傳1,反轉時回傳-1
main.c
/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
int8_t PhaseAB(void)
{
//Forward rotation +1
//Reverse rotation -1
uint8_t bit1 = HAL_GPIO_ReadPin(GPIOC, GPIO_PIN_13);//Phase A
uint8_t bit0 = HAL_GPIO_ReadPin(GPIOC, GPIO_PIN_14);//Phase B
uint8_t result = 0;
result |= (bit1<<1);
result |= (bit0<<0);
if(result == 2) return 1;
else if(result == 1) return -1;
else return 0;
}
/* USER CODE END 0 */
添加IO中斷事件 HAL_GPIO_EXTI_Callback(),在AB相位觸發Rising edge事件時,呼叫 PhaseAB()為value數值加減1
並透出UART輸出value數值
main.c
/* USER CODE BEGIN 4 */
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
static uint8_t value;
if(PhaseAB() == 1)
{
if(value <0xFF) value++;
printf("%02X\n\r", value);
}else if(PhaseAB() == -1)
{
if(value >0) value--;
printf("%02X\n\r", value);
}
}
/* USER CODE END 4 */