新聞中心

        EEPW首頁 > 嵌入式系統 > 設計應用 > STM32 CAN模塊使用詳解

        STM32 CAN模塊使用詳解

        作者: 時間:2016-11-24 來源:網絡 收藏
        STM32 CAN模塊使用詳解.重點介紹以STM32F103E系列芯片為基礎介紹CAN 總線的使用方法。CAN 總線在控制領域使用的非常廣泛,如今大多數CPU芯片外圍都擴展CAN接口。

        1. 硬件基礎
        CAN總線工作需要兩根數據線,RX和TX,即為輸入總線和輸出總線。一般CPU與外界通信需要接一個驅動芯片(這點很像UART接口),常用的CAN芯片主要有:SN65VHD230、PCA82C250T等,本系統使用SN65VHD230作為CAN接口芯片。而CPU提供的CAN接口為CAN_L和CAN_H。
        2. 軟件設計
        在進行軟件設計時,我們首先來看這樣的一個結構體:
        typedef struct
        {
        uint32_t StdId;
        uint32_t ExtId;
        uint8_t IDE;
        uint8_t RTR;
        uint8_t DLC;
        uint8_t Data[8];
        } CanTxMsg;
        這是定義一個can數據包的結構體,即一個CAN數據包包含以上幾個部分。
        現在我們思考一個問題:由于can可連接多個節點,如果一個系統為星形網絡連接方式,那么主機應該怎樣區別這些從機發送的信息呢?
        答案在上面那個結構體中,我們可以給每個分機定義一個ID,那么主機在接收到分機發送的數據后,通過ID號判別接收到的信息是那個從機發送的。
        注意: DLC定義發送數據的長度,其范圍為:0~8。
        下面我們來編寫CAN驅動:
        對CAN模塊初始化
        void CAN_CfgInit(void)
        {
        CAN_InitTypeDef CAN_InitStructure;
        CAN_FilterInitTypeDefCAN_FilterInitStructure;

        CAN_PortInit();
        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;
        CAN_InitStructure.CAN_RFLM=DISABLE;
        CAN_InitStructure.CAN_TXFP=DISABLE;
        CAN_InitStructure.CAN_Mode=CAN_Mode_LoopBack;
        CAN_InitStructure.CAN_SJW=CAN_SJW_1tq;
        CAN_InitStructure.CAN_BS1=CAN_BS1_8tq;
        CAN_InitStructure.CAN_BS2=CAN_BS2_7tq;
        CAN_InitStructure.CAN_Prescaler=5;
        CAN_Init(CAN1, &CAN_InitStructure);

        CAN_FilterInitStructure.CAN_FilterNumber=0;
        CAN_FilterInitStructure.CAN_FilterMode=CAN_FilterMode_IdMask;
        CAN_FilterInitStructure.CAN_FilterScale=CAN_FilterScale_32bit;
        CAN_FilterInitStructure.CAN_FilterIdHigh=0x0000;
        CAN_FilterInitStructure.CAN_FilterIdLow=0x0000;
        CAN_FilterInitStructure.CAN_FilterMaskIdHigh=0x0000;
        CAN_FilterInitStructure.CAN_FilterMaskIdLow=0x0000;
        //CAN_FilterInitStructure.CAN_FilterFIFOAssignment=0;
        CAN_FilterInitStructure.CAN_FilterFIFOAssignment=CAN_FIFO0;
        CAN_FilterInitStructure.CAN_FilterActivation=ENABLE;
        CAN_FilterInit(&CAN_FilterInitStructure);

        CAN_ITConfig(CAN1, CAN_IT_FMP0, ENABLE);
        }
        這里為can 定義一個專門的結構體,便于數據處理:
        typedef struct CAN_Socket CAN;
        struct CAN_Socket {
        INT32U u32_StdId;
        INT32U u32_ExtId;
        INT8Uu8_IDE;
        INT8Uu8_RTR;
        INT8Uu8_DLC;
        INT8Uu8_FMI;
        INT8Uu8_data[8];
        };
        數據打包,并且發送
        void CAN_TxSocket( CAN *can_Socket )
        {
        INT8U i = 0;
        CanTxMsg TxMessage;

        CAN_ITConfig(CAN1, CAN_IT_FMP0, ENABLE); // CAN FIFO0 message pending interrupt enable
        // Transmit a message
        TxMessage.StdId=can_Socket->u32_StdId;
        TxMessage.ExtId=can_Socket->u32_ExtId;
        TxMessage.IDE=can_Socket->u8_IDE;
        TxMessage.RTR= can_Socket->u8_RTR;
        TxMessage.DLC=can_Socket->u8_DLC;
        for( i =0; i
        TxMessage.Data = can_Socket->u8_data;
        }
        CAN_Transmit(CAN1, &TxMessage);
        CAN_ITConfig(CAN1, CAN_IT_FMP0, DISABLE); // Disable interrupt handling
        }
        接收函數放在中斷程序中處理:
        void USB_LP_CAN1_RX0_IRQHandler(void)
        {
        CanRxMsg RxMessage;
        INT8U i = 0;
        INT8U u8_RxLen = 0;

        RxMessage.StdId = 0x00;
        RxMessage.ExtId = 0x00;
        RxMessage.IDE = 0;
        RxMessage.RTR = 0;
        RxMessage.DLC = 0;
        RxMessage.FMI = 0;
        for( i=0;i<8;i++){
        RxMessage.Data=0x00;
        }

        CAN_Receive(CAN1, CAN_FIFO0, &RxMessage);
        u8_RxLen = RxMessage.DLC;
        if((RxMessage.ExtId==0x12) && (RxMessage.IDE==CAN_ID_EXT)){
        for( i=0;i
        CAN_ReceiveBuff = RxMessage.Data;
        }
        }
        }
        這里只介紹CAN使用方法和主要驅動程序,測試程序可自行設計。
        本人的測試程序:
        ~INT8U SendBuff1[]="Hello";
        INT8U SendBuff2[]="World";
        INT8U SendBuff3[]="ADC= 255";
        void main(void)
        {
        System_HardwareInit();
        while (1)
        {
        CAN_Tx(SendBuff1);
        Disp_CanReceveData();
        CAN_Tx(SendBuff2);
        Disp_CanReceveData();
        CAN_Tx(SendBuff3);
        Disp_CanReceveData();
        }
        }
        接收數據,并在液晶上打印出來!
        void Disp_CanReceveData( void )
        {
        INT8U u8_CanRecBuff[64];

        if(CAN_ReceiveBuff[0] == H){
        sprintf(( char *)u8_CanRecBuff,"CAN receve buff1 is : %s",CAN_ReceiveBuff);
        GCLDASC_PutChar16x16Str(10,30,u8_CanRecBuff, Red, Green, 1);
        }
        if(CAN_ReceiveBuff[0] == W){
        sprintf(( char *)u8_CanRecBuff,"CAN receve buff2 is : %s",CAN_ReceiveBuff);
        GCLDASC_PutChar16x16Str(10,50,u8_CanRecBuff, Red, Green, 1);
        }
        if(CAN_ReceiveBuff[0] == A){
        sprintf(( char *)u8_CanRecBuff,"CAN receve buff3 is : %s",CAN_ReceiveBuff);
        GCLDASC_PutChar16x16Str(10,70,u8_CanRecBuff, Red, Green, 1);
        }
        }

        本文引用地址:http://www.104case.com/article/201611/320935.htm


        評論


        技術專區

        關閉
        主站蜘蛛池模板: 花莲市| 石城县| 天津市| 天峻县| 武乡县| 淮阳县| 庆元县| 南康市| 曲麻莱县| 吉木萨尔县| 延长县| 上栗县| 尖扎县| 巴彦淖尔市| 封开县| 布拖县| 龙胜| 军事| 敖汉旗| 太和县| 涞水县| 顺平县| 务川| 德钦县| 海南省| 信丰县| 潞城市| 青铜峡市| 乐亭县| 曲松县| 武平县| 定兴县| 阳春市| 西丰县| 清新县| 中宁县| 西乌珠穆沁旗| 高碑店市| 北流市| 双江| 呼伦贝尔市|