1.CAN设备时钟赋能和GPIO口时钟赋能
GPIO_InitTypeDef GPIO_InitStrcture;
CAN_InitTypeDef CAN_InitStrcture;
CAN_FilterInitTypeDef CAN_FilterInitStrcture;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_CAN1,ENABLE);
2.GPIO口初始化,PA12为TX设置为复用推挽输出,PA11为RX设置为上拉输入。
GPIO_InitStrcture.GPIO_Mode=GPIO_Mode_AF_PP;
GPIO_InitStrcture.GPIO_Pin=GPIO_Pin_12;
GPIO_InitStrcture.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_Init(GPIOA,&GPIO_InitStrcture);
GPIO_InitStrcture.GPIO_Mode=GPIO_Mode_IPU;
GPIO_InitStrcture.GPIO_Pin=GPIO_Pin_11;
GPIO_InitStrcture.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_Init(GPIOA,&GPIO_InitStrcture);
3.CAN设备的初始化,CAN设备和其他设备的区别是没有CMD函数来驱动CAN设备,只需要初始化即可
//配置CAN设备
//CAN_InitTypeDef CAN_InitStrcture;
CAN_InitStrcture.CAN_Mode=CAN_Mode_LoopBack;//环回模式,CAN发出的报文自己接收且发送到主线上
CAN_InitStrcture.CAN_Prescaler=48; //波特率=36M/48/(1+2+3)=125k
CAN_InitStrcture.CAN_BS1=CAN_BS1_2tq;
CAN_InitStrcture.CAN_BS2=CAN_BS2_3tq;
CAN_InitStrcture.CAN_SJW=CAN_SJW_2tq;
CAN_InitStrcture.CAN_NART=DISABLE;//置1,关闭自动重传,CAN报文只被发送1次,不管发送的结果如何(成功、出错或仲裁丢失);置0,自动重传,CAN硬件在发送报文失败时会一直自动重传直到发送成功
CAN_InitStrcture.CAN_TXFP=DISABLE;//置1,优先级由发送请求的顺序来决定,先请求的先发送;置0,优先级由报文标识符来决定,标识符值小的先发送(标识符值相等时,邮箱号小的报文先发送)
CAN_InitStrcture.CAN_RFLM=DISABLE;//置1,接收FIFO锁定,FIFO溢出时,新收到的报文会被丢弃;置0,禁用FIFO锁定,FIFO溢出时,FIFO中最后收到的报文被新报文覆盖
CAN_InitStrcture.CAN_AWUM=DISABLE;//置1,自动唤醒,一旦检测到CAN总线活动,硬件就自动清零SLEEP,唤醒CAN外设;置0,手动唤醒,软件清零SLEEP,唤醒CAN外设
CAN_InitStrcture.CAN_TTCM=DISABLE;
CAN_InitStrcture.CAN_ABOM=DISABLE;
CAN_Init(CAN1,&CAN_InitStrcture);
4.配置CAN的过滤器
//配置CAN的过滤器
//CAN_FilterInitTypeDef CAN_FilterInitStrcture;
CAN_FilterInitStrcture.CAN_FilterNumber=0;//选择使用哪一个过滤器
CAN_FilterInitStrcture.CAN_FilterIdHigh=0x0000;//R1高16位,这里选择屏蔽模式,全ID通过
CAN_FilterInitStrcture.CAN_FilterIdLow=0x0000;//R1低16位
CAN_FilterInitStrcture.CAN_FilterMaskIdHigh=0x0000;//R2高16位
CAN_FilterInitStrcture.CAN_FilterMaskIdLow=0x0000;//R2低16位
CAN_FilterInitStrcture.CAN_FilterScale=CAN_FilterScale_32bit;//过滤器位宽
CAN_FilterInitStrcture.CAN_FilterMode=CAN_FilterMode_IdMask;//屏蔽模式
CAN_FilterInitStrcture.CAN_FilterActivation=ENABLE;//激活过滤器
CAN_FilterInitStrcture.CAN_FilterFIFOAssignment=CAN_Filter_FIFO0;//选择报文存入哪一个FIFO中
CAN_FilterInit(&CAN_FilterInitStrcture);
5.CAN设备发送函数
使用函数传递结构体数值
void MyCAN_Transmit(uint32_t ID,uint8_t Length,uint8_t *Data)
{
uint8_t i;
uint8_t TransmitMailbox;
uint32_t time;
CanTxMsg TxMessage;
TxMessage.StdId=ID;//标准模式时有用
TxMessage.ExtId=ID;//扩展模式时有用
TxMessage.IDE=CAN_Id_Standard;//标准模式
TxMessage.RTR=CAN_RTR_Data;//数据报文
TxMessage.DLC=Length;
for(i=0;i<Length;i++)
{
TxMessage.Data[i]=Data[i];
}
TransmitMailbox =CAN_Transmit(CAN1,&TxMessage);//接收CAN_Transmit此方法返回的值,代表哪个邮箱接收数据
while(CAN_TransmitStatus(CAN1,TransmitMailbox) !=CAN_TxStatus_Ok)//等待发送成功
{
time++;
if(time>100000)
{
break;
}
}
}
6.判断FIFO 0 是否接收到数据报文
CAN_MessagePending此函数返回0表示FIFO 0 和1 都没收到报文
uint8_t MyCAN_ReceiveFlag(void)//判断FIFO 0是否接收到报文
{
if(CAN_MessagePending(CAN1,CAN_FIFO0)>0)
{
return 1;
}
return 0;
}
7.CAN设备接收函数
void MyCAN_Receive(uint32_t *ID,uint8_t *Length,uint8_t *Data)
{
CanRxMsg RxMessage;
CAN_Receive(CAN1,CAN_FIFO0,&RxMessage);//将CAN1中FIFO 0接收到的报文数据读出到RxMessage
if(RxMessage.IDE == CAN_Id_Standard)//判断是否是标准模式
{
*ID=RxMessage.StdId;
}
else
{
*ID=RxMessage.ExtId;
}
if(RxMessage.RTR == CAN_RTR_Data)//判断是否是数据报文,如果是数据报文则接收数据
{
uint8_t i;
*Length=RxMessage.DLC;
for(i=0;i<*Length;i++)
{
Data[i]=RxMessage.Data[i];
}
}
}
8.主函数
uint8_t KeyNum;
uint32_t TxID=0x55;
uint8_t TxLength=4;
uint8_t TxData[8]={0x11,0x22,0x33,0x44};
uint32_t RxID;
uint8_t RxLength;
uint8_t RxData[8];
int main(void)
{
OLED_ShowString(1,1,"TxID:");
OLED_ShowHexNum(2,6,TxID,3);
OLED_ShowString(2,1,"RxID:");
OLED_ShowString(3,1,"Length:");
OLED_ShowString(4,1,"Data:");
while(1)
{
KeyNum = Key_Number();
if(KeyNum == 1)
{
TxData[0]++;
TxData[1]++;
TxData[2]++;
TxData[3]++;
MyCAN_Transmit(TxID,TxLength,TxData);
}
if(MyCAN_ReceiveFlag()==1)//判断是否接收到数据
{
MyCAN_Receive(&RxID,&RxLength,RxData);
OLED_ShowHexNum(2,6,RxID,3);
OLED_ShowHexNum(3,6,RxLength,1);
OLED_ShowHexNum(4,6,RxData[0],2);
OLED_ShowHexNum(4,9,RxData[1],2);
OLED_ShowHexNum(4,12,RxData[2],2);
OLED_ShowHexNum(4,15,RxData[3],2);
}
}
}