在使用EPOS4控制板控制电机中,在调试过程中官方提供的EPOS studio是一个强大的上位机工具,但使用它需要对EPOS控制板与MAXON电机都有一定了解的情况下;基于同样原因若使用can分析直接给控制板发送命令也不适合产品的使用者。
为满足开发项目产品化的需求,现准备在原先搭建好can通信的基础上再加入串口通信部分。即构建好收发协议,使得用户或接收项目的工程人员无需系统的了解该控制系统,通过了解发送命令的格式即可实现对设备的调试。同时,再后续若要采用无线通信方式也可采用同样协议。
![](https://img-blog.csdnimg.cn/direct/d1d22781f4764f67a5824bc831860679.jpeg)
由于在正点原子官方的can收发实验中为调试can通信实验而已经加入了串口文件usart.c故我们在工程文件中稍做修改即可。
![](https://img-blog.csdnimg.cn/direct/9746a042000e49aaa4ff040b832101f8.png)
如下图代码所示,这里我在主函数中加入了一系列按键,将其中的key4设置成了进出串口调试模式的按键,按下后进入串口调试,再次按下后进入主循环。当检查到标志位表示接收到数据后开始对数据进行处理。
![](https://img-blog.csdnimg.cn/direct/08217ad2b7764a8ca0db285577538472.png)
如下为串口协议的重点,可以作为串口转can协议的一个示例,可以看到整个函数还是较为繁琐的,因此建议放到主函数之外。简单来说,就是为了满足can协议的需要,自定义一个收发规则,从经串口发送的数据中截取can协议需要的控制字、index、subindex、data已经nodeID,再辅以帧头帧尾。最后再将截取的数据打印并发送can命令即可。
//该函数用于将串口指令转为can指令发送
//#开始,_分割,&结束
//要求串口指令十六进制,大写
void Data_Analyse()
{
uint16_t control_word = 0;
uint16_t index[2] = {0,0};
uint16_t subindex = 0;
uint16_t data[4] = {0,0,0,0};
uint16_t ID = 0;
uint8_t i = 1;
uint8_t canbuf[]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};//000100
if(g_usart_rx_buf[0] == '#'){
do{
control_word *= 16;
if(g_usart_rx_buf[i] <= '9')
control_word += (g_usart_rx_buf[i] - '0');
else
control_word += (g_usart_rx_buf[i] - 'A' + 10);
i++;
}while(g_usart_rx_buf[i] != '_');//控制字
i++;
do{
index[0] *= 16;
index[1] *= 16;
if(g_usart_rx_buf[i] <= '9')
index[0] += (g_usart_rx_buf[i] - '0');
else
index[0] += (g_usart_rx_buf[i] - 'A' + 10);
if(g_usart_rx_buf[i+2] <= '9')
index[1] += (g_usart_rx_buf[i+2] - '0');
else
index[1] += (g_usart_rx_buf[i+2] - 'A' + 10);
i++;
}while(g_usart_rx_buf[i+2] != '_');//index
i += 2;
i++;
do{
subindex *= 16;
if(g_usart_rx_buf[i] <= '9')
subindex += (g_usart_rx_buf[i] - '0');
else
subindex += (g_usart_rx_buf[i] - 'A' + 10);
i++;
}while(g_usart_rx_buf[i] != '_');//subindex
i++;
do{
data[0] *= 16;
data[1] *= 16;
data[2] *= 16;
data[3] *= 16;
if(g_usart_rx_buf[i] <= '9')
data[0] += (g_usart_rx_buf[i] - '0');
else
data[0] += (g_usart_rx_buf[i] - 'A' + 10);
if(g_usart_rx_buf[i+2] <= '9')
data[1] += (g_usart_rx_buf[i+2] - '0');
else
data[1] += (g_usart_rx_buf[i+2] - 'A' + 10);
if(g_usart_rx_buf[i+4] <= '9')
data[2] += (g_usart_rx_buf[i+4] - '0');
else
data[2] += (g_usart_rx_buf[i+4] - 'A' + 10);
if(g_usart_rx_buf[i+6] <= '9')
data[3] += (g_usart_rx_buf[i+6] - '0');
else
data[3] += (g_usart_rx_buf[i+6] - 'A' + 10);
i++;
}while(g_usart_rx_buf[i+6] != '_');//data
i++;
ID = (g_usart_rx_buf[i+6] - '0');//ID
//串口指令解析完毕,打印信息供检查
printf("\r\n*串口输入信息如下*\r\n");
printf("\r control_word:%x \r",control_word);
printf("\r index:%x,%x \r",index[0],index[1]);
printf("\r subindex:%x \r\n",subindex);
printf("\r data:%x,%x,%x,%x \r\n",data[0],data[1],data[2],data[3]);
printf("\r ID:%x \r",ID);
canbuf[0] = control_word;
canbuf[1] = index[0];
canbuf[2] = index[1];
canbuf[3] = subindex;
canbuf[4] = data[0];
canbuf[5] = data[1];
canbuf[6] = data[2];
canbuf[7] = data[3];
ID += 0x600;
can_send_msg(ID,canbuf,8);
printf("\r\n*已发送can命令*\r\n");
}
else
printf("\r\n*未按要求输入*\r\n");
}
编写好程序,打开串口助手进行测试。将之前的can命令记录下来并转为串口发送的格式。需要注意的是。正点原子官方在编写串口收发函数时需要检查到回车,故在将命令发送至串口助手时需要在最后另起一行。
![](https://img-blog.csdnimg.cn/direct/b44acbdde42e448e9bd0aa1d7b503823.png)
可以看到,输入命令后,程序正常执行,串口输入的字符串被成功截取为若干can指令所需参数。在串口收发过程中,通过串口助手发送时可能会出现串口助手弹出:“函数错误”的警告,目前还未找到原因,希望懂的大佬帮忙指点。不过在实验中并对发送can指令产生影响。
![](https://img-blog.csdnimg.cn/direct/81ae819579fd42499e7aa313192953c8.png)
将一系列指令正确发送后,电机成功运转到指定位置。