天天看點

STM32常見通信方式(TTL、RS232、RS485、I2C,SPI,CAN)總結STM32常見通信方式(TTL、RS232、RS485、I2C,SPI,CAN)總結三、RS-485:半雙工、(邏輯1:+2V–+6V  邏輯0: -6V—2V)這裡的電平指AB 兩線間的電壓差。五、I2CSPICAN

STM32常見通信方式(TTL、RS232、RS485、I2C,SPI,CAN)總結

一、TTL電平:全雙工(邏輯1: 2.4V–5V   邏輯0: 0V–0.5V)

1、硬體框圖如下,TTL用于兩個MCU間通信

STM32常見通信方式(TTL、RS232、RS485、I2C,SPI,CAN)總結STM32常見通信方式(TTL、RS232、RS485、I2C,SPI,CAN)總結三、RS-485:半雙工、(邏輯1:+2V–+6V  邏輯0: -6V—2V)這裡的電平指AB 兩線間的電壓差。五、I2CSPICAN

2、‘0’和‘1’表示

STM32常見通信方式(TTL、RS232、RS485、I2C,SPI,CAN)總結STM32常見通信方式(TTL、RS232、RS485、I2C,SPI,CAN)總結三、RS-485:半雙工、(邏輯1:+2V–+6V  邏輯0: -6V—2V)這裡的電平指AB 兩線間的電壓差。五、I2CSPICAN

二、RS-232電平:全雙工(邏輯1:-15V–5V  邏輯0:+3V–+15V)

1、硬體框圖如下,TTL用于MCU與PC機之間通信

STM32常見通信方式(TTL、RS232、RS485、I2C,SPI,CAN)總結STM32常見通信方式(TTL、RS232、RS485、I2C,SPI,CAN)總結三、RS-485:半雙工、(邏輯1:+2V–+6V  邏輯0: -6V—2V)這裡的電平指AB 兩線間的電壓差。五、I2CSPICAN

2、‘0’和‘1’表示

STM32常見通信方式(TTL、RS232、RS485、I2C,SPI,CAN)總結STM32常見通信方式(TTL、RS232、RS485、I2C,SPI,CAN)總結三、RS-485:半雙工、(邏輯1:+2V–+6V  邏輯0: -6V—2V)這裡的電平指AB 兩線間的電壓差。五、I2CSPICAN

三、RS-485:半雙工、(邏輯1:+2V–+6V  邏輯0: -6V—2V)這裡的電平指AB 兩線間的電壓差。

1、硬體框圖如下

STM32常見通信方式(TTL、RS232、RS485、I2C,SPI,CAN)總結STM32常見通信方式(TTL、RS232、RS485、I2C,SPI,CAN)總結三、RS-485:半雙工、(邏輯1:+2V–+6V  邏輯0: -6V—2V)這裡的電平指AB 兩線間的電壓差。五、I2CSPICAN

2、‘0’和‘1’表示

STM32常見通信方式(TTL、RS232、RS485、I2C,SPI,CAN)總結STM32常見通信方式(TTL、RS232、RS485、I2C,SPI,CAN)總結三、RS-485:半雙工、(邏輯1:+2V–+6V  邏輯0: -6V—2V)這裡的電平指AB 兩線間的電壓差。五、I2CSPICAN

四、CAN總線:邏輯1:-1.5V–0V  邏輯0:+1.5V–+3V)這裡的電平指CAN_High、CAN_Low 兩線間的電壓差。

1、硬體框圖如下

STM32常見通信方式(TTL、RS232、RS485、I2C,SPI,CAN)總結STM32常見通信方式(TTL、RS232、RS485、I2C,SPI,CAN)總結三、RS-485:半雙工、(邏輯1:+2V–+6V  邏輯0: -6V—2V)這裡的電平指AB 兩線間的電壓差。五、I2CSPICAN

2、‘0’和‘1’表示

STM32常見通信方式(TTL、RS232、RS485、I2C,SPI,CAN)總結STM32常見通信方式(TTL、RS232、RS485、I2C,SPI,CAN)總結三、RS-485:半雙工、(邏輯1:+2V–+6V  邏輯0: -6V—2V)這裡的電平指AB 兩線間的電壓差。五、I2CSPICAN

以上總結:

