在线观看www成人影院-在线观看www日本免费网站-在线观看www视频-在线观看操-欧美18在线-欧美1级

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

使用STM32F103做CAN的收發通信

STM32嵌入式開發 ? 來源:STM32嵌入式開發 ? 作者:STM32嵌入式開發 ? 2022-07-06 11:01 ? 次閱讀

CAN通信

CAN 是Controller Area Network 的縮寫(以下稱為CAN),該通信使用的是ISO11898標準,該標準的物理層特征如下圖所示。

95bfe748-f6c2-11ec-ba43-dac502259ad0.png

CAN協議是通過以下5種類型的幀進行的:

  • 數據幀

  • 搖控幀

  • 錯誤幀

  • 過載幀

  • 幀間隔

另外,數據幀和遙控幀有標準格式和擴展格式兩種格式。標準格式有11 個位的標識符(ID),擴展格式有29 個位的ID。

大部分系統使用的都是數據幀 ,我這里使用的也是數據幀。
數據幀一般由7個段構成,即:
(1) 幀起始。表示數據幀開始的段。
(2) 仲裁段。表示該幀優先級的段。
(3) 控制段。表示數據的字節數及保留位的段。
(4) 數據段。數據的內容,一幀可發送0~8個字節的數據。
(5) CRC段。檢查幀的傳輸錯誤的段。
(6) ACK段。表示確認正常接收的段。
(7) 幀結束。表示數據幀結束的段。

明確了數據幀概念,還需要理解一下過濾器的作用。

STM32的標識符屏蔽濾波目的是減少了CPU處理CAN通信的開銷。STM32的過濾器組最多有28個(互聯型),但是STM32F103ZET6只有14個(增強型),每個濾波器組x由2個32為寄存器,CAN_FxR1和CAN_FxR2組成。
STM32每個過濾器組的位寬都可以獨立配置,以滿足應用程序的不同需求。根據位寬的不同,每個過濾器組可提供:

  • 1個32位過濾器,包括:STDID[10:0]、EXTID[17:0]、IDE和RTR位

  • 2個16位過濾器,包括:STDID[10:0]、IDE、RTR和EXTID[17:15]位

此外過濾器可配置為,屏蔽位模式和標識符列表模式。

在屏蔽位模式下,標識符寄存器和屏蔽寄存器一起,指定報文標識符的任何一位,應該按照“必須匹配”或“不用關心”處理。
而在標識符列表模式下,屏蔽寄存器也被當作標識符寄存器用。因此,不是采用一個標識符加一個屏蔽位的方式,而是使用2個標識符寄存器。接收報文標識符的每一位都必須跟過濾器標識符相同。相關
文章:CAN總線詳解

一般也都是使用標識符列表模式,這里使用的也是標識符列表模式。濾波過程舉例如下:
95d70536-f6c2-11ec-ba43-dac502259ad0.png

在程序中就是:


		
//要過濾的ID高位 CAN_FilterInitStructure.CAN_FilterIdHigh=0X00;  //要過濾的ID低位                 CAN_FilterInitStructure.CAN_FilterIdLow= (((u32)0x1314<<3)|CAN_ID_EXT|CAN_RTR_DATA)&0xFFFF; //過濾器屏蔽標識符的高16位值CAN_FilterInitStructure.CAN_FilterMaskIdHigh=0xFFFF;   //過濾器屏蔽標識符的低16位值         CAN_FilterInitStructure.CAN_FilterMaskIdLow=0xFFFF;

		

這里的CAN_FilterId和CAN_FilterMaskId是配合使用的,意思是CAN_FilterId指出需要屏蔽ID的什么內容,什么格式;CAN_FilterMaskId是指CAN_FilterId的每一位是否需要過濾,若CAN_FilterMaskId在某位上是1的話,ID對應位上的數值就必須和CAN_FilterId該位上的一樣,保持一致,反之則是“不關心”。

上述程序的設置的含義就是:只接收來自0x1314的數據,屏蔽其他ID的數據。

程序思路

這里準備做一個主機與從機的通信,主要用擴展標識符ExtId來區分,分配的標識符是: 主機:0x1314 從機:0x1311

主機負責接收所有從機的數據,不需要過濾,用擴展標識符ExtId來區分不同從機的數據;主機還可以向不同從機發送信息。而從機則只接收來自主機的數據,同樣用擴展標識符ExtId來區分是否是發向自己的數據;同時,也能夠向主機發送信息。

相關代碼

代碼也是非常簡單的,這里貼出了主機和從機的can.c和can.h兩個文件。

