1、CAN总线的初始化
{
CAN_InitTypeDef CAN_InitStructure;
CAN_FilterInitTypeDef CAN_FilterInitStructure;
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中止
}
{
/* Enable CAN reset state */
RCC_APB1PeriphResetCmd(RCC_APB1Periph_CAN, ENABLE);
/* Release CAN from reset state */
RCC_APB1PeriphResetCmd(RCC_APB1Periph_CAN, DISABLE);
}
{
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;
}
{
//清空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;
}
对扩展数据帧过滤:
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显性表明数据帧,隐性表明长途帧。
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_FilterInitStructure.CAN_FilterNumber=0;//挑选过滤器0
CAN_FilterInitStructure.CAN_FilterMode=CAN_FilterMode_IdMask;//指定过滤器被设置为标识符屏蔽方式
CAN_FilterInitStructure.CAN_FilterScale=CAN_FilterScale_32bit;//给出过滤器位宽为32位
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;
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;
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号。