1、從單片機軟體程式設計角度來說,RS232、RS-485最終結果都是轉換為TTL電平方式與單片機通信(CAN收發器把差分信号轉化為TTL–>CAN控制器(MCU))。其目的都是提高通信品質,提高抗幹擾能力。

2、TTL、RS232是邏輯電平信号。RS-485、CAN為差分信号。

五、I2C

5.1 I2C實體層

STM32常見通信方式(TTL、RS232、RS485、I2C,SPI,CAN)總結STM32常見通信方式(TTL、RS232、RS485、I2C,SPI,CAN)總結三、RS-485:半雙工、(邏輯1:+2V–+6V  邏輯0: -6V—2V)這裡的電平指AB 兩線間的電壓差。五、I2CSPICAN

5.2 I2C協定層

STM32常見通信方式(TTL、RS232、RS485、I2C,SPI,CAN)總結STM32常見通信方式(TTL、RS232、RS485、I2C,SPI,CAN)總結三、RS-485:半雙工、(邏輯1:+2V–+6V  邏輯0: -6V—2V)這裡的電平指AB 兩線間的電壓差。五、I2CSPICAN

5.3 資料的起始信号與停止信号

STM32常見通信方式(TTL、RS232、RS485、I2C,SPI,CAN)總結STM32常見通信方式(TTL、RS232、RS485、I2C,SPI,CAN)總結三、RS-485:半雙工、(邏輯1:+2V–+6V  邏輯0: -6V—2V)這裡的電平指AB 兩線間的電壓差。五、I2CSPICAN

5.4資料有效性

STM32常見通信方式(TTL、RS232、RS485、I2C,SPI,CAN)總結STM32常見通信方式(TTL、RS232、RS485、I2C,SPI,CAN)總結三、RS-485:半雙工、(邏輯1:+2V–+6V  邏輯0: -6V—2V)這裡的電平指AB 兩線間的電壓差。五、I2CSPICAN

I2C 協定在 SCL 高電平時對 SDA 信号采樣, SCL 低電平時 SDA準備下一個資料。

SPI

标準SPI

标準SPI通常就稱SPI,它是一種串行外設接口規範,有4根引腳信号:clk , cs, mosi, miso

Dual SPI

它隻是針對SPI Flash而言,不是針對所有SPI外設。對于SPI Flash,全雙工并不常用,是以擴充了mosi和miso的用法,讓它們工作在半雙工,用以加倍資料傳輸。也就是對于Dual SPI Flash,可以發送一個指令位元組進入dual mode,這樣mosi變成SIO0(serial io 0),mosi變成SIO1(serial io 1),這樣一個時鐘周期内就能傳輸2個bit資料,加倍了資料傳輸

Qual SPI

與Dual SPI類似,也是針對SPI Flash,Qual SPI Flash增加了兩根I/O線(SIO2,SIO3),目的是一個時鐘内傳輸4個bit

是以對于SPI Flash,有标準spi flash,dual spi , qual spi 三種類型,分别對應3-wire, 4-wire, 6-wire,在相同clock下,線數越多,傳輸速率越高。

btw:spi flash一般為NOR Flash

SPI接口介紹

    SPI是由美國摩托羅拉公司推出的一種同步串行傳輸規範,常作為單片機外設晶片串行擴充接 口。SPI有4個引腳:SS(從器件選擇線)、SDO(串行資料輸出線)、SDI(串行資料輸入線)和SCK(同步串行時鐘線)。SPI可以用全雙工通信 方式同時發送和接收8(16)位資料,過程如下:主機啟動發送過程,送出時鐘脈沖信号,主移位寄存器的資料通過SDO移入到從移位寄存器,同時從移位寄存 器中的資料通過SDI移人到主移位寄存器中。8(16)個時鐘脈沖過後,時鐘停頓,主移位寄存器中的8(16)位資料全部移人到從移位寄存器中,随即又被 自動裝入從接收緩沖器中,從機接收緩沖器滿标志位(BF)和中斷标志位(SSPIF)置“1”。同理,從移位寄存器中的8位資料全部移入到主寄存器中,随 即又被自動裝入到主接收緩沖器中.主接收緩沖器滿标志位(BF)和中斷标志位(SSPIF)置“1”。主CPU檢測到主接收緩沖器的滿标志位或者中斷标志 位置1後,就可以讀取接收緩沖器中的資料。同樣,從CPU檢測到從接收緩沖器滿标志位或中斷标志位置1後,就可以讀取接收緩沖器中的資料,這樣就完成了一 次互相通信過程。這裡設定dsPIC30F6014為主要制器,ISD4002為從器件,通過SPI口完成通信控制的過程。

