×
单片机 > 单片机程序设计 > 详情

STM32_MDK_bxCAN

发布时间:2020-05-19 发布时间:
|
今天整理下CAN方面的资料,首先使用的是stm32f103vet6,只有一个CAN(2.0A & 2.0B)。CAN本身是工作的数据链路层的总线,有很多优势就不再一一介绍了,随便买本书看看都有。

基础的CAN的知识就不赘述了,这些是必要的可以自己去买书了解,现在来看下STM32下对CAN的驱动,STM32本身包括了CAN的数据链路层,然后物理层就是CAN收发器用的是TJA1050,是非容错CAN。终端电阻用120欧姆。

说道CAN最主要的是CAN的初始化,他包括两个主要的部分,一个是基本属性的声明,另一部分就是过滤器的设置。见如下代码:


/*******************************************************************************
* Function Name  : bxCAN_Port_Configuration
* Description    : CAN端口设置
* Input          : None
* Output         : None
* Return         : None
*******************************************************************************/
void bxCAN_Port_Configuration(void)
{
 GPIO_InitTypeDef GPIO_InitStructure_bxCAN;

 GPIO_PinRemapConfig(GPIO_Remap1_CAN1 , ENABLE);           //端口复用为CAN1
 
 GPIO_InitStructure_bxCAN.GPIO_Pin = GPIO_Pin_8;              //PB8:CAN-RX
    GPIO_InitStructure_bxCAN.GPIO_Mode = GPIO_Mode_IPU;    //输入上拉
 GPIO_InitStructure_bxCAN.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOB, &GPIO_InitStructure_bxCAN);
 
   GPIO_InitStructure_bxCAN.GPIO_Pin = GPIO_Pin_9;        //PB9:CAN-TX
   GPIO_InitStructure_bxCAN.GPIO_Mode = GPIO_Mode_AF_PP;      //复用模式
   GPIO_InitStructure_bxCAN.GPIO_Speed = GPIO_Speed_50MHz;
   GPIO_Init(GPIOB, &GPIO_InitStructure_bxCAN);
}

/*******************************************************************************
* Function Name  : bxCAN_Property_Configuration
* Description    : CAN配置具体属性
* Input          : None
* Output         : None
* Return         : None
*******************************************************************************/
void bxCAN_Property_Configuration(void)
{
 CAN_InitTypeDef        CAN_InitStructure;
   CAN_FilterInitTypeDef  CAN_FilterInitStructure;

  /* CAN register init */
   CAN_DeInit(CAN1);
   CAN_StructInit(&CAN_InitStructure);

  /* CAN cell init */
   CAN_InitStructure.CAN_TTCM=DISABLE;         //MCR-TTCM   禁止时间触发通信模式 
   CAN_InitStructure.CAN_ABOM=DISABLE;   //MCR-ABOM   禁止自动离线管理
   CAN_InitStructure.CAN_AWUM=DISABLE;   //MCR-AWUM   通过清除CAN_MCR_SLEEP位进入自动唤醒模式
   CAN_InitStructure.CAN_NART=DISABLE;   //MCR-NART   禁止报文自动重传   0-自动重传   1-报文只传一次
   CAN_InitStructure.CAN_RFLM=DISABLE;   //MCR-RFLM   接收FIFO 锁定模式  0-溢出时新报文会覆盖原有报文  1-溢出时,新报文丢弃
   CAN_InitStructure.CAN_TXFP=DISABLE;   //MCR-TXFP   发送FIFO优先级 0-优先级取决于报文标示符 1-优先级取决于发送请求的顺序
   CAN_InitStructure.CAN_Mode=CAN_Mode_LoopBack; //BTR-SILM/LBKM   CAN环回模式  
//  CAN_InitStructure.CAN_Mode=CAN_Mode_Normal; //         CAN正常模式
   CAN_InitStructure.CAN_SJW=CAN_SJW_1tq;      //BTR-SJW 重新同步跳跃宽度 1个时间单元
   CAN_InitStructure.CAN_BS1=CAN_BS1_2tq;   //BTR-TS1 时间段1 占用了2个时间单元
   CAN_InitStructure.CAN_BS2=CAN_BS2_3tq;   //BTR-TS1 时间段2 占用了3个时间单元

 #if   CAN_BAUDRATE == 1000 /* 1MBps   */  //BTR-BRP 波特率分频器  定义了时间单元的时间长度 36/(1+2+3)/6=1Mbps
    CAN_InitStructure.CAN_Prescaler = 6;     
  #elif CAN_BAUDRATE == 500  /* 500KBps */
    CAN_InitStructure.CAN_Prescaler = 12;
  #elif CAN_BAUDRATE == 250  /* 250KBps */
   CAN_InitStructure.CAN_Prescaler = 24;
  #elif CAN_BAUDRATE == 125  /* 125KBps */
   CAN_InitStructure.CAN_Prescaler = 48;
 #elif CAN_BAUDRATE == 100  /* 100KBps */
     CAN_InitStructure.CAN_Prescaler = 60;
 #elif CAN_BAUDRATE == 50   /* 50KBps  */
     CAN_InitStructure.CAN_Prescaler = 120;
   #elif CAN_BAUDRATE == 20   /* 20KBps  */
    CAN_InitStructure.CAN_Prescaler = 300;
   #elif CAN_BAUDRATE == 10   /* 10KBps  */
    CAN_InitStructure.CAN_Prescaler = 600;
   #endif
   CAN_Init(CAN1, &CAN_InitStructure);       //初始化CAN寄存器

  /* CAN filter init */
   CAN_FilterInitStructure.CAN_FilterNumber=1;         // 选择过滤器编号
   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;   // 标识符屏蔽位,1:必须匹配,0:不用关心
   CAN_FilterInitStructure.CAN_FilterMaskIdLow=0x0000;
   CAN_FilterInitStructure.CAN_FilterFIFOAssignment=CAN_FIFO0;     // 选择存放在关联的FIFO为FIFO0
   CAN_FilterInitStructure.CAN_FilterActivation=ENABLE;   // 激活过滤器
   CAN_FilterInit(&CAN_FilterInitStructure);      // 初始化过滤器

  /* CAN FIFO0 message pending interrupt enable */
   CAN_ITConfig(CAN1, CAN_IT_FMP0, ENABLE);      // 设置CAN1,FIFO0接收中断使能
//  CAN_ITConfig(CAN1, CAN_IT_FMP0, DISABLE);
}

