公告版位
從小害怕寫作文, 文筆不佳到現在, 還請各位讀者大大:
1. 發現有錯誤, 請留言告知. (或者你 '覺得' 不對也行)
2. 用字措辭不當, 請留言告知.
3. 有看沒有懂? 幫到忙也好, 幫倒忙也罷, 總之留個言吧.

隨著科技的演進, 在單晶片微控制器及 SoC 的領域中, SPI 及 I2C 這二種串列 (序列) 介面變得十分常見. 這二者與主機間通訊用的非同步串列通訊埠 RS-232 (UART) 非常不一樣

  • 二個都是同步傳輸介面, 主要是用於 CPU 和週邊晶片之間.
  • SPI 及 I2C 二者設計的主要目的在於減少 CPU 和週邊晶片之間的接腳數.
  • SPI 一般需要 4 條接線 (至少三條), 而 I2C 則只要二條線, 這和早期常用的並列匯流排動輒十數條接線有著明顯的差異.
  • SPI 的硬體結構簡單而且傳輸速度快, 一般是 5M/10M/20Mbps 或是更快 (可以到 200Mbps), I2C 的傳輸速度則只有 100Kbps/400Kbps/1Mbps(/3.4Mbps/單向5Mbps).
  • SPI 是全雙工, I2C 則是半雙工.
  • SPI 使用硬體線路來指定 slave 晶片, I2C 則在傳送的第一個位元組上指定 (7bit位址).
  • SPI 不提供交握機制, 無法確認 slave 晶片是否有跟上. I2C 則有雙向的確認機制.

本篇介紹的是 SPI 介面



文章標籤

MagicJackTing 發表在 痞客邦 留言(34) 人氣()

假設有一個 16bit 硬體計時/計數器 (Timer/Counter) 負責計數外部的訊號. 所以我們直覺的反應是某一段時間之內的訊號個數是本次讀取的計數值減掉上次讀取的計數值, 像這樣 Count = ValCurr - ValPrev. 但是如果上次讀取的內容已經接近上限了 (例如: 65530), 而這一次讀到的內容已經溢位變成一個很小的數值 (例如: 5) 呢?

當下你可能會想到下列幾個:

  • 改用 32bit 來處理.
  • 65536 - (大值 - 小值)
  • ...

其實沒那麼麻煩, 答案很簡單依然是 Count = ValCurr - ValPrev, 只不過記得要用 uint16_t (或者 unsigned short) 來定義這些變數.

文章標籤

MagicJackTing 發表在 痞客邦 留言(0) 人氣()

最近因實驗需要, 上網找到很多人拿來控制 Arduino 的 APC220 UART 轉 RF 的傳輸模組.

由於網路上拍賣網站眾多, 但資料大多不全, 個人研判製造商應該是 APPCON 這家公司, 因為設定工具程式 (網路上找到的) 內有這家公司的相關資訊. 以下資料主要來自從 APPCON 網站下載下來的 datasheet



APC220 套件產品照片


APC220 Front View APC200 Back

可以相容對接的產品還有 APC230 及 APC802, 三者最大的差異是傳輸功率: APC220 是 13dBm (20mW), APC230 是 20dBm (100mW), APC802 是 27dBm (500mW), 當然功率變大電流需求也會變大, 同時也可以傳更遠. 由規格看來, 傳輸功率增加 7dBm, 距離由 800m 增加到 1800m, 20log(1800)-20log(800)=7.04 符合理論計算.

文章標籤

MagicJackTing 發表在 痞客邦 留言(1) 人氣()

給用手機瀏覽的讀者


很抱歉, 這一篇因為用了 MathJax 套件來顯示分數, 目前設定和痞客邦的 "手機版模式" 有點小衝突 (它把行高設定死了), 已經修正好了, 如果閱讀上還有問題請留言告知.要等改天有空才能修正. 請先改用 "電腦版模式" 或者換用 PC/平板 來閱讀.

UART 接收同步機制


下圖所示是經由 UART 輸送一個 ASCII 字元 'r' (0x72) 的 TTL 輸出 (未經過 RS-232 Transceiver). 圖上的小箭號所指的是接收端取樣訊號的相對時序位置, 上半部是理想狀況下接收 UART 資料的時序圖. 我們設定了鮑率之後, UART 在第一個向下訊號邊緣取得同步 (開始計時) 是為啟始位元, 然後以設定的鮑率開始取樣接收資料. 不過事情總不會如此美好. 萬一接收者和發送者的計時精準度不同 (即使是同樣的廠牌、型號, 總還是有製造上的誤差, 及操作溫度...等等因素的影響), 致使二者不完全一致, 下圖的下半部刻意把誤差放大, 我們很容易就看出一共有 4 個位元的資料錯了.

文章標籤

MagicJackTing 發表在 痞客邦 留言(3) 人氣()

參考手冊:


設定 CSS, 總會要查一下手冊, 下面列的是個人經常參考的 CSS 手冊及標準文件

HTML CSS 的語法結構:


網頁作者的設定是 CSS style 中最重要的部份, 網頁作者可以運用的 CSS 設定有多種來源:

文章標籤

MagicJackTing 發表在 痞客邦 留言(0) 人氣()

型號


電路版的型號依時間序有

  • Pi rev.1 (2012/02/29)
  • Pi rev.2 (2012/09/05)
  • Pi+ (2014/07/14)
  • Pi2 (2015/02/02)
  • Pi3 (2016/02/28)
  • Pi3+ (2018/03/14)
  • Pi4 (2019/06/24)

Pi rev.2 和 Pi+ 有分 Model A 和 Model B. 二者的差異是電子零件用料不同 (Model A 用料縮減, 主要為減少 RAM, 網路接口, 及部份 USB 接口)

