基于STM32(HAL)的CAN通信驱动伺服电机

 1.CAN通信原理介绍:

1.1 CAN介绍:

1.CAN(Controller Area Network)是二十世纪八十年代初德国Bosch公司为解决现代汽车中众多电控单元(ECU)之间的数据交换而开发的一种多主机局部网络串行通信协议。

2.是一种串行通信协议,能有效的支持具有很高安全等级的分布实时控制。

3.应用范围很广,数据传输速度极快,较为稳定。

2.CAN通信协议:

2.1 CAN协议:

1.CAN总线上传输的信息称为报文,当总线空闲时任何连接的单元都可以开始发送新的报文。

2. CAN通信是通过以下5种类型的帧进行的:数据帧、遥控帧、错误帧、过载帧、帧间隔。

 

3. CAN协议节点

3.硬件介绍:

STM32F405RGT6MCU开发板:进行程序编写,以及电机的控制。

USBCAN-II CS收发器:当CAN监听功能,查看数据传输是否正确。

EUC3100 USB-485转换器:串口数发送。

CAN电路设计:

                                                  CAN电路

RS485电路设计:

                                                         RS485电路

 

USBCAN-II CS收发器                     USB-485转换器

4.软件介绍:

软件介绍:STM32CubeMx软件:STM32单片机端的软件开发环境采用STM32CubeMX软件,并配合使用Keil MDK5,通过C语言编程。

1.打开STM32CubeMx,新建项目

2.输入自己使用的芯片,双击

3.配置好RCC,与SYS。

4.配置好CAN1

1.选择CAN,勾选Activated

2.Bit Timings Parameters中Prescaler改为9,Bit1 改为5Times,Bit2 改为2Times ,Jump Width 改为1Times .(波特率计算公式:36M/9/(5+2+1)=500K.)

3.使能CAN RX0中断,代表的是接受邮箱0的接收中断

5.设置串口:

1.打开串口异步通信

2.波特率按要求设定,使能中断Enabled勾上;

6.设置主频并输出。

5.代码部分:

共为四个部分:CAN滤波器;CAN接收,CAN发送;电机控制程序;串口部分。

1. CAN滤波器:

CAN_TxHeaderTypeDef can1_tx_header_msg;
CAN_RxHeaderTypeDef can1_rx_header_msg;


CAN_RecvMsg can1_recv_msg;
CAN_RecvMsg can2_recv_msg;



void can1_cfg_init(void)
{
    CAN_FilterTypeDef sFilterConfig;

    sFilterConfig.FilterIdHigh = 0x0000;
    sFilterConfig.FilterIdLow = 0x0000;
    sFilterConfig.FilterMaskIdHigh = 0x0000;
    sFilterConfig.FilterMaskIdLow = 0x0000;
    sFilterConfig.FilterFIFOAssignment = CAN_FILTER_FIFO0;
    sFilterConfig.FilterBank = 0;
    sFilterConfig.FilterScale = CAN_FILTERSCALE_32BIT;
    sFilterConfig.FilterMode = CAN_FILTERMODE_IDMASK;
    sFilterConfig.FilterActivation = ENABLE;
    sFilterConfig.SlaveStartFilterBank = 14;
    if (HAL_CAN_ConfigFilter(&hcan1, &sFilterConfig) != HAL_OK)
    {
        Error_Handler();
    }
    if (HAL_CAN_Start(&hcan1) != HAL_OK)
    {
        Error_Handler();
    }

    if (HAL_CAN_ActivateNotification(&hcan1, CAN_IT_RX_FIFO0_MSG_PENDING) != HAL_OK)
    {
        Error_Handler();
    }
}

2. CAN接收,CAN发送

void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef *hcan)
{
    if (hcan->Instance == CAN1)
    {
        HAL_CAN_GetRxMessage(hcan, CAN_RX_FIFO0, &can1_rx_header_msg, can1_recv_msg.data);
    }
}

void can1_transmit(uint16_t std_id, uint8_t *buff)
{
    can1_tx_header_msg.DLC = 5;
    can1_tx_header_msg.StdId = std_id;
    can1_tx_header_msg.ExtId = 0;
    can1_tx_header_msg.IDE = CAN_ID_STD;
    can1_tx_header_msg.RTR = CAN_RTR_DATA;

    if (HAL_CAN_AddTxMessage(&hcan1, &can1_tx_header_msg, buff, (uint32_t *)CAN_TX_MAILBOX0) != HAL_OK)
    {
        Error_Handler();
    }
}

3.电机控制程序:

