MCP3201串行通信
關鍵理解:主出從入, 主設備上升沿採集數據的同時,從設備爲下降沿輸出數據,以此往復,完成主設備與從設備之 間的全雙工通信。
可用標準SPI兼容串行接口與該器件進行通信。 當CS變爲低電平時,啓動與MCP3201的通信。 如果器件上電時CS 引腳爲低電平,則必須先將此引腳拉爲高電平,然後再恢復至低電平以啓動通信。 器件將在CS 變爲低電平後在第一個上升沿開始對模擬輸入信號進行採樣。 採樣週期將在第二個時鐘週期的下降沿結束,此時器件將輸出一個低電平空位。 接下來的12個時鐘脈衝將以首先發送MSB位的格式輸出轉換結果,如圖5-1所示。 器件總是在時鐘下降沿輸出數據。 所有12個數據位均發送完畢後,如果器件繼續接收時鐘脈衝,而CS保持爲低電平,則器件將以首先發送LSB的格式輸出轉換結果,如圖5-2所示。 如果在CS保持爲低電平時繼續向器件提供時鐘脈衝 (在以首先發送LSB的格式發送完數據後),器件將持續輸出零。
以上總述,8個週期完成一次數據寄存器的傳遞,但要獲得完整數據需要16個週期,而在16個週期中,首先前兩個週期是對模擬輸入信號的採樣,並不獲取數據,接下來的第三個週期主要是發送MSB,而在第16個週期,發送LSB。所以說,在寄存器只能儲存8個有效數字的情況下,真正獲取數據的是寄存器第一次獲取數值時後5位有效位數,寄存器第二次獲取的有效數字是前7位有效位數。
以下例子只是簡單實現 寄存器的讀寫:
#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/delay.h>
#define u8 volatile unsigned char
// 控制寄存器
#define CtrlRes *(u8 *) 0xbfe80000
//狀態寄存器
#define StaticRes *(u8 *) 0xbfe80001
//數據寄存器
#define DataRes *(u8*) 0xbfe80002
// 外部寄存器
#define ExternRes *(u8 *) 0xbfe80003
// 參數控制寄存器
#define ParaCtrlRes *(u8 *) 0xbfe80004
// 片選寄存器
#define PianRes *(u8 *) 0xbfe80005
// 時序控制寄存器
#define TimingCtrlRes *(u8 *) 0xbfe80005
void init_master(void)
{
//停止 SPI 控制器工作,對控制寄存器 spcr 的 spe 位寫 0
CtrlRes = 0x12;
//重置狀態寄存器 spsr,對寄存器寫入 8'b1100_0000
StaticRes = 0xc0 ;
//設置接口模式與分頻係數
ExternRes = 0x05;
//時鐘分頻數選擇 與 spi flash 讀使能
ParaCtrlRes = 0x61;
//片選控制寄存器,不啓用從設備
PianRes = 0xff;
//時鐘週期設爲8T
TimingCtrlRes = 0x03;
}
int i;
static int __init spi_init(void)
{
u8 low_data;
unsigned short data, high_data;
//init_master()函數 實現寄存器的初始值
init_master( );
//連續10次讀取數據寄存器
for (i=0; i<10; i++)
{
//開啓控制寄存器工作使能
CtrlRes = 0x52;
//開啓片選cs3信號,
PianRes = 0x7f;
// 第一次數據寄存器獲取值
// 可以任意給數據寄存器賦值,只是爲了推動數據寄存器的運作
DataRes = 0xff;
printk("StaticRes : %x\n",StaticRes);
//判斷狀態寄存器讀標誌是否爲空,當爲空時,說明數據寄存器已經獲取完
while (StaticRes &(0x1));
high_data = DataRes;
high_data= (high_data<<7);
//第二次數據寄存器獲取值
DataRes = 0xff;
while (StaticRes &(0x1));
low_data = DataRes;
low_data = (low_data>>1);
// 將兩次寄存器獲取的值合併
data = high_data + low_data;
data &= 0x0fff;
printk("data : %d\n",data);
mdelay(5);
//在獲取完值要關閉片選寄存器
PianRes = 0xff;
}
return 0;
}
static void __exit spi_exit(void)
{
printk("exit!\n");
}
module_init(spi_init);
module_exit(spi_exit);
MODULE_LICENSE("GPL");