CAN通信步骤详解

CAN通讯的实现步骤:

1.CAN初始化,其中包括:a.配置CAN时钟,配置IO;

                                          b.使能CAN中断向量;

                                          c.CAN硬件寄存器配置初始化;

                                          d.过滤器初始化;

                                          e.打开CAN中断。

2.CAN发送函数

3.CAN接收函数

4.中断函数

  依据上面的CAN通讯的实现步骤,开始编写代码,注意,我使用的是库函数。

一.CAN初始化

void CAN_Init(void)
{ 
    GPIO_InitTypeDef GPIO_InitStructure;
    NVIC_InitTypeDef NVIC_InitStructure;
    CAN_InitTypeDef CAN_InitStructure;
    CAN_FilterInitTypeDef CAN_FilterInitStructure;

    //1.配置CAN时钟和对应的IO时钟
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_CAN1,ENABLE);  //使能CAN1的时钟,注意:CAN1是挂载在APB1上,不要用错函数
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_AFIO,ENABLE);  //使能GPIO

    //2.初始化CAN1_Tx(PA12)和CAN1_Rx(PA11)的IO
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12;  //PA12 —>CAN1_Tx
    GIOP_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOA,&GPIO_InitStructure);  //初始化PA12
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11;  //PA11 -> CAN1_RX
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;  //上拉输入,注意:Rx必须使用上拉输入模式
    GPIO_Init(GPIOA,&GPIO_InitStructure);  //初始化PA11

    //3.使能中断向量
    NVIC_InitStructure.NVIC_IRQChannel = USB_LP_CAN1_RX0_IRQn;  //我这使用的是CAN1的接收中断,实际上,CAN1还有发送中断:USB_HP_CAN1_TX_IRQn。注意,CAN1中断是和USB是共用的,所以如果你打开了CAN1中断,就不能再用USB中断了。
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;   //抢占优先级 = 0
    NVIC_InitStructure.NVIC_IRQChannelPreemPreemptionPriority = 3;  //子优先级 = 3
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStructure);

    //4.CAN硬件寄存器配置初始化
    CAN_DeInit(CAN1);
    CAN_InitStructure.CAN_TTCM = DISABLE;//失能时间触发通讯模式
    CAN_InitStructure.CAN_ABOM = DISABLE;//失能自动离线管理模式
    CAN_InitStructure.CAN_AWUM = DISABLE;//失能自动唤醒模式
    CAN_InitStructure.CAN_NART = DISABLE;//失能非自动重传输模式
    CAN_InitStructure.CAN_RFLM = DISABLE;//失能接收FIFO锁定模式
    CAN_InitStructure.CAN_TXFP = DISABLE;//失能发送FIFO优先级
    CAN_InitStructure.CAN_Mode = CAN_Mode_Normal;//CAN硬件工作在正常模式;
    CAN_InitStructure.CAN_SJW = CAN_SJW_1tq;//重新同步跳跃宽度1个时间单位;
    CAN_InitStructure.CAN_BS1 = CAN_BS1_9tq;//时间段1为9个时间单位;
    CAN_InitStructure.CAN_BS2  = CAN_BS2_8tq;//时间段2为8个时间单位;
    CAN_InitStructure.CAN_Prescaler = 3;//1个时间单位的长度为3
    CAN_Init(CAN1&CAN_InitStructure);

    //5.过滤器初始化
    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;//过滤器标识符高段位:0x0000;
    CAN_FilterInitStructure.CAN_FIlterIdLow = 0x0000;//过滤器标识符低段位:0x0000;
    CAN_FilterInitStructure.CAN_FilterMaskIdHigh = 0x0000;//过滤器标识符高段位
    CAN_FilterInitStructure.CAN_FilterMaskIdLow = 0x0000;//过滤器屏蔽标识符低段位
    CAN_FilterInitStructure.CAN_FilterActivation = ENABLE;//使能过滤器
    CAN_FilterInitStructure.CAN_FilterFIFOAssignment = CAN_FIlterFIFO0;//指向过滤器的FIFO0;
    CAN_FilterInit(&CAN_FilterInitStructe);

    //6.打开CAN中断
    CAN_ITConfig(CAN1,CAN_IT_FMP0,ENABLE)//FIFO0消息挂号中断屏蔽
}
 
  

二.CAN发送函数

void can_SendData(CanTxMsg* TxMessage)
{
    unsigned char i = 0;
 
    unsigned char TransmitMailbox;
  
    TransmitMailbox = CAN_Transmit(CAN1,TxMessage);//发送数据,返回邮箱号

   while((CAN_TransmitStatus(CAN1,TransmitMailbox) != CANTXOK)&&(i != 0xff))
   {
        //查看是否发送完成
    i++;
   }

   i = 0;
 
   while((CAN_MessagePendding(CAN1,CAN_FIFO0)<1)&&(i != 0xff)) 
   {
        //查看被挂起的报文是否为0
     i++;
   }
 
}

三.接收数据

     今天不想写。。。。迟点补上蛤~~~~

四.中断函数

CanRxMsg RxMessage;

void USB_LP_CAN1_RX0_IRQHandler(void)
{
    CAN_Receive(CAN1,CAN_FIFO0,&RxMessage);//接收数据,存储到RxMessage中

    。。。。。//自行脑补
}

因为我这篇文章是自己一个一个字敲进去的,可能会出现单词拼写错误~~~~~

欢迎指错蛤~~~~~~

你可能感兴趣的:(单片机,stm32,嵌入式硬件)