分析一下到底是上升沿還是下降沿讀寫數據

轉載至:http://blog.chinaunix.net/uid-20788517-id-3045170.html


看芯片pdf文檔的時候總是容易被迷糊,總結一下,通過看時序圖瞭解到底是上升沿還是下降沿讀寫數據!

首先必須明白的幾個術語:

1. ReadWriteReadWrite均是指MCU的讀和寫。

2. OutputInput:在芯片官方文檔中大多會有inputouput介紹,顯然是指器件的輸入和輸出。這裏和上面的Readwrite相對應。對應關係是:

    

這是很顯然的對應關係,但是很不幸,由於沒有經過思考,一直以來我均誤以爲

輸入=讀,輸出=寫。這是完全沒有考慮到對象的因素,輸入(指器件的輸入)<==>(MCU的寫操作),輸出(指器件的輸出)<==>(MCU的讀操作)

在芯片的pdf資料中,所給出的時序操作圖一般都是MCU來操作芯片的時序。

1) 所謂讀即是指MCU從器件的數據總線上根據一定的時序來讀取器件的數據。一般而言,MCU提供一個邊沿信號(上升沿或者下降沿均可)告訴器件可以發數據了,器件檢測到邊沿信號以後,立即在數據總線上更新數據,待數據穩定以後,MCU即可讀取數據。所以一般所說的上升沿(下降沿)開始讀數據是不準確地說法,上升沿(下降沿)這是數據總線上的數據發生改變,MCU並沒有在此時刻讀取數據,而是等待數據穩定之後纔開始讀取數據。

以DS1302的單字節讀時序爲例說明,要讀取DS1302數據,先必須寫1byte數據到DS1302,即是指(R/W,A0~A4,R/C,1這8位數據),然後再讀。所以我們應該看後半部分來解讀數據的read操作。

顯然在時鐘信號的下降沿數據總線上的數據發生改變,等待數據穩定之後,MCU將讀取該數據D0,接着MCU產生下一個下降沿,器件檢測到下降沿信號立即更新數據D1,等待數據穩定之後被MCU讀取。後面相同。

2)所謂寫即是指MCU向器件寫入數據,其操作是:先將數據放置在數據總線上,等待其穩定之後,MCU產生一個邊沿信號,將數據寫入器件。

DS1302的單字節寫時序爲例說明,要向DS1302寫數據,,先必須寫1byte數據到DS1302,即是指(R/W,A0~A4,R/C,18位數據),然後再寫。所以上圖的16個脈衝下的操作均是寫操作,可以從第一位(R/W)分析起,當然也可以向讀操作一樣,只分析後半部分的操作。

 寫操作必須先將數據準備在數據總線上,等待數據穩定之後,MCU產生一個邊沿信號,寫入數據到器件。從圖中可以看出,在起始狀態,數據總線上準備數據,穩定後遇到上升沿MCU將數據寫入到器件。寫完之後,數據總線上出現第二位數據A0,等待其穩定之後,MCU產生一個上升沿將A0寫入器件。

 OK,總結完畢,可以簡單理解爲“寫穩讀變”。MCU在數據總線上的數據穩定之後,檢測邊沿信號寫數據到器件;MCU發出邊沿信號告訴器件發送數據,檢測到邊沿信號之後,器件改變(更新)數據,等待穩定之後MCU讀取數據。

對照上面的時序圖寫驅動函數:

  1. /*
  2. ** 函 數:single_byte_read
  3. ** 參 數: unsigned char commd--讀之前必須寫入的命令
  4. ** 返回值: unsigned char tempbyte--讀取的1byte數據
  5. ** 說 明: 這只是一個例子函數,對應上面的時序圖所寫的完整的讀1字節數據函數
  6. */
  7. unsigned char single_byte_read(unsigned char commd)
  8. {
  9.   int i;
  10.   unsigned char tempbit;
  11.   unsigned char tempbyte;
  12.   /* 初始化*/
  13.   CE = 0;
  14.   SCLK_OFF;

  15.   /* 寫1byte 數據(R/W,addr,R/C,1):讀的地址命令*/
  16.   /* 數據總線上先準備好數據,上升沿寫入數據到器件*/
  17.   for(i=0;i<8;i++)
  18.   {
  19.     if(commd & 0x01)
  20.      DataIO = 1; //數據總線上準備數據1
  21.     else
  22.      DataIO = 0; //數據總線上準備數據0
  23.     commd=commd>>1;
  24.     SCLK_ON; //上升沿來臨,MCU將數據寫入器件
  25.     _NOP(); 
  26.     SCLK_OFF; //再次拉低,爲下一個數據提供上升沿條件
  27.   }

  28.   /*寫完命令之後, 從器件讀1byte數據*/
  29.   /*下降沿通知器件更新數據,等待其穩定之後讀取數據*/
  30.   for(i=0;i<8;i++)
  31.   {
  32.    if(DataIO) //緊接上面寫命令的最後一個信號是下降沿信號,故此時第一位數據即是器件更新數據
  33.     tempbit = 0x80;
  34.    else
  35.     tempbit = 0;
  36.    tempbyte = tempbyte >> 1 | tempbit;
  37.    SCLK_ON; //上升沿,爲下降沿提供條件
  38.    _NOP();
  39.    SCLK_OFF; //下降沿來臨,通知器件更新數據,在下一個循環中MCU讀取更新的數據.
  40.   }

  41.   return tempbyte;
  42. }
  1. /*
  2. ** 函 數:single_byte_write
  3. ** 參 數: unsigned char commd--寫數據之前必須先寫命令
  4. ** unsigned char data--寫的1byte數據
  5. ** 返回值: none
  6. ** 說 明: 這只是一個例子函數,對應上面的時序圖所寫的完整的寫1字節數據函數
  7. */
  8. void single_byte_write(unsigned char commd,unsigned char data)
  9. {
  10.   int i;
  11.   
  12.   /* 初始化*/
  13.   CE = 0;
  14.   SCLK_OFF;

  15.   /* 寫1byte 數據(R/W,addr,R/C,1):讀的地址命令*/
  16.   /* 數據總線上先準備好數據,等待其數據穩定之後,MCU產生一個上升沿寫入命令到器件*/
  17.   for(i=0;i<8;i++)
  18.   {
  19.     if(commd & 0x01)
  20.      DataIO = 1; //數據總線上準備數據1
  21.     else
  22.      DataIO = 0; //數據總線上準備數據0
  23.     commd=commd>>1;
  24.     SCLK_ON; //上升沿來臨,MCU將數據寫入器件
  25.     _NOP();
  26.     SCLK_OFF; //再次拉低,爲下一個數據提供上升沿條件
  27.   }

  28.   /*寫完1byte命令之後, 再寫1byte數據*/
  29.   /*與寫命令是一樣的,數據總線上先準備好數據,等待其數據穩定之後,MCU產生一個上升沿信號將數據寫入*/
  30.   for(i=0;i<8;i++)
  31.   {
  32.     if(data & 0x01)
  33.      DataIO = 1; //數據總線上準備數據1
  34.     else
  35.      DataIO = 0; //數據總線上準備數據0
  36.     data=data>>1;
  37.     SCLK_ON; //上升沿來臨,MCU將數據寫入器件
  38.     _NOP();
  39.     SCLK_OFF; //再次拉低,爲下一個數據提供上升沿條件
  40.   }

  41. }

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