加入星計劃,您可以享受以下權(quán)益:

  • 創(chuàng)作內(nèi)容快速變現(xiàn)
  • 行業(yè)影響力擴散
  • 作品版權(quán)保護
  • 300W+ 專業(yè)用戶
  • 1.5W+ 優(yōu)質(zhì)創(chuàng)作者
  • 5000+ 長期合作伙伴
立即加入
  • 正文
    • 1. STM32CubeMX配置
    • 2.?MDK-ARM編程
    • 3. 下載測試
  • 推薦器件
  • 相關(guān)推薦
  • 電子產(chǎn)業(yè)圖譜
申請入駐 產(chǎn)業(yè)圖譜

CAN總線學(xué)習筆記 | CAN盒測試STM32的CAN中斷接收

2023/01/19
2179
閱讀需 19 分鐘
加入交流群
掃碼加入
獲取工程師必備禮包
參與熱點資訊討論

CAN基礎(chǔ)知識介紹文中介紹了CAN協(xié)議相關(guān)的基礎(chǔ)知識,以及STM32F4芯片的CAN控制器相關(guān)知識,下面將通過實例,利用STM32CubeMX圖形化配置工具,并配合CAN盒,來實現(xiàn)CAN通訊的中斷收發(fā)測試

1. STM32CubeMX配置

? CAN是掛載在APB1總線上,設(shè)置PCLK1時鐘頻率到最大45MHz

? 激活CAN1,配置位時序參數(shù),其他基本參數(shù)以及工作模式(此處設(shè)置為Normal普通模式)

CAN波特率的計算公式:只需要知道BS1和BS2的設(shè)置,以及APB1的時鐘頻率,就可以方便的計算出波特率。比如設(shè)置TS1=8、TS2=6和BRP=6,在APB1頻率為45Mhz的條件下,即可得到CAN通信的波特率=45000/6/(8+6+1)=500Kbps

? 激活USART1作為調(diào)試串口,配置相關(guān)LED對應(yīng)的GPIO引腳作為指示燈

2.?MDK-ARM編程

2.1 幾個重要的結(jié)構(gòu)體

? CAN 初始化結(jié)構(gòu)體:此結(jié)構(gòu)體內(nèi)容,可由STM32CubeMX工具進行配置

typedef?struct
{
??uint32_t?Prescaler;???????/*?配置?CAN?外設(shè)的時鐘分頻,可設(shè)置為?1-1024*/
??uint32_t?Mode;????????????/*?配置?CAN?的工作模式,回環(huán)或正常模式?*/
??uint32_t?SyncJumpWidth;???/*?配置?SJW?極限值?*/
??uint32_t?TimeSeg1;????????/*?配置?BS1?段長度?*/
??uint32_t?TimeSeg2;????????/*?配置?BS2?段長度?*/
??FunctionalState?TimeTriggeredMode;????/*?是否使能?TTCM?時間觸發(fā)功能?*/
??FunctionalState?AutoBusOff;???????????/*?是否使能?ABOM?自動離線管理功能?*/
??FunctionalState?AutoWakeUp;?????????  /*?是否使能?AWUM?自動喚醒功能?*/
??FunctionalState?AutoRetransmission;???/*?是否使能?NART?自動重傳功能?*/
??FunctionalState?ReceiveFifoLocked;????/*?是否使能?RFLM?鎖定?FIFO?功能?*/
??FunctionalState?TransmitFifoPriority;?/*?配置?TXFP?報文優(yōu)先級的判定方法?*/
}?CAN_InitTypeDef;

? 發(fā)送及接收頭結(jié)構(gòu)體:主要用于構(gòu)造發(fā)送報文,以及接收報文。收發(fā)發(fā)文時,需要自定義頭結(jié)構(gòu)體變量

typedef?struct
{
??uint32_t?StdId;??????/*?存儲報文的標準標識符?11?位,0-0x7FF?*/
??uint32_t?ExtId;??????/*?存儲報文的擴展標識符?29?位,0-0x1FFFFFFF?*/
??uint32_t?IDE;????????/*?存儲?IDE?擴展標志?*/
??uint32_t?RTR;????????/*?存儲?RTR?遠程幀標志?*/
??uint32_t?DLC;????????/*?存儲報文數(shù)據(jù)段的長度,0-8?*/
??FunctionalState?TransmitGlobalTime;?
}?CAN_TxHeaderTypeDef;

typedef?struct
{
??uint32_t?StdId;??????/*?存儲報文的標準標識符?11?位,0-0x7FF.?*/
??uint32_t?ExtId;??????/*?存儲報文的擴展標識符?29?位,0-0x1FFFFFFF?*/
??uint32_t?IDE;????????/*?存儲?IDE?擴展標志?*/
??uint32_t?RTR;????????/*?存儲?RTR?遠程幀標志?*/
??uint32_t?DLC;????????/*?存儲報文數(shù)據(jù)段的長度,0-8?*/
??uint32_t?Timestamp;?
??uint32_t?FilterMatchIndex;?
}?CAN_RxHeaderTypeDef;