SPI總線協定

SPI是一個環形總線結構,由ss(cs)、sck、sdi、sdo構成,其時序其實很簡單,主要是在sck的控制下,兩個雙向移位寄存器進行資料交換。

       假設下面的8位寄存器裝的是待發送的資料10101010,上升沿發送、下降沿接收、高位先發送。

       那麼第一個上升沿來的時候 資料将會是sdo=1;寄存器=0101010x。下降沿到來的時候,sdi上的電平将所存到寄存器中去,那麼這時寄存器=0101010sdi,這樣在 8個時鐘脈沖以後,兩個寄存器的内容互相交換一次。這樣就完成裡一個spi時序。

       例子:

       假設主機和從機初始化就緒:并且主機的sbuff=0xaa,從機的sbuff=0x55,下面将分步對spi的8個時鐘周期的資料情況示範一遍:假設上升沿發送資料

脈沖    主機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引腳作為主機的時候,從機可以把它拉底被 動選為從機,作為從機的是時候,可以作為片選腳用。根據以上分析,一個完整的傳送周期是16位,即兩個位元組,因為,首先主機要發送指令過去,然後從機根據 主機的名準備資料,主機在下一個8位時鐘周期才把資料讀回來

SPI 總線是Motorola公司推出的三線同步接口,同步串行3線方式進行通信:一條時鐘線SCK,一條資料輸入線MOSI,一條資料輸出線MISO;用于 CPU與各種外圍器件進行全雙工、同步串行通訊。SPI主要特點有:可以同時發出和接收串行資料;可以當作主機或從機工作;提供頻率可程式設計時鐘;發送結束 中斷标志;寫沖突保護;總線競争保護等。圖3示出SPI總線工作的四種方式,其中使用的最為廣泛的是SPI0和SPI3方式(實線表示):

SPI總線接口及時序

   SPI 子產品為了和外設進行資料交換,根據外設工作要求,其輸出串行同步時鐘極性和相位可以進行配置,時鐘極性(CPOL)對傳輸協定沒有重大的影響。如果 CPOL=0,串行同步時鐘的空閑狀态為低電平;如果CPOL=1,串行同步時鐘的空閑狀态為高電平。時鐘相位(CPHA)能夠配置用于選擇兩種不同的傳 輸協定之一進行資料傳輸。如果CPHA=0,在串行同步時鐘的第一個跳變沿(上升或下降)資料被采樣;如果CPHA=1,在串行同步時鐘的第二個跳變沿 (上升或下降)資料被采樣。SPI主子產品和與之通信的外設音時鐘相位和極性應該一緻。SPI總線接口時序如下所示。

STM32常見通信方式(TTL、RS232、RS485、I2C,SPI,CAN)總結STM32常見通信方式(TTL、RS232、RS485、I2C,SPI,CAN)總結三、RS-485:半雙工、(邏輯1:+2V–+6V  邏輯0: -6V—2V)這裡的電平指AB 兩線間的電壓差。五、I2CSPICAN

SPI功能子產品的設計

根據功能定義及SPI的工作原理,将整個IP Core分為8個子子產品:uC接口子產品、時鐘分頻子產品、發送資料FIFO子產品、接收資料FIFO子產品、狀态機子產品、發送資料邏輯子產品、接收資料邏輯子產品以及中斷形式子產品。

深入分析SPI的四種傳輸協定可以發現,根據一種協定,隻要對串行同步時鐘進行轉換,就能得到其餘的三種協定。為了簡化設計規定,如果要連續傳輸多個資料,在兩個資料傳輸之間插入一個串行時鐘的空閑等待,這樣狀态機隻需兩種狀态(空閑和工作)就能正确工作。

CAN

CAN 是Controller Area Network 的縮寫(以下稱為CAN),是ISO國際标準化的串行通信協定。

它的通信速度較快,通信距離遠,最高1Mbps(距離小于40米),最遠可達10千裡(速率低于5Kbps)。在總線空閑時,所有單元都可以發送消息(多主要制),而兩個以上的單元同時開始發送消息時,根據辨別符(Identifier 以下稱為 ID)決定優先級。ID 并不是表示發送的目的位址,而是表示通路總線的消息的優先級。兩個以上的單元同時開始發送消息時,對各消息ID 的每個位進行逐個仲裁比較。仲裁獲勝(被判定為優先級最高)的單元可繼續發送消息,仲裁失利的單元則立刻停止發送而進行接收工作。

