15.增改源代码,通过CAN通讯实现自定义协议的控制

15.增改源代码,通过CAN通讯实现自定义协议的控制

  • 已经实现的LED的闪烁来表达系统的运行状态。如果电机运行故障,则会相应的闪烁LED来指示故障信息。
  • 对于一个控制系统,应该有检测反馈,控制决策,动力执行。电机驱动是动力执行单元,受控于上层控制器。在常规的电机驱动控制中,有模拟量控制、232/485类的串口控制、CAN通讯控制、网络控制。现在采用can通讯的接口方式来控制。
  • CAN通讯,在调试的时候,有几点需要经常注意。CAN网络上面必须有接收节点,CAN消息才能被准确发送;CAN收发控制器,不同的芯片等,要注意波特率的配置确确实实是一致的;CAN的终端电阻也非常关键,应该让总线的两根线间电阻保持在120欧姆,这样才能让电压波形在总线上快速准确的建立。

 配置CAN通讯,还得遵照HAL库的方式来进行,虽然是手写代码来实现。新建了一个can.c.h文件块。
 做完这几个函数的配置后,再收发数据控制电机就非常容易了,就是基本的一些通讯概念。

1.使能CAN通讯
void MX_CAN_Init(u32 tsjw,u32 tbs1,u32 tbs2,u16 brp,u32 mode)
{

  CAN_FilterTypeDef  sFilterConfig;

  /*##-1- Configure the CAN peripheral #######################################*/
  CanHandle.Instance = CANx;

  CanHandle.Init.TimeTriggeredMode = DISABLE;
  CanHandle.Init.AutoBusOff = DISABLE;
  CanHandle.Init.AutoWakeUp = DISABLE;
  CanHandle.Init.AutoRetransmission = ENABLE;
  CanHandle.Init.ReceiveFifoLocked = DISABLE;
  CanHandle.Init.TransmitFifoPriority = DISABLE;
  CanHandle.Init.Mode =mode;// CAN_MODE_NORMAL;   //模式设置 
  CanHandle.Init.SyncJumpWidth =tsjw;// CAN_SJW_1TQ; //重新同步跳跃宽度(Tsjw)为tsjw+1个时间单位 CAN_SJW_1TQ~CAN_SJW_4TQ
  CanHandle.Init.TimeSeg1 = tbs1;//CAN_BS1_9TQ;  //tbs1范围CAN_BS1_1TQ~CAN_BS1_16TQ
  CanHandle.Init.TimeSeg2 = tbs2;//CAN_BS2_8TQ;   //tbs2范围CAN_BS2_1TQ~CAN_BS2_8TQ
  CanHandle.Init.Prescaler = brp;

  if (HAL_CAN_Init(&CanHandle) != HAL_OK)
  {
    /* Initialization Error */
    Error_Handler();
  }

  /*##-2- Configure the CAN Filter ###########################################*/
  sFilterConfig.FilterBank = 0;
  sFilterConfig.FilterMode = CAN_FILTERMODE_IDMASK;
  sFilterConfig.FilterScale = CAN_FILTERSCALE_32BIT;
  sFilterConfig.FilterIdHigh = 0x0000;   //32位ID
  sFilterConfig.FilterIdLow = 0x0000;
  sFilterConfig.FilterMaskIdHigh = 0x0000; //32位MASK
  sFilterConfig.FilterMaskIdLow = 0x0000;
  sFilterConfig.FilterFIFOAssignment = CAN_RX_FIFO0;  //过滤器0关联到FIFO0
  sFilterConfig.FilterActivation = ENABLE;  //激活滤波器0
  sFilterConfig.SlaveStartFilterBank = 14;

  if (HAL_CAN_ConfigFilter(&CanHandle, &sFilterConfig) != HAL_OK)
  {
    /* Filter configuration Error */
    Error_Handler();
  }

  /*##-3- Start the CAN peripheral ###########################################*/
  if (HAL_CAN_Start(&CanHandle) != HAL_OK)
  {
    /* Start Error */
    Error_Handler();
  }

  /*##-4- Activate CAN RX notification #######################################*/
  if (HAL_CAN_ActivateNotification(&CanHandle, CAN_IT_RX_FIFO0_MSG_PENDING) != HAL_OK)
  {
    /* Notification Error */
    Error_Handler();
  }

  /*##-5- Configure Transmission process #####################################*/
  TxHeader.StdId = 0x321;
  TxHeader.ExtId = 0x00;
  TxHeader.RTR = CAN_RTR_DATA;
  TxHeader.IDE = CAN_ID_STD;
  TxHeader.DLC = 8;
  TxHeader.TransmitGlobalTime = DISABLE;
}

 在这个初始化函数里,也将需要设置的波特率和工作模式通过参数传入进来。将CAN配置来工作在CAN 2.0A标准帧的工作方式,将标准帧ID先赋值一个数据。
 配置波特率的参数的时候,尤其要注意,can的时钟频率是多少。STM32 CAN 是与fclk1接在一起的,我的工程中,外接晶振是8M,系统主频是72M,fclk1的频率是36M的。