? 過濾器結(jié)構(gòu)體:STM32CubeMX不會初始化過濾器的相關(guān)內(nèi)容,需要自己添加

typedef?struct
{
??uint32_t?FilterIdHigh;?????????/*CAN_FxR1?寄存器的高?16?位?*/
??uint32_t?FilterIdLow;??????????/*CAN_FxR1?寄存器的低?16?位?*/
??uint32_t?FilterMaskIdHigh;?????/*CAN_FxR2?寄存器的高?16?位?*/
??uint32_t?FilterMaskIdLow;??????/*CAN_FxR2?寄存器的低?16?位?*/
??uint32_t?FilterFIFOAssignment;?/*?設(shè)置經(jīng)過篩選后數(shù)據(jù)存儲到哪個接收?FIFO?*/
??uint32_t?FilterBank;???????????/*?篩選器編號,范圍0-27,CAN1是0-13,CAN2是14-27?*/
??uint32_t?FilterMode;???????????/*?篩選器模式?*/
??uint32_t?FilterScale;??????????/*?設(shè)置篩選器的尺度?*/
??uint32_t?FilterActivation;?????/*?是否使能本篩選器?*/
??uint32_t?SlaveStartFilterBank;?/*?CAN2起始過濾器組?*/
}?CAN_FilterTypeDef;

2.2 程序編寫

? 生成工程后,打開can.c文件,可見STM32CubeMX已經(jīng)對位時序參數(shù)、其他基本參數(shù)以及工作模式進行了初始化。但是并沒有初始化過濾器的相關(guān)內(nèi)容,因此需要我們自己添加,并在CAN初始化時調(diào)用

//下面的設(shè)置只使能了FIFO0,并不過濾任何消息
void?CAN_Filter_Config(){
? CAN_FilterTypeDef?sFilterConfig;
?
 ?sFilterConfig.FilterBank?=?0;??????//篩選器編號,?CAN1是0-13,?CAN2是14-27
 ?sFilterConfig.FilterMode?=?CAN_FILTERMODE_IDMASK;?//采用掩碼模式
 ?sFilterConfig.FilterScale?=?CAN_FILTERSCALE_32BIT;?//設(shè)置篩選器的尺度,?采用32位
 ?sFilterConfig.FilterIdHigh?=?0X0000;????//過濾器ID高16位,即CAN_FxR1寄存器的高16位
 ?sFilterConfig.FilterIdLow?=?0X0000;?????//過濾器ID低16位,即CAN_FxR1寄存器的低16位
 ?sFilterConfig.FilterMaskIdHigh?=?0X0000;???//過濾器掩碼高16位,即CAN_FxR2寄存器的高16位
 ?sFilterConfig.FilterMaskIdLow?=?0X0000;????//過濾器掩碼低16位,即CAN_FxR2寄存器的低16位
 ?sFilterConfig.FilterFIFOAssignment?=?CAN_RX_FIFO0;?//設(shè)置經(jīng)過篩選后數(shù)據(jù)存儲到哪個接收FIFO
? sFilterConfig.FilterActivation?=?ENABLE;???//是否使能本篩選器
? sFilterConfig.SlaveStartFilterBank?=?14;???//指定為CAN1分配多少個濾波器組
?
 ?if(HAL_CAN_ConfigFilter(&hcan1,?&sFilterConfig)?!=?HAL_OK)
? {
??  Error_Handler();
? }
}

? 編寫發(fā)送和接收數(shù)據(jù)函數(shù):此處將格式固定為標準數(shù)據(jù)幀,ID為12

uint8_t?CAN1_Send_Msg(uint8_t?*msg,?uint8_t?len){
? uint16_t?i?=?0;
? uint32_t?txMailBox;
? uint8_t?send_buf[8];
?
 ?txHeader.StdId?=?12;
 ?txHeader.ExtId?=?12;
? txHeader.IDE?=?CAN_ID_STD;
? txHeader.RTR?=?CAN_RTR_DATA;
? txHeader.DLC?=?len;
?
? for(i?=?0;?i?<?len;?i++)
??  send_buf[i]?=?msg[i];
?
? if(HAL_CAN_AddTxMessage(&hcan1,?&txHeader,?send_buf,?&txMailBox)?!=?HAL_OK)
??  return?1;?
? return?0;
}