CAN協定經過ISO标準化後有兩個标準:ISO11898标準和ISO11519-2标準。其中ISO11898是針對通信速率為125Kbps~1Mbps的高速通信标準,而ISO11519-2是針對通信速率為125Kbps以下的低速通信标準。

本章,我們使用的是450Kbps的通信速率,使用的是ISO11898标準,該标準的實體層特征如圖1所示:

STM32常見通信方式(TTL、RS232、RS485、I2C,SPI,CAN)總結STM32常見通信方式(TTL、RS232、RS485、I2C,SPI,CAN)總結三、RS-485:半雙工、(邏輯1:+2V–+6V  邏輯0: -6V—2V)這裡的電平指AB 兩線間的電壓差。五、I2CSPICAN

從該特性可以看出,顯性電平對應邏輯0,CAN_H和CAN_L之差為2.5V左右。而隐性電平對應邏輯1,CAN_H和CAN_L之差為0V。在總線上顯性電平具有優先權,隻要有一個單元輸出顯性電平,總線上即為顯性電平。而隐形電平則具有包容的意味,隻有所有的單元都輸出隐性電平,總線上才為隐性電平(顯性電平比隐性電平更強)。另外,在CAN總線的起止端都有一個120Ω的終端電阻,來做阻抗比對,以減少回波反射。

CAN協定是通過以下5種類型的幀進行的:

l 資料幀

l 搖控幀

l 錯誤幀

l 過載幀

l 幀間隔

另外,資料幀和遙控幀有标準格式和擴充格式兩種格式。标準格式有11 個位的辨別符(ID),擴充格式有29 個位的ID。

1.資料幀

資料幀一般由7個段構成,即:

(1) 幀起始。表示資料幀開始的段。

(2) 仲裁段。表示該幀優先級的段。

(3) 控制段。表示資料的位元組數及保留位的段。

(4) 資料段。資料的内容,一幀可發送0~8個位元組的資料。

(5) CRC段。檢查幀的傳輸錯誤的段。

(6) ACK段。表示确認正常接收的段。

(7) 幀結束。表示資料幀結束的段。

如圖2為資料幀的構成:

STM32常見通信方式(TTL、RS232、RS485、I2C,SPI,CAN)總結STM32常見通信方式(TTL、RS232、RS485、I2C,SPI,CAN)總結三、RS-485:半雙工、(邏輯1:+2V–+6V  邏輯0: -6V—2V)這裡的電平指AB 兩線間的電壓差。五、I2CSPICAN

圖中D表示顯性電平,R表示隐形電平(下同)。

幀起始,标準幀和擴充幀都是由1個位的顯性電平表示幀起始。

仲裁段,表示資料優先級的段,标準幀和擴充幀格式在本段有所差別,标準格式的ID 有11 個位。從ID28 到ID18 被依次發送。禁止高7 位都為隐性(禁止設定:ID=1111111XXXX,原因:can通信采用的是NZR編碼,而can的仲裁是靠資料幀中的ID部分來實作的,全為隐性狀态,可能導緻仲裁失敗!)。擴充格式的 ID 有29 個位。基本ID 從ID28 到ID18,擴充ID 由ID17 到ID0 表示。基本ID 和标準格式的ID 相同。禁止高7 位都為隐性(禁止設定:基本ID=1111111XXXX)。

其中RTR位用于辨別是否是遠端幀(0,資料幀;1,遠端幀),IDE位為辨別符選擇位(0,使用标準辨別符;1,使用擴充辨別符),SRR位為代替遠端請求位,為隐性位,它代替了标準幀中的RTR位。

控制段,由6個位構成,表示資料段的位元組數。

資料段,該段可包含0~8個位元組的資料。從最高位(MSB)開始輸出,标準幀和擴充幀在這個段的定義都是一樣的。

CRC段,該段用于檢查幀傳輸錯誤。由15個位的CRC順序和1個位的CRC界定符(用于分隔的位)組成,标準幀和擴充幀在這個段的格式也是相同的。

ACK段,此段用來确認是否正常接收。由ACK槽(ACK Slot)和ACK界定符2個位組成。标準幀和擴充幀在這個段的格式也是相同的。