#define MOTOR1_IDD 0x01
uint32_t ret1=0;
uint32_t ret2=0; 	uint32_t ress; uint32_t ressS;
/*************************设置电机模式*********************************************/
int32_t set_work_mode(yz_motor_tt motor_id, motor_work_mode_tt mode,int32_t val)
{    
	  uint16_t i = 0xffff;
	  uint16_t res;
 
    uint8_t buff[5] = {0x1D,0x00,0x00,0x00,0x00};
    buff[1] = (uint8_t)(val & 0x000000ff);
    buff[2] = (uint8_t)((val & 0x0000ff00) >> 8);
    buff[3] = (uint8_t)((val & 0x00ff0000) >> 16);
    buff[4] = (uint8_t)((val & 0xff000000) >> 24);
    ress=(uint32_t)(buff[1] + (buff[2] << 8) + (buff[3] << 16) + (buff[4] << 24));
		if (motor_id == YZ_MOTORR_0)
		{
			can1_transmit(MOTOR1_IDD, (uint8_t *)buff);
		}
				while (1)
		{
				i--;
				if (i == 0)
				{
						break;
				}
				if (motor_id == YZ_MOTORR_0)
				{
					if ((can1_recv_msg.data)[0] == 0x00 || (can1_recv_msg.data)[0] == 0x01 || (can1_recv_msg.data)[0] == 0x02 || (can1_recv_msg.data)[0] == 0x03)
					{
							return res = (can1_recv_msg.data)[1] + ((can1_recv_msg.data)[2] << 8) + ((can1_recv_msg.data)[3] << 16) + ((can1_recv_msg.data)[4] << 24);
					}
				}
		}		
		return res;
}


/**
  * @brief  获取运行状态
  * @param  motor_id: 电机的名称
  * @retval 状态值
  */
int32_t get_state_word(yz_motor_tt motor_id)
{
    uint16_t i = 0xffff;
	  uint16_t res;
    uint8_t buff[1] = {0x03};
    if (motor_id == YZ_MOTORR_0)
    {
        can1_transmit1(MOTOR1_IDD, (uint8_t *)buff);
    }

    // 一直读取
    while (1)
    {
        i--;
        if (i == 0)
        {
            break;
        }
        if (motor_id == YZ_MOTORR_0)
        {
					if ((can1_recv_msg.data)[0] == 0x00 || (can1_recv_msg.data)[0] == 0x01 || (can1_recv_msg.data)[0] == 0x02 || (can1_recv_msg.data)[0] == 0x03)
					{
							return res = (can1_recv_msg.data)[0];
					}
        }
    }
		return res;
}



/*************************设置波特率*********************************************/
int32_t set_bit(yz_motor_tt motor_id,int32_t val)
{    
	  uint16_t i = 0xffff;
	  uint16_t res;
    uint8_t buff[5] = {0x3F,0x00,0x00,0x00,0x00};
    buff[1] = (uint8_t)(val & 0x000000ff);
    buff[2] = (uint8_t)((val & 0x0000ff00) >> 8);
    buff[3] = (uint8_t)((val & 0x00ff0000) >> 16);
    buff[4] = (uint8_t)((val & 0xff000000) >> 24);
    ressS=(uint32_t)(buff[1] + (buff[2] << 8) + (buff[3] << 16) + (buff[4] << 24));
		if (motor_id == YZ_MOTORR_0)
		{
			can1_transmit(MOTOR1_IDD, (uint8_t *)buff);
		}
				while (1)
		{
				i--;
				if (i == 0)
				{
						break;
				}
				if (motor_id == YZ_MOTORR_0)
				{
					if ((can1_recv_msg.data)[0] == 0x00 || (can1_recv_msg.data)[0] == 0x01 || (can1_recv_msg.data)[0] == 0x02 || (can1_recv_msg.data)[0] == 0x03)
					{
							return res = (can1_recv_msg.data)[1] + ((can1_recv_msg.data)[2] << 8) + ((can1_recv_msg.data)[3] << 16) + ((can1_recv_msg.data)[4] << 24);
					}
				}
		}		
		return res;
}



/****************初始化设置*******************/
void my_motor(void)
{

	set_work_mode(YZ_MOTORR_0,SPEED_MODEE,1000);
	HAL_Delay(1000);

}

4.串口部分:

printf重定义:
1.在usart.c最下面添加以下函数
/*********************************************************
*
*重定义 fputc 函数
*
**********************************************************/
int fputc(int ch,FILE *f)
{
	HAL_UART_Transmit (&huart6 ,(uint8_t *)&ch,1,HAL_MAX_DELAY );
	return ch;
}

2.在usart.c中添加头文件:#include "stdio.h"
3.魔法棒打开,然后将Use MicroLlB勾上
4.在main.c文件中添加头文件:#include <string.h> #include <stdio.h>

5.main

int main(void)
{
  /* USER CODE BEGIN 1 */
  /* 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();
  MX_USART1_UART_Init();
  /* USER CODE BEGIN 2 */
	
	can1_cfg_init();
 
	HAL_UART_Receive_IT(&huart1, &rx_buffer, 1);//放串口初始化后面
  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {	 
	
	 	HAL_GPIO_WritePin(GPIOA,GPIO_PIN_11,GPIO_PIN_RESET);
    my_motor();
		RS485_SentMode();
		printf("zhuangtai11:%d \r\n ",ret1);
		printf("zhuangtai22:%d \r\n ",ret2);
		RS485_ResMode();
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
  }
  /* USER CODE END 3 */
}

6.CAN分析仪与串口调试:

7.总结:

基于STM32(HAL库)的CAN通信驱动伺服电机,使用电机的通信协议,使用CAN数据发送。

有错误等问题,及时联系我,谢谢!

  • 12
    点赞
  • 96
    收藏
    觉得还不错? 一键收藏
  • 8
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值