2.配置CAN通讯用到的引脚

使能can通讯后,在HAL库的模式下,还需要用一个回调函数的方式,将引脚进行配置使能。

/**
* @brief CAN MSP Initialization
* This function configures the hardware resources used in this example
* @param hcan: CAN handle pointer
* @retval None
*/
void HAL_CAN_MspInit(CAN_HandleTypeDef* hcan)
{
  GPIO_InitTypeDef GPIO_InitStruct = {0};
  if(hcan->Instance==CAN)
  {
  /* USER CODE BEGIN CAN_MspInit 0 */

  /* USER CODE END CAN_MspInit 0 */
    /* Peripheral clock enable */
    __HAL_RCC_CAN1_CLK_ENABLE();
  
    __HAL_RCC_GPIOA_CLK_ENABLE();
    /**CAN GPIO Configuration    
    PA11     ------> CAN_RX
    PA12     ------> CAN_TX 
    */
    GPIO_InitStruct.Pin = GPIO_PIN_11|GPIO_PIN_12;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
    GPIO_InitStruct.Alternate = GPIO_AF9_CAN;
    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

  /* USER CODE BEGIN CAN_MspInit 1 */

  /* USER CODE END CAN_MspInit 1 */
  }

}
3.发送数据函数

 编写can通讯发送消息的函数,传入要发送的数据消息的指针,要发送的数据长度,ID号。
 在实际传送消息的函数调用前,检查一下是否有空消息邮箱。如果没有的话,那消息邮箱表示已经满了,消息是不能被发送的。消息邮箱被占用完的很大原因,就是CAN总线不对,消息没有准备的被任一节点收到。
 TxMailbox可以自定义一个U16数就行,它是储存一下,现在用的是哪个消息邮箱进行的数据发送。

u8 CAN1_Send_Msg(u8* msg,u8 len,u16 StdId)
{	
  u16 i=0;
	
	TxHeader.StdId = StdId;
//  TxHeader.ExtId = ExtId;
//  TxHeader.RTR = CAN_RTR_DATA;
//  TxHeader.IDE = CAN_ID_STD;
  TxHeader.DLC = len;
     
	for(i=0;i<len;i++)
	TxData[i]=msg[i];
	
	while( HAL_CAN_GetTxMailboxesFreeLevel( &CanHandle ) == 0 );
		/* Start the Transmission process */
	if (HAL_CAN_AddTxMessage(&CanHandle, &TxHeader, TxData, &TxMailbox) != HAL_OK)
	{
		/* Transmission request Error */
		Error_Handler();
		return 1;     //发送
	}
	return 0;
}
4.消息接收

 没有使用中断的方式来接收can消息,而是轮询的方式。轮询的时候,检查FIFO中是否有消息在,有的话就取出来放到RxHeader里面去。

u8 CanReceiveMsg(void)
{		   		   
	  /* Get RX message */
  if (HAL_CAN_GetRxMessage(&CanHandle, CAN_RX_FIFO0, &RxHeader, RxData) != HAL_OK)
  {
    /* Reception Error */
    Error_Handler();
		return 0;
  }
	return 1;
}
  • 1
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值