---
# System prepended metadata

title: Upboard Lab02
tags: [Embedded, Upobard]

---

Upboard Lab02
==
###### tags: `Upobard` `Embedded`
[TOC]
# A. Introduction to this Lab Practicing Unit 

## I. Task
1. 透過控制 74HC165、74HC595、MAX7219 IC 了解控制周邊元件的過程，並了解序列與平行訊號的原理與轉換。
2. 透過控制 MCP3201 IC 了解類比數位轉換器的使用。 
3. 透過控制UpBoard上的 PWM 針腳，了解 PWM 針腳如何應用。

## II. Overview
1. IC
74HC165		( 平行訊號 → 序列訊號 ) 可以搭配Lab01
74HC595		( 序列訊號 → 平行訊號 )
MAX7219	( LED矩陣控制 )
2. ADC
MCP3201	( 類比數位轉換器 )
3. PWM		( 脈波寬度調變 )

![](https://i.imgur.com/THz8e1d.png)

## III. Hardware
本次實驗會使用到的硬體

![](https://i.imgur.com/RGnojDB.png)

## IV. IC
積體電路（Integrated Circuit），或稱晶片（chip）

將電路元件集中製造於半導體晶圓的表面，並經由封裝處理後，透過其保留之對外針腳輸出／入電磁訊號，能實現特定應用。

以下介紹之 74HC165、74HC595、MAX7219、MCP3201 均為 IC 的特定種類之型號代稱，實際型號可能有些許差異，但應用特性並無不同。
例如 74HC165 與 74HCT165 在本實驗中的應用中功能可視為相同

備註: 本實驗使用到的 IC 均在擴充版背面，看不到

---

#### 1. 擴充板背面
![](https://i.imgur.com/O9vOmx9.png)
![](https://i.imgur.com/EMndXyN.jpg)
#### 2. 74HC165長相
![](https://i.imgur.com/vMk8LjL.png)
#### 3. 74HC595長相
![](https://i.imgur.com/TLOEiCV.png)
#### 4. MAX7219長相
![](https://i.imgur.com/SdZ1lrh.png)
#### 5. MCP3201長相
![](https://i.imgur.com/c6ywmi3.png)

## V. 實驗目的
#### 問題
直覺來說，一般會以一個針腳控制一個裝置，如 LED 等裝置。但==如果周邊裝置過多時會導致針腳數量不夠用==，為了因應此問題，我們可以使用==平行訊號 ( parallel ) 與序列訊號 ( serial ) 的轉換==，實現==少量針腳控制大量裝置之應用==。
因此我們將學習符合平行－序列訊號轉換需求之特定 IC 型號的使用方法。
#### 解決方式
1. 使用 74HC165 平行轉序列晶片
2. 使用 74HC595 序列轉平行晶片
3. 使用 MAX7219 控制 LED 矩陣

## VI. 74HC165
74HC165 主要功能是==將平行輸入 ( parallel ) 轉為序列輸出 ( serial )== 。其硬體規格也支援序列輸入，但本次實驗之應用不會使用到此功能。

![](https://i.imgur.com/EZBPAQo.png)

#### 1. 腳位說明

![](https://i.imgur.com/slBPBYO.png)

![](https://i.imgur.com/2JLumIP.png)
#### 2. Operating mode
![](https://i.imgur.com/4yNPLuN.png)

PL:
* 當 PL 為低時將 D0~D7 之電位訊號平行載入至 74HC165 晶片的暫存器
* 當 PL 為高時停止並行載入資料

CE:
* CE 腳位為低時致能 CLK 訊號
* CE 腳位為高時 CLK訊號無效

CP (CLK):
* Clock 每次產生正緣觸發時，D0~D7 進行右移
* 同時會將 DS 之電位訊號讀取至 D0 暫存器，本次實驗不會使用 DS 針腳

Q7 (DATA):
* 其電位訊號與 D7 之暫存器電位訊號相同，用於序列輸出

#### 3. UpBoard pin diagram
![](https://i.imgur.com/pZVRyIU.png)


## VII. 74HC595
74HC595 主要功能是將==序列輸入 ( serial ) 轉為平行輸出 ( parallel )==。其硬體規格也支援序列輸出，本次實驗之應用只會使用到序列輸入轉為平行輸出的功能。

![](https://i.imgur.com/p8f0PtZ.png)

#### 1. 腳位說明
![](https://i.imgur.com/mW0EA1g.png)

![](https://i.imgur.com/QcehGtv.png)

#### 2. Operating mode
![](https://i.imgur.com/sM42MJa.png)


DS:
* 用於輸入序列訊號，被動等待 SHCP 發生正緣觸發時的讀取。

STCP:
* 當 STCP 發生正緣觸發時，將 Q0~Q7 暫存器之訊號輸出至其 Q0~Q7 對應之腳位。

SHCP:
* 當 SHCP 發生正緣觸發時，將 Q0~Q6 暫存器之訊號移動 (shift) 至 Q1~Q7 暫存器，例如 Q0 → Q1、Q6 → Q7，並讀取 DS 腳位之電位訊號至 Q0 暫存器。
* 當 SHCP 發生正緣觸發時，原本在 Q6 的值會移到 Q7，並透過 Q7S 進行序列輸出，本次實驗不會使用到 Q7S 針腳。

#### 3. UpBoard pin diagram
![](https://i.imgur.com/kMAufEV.png)

## VIII. MAX7219
MAX7219 是一個 ==24 接腳的 DIP(Dual In-line Package)== 封裝晶片，==透過序列輸入／輸出驅動 8*8 LED矩陣、或 7 段顯示器==

#### 1. 腳位說明
![](https://i.imgur.com/cXuuk3C.png)

![](https://i.imgur.com/bhHKL4m.png)

#### 2. Data Format 
![](https://i.imgur.com/8u6vqGZ.png)

![](https://i.imgur.com/VMmprkL.png)

![](https://i.imgur.com/hqdIxMc.png)

LOAD:
* 當 LOAD 為低時，允許序列資料（包括CLK與DIN）進入暫存器
* 當 LOAD 為高時，不允許序列資料進入暫存器
* 當 LOAD 發生正緣觸發時，將暫存器資料鎖住 ( latched ) 

CLK:
* 當 CLK 發生正緣觸發時，從 DIN 讀取序列資料至暫存器

DIN:
* 用於輸入序列訊號，被動等待 CLK 發生正緣觸發時的讀取

#### 3. UpBoard pin diagram
![](https://i.imgur.com/VXRd6nL.png)

從 DIN 輸入的 16 bits 資料，格式應符合以下規範：
* D0~D7 為資料內容（值）
* D8~D11 為位址，例如：
    第一行 LED 位址為0x1
    0xa位址用來調整亮度
* D12~D15 不管（硬體設計考量）

![](https://i.imgur.com/EYqBmQ0.png)

MAX7219使用前須初始化，方式為透過 DIN 以序列訊號的方式溝通，對特定位址寫入特定值
步驟:
* 對 0x0c 寫入 0x01：leave shutdown mode
* 對 0x0f  寫入 0x00：turn off display test
* 對 0x09 寫入 0x00：set decode mode: no decode
* 對 0x0b 寫入 0x07：set scan limit to full
* 對 0x0a 寫入 0x01：set brightness (duty cycle = 3/32)

---

## XI. ADC
#### 實驗目的
本實驗將透過數位類比轉換器，==量測外部電路中的可變電阻之分壓==，從過程學到如何與數位類比轉換器等 SPI 裝置交換資訊。

## XII. MCP3201
#### 1. 腳位說明

![](https://i.imgur.com/uQe7nl9.png)

![](https://i.imgur.com/i3bafo1.png)

CS:
* 當 CS 為高電位時，停止 SPI 通訊。
* 當 CS 為低電位時，開始 SPI 通訊。
* 
CLK:
* 當 CLK 發生負緣觸發時，從 IN+ 讀取電壓值，與 VREF 做比較得到電壓差的數位訊號，並存放於暫存器，但須注意讀取後約 200 ns 後之資料才準確 ( tDO硬體規格規定 )，因此有兩種取值方式：
    * 直接在最穩定的正緣觸發時取值，此方法的有效位元（包括 null bit）為第 3~15 次取得的值，本實驗範例使用此方式取值。
    * 在負緣觸發後至少延遲 200 ns 後取值，此方法的有效位元為（包括 null bit）為第 2 ~14 次取得的值。

DOUT:
* 用於輸出序列訊號，等待 CLK 發生負緣觸發時的讀取後將暫存器內的值序列輸出。

#### 2. SPI communication
![](https://i.imgur.com/k10Hznq.png)

#### 3. 比例轉換公式
$\dfrac{測量值}{最大可測得範圍值}  =  \dfrac{實際輸入電壓}{參考最大電壓}$

$\dfrac{D𝑖𝑔𝑖𝑡𝑎𝑙\ 𝑂𝑢𝑡𝑝𝑢𝑡\ 𝐶𝑜𝑑𝑒}{1≪12(𝑙𝑒𝑓𝑡\ 𝑠ℎ𝑖𝑓)}  =  \dfrac{V_{in}}{V_{REF}},\ MCP3201\ resolution = 12bits$

移項後可得$D𝑖𝑔𝑖𝑡𝑎𝑙\ 𝑂𝑢𝑡𝑝𝑢𝑡\ 𝐶𝑜𝑑𝑒 = \dfrac{V_{in}*4096}{V_{REF}}$

![](https://i.imgur.com/Pmf8r6G.png)

#### 4. UpBoard pin diagram

![](https://i.imgur.com/FCtJ1KA.png)

## XIII. PWM

#### 1. 實驗目的
* 問題
    * 類比訊號可利用電壓大小決定輸出的功率，在額定工作範圍內，通常越高的電壓差能產生較高的工作效率，例如提升 LED 亮度、改變馬達轉速等。但數位訊號僅有高電位與低電位兩種電壓階級，若要達到與類比相同的電壓調整功能，則需要特殊的轉換電路。

* 解決方式
    * 脈波寬度調變 (PWM) 可以藉由 duty cycle 的調整，在使用數位訊號的條件下模擬出類比訊號的電壓調整功能。

![](https://i.imgur.com/zhz2iPT.png)

#### 2. 運作原理

* 切換週期 T，通常我們會用頻率 f (Hz) 來表達
* Von為最大可輸出的電壓

![](https://i.imgur.com/n1DY37z.png)

* duty cycle = Ton/Toff (%)，為電壓處於高電位 ( ON ) 的時間長與電壓處於低電位 ( OFF ) 時間長相除的百分比值

* 模擬出的電壓 V = Von x duty cycle (%)
可以知道 duty cycle 越高，模擬電壓 V 就越高，當完全不切至低電位的時候，duty cycle = 100%，輸出電壓 V 將維持在最大可輸出的電壓 Von。

![](https://i.imgur.com/WU57x2i.png)

將輸入的電壓值與頻率固定之鋸齒波透過比較器進行電位高低的比較，結果將決定工作頻率比 ( duty cycle )。
* 黃線：輸入電壓
* 綠線：鋸齒波之電壓
* 紅線：比較器之輸出，同義於利用 duty cycle 產生的模擬電壓

![](https://i.imgur.com/WcKTUY4.png)

#### 3. PWM in mraa
* dev = mraa_pwm_context  mraa_pwm_init ( int pin )
初始化 pwm 裝置連接針腳 ( pin ) 取得裝置資料 mraa_pwm_context dev
* mraa_result_t  mraa_pwm_period_us ( mraa_pwm_context dev, int us )
設定 pwm 裝置 dev 的工作週期 ( us表示週期，單位: 微秒 )
* mraa_result_t  mraa_pwm_enable ( mraa_pwm_context dev, int enable )
開啟 pwm 裝置 dev ( enable: 0 = 關閉、1 = 開啟 )
* mraa_result_t  mraa_pwm_write ( mraa_pwm_context dev,　　　　　 float percentage )
依據輸入的百分比值 ( percentage 範圍: 0.0~1.0 ) 決定該裝置 ( dev ) 的 duty cycle
* mraa_result_t  mraa_pwm_close ( mraa_pwm_context dev )
關閉 pwm 裝置 dev

# B. Demonstration

## I. 按鍵輸入偵測
* 利用 74HC165 IC 驅動來達到多顆按鍵偵測功能。按下 SW2、SW3、SW4 做按鍵偵測，結果顯示於螢幕上。
    * 單個 74HC165 可以檢測 8 個平行輸入訊號，所以會有 0~7 共八個輸入的暫存值
    * 此實驗只用到 SW2,SW3,SW4 共三個輸入訊號，分別對應的腳位為 D0、D1、D2 ，觀察 SW2, SW3, SW4 按鈕按壓後， D0、D1、D2 三個輸出的高低電位變化，有按壓時輸出 0，沒按壓時輸出 1。

![](https://i.imgur.com/FU71kNy.png)
![](https://i.imgur.com/Xml1ba1.png)

> Reminder: 74HC165
> 
> PL:
> * 當 PL 為低時將 D0~D7 之電位訊號平行載入至 74HC165 晶片的暫存器
> * 當 PL 為高時停止並行載入資料

> CE:
> * CE 腳位為低時致能 CLK 訊號
> * CE 腳位為高時 CLK 

> CP (CLK):
> * Clock 每次產生正緣觸發時，D0~D7 進行右移
> * 同時會將 DS 之電位訊號讀取至 D0 暫存器，本次實驗不會使用 DS 針腳

> Q7 (DATA):
> * 其電位訊號與 D7 之暫存器電位訊號相同，用於序列輸出![](https://i.imgur.com/wnofChY.png)



## II. 基礎跑馬燈應用：多顆LED輸出
> 使用 74HC595 IC 驅動多顆 LED 輸出功能。板子上的 LED2、LED3、LED4 執行跑馬燈功能。 

寫入序列資料進入 74HC595
* STCP ( en ) 為了待會的正緣觸發先拉低
* SHCP ( sl )為了待會的正緣觸發先拉低
* 將序列值寫入 DS ( data ) 
* 對 SHCP 發出正緣觸發，先將所有暫存器位移一次，並將 DS 的值讀入 Q0
    * Q0~Q6 → Q1~Q7
    * Q0 = DS 
* 2.~4.重複8次，相當於讀取 8 bits 長度的序列資料進入暫存器

從 74HC595 平行輸出
* 對 STCP 發出正緣觸發，將 Q0~Q7 的暫存器之值輸出至對應之 Q0~Q7 腳位
![](https://i.imgur.com/6ZoMJh6.png)
![](https://i.imgur.com/z8Yqfbs.png)

> Reminder: 74HC595
> 
> DS:
> * 用於輸入序列訊號，被動等待 SHCP 發生正緣觸發時的讀取。

> STCP:
> * 當 STCP 發生正緣觸發時，將 Q0~Q7 暫存器之訊號輸出至其 Q0~Q7 對應之腳位。

> SHCP:
> * 當 SHCP 發生正緣觸發時，將 Q0~Q6 暫存器之訊號移動 (shift) 至 Q1~Q7 暫存器，例如 Q0 → Q1、Q6 → Q7，並讀取 DS 腳位之電位訊號至 Q0 暫存器。
> * 當 SHCP 發生正緣觸發時，原本在 Q6 的值會移到 Q7，並透過 Q7S 進行序列輸出，本次實驗不會使用到 Q7S 針腳。![](https://i.imgur.com/a5Tka1G.png)



## III. 基礎點矩陣應用：矩陣跑馬燈
> 使用 MAX7219 IC 驅動 8×8 LED 點矩陣。板子上點矩陣執行跑馬燈功能

* 將符合 MAX7219 資料格式的內容傳入 IC 
    * sent_byte 
        > * 傳入參數 : 8 bits 序列訊息
        > * 作用 :==傳送序列訊息至MAX7219== 
    1. CLK為了待會的正緣觸發先拉低
    2. 將參數從右邊數來第 i 個 bit 輸出至 DIN，因為須從最左側的 bit (MSB) 開始傳，因此 i = 7~0
    3. 對 CLK 發出正緣觸發，在 LOAD 為低電位的條件下可讀取 DIN 進入暫存器
    4. 重複1.~3.，直到 8 bits 都送達 MAX7219
    
    ![](https://i.imgur.com/DmsWeg2.png)

    * write_reg 
        > * 傳入參數 : 16 bits 序列長訊息，此處==為了理解拆成前半 8 bits 之 addr 與後半 8 bits 之 data==
        > * 作用 : ==傳送序列訊息至 MAX7219==
    1. CLK 設為高電位，使訊息間不互相影響
    2. LOAD 拉低，允許序列資料（包括CLK與DIN）　進入暫存器
    3. 利用sent_byte 函式傳送前 8 bits
    4. 利用sent_byte 函式傳送後 8 bits
    5. CLK 設為低電位，使訊息間不互相影響
    6. LOAD 拉低，不允許序列資料進入暫存器，並將暫存器資料鎖住 
    
    ![](https://i.imgur.com/32ghBOp.png)

    * 依照使用手冊，初始化 LED 矩陣
        > * init_matrix
        > * 作用: 利用 write_reg ( addr, data ) 函式調整 LED 矩陣的設定
    1. 對 0x0c 寫入 0x01：leave shutdown mode
    2. 對 0x0f 寫入 0x00：turn off display test
    3. 對 0x09 寫入 0x00：set decode mode: no decode
    4. 對 0x0b 寫入 0x07：set scan limit to full
    5. 對 0x0a 寫入 0x01：set brightness (duty cycle = 3/32)
 
    ![](https://i.imgur.com/L1LShfY.png)


![](https://i.imgur.com/XAI3asV.png)
![](https://i.imgur.com/zVriNRE.png)

> Reminder: MAX7219
> 
> LOAD:
> * 當 LOAD 為低時，允許序列資料（包括CLK與DIN）進入暫存器
> * 當 LOAD 為高時，不允許序列資料進入暫存器
> * 當 LOAD 發生正緣觸發時，將暫存器資料鎖住 ( latched ) 

> CLK:
> * 當 CLK 發生正緣觸發時，從 DIN 讀取序列資料至暫存器

> DIN:
> * 用於輸入序列訊號，被動等待 CLK 發生正緣觸發時的讀取![](https://i.imgur.com/qzWDfg3.png)

## IV ADC
> 利用 MCP3201 IC。撥動開發版上的可變電阻 VR1，測量可變電阻 VR1 之分壓，並將結果顯示於螢幕上

#### SPI 傳送資料
1. 把 CS 拉低以開始 SPI 溝通
2. 對 CLK 發出正緣觸發，使 ADC 進行類比數位轉換，並將當前的數值放在暫存器
3. 將該位元之數值經由 DOUT 讀出並記錄
4. 當下累加值 = 上次累加值 << 1 + 此次讀得資料
    前三位元不累加
5. 重複 2.~ 4. 直到 12 位元讀完
6. 把 CS 拉高結束 SPI 溝通

![](https://i.imgur.com/rpRP2cF.png)

![](https://i.imgur.com/gEA6QU2.png)

> Reminder: MCP3201
> CS
> * 當 CS 為高電位時，停止 SPI 通訊。
> * 當 CS 為低電位時，開始 SPI 通訊。
> 
> CLK
> * 當 CLK 發生負緣觸發時，從 IN+ 讀取電壓值，與 VREF 做比較得到電壓差的數位訊號，並存放於暫存器，但須注意讀取後約 200 ns 後之資料才準確 ( tDO硬體規格規定 )，因此有兩種取值方式：
    (1) 直接在最穩定的正緣觸發時取值，此方法的有效位元（包括 null bit）為第 3~15 次取得的值，本實驗範例使用此方式取值。
    (2) 在負緣觸發後至少延遲 200 ns 後取值，此方法的有效位元為（包括 null bit）為第 2 ~14 次取得的值。
    
> DOUT
> * 用於輸出序列訊號，等待 CLK 發生負緣觸發時的讀取後將暫存器內的值序列輸出。

## PWM
> 使用系統內建 PWM 輸出至 LED 5 上。當調變脈波寬度時，LED5 有亮暗變化。
* 使用步驟：
    * 初始化
        (1) 初始化 PWM 針腳
        (2) 設定 PWM 週期
        (3) 開啟 PWM 針腳
    * 使用
        * 對 PWM 針腳寫入 duty cycle 的百分比值

![](https://i.imgur.com/hreAu45.png)

