SN8F5701 – 8051 ADC 功能介紹

上次由於篇幅的緣故,和大家分享 8051 的 UART 之後沒能繼續把 ADC 講完 (每次都說最後一篇,然後每次都有最最後一篇哈哈…),所以今天這篇真的真的要終結這顆埋控了,文末也會稍微提到目前正在進行的專案,與 2.4G RF 有關。

ADC (analog to digital converter)

我們都知道現實世界是 “類比” 的,不過類比實在太複雜,聰明的人類因此創造出 “數位” 來簡化問題,如果不夠清楚,就想像類比是 “連續數值的變化” 而數位就只有 0 或 1,而這之間的轉換牽涉到很多數學的複雜運算,比如說傅立葉轉換 (fourier tranform),將 time domain 的 data 轉成 frequency domain,原本看似沒意義的 function curve 突然之間有了生命。

本篇就用最簡單的例子 – 電壓大小變化,來實作這顆 SN8F5701 埋控的 ADC 功能。

這顆埋控 ADC 的部分是用 SAR 架構 (聽說還有很多種,但我都還沒遇到過或是我不知道我遇過了…),6 隻可以設為 analog input 的 pin 腳位,解析度有到 4096 steps,在腦中想像一下長條圖 y 軸的刻度,就是 4096 階,也就是說如果 4096 階這個值不變,在 reference high voltage 和 VSS (通常都是接地 0V) 相差的越小  (下方會說明),解析度相對就會提高,但有利有弊,除非進來的 analog 訊號數值和變化真的不大,否則這個情況很難發生。

上述提到的 reference high voltage (參考高電位) 還有 clock rate 是 ADC 中相當重要的一環,這顆埋控有四個 clock rate 可以選擇,以 datasheet 裡面提到的 converting rate,我目前的理解是每次每個數值轉換 (analog to digital) 的速率,所以說如果類比訊號進來的很快,但我 MCU ADC 的 converting rate 設太低,用膝蓋想都知道讀出來的數值可能會出問題。

剛剛之所以說以我目前的理解是因為我在別顆埋控的 datasheet 裡面有看過 ADC sampling rate,至於這和 converting rate 是否相同,經過詢問 Bird 後得知,在大部分的狀況下是一樣的,但有些進階的 ADC 上會不一樣 (就我所知 sampling rate 越高表示越能模擬出真正 analog 訊號的全貌)。

再來談到參考高電位, SN8F5701 提供 4 個 sources 給開發者選擇,分別是 VDD, 4V, 3V, 2V,拿 3V 舉例,因為埋控規定 VSS (0V) <= sampled input voltage 一定要 <= 參考高電位,意思是說如果 reference high voltage 我設定為 3V 我只能去測量 0-3V 之間的數值,而 4096 這個解析度,就是將 0-3V 分割成 4096 階,去定義進來的 analog 訊號該對應到什麼二進位的數值,用下圖搭配著看會更清楚:

螢幕快照 2018-10-20 下午10.32.32.png
圖片出處:類比數位資料轉換器 ADC 介紹

接著在講 initiate ADC 之間,先談談整個轉換流程在這顆埋控中是怎麼進行的。首先要讓 ADC enable (ADENB=1),接下來要讓 ADC 開始可以轉換數值 (ADS=1),當轉換結束後硬體自行會將 ADS 變為 0 表示轉換結束,硬體也會把其他兩個 flag – EOC 和 ADCF 拉 HIGH 為 1,另外轉換好的數值就存在 ADB[11:4] 和 ADR[3:0] 兩個 registers。

而上方提到的 ADCF 其實是和 ADC 的 interrput 做搭配,ADCF 為 1 時,如果開發者有 enable adc interrput (EADC=1),這時 ISR 會被觸發,觸發 “前” ADCF flag 就會被硬體清掉。但我並沒有用 ADC interrupt 的功能,原因下方我會說明。

以下程式碼是 ADC 功能的初始設定:

要作為 ADC pin 腳位,首先要將 pin 設定為 input mode,再用 POCON 設為 pure analog input pin,重點是一次同時間只能有一隻腳位為 analog pin,因為這顆埋控 analog 和 digital I/O 腳位是共用,所以非 analog pin 的腳位一律要設定好是 digital 不然會有問題。

根據四種不同的 clock rate (ADR 的 ADCKS 設定) 會對應出不同的 converting time (converting time 的時間是指從開始轉換 <ADS=1> 到結束 <EOC=1> 這段時間) 我是直接開到最大,用 fosc / 1 的 clock rate 在跑,至於 reference high voltage 我是用內部 VDD (5V) 作為參考高電位,因此可以利用電源供應器給 P01 這隻 pin 腳 0-5V 的類比訊號做為測試。

以下是部分程式碼:

上方程式碼片段總共有三個重點,第一,要讀出來總要看得到是多少,所以搭配 UART 顯示在我的 console 上 (所以也是為什麼我上次覺得 UART 和 ADC 要寫在同一篇的緣故)。第二,我之所以沒有開 ADC 的 interrupt 就是因為我不需要這麼常取值 (但還是很看應用所以也不一定),我反而是用 timer0 去計時,在 main 裡面每隔 1 秒去讀一次 ADB 和 ADR 裡的值。第三,因為轉換結束後不僅 EOC 會被系統拉 HIGH,還有 ADS 也會拉 LOW,所以我為了要啟動下一次的轉換,我勢必得清掉 EOC 並且拉 HIGH ADS。

以上搞懂且成功運行後,就可以在 PC 的 console 上面看到,隨著電源供應器的旋鈕被轉動,console 上顯示的數值就會跟著做改變,而 ADC 的功能測試也到這告一個段落,SN8F5701 大致玩完,雖然沒有到很深,但該摸的基本上都有摸到,繼續前進下一顆埋控!

文章最後提一下我目前手邊正在進行的專案,是利用 Amiccom A8106 2.4G RF module 實作發射與接收器,RF 比我想像中還要複雜許多,不僅僅是廠商自定義的 protocol,還要 based on 這個 protocol 去做不同的 use case (比如說學習模式,接收器可以認得三隻發射器等等),屆時再來分享瞜!

*本文同步刊登 MakerPRO

廣告

發表迴響

在下方填入你的資料或按右方圖示以社群網站登入:

WordPress.com 標誌

您的留言將使用 WordPress.com 帳號。 登出 /  變更 )

Google photo

您的留言將使用 Google 帳號。 登出 /  變更 )

Twitter picture

您的留言將使用 Twitter 帳號。 登出 /  變更 )

Facebook照片

您的留言將使用 Facebook 帳號。 登出 /  變更 )

連結到 %s