2.遠端幀(遙控幀)

遠端幀作用:隻發送ID号,不發送資料,它将ID發給另一台裝置,請求另一台裝置傳回資料。

3.CAN總線波特率設定

位速率:由發送單元在非同步的情況下發送的每秒鐘的位數稱為位速率。一個位可分為 4 段。

l 同步段(SS)

l 傳播時間段(PTS)

l 相位緩沖段1(PBS1)

l 相位緩沖段2(PBS2)

這些段又由可稱為 Time Quantum(以下稱為Tq)的最小時間機關構成。

1 位分為4 個段,每個段又由若幹個Tq 構成,這稱為位時序。

1 位由多少個Tq 構成、每個段又由多少個Tq 構成等,可以任意設定位時序。通過設定位時序,多個單元可同時采樣,也可任意設定采樣點。STM32把傳播時間段和相位緩沖段1(STM32稱之為時間段1)合并了,是以STM32的CAN一個位隻有3段:同步段(SYNC_SEG)、時間段1(BS1)和時間段2(BS2)。STM32的BS1段可以設定為1~16個時間單元,剛好等于我們上面介紹的傳播時間段和相位緩沖段1之和。STM32的CAN位時序如圖3所示:

STM32常見通信方式(TTL、RS232、RS485、I2C,SPI,CAN)總結STM32常見通信方式(TTL、RS232、RS485、I2C,SPI,CAN)總結三、RS-485:半雙工、(邏輯1:+2V–+6V  邏輯0: -6V—2V)這裡的電平指AB 兩線間的電壓差。五、I2CSPICAN

圖中還給出了CAN波特率的計算公式,我們隻需要知道BS1和BS2的設定,以及APB1的時鐘頻率(一般為36Mhz),就可以友善的計算出波特率。比如設定TS1=6、TS2=7和BRP=4,在APB1頻率為36Mhz的條件下,即可得到CAN通信的波特率=36000/[(7+8+1)*5]=450Kbps。圖4是常見CAN總線的波特率設定:

STM32常見通信方式(TTL、RS232、RS485、I2C,SPI,CAN)總結STM32常見通信方式(TTL、RS232、RS485、I2C,SPI,CAN)總結三、RS-485:半雙工、(邏輯1:+2V–+6V  邏輯0: -6V—2V)這裡的電平指AB 兩線間的電壓差。五、I2CSPICAN
STM32常見通信方式(TTL、RS232、RS485、I2C,SPI,CAN)總結STM32常見通信方式(TTL、RS232、RS485、I2C,SPI,CAN)總結三、RS-485:半雙工、(邏輯1:+2V–+6V  邏輯0: -6V—2V)這裡的電平指AB 兩線間的電壓差。五、I2CSPICAN
STM32常見通信方式(TTL、RS232、RS485、I2C,SPI,CAN)總結STM32常見通信方式(TTL、RS232、RS485、I2C,SPI,CAN)總結三、RS-485:半雙工、(邏輯1:+2V–+6V  邏輯0: -6V—2V)這裡的電平指AB 兩線間的電壓差。五、I2CSPICAN
STM32常見通信方式(TTL、RS232、RS485、I2C,SPI,CAN)總結STM32常見通信方式(TTL、RS232、RS485、I2C,SPI,CAN)總結三、RS-485:半雙工、(邏輯1:+2V–+6V  邏輯0: -6V—2V)這裡的電平指AB 兩線間的電壓差。五、I2CSPICAN

4.CAN總線屏蔽濾波

STM32的辨別符屏蔽濾波目的是減少了CPU處理CAN通信的開銷。STM32的過濾器組最多有28個(互聯型),但是STM32F103ZET6隻有14個(增強型),每個濾波器組x由2個32為寄存器,CAN_FxR1和CAN_FxR2組成。

STM32每個過濾器組的位寬都可以獨立配置,以滿足應用程式的不同需求。根據位寬的不同,每個過濾器組可提供:

● 1個32位過濾器,包括:STDID[10:0]、EXTID[17:0]、IDE和RTR位

● 2個16位過濾器,包括:STDID[10:0]、IDE、RTR和EXTID[17:15]位

此外過濾器可配置為,屏蔽位模式和辨別符清單模式。

在屏蔽位模式下,辨別符寄存器和屏蔽寄存器一起,指定封包辨別符的任何一位,應該按照“必須比對”或“不用關心”處理。

