1、FlexCAN 簡(jiǎn)介
FlexCAN 控制器局域網(wǎng)模塊是符合 ISO 11898-1 標(biāo)準(zhǔn)和 CAN 2.0B 規(guī)范的通信控制器,支持 CAN 總線協(xié)議。FlexCAN 模塊框圖如 圖1 所示。FlexCAN 模塊包括 CAN 收發(fā)器(CAN Transceiver)、協(xié)議引擎(Protocol Engine)、控制接口(Controller Host Interface)、總線接口單元(Bus Interface Unit),以及多個(gè)支持獨(dú)立收發(fā)功能的信息緩沖區(qū)(Message Buffer)。其中 CAN 收發(fā)器負(fù)責(zé)將收發(fā)引腳的 TTL 信號(hào)轉(zhuǎn)換為 CAN 總線的電平信號(hào),協(xié)議引擎負(fù)責(zé)處理對(duì)信息緩沖區(qū)的讀寫(xiě)請(qǐng)求,控制接口負(fù)責(zé)傳輸幀的發(fā)送仲裁以及接收匹配,總線接口單元處理 FlexCAN 和內(nèi)部總線的交互,信息緩沖區(qū)用于存儲(chǔ) FlexCAN 的傳輸幀。
圖 1 MM32F0140 FlexCAN 模塊框圖
MM32F0140 的 FlexCAN 模塊支持標(biāo)準(zhǔn)幀和擴(kuò)展幀兩種幀格式,支持?jǐn)?shù)據(jù)幀和遠(yuǎn)程請(qǐng)求幀兩種幀類(lèi)型,其中數(shù)據(jù)幀的最大有效數(shù)據(jù)長(zhǎng)度可達(dá)8比特。FlexCAN 模塊支持最高可達(dá) 1Mps 的可編程比特率,支持對(duì)前 16 個(gè)信息緩沖區(qū)的中斷,支持局部和全局的接收幀過(guò)濾機(jī)制,支持可選擇的 FIFO 接收功能。
FlexCAN 模塊支持三種工作模式:回環(huán)模式、只聽(tīng)模式和正常工作模式。因?yàn)樵诨丨h(huán)模式下,F(xiàn)lexCAN 的傳輸幀并不會(huì)通過(guò)其收發(fā)引腳發(fā)送到 CAN 總線,所以通常用于測(cè)試單塊芯片的 FlexCAN 模塊是否工作正常。只聽(tīng)模式下,F(xiàn)lexCAN 模塊將只接收總線上的幀,而不能發(fā)送幀,并且也無(wú)法發(fā)送接收應(yīng)答。正常工作模式下,F(xiàn)lexCAN 模塊既可發(fā)送幀,也可接收幀。
2、FlexCAN 幀格式
FlexCAN 幀傳輸過(guò)程
圖 2 CAN 幀發(fā)送流程
圖2 是 CAN 幀的發(fā)送流程,首先是幀起始位 SOF,SOF 值規(guī)定為 1,標(biāo)識(shí)此幀的開(kāi)始。在 CAN 總線協(xié)議中約定,值 0 為顯性位,值 1 為隱性位。FlexCAN 采取多主機(jī)、基于優(yōu)先級(jí)的總線傳輸方式,總線幀的收發(fā)順序在 Arbitration field 仲裁段確定。仲裁成功的節(jié)點(diǎn)會(huì)繼續(xù)發(fā)送幀,仲裁失敗的節(jié)點(diǎn)會(huì)轉(zhuǎn)為接收狀態(tài)。如果不設(shè)置使用幀的優(yōu)先級(jí)進(jìn)行仲裁,則使用幀的 ID 號(hào)進(jìn)行仲裁比較,越小優(yōu)先級(jí)越高。結(jié)合 圖2 CAN 幀發(fā)送流程 和 圖3 CAN 標(biāo)準(zhǔn)數(shù)據(jù)幀格式可知,Arbitration field 仲裁段存放 CAN 報(bào)文的 ID 號(hào)以及 RTR 標(biāo)識(shí),RTR 用于表示幀類(lèi)型,在下文講述 FlexCAN 使用信息緩沖區(qū)發(fā)送報(bào)文時(shí),會(huì)進(jìn)一步解釋其含義。Control filed 控制段在 MM32F0140 的 FlexCAN 中,主要涉及兩個(gè)部分,IDE 字段和 DLE 字段。IDE 字段用于標(biāo)識(shí)幀格式,為數(shù)據(jù)幀還是遠(yuǎn)程幀。DLC 字段用于標(biāo)識(shí)此幀的有效字節(jié)數(shù),DLC 字段值將影響后續(xù)的 Data field 字段長(zhǎng)度。FDF 字段表示此幀是否為 CAN FD 幀,在MM32F0140 的 FlexCAN 模塊中暫時(shí)未使用到。Data field 有效傳輸數(shù)據(jù)負(fù)載段,如果此幀為遠(yuǎn)程幀,將不攜帶任何數(shù)據(jù),所以 DLC 字段對(duì)應(yīng)為 0;如果此幀為數(shù)據(jù)幀,此段長(zhǎng)度由 DLC 字段控制。CRC field 循環(huán)冗余碼段,用于在發(fā)送和接收流程中檢查此幀是否出現(xiàn)比特錯(cuò)誤。CRC 后,為 ACK field 檢測(cè)段,發(fā)送方會(huì)發(fā)送隱性位 1,然后在此段期間回讀總線上信號(hào)。如果讀到為顯性位 0,則說(shuō)明有其他 CAN 接收器接收到此幀,發(fā)送方發(fā)送成功。最后是 EOF 結(jié)束位,標(biāo)識(shí)發(fā)送結(jié)束。
圖 3 CAN 標(biāo)準(zhǔn)數(shù)據(jù)幀格式
以下是 MM32F0140 FlexCAN 在上述 CAN 發(fā)送流程要求下,使用信息緩沖區(qū)寄存器進(jìn)行 CAN 幀的收發(fā)的詳細(xì)操作流程。信息緩沖區(qū)寄存器的結(jié)構(gòu)如圖 4 所示。
圖 4 FlexCAN 信息緩沖區(qū)結(jié)構(gòu)圖
FlexCAN 發(fā)送幀
FlexCAN 發(fā)送幀時(shí),首先將幀相關(guān)信息寫(xiě)入預(yù)計(jì)使用的信息緩沖區(qū)寄存器中。如果此幀的 ID 號(hào)可用 11 個(gè)比特位進(jìn)行表示,則將此幀的 ID 號(hào)填入 ID 段,并將 IDE 位置 0,標(biāo)識(shí)為標(biāo)準(zhǔn)幀。如果此幀的 ID 號(hào)超過(guò) 11 位,則將剩余低位部分填入 ID(Extended) 段,并將 IDE 位置 1,標(biāo)識(shí)為擴(kuò)展幀。FlexCAN 的幀 ID 長(zhǎng)度不能超過(guò) 29 位。
然后根據(jù)此幀的幀類(lèi)型,如果是攜帶數(shù)據(jù)的數(shù)據(jù)幀,則將 SRR 替代遠(yuǎn)程請(qǐng)求位和 RTR 遠(yuǎn)程請(qǐng)求位都設(shè)置為 0,并將對(duì)應(yīng)需要發(fā)送的數(shù)據(jù)寫(xiě)入 DataByte 區(qū),將數(shù)據(jù)長(zhǎng)度寫(xiě)入 DLC 字段;如果是不攜帶數(shù)據(jù)的遠(yuǎn)程請(qǐng)求幀,則將上述的 SRR 位和 RTR 位都設(shè)置為 1。
如果 MCR[LPRIOEN] 位被設(shè)置為 1,則在發(fā)送前還需要將此幀的優(yōu)先級(jí)寫(xiě)入 PRIO 位,PRIO 位值越小,優(yōu)先級(jí)越高。
當(dāng)上述各字段都填充完畢后,將 CODE 值 12 填入 CODE 區(qū),此 CODE 值表示將要發(fā)送此幀,發(fā)送完畢后 CODE 值變?yōu)?8,表示發(fā)送完畢?;刈x TIME STAMP 段,可以得到發(fā)送成功時(shí)的時(shí)間戳。
FlexCAN 接收幀
FlexCAN 接收幀前,需要設(shè)置此接收信息緩沖區(qū)的 ID 號(hào)、幀格式 IDE 和幀類(lèi)型 SRR 和 RTR,參考上述發(fā)送過(guò)程的設(shè)置。然后將 CODE 區(qū)值設(shè)置為值 4,表示等待接收。如果需要幀過(guò)濾,還需要設(shè)置局部幀過(guò)濾器 RXIMR 和全局幀過(guò)濾器 RXMGMASK、RX14MASK和RX15MASK。當(dāng) CAN 總線上有其他 FlexCAN 模塊發(fā)送的幀時(shí),信息緩沖區(qū)會(huì)將總線上的幀 ID 與自己的 ID 段以及掩碼值進(jìn)行匹配,接收幀,此時(shí) TIME STAMP 段的值為接收時(shí)的時(shí)間戳。
在傳輸中會(huì)常使用到的 CODE 值如下表 1 所示。
表格 1 信息緩沖區(qū) CODE 值含義
FlexCAN 功能測(cè)試流程
首先使用 FlexCAN 的回環(huán)模式測(cè)試開(kāi)發(fā)板上的 FlexCAN 是否工作正常?;丨h(huán)測(cè)試成功以后可以進(jìn)行 FlexCAN 正常工作模式的測(cè)試。如果使用的是兩塊開(kāi)發(fā)板或使用 CAN 分析儀進(jìn)行測(cè)試,需要注意總線兩端必須連接 120Ω 終端電阻。在配置 FlexCAN 過(guò)程中,要保證收發(fā)方的波特率都配置成相同值。測(cè)試 FlexCAN 正常工作模式下收發(fā)的實(shí)驗(yàn)過(guò)程中,要確保至少有一個(gè)接收節(jié)點(diǎn)是正常工作模式,而非只聽(tīng)模式。
3、FlexCAN 配置
配置時(shí)鐘
首先需要使能 FlexCAN 時(shí)鐘,根據(jù)所使用的外設(shè)對(duì) RCC 的 RCC_APB1ENR 寄存器進(jìn)行賦值,將對(duì)應(yīng)外設(shè)位置 1 即可使能時(shí)鐘,詳細(xì)外設(shè)如圖 5 所示。
圖 5 MM32F0140 APB1總線外設(shè)
使能并初始化模塊
使能 FlexCAN 模塊,通過(guò)配置 FLEXCAN_MCR[MDIS] 為 0,可以使能 FlexCAN 模塊。使能后,F(xiàn)lexCAN 模塊會(huì)自動(dòng)進(jìn)入凍結(jié)模式。在凍結(jié)模式下,設(shè)置 FLEXCAN_MCR_SOFTRST 為 1,軟件重置 FlexCAN 模塊寄存器。然后將所有的信息緩沖區(qū)的獨(dú)立掩碼寄存器和全局掩碼寄存器的掩碼值都設(shè)置為 1,表示接收信息緩沖區(qū)將只接收 ID 號(hào)和緩沖區(qū)提前配置的 ID 號(hào)完全相同的報(bào)文,同時(shí)將每個(gè)信息緩沖區(qū)寄存器也全部清 0。
配置工作模式
如果 FlexCAN 需要進(jìn)入正常工作模式,僅需在使能 FlexCAN、初始化信息緩沖區(qū)后退出凍結(jié)模式即可進(jìn)入,即將 FLEXCAN_MCR[FRZ] 設(shè)置為 0。因?yàn)橥顺鰞鼋Y(jié)模式需要一定時(shí)間,通過(guò)輪詢(xún) FLEXCAN_MCR[FRZACK] 是否等于 1 判斷是否退出成功。如果 FlexCAN 需要配置為只讀模式,則需要將 FLEXCAN_CTRL1[LOM] 置為 1;如果 FlexCAN 需要配置為回環(huán)模式,則需要將 FLEXCAN_CTRL1[LPB] 設(shè)置為 1。值得注意的是,當(dāng)配置為回環(huán)模式時(shí),F(xiàn)lexCAN 的 FLEXCAN_MCR[SRXDIS] 不能被設(shè)置為 1,否則 FlexCAN 將無(wú)法收到回環(huán)報(bào)文。
配置波特率
首先通過(guò)設(shè)置 FLEXCAN_CTRL1[CLKSRC] 指定 FlexCAN 協(xié)議引擎的時(shí)鐘源,設(shè)置為 0 時(shí)使用振蕩器時(shí)鐘,設(shè)置為 1 時(shí)使用外設(shè)時(shí)鐘??稍斠?jiàn)圖 6 FlexCAN 模塊協(xié)議引擎時(shí)鐘框圖。
圖 6 FlexCAN模塊協(xié)議引擎時(shí)鐘框圖
對(duì) FlexCAN 引擎時(shí)鐘頻率進(jìn)行可編程分頻后得到 FlexCAN 串行時(shí)鐘頻率,F(xiàn)lexCAN 串行時(shí)鐘頻率的倒數(shù)被稱(chēng)為時(shí)間份額,用于衡量 FlexCAN 傳輸過(guò)程中各個(gè)階段所需的時(shí)間長(zhǎng)度,詳見(jiàn)圖 7 1 bit time 下 FlexCAN 傳輸段。
圖 7 1 bit time下FlexCAN傳輸段
SYNC_SEG 表示使用 1 個(gè)時(shí)間份額用于同步;Time Segment 1 段包括 PROPSEG 段和 PSEG1 段,前者用于補(bǔ)償實(shí)際網(wǎng)絡(luò)傳輸延時(shí),后者和 PSEG2 都將用于補(bǔ)償在 FlexCAN 傳輸過(guò)程中潛在的邊緣相位誤差。上述三項(xiàng)可以分別通過(guò) FLEXCAN_CTRL1[PROPSEG]、FLEXCAN_CTRL1[PSEG1] 和 FLEXCAN_CTRL1[PSEG2] 進(jìn)行設(shè)置。下圖 8 是 Bosch CAN 2.0B 標(biāo)準(zhǔn)中對(duì)于 PSEG1 和PSEG2 的設(shè)置表。
圖 8 Bosch CAN 2.0B 標(biāo)準(zhǔn)中 PSEG1 和 PSEG2 的建議設(shè)置
在上述定義下,假定此時(shí)引擎時(shí)鐘源的時(shí)鐘頻率為 ClockFreqHz,PROPSEG 中指定值為 PropSegLen,PSEG1 和PSEG2 中指定值分別為 PhaSegLen1 和 PhaSegLen2,所需波特率為 BaudRate 時(shí),我們可以得到預(yù)期的分頻數(shù)值 Div 為:
得到的 Div 值通過(guò)配置 FLEXCAN_CTRL1[PreDiv] 實(shí)現(xiàn)。這里尤其要注意各項(xiàng)和 ClockFreqHz 之間是否滿(mǎn)足整除關(guān)系。
配置發(fā)送幀
首先需要將發(fā)送幀的內(nèi)容填入等待發(fā)送的 i 號(hào)信息緩沖區(qū)的寄存器 FLEXCAN_MB[i] 的 CS、ID、WORD0 和WORD1 寄存器。然后將發(fā)送 CODE 值 (12) 填入 FLEXCAN_MB[i].CS[CODE] 中,即可發(fā)送。此時(shí),如果將 FLEXCAN_ IMASK1 中對(duì)應(yīng)中斷位設(shè)置為 1,則發(fā)送成功后將會(huì)喚起中斷。
配置接收幀格式
接收匹配需要設(shè)置對(duì)應(yīng)的 i 號(hào)信息緩沖區(qū) FLEXCAN_MB[i].CS[CODE] 值為 4,表示當(dāng)前信息緩沖區(qū)接收為空,可以接收信息并安全存儲(chǔ),配置 FLEXCAN_MB[i].ID 為預(yù)期接收的幀 ID 號(hào)。設(shè)置 FLEXCAN_MB[i].CS[IDE] 配置接收擴(kuò)展幀或標(biāo)準(zhǔn)幀,接收擴(kuò)展幀則配置為 1,接收標(biāo)準(zhǔn)幀則配置為 0。設(shè)置 FLEXCAN_MB[i].CS[RTR] 配置接收遠(yuǎn)程幀或數(shù)據(jù)幀,接收遠(yuǎn)程幀則此位配置為 1,否則配置為 0。
如果需要對(duì)幀進(jìn)行過(guò)濾接收,則需額外考慮配置全局幀過(guò)濾器或局部幀過(guò)濾器。配置 FLEXCAN_MCR[IRMQ] 為 1 則采用局部幀過(guò)濾,配置為 0 則采用全局幀過(guò)濾。當(dāng)使用局部幀過(guò)濾方法時(shí),掩碼需要通過(guò) FLEXCAN_RXIMRN[i] 寄存器配置,全局則通過(guò) FLEXCAN_RXMGMASK、FLEXCAN_RX14MASK 和FLEXCAN_RX15MASK 寄存器進(jìn)行配置。
4、FlexCAN 實(shí)驗(yàn)
在 SDK 中已有支持的 pokt-f0140 開(kāi)發(fā)板上,在 driver example 下的 flexcan_loopback 樣例中,使用 FlexCAN 模塊進(jìn)行回環(huán)測(cè)試,演示 FlexCAN 的初始化設(shè)置、接收和發(fā)送設(shè)置以及中斷處理。
初始化外設(shè)時(shí)鐘
FlexCAN 模塊在 APB1 總線上,因此對(duì) RCC_ APB1ENR 寄存器的 FLEXCAN 對(duì)應(yīng)位設(shè)置為 1。
RCC_EnableAPB1Periphs(RCC_APB1_PERIPH_FLEXCAN, true);
初始化FlexCAN
使用外設(shè)時(shí)鐘作為 FlexCAN 的時(shí)鐘源,則 FlexCAN 的時(shí)鐘頻率為 pokt-f0140 上 APB1 總線時(shí)鐘頻率,為48MHz。此時(shí)將傳輸階段的時(shí)鐘配置 PhaseSegLen1,PhaseSegLen2,PropSegLen 分別配置為 2, 1, 1;將波特率APP_FLEXCAN_XFER_BAUDRATE 設(shè)置為 1MHz。則根據(jù)先前所述的波特率計(jì)算公式,可以滿(mǎn)足整除關(guān)系。在實(shí)際調(diào)整波特率,需要考慮傳輸段的時(shí)鐘設(shè)置是否滿(mǎn)足整除關(guān)系。
/* Setup the flexcan module. */ void app_flexcan_init(void) { /* Set the baudrate and bit time. */ FLEXCAN_TimConf_Type flexcan_tim_conf; flexcan_tim_conf.EnableExtendedTime = false;/* No need to use extended time setting register. */ flexcan_tim_conf.PhaSegLen1 = 2u; flexcan_tim_conf.PhaSegLen2 = 1u; flexcan_tim_conf.PropSegLen = 1u; /* Setup flexcan. */ FLEXCAN_Init_Type flexcan_init; flexcan_init.MaxXferNum = APP_FLEXCAN_XFER_MaxNum; /* The max mb number to be used. */ flexcan_init.ClockSource = FLEXCAN_ClockSource_Periph; /* Use peripheral clock. */ flexcan_init.BaudRate = APP_FLEXCAN_XFER_BAUDRATE; /* Set baudrate. */ flexcan_init.ClockFreqHz = CLOCK_APB1_FREQ; /* Set clock frequency. */ flexcan_init.SelfWakeUp = FLEXCAN_SelfWakeUp_BypassFilter; /* Use unfiltered signal to wake up flexcan. */ flexcan_init.WorkMode = FLEXCAN_WorkMode_LoopBack; /* Normal workmode, can receive and transport. */ flexcan_init.Mask = FLEXCAN_Mask_Global; /* Use global mask for filtering. */ flexcan_init.EnableSelfReception = true; /* Must receive mb frame sent by self. */ flexcan_init.EnableTimerSync = true; /* Every tx or rx done, refresh the timer to start from zero. */ flexcan_init.TimConf = flexcan_tim_conf; /* Set timing sychronization. */ /* Enable FlexCAN. */ FLEXCAN_Init(BOARD_FLEXCAN_PORT, flexcan_init); }
配置接收信息緩沖區(qū)
配置接收 MB 的接收幀類(lèi)型為標(biāo)準(zhǔn)數(shù)據(jù)幀,ID 為 APP_FLEXCAN_XFER_ID。通過(guò)配置接收 MB 的 CODE 區(qū),將其配置為接收為空的狀態(tài)。
/* Set rx mb. */ FLEXCAN_RxMbConf_Type flexcan_mb_conf; flexcan_mb_conf.Id = APP_FLEXCAN_XFER_ID; /* Id for receiving. */ flexcan_mb_conf.MbType = FLEXCAN_MbType_Data; /* Only receive standard data frame. */ flexcan_mb_conf.MbFormat = FLEXCAN_MbFormat_Standard; FLEXCAN_SetRxMb(BOARD_FLEXCAN_PORT, BOARD_FLEXCAN_RX_MB_CH, flexcan_mb_conf); /* Set for receiving frames. */ FLEXCAN_SetMbCode(BOARD_FLEXCAN_PORT, BOARD_FLEXCAN_RX_MB_CH, FLEXCAN_MbCode_RxEmpty);
配置發(fā)送信息緩沖區(qū)
將發(fā)送 MB 的寄存器清空。通過(guò)設(shè)置該 MB 的 CODE 區(qū),將該 MB 設(shè)置為發(fā)送空閑。
/* Reset tx mb. */ FLEXCAN_ResetMb(BOARD_FLEXCAN_PORT, BOARD_FLEXCAN_TX_MB_CH); FLEXCAN_SetMbCode(BOARD_FLEXCAN_PORT, BOARD_FLEXCAN_TX_MB_CH, FLEXCAN_MbCode_TxInactive);
配置接收中斷
使能 FlexCAN 的接收中斷,設(shè)置 NVIC。
/* Enable intterupts for rx mb. */ FLEXCAN_EnableMbInterrupts(BOARD_FLEXCAN_PORT, BOARD_FLEXCAN_RX_MB_INT, true); NVIC_EnableIRQ(BOARD_FLEXCAN_IRQn);
中斷處理函數(shù)
中斷處理函數(shù)檢查接收中斷,設(shè)置接收全局標(biāo)志位為真。
/* Interrupt request handler. */ void BOARD_FLEXCAN_IRQHandler(void) { /* Check mb status. If received. */ if (0u!= (FLEXCAN_GetMbStatus(BOARD_FLEXCAN_PORT) BOARD_FLEXCAN_RX_MB_STATUS) ) { /* Clear flexcan mb interrupt flag. */ FLEXCAN_ClearMbStatus(BOARD_FLEXCAN_PORT, BOARD_FLEXCAN_RX_MB_STATUS); /* Update the flag. */ app_flexcan_rx_flag = true; } }
發(fā)送數(shù)據(jù)
設(shè)置標(biāo)準(zhǔn)數(shù)據(jù)幀的 ID 號(hào),幀類(lèi)型和幀格式以及優(yōu)先級(jí);然后填入數(shù)據(jù);設(shè)置數(shù)據(jù)長(zhǎng)度。將上述配置寫(xiě)入 MB 相關(guān)寄存器,然后修改 MB 的 CODE 區(qū)進(jìn)行發(fā)送。
/* Send a message frame. */ void app_flexcan_tx(uint8_t * tx_buf) { /* Prepare sending mb frame. */ FLEXCAN_Mb_Type mb; mb.ID = APP_FLEXCAN_XFER_ID; /* Indicated ID number. */ mb.TYPE = FLEXCAN_MbType_Data; /* Data frame type. */ mb.FORMAT = FLEXCAN_MbFormat_Standard; /* Standard frame format. */ mb.PRIORITY = APP_FLEXCAN_XFER_PRIORITY; /* The priority of the frame mb. */ /* Set the information. */ mb.BYTE0 = tx_buf[0]; mb.BYTE1 = tx_buf[1]; mb.BYTE2 = tx_buf[2]; mb.BYTE3 = tx_buf[3]; mb.BYTE4 = tx_buf[4]; mb.BYTE5 = tx_buf[5]; mb.BYTE6 = tx_buf[6]; mb.BYTE7 = tx_buf[7]; /* Set the workload size. */ mb.LENGTH = APP_FLEXCAN_XFER_BUF_LEN; /* Send. */ FLEXCAN_WriteTxMb(BOARD_FLEXCAN_PORT, BOARD_FLEXCAN_TX_MB_CH, mb); FLEXCAN_SetMbCode(BOARD_FLEXCAN_PORT, BOARD_FLEXCAN_TX_MB_CH, FLEXCAN_MbCode_TxDataOrRemote); /* Write code to send. */ }
讀取數(shù)據(jù)
讀取對(duì)應(yīng)的 MB 寄存器,將幀數(shù)據(jù)段內(nèi)容解析出來(lái)。
/* Receive a message frame. */ void app_flexcan_read(uint8_t *rx_buf) { /* Read the info from mb and reconstruct for understanding. */ FLEXCAN_ReadRxMb(BOARD_FLEXCAN_PORT, BOARD_FLEXCAN_RX_MB_CH, app_flexcan_rx_mb); rx_buf[0] = app_flexcan_rx_mb.BYTE0; rx_buf[1] = app_flexcan_rx_mb.BYTE1; rx_buf[2] = app_flexcan_rx_mb.BYTE2; rx_buf[3] = app_flexcan_rx_mb.BYTE3; rx_buf[4] = app_flexcan_rx_mb.BYTE4; rx_buf[5] = app_flexcan_rx_mb.BYTE5; rx_buf[6] = app_flexcan_rx_mb.BYTE6; rx_buf[7] = app_flexcan_rx_mb.BYTE7; }
main() 函數(shù)
主函數(shù)會(huì)在鍵入之后,準(zhǔn)備好數(shù)據(jù)并通過(guò)發(fā)送 MB 發(fā)送;等待中斷處理函數(shù)將全局標(biāo)志位設(shè)置為真后,解析接收MB 收到的幀,并打印。然后再等待下一次鍵入。
int main(void) { BOARD_Init(); printf("rnflexcan_loopback example.rn"); /* Setup the flexcan module.*/ app_flexcan_init(); printf("press any key to send loop back frame with id %u.rn", (unsigned)APP_FLEXCAN_XFER_ID); while (1) { getchar(); /* Send a message through flexcan. */ for (uint8_t i = 0u; i < APP_FLEXCAN_XFER_BUF_LEN; i++) { app_flexcan_tx_buf[i] = ( app_flexcan_tx_buf[i] + i) % 256u; } app_flexcan_tx(app_flexcan_tx_buf); printf("app_flexcan_tx() done.rn"); /* Wait for reception. */ while (!app_flexcan_rx_flag) /* This flag will be on when the Rx interrupt is asserted. */ { } app_flexcan_rx_flag = false; /* Read the message. */ app_flexcan_read(app_flexcan_rx_buf); /* Send frame. */ printf("app_flexcan_read(): "); for (uint8_t i = 0u; i < APP_FLEXCAN_XFER_BUF_LEN; i++) { printf("%u ", (unsigned)app_flexcan_rx_buf[i]); } printf("rnrn"); } }
實(shí)驗(yàn)結(jié)果
圖 9 實(shí)驗(yàn)結(jié)果
來(lái)源:靈動(dòng)MM32MCU
免責(zé)聲明:本文為轉(zhuǎn)載文章,轉(zhuǎn)載此文目的在于傳遞更多信息,版權(quán)歸原作者所有。本文所用視頻、圖片、文字如涉及作品版權(quán)問(wèn)題,請(qǐng)聯(lián)系小編進(jìn)行處理
審核編輯 黃宇
-
控制器
+關(guān)注
關(guān)注
112文章
16464瀏覽量
179601 -
CAN
+關(guān)注
關(guān)注
57文章
2773瀏覽量
464454 -
局域網(wǎng)
+關(guān)注
關(guān)注
5文章
761瀏覽量
46408 -
總線
+關(guān)注
關(guān)注
10文章
2904瀏覽量
88438
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
基于MM32F0140系列MCU實(shí)現(xiàn)UDS Bootloader的設(shè)計(jì)
靈動(dòng)MM32F0140:FlexCAN控制器介紹
![靈動(dòng)<b class='flag-5'>MM32F0140</b>:<b class='flag-5'>FlexCAN</b><b class='flag-5'>控制器</b>介紹](https://file.elecfans.com//web2/M00/43/85/pYYBAGJ-GfGAe7mnAAFWwN0WSBI697.png)
評(píng)論