從機相關代碼

can.c文件:

#include "can.h"

/* 在中斷處理函數中返回 *///__IO uint32_t ret = 0;

//接收數據緩沖器u8 RxBuf[5];u8 Rx_flag=0;

void CAN1_Init(void){    GPIO_InitTypeDef GPIO_InitStructure;     NVIC_InitTypeDef NVIC_InitStructure;    CAN_InitTypeDef        CAN_InitStructure;    CAN_FilterInitTypeDef  CAN_FilterInitStructure;

    /* 復用功能和GPIOB端口時鐘使能*/        RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO | RCC_APB2Periph_GPIOB, ENABLE);                                                                      

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

    /* Configure CAN pin: RX */  // PB8    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8;    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;       //上拉輸入    GPIO_Init(GPIOB, &GPIO_InitStructure);

    /* Configure CAN pin: TX */   // PB9    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;     //復用推挽輸出    GPIO_Init(GPIOB, &GPIO_InitStructure);

    //#define GPIO_Remap_CAN    GPIO_Remap1_CAN1 本實驗沒有用到重映射I/O    GPIO_PinRemapConfig(GPIO_Remap1_CAN1, ENABLE);

    //CAN_NVIC_Configuration(); //CAN中斷初始化       /* Configure the NVIC Preemption Priority Bits */      NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0);

    #ifdef  VECT_TAB_RAM        /* Set the Vector Table base location at 0x20000000 */       NVIC_SetVectorTable(NVIC_VectTab_RAM, 0x0);     #else  /* VECT_TAB_FLASH  */      /* Set the Vector Table base location at 0x08000000 */       NVIC_SetVectorTable(NVIC_VectTab_FLASH, 0x0);       #endif

    /* enabling interrupt */    NVIC_InitStructure.NVIC_IRQChannel=USB_LP_CAN1_RX0_IRQn;;    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;    NVIC_Init(&NVIC_InitStructure);

    //CAN_INIT();//CA初始化N模塊     /* CAN register init */    CAN_DeInit(CAN1);                       //將外設CAN的全部寄存器重設為缺省值    CAN_StructInit(&CAN_InitStructure);     //把CAN_InitStruct中的每一個參數按缺省值填入

    /* CAN cell init */    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;         //沒有使能接收FIFO鎖定模式    CAN_InitStructure.CAN_TXFP=DISABLE;         //沒有使能發送FIFO優先級    CAN_InitStructure.CAN_Mode=CAN_Mode_Normal; //CAN設置為正常模式    CAN_InitStructure.CAN_SJW=CAN_SJW_1tq;      //重新同步跳躍寬度1個時間單位    CAN_InitStructure.CAN_BS1=CAN_BS1_3tq;      //時間段1為3個時間單位    CAN_InitStructure.CAN_BS2=CAN_BS2_2tq;      //時間段2為2個時間單位    CAN_InitStructure.CAN_Prescaler=60;         //時間單位長度為60     CAN_Init(CAN1,&CAN_InitStructure);          //波特率為:72M/2/60(1+3+2)=0.1 即波特率為100KBPs

    // CAN filter init 過濾器,注意,只接收主機發過來的數據,屏蔽其他數據    CAN_FilterInitStructure.CAN_FilterNumber=1;                     //指定過濾器為1    CAN_FilterInitStructure.CAN_FilterMode=CAN_FilterMode_IdMask;   //指定過濾器為標識符屏蔽位模式    CAN_FilterInitStructure.CAN_FilterScale=CAN_FilterScale_32bit;  //過濾器位寬為32位

    //CAN_FilterInitStructure.CAN_FilterIdHigh= (((u32)0x1314<<3)&0xFFFF0000)>>16;      CAN_FilterInitStructure.CAN_FilterIdHigh=0X00;                  //要過濾的ID高位     CAN_FilterInitStructure.CAN_FilterIdLow= (((u32)0x1314<<3)|CAN_ID_EXT|CAN_RTR_DATA)&0xFFFF; //要過濾的ID低位 

    CAN_FilterInitStructure.CAN_FilterMaskIdHigh=0xFFFF;            //過濾器屏蔽標識符的高16位值    CAN_FilterInitStructure.CAN_FilterMaskIdLow=0xFFFF;             //過濾器屏蔽標識符的低16位值    CAN_FilterInitStructure.CAN_FilterFIFOAssignment=CAN_FIFO0;     //設定了指向過濾器的FIFO為0    CAN_FilterInitStructure.CAN_FilterActivation=ENABLE;            //使能過濾器    CAN_FilterInit(&CAN_FilterInitStructure);                       //按上面的參數初始化過濾器

    /* CAN FIFO0 message pending interrupt enable */     CAN_ITConfig(CAN1,CAN_IT_FMP0, ENABLE);                         //使能FIFO0消息掛號中斷}