而在辨別符清單模式下,屏蔽寄存器也被當作辨別符寄存器用。是以,不是采用一個辨別符加一個屏蔽位的方式,而是使用2個辨別符寄存器。接收封包辨別符的每一位都必須跟過濾器辨別符相同。

濾波過程舉例:

現有ID号為001,002,003,004的4個CAN,他們都能發送、接收廣播封包。站在CAN002号角度看,它所能接受到封包的ID是通過濾波器濾波後的ID号,即這裡将過濾方式分兩種,一是002号能接收多個ID封包(屏蔽濾波模式),二是002号隻能接收一個ID封包(辨別符清單模式)。

屏蔽濾波模式:

辨別符寄存器:0 0 1

屏蔽寄存器: 1 0 1

封包ID号: 0 0/1 1

如果設定辨別符寄存器和屏蔽寄存器為001和101;屏蔽濾波模式的作用是如果屏蔽寄存器某位上出現了1,則封包ID号對應的那位要與辨別符寄存器那位一緻,即“必須比對”原則,是以辨別符寄存器第一位0,封包ID号第一位也必須為0,因為屏蔽寄存器第一位為1,類似的第三位也是這樣。如果屏蔽寄存器某位上出現了0,則封包ID号對應的那位可與辨別符寄存器那位不一緻也可以一緻,即“不用關心”原則,第二位由于屏蔽寄存器上為0,是以封包ID号可以與辨別符寄存器上的0一緻也可以不一緻,故封包ID号第二位為0/1。是以002号(010)可以接受來自001号(001)和003号(011)的封包。

辨別符清單模式:将設定的屏蔽寄存器改為辨別符寄存器

辨別符寄存器:0 0 1

辨別符寄存器: 0 0 1

封包ID号: 0 0 1

如果設定2個辨別符寄存器為001和001;封包ID号必須與這兩個辨別符寄存器所對應的位相等。是以002号CAN隻能接受001号的封包。

下圖5是CAN_FMR寄存器,可以配置過濾器組的寄存器位數16還是32位,工作模式以及它和标準幀、擴充幀位數的對應關系,友善我們在不同的幀模式(标準資料幀、擴充資料幀、标準遠端幀、擴充遠端幀)下對封包ID進行過濾。

STM32常見通信方式(TTL、RS232、RS485、I2C,SPI,CAN)總結STM32常見通信方式(TTL、RS232、RS485、I2C,SPI,CAN)總結三、RS-485:半雙工、(邏輯1:+2V–+6V  邏輯0: -6V—2V)這裡的電平指AB 兩線間的電壓差。五、I2CSPICAN

5.CAN的發送與接收流程

5.1CAN 發送流程

發送封包的流程為:應用程式選擇1個空發送郵箱;設定辨別符、資料長度和待發送資料;然後CAN_TIxR寄存器的TXRQ位置1,來請求發送。TXRQ位置1後,郵箱就不再是空郵箱;而一旦郵箱不再為空,軟體對郵箱寄存器就不再有寫的權限。TXRQ位置1後,郵箱馬上進入挂号狀态,并等待成為最高優先級的郵箱。一旦郵箱成為最高優先級的郵箱,其狀态就變為預定發送狀态。當CAN總線進入空閑狀态,預定發送郵箱中的封包就馬上被發送(進入發送狀态)。郵箱中的封包被成功發送後,它馬上變為空郵箱,硬體相應地對CAN_TSR寄存器的RQCP和TXOK位置1,此時可以設定發送中斷(入口位址:USB_HP_CAN_TX_IRQChannel()),進入中斷置can_tx_flag_success=1,來表明一次成功發送。

5.2CAN接收流程

接收到的封包,被存儲在3級郵箱深度的FIFO中。FIFO完全由硬體來管理,進而節省了CPU的處理負荷,簡化了軟體并保證了資料的一緻性。應用程式隻能通過讀取FIFO輸出郵箱,來讀取FIFO中最先收到的封包。根據CAN協定,當封包被正确接收(直到EOF域的最後1位都沒有錯誤),且通過了辨別符過濾,那麼該封包被認為是有效封包。接收相關的中斷條件:

一旦往FIFO存入1個封包,硬體就會更新FMP[1:0]位,并且如果CAN_IER寄存器的FMPIE位為1,那麼就會産生一個中斷請求,可以進入接收中斷讀取接收的資料(入口位址:USB_LP_CAN_RX0_IRQChannel())。

