久久久久久久999_99精品久久精品一区二区爱城_成人欧美一区二区三区在线播放_国产精品日本一区二区不卡视频_国产午夜视频_欧美精品在线观看免费

 找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索
查看: 4115|回復: 0
打印 上一主題 下一主題
收起左側

STM32 CAN 控制器 詳解

[復制鏈接]
跳轉到指定樓層
樓主
ID:86860 發表于 2015-7-26 01:50 | 只看該作者 回帖獎勵 |倒序瀏覽 |閱讀模式
CAN 簡介

CAN  是 Controller Area Network  的縮寫(以下稱為 CAN),是 ISO 國際標準化的串行通信協議。在當前的汽車產業中,出于對安全性、舒適性、方便性、低公害、低成本的要求,各種各樣的電子控制系統被開發了出來。由于這些系統之間通信所用的數據類型及對可靠性的要求不盡相同,由多條總線構成的情況很多,線束的數量也隨之增加。為適應“減少線束的數量”、“通過多個 LAN,進行大量數據的高速通信”的需要,1986  年德國電氣商博世公司開發出面向汽車的 CAN  通信協議。此后,CAN  通過 ISO11898  及 ISO11519  進行了標準化,現在在歐洲已是汽車網絡的標準協議。  

現在,CAN  的高性能和可靠性已被認同,并被廣泛地應用于工業自動化、船舶、醫療設備、工業設備等方面,F場總線是當今自動化領域技術發展的熱點之一,被譽為自動化領域的計算機局域網。它的出現為分布式控制系統實現各節點之間實時、可靠的數據通信提供了強有力的技術支持。 

CAN  控制器根據兩根線上的電位差來判斷總線電平?偩電平分為顯性電平和隱性電平,二者必居其一。發送方通過使總線電平發生變化,將消息發送給接收方。

STM32 自帶的是 bxCAN,即基本擴展 CAN。它支持 CAN 協議 2.0A 和 2.0B。它的設計目標是,以最小的 CPU 負荷來高效處理大量收到的報文。它也支持報文發送的優先級要求(優先級特性可軟件配置)。對于安全緊要的應用,bxCAN 提供所有支持時間觸發通信模式所需的硬件功能。

STM32 的 bxCAN 的主要特點有:

支持 CAN 協議 2.0A 和 2.0B 主動模式

波特率最高達 1Mbps

支持時間觸發通信

具有 個發送郵箱

具有 級深度的 個接收 FIFO

可變的過濾器組(最多 28 個)

在 STM32 互聯型產品中,帶有 個 CAN 控制器,而 STM32F103ZET6 屬于增強型,不是互聯型,只有 個 CAN 控制器

STM32 的標識符過濾是一個比較復雜的東東,它的存在減少了 CPU 處理 CAN 通信的開銷。STM32 的過濾器組最多有 28 個(互聯型),但是 STM32F103ZET6 只有 14 個(增強型),每個濾波器組 由 個 32 為寄存器,CAN_FxR1 和 CAN_FxR2 組成。

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

CAN 的初始化配置步驟,CAN 相關的固件庫函數和定義分布在文件 stm32f10x_can.c 和頭文件 stm32f10x_can.h 文件中。

1配置相關引腳的復用功能,使能 CAN 時鐘。

我們要用 CAN,第一步就要使能 CAN 的時鐘。其次要設置 CAN 的相關引腳為復用輸出,這里我們需要設置 PA11 為上拉輸入(CAN_RX 引腳)PA12 為復用輸出(CAN_TX 引腳),并使能 PA 口的時鐘。使能 CAN1 時鐘的函數是:

RCC_APB1PeriphClockCmd(RCC_APB1Periph_CAN1, ENABLE);//使能 CAN1 時鐘

2設置 CAN 工作模式及波特率等。

這一步通過先設置 CAN_MCR 寄存器的 INRQ 位,讓 CAN 進入初始化模式,然后設置CAN_MCR 的其他相關控制位。再通過 CAN_BTR 設置波特率和工作模式(正常模式/環回模式)等信息。  最后設置 INRQ 為 0,退出初始化模式。

