【STM32學習】(22)STM32實現360度旋轉編碼器

360度 旋轉編碼器實物如下:

KY-040旋轉編碼器模塊

 工作電壓:5V

一圈脈衝數:20

旋轉編碼器可通過旋轉可以計數正方向和反方向轉動過程中輸出脈衝的次數,旋轉計數不像電位計,這種轉動計數是沒有限制的。配合旋轉編碼器上的按鍵,可以復位到初始狀態,即從0開始計數。

 工作原理:增量編碼器是一種將旋轉位移轉換爲一連串數字脈衝信號的旋轉式傳感器。這些脈衝用來控制角位移。在Eltra編碼器中角位移的轉換採用了光電掃描原理。讀數系統以由交替的透光窗口和不透光窗口構成的徑向分度盤(碼盤)的旋轉爲依據,同時被一個紅外光源垂直照射,光把碼盤的圖像投射到接收器表面上。接收器覆蓋着一層衍射光柵,它具有和碼盤相同的窗口寬度。接收器的工作是感受光盤轉動所產生的變化,然後將光變化轉換成相應的電變化。再使低電平信號上升到較高電平,併產生沒有任何干擾的方形脈衝,這就必須用電子電路來處理。讀數系統通常採用差分方式,即將兩個波形一樣但相位差爲180°的不同信號進行比較,以便提高輸出信號的質量和穩定性。讀數是再兩個信號的差別基礎上形成的,從而消除了干擾。

增量編碼器給出兩相方波,它們的相位差90°,通常稱爲A通道和B通道。其中一個通道給出與轉速相關的信息,與此同時,通過兩個通道信號進行順序對比,得到旋轉方向的信息。還有一個特殊信號稱爲Z或零通道,該通道給出編碼器的絕對零位,此信號是一個方波與A通道方波的中心線重合。

 

現在實現檢測這個增量編碼器正轉還是反轉

我們這裏用讀取IO的方式來讀取數據,來判斷是正轉還是反轉。

單片機型號:STM32L052K8*

接線:CLK  接  PA0

            DT   接  PA1

            SW  接  PA2

int main(void)
{
  /* USER CODE BEGIN 1 */
	unsigned char dt;
	unsigned char clk,key;
  /* USER CODE END 1 */

  /* MCU Configuration--------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* Configure the system clock */
  SystemClock_Config();

  /* USER CODE BEGIN SysInit */

  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_USART1_UART_Init();
  /* USER CODE BEGIN 2 */
	printf("\n\r****wantin****\n\r");
  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
	  printf("\n\**************\n\r");
	  clk = HAL_GPIO_ReadPin(DT_GPIO_Port,DT_Pin);
	  dt = HAL_GPIO_ReadPin(DT_GPIO_Port,DT_Pin);
	  key = HAL_GPIO_ReadPin(SW_GPIO_Port,SW_Pin);
	  if(1 == clk)
	  {
		  printf("\n\clk == 1\n\r");
	  }
	  else
	  {
		  printf("\n\clk == 0\n\r");
	  }
	  if(1 == dt)
	  {
		  printf("\n\dt == 1\n\r");
	  }
	  else
	  {
		  printf("\n\dt == 0\n\r");
	  }
	  if(1 == key)
	  {
		  printf("\n\key == 1\n\r");
	  }
	  else
	  {
		  printf("\n\key == 0\n\r");
	  }
	  HAL_Delay(1000);
  }
  /* USER CODE END 3 */
}

 

實現效果來看,不理想:

不管你正轉還是反轉,CLK和DT這兩個引腳的電平,都是成0、1交替,而且兩個的電平一致,根本無法區分正轉還是反轉。

隨後,將其插上電源,用示波器測試了一下這兩個引腳產生的波形。效果如下:

採集中斷0口,接的clk信號

正轉的波形圖:黃色的線爲clk,藍色的線爲dt

下降沿觸發,採集到的電平  都爲低電平  clk = 0   dt = 0;

反轉的波形圖:黃色的線爲clk,藍色的線爲dt

下降沿觸發,採集到的電平  clk = 0   dt = 1;

通過波形可以看出,正反轉是有波形區別的,如何實現正反轉檢測,可以使用中斷的方式來實現。

採用下降沿觸發方式來採集波形的變化。

int main(void)
{
  /* USER CODE BEGIN 1 */
	unsigned char dt;
	unsigned char clk,key;
  /* USER CODE END 1 */

  /* MCU Configuration--------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* Configure the system clock */
  SystemClock_Config();

  /* USER CODE BEGIN SysInit */

  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_USART1_UART_Init();
  /* USER CODE BEGIN 2 */
	printf("\n\r****wantin****\n\r");
  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
	  printf("\n\**************\n\r");
	  if(10 == spped_counter)
	  {
		  printf("\n\***正轉***\n\r");
	  }
	  else
	  {
		  printf("\n\***反轉***\n\r");
	  }
//	  clk = HAL_GPIO_ReadPin(DT_GPIO_Port,DT_Pin);
//	  dt = HAL_GPIO_ReadPin(DT_GPIO_Port,DT_Pin);
//	  key = HAL_GPIO_ReadPin(SW_GPIO_Port,SW_Pin);
//	  if(1 == clk)
//	  {
//		  printf("\n\clk == 1\n\r");
//	  }
//	  else
//	  {
//		  printf("\n\clk == 0\n\r");
//	  }
//	  if(1 == dt)
//	  {
//		  printf("\n\dt == 1\n\r");
//	  }
//	  else
//	  {
//		  printf("\n\dt == 0\n\r");
//	  }
//	  if(1 == key)
//	  {
//		  printf("\n\key == 1\n\r");
//	  }
//	  else
//	  {
//		  printf("\n\key == 0\n\r");
//	  }
	  HAL_Delay(1000);
  }
  /* USER CODE END 3 */
}
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)  //外部中斷 回調函數
{
	if(GPIO_Pin == CLK_Pin) //檢測到有變化就進來處理
	{
		if(HAL_GPIO_ReadPin(CLK_GPIO_Port,CLK_Pin) == HAL_GPIO_ReadPin(DT_GPIO_Port,DT_Pin))  //clk pb0 == dt pb1
		spped_counter=10;		//	表示 正轉
		else
		spped_counter=100;		//	表示 反轉
		
	}
}

 

 

效果如下:

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章