當FIFO變滿時(即第3個封包被存入),CAN_RFxR寄存器的FULL位就被置1,并且如果CAN_IER寄存器的FFIE位為1,那麼就會産生一個滿中斷請求。

在溢出的情況下,FOVR位被置1,并且如果CAN_IER寄存器的FOVIE位為1,那麼就會産生一個溢出中斷請求。

6.CAN總線應用——CAN與上位機通訊實驗(基于stm32f103zet6)

6.1硬體設計

本文的TX與RX采用PB9和PB8(端口重映射),他們與CAN收發器連接配接,CAN收發器(晶片有很多,如:TJA1050;SN65VD230)與USB/CAN轉換器連接配接到PC機上,具體電路如圖6。

CAN收發器:

STM32常見通信方式(TTL、RS232、RS485、I2C,SPI,CAN)總結STM32常見通信方式(TTL、RS232、RS485、I2C,SPI,CAN)總結三、RS-485:半雙工、(邏輯1:+2V–+6V  邏輯0: -6V—2V)這裡的電平指AB 兩線間的電壓差。五、I2CSPICAN

usb/can轉換器:某寶上有賣,100多就行。

6.2程式

#include "pbdata.h"

void RCC_Configuration(void);
void GPIO_Configuration(void);
void NVIC_Configuration(void);
void CAN_Configuration(void);


int main(void)
{
	CanTxMsg TxMessage;
	
	RCC_Configuration();	//時鐘配置
	GPIO_Configuration();//端口配置
	NVIC_Configuration();
	CAN_Configuration();
	
	
	while(1)
	{
		//每隔1s發送一個封包,一個封包8B
		TxMessage.StdId=0xFF00>>5;//标準幀隻有31-21位,對于16位寄存器而言,低五位為擴充幀,是以在寫16位資料時,最後5位置0
		TxMessage.ExtId=0;
		TxMessage.IDE=CAN_ID_STD;//選擇發送标準幀
   		//TxMessage.StdId=0;
		//TxMessage.ExtId=0xFFFFFFFF>>3;//擴充幀隻有18位,在32位資料時最後三位為(IDE,RTR,TXRQ),是以在寫擴充幀時,最後三位要置0
    
		
		//TxMessage.IDE=CAN_ID_EXT;
		//發送擴充幀
		TxMessage.RTR=CAN_RTR_DATA;//發送的是資料幀
	//TxMessage.RTR=CAN_RTR_REMOTE;//遠端幀,隻發送ID,不發送資料,将ID發給另一台裝置,請求另一台裝置傳回資料
		TxMessage.DLC=8;//資料長度8B
		
		TxMessage.Data[0]=0x11;
		TxMessage.Data[1]=0x22;
		TxMessage.Data[2]=0x33;
		TxMessage.Data[3]=0x44;
		TxMessage.Data[4]=0x55;
		TxMessage.Data[5]=0x66;
		TxMessage.Data[6]=0x77;
		TxMessage.Data[7]=0x88;
		//資料内容
		can_tx_success_flag = 0;
       CAN_Transmit(CAN1,&tx_message);//can發送資料
       while(can_tx_success_flag == 0);//是否一次發送成功
		delay_ms(1000);//1s一次 
	}	
}

void RCC_Configuration(void)
{
    SystemInit();//72m
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_CAN1,ENABLE);
}

void GPIO_Configuration(void)
{
    GPIO_InitTypeDef GPIO_InitStructure;	
	
	//端口重映射
	GPIO_PinRemapConfig(GPIO_Remap1_CAN1,ENABLE);

	GPIO_InitStructure.GPIO_Pin=GPIO_Pin_8;//RX
	GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IPU;
	GPIO_Init(GPIOB,&GPIO_InitStructure);

	GPIO_InitStructure.GPIO_Pin=GPIO_Pin_9;//TX
	GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
	GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF_PP;
	GPIO_Init(GPIOB,&GPIO_InitStructure);
}

void NVIC_Configuration(void)
{
   	NVIC_InitTypeDef NVIC_InitStructure; 

	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1); 

	NVIC_InitStructure.NVIC_IRQChannel = USB_LP_CAN1_RX0_IRQn; 
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; 
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; 
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; 
	NVIC_Init(&NVIC_InitStructure);
}