在庫函數中,提供了函數 CAN_Init()用來初始化 CAN 的工作模式以及波特率,CAN_Init()函數體中,在初始化之前,會設置 CAN_MCR 寄存器的 INRQ 為 讓其進入初始化模式,然后初始化 CAN_MCR 寄存器和 CRN_BTR 寄存器之后,會設置 CAN_MCR 寄存器的 INRQ 為 0讓其退出初始化模式。所以我們在調用這個函數的前后不需要再進行初始化模式設置。下面我們來看看 CAN_Init()函數的定義:

uint8_t CAN_Init(CAN_TypeDef* CANx, CAN_InitTypeDef* CAN_InitStruct);

第一個參數就是 CAN 標號,這里我們的芯片只有一個 CAN,所以就是 CAN1

第二個參數是 CAN 初始化結構體指針,結構體類型是 CAN_InitTypeDef,下面我們來看看這個結構體的定義:

typedef struct

{

uint16_t CAN_Prescaler;  

uint8_t CAN_Mode;     

uint8_t CAN_SJW;      

uint8_t CAN_BS1;         

uint8_t CAN_BS2;       

FunctionalState CAN_TTCM; 

FunctionalState CAN_ABOM;  

FunctionalState CAN_AWUM;  

FunctionalState CAN_NART; 

FunctionalState CAN_RFLM; 

FunctionalState CAN_TXFP;  

} CAN_InitTypeDef;

這個結構體看起來成員變量比較多,實際上參數可以分為兩類。前面 個參數是用來設置寄存器 CAN_BTR,用來設置模式以及波特率相關的參數,設置模式的參數是CAN_Mode, 我們實驗中用到回環模式 CAN_Mode_LoopBack 和常規模式 CAN_Mode_Normal,大家還可以選擇靜默模式以及靜默回環模式測試。其他設置波特率相關的參數 CAN_PrescalerCAN_SJW,CAN_BS1 和 CAN_BS2 分別用來設置波特率分頻器,重新同步跳躍寬度以及時間段 和時間段 占用的時間單元數。后面 個成員變量用來設置寄存器 CAN_MCR,也就是設置 CAN 通信相關的控制位。

初始化實例為:

CAN_InitStructure.CAN_TTCM=DISABLE;      //非時間觸發通信模式 

CAN_InitStructure.CAN_ABOM=DISABLE;      //軟件自動離線管理   

CAN_InitStructure.CAN_AWUM=DISABLE;          //睡眠模式通過軟件喚醒

CAN_InitStructure.CAN_NART=ENABLE;    //禁止報文自動傳送 

CAN_InitStructure.CAN_RFLM=DISABLE;      //報文不鎖定,新的覆蓋舊的 

CAN_InitStructure.CAN_TXFP=DISABLE;      //優先級由報文標識符決定 

CAN_InitStructure.CAN_Mode= CAN_Mode_LoopBack; //模式設置:  1,回環模式;

//設置波特率

CAN_InitStructure.CAN_SJW=CAN_SJW_1tq;//重新同步跳躍寬度為個時間單位 

CAN_InitStructure.CAN_BS1=CAN_BS1_8tq; //時間段 1 占用 8 個時間單位

CAN_InitStructure.CAN_BS2=CAN_BS2_7tq;//時間段 2 占用 7 個時間單位

CAN_InitStructure.CAN_Prescaler=5;   //分頻系數(Fdiv) 

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

3設置濾波器。

我們將使用濾波器組 0,并工作在 32 位標識符屏蔽位模式下。先設置 CAN_FMR的 FINIT 位,讓過濾器組工作在初始化模式下,然后設置濾波器組 的工作模式以及標識符 ID和屏蔽位。最后激活濾波器,并退出濾波器初始化模式。

在庫函數中,提供了函數 CAN_FilterInit ()用來初始化 CAN 的濾波器相關參數, CAN_Init()函數體中,在初始化之前,會設置 CAN_FMR 寄存器的 INRQ 為 INIT 讓其進入初始化模式,然后初始化 CAN 濾波器相關的寄存器之后,會設置 CAN_FMR 寄存器的 FINIT 為 讓其退出初始化模式。所以我們在調用這個函數的前后不需要再進行初始化模式設置。下面我們來看看CAN_FilterInit ()函數的定義:

void CAN_FilterInit(CAN_FilterInitTypeDef* CAN_FilterInitStruct);

