SPI、IIC、UART、can區(qū)別
脈沖 | 主機sbuff | 從機sbuff | sdi | sdo |
0 | 10101010 | 01010101 | 0 | 0 |
1上 | 0101010x | 1010101x | 0 | 1 |
1下 | 01010100 | 10101011 | 0 | 1 |
2上 | 1010100x | 0101011x | 1 | 0 |
2下 | 10101001 | 01010110 | 1 | 0 |
3上 | 0101001x | 1010110x | 0 | 1 |
3下 | 01010010 | 10101101 | 0 | 1 |
4上 | 1010010x | 0101101x | 1 | 0 |
4下 | 10100101 | 01011010 | 1 | 0 |
5上 | 0100101x | 1011010x | 0 | 1 |
5下 | 01001010 | 10110101 | 0 | 1 |
6上 | 1001010x | 0110101x | 1 | 0 |
6下 | 10010101 | 01101010 | 1 | 0 |
7上 | 0010101x | 1101010x | 0 | 1 |
7下 | 00101010 | 11010101 | 0 | 1 |
8上 | 0101010x | 1010101x | 1 | 0 |
8下 | 01010101 | 10101010 | 1 | 0 |
這樣就完成了兩個寄存器8位的交換,上面的上表示上升沿、下表示下降沿,sdi、sdo相對于主機而言的。其中ss引腳作為主機的時候,從機可以把它拉底被動選為從機,作為從機的是時候,可以作為片選腳用。根據(jù)以上分析,一個完整的傳送周期是16位,即兩個字節(jié),因為,首先主機要發(fā)送命令過去,然后從機根據(jù)主機的名準備數(shù)據(jù),主機在下一個8位時鐘周期才把數(shù)據(jù)讀回來
SPI 總線是Motorola公司推出的三線同步接口,同步串行3線方式進行通信:一條時鐘線SCK,一條數(shù)據(jù)輸入線MOSI,一條數(shù)據(jù)輸出線MISO;用于CPU與各種外圍器件進行全雙工、同步串行通訊。SPI主要特點有:可以同時發(fā)出和接收串行數(shù)據(jù);可以當作主機或從機工作;提供頻率可編程時鐘;發(fā)送結束中斷標志;寫沖突保護;總線競爭保護等。圖3示出SPI總線工作的四種方式,其中使用的最為廣泛的是SPI0和SPI3方式(實線表示):
圖2
SPI模塊為了和外設進行數(shù)據(jù)交換,根據(jù)外設工作要求,其輸出串行同步時鐘極性和相位可以進行配置,時鐘極性(CPOL)對傳輸協(xié)議沒有重大的影響。如果CPOL=0,串行同步時鐘的空閑狀態(tài)為低電平;如果CPOL=1,串行同步時鐘的空閑狀態(tài)為高電平。時鐘相位(CPHA)能夠配置用于選擇兩種不同的傳輸協(xié)議之一進行數(shù)據(jù)傳輸。如果CPHA=0,在串行同步時鐘的第一個跳變沿(上升或下降)數(shù)據(jù)被采樣;如果CPHA=1,在串行同步時鐘的第二個跳變沿(上升或下降)數(shù)據(jù)被采樣。SPI主模塊和與之通信的外設音時鐘相位和極性應該一致。SPI接口時序如圖3、圖4所示。
二,.SPI功能模塊的設計
根據(jù)功能定義及SPI的工作原理,將整個IP Core分為8個子模塊:uC接口模塊、時鐘分頻模塊、發(fā)送數(shù)據(jù)FIFO模塊、接收數(shù)據(jù)FIFO模塊、狀態(tài)機模塊、發(fā)送數(shù)據(jù)邏輯模塊、接收數(shù)據(jù)邏輯模塊以及中斷形式模塊。
深入分析SPI的四種傳輸協(xié)議可以發(fā)現(xiàn),根據(jù)一種協(xié)議,只要對串行同步時鐘進行轉換,就能得到其余的三種協(xié)議。為了簡化設計規(guī)定,如果要連續(xù)傳輸多個數(shù)據(jù),在兩個數(shù)據(jù)傳輸之間插入一個串行時鐘的空閑等待,這樣狀態(tài)機只需兩種狀態(tài)(空閑和工作)就能正確工作。
SPI協(xié)議心得
SPI接口時鐘配置心得:
在主設備這邊配置SPI接口時鐘的時候一定要弄清楚從設備的時鐘要求,因為主設備這邊的時鐘極性和相位都是以從設備為基準的。因此在時鐘極性的配置上一定要搞清楚從設備是在時鐘的上升沿還是下降沿接收數(shù)據(jù),是在時鐘的下降沿還是上升沿輸出數(shù)據(jù)。但要注意的是,由于主設備的SDO連接從設備的SDI,從設備的SDO連接主設備的SDI,從設備SDI接收的數(shù)據(jù)是主設備的SDO發(fā)送過來的,主設備SDI接收的數(shù)據(jù)是從設備SDO發(fā)送過來的,所以主設備這邊SPI時鐘極性的配置(即SDO的配置)跟從設備的SDI接收數(shù)據(jù)的極性是相反的,跟從設備SDO發(fā)送數(shù)據(jù)的極性是相同的。下面這段話是Sychip Wlan8100 Module Spec上說的,充分說明了時鐘極性是如何配置的:
The 81xx module will always input data bits at the rising edge of the clock, and the host will always output data bits on the falling edge of the clock.
意思是:主設備在時鐘的下降沿發(fā)送數(shù)據(jù),從設備在時鐘的上升沿接收數(shù)據(jù)。因此主設備這邊SPI時鐘極性應該配置為下降沿有效。
又如,下面這段話是摘自LCD Driver IC SSD1289:
SDI is shifted into 8-bit shift register on every rising edge of SCK in the order of data bit 7, data bit 6 …… data bit 0.
意思是:從設備SSD1289在時鐘的上升沿接收數(shù)據(jù),而且是按照從高位到地位的順序接收數(shù)據(jù)的。因此主設備的SPI時鐘極性同樣應該配置為下降沿有效。
時鐘極性和相位配置正確后,數(shù)據(jù)才能夠被準確的發(fā)送和接收。因此應該對照從設備的SPI接口時序或者Spec文檔說明來正確配置主設備的時鐘。
IIC
24C01
24C02
24C04
24C08
24C16
解析:IIC總線接口器件24C系列非易失性存儲器與89C51接口采用軟件模擬IIC。24C系列
存儲器器件地址統(tǒng)一為1010XXXX,不要問為什么,這是廠家出廠的時候規(guī)定好的了。至
于24C的引腳功能和89C51的接口我就不多說了,本文的重點主要是如何應用。
位為0的時候表示89C51要寫數(shù)據(jù)入存儲器,1的時候表示要從存儲器讀數(shù)據(jù)。還剩下中
三位A2,A1和A0。它們的高低電平取決于24C的A2,A1,A0是接高電平還是接地。A2,
A1 和A0有8個組合,因此可以擴展8個相同的器件,根據(jù)A2、A1、A0的不同,一樣的器件
也會有不同的地址。那么是不是每一個24C都可以擴展8個呢?不是的。注意上表,24C01
有三個可尋址位,A2,A1,A0,所以可以擴展8個,24C02也一樣。而04則只可以擴展4個
08只可以擴展2個,16就沒有擴展了,只可以掛一片24C16。為什么呢?因為訪問24C系列
除了訪問器件地址外,還要訪問器件內的字節(jié)的地址。例如24C01,要對其操作,就先選
選中它的地址,然后操作第一個字節(jié)或其他字節(jié),這些字節(jié)也是有地址的,分模塊,用
一個字節(jié)表示,最多可以操作256個字節(jié)。24C01和24C02不大于256個字節(jié),對其操作就
簡單得多了。但24C04,08和16呢?他們都大于256個字節(jié),怎么辦?分模塊。注意到上
表的P0,P1,P3沒有?把04分成兩個模塊,2X256B,08四個模塊,16就八個模塊。究竟
怎么
模塊操作呢?拿24C08為例,有A2 P1 P0。A2只可以0或1,所以只能擴展2個24C08,其
內有4個256字節(jié)的模塊,要操作哪個模塊取決于P1,P0的組合。例如,24C08的地址字節(jié)
為1010000X第一個字節(jié)地址為0,第256個地址為255,如果地址字節(jié)是1010001X,那么第
256個字節(jié)的地址為0,第512個字節(jié)的地址為255。就如此。
以了,這樣就擴展了,他們的器件地址分別是1010000X和1010100X。當要讀第一個(A2
接地)
進第二個(A2接高電平)24C08的第二個模塊的時候,應發(fā)送10101010地址字節(jié)。
代碼:
#include#define WRITE 0xA0
#define READ
#define BLOCK_SIZE
#define uchar unsigned char
#define HIGH 1
#define LOW 0
#define FALSE 0
#define TRUE ~FALSE
sbit SCL
sbit SDA
uchar xdata EAROMImage[BLOCK_SIZE]={0};
void delayi2c( void ) {
}
void I_start( void ) {
}
void I_stop( void ) {
}
//初始化
void I_init( void ) {
}
bit I_clock( void ) {
}
//發(fā)送8位數(shù)據(jù)
bit I_send( uchar I_data ) {
//接受8位數(shù)據(jù)
uchar I_receive( void ) {
}
//應答
void I_Ack( void ) {
}
評論