基于canfestival的canopen控制

发布于 2022-07-04  551 次阅读


相关文件(包含源码和python小工具)

软件定时器移植及配置


#ifndef __TIMERSCFG_H__
#define __TIMERSCFG_H__

// Whatever your microcontroller, the timer wont work if
// TIMEVAL is not at least on 32 bits
#define TIMEVAL UNS32

// using 16 bits timer
#define TIMEVAL_MAX 0xFFFF

// The timer is incrementing every 10 us.
#define MS_TO_TIMEVAL(ms) ((ms)*10)
#define US_TO_TIMEVAL(us) ((us)/100)

#endif
/* TIM3 init function */
void MX_TIM3_Init(void)
{

  /* USER CODE BEGIN TIM3_Init 0 */

  /* USER CODE END TIM3_Init 0 */

  TIM_ClockConfigTypeDef sClockSourceConfig = {0};
  TIM_MasterConfigTypeDef sMasterConfig = {0};
  TIM_OC_InitTypeDef sConfigOC = {0};

  /* USER CODE BEGIN TIM3_Init 1 */

  /* USER CODE END TIM3_Init 1 */
  htim3.Instance = TIM3;
  htim3.Init.Prescaler = 8400-1;
  htim3.Init.CounterMode = TIM_COUNTERMODE_UP;
  htim3.Init.Period = 0xFFFF;
  htim3.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
  htim3.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_ENABLE;
  if (HAL_TIM_Base_Init(&htim3) != HAL_OK)
  {
    Error_Handler();
  }
  sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;
  if (HAL_TIM_ConfigClockSource(&htim3, &sClockSourceConfig) != HAL_OK)
  {
    Error_Handler();
  }
  if (HAL_TIM_OC_Init(&htim3) != HAL_OK)
  {
    Error_Handler();
  }
  sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
  sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
  if (HAL_TIMEx_MasterConfigSynchronization(&htim3, &sMasterConfig) != HAL_OK)
  {
    Error_Handler();
  }
  sConfigOC.OCMode = TIM_OCMODE_TIMING;
  sConfigOC.Pulse = 49152;
  sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;
  sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;
  if (HAL_TIM_OC_ConfigChannel(&htim3, &sConfigOC, TIM_CHANNEL_1) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN TIM3_Init 2 */

  /* USER CODE END TIM3_Init 2 */

}

//协议栈启动时,开启硬件定时器
void StartTimerLoop(TimerCallback_t _init_callback) 
{
	init_callback = _init_callback;
	
	setNodeId(OD_Data, 0x01);
	setState(OD_Data, Initialisation);
	setState(OD_Data, Operational);
	osTimerStart(PDOeventTime,10);
	
	SetAlarm(OD_Data, 0, init_callback, MS_TO_TIMEVAL(2000), 0);
	
	/* 在中断模式下启动定时器 */
	if(htimx_can == NULL)
	{
		#if (USER_DEBUG)
		printf("htimx_can is NULL, need init a timer\n");
		#endif
	}
	else
	{
		HAL_TIM_OC_Start_IT(htimx_can,TIM_CHANNEL_1);
	}
}

/** 函数名:setTimer
  * 功能	:设置定时时间
  * 输入	:
	* 输出	:
	* 编写人:XMW
  */
void setTimer(TIMEVAL value)
{
	uint16_t capture = 0;

	capture = __HAL_TIM_GET_COMPARE(htimx_can,TIM_CHANNEL_1);
	__HAL_TIM_SET_COMPARE(htimx_can,TIM_CHANNEL_1, capture + value);
}

/** 函数名:getElapsedTime
  * 功能	:获取等待时间
  * 输入	:
	* 输出	:
	* 编写人:XMW
  */
TIMEVAL getElapsedTime(void)
{
	uint16_t timer = __HAL_TIM_GET_COUNTER(htimx_can);
  /* Calculate the time difference */
	/* I think this should be fixed to
	   16 bit substraction */
	timer = timer - last_time_set;		
	return timer;
}


/** 函数名:HAL_TIM_OC_DelayElapsedCallback
  * 功能	:比较中断回调函数
  * 输入	:
	* 输出	:
	* 编写人:XMW
  */
void HAL_TIM_OC_DelayElapsedCallback(TIM_HandleTypeDef *htim)
{
	if(htimx_can->Instance == htim->Instance)
	{
		if(__HAL_TIM_GET_IT_SOURCE(htim,TIM_IT_CC1)!=RESET)
		{
			__HAL_TIM_CLEAR_IT(htim,TIM_IT_CC1);
			last_time_set=__HAL_TIM_GET_COUNTER(htim);
			TimeDispatch();
		}
	}
}

提供can收发接口

/** 函数名:CANRcv_Task
  * 功能	:canopen接收解析任务
  * 输入	:
	* 输出	:
	* 编写人:XMW
  */
static void CANRcv_Task(void *pvParameters)
{
  static CanRxMsg RxMsg;
  static Message msg;

  uint8_t i = 0;
  for(;;)
  {
    if(osMessageQueueGet(xCANRcvQueue, &RxMsg, 0,osWaitForever) == osOK)
    {
      msg.cob_id = RxMsg.RxHeader.StdId;                  //CAN-ID

      if(CAN_RTR_REMOTE == RxMsg.RxHeader.RTR)
        msg.rtr = 1;                             //远程帧
      else
        msg.rtr = 0;                             //数据帧

      msg.len = (UNS8)RxMsg.RxHeader.DLC;                 //长度

      for(i=0; i<RxMsg.RxHeader.DLC; i++)                 //数据
        msg.data[i] = RxMsg.RxData[i];
			
			EnterMutex();
			canDispatch(&ZERO_Data, &msg);        //调用协议相关接口

			LeaveMutex();
    }
		osDelay(1);
  }
}


/** 函数名:canSend
  * 功能	:canopen发送接口
  * 输入	:
	* 输出	:
	* 编写人:XMW
  */
unsigned char canSend(CAN_PORT notused, Message *m)
{
  uint8_t i;
  static CanTxMsg TxMsg;

  TxMsg.TxHeader.StdId = m->cob_id;

  if(m->rtr)
      TxMsg.TxHeader.RTR = CAN_RTR_REMOTE;
  else
      TxMsg.TxHeader.RTR = CAN_RTR_DATA;

  TxMsg.TxHeader.IDE = CAN_ID_STD;
  TxMsg.TxHeader.DLC = m->len;
  for(i=0; i<m->len; i++)
      TxMsg.TxData[i] = m->data[i];
	if(osMessageQueuePut(xCANSendQueue,&TxMsg,0,0) != osOK)
	{                                            //加入队列失败
		return 0xFF;
	}
  return 0;
}

一沙一世界,一花一天堂。君掌盛无边,刹那成永恒。