這 個 函 數 只 有 一 個 入 口 參 數 就 是 CAN 濾 波 器 初 始 化 結 構 體 指 針 , 結 構 體 類 型 為CAN_FilterInitTypeDef,下面我們看看類型定義:

typedef struct

{

uint16_t CAN_FilterIdHigh; 

uint16_t CAN_FilterIdLow;   

uint16_t CAN_FilterMaskIdHigh; 

uint16_t CAN_FilterMaskIdLow; 

uint16_t CAN_FilterFIFOAssignment; 

uint8_t CAN_FilterNumber;     

uint8_t CAN_FilterMode;     

uint8_t CAN_FilterScale;        

FunctionalState CAN_FilterActivation; 

} CAN_FilterInitTypeDef;

結構體一共有 個成員變量,第 個至第 個是用來設置過濾器的 32 位 id 以及 32 位 mask id,分別通過 個 16 位來組合的

第 個成員變量 CAN_FilterFIFOAssignment 用來設置 FIFO 和過濾器的關聯關系,我們的實驗是關聯的過濾器 到 FIFO0,值為 CAN_Filter_FIFO0。

第 個成員變量 CAN_FilterNumber 用來設置初始化的過濾器組,取值范圍為 0~13。

第 個成員變量 FilterMode 用來設置過濾器組的模式,取值為標識符列表模式CAN_FilterMode_IdList 和標識符屏蔽位模式 CAN_FilterMode_IdMask

第 個成員變量 FilterScale 用來設置過濾器的位寬為 個 16 位 CAN_FilterScale_16bit 還是 32 位 CAN_FilterScale_32bit。

第 個成員變量 CAN_FilterActivation 就很明了了,用來激活該過濾器。

過濾器初始化參考實例代碼:

CAN_FilterInitStructure.CAN_FilterNumber=0;    //過濾器 0

CAN_FilterInitStructure.CAN_FilterMode=CAN_FilterMode_IdMask; 

CAN_FilterInitStructure.CAN_FilterScale=CAN_FilterScale_32bit; //32 位 

CAN_FilterInitStructure.CAN_FilterIdHigh=0x0000;////32 位 ID

CAN_FilterInitStructure.CAN_FilterIdLow=0x0000;

CAN_FilterInitStructure.CAN_FilterMaskIdHigh=0x0000;//32 位 MASK

CAN_FilterInitStructure.CAN_FilterMaskIdLow=0x0000;

CAN_FilterInitStructure.CAN_FilterFIFOAssignment=CAN_Filter_FIFO0;// FIFO0

CAN_FilterInitStructure.CAN_FilterActivation=ENABLE; //激活過濾器 0

CAN_FilterInit(&CAN_FilterInitStructure);//濾波器初始化

至此,CAN 就可以開始正常工作了。如果用到中斷,就還需要進行中斷相關的配置

4發送接受消息

在初始化 CAN 相關參數以及過濾器之后,接下來就是發送和接收消息了。庫函數中提供了發送和接受消息的函數。發送消息的函數是:

uint8_t CAN_Transmit(CAN_TypeDef* CANx, CanTxMsg* TxMessage)

這個函數比較好理解,第一個參數是 CAN 標號,我們使用 CAN1。第二個參數是相關消息結構體 CanTxMsg 指針類型,CanTxMsg 結構體的成員變量用來設置標準標識符,擴展標示符,消息類型和消息幀長度等信息。

接受消息的函數是:

void CAN_Receive(CAN_TypeDef* CANx, uint8_t FIFONumber, CanRxMsg* RxMessage);

前面兩個參數也比較好理解,CAN 標號和 FIFO 號。第二個參數 RxMessage 是用來存放接受到的消息信息。

結構體 CanRxMsg 和結構體 CanTxMsg 比較接近,分別用來定義發送消息和描述接受消息,

5CAN 狀態獲取

對于 CAN 發送消息的狀態,掛起消息數目等等之類的傳輸狀態信息,庫函數提供了一些列的函數,包括 CAN_TransmitStatus()函數,CAN_MessagePending()函數,CAN_GetFlagStatus()函數等等,大家可以根據需要來調用。