void?HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef?*hcan){
? uint16_t?i?=?0;
? uint8_t?buf[8]?=?{0};
?
? if(hcan->Instance?==?CAN1){
??  printf("*******************************rn");
??  printf("Recv?via?STM32F429?Interruptrn");
?
??  HAL_CAN_GetRxMessage(&hcan1,?CAN_RX_FIFO0,?&rxHeader,?buf);
?
??  if(rxHeader.IDE?==?CAN_ID_STD)
???   printf("StdId?ID:?%dn",?rxHeader.StdId);
??  else
???   printf("ExtId?ID:?%dn",?rxHeader.ExtId);
??  printf("rn");
??  printf("CAN?IDE:?%dn",?rxHeader.IDE);printf("rn");
??  printf("CAN?RTR:?%dn",?rxHeader.RTR);printf("rn");
??  printf("CAN?DLC:?%dn",?rxHeader.DLC);printf("rn");
??  printf("Recv?Data:?");
?
??  for(i?=?0;?i?<?rxHeader.DLC;?i++)
???   printf("%c?",buf[i]);
?
??  printf("rn");
??  printf("*******************************rn");
? }
}

? 默認Cubemx生成的代碼并沒有can start,沒有調(diào)用HAL_CAN_Start(&hcan1) 來使能CAN,因此需要在CAN初始化代碼中添加

void?MX_CAN1_Init(void){
 ?......
 ?/*?USER?CODE?BEGIN?CAN1_Init?2?*/
 ?CAN_Filter_Config();
? HAL_CAN_Start(&hcan1);?
 ?HAL_CAN_ActivateNotification(&hcan1,?CAN_IT_RX_FIFO0_MSG_PENDING);
??/*?USER?CODE?END?CAN1_Init?2?*/
}

? 主函數(shù)main.c中,代碼如下

int?main(void){
??HAL_Init();
??SystemClock_Config();
??MX_GPIO_Init();
??MX_CAN1_Init();
??MX_USART1_UART_Init();
???/*?USER?CODE?BEGIN?2?*/
? uint8_t?ret;
? printf("CAN?Testing....!rn");
? uint8_t?txdata[8]?=?{78,?79,?82,?77,?65,?76,?33,?32};
??/*?USER?CODE?END?2?*/
??/*?Infinite?loop?*/
??/*?USER?CODE?BEGIN?WHILE?*/
??while?(1)
??{
??  HAL_GPIO_TogglePin(GPIOB,GPIO_PIN_1);
??  printf("Start?Send?data...rn");
??
??  ret?=?CAN1_Send_Msg(txdata,?8);
??  if(ret?==?0)
???   printf("STM32F429?CAN?Send?success!rn");
??  else?
???   printf("STM32F429?CAN?Send?failed!rn");
??
??  HAL_Delay(3000);
????/*?USER?CODE?END?WHILE?*/
????/*?USER?CODE?BEGIN?3?*/
??}
??/*?USER?CODE?END?3?*/
}

3. 下載測試

將CAN盒與STM32的CAN接口連接起來,CAN盒連接電腦,使用CAN調(diào)試軟件接收和發(fā)送數(shù)據(jù),如下圖示

STM32工程編譯無誤后,下載到開發(fā)板,可以看到系統(tǒng)運行時D1指示燈不斷閃爍,串口不斷的打印STM32發(fā)送CAN消息成功的信息。使用CAN調(diào)試軟件,可以看到CAN盒接收到了STM32發(fā)出的數(shù)據(jù)。使用調(diào)試軟件,發(fā)送CAN數(shù)據(jù)給STM32

串口調(diào)試助手中可以看到,STM32通過中斷接收到了CAN盒發(fā)來的數(shù)據(jù)

推薦器件

更多器件
器件型號 數(shù)量 器件廠商 器件描述 數(shù)據(jù)手冊 ECAD模型 風險等級 參考價格 更多信息
BCM5241A1IMLG 1 Broadcom Limited Ethernet Transceiver, PACKAGE
$3.42 查看
KSZ9031RNXIC 1 Microchip Technology Inc DATACOM, ETHERNET TRANSCEIVER

ECAD模型

下載ECAD模型
$8.98 查看
DP83848CVVX/NOPB 1 Texas Instruments Commercial temperature, 10/100-Mbps Ethernet PHY transceiver with SNI interface &amp; JTAG support 48-LQFP 0 to 70

ECAD模型

下載ECAD模型
$4.35 查看

相關(guān)推薦

電子產(chǎn)業(yè)圖譜

公眾號:嵌入式攻城獅;專注于分享和記錄嵌入式開發(fā)技術(shù),主要包含C語言、STM32、STM32CubeMX、lwIP、FreeRTOS、Linux、Zigbee、WIFI、BLE、LoRa、NB-loT、PCB電路設(shè)計、QT等等。