Pi3+ 相對於 P3 只是 CPU 的執行速度加快 1400 MHz (雙核 ARM Cortex-A53), Ethernet 網路接口改為 10/100/1000 Mbit/s, WiFi 改為 802.11ac Dual band, Bluetooth 改為 4.2 BLE, 以及可以經 PoE 取電 (需另購 PoE HAT 擴充板). (還有總耗電量變大)

文章標籤

MagicJackTing 發表在 痞客邦 留言(1) 人氣()

Reentrant vs Thread-safe


Part 3: C 語言例子 (thread-safe function)

接下來, 我們來看一些 thread-safe 的例子: 首先是在 wiki 網站上的一個 Thread-safe 但不是 reentrant 的例子.

#include <pthread.h>

int increment_counter() {
    static int counter = 0;
    static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;

    pthread_mutex_lock(&mutex);

    // only allow one thread to increment at a time
    ++counter;
    // store value before any other threads increment it further
    int result = counter;

    pthread_mutex_unlock(&mutex);

    return result;
}

這個例子中的 increment_counter() 可以被多個執行緒呼叫而不會產生任何問題, 因為它用了一個 mutex 來保護 (同步) 所有對共用的靜態變數 counter 的存取. 但是如果中斷服務程式 ISR 也呼叫了 increment_counter(), 就會很容易使系統當掉. 原因是如果中斷發生在執行緒正呼叫 increment_counter() 時 (尤其是 mutex lock 和 unlock 之間), 那 ISR 將永遠等不到 mutex 被 unlock. 因為 CPU 接受中斷進入 ISR 後, 只有 ISR 完成, 才會回到執行緒. 記住: 中斷永遠比正常執行優先, 所以 ISR 要比執行緒或者是 OS 核心優先執行.

文章標籤

MagicJackTing 發表在 痞客邦 留言(1) 人氣()

Reentrant vs Thread-safe


Part 2: C 語言例子 (reentrant function)

先來看 reentrant 的例子: 最常見到用來說明 reentrant 的例子大概就屬 swap()

int t;

void swap(int *x, int *y) {
    t = *x;
    *x = *y;
    *y = t;
}

void isr(void) {
    int x = 1, y = 2;
    swap(&x, &y);
    ...
    return;
}

void main(void) {
    int x = 3, y = 4;
    ...
    swap(&x, &y);
    ...
}

這個例子中的 swap() 函數是 non-reentrant function (而且也不是 thread-save). 原因是第4行及第6行用到共用的變數 t. 即便是我們用的是 32bit CPU, 甚至也有技援 mem. to mem. 移轉資料不被中斷, 也還是有二個時間點(在第5行執行前或執行後) 發生中斷會產生錯誤的執行結果. 如下表的 NG Example 1 和 NG Example 2 所示 (在這裡為了讓這一張表格不致於太長, 我只把動作拆解到高階語言的單一指令階段, 實際上像 *x=*y 這樣的指令可能就要二個以上的低階組合語言指令.)

文章標籤

MagicJackTing 發表在 痞客邦 留言(0) 人氣()

Reentrant vs Thread-safe



Reentrancy 和 thread-safty 是兩個容易被搞混了的觀念. 其中最嚴重的是誤以為 reentrant function 必定是 thread-safe 或者相反以為 thread-safe function 必為 reentrant, stackoverflow 網站上的答覆甚至同時出現二種答案的現象.

Reentrancy 和 Thread-safty 二者的差異


首先來看 reentrancy: 字面上的意思是可重入. Reentrancy 原先是討論單一執行緒環境下 (即沒有使用多工作業系統時) 的主程式和中斷服務程式 (ISR) 之間共用函數的問題. 當然現在多核心的 CPU 盛行, 討論範圍也必需擴充至多執行緒的情況. 重點是它討論的主體是: 在 ISR 中使用的函數 (不論是自己寫的或者是函數庫提供的) 是否會引發錯誤結果. 主要的達成條件是二者 (ISR 和非 ISR) 的共用函數中不使用靜態變數或全域變數 (意即只用區域變數). 一般是撰寫驅動程式 (device driver) 或者是寫 embedded system 的人會遇到這個問題.

文章標籤

MagicJackTing 發表在 痞客邦 留言(3) 人氣()

Keil C51 和標準 C 主要的差異



Keil 的 C51 是以 ANSI C90 為其設計基礎, 即便是如此, 它和標準 C 語言 (ANSI C90) 之間還是有幾個滿大的差異:

  • Keil C51 因應 8051 的特性多了 bit, sbit, sfr, sfr16 等四種資料型態. 一般我們只會用到 bit, 其他三個是定義 CPU 的特殊功能暫存器用的.
  • Keil C51 在定義變數時多了儲存空間修飾字, 用來修改變數使用記憶體空間. 詳細可參考這一篇
  • 多了定義中斷服務常式 ISR 的方法及進入 ISR 時切換暫存器區段 (register bank) 的語法, 例如: static void UART0_ISR(void) interrupt 4 using 2
  • 標準函數庫沒有依標準來實作, 如: printf()
  • 在 Keil C51 中, 函數預設是 non-reentrant, 這點是最嚴重的差異. 我們在使用時要有所警覺才好, 才不致於掉到陷阱裡而不自知.

什麼是 reentrant


在此先來了解一下 reentrant 的定義, Wiki 網站上給 reentrancy 下的定義是

文章標籤

MagicJackTing 發表在 痞客邦 留言(3) 人氣()

您尚未登入,將以訪客身份留言。亦可以上方服務帳號登入留言

請輸入暱稱 ( 最多顯示 6 個中文字元 )

請輸入標題 ( 最多顯示 9 個中文字元 )

請輸入內容 ( 最多 140 個中文字元 )

請輸入左方認證碼:

看不懂,換張圖

請輸入驗證碼