//CAN初始化
//tsjw:重新同步跳躍時間單元.范圍:1~3; CAN_SJW_1tq CAN_SJW_2tq CAN_SJW_3tq CAN_SJW_4tq
//tbs2:時間段2的時間單元.范圍:1~8;
//tbs1:時間段1的時間單元.范圍:1~16; CAN_BS1_1tq ~CAN_BS1_16tq
//brp :波特率分頻器.范圍:1~1024;(實際要加1,也就是1~1024) tq=(brp)*tpclk1
//注意以上參數任何一個都不能設為0,否則會亂.
//波特率=Fpclk1/((tsjw+tbs1+tbs2)*brp);
//mode:0,普通模式;1,回環模式;
//Fpclk1的時鐘在初始化的時候設置為36M,如果設置CAN_Normal_Init(1,8,7,5,1);
//則波特率為:36M/((1+8+7)*5)=450Kbps
//返回值:0,初始化OK;
// 其他,初始化失敗;
u8 CAN_Mode_Init(u8 tsjw,u8 tbs2,u8 tbs1,u16 brp,u8 mode)
{

GPIO_InitTypeDef GPIO_InitStructure;
CAN_InitTypeDef CAN_InitStructure;
CAN_FilterInitTypeDef CAN_FilterInitStructure;
#if CAN_RX0_INT_ENABLE
NVIC_InitTypeDef NVIC_InitStructure;
#endif

RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);//使能PORTA時鐘

RCC_APB1PeriphClockCmd(RCC_APB1Periph_CAN1, ENABLE);//使能CAN1時鐘

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //復用推挽
GPIO_Init(GPIOA, &GPIO_InitStructure); //初始化IO


//CAN單元設置
CAN_InitStructure.CAN_TTCM=DISABLE; //非時間觸發通信模式 //
CAN_InitStructure.CAN_ABOM=DISABLE; //軟件自動離線管理 //
CAN_InitStructure.CAN_AWUM=DISABLE; //睡眠模式通過軟件喚醒(清除CAN->MCR的SLEEP位)//
CAN_InitStructure.CAN_NART=ENABLE; //禁止報文自動傳送 //
CAN_InitStructure.CAN_RFLM=DISABLE; //報文不鎖定,新的覆蓋舊的 //
CAN_InitStructure.CAN_TXFP=DISABLE; //優先級由報文標識符決定 //
CAN_InitStructure.CAN_Mode= mode; //模式設置: mode:0,普通模式;1,回環模式; //
//設置波特率
CAN_InitStructure.CAN_SJW=tsjw; //重新同步跳躍寬度(Tsjw)為tsjw+1個時間單位 CAN_SJW_1tq CAN_SJW_2tq CAN_SJW_3tq CAN_SJW_4tq
CAN_InitStructure.CAN_BS1=tbs1; //Tbs1=tbs1+1個時間單位CAN_BS1_1tq ~CAN_BS1_16tq
CAN_InitStructure.CAN_BS2=tbs2;//Tbs2=tbs2+1個時間單位CAN_BS2_1tq ~ CAN_BS2_8tq
CAN_InitStructure.CAN_Prescaler=brp; //分頻系數(Fdiv)為brp+1 //
CAN_Init(CAN1, &CAN_InitStructure); // 初始化CAN1

CAN_FilterInitStructure.CAN_FilterNumber=0; //過濾器0
CAN_FilterInitStructure.CAN_FilterMode=CAN_FilterMode_IdMask;
CAN_FilterInitStructure.CAN_FilterScale=CAN_FilterScale_32bit; //32位
CAN_FilterInitStructure.CAN_FilterIdHigh=0x0000;////32位ID
CAN_FilterInitStructure.CAN_FilterIdLow=0x0000;
CAN_FilterInitStructure.CAN_FilterMaskIdHigh=0x0000;//32位MASK
CAN_FilterInitStructure.CAN_FilterMaskIdLow=0x0000;
CAN_FilterInitStructure.CAN_FilterFIFOAssignment=CAN_Filter_FIFO0;//過濾器0關聯到FIFO0
CAN_FilterInitStructure.CAN_FilterActivation=ENABLE; //激活過濾器0

CAN_FilterInit(&CAN_FilterInitStructure);//濾波器初始化

#if CAN_RX0_INT_ENABLE