void CAN_Configuration(void)
{
	//硬體上有個can/usb才能與PC通訊
   CAN_InitTypeDef CAN_InitStructure;
   CAN_FilterInitTypeDef CAN_FilterInitStructure;

   CAN_DeInit(CAN1);
   CAN_StructInit(&CAN_InitStructure);

   //關閉時間觸發模式
   CAN_InitStructure.CAN_TTCM=DISABLE;
   //關閉自動離線管理
   CAN_InitStructure.CAN_ABOM=DISABLE;
   //關閉自動喚醒模式
   CAN_InitStructure.CAN_AWUM=DISABLE;
   //禁止封包自動重傳
   CAN_InitStructure.CAN_NART=DISABLE;
   //FIFO溢出時封包覆寫源檔案
   CAN_InitStructure.CAN_RFLM=DISABLE;
   //封包發送優先級取決于ID号,本次隻用了一個發送郵箱,關閉TXFP
   CAN_InitStructure.CAN_TXFP=DISABLE;
   //工作模式(正常)
   CAN_InitStructure.CAN_Mode=CAN_Mode_Normal;

   //波特率設定125 KBPS

   CAN_InitStructure.CAN_SJW=CAN_SJW_1tq;
   CAN_InitStructure.CAN_BS1=CAN_BS1_3tq;
   CAN_InitStructure.CAN_BS2=CAN_BS2_2tq;
   CAN_InitStructure.CAN_Prescaler = 48;


   //初始化CAN
   CAN_Init(CAN1,&CAN_InitStructure);

   //屏蔽濾波(can接收才涉及)
   CAN_FilterInitStructure.CAN_FilterNumber=0;//0号濾波器
   //屏蔽濾波模式
   CAN_FilterInitStructure.CAN_FilterMode=CAN_FilterMode_IdMask;//辨別符屏蔽位模式
   //32位寄存器
   CAN_FilterInitStructure.CAN_FilterScale=CAN_FilterScale_32bit;
   //辨別符寄存器高16位
   CAN_FilterInitStructure.CAN_FilterIdHigh=0x0F00;
   //辨別符寄存器低16位
   CAN_FilterInitStructure.CAN_FilterIdLow=0;
   //屏蔽寄存器高16位
   CAN_FilterInitStructure.CAN_FilterMaskIdHigh=0x0F00;
   //屏蔽寄存器低16位
   CAN_FilterInitStructure.CAN_FilterMaskIdLow=0;
   //過濾器将ID封包關聯到FIFO0緩存區中,資料隻能從這裡導出
   CAN_FilterInitStructure.CAN_FilterFIFOAssignment=CAN_Filter_FIFO0;
   //過濾器使能
   CAN_FilterInitStructure.CAN_FilterActivation=ENABLE;
   //初始化過濾器
   CAN_FilterInit(&CAN_FilterInitStructure);

   //接收中斷使能
   CAN_ITConfig(CAN1,CAN_IT_FMP0,ENABLE);
   //發送中斷使能
   CAN_ITConfig(CAN1,CAN_IT_TME,ENABLE);
}

           
void USB_LP_CAN1_RX0_IRQHandler(void)
{
	CanRxMsg RxMessage;
	CanTxMsg TxMessage;

	//CAN接收
	CAN_Receive(CAN1,CAN_FIFO0,&RxMessage);//can接收的資料存在FIFO0的RxMessage裡

	TxMessage.StdId=RxMessage.StdId;//标準ID
	TxMessage.ExtId=RxMessage.ExtId;//擴充ID
	TxMessage.IDE=RxMessage.IDE;//标準幀還是擴充幀
	TxMessage.RTR=RxMessage.RTR;//資料幀還是遠端幀
	TxMessage.DLC=RxMessage.DLC;//待傳輸資料長度

	TxMessage.Data[0]=RxMessage.Data[0];
	TxMessage.Data[1]=RxMessage.Data[1];
	TxMessage.Data[2]=RxMessage.Data[2];
	TxMessage.Data[3]=RxMessage.Data[3];
	TxMessage.Data[4]=RxMessage.Data[4];
	TxMessage.Data[5]=RxMessage.Data[5];
	TxMessage.Data[6]=RxMessage.Data[6];
	TxMessage.Data[7]=RxMessage.Data[7];
	//CAN發送
	CAN_Transmit(CAN1,&TxMessage);
}
           

繼續閱讀