① MCU:MCU通過APB總線訪問CAN外設(shè)。② CAN外設(shè):掛載在MCU的APB總線上,實現(xiàn)基本協(xié)議CAN2.0A、擴展協(xié)議CAN2.0B、接收濾波器、發(fā)送優(yōu)先級及對CAN FD的支持等,并留出外設(shè)訪問接口給MCU,以便MCU控制。③ CAN收發(fā)器:看其收發(fā)器框圖,因僅包含CANH、CANL總線,所以TXD發(fā)出的CANH、CANL與RXD讀出的CANH、CANL是連接在一起的,因此CAN收發(fā)器TXD發(fā)送出來的總線信號會立即被轉(zhuǎn)換從RXD輸出給CAN接口(LBME環(huán)回模式使用此特性)
MCU通過APB總線訪問CAN外設(shè),通過配置相關(guān)寄存器配置CAN的運行環(huán)境,通過寫B(tài)UF及相關(guān)配置位發(fā)送CAN幀;通過輪詢某些狀態(tài)位或者中斷,讀取收到的BUF或者CAN外設(shè)目前處于的狀態(tài),并依據(jù)部分狀態(tài)作出相應(yīng)的動作;CAN收發(fā)器將CAN外設(shè)的CAN_TX高低電平信號轉(zhuǎn)換為CANH、CANL總線信號,并將接收到的CANH、CANL總線信號轉(zhuǎn)換為CAN外設(shè)的CAN_RX高低電平信號,該信號輸送給CAN外設(shè),CAN外設(shè)根據(jù)CAN接收濾波器的設(shè)置判斷是否接收該數(shù)據(jù)幀等等。
1、查看原理圖,看使用哪一個CAN接口。STB使用的引腳
#define CAN1_TX (GPIO_PC15) //pin 75
#define CAN1_RX (GPIO_PC14) //pin 74
#define CAN1_STB (GPIO_PD5) // pin9
2、進行初始化操作
CAN_InitHardwr();
定義兩個結(jié)構(gòu)體變量,CAN_Config和CAN_BaudrateConfig
- 初始化硬件接口
GPIO_SetFunc(CAN1_TX, GPIO_FUNC_1);//設(shè)置CAN1引腳復(fù)用功能 GPIO_SetFunc(CAN1_RX, GPIO_FUNC_1); GPIO_SetDir(CAN1_STB, GPIO_OUTPUT);//設(shè)置CAN1收發(fā)器控制為IO控制 //GPIO_FUNC_1 參考數(shù)據(jù)手冊中“信號多路復(fù)用和引腳分配”,使用function 1功能
- 使能CAN收發(fā)器
CAN1_TRASCVER_NML;//使能CAN收發(fā)器 //#define CAN1_TRASCVER_NML do{GPIO_ResetPinBits(CAN1_STB);}while(0)
- 設(shè)置波特率和采樣點進行配置
/*
設(shè)置波特率為500K,采樣點為81.25%.
tSeg1 = (S_SEG_1 + 2); tSeg2 = (S_SEG_2 + 1).
BandRate = (48M / (S_PRESC + 1) / ((S_SEG_1 + 2) + (S_SEG_2 + 1)))
SamplePoint = (tSeg1 / (tSeg1 + tSeg2)).
在已經(jīng)知道波特率與采樣點的情況下,經(jīng)過計算后:tSeg1 = 13,tSeg2 = 3.
*/
canBandrateConfig.S_PRESC = 5;//分頻后時鐘為8M.
canBandrateConfig.S_SEG_1 = 11;
canBandrateConfig.S_SEG_2 = 2;
canBandrateConfig.S_SJW = 2;//滿足S_SJW <= tSeg2即可.
- 過濾器設(shè)置:選擇哪一個過濾器、指定過濾模式、過濾的ID類型
16個過濾器中,可隨意選擇使用哪個,并制定其過濾模式,制定其過濾ID的類型. 如果一個過濾器只需要接收一個ID,直接可將其設(shè)置CODE模式,然后根據(jù)ID類型設(shè)置過濾類型. 如果一個過濾器需要接收多個ID,將其設(shè)置為MASK模式,并根據(jù)這幾個ID的實際類型設(shè)置過濾ID類型,如果既有STD又有EXT,則應(yīng)選擇FILTER_IDE_STD_EXT_BOTH. 此處加宏是為了更清楚的說明各種設(shè)置是否有效,在實際應(yīng)用中,可將各種組合放在一起使用. #if (RECV_FRM_KIND_SEL == ONLY_RECV_STD_FRM) CAN_SetFilterParam( 0, 1, CAN_FILTER_CODE_MODE, FILTER_IDE_STD_ONLY, CAN1_RECV_DATA_ID1);//使用CODE模式只接收STD幀 CAN_SetFilterParam( 1, 1, CAN_FILTER_CODE_MODE, FILTER_IDE_STD_ONLY, CAN1_RECV_DATA_ID2);//使用CODE模式只接收STD幀 #endif #if (RECV_FRM_KIND_SEL == ONLY_RECV_EXT_FRM) CAN_SetFilterParam( 0, 1, CAN_FILTER_CODE_MODE, FILTER_IDE_EXT_ONLY, CAN1_RECV_DATA_ID11);//使用CODE模式只接收EXT幀 CAN_SetFilterParam( 1, 1, CAN_FILTER_CODE_MODE, FILTER_IDE_EXT_ONLY, CAN1_RECV_DATA_ID12);//使用CODE模式只接收EXT幀 #endif #if (RECV_FRM_KIND_SEL == RECV_STD_EXT_BOTH_FRM) CAN_SetFilterParam( 0, 1, CAN_FILTER_MASK_MODE, FILTER_IDE_STD_EXT_BOTH, (CAN1_RECV_DATA_ID1 & CAN1_RECV_DATA_ID11));//使用MASK模式接收兩種幀 CAN_SetFilterParam( 1, 1, CAN_FILTER_MASK_MODE, FILTER_IDE_STD_EXT_BOTH, (CAN1_RECV_DATA_ID2 & CAN1_RECV_DATA_ID12));//使用MASK模式接收兩種幀 #endif
- CAN_SetFilterParam( 0, 1, CAN_FILTER_CODE_MODE, FILTER_IDE_STD_ONLY, CAN1_RECV_DATA_ID1);//使用CODE模式只接收STD幀
* @prototype CAN_SetFilterParam(uint8_t filterNum, uint8_t filterEn, CAN_FilterMode_TypeDef filterMode, CAN_FilterMask_TypeDef filterMask, uint32_t ID)
*
* @param[in] filterNum:過濾器編碼,0到15可用.
* @param[in] filterEn:過濾器使能狀態(tài),1使能,0禁能
* @param[in] filterMode:CAN_FilterMode_TypeDef已定義.
* @param[in] filterMask:參考CAN_FilterMask_TypeDef.
* @param[in] ID
* @return void
參數(shù)說明:0:選用的過濾器編碼
1:1標識使能,0為禁止
CAN_FILTER_CODE_MODE:分code模式和mask模式,code只能接收一個ID,mask可以接收多個ID
FILTER_IDE_STD_ONLY:分標準幀、擴展幀、混合幀
ID:需要過濾的ID,表示這個ID可以通過,單片機可以接收到數(shù)據(jù)。
- 設(shè)置can配置
canConfig.interruptEnable = TRUE;//使能中斷 canConfig.TSSS = TRUE;//使用次發(fā)送緩沖區(qū)發(fā)送 canConfig.canMode = CAN_MODE_NORMAL; canConfig.autoReset = TRUE;//CAN BUSOFF后,自動恢復(fù) canConfig.filterList = g_canFilterTab;//賦值過濾器設(shè)置list
- 設(shè)置回調(diào)函數(shù)CAN_SetEventCallBack(CAN1, CAN1_IRQnCallBack);
/** * @prototype CAN1_IRQnCallBack(uint32_t event, uint32_t wparam, uint32_t lparam) * * @param[in] ... * @return ... * * @brief CAN1 module interrupt handler. * CAN1中斷處理函數(shù). */ int32_t CAN1_IRQnCallBack(uint32_t event, uint32_t wparam, uint32_t lparam) { if (event & CAN_EVENT_RECVMSG) { if (CAN_IsMsgInReceiveBuf((CAN_Type*)lparam)) { CAN_MessageRead((CAN_Type*)lparam, &g_recvCANMsgInfo); g_recvedCANDataRdy = TRUE; } } return 1; }
- 調(diào)用庫函數(shù)CAN_Initialize()。
CAN_Initialize(CAN1, &canConfig, &canBandrateConfig);//程序引用
CAN_Initialize(CAN_Type *CANx, CAN_Config *config, const CAN_BaudrateConfig *baudrate)//函數(shù)原型
參數(shù)說明:
- @param[in] CANx: CAN type pointer
- @param[in] config: CAN config
- @param[in] baudrate: CAN baud rate
- @return 0: no error, 1: Initialize error
void CAN_InitHardwr(void)
{
CAN_Config canConfig = {0};
CAN_BaudrateConfig canBandrateConfig = {0};
GPIO_SetFunc(CAN1_TX, GPIO_FUNC_1);//設(shè)置CAN1引腳復(fù)用功能
GPIO_SetFunc(CAN1_RX, GPIO_FUNC_1);
GPIO_SetDir(CAN1_STB, GPIO_OUTPUT);//設(shè)置CAN1收發(fā)器控制為IO控制
CAN1_TRASCVER_NML;//使能CAN收發(fā)器
/*
設(shè)置波特率為500K,采樣點為81.25%.
tSeg1 = (S_SEG_1 + 2); tSeg2 = (S_SEG_2 + 1).
BandRate = (48M / (S_PRESC + 1) / ((S_SEG_1 + 2) + (S_SEG_2 + 1)))
SamplePoint = (tSeg1 / (tSeg1 + tSeg2)).
在已經(jīng)知道波特率與采樣點的情況下,經(jīng)過計算后:tSeg1 = 13,tSeg2 = 3.
*/
canBandrateConfig.S_PRESC = 5;//分頻后時鐘為8M.
canBandrateConfig.S_SEG_1 = 11;
canBandrateConfig.S_SEG_2 = 2;
canBandrateConfig.S_SJW = 2;//滿足S_SJW <= tSeg2即可.
/*
16個過濾器中,可隨意選擇使用哪個,并制定其過濾模式,制定其過濾ID的類型.
如果一個過濾器只需要接收一個ID,直接可將其設(shè)置CODE模式,然后根據(jù)ID類型設(shè)置過濾類型.
如果一個過濾器需要接收多個ID,將其設(shè)置為MASK模式,并根據(jù)這幾個ID的實際類型設(shè)置過濾ID類型,如果既有STD又有EXT,則應(yīng)選擇FILTER_IDE_STD_EXT_BOTH.
此處加宏是為了更清楚的說明各種設(shè)置是否有效,在實際應(yīng)用中,可將各種組合放在一起使用.
*/
#if (RECV_FRM_KIND_SEL == ONLY_RECV_STD_FRM)
CAN_SetFilterParam( 0, 1, CAN_FILTER_CODE_MODE, FILTER_IDE_STD_ONLY, CAN1_RECV_DATA_ID1);//使用CODE模式只接收STD幀
CAN_SetFilterParam( 1, 1, CAN_FILTER_CODE_MODE, FILTER_IDE_STD_ONLY, CAN1_RECV_DATA_ID2);//使用CODE模式只接收STD幀
#endif
#if (RECV_FRM_KIND_SEL == ONLY_RECV_EXT_FRM)
CAN_SetFilterParam( 0, 1, CAN_FILTER_CODE_MODE, FILTER_IDE_EXT_ONLY, CAN1_RECV_DATA_ID11);//使用CODE模式只接收EXT幀
CAN_SetFilterParam( 1, 1, CAN_FILTER_CODE_MODE, FILTER_IDE_EXT_ONLY, CAN1_RECV_DATA_ID12);//使用CODE模式只接收EXT幀
#endif
#if (RECV_FRM_KIND_SEL == RECV_STD_EXT_BOTH_FRM)
CAN_SetFilterParam( 0, 1, CAN_FILTER_MASK_MODE, FILTER_IDE_STD_EXT_BOTH, (CAN1_RECV_DATA_ID1 & CAN1_RECV_DATA_ID11));//使用MASK模式接收兩種幀
CAN_SetFilterParam( 1, 1, CAN_FILTER_MASK_MODE, FILTER_IDE_STD_EXT_BOTH, (CAN1_RECV_DATA_ID2 & CAN1_RECV_DATA_ID12));//使用MASK模式接收兩種幀
#endif
canConfig.interruptEnable = TRUE;//使能中斷
canConfig.TSSS = TRUE;//使用次發(fā)送緩沖區(qū)發(fā)送
canConfig.canMode = CAN_MODE_NORMAL;
canConfig.autoReset = TRUE;//CAN BUSOFF后,自動恢復(fù)
canConfig.filterList = g_canFilterTab;//賦值過濾器設(shè)置list
CAN_SetEventCallBack(CAN1, CAN1_IRQnCallBack);
CAN_Initialize(CAN1, &canConfig, &canBandrateConfig);
}
-
濾波器
+關(guān)注
關(guān)注
160文章
7703瀏覽量
177485 -
AMBA
+關(guān)注
關(guān)注
0文章
68瀏覽量
14940 -
CAN收發(fā)器
+關(guān)注
關(guān)注
2文章
162瀏覽量
25589 -
串口中斷
+關(guān)注
關(guān)注
0文章
64瀏覽量
13847 -
MCU控制器
+關(guān)注
關(guān)注
0文章
27瀏覽量
6867
發(fā)布評論請先 登錄
相關(guān)推薦
評論