/*******************************************************************************
* Function Name  : bxCAN_Configuration
* Description    : CAN初始化
* Input          : None
* Output         : None
* Return         : None
*******************************************************************************/
void bxCAN_Configuration(void)
{
 bxCAN_Port_Configuration();
 bxCAN_Property_Configuration();
}

/*******************************************************************************
* Function Name  : Interrupt_Handle_bxCAN
* Description    : 中断服务函数
* Input          : None
* Output         : None
* Return         : None
*******************************************************************************/
void Interrupt_Handle_bxCAN(void)
{
 CanRxMsg RxMessage;

   RxMessage.StdId=0x00;
  RxMessage.ExtId=0x00;
 RxMessage.IDE=0;
  RxMessage.DLC=0;
  RxMessage.FMI=0;
  RxMessage.Data[0]=0x00;
  RxMessage.Data[1]=0x00;

   CAN_Receive(CAN1, CAN_FIFO0, &RxMessage);
}

初始化第一部分基本属性设置,要看下datasheet中,CAN的发送流程和接受流程,然后看下他相关的状态寄存器就知道其意义了。在过滤器设置部分,要理解他两种模式的不同之处,屏蔽位模式就是给出 一个参考值然后用屏蔽属性去匹配,列表模式就是直接根据寄存器的参考值进行全匹配。这里对屏蔽位我也没有做特殊的设置,就设置全部接受。
本历程只实现了发送标准帧,扩展帧,接受帧数据。
接收程序使用中断方式,见上面代码函数Interrupt_Handle_bxCAN(),发送代码如下:


void Send_Std_KLS_KL15(unsigned char value)
{
CanTxMsg TxMessage;

TxMessage.StdId=0x570;
TxMessage.IDE=CAN_ID_STD;
TxMessage.RTR=CAN_RTR_DATA;
TxMessage.DLC=8;
TxMessage.Data[0]=value;
TxMessage.Data[1]=0x00;
TxMessage.Data[2]=0x00;
TxMessage.Data[3]=0x00;
TxMessage.Data[4]=0x00;
TxMessage.Data[5]=0x00;
TxMessage.Data[6]=0x00;
TxMessage.Data[7]=0x00;

CAN_Transmit(CAN1, &TxMessage);
}

这个是发送一个标准帧,如果发送扩展帧 如下:


void Send_Exd_message(void)
{
CanTxMsg TxMessage;

TxMessage.StdId=0x0000;
TxMessage.ExtId=0x1234;
TxMessage.IDE=CAN_ID_EXT;
TxMessage.RTR=CAN_RTR_DATA;
TxMessage.DLC=2;
TxMessage.Data[0]=0xDE;
TxMessage.Data[1]=0xCA;
CAN_Transmit(CAN1, &TxMessage);
}

由于CAN透明化了数据链路层,所以在实际应用中只要用好屏蔽位就能够高效的使用CAN网络。
关键字:STM32  MDK  bxCAN 

『本文转载自网络,版权归原作者所有,如有侵权请联系删除』

热门文章 更多
8051单片机的函数发生器的设计