/* 發送兩個字節的數據*/u8 CAN_SetMsg(u8 Data1,u8 Data2){     u8 mbox;    u16 i=0;     CanTxMsg TxMessage;  

    TxMessage.StdId=0x0000;     //標準標識符為0x00    TxMessage.ExtId=0x1311;     //擴展標識符0x1311,可以更改該標識符以示區分不同從機    TxMessage.IDE=CAN_ID_EXT;   //使用擴展標識符    TxMessage.RTR=CAN_RTR_DATA; //為數據幀    TxMessage.DLC=2;            //消息的數據長度為2個字節    TxMessage.Data[0]=Data1;    //第一個字節數據    TxMessage.Data[1]=Data2;    //第二個字節數據 

    //發送數據    mbox= CAN_Transmit(CAN1, &TxMessage);      while((CAN_TransmitStatus(CAN1, mbox)==CAN_TxStatus_Failed)&&(i<0XFFF))        i++;    //等待發送結束    if(i>=0XFFF)        return 0;    return 1;}u8 CAN_GetMsg(u8 *msg1,u8 *msg2){    if(Rx_flag == 1)//發現數據    {        *msg1=RxBuf[0];        *msg2=RxBuf[1];        Rx_flag=0;//數據已經取走,可以更新數據        return 1;    }else        return 0;}/* USB中斷和CAN接收中斷服務程序,USB跟CAN公用I/O,這里只用到CAN的中斷。*/void USB_LP_CAN1_RX0_IRQHandler(void){

  CanRxMsg RxMessage;

  RxMessage.StdId=0x00;  RxMessage.ExtId=0x00;  RxMessage.IDE=0;  RxMessage.DLC=0;  RxMessage.FMI=0;  RxMessage.Data[0]=0x00;  RxMessage.Data[1]=0x00;    

  CAN_Receive(CAN1,CAN_FIFO0, &RxMessage); //接收FIFO0中的數據  

  if(Rx_flag == 0)//數據已取走或者緩沖器為空    {        RxBuf[0]=RxMessage.Data[0];        RxBuf[1]=RxMessage.Data[1];        Rx_flag=1;//數據已經備好,等待取走    }

}

		

can.h文件

95e760c0-f6c2-11ec-ba43-dac502259ad0.png

主機相關代碼

這里主機代碼大部分是和從機類似的,就只貼出不同的地方了。 can.c文件:

#include "can.h"

/* 在中斷處理函數中返回 *///__IO uint32_t ret = 0;

void CAN1_Init(void){    ......//以上與從機部分相同

    //CAN filter init 過濾器,已經設置為任意,可以通過ExtId標識符區分從機代號    CAN_FilterInitStructure.CAN_FilterNumber=1;                     //指定過濾器為1    CAN_FilterInitStructure.CAN_FilterMode=CAN_FilterMode_IdMask;   //指定過濾器為標識符屏蔽位模式    CAN_FilterInitStructure.CAN_FilterScale=CAN_FilterScale_32bit;  //過濾器位寬為32位    CAN_FilterInitStructure.CAN_FilterIdHigh=0x0000;                //過濾器標識符的高16位值    CAN_FilterInitStructure.CAN_FilterIdLow=CAN_ID_EXT|CAN_RTR_DATA;//過濾器標識符的低16位值    CAN_FilterInitStructure.CAN_FilterMaskIdHigh=0x0000;            //過濾器屏蔽標識符的高16位值    CAN_FilterInitStructure.CAN_FilterMaskIdLow=0x0000;             //過濾器屏蔽標識符的低16位值    CAN_FilterInitStructure.CAN_FilterFIFOAssignment=CAN_FIFO0;     //設定了指向過濾器的FIFO為0    CAN_FilterInitStructure.CAN_FilterActivation=ENABLE;            //使能過濾器    CAN_FilterInit(&CAN_FilterInitStructure);                       //按上面的參數初始化過濾器

    /* CAN FIFO0 message pending interrupt enable */     CAN_ITConfig(CAN1,CAN_IT_FMP0, ENABLE);                         //使能FIFO0消息掛號中斷}

//接收數據緩沖器u8 CAN_RX_BUF[CAN_RX_LEN]={0};     //接收緩沖,最大USART_REC_LEN個字節.//接收標志位u8 Rx_flag=0;/* USB中斷和CAN接收中斷服務程序,USB跟CAN公用I/O,這里只用到CAN的中斷。*/void USB_LP_CAN1_RX0_IRQHandler(void){    u8 i=0;    CanRxMsg RxMessage;

    RxMessage.StdId=0x00;    RxMessage.ExtId=0x00;    RxMessage.IDE=0;    RxMessage.DLC=0;    RxMessage.FMI=0;

    CAN_Receive(CAN1,CAN_FIFO0, &RxMessage); //接收FIFO0中的數據  

    if(Rx_flag == 0)//數據已取走或者緩沖器為空    {        if((RxMessage.DLC) == 2)//是否收到2位字節數據        {             CAN_RX_BUF[0]=RxMessage.Data[0];             CAN_RX_BUF[1]=RxMessage.Data[1];             }    }

} 