CAN_ITConfig(CAN1,CAN_IT_FMP0,ENABLE);//FIFO0消息掛號中斷允許.

NVIC_InitStructure.NVIC_IRQChannel = USB_LP_CAN1_RX0_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; // 主優先級為1
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; // 次優先級為0
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
#endif
return 0;

}

#if CAN_RX0_INT_ENABLE //使能RX0中斷
//中斷服務函數
void USB_LP_CAN1_RX0_IRQHandler(void)
{
CanRxMsg RxMessage;
int i=0;
CAN_Receive(CAN1, 0, &RxMessage);
for(i=0;i<8;i++)
printf("rxbuf[%d]:%d\r\n",i,RxMessage.Data[i]);
}
#endif


//can發送一組數據(固定格式:ID為0X12,標準幀,數據幀)
//len:數據長度(最大為8)
//msg:數據指針,最大為8個字節.
//返回值:0,成功;
// 其他,失敗;
u8 Can_Send_Msg(u8* msg,u8 len)
{
u8 mbox;
u16 i=0;
CanTxMsg TxMessage;
TxMessage.StdId=0x12; // 標準標識符為0
TxMessage.ExtId=0x12; // 設置擴展標示符(29位)
TxMessage.IDE=0; // 使用擴展標識符
TxMessage.RTR=0; // 消息類型為數據幀,一幀8位
TxMessage.DLC=len; // 發送兩幀信息
for(i=0;i<len;i++)
TxMessage.Data[i]=msg[i]; // 第一幀信息
mbox= CAN_Transmit(CAN1, &TxMessage);
i=0;
while((CAN_TransmitStatus(CAN1, mbox)==CAN_TxStatus_Failed)&&(i<0XFFF))i++; //等待發送結束
if(i>=0XFFF)return 1;
return 0;

}


//can口接收數據查詢
//buf:數據緩存區;
//返回值:0,無數據被收到;
// 其他,接收的數據長度;
u8 Can_Receive_Msg(u8 *buf)
{
u32 i;
CanRxMsg RxMessage;
if( CAN_MessagePending(CAN1,CAN_FIFO0)==0)return 0; //沒有接收到數據,直接退出
CAN_Receive(CAN1, CAN_FIFO0, &RxMessage);//讀取數據
for(i=0;i<8;i++)
buf[i]=RxMessage.Data[i];
return RxMessage.DLC;
}



分享到:  QQ好友和群QQ好友和群 QQ空間QQ空間 騰訊微博騰訊微博 騰訊朋友騰訊朋友
收藏收藏1 分享淘帖 頂 踩
回復

使用道具 舉報

您需要登錄后才可以回帖 登錄 | 立即注冊

本版積分規則

手機版|小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術交流QQ群281945664

Powered by 單片機教程網

快速回復 返回頂部 返回列表
主站蜘蛛池模板: 亚洲欧美日韩在线一区二区 | 人人干人人干人人 | 夜夜爽99久久国产综合精品女不卡 | 中文字幕亚洲一区 | 在线一区二区国产 | 国产ts人妖系列高潮 | 日本免费黄色 | 欧美日韩国产一区二区 | 亚洲精品国产综合区久久久久久久 | 国产成人99久久亚洲综合精品 | 国产精品免费一区二区三区 | 亚洲精品一区二区 | 精品久久久久久18免费网站 | 亚洲精品久久久久久久久久久久久 | 中文字幕高清 | 亚洲精品一二区 | 中文字幕一区二区三区精彩视频 | 国产精品成人久久久久 | 国产成人精品亚洲日本在线观看 | 成人免费av在线 | 欧美xxxx性| 欧美a在线| 国产精品久久久久久久久久了 | 一区二区中文字幕 | 影音先锋男 | 精品一区二区久久久久久久网站 | 日韩精品一区二区三区在线播放 | 香蕉大人久久国产成人av | 粉嫩高清一区二区三区 | 欧美一级在线免费观看 | 国产三级一区二区 | 国产精品爱久久久久久久 | 日日骚网 | 91精品国产综合久久小仙女图片 | 黄色网址在线免费观看 | 日韩成人在线播放 | 日韩免费一区 | 一本一道久久a久久精品综合 | 国产精品久久久久aaaa九色 | 欧洲精品一区 | 午夜精品一区二区三区在线观看 |