一、CAN通信初始化
1、开时钟
//开时钟 APB1是42MHz时钟
RCC_APB1PeriphClockCmd(RCC_APB1Periph_CAN1, ENABLE);
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);
2、引脚复用
GPIO_PinAFConfig(GPIOA,GPIO_PinSource11,GPIO_AF_CAN1);
GPIO_PinAFConfig(GPIOA,GPIO_PinSource12,GPIO_AF_CAN1);
3、配置GPIO
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11 | GPIO_Pin_12;;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
4、CAN单元配置
CAN_InitTypeDef CAN_InitStructure;
//软件自动离线管理
CAN_InitStructure.CAN_ABOM = DISABLE;
//睡眠模式通过软件唤醒(清除CAN -> MCR 的 SLEEP位)
CAN_InitStructure.CAN_AWUM = DISABLE;
CAN_InitStructure.CAN_BS1 = CAN_BS1_5tq;
CAN_InitStructure.CAN_BS2 = CAN_BS2_6tq;
//模式设置:mode:0,普通模式;1,回环模式
CAN_InitStructure.CAN_Mode = CAN_Mode_LoopBack;
//禁止报文自动传送
CAN_InitStructure.CAN_NART = ENABLE;
//分频系数 (0—1023)+ 1
CAN_InitStructure.CAN_Prescaler = 6;
//报文不锁定,新的覆盖旧的
CAN_InitStructure.CAN_RFLM = DISABLE;
CAN_InitStructure.CAN_SJW = CAN_SJW_1tq;
//非时间触发通信模式
CAN_InitStructure.CAN_TTCM = DISABLE;
//优先级由报文标识符决定
CAN_InitStructure.CAN_TXFP = DISABLE;
CAN_Init(CAN1, &CAN_InitStructure);
5、配置过滤器
CAN_FilterInitTypeDef CAN_FilterInitStructure;
//激活过滤器0
CAN_FilterInitStructure.CAN_FilterActivation = ENABLE;
//过滤器0关联到 FIFO 0
CAN_FilterInitStructure.CAN_FilterFIFOAssignment = CAN_Filter_FIFO0;
//32位ID
CAN_FilterInitStructure.CAN_FilterIdHigh = 0x0000;
CAN_FilterInitStructure.CAN_FilterIdLow = 0x0000;
//32位MASk:不过滤任何ID,收到的所有ID都有效
CAN_FilterInitStructure.CAN_FilterMaskIdHigh = 0x00;
CAN_FilterInitStructure.CAN_FilterMaskIdLow = 0x00;
//屏蔽位模式
CAN_FilterInitStructure.CAN_FilterMode = CAN_FilterMode_IdMask;
//过滤器0
CAN_FilterInitStructure.CAN_FilterNumber = 0;
//32位宽
CAN_FilterInitStructure.CAN_FilterScale = CAN_FilterScale_32bit;
CAN_FilterInit(&CAN_FilterInitStructure);
6、配置NVIC
//FIFO 0 消息挂号中断允许
CAN_ITConfig(CAN1, CAN_IT_FMP0, ENABLE);
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_InitStructure.NVIC_IRQChannel = CAN1_RX0_IRQn;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;
NVIC_Init(&NVIC_InitStructure);
二、发送一个数组
//CAN发送一个数组(固定格式:ID为0x12,标准帧,数据帧)
void CanSendData(uint8_t *Array, uint8_t Length)
{
//发送邮箱ID
uint8_t MboxId;
uint16_t i = 0;
uint32_t TimeOut = 0xffff;
CanTxMsg TxMessage;
TxMessage.StdId = 0x12;
TxMessage.ExtId = 0x12;
TxMessage.IDE = CAN_Id_Standard;
TxMessage.RTR = CAN_RTR_DATA;
TxMessage.DLC = Length;
for(i = 0 ; i < Length; i++)
{
TxMessage.Data[i] = Array[i];
}
MboxId = CAN_Transmit(CAN1, &TxMessage);
i = 0 ;
while((CAN_TransmitStatus(CAN1, MboxId) == CAN_TxStatus_Failed) && (TimeOut == 0))
{
// i++;
// if(i > 0xfff)
// return;
TimeOut--;
}
}
三、查询接收
这里提供查询接收和中断接收两种方式
void CanReceiveData(void)
{
uint16_t i = 0;
uint32_t TimeOut = 0xffff;
CanRxMsg RxMessage;
if(CAN_MessagePending(CAN1, CAN_FIFO0) == 0)
return;
CAN_Receive(CAN1, CAN_FIFO0, &RxMessage);
for(i = 0; i < 8; i++)
{
Rxdata[i] = RxMessage.Data[i];
}
}
四、中断接收
void CAN1_RX0_IRQHandler(void)
{
CanRxMsg RxMessage;
uint8_t i = 0;
if(CAN_GetITStatus(CAN1, CAN_IT_FMP0) == SET)
{
CAN_ClearITPendingBit(CAN1, CAN_IT_FMP0);
CAN_Receive(CAN1, CAN_FIFO0, &RxMessage);
for(i = 0; i < 8; i++)
{
Rxdata[i] = RxMessage.Data[i];
}
}
}