/* 發送兩個字節的數據*/u8 CAN_SendMsg(u8* data1, u8* data2){     u8 mbox;    u16 i=0;     CanTxMsg TxMessage;  

    TxMessage.StdId=0x0000;     //標準標識符為0x00    TxMessage.ExtId=0x1314;     //擴展標識符0x0000    TxMessage.IDE=CAN_ID_EXT;   //使用擴展標識符    TxMessage.RTR=CAN_RTR_DATA; //為數據幀    TxMessage.DLC=2;            //消息的數據長度為2個字節    TxMessage.Data[0]=Data1;    //第一個字節數據    TxMessage.Data[1]=Data2;    //第二個字節數據 

    //發送數據    mbox= CAN_Transmit(CAN1, &TxMessage);      while((CAN_TransmitStatus(CAN1, mbox)==CAN_TxStatus_Failed)&&(i<0XFFF))        i++;    //等待發送結束    if(i>=0XFFF)        return 0;//發送失敗    return 1;//發送成功 }u8 CAN_GetMsg(u8 *msg1,u8 *msg2){    if(Rx_flag == 1)//發現數據    {        *msg1=CAN_RX_BUF[0];        *msg2=CAN_RX_BUF[1];        Rx_flag=0;//數據已經取走,可以更新數據        return 1;    }else        return 0;}void Clear_canBuffer(void){    Rx_flag=0;//清楚接收標志位    memset(CAN_RX_BUF, 0, sizeof(u8)*CAN_RX_LEN);//清空緩沖區}u8 Check_canRX(void){    return (Rx_flag == 6);}

		

can.h文件:

#ifndef __CAN_H#define __CAN_H

#include "sys.h"#include "string.h"

#define CAN_RX_LEN          30          //定義最大接收字節數 

extern u8  CAN_RX_BUF[CAN_RX_LEN]; //接收緩沖,最大USART_REC_LEN個字節.末字節為換行符 

void CAN1_Init(void);u8 CAN_SendMsg(u8* data1, u8* data2);u8 CAN_GetMsg(u8 *msg1,u8 *msg2);

#endif /* __CAN_H */

文章出處:【微信公眾號:STM32嵌入式開發】歡迎添加關注!文章轉載請注明出處。

審核編輯:符乾江
聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • CAN
    CAN
    +關注

    關注

    57

    文章

    2756

    瀏覽量

    463893
  • STM32
    +關注

    關注

    2270

    文章

    10906

    瀏覽量

    356530

原文標題:使用STM32F103做CAN的收發通信

文章出處:【微信號:c-stm32,微信公眾號:STM32嵌入式開發】歡迎添加關注!文章轉載請注明出處。

收藏 人收藏

    評論

    相關推薦

    STM32F103x8/STM32F103xB規格書

    電子發燒友網站提供《STM32F103x8/STM32F103xB規格書.pdf》資料免費下載
    發表于 12-06 15:43 ?1次下載

    STM32F103×8/STM32F103×B MCU手冊

    1. Q: STM32F103C8T6如何正確配置時鐘系統?A: STM32F103C8T6的時鐘系統配置通常涉及HSE(高速外部時鐘)、HSI(高速內部時鐘)、PLL(相位鎖定環)等。配置時,首先
    發表于 11-18 15:14 ?0次下載

    STM32F103xC,STM32F103xD,STM32F103xE中文資料

    電子發燒友網站提供《STM32F103xC,STM32F103xD,STM32F103xE中文資料.pdf》資料免費下載
    發表于 06-17 14:12 ?4次下載

    STM32F103CAN調試器接到該板子后給其發消息,調試器會顯示總線數據錯誤的原因?

    項目里有個CAN收發相關的板子,用的是STM32F103芯片。在與上位機的CAN交互過程中經常會出現通訊錯誤的情況,表現在上位機發送報文后沒有收到回復。用
    發表于 05-27 07:42

    stm32f103 CANbus控制器對于擴展幀格式的srr位怎么設置成低電平?

    這周 用stm32f103芯片自帶的can控制器 驅動外部的can發射器 ,用擴展幀發現 srr位一直為高電平。這個可以通過軟件設置成低電平嗎? 外部發射芯片是nxp a82c250can
    發表于 05-17 07:44

    stm32f302和stm32f103的ADC區別是什么?

    請問stm32f302和stm32f103的ADC除了stm32f103有2個ADC(ADC1和ADC2),stm32f302只有1個ADC外,在使用ADC+DMA采樣多通道的模擬信號
    發表于 05-15 08:03

    STM32F103在電路板上怎樣配套的電路設計呢?

    新手求助: 小弟正在用STM32F103做一個開發,現在正在做硬件部分的電路設計,想求助一下大嬸們如果程序用JLink來下載的話,在電路板上怎樣配套的電路設計呢? 由于剛開始學習,所以請大神不吝賜教~~~
    發表于 05-11 08:14

    求助,關于STM32F103 CAN通信的幾個疑問求解

    使用STM32F103作為CAN從機發送和接收數據,從機是被動發送,在收到主機特定命令幀后才會發送數據,其余時候只接收:問題1:單個發送沒有問題,多個CAN并在一起,其中某個會出現只能接收并未
    發表于 04-18 07:30

    請問STM32F103能否USB打印機?

    STM32F103能否USB打印機? 虛擬成打印機接收數據,再從其它數據口(SPI或UART)傳出打印數據。找不到這樣的例程。
    發表于 04-16 06:29

    STM32F103RB無法進入CAN中斷的原因?怎么解決?

    鄙人買了一塊NUCLEO F103RB的開發板,第一次玩STM系列的片子。使用STM32Cube和STM32MX開發,確實很好用,快捷方便。 IO,定時器等等資源很快就調試完了。現在有個小問題,請教
    發表于 04-09 07:14

    如何用STM32F103傅里葉變換?

    Hi,想問下,用STM32F103傅里葉變換,請問例程在那里下載?
    發表于 03-27 07:52

    請問STM32F103 I2C通信和SPI通信哪種方式更穩定?

    STM32F103這顆料I2C通信和SPI通信哪種方式更穩定?
    發表于 03-22 06:24

    STM32F103如何使用BOOT下載程序?

    STM32F103如何使用BOOT下載程序
    發表于 03-15 07:21

    ARM系列STM32F103芯片的解密方法

    本文介紹ARM系列STM32F103芯片的解密方法,其內核是Cortex-M3,內存從16K-512K都有。
    發表于 02-28 11:20 ?1737次閱讀

    stm32f103 flash模擬eeprom

    STM32F103是意法半導體(STMicroelectronics)推出的一款32位單片機系列,該系列芯片具有高性能和豐富的外設接口,廣泛應用于工業控制、消費電子、汽車電子等領域。其中
    的頭像 發表于 01-09 11:21 ?2098次閱讀
    主站蜘蛛池模板: 2020欧美极品hd18| 97影院理论片在线观看| 四虎最新影院| 114毛片免费观看网站| 32pao强力打造免费高速高清 | 欧美日剧在线免费| 美女黄视频免费| 韩国三级床戏合集| 欧美成人性动漫在线观看| 四虎成人精品在永久在线观看| 免费大片黄在线观看| 中文字幕有码在线视频| 视频一区在线观看| 四虎4444hu4影视最新地址| 日本免费人成黄页在线观看视频| bt种子在线搜索| 天天色天天草| 国产精品久久久久久影院| 日本加勒比在线精品视频| 黄黄网| 久久久久大香线焦| 欧美人与zoxxxx另类9| 欧美日韩一区二区三区毛片| 亚洲欧美经典| 亚洲第一页视频| 亚洲一级色| 日本久久久久久久| 欧美性一级交视频| 国产精品你懂得| 国产在线视频资源| 天天躁狠狠躁| 天天舔天天干天天操| 黄网站色| 日本在线不卡免费| 四虎影视在线看| 国产精品黄网站免费观看| 日日操天天操夜夜操| 高清欧美色欧美综合网站| 亚洲第一黄色网| 四虎影院台湾辣妹| 狠狠色狠狠色综合日日小蛇|