单片机学习小组
直播中

靓仔峰

9年用户 1144经验值
擅长:可编程逻辑
私信 关注

STM32F407 CubeMX如何配置CAN实现简单的发送接收?

STM32F407 CubeMX如何配置CAN实现简单的发送接收?

回帖(1)

蒋美燕

2022-2-7 16:17:42
时钟配置

  时钟配置没什么特别的 外部晶振频率为25MHz
引脚配置


  PE0连接到TJA1050的8脚上,使用时固定输出低电平即可。
MX CAN配置


  修改了时序参数和使能了自动总线管理,其他的都为默认设置

代码
配置完成后,生成代码。生成的代码没有进行过滤器配置,需要自己添加过滤器配置代码。


在MX_CAN1_Init()中添加过滤器配置代码
为了方便测试,只使用FIFO0,过滤器使用掩码模式,配置为允许所有消息通过(相当于不过滤)


void MX_CAN1_Init(void)
{


  /* USER CODE BEGIN CAN1_Init 0 */
  CAN_FilterTypeDef Filter;




  /* USER CODE END CAN1_Init 0 */


  /* USER CODE BEGIN CAN1_Init 1 */


  /* USER CODE END CAN1_Init 1 */
  hcan1.Instance = CAN1;
  hcan1.Init.Prescaler = 30;
  hcan1.Init.Mode = CAN_MODE_NORMAL;
  hcan1.Init.SyncJumpWidth = CAN_SJW_2TQ;
  hcan1.Init.TimeSeg1 = CAN_BS1_8TQ;
  hcan1.Init.TimeSeg2 = CAN_BS2_5TQ;
  hcan1.Init.TimeTriggeredMode = DISABLE;
  hcan1.Init.AutoBusOff = ENABLE;
  hcan1.Init.AutoWakeUp = DISABLE;
  hcan1.Init.AutoRetransmission = DISABLE;
  hcan1.Init.ReceiveFifoLocked = DISABLE;
  hcan1.Init.TransmitFifoPriority = DISABLE;
  if (HAL_CAN_Init(&hcan1) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN CAN1_Init 2 */


  //过滤器0
  Filter.FilterIdHigh=0;//由于掩码全0 此段没什么用 随便给一个数
  Filter.FilterIdLow=0;//由于掩码全0 此段没什么用 随便给一个数
  Filter.FilterMaskIdHigh=0;//全0 不对比任何位
  Filter.FilterMaskIdLow=0;//全0 不对比任何位
  Filter.SlaveStartFilterBank=14;//此段配置CAN1与CAN2使用的过滤器 0~13为CAN1使用 14~...为CAN2使用
  Filter.FilterScale=CAN_FILTERSCALE_32BIT;//32Bit
  Filter.FilterMode=CAN_FILTERMODE_IDMASK;//掩码模式
  Filter.FilterBank=0;//过滤器0
  Filter.FilterFIFOAssignment=CAN_FilterFIFO0;//使用FIFO0
  Filter.FilterActivation=CAN_FILTER_ENABLE;//使能过滤器


  HAL_CAN_ConfigFilter(&hcan1,&Filter);//将Filter的配置设置到hcan1


  HAL_CAN_Start(&hcan1);//启动hcan1


  /* USER CODE END CAN1_Init 2 */


}


在main.c中添加发送接收代码
为了方便测试,我没有打开CAN的中断,使用在死循环里进行轮询的方式,每秒发送一个数据包,接收到数据包后把接收到的数据更新到CAN_RIxR,CAN_RDTxR和CAN_Data中


/* USER CODE BEGIN 0 */
//接收到的数据储存到下面的变量中
volatile unsigned int CAN_RIxR;
volatile unsigned int CAN_RDTxR;
volatile unsigned int CAN_Data[2];
/* USER CODE END 0 */


/**
  * @brief  The application entry point.
  * @retval int
  */
int main(void)
{
  /* USER CODE BEGIN 1 */
  unsigned int lastT;
  /* USER CODE END 1 */


  /* MCU Configuration--------------------------------------------------------*/


  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();


  /* USER CODE BEGIN Init */


  /* USER CODE END Init */


  /* Configure the system clock */
  SystemClock_Config();


  /* USER CODE BEGIN SysInit */


  /* USER CODE END SysInit */


  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_CAN1_Init();
  /* USER CODE BEGIN 2 */


  /* USER CODE END 2 */


  /* Infinite loop */
  /* USER CODE BEGIN WHILE */


  lastT=(int)HAL_GetTick();//更新lastT


  while (1)
  {
    /* USER CODE END WHILE */


    /* USER CODE BEGIN 3 */


    //间隔1000ms调用if里面的代码一次,即使溢出也不会影响结果。除非等待时间超过0x7FFFFFFF(谁会要求间隔那么久)
    if((HAL_GetTick()-lastT)>999){
      lastT+=1000;
       
      //每1000ms执行到这里一次
      if((hcan1.Instance->sTxMailBox[0].TIR&CAN_TI0R_TXRQ)==0){//邮箱0是否空


        hcan1.Instance->sTxMailBox[0].TDLR=0x20000607;//低4字节数据(低位先发送) 低4字节先发送
        hcan1.Instance->sTxMailBox[0].TDHR=0x9DEFA478;//高4字节数据(低位先发送)
        hcan1.Instance->sTxMailBox[0].TDTR=8;//发送8字节
        
        hcan1.Instance->sTxMailBox[0].TIR=0x40000000;//ID IDE RTR 等 详见数据手册,使用两个板子相互通信时 建议ID/EXID设置为不同值


        hcan1.Instance->sTxMailBox[0].TIR|=CAN_TI0R_TXRQ;//触发发送请求
      }


    }


        //检测FIFO0是否有数据
    if((hcan1.Instance->RF0R&CAN_RF0R_FMP0)!=0){


      //读取接收的数据 数据布局与发送邮箱类似
      CAN_RIxR=hcan1.Instance->sFIFOMailBox[0].RIR;
      CAN_RDTxR=hcan1.Instance->sFIFOMailBox[0].RDTR;
      CAN_Data[0]=hcan1.Instance->sFIFOMailBox[0].RDLR;
      CAN_Data[1]=hcan1.Instance->sFIFOMailBox[0].RDHR;


      hcan1.Instance->RF0R|=CAN_RF0R_RFOM0;
    }


  }
  /* USER CODE END 3 */
}


测试
测试很方便,两个一样的板子,下一样的程序(仅hcan1.Instance->sTxMailBox[0].TIR的ID不同),将两个板子的CANH,CANL,连在一起。使用stlink(其他调试器也行)对其中一个板子测试,在读取接收数据那部分代码上打一个断点,即可知道有没有正常接收到数据,并且可查看接收到的数据是否正确。


调试问题
调试时发现通信并没有成功,查看CAN1->ESR寄存器,发现其中的TEC段一直在增加,错误代码LEC为0x3。然后调试另一个板子,TEC段也是一直在增加,但不同的是LEC为0x5,查手册得知这是位显性错误,然后检查板子发现单片机上的
CAN1_TX(PB9)虚焊了,补焊后程序运行就正常了。
举报

更多回帖

发帖
×
20
完善资料,
赚取积分