新聞中心

        EEPW首頁 > 嵌入式系統(tǒng) > 設(shè)計(jì)應(yīng)用 > 基于STM32的CAN總線通信程序

        基于STM32的CAN總線通信程序

        作者: 時(shí)間:2016-11-24 來源:網(wǎng)絡(luò) 收藏
        #include

        #include "sys.h"
        #include "delay.h"
        #include "CAN.h"
        CAN_msg CAN_TxMsg; //發(fā)送郵箱
        CAN_msg CAN_RxMsg; //接收郵箱
        u8 CAN_TxRdy=0; //發(fā)送就緒標(biāo)志
        u8 CAN_RxRdy=0; //接收就緒標(biāo)志
        u8CAN_TDTxR_DLC; //數(shù)據(jù)長度,最高為1111
        /////////////////CAN設(shè)置/////////////////////////////////////
        void CAN_setup(void)
        {
        u8 brp=20; //獲取主時(shí)鐘頻率 APB1ENR時(shí)鐘頻率為36M
        RCC->APB1ENR|=1<<25; //RCC_APB1ENR_CANEN; //開啟CAN使能時(shí)鐘
        RCC->APB2ENR|=1<<0; //RCC_APB2ENR_AFIOEN; //開啟輔助時(shí)鐘
        AFIO->MAPR&=0XFFFF9FFF;//清除復(fù)用重映射配置寄存器13,14位,
        AFIO->MAPR|=0X00004000;//配置為10;IO口重映射至PB8.PB9
        RCC->APB2ENR|=1<<3; //RCC_APB2ENR_IOPBEN;//開啟IO口B時(shí)鐘
        GPIOB->CRH&=~(0X0F<<0);//清除PB8狀態(tài)寄存器~(1111<<0)
        GPIOB->CRH|=(0X08<<0);//設(shè)定pb8上下拉輸入1000
        GPIOB->CRH&=~(0XF<<4);//清空pb9狀態(tài)寄存器
        GPIOB->CRH|=(0X0B<<4);//設(shè)定PB9推挽輸出
        MY_NVIC_Init(1,1,USB_HP_CAN_TX_IRQChannel,2);//發(fā)送中斷使能
        MY_NVIC_Init(1,1,USB_LP_CAN_RX0_IRQChannel,2);//接收中斷使能
        CAN->MCR|=1<<4;//置NART位為1,禁止自動(dòng)重傳 403
        CAN->MCR|=1<<0; //置INRQ位為1,請(qǐng)求初始化 403 (CAN_MCR_NART|CAN_MCR_INRQ);//初始化模式,禁止重傳
        CAN->IER|=1<<0;//發(fā)送郵箱空中斷允許 409
        CAN->IER|=1<<1; //FIFO0消息掛號(hào)中斷允許 409 (CAN_IER_FMPIE0|CAN_IER_TMEIE);
        //brp=(brp/18)/500000;//波特率設(shè)置500Kb/s,計(jì)算波特率分頻器值
        CAN->BTR&=~(((0X03)<<24)|((0x07)<<20)|((0x0f)<<16)|(0x1ff)); //清空BTR寄存器相關(guān)位 410 400
        CAN->BTR|=(((1&0X03)<<24)|((7&0X07)<<20)|((8&0X0F)<<16)|(brp-1));//設(shè)置BTR寄存器 410 400

        }
        //////////////從初始化模式進(jìn)入正常工作模式/////////////////////////////////////////////
        void CAN_start(void)
        {
        CAN->MCR&=0xfffffffe;
        while(CAN->MSR&(0x01));
        CAN->MCR&=0xfffffffd; //清零INRQ位,進(jìn)入正常模式
        //while(~(CAN->MSR&0x01)); //等待硬件對(duì)INAK位清零,確認(rèn)退出初始化
        }
        //////////////設(shè)置工作模式///////////////////////////////////////////
        void CAN_testmode(void)
        {
        CAN->BTR&=0x3fffffff;//清空BTR 的SILM LBKM位410
        CAN->BTR|=0XC0000000;//設(shè)置BTR 的LBKM位為高,環(huán)回模式 410

        }
        ///////////////檢測(cè)發(fā)送郵箱為空////////////////////////////////////////////////
        void CAN_waitReady(void)
        {
        while((CAN->TSR&(1<<26))==0); //檢測(cè)發(fā)送郵箱0標(biāo)志位,為1則為空,為0不為空
        CAN_TxRdy=1; //置發(fā)送就緒標(biāo)志位為1
        }
        ///////////////發(fā)送數(shù)據(jù)//////////////////////////////////////
        void CAN_wrMsg(CAN_msg *msg)
        {
        CAN->sTxMailBox[0].TIR=(u8)0; //發(fā)送郵箱標(biāo)示符寄存器復(fù)位 清零
        if(msg->format ==STANDARD_FORMAT)//如果是標(biāo)準(zhǔn)11位標(biāo)示符幀
        {msg->id=33 ;
        CAN->sTxMailBox[0].TIR|=0x4200000;//(msg->id<<21)|CAN_ID_STD; //則標(biāo)示符左移21位,高11位為標(biāo)準(zhǔn)標(biāo)示符,標(biāo)示符選擇位置0 411
        }
        else //如果是29位擴(kuò)展標(biāo)示符幀
        {
        CAN->sTxMailBox[0].TIR|=(u8)(msg->id<<3)|CAN_ID_EXT; //標(biāo)示符左移3位,高29位為標(biāo)示符(擴(kuò)展標(biāo)示符)標(biāo)示符選擇位置1 411
        }
        if(msg->type==DATA_FRAME) //如果消息為數(shù)據(jù)幀
        {
        CAN->sTxMailBox[0].TIR|=CAN_RTR_DATA;//標(biāo)示符寄存器RTR位置0,數(shù)據(jù)幀
        }
        else //如果為遠(yuǎn)程幀
        {
        CAN->sTxMailBox[0].TIR|=CAN_RTR_REMOTE;//標(biāo)示符寄存器RTR置1,遠(yuǎn)程幀
        }
        CAN->sTxMailBox[0].TDLR=(((u8)msg->data[3]<<24)|((u8)msg->data[2]<<16)|((u8)msg->data[1]<<8)|((u8)msg->data[0])); //數(shù)據(jù)位低4字節(jié)寫入發(fā)送郵箱0



        CAN->sTxMailBox[0].TDHR=(((u8)msg->data[7]<<24)|((u8)msg->data[6]<<16)|((u8)msg->data[5]<<8)|((u8)msg->data[4])); //數(shù)據(jù)位高4字節(jié)寫入發(fā)送郵箱0



        CAN->sTxMailBox[0].TDTR&=0xfffffff0;//設(shè)置消息長度DLC清0
        CAN->sTxMailBox[0].TDTR|=0x00000004;//設(shè)置消息長度為4個(gè)字節(jié)
        CAN->IER|=1<<0; //發(fā)送郵箱空中斷使能 409
        CAN->sTxMailBox[0].TIR|=1<<0; //發(fā)送消息411

        }
        ///////////////讀取郵箱數(shù)據(jù)并釋放//////////////////////////////////////////////////////////////
        void CAN_rdMsg(CAN_msg *msg)
        {
        if((CAN->sFIFOMailBox[0].RIR&CAN_ID_EXT)==0) //如果是11位標(biāo)準(zhǔn)標(biāo)識(shí)符
        {
        msg->format=STANDARD_FORMAT; //消息為標(biāo)準(zhǔn)格式
        msg->id=(u32)0x000007ff&(CAN->sFIFOMailBox[0].RIR>>21); //標(biāo)示符等于標(biāo)示符位右移21位與0x7ff
        }
        else //如果是29位擴(kuò)展標(biāo)識(shí)符
        {
        msg->format=EXTENDED_FORMAT; //消息格式為擴(kuò)展標(biāo)示符格式
        msg->id=(u32)0x0003ffff&(CAN->sFIFOMailBox[0].RIR>>3);//標(biāo)示符等于標(biāo)示符位右移3位與上0x3ffff
        }
        if((CAN->sFIFOMailBox[0].RIR&CAN_RTR_REMOTE)==0) //如果消息為數(shù)據(jù)幀
        {
        msg->type=DATA_FRAME;
        }
        else //數(shù)據(jù)位遠(yuǎn)程幀
        {
        msg->type=REMOTE_FRAME;
        }
        msg->len = (unsigned char)0x0000000F & CAN->sFIFOMailBox[0].RDTR; //讀取數(shù)據(jù)長度

        msg->data[0] = (unsigned int)0x000000FF & (CAN->sFIFOMailBox[0].RDLR); //讀取數(shù)據(jù)低4字節(jié)
        msg->data[1] = (unsigned int)0x000000FF & (CAN->sFIFOMailBox[0].RDLR >> 8);
        msg->data[2] = (unsigned int)0x000000FF & (CAN->sFIFOMailBox[0].RDLR >> 16);
        msg->data[3] = (unsigned int)0x000000FF & (CAN->sFIFOMailBox[0].RDLR >> 24);

        msg->data[4] = (unsigned int)0x000000FF & (CAN->sFIFOMailBox[0].RDHR); //讀取數(shù)據(jù)高4字節(jié)
        msg->data[5] = (unsigned int)0x000000FF & (CAN->sFIFOMailBox[0].RDHR >> 8);
        msg->data[6] = (unsigned int)0x000000FF & (CAN->sFIFOMailBox[0].RDHR >> 16);
        msg->data[7] = (unsigned int)0x000000FF & (CAN->sFIFOMailBox[0].RDHR >> 24);

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

        CAN->RF0R |= 1<<5; //釋放接收郵箱0 407
        }
        ////////////////////////設(shè)置標(biāo)示符過濾器組/////////////////////////////////////////////////////////////////////////////

        void CAN_wrFilter (unsigned int id, unsigned char format)
        {
        static unsigned short CAN_filterIdx = 0; //標(biāo)示符設(shè)置數(shù)量索引
        unsigned int CAN_msgId = 0; //變量用于存儲(chǔ)需要設(shè)定的標(biāo)示符

        if (CAN_filterIdx > 13) //檢查CAN過濾器是否已滿,最高到13
        {
        return; //如果已滿-返回
        }
        if (format == STANDARD_FORMAT) //如果是標(biāo)準(zhǔn)幀,標(biāo)準(zhǔn)幀是11位ID(報(bào)文識(shí)別碼)
        { // Standard ID
        CAN_msgId |= (unsigned int)(id << 21) | CAN_ID_STD;//標(biāo)示符左移21位并添加幀識(shí)別碼,得到32位的標(biāo)示符字
        }
        else //如果是擴(kuò)展幀,擴(kuò)展幀是29位ID(報(bào)文識(shí)別碼)
        { // Extended ID
        CAN_msgId |= (unsigned int)(id << 3) | CAN_ID_EXT;//標(biāo)示符左移3位并添加幀識(shí)別碼,得到32位的標(biāo)示符字
        }
        // set Initialisation mode for filter banks
        //CAN過濾器組工作在初始化模式
        CAN->FMR |= 1<<0;
        // deactivate filter
        CAN->FA1R &= ~(unsigned int)(1 << CAN_filterIdx);

        // initialize filter
        // set 32-bit scale configuration
        //初始化過濾器
        //過濾器位寬為單個(gè)32位
        CAN->FS1R |= (unsigned int)(1 << CAN_filterIdx);
        // set 2 32-bit identifier list mode
        //過濾器組x的2個(gè)32位寄存器工作在標(biāo)識(shí)符列表模式
        CAN->FM1R |= (unsigned int)(1 << CAN_filterIdx);
        // 32-bit identifier
        //32位標(biāo)識(shí)符
        CAN->sFilterRegister[CAN_filterIdx].FR1 = CAN_msgId;
        // 32-bit identifier
        //32位標(biāo)識(shí)符
        CAN->sFilterRegister[CAN_filterIdx].FR2 = CAN_msgId;
        // assign filter to FIFO 0
        //過濾器被關(guān)聯(lián)到FIFO0
        CAN->FFA1R &= ~(unsigned int)(1 << CAN_filterIdx);
        // activate filter
        //過濾器被激活
        CAN->FA1R |= (unsigned int)(1 << CAN_filterIdx);
        // reset Initialisation mode for filter banks
        //CAN過濾器組工作在正常模式
        CAN->FMR &= ~(1<<0); // 該位置0為正常模式 415
        // increase filter index
        //設(shè)置的過濾器數(shù)量增加
        CAN_filterIdx += 1;
        }


        上一頁 1 2 下一頁

        關(guān)鍵詞: STM32CAN總線通信程

        評(píng)論


        技術(shù)專區(qū)

        關(guān)閉
        主站蜘蛛池模板: 秦安县| 常宁市| 霍邱县| 四川省| 清原| 广汉市| 贵州省| 金寨县| 大渡口区| 淮北市| 安宁市| 呼图壁县| 邵阳县| 大英县| 永胜县| 广安市| 青河县| 定远县| 乌拉特前旗| 湖北省| 通河县| 手游| 大方县| 宾阳县| 延吉市| 托克托县| 凤翔县| 宜黄县| 尼玛县| 莆田市| 科尔| 镇坪县| 公主岭市| 大足县| 隆林| 原平市| 永定县| 景德镇市| 景泰县| 麻阳| 育儿|