iT邦幫忙

第 12 屆 iT 邦幫忙鐵人賽

DAY 16
1
IoT

熟悉Arduino的Maker必看!30天帶你快速入門基於STM32嵌入式開發~系列 第 16

[Day 16]-【STM32系列】ADC and Joystick 搖桿控制

ADC (Analog-to-Digital Converter)

ADC 即數位類比轉換器,將一連串連續的類比訊號(或物理量)轉換為數位訊號
https://ithelp.ithome.com.tw/upload/images/20201001/20120093FpQUsvk0oq.png
概念類似於將單位時間內瞬間的每一點電壓轉換為數位訊號

自然界的訊號皆為類比電壓,時間大小是連續的
而ADC則是將類比形式的連續訊號轉換為數位形式的離散訊號的一種設備
當嵌入式開發當中需要讀取周遭環境例如溫溼度、壓力等,就需要ADC將類比訊號轉換為數位訊號

ADC取樣率

  • 多久對輸入的類比訊號進行一次轉換,取樣率越高,得到的數位訊號會越接近類比訊號

ADC解析度

即類比電壓轉換成數位後,轉換為多準確的數位值,解析度越高,訊號越精準
因為訊號以二進制方式儲存,通常以位元(bit)為單位
以12bit的解析度為例,總共有2^12=4096階,實際表示方式可能為0~4095
假設電壓上限為 0~5V,則數位訊號需要上升一個單位需要(5V-0V)/ (2^12-1)=0.0012V
假設讀取的值為1000,實際電壓即1000*0.0012=1.2V

Joystick 搖桿

Joystick的原理就是透過改變(X,Y)兩軸電阻的分壓值
我們就可以透過ADC將類比訊號轉換為數位訊號
幾乎就可以當作搖桿使用 (他本來就是搖桿啊!XD)
https://ithelp.ithome.com.tw/upload/images/20201001/20120093U4MuSHWcr5.jpg
Joystick-Module接腳
Vcc : 正電源
GND : 接地
VRX : X軸分量
VRY : Y軸分量
SW : 按鈕

Setup

今天的目標是控制搖桿使用ADC讀取這些引腳,當搖桿在向上位置時,上方LED燈就亮,反之不亮,其餘向下、左、右以此類推,當搖桿按鈕被按下,點亮中間的LED。來看看下面CubeMX的設定

https://ithelp.ithome.com.tw/upload/images/20201001/20120093ohfXBHoFe5.png

跟往常一樣設定RCC -> HSE、LSE為Crystal/Ceramic Resonator
SYS -> Debug Serial Wire 打勾
將ADC -> IN0、IN1作為搖桿X-Y軸的輸入引腳
預設PIN腳會是PA0、PA1
同時我們需要PA2設定GPIO_Input做按鈕偵測
PA3~PA7設定GPIO_Output供應點亮LED
分別是上、下、左、右、中心。

https://ithelp.ithome.com.tw/upload/images/20201001/20120093mwsW2dOAkz.png
頻率直接給他最大下去了啦

https://ithelp.ithome.com.tw/upload/images/20201001/20120093x5GC2VeX6M.png
https://ithelp.ithome.com.tw/upload/images/20201001/20120093NE1rH4p4Uu.png
開啟DMA,DMA不須透過CPU讓ADC自動讀取值放在指定的記憶體位置,使用者只須到指定的記憶體提取資料即可
1.DMA Settings
2.ADD
3.Choose ADC
4.Data Width -> Word(32bit)
5.apply and ok
---生成檔案---

程式碼部分

uint32_t joy[]={0,0};

為了儲存12 bit的ADC值(搖桿的X-Y分量),我宣告了一個包兩個變數的陣列

HAL_ADC_Start_DMA(&hadc, joy, 2);

我們要讀取ADC1的多個通道,我們必須使用DMA來做到這一點
在上面的code中,DMA 將讀取 ADC1 的 2 個通道,並將資料儲存到我們指定的joy陣列,且有兩筆資料

while(1)

  if (joy[1]>=4000)  //up
      HAL_GPIO_WritePin( GPIOA, GPIO_PIN_3, GPIO_PIN_SET);
  else
      HAL_GPIO_WritePin( GPIOA, GPIO_PIN_3, GPIO_PIN_RESET);
      
  if (joy[1]<=800)  //down
      HAL_GPIO_WritePin( GPIOA, GPIO_PIN_4, GPIO_PIN_SET);
  else
      HAL_GPIO_WritePin( GPIOA, GPIO_PIN_4, GPIO_PIN_RESET);
      
  if (joy[0]>=4000)  //right
      HAL_GPIO_WritePin( GPIOA, GPIO_PIN_5, GPIO_PIN_SET);
  else
      HAL_GPIO_WritePin( GPIOA, GPIO_PIN_5, GPIO_PIN_RESET);
      
  if (joy[0]<=800)  //left
      HAL_GPIO_WritePin( GPIOA, GPIO_PIN_6, GPIO_PIN_SET);
  else
      HAL_GPIO_WritePin( GPIOA, GPIO_PIN_6, GPIO_PIN_RESET);
  
  if (HAL_GPIO_ReadPin( GPIOA, GPIO_PIN_2))  //center
		HAL_GPIO_WritePin( GPIOA, GPIO_PIN_7, GPIO_PIN_SET);
	else
		HAL_GPIO_WritePin( GPIOA, GPIO_PIN_7, GPIO_PIN_RESET);
  }

相關連結


結語

已經快不行了


上一篇
[Day 15]-【STM32系列】你所不知道的 PWM 脈波寬度調變!
下一篇
[Day 17]-【STM32系列】4×4 keypad with STM32
系列文
熟悉Arduino的Maker必看!30天帶你快速入門基於STM32嵌入式開發~30

尚未有邦友留言

立即登入留言