基于stm32的can总线彻底研究
1、CAN總線的初始化
void can_init(void)
{
????? CAN_InitTypeDef??????? CAN_InitStructure;
????? CAN_FilterInitTypeDef? CAN_FilterInitStructure;
????? /* CAN register init */
????? CAN_DeInit();
????? CAN_StructInit(&CAN_InitStructure);
????
????? /* CAN cell init */
????? CAN_InitStructure.CAN_TTCM=DISABLE;//禁止時間觸發通信模式
????? CAN_InitStructure.CAN_ABOM=DISABLE;
????? CAN_InitStructure.CAN_AWUM=DISABLE;
????? CAN_InitStructure.CAN_NART=DISABLE;//CAN報文只被發送1次,不管發送的結果如何(成功、出錯或仲裁丟失)?
????? CAN_InitStructure.CAN_RFLM=DISABLE;
????? CAN_InitStructure.CAN_TXFP=DISABLE;
????? CAN_InitStructure.CAN_Mode=CAN_Mode_Normal;
????? //CAN_Mode_LoopBack
????? //CAN_Mode_Normal
????? CAN_InitStructure.CAN_SJW=CAN_SJW_1tq;
????? CAN_InitStructure.CAN_BS1=CAN_BS1_5tq;//1--16
????? CAN_InitStructure.CAN_BS2=CAN_BS2_2tq;//1--8
????? CAN_InitStructure.CAN_Prescaler=2;
????? CAN_Init(&CAN_InitStructure);
#ifdef can_id_filter
?????? /* CAN filter init */
????? CAN_FilterInitStructure.CAN_FilterNumber=0;//選擇過濾器0
????? CAN_FilterInitStructure.CAN_FilterMode=CAN_FilterMode_IdMask;//指定過濾器被設置為標識符屏蔽模式
????? CAN_FilterInitStructure.CAN_FilterScale=CAN_FilterScale_32bit;//給出過濾器位寬為32位
????? CAN_FilterInitStructure.CAN_FilterIdHigh=slave_id<<5;//過濾器標識符
????? CAN_FilterInitStructure.CAN_FilterIdLow=0x0000;//
????? CAN_FilterInitStructure.CAN_FilterMaskIdHigh=0xffff;//過濾器屏蔽標識符
????? CAN_FilterInitStructure.CAN_FilterMaskIdLow=0xfffc;
????? CAN_FilterInitStructure.CAN_FilterFIFOAssignment=0;//選擇FIFO0
????? CAN_FilterInitStructure.CAN_FilterActivation=ENABLE;//使能過濾器
????? CAN_FilterInit(&CAN_FilterInitStructure);//進入初始化函數
#else
????? /* CAN filter init */
????? CAN_FilterInitStructure.CAN_FilterNumber=0;//選擇過濾器0
????? CAN_FilterInitStructure.CAN_FilterMode=CAN_FilterMode_IdMask;//指定過濾器被設置為標識符屏蔽模式
????? CAN_FilterInitStructure.CAN_FilterScale=CAN_FilterScale_32bit;//給出過濾器位寬為32位
????? CAN_FilterInitStructure.CAN_FilterIdHigh=0x0000;//過濾器標識符
????? CAN_FilterInitStructure.CAN_FilterIdLow=0x0000;//
????? CAN_FilterInitStructure.CAN_FilterMaskIdHigh=0x0000;//過濾器屏蔽標識符
????? CAN_FilterInitStructure.CAN_FilterMaskIdLow=0x0000;
????? CAN_ITConfig(CAN_IT_FMP0, ENABLE);//使能指定的can中斷
}
?
?
void CAN_DeInit(void)
{
? /* Enable CAN reset state */
? RCC_APB1PeriphResetCmd(RCC_APB1Periph_CAN, ENABLE);
? /* Release CAN from reset state */
? RCC_APB1PeriphResetCmd(RCC_APB1Periph_CAN, DISABLE);
}
2、發送程序
unsigned?char?CAN_PushMessage(CAN_MSG? *pTransmitBuf )
{
? u8 TransmitMailbox=0;
? CanTxMsg TxMessage;
? if(pTransmitBuf -> LEN > 8)
? {
?????? return? 1;
? }
? /* transmit */
? TxMessage.StdId=pTransmitBuf ->StdId;//用來設定標準標識符(0-0x7ff,11位)
? TxMessage.ExtId=pTransmitBuf ->ExtId;
? TxMessage.RTR=? pTransmitBuf ->RTR;//設置RTR位為數據幀
? TxMessage.IDE=? pTransmitBuf ->IDE;//標識符擴展位,為標準幀
? TxMessage.DLC=? pTransmitBuf ->LEN;//設置數據長度
? //根據DLC字段的值,將有效數據拷貝到發送數據寄存器
? memcpy(TxMessage.Data, pTransmitBuf ->BUF,pTransmitBuf ->LEN);
? TransmitMailbox = CAN_Transmit(&TxMessage);
?// TxMessage.Data[1]=(data & 0xff00)>>8;
? return 1;
}
3、中斷接收程序
void USB_LP_CAN_RX0_IRQHandler(void)
{
? //清空can接收緩存
? CanRxMsg RxMessage;
? RxMessage.StdId=0x00;
? RxMessage.ExtId=0x00;
? RxMessage.IDE=0;
? RxMessage.DLC=0;
? RxMessage.FMI=0;//CAN過濾主控制寄存器
? memset( &RxMessage.Data[0],0,8);
? //can總線接收數據函數
? CAN_Receive(CAN_FIFO0, &RxMessage);
? //將接收到的數據寫于modbus的寄存器1
? //modbus_regester[1]=(RxMessage.Data[0]<<8)|(RxMessage.Data[1]);
?// if((RxMessage.StdId==slave_id) && (RxMessage.ExtId==0x00) && (RxMessage.IDE==CAN_ID_STD))
? {
??? //將can接收標志位置1,表示從卡應經接收到一個can報文
??? flag_can_recv=0;
??? memcpy(can_rx_data,&RxMessage.Data,RxMessage.DLC);
????? flag_can_recv=1;
? }
}
4、can總線的id過濾
對擴展數據幀過濾:
CAN_FilterInitStructure.CAN_FilterNumber???=?0;?
CAN_FilterInitStructure.CAN_FilterMode?????=?CAN_FilterMode_IdMask;?
CAN_FilterInitStructure.CAN_FilterScale????=?CAN_FilterScale_32bit;?
CAN_FilterInitStructure.CAN_FilterIdHigh?=?(((u32)CAN_ID<<3)&0xFFFF0000)>>16;?
CAN_FilterInitStructure.CAN_FilterIdLow=?(((u32)CAN_ID<<3)|CAN_ID_EXT|CAN_RTR_DATA)&0xFFFF;?
CAN_FilterInitStructure.CAN_FilterMaskIdHigh??=?0xFFFF;?
CAN_FilterInitStructure.CAN_FilterMaskIdLow???=?0xFFFF;?
對標準數據幀過濾:
CAN_FilterInitStructure.CAN_FilterIdHigh=?(((u32)CAN_ID0<<21)&0xFFFF0000)>>16;?
CAN_FilterInitStructure.CAN_FilterIdLow=(((u32)CAN_ID0<<21)|CAN_ID_STD|CAN_RTR_DATA)&0xFFFF;?
CAN_FilterInitStructure.CAN_FilterMaskIdHigh???=?0xFFFF;?
CAN_FilterInitStructure.CAN_FilterMaskIdLow????=?0xFFFF;?
假如要對標準遠程幀進行過濾,那么:
只需要將
CAN_FilterInitStructure.CAN_FilterIdLow=(((u32)CAN_ID0<<21)|CAN_ID_STD|CAN_RTR_DATA)&0xFFFF;?改成:
CAN_FilterInitStructure.CAN_FilterIdLow=(((u32)CAN_ID0<<21)|CAN_ID_STD|CAN_RTR_REMOTE)&0xFFFF;
5、can總線的幀格式
數據幀格式:
遠程幀格式:
6、can總線的邏輯電平
can總線的物理連接有兩根線:CANH和CANL,以差分的形式輸出。
(有的時候有地線,作為屏蔽線使用)
can總線的高電平?3.5v,表示邏輯0
can總線的低電平?1.5v,表示邏輯1
7、CAN總線的波特率計算
can時鐘是RCC_APB1PeriphClock,要注意CAN時鐘頻率?
CAN波特率?=?RCC_APB1PeriphClock/CAN_SJW CAN_BS1 CAN_BS2/CAN_Prescaler;?
如果CAN時鐘為8M,?CAN_SJW?=?1,CAN_BS1?=?8,CAN_BS2?=?7,CAN_Prescaler?=?2?
那么波特率就是=8M/(1 8 7)/2=250K?
8、can總線的仲裁機制
根據仲裁來判斷優先級:
??? (1)?若在同一時刻,標準格式的報文與擴展格式的報文同時搶占總線,且它們的基礎ID相同,則發標準格式的報文節點就會PK成功。這是因為擴展格式在基本ID后,緊接著是SRR位,與IDE位,且這兩位都是隱性位。而在標準格式中,這兩位分別對應的位為RTR與r1,其中RTR既可以為隱性位,也可以為顯性位,,但是r1必須為顯性位。由仲裁規則可以此時標準幀必定勝出。
????(2)??同理,如果在同一時刻,具有相同格式,且具有相同ID的數據幀與遠程幀爭奪總線控制權,那么數據幀必定勝出。因為RTR顯性表示數據幀,隱性表示遠程幀。
?
stm32的can總線的配置如下:
????? CAN_InitStructure.CAN_TTCM=DISABLE;//禁止時間觸發通信模式
????? CAN_InitStructure.CAN_ABOM=DISABLE;
????? CAN_InitStructure.CAN_AWUM=DISABLE;
????? CAN_InitStructure.CAN_NART=DISABLE;//CAN報文只被發送1次,不管發送的結果如何(成功、出錯或仲裁丟失)?
????? CAN_InitStructure.CAN_RFLM=DISABLE;
????? CAN_InitStructure.CAN_TXFP=DISABLE;
????? CAN_InitStructure.CAN_Mode=CAN_Mode_Normal;
????? //CAN_Mode_LoopBack
????? //CAN_Mode_Normal
????? CAN_InitStructure.CAN_SJW=CAN_SJW_1tq;
????? CAN_InitStructure.CAN_BS1=CAN_BS1_5tq;//1--16
????? CAN_InitStructure.CAN_BS2=CAN_BS2_2tq;//1--8
????? CAN_InitStructure.CAN_Prescaler=2;
????? CAN_Init(&CAN_InitStructure);
?????? /* CAN filter init */
????? CAN_FilterInitStructure.CAN_FilterNumber=0;//選擇過濾器0
????? CAN_FilterInitStructure.CAN_FilterMode=CAN_FilterMode_IdMask;//指定過濾器被設置為標識符屏蔽模式
????? CAN_FilterInitStructure.CAN_FilterScale=CAN_FilterScale_32bit;//給出過濾器位寬為32位
?
下面根據設置的參數不同來決定can總線can總線的配置情況:
1、對擴展數據幀進行過濾:(只接收擴展數據幀)
????? CAN_FilterInitStructure.CAN_FilterIdHigh?? = (((u32)slave_id<<3)&0xFFFF0000)>>16;
????? CAN_FilterInitStructure.CAN_FilterIdLow?? = (((u32)slave_id<<3)|CAN_ID_EXT|CAN_RTR_DATA)&0xFFFF;
????? CAN_FilterInitStructure.CAN_FilterMaskIdHigh? = 0xFFFF;
????? CAN_FilterInitStructure.CAN_FilterMaskIdLow?? = 0xFFFF;
(注:標準幀數據幀、標準遠程幀和擴展遠程幀均被過濾)
2、對擴展遠程幀過濾:(只接收擴展遠程幀)
????? CAN_FilterInitStructure.CAN_FilterIdHigh?? = (((u32)slave_id<<3)&0xFFFF0000)>>16;
????? CAN_FilterInitStructure.CAN_FilterIdLow?? = (((u32)slave_id<<3)|CAN_ID_EXT|CAN_RTR_REMOTE)&0xFFFF;
????? CAN_FilterInitStructure.CAN_FilterMaskIdHigh? = 0xFFFF;
????? CAN_FilterInitStructure.CAN_FilterMaskIdLow?? = 0xFFFF;
3、對標準遠程幀過濾:(只接收標準遠程幀)
????? CAN_FilterInitStructure.CAN_FilterIdHigh?? = (((u32)slave_id<<21)&0xffff0000)>>16;
????? CAN_FilterInitStructure.CAN_FilterIdLow?? = (((u32)slave_id<<21)|CAN_ID_STD|CAN_RTR_REMOTE)&0xffff;
????? CAN_FilterInitStructure.CAN_FilterMaskIdHigh? = 0xFFFF;
????? CAN_FilterInitStructure.CAN_FilterMaskIdLow?? = 0xFFFF;
4、對標準數據幀過濾:(只接收標準數據幀)
????? CAN_FilterInitStructure.CAN_FilterIdHigh?? = (((u32)slave_id<<21)&0xffff0000)>>16;
????? CAN_FilterInitStructure.CAN_FilterIdLow?? = (((u32)slave_id<<21)|CAN_ID_STD|CAN_RTR_DATA)&0xffff;
????? CAN_FilterInitStructure.CAN_FilterMaskIdHigh? = 0xFFFF;
????? CAN_FilterInitStructure.CAN_FilterMaskIdLow?? = 0xFFFF;
5、對擴展幀進行過濾:(擴展幀不會被過濾掉)
????? CAN_FilterInitStructure.CAN_FilterIdHigh?? = (((u32)slave_id<<3)&0xFFFF0000)>>16;
????? CAN_FilterInitStructure.CAN_FilterIdLow?? = (((u32)slave_id<<3)|CAN_ID_EXT)&0xFFFF;
????? CAN_FilterInitStructure.CAN_FilterMaskIdHigh? = 0xFFFF;
????? CAN_FilterInitStructure.CAN_FilterMaskIdLow?? = 0xFFFC;
6、對標準幀進行過濾:(標準幀不會被過濾掉)
????? CAN_FilterInitStructure.CAN_FilterIdHigh?? = (((u32)slave_id<<21)&0xffff0000)>>16;
????? CAN_FilterInitStructure.CAN_FilterIdLow?? = (((u32)slave_id<<21)|CAN_ID_STD)&0xffff;
????? CAN_FilterInitStructure.CAN_FilterMaskIdHigh? = 0xFFFF;
????? CAN_FilterInitStructure.CAN_FilterMaskIdLow?? = 0xFFFC;
注:slave_id為要過濾的id號。
總結
以上是生活随笔為你收集整理的基于stm32的can总线彻底研究的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: STM32之CAN---中断管理浅析
- 下一篇: 再谈STM32的CAN过滤器-bxCAN