提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档


前言

提示:这里可以添加本文要记录的大概内容:

开始说点废话。
最近在学习stm32单片机的can总线。怎么用can总线控制步科的步进驱动器实现电机的正反转,反复尝试了好久,最终终于成功了。下面开始正文部分。


提示:以下是本篇文章正文内容,下面案例可供参考

一、驱动器和stm单片机can接线

把驱动器的的SW1拨打ON,为1号站。SW6拨到ON,终端120Ω电阻接入电路。然后把驱动器的CANH和CANL分别接到stm32 PA11和PA12号引脚
请添加图片描述

二、PDO介绍

PDO一次性可以传送8个字节的数据,只要用来传输需要高频率交换的数据。PDO的传输方式打破了现有的数据问答式传输理念,设备双方在传输前先在各个设备定义好数据接收和发送区域,在数据交换时直接发送相关的数据到对方的数据接收区即可,减少了问答式的询问时间,从而得到了极高的总线利用率

1.PDO传输类型,同步和异步

异步(传输类型:254/255)
1、定义一个事件时间,每隔一段时间驱动器向单片机发送一次数据。步科调试软件配置如下
如图所示驱动器每隔30ms发送一次数据到单片机在这里插入图片描述

2.PDO映射关系解释

TPDO映射设置格式:对象索引地址+对象索引地址+数据类型
映射组数值=所设置的映射个数
![在这里插入图片描述](https://img-blog.csdnimg.cn/1927922b12134c818b4116d1568788cc.png在这里插入图片描述

映射组数值:图中映射了TPDO1映射1和TPDO1映射2;映射组所以填2;
TPDO1映射1:606300代表驱动器 “实际位置” 的can数据地址,20表示32位数据长度
TPDO1站号:TPDO1站号(180)+驱动器ID
注意一个TPDO站号只能传输8个byte数据。

RPDO映射设置格式如下
在这里插入图片描述

3.开启PDO节点

在这里插入图片描述
这里只需要在单片机启动的时候发送一个{0x01,0x00}的报文开启所有下位机节点即可,这时候驱动器就会主动给stm传递数据。

4.步科驱动器主要参数对应的can地址如下

在这里插入图片描述

三、视屏演示

https://mp.csdn.net/mp_others/manage/video?spm=3001.5304

四、主要部分代码

main.c代码部分

#include "led.h"
#include "delay.h"
#include "key.h"
#include "sys.h"
#include "lcd.h"
#include "usart.h"	 
#include "can.h" 
#include "can_axis.h"

int main(void)
{	 
	u8 initbyte[2] = {0x01,0x00};
	u8 i,j;
	u8 key;

	delay_init();	    	 //延时函数初始化	  
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//设置中断优先级分组为组2:2位抢占优先级,2位响应优先级
	uart_init(115200);	 	//串口初始化为115200
	LED_Init();		  		//初始化与LED连接的硬件接口
	LCD_Init();			   	//初始化LCD	
	KEY_Init();				//按键初始化		 	
   
	CAN_Mode_Init(CAN_SJW_1tq,CAN_BS2_8tq,CAN_BS1_9tq,4);//CAN初始化,波特率500Kbps    

 	POINT_COLOR=RED;//设置字体为红色 800*480
	LCD_ShowString(0,10,480,24,24,"--------------------------------------------------------");
	for(i=0;i<2;i++)
		for(j=0;j<2;j++)
		{
			LCD_ShowString(0+i*240,40+j*170,96  ,24,24, "Node ID:");		//收到数据的站号
			LCD_ShowString(0+i*240,70+j*170,96  ,24,24, "Staword:");		//状态字
			LCD_ShowString(0+i*240,100+j*170,96 ,24,24, "Postion:");		//实际位置
			LCD_ShowString(0+i*240,130+j*170,96 ,24,24, "Speed  :");		//实际速度
			LCD_ShowString(0+i*240,160+j*170,96 ,24,24, "Current:");		//实际电流
			LCD_ShowString(0+i*240,190+j*170,240,24,24,"----------------------------");		
		}
	
	POINT_COLOR=BLUE;//设置字体为蓝色	  
	
	Can_Send_Msg(0x000,initbyte,2);//发送8个字节 
 	while(1)
	{
		key=KEY_Scan(0);
		if(key==KEY0_PRES)//KEY0按下,反转
		{
			//SpeedMode(0x201,3,-50,0xf);
			
			Move_300(0x301, 10, 10);
			Move_400(0x401, -20000000, 100);
			Move_200(0x201, 1,0, 0x4F);
			delay_ms(2);
			Move_200(0x201, 1,0, 0x5F);
		}
		if(key==KEY1_PRES)//KEY1按下,正转
		{
			//SpeedMode(0x201,3,50,0xf);
			Move_300(0x301, 10, 10);
			Move_400(0x401, 20000000, 100);
			Move_200(0x201, 1,0, 0x4F);
			delay_ms(2);
			Move_200(0x201, 1,0, 0x5F);
		}
		
		if(key==WKUP_PRES)//WKUP_PRES按下,停止
		{
			SpeedMode(0x201,3,0,0x6);;
		}
		Receive_status();		   
	}
}

can接收发送程序部分

#include "can.h"
#include "led.h"
#include "delay.h"
#include "usart.h"
#include <stdlib.h>
							  
//CAN初始化
//tsjw:重新同步跳跃时间单元.范围:CAN_SJW_1tq~ CAN_SJW_4tq
//tbs2:时间段2的时间单元.   范围:CAN_BS2_1tq~CAN_BS2_8tq;
//tbs1:时间段1的时间单元.   范围:CAN_BS1_1tq ~CAN_BS1_16tq
//brp :波特率分频器.范围:1~1024;  tq=(brp)*tpclk1
//波特率=Fpclk1/((tbs1+1+tbs2+1+1)*brp);
//mode:CAN_Mode_Normal,普通模式;CAN_Mode_LoopBack,回环模式;
//Fpclk1的时钟在初始化的时候设置为36M,如果设置CAN_Mode_Init(CAN_SJW_1tq,CAN_BS2_8tq,CAN_BS1_9tq,4,CAN_Mode_LoopBack);
//则波特率为:36M/((8+9+1)*4)=500Kbps
//返回值:0,初始化OK;
//    其他,初始化失败;


u8 CAN_Mode_Init(u8 tsjw,u8 tbs2,u8 tbs1,u16 brp)
{
	  GPIO_InitTypeDef	GPIO_InitStructure; 
	  CAN_InitTypeDef	CAN_InitStructure;
 	  CAN_FilterInitTypeDef  CAN_FilterInitStructure;
#if CAN_RX0_INT_ENABLE 
   	NVIC_InitTypeDef  NVIC_InitStructure;
#endif

	  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);//使能PORTA时钟	                   											 

  	RCC_APB1PeriphClockCmd(RCC_APB1Periph_CAN1, ENABLE);//使能CAN1时钟	

    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;	//复用推挽
    GPIO_Init(GPIOA, &GPIO_InitStructure);		//初始化IO
   
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;//上拉输入
    GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化IO
	  
 	//CAN单元设置
 	CAN_InitStructure.CAN_TTCM=DISABLE;						 //非时间触发通信模式  //
 	CAN_InitStructure.CAN_ABOM=DISABLE;						 //软件自动离线管理	 //
  	CAN_InitStructure.CAN_AWUM=DISABLE;						 //睡眠模式通过软件唤醒(清除CAN->MCR的SLEEP位)//
  	CAN_InitStructure.CAN_NART=ENABLE;						 //禁止报文自动传送 //
  	CAN_InitStructure.CAN_RFLM=DISABLE;						 //报文不锁定,新的覆盖旧的 // 
  	CAN_InitStructure.CAN_TXFP=DISABLE;						 //优先级由报文标识符决定 //
  	CAN_InitStructure.CAN_Mode= CAN_Mode_Normal;	         //模式设置: mode:0,普通模式;1,回环模式; //
  	//设置波特率
  	CAN_InitStructure.CAN_SJW=tsjw;				//重新同步跳跃宽度(Tsjw)为tsjw+1个时间单位  CAN_SJW_1tq	 CAN_SJW_2tq CAN_SJW_3tq CAN_SJW_4tq
  	CAN_InitStructure.CAN_BS1=tbs1; //Tbs1=tbs1+1个时间单位CAN_BS1_1tq ~CAN_BS1_16tq
  	CAN_InitStructure.CAN_BS2=tbs2;//Tbs2=tbs2+1个时间单位CAN_BS2_1tq ~	CAN_BS2_8tq
  	CAN_InitStructure.CAN_Prescaler=brp;            //分频系数(Fdiv)为brp+1	//
  	CAN_Init(CAN1, &CAN_InitStructure);            // 初始化CAN1 

 	CAN_FilterInitStructure.CAN_FilterNumber=0;	  //过滤器0
   	CAN_FilterInitStructure.CAN_FilterMode=CAN_FilterMode_IdMask; 
  	CAN_FilterInitStructure.CAN_FilterScale=CAN_FilterScale_32bit; //32位 
  	CAN_FilterInitStructure.CAN_FilterIdHigh=0x0000;32位ID
  	CAN_FilterInitStructure.CAN_FilterIdLow=0x0000;
  	CAN_FilterInitStructure.CAN_FilterMaskIdHigh=0x0000;//32位MASK
  	CAN_FilterInitStructure.CAN_FilterMaskIdLow=0x0000;
  	CAN_FilterInitStructure.CAN_FilterFIFOAssignment=CAN_Filter_FIFO0;//过滤器0关联到FIFO0
 	CAN_FilterInitStructure.CAN_FilterActivation=ENABLE; //激活过滤器0

  	CAN_FilterInit(&CAN_FilterInitStructure);//滤波器初始化

#if CAN_RX0_INT_ENABLE
	
	CAN_ITConfig(CAN1,CAN_IT_FMP0,ENABLE);//FIFO0消息挂号中断允许.		    
  
  	NVIC_InitStructure.NVIC_IRQChannel = USB_LP_CAN1_RX0_IRQn;
  	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;     // 主优先级为1
  	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;            // 次优先级为0
  	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  	NVIC_Init(&NVIC_InitStructure);
#endif
	return 0;
}   
 
#if CAN_RX0_INT_ENABLE	//使能RX0中断
//中断服务函数			    
void USB_LP_CAN1_RX0_IRQHandler(void)
{
  	CanRxMsg RxMessage;
	int i=0;
    CAN_Receive(CAN1, 0, &RxMessage);
	for(i=0;i<8;i++)
	printf("rxbuf[%d]:%d\r\n",i,RxMessage.Data[i]);
}
#endif

//can发送一组数据(固定格式:ID为0X12,标准帧,数据帧)	
//len:数据长度(最大为8)				     
//msg:数据指针,最大为8个字节.
//返回值:0,成功;
//		 其他,失败;
u8 Can_Send_Msg(u16 std_id, u8* msg,u8 len)
{	
  u8 mbox;
  u16 i=0;
  CanTxMsg TxMessage;
  TxMessage.StdId=std_id;					 // 标准标识符 
  TxMessage.ExtId=0x00;				   // 设置扩展标示符 
  TxMessage.IDE=CAN_Id_Standard; // 标准帧
  TxMessage.RTR=CAN_RTR_Data;		 // 数据帧
  TxMessage.DLC=len;						// 要发送的数据长度
  for(i=0;i<len;i++)
  TxMessage.Data[i]=msg[i];			          
  mbox= CAN_Transmit(CAN1, &TxMessage);   
  i=0;
  while((CAN_TransmitStatus(CAN1, mbox)==CAN_TxStatus_Failed)&&(i<0XFFF))i++;	//等待发送结束
  if(i>=0XFFF)return 1;
  return 0;		

}

//can接收数据,返回结构体指针变量
u8 Can_Receive_Msg(CanRxMsg *p)
{	
	if( CAN_MessagePending(CAN1,CAN_FIFO0) == 0)	//没有接收到数据,直接退出返回	
		return 0;
	CAN_Receive(CAN1, CAN_FIFO0, p);//读取数据
	return 1;	
}

can控制逻辑部分

#include "sys.h"
#include "can.h" 
#include "delay.h"
#include "can_axis.h"
#include "lcd.h"

/*发送字节内容SDO
如果待发数据为1个字节,则发送命令字为0x2F
如果待发数据为2个字节,则发送命令字为0x2B
如果待发数据为4个字节,则发送命令字为0x23
SDO报文发送成功,接收命令字为0x60
SDO报文发送失败,接收命令字为0x80
*/
//u8 workmode[8] = {0x2F,0x60,0x60,0x00};			//8    
//u8 controlword[8] = {0x2B,0x40,0x60,0x00};		//16   
//u8 t_speed[8] = {0x23,0xFF,0x60,0x00};		//32	目标速度   
//u8 d_speed[8] = {0x23,0x81,0x60,0x00};		//32	轮廓速度
//u8 t_postion[8] = {0x23,0x7A,0x60,0x00};	//32	目标位置
//u8 t_accelerated[8] = {0x23,0x83,0x60,0x00};	//加速度
//u8 t_deceleration[8] = {0x23,0x84,0x60,0x00};	//减速度

/*
发送字节内容RPDO
401 目标位置   目标速度  8个字节
301 加速度 减速度 8个字节
201 工作模式 控制字
*/

/*接收字节内容
报文发送时命令字均为0x40;
如果接收数据为1个字节,则接收命令字为0x4F
如果接收数据为2个字节,则接收命令字为0x4B
如果接收数据为4个字节,则接收命令字为0x43
如果接收数据存在错误,则接收命令字为0x80
*/
//u8 statusword[8] = {0x4B,0x41,0x60,0x00};		//16   
//u8 actualpostion[8] = {0x43,0x63,0x60,0x00};	//32 
//u8 actualvelocity[8] = {0x4B,0x6C,0x60,0x00};	//16
//u8 actualcurrent[8] = {0x4B,0x78,0x60,0x00};	//16

//速度换算rpm
void TKspeed(s32 value,u8* p)
{	
	s32 data;
	//data = value*512*60000/1875;  //速度换算DEC十进制
	data = value*16384;  //简化后	
	*(p+4) = ((data<<24)&0xFF000000)>>24;
	*(p+5) = ((data<< 8)&0x00FF0000)>>16;
	*(p+6) = ((data>> 8)&0x0000FF00)>>8;
	*(p+7) = (data>> 24)&0x000000FF;
}

//目标位置换算DEC
void Tpostion(s32 value,u8* p)
{	
	//data = ((value<<24)&0xFF000000)&0xFF000000 + ((value<<8)&0x00FF0000) + ((value>>8)&0x0000FF00) + ((value>>24)&0x000000FF);
	*(p+0) = ((value<<24)&0xFF000000)>>24;
	*(p+1) = ((value<< 8)&0x00FF0000)>>16;
	*(p+2) = ((value>> 8)&0x0000FF00)>>8;
	*(p+3) = (value>> 24)&0x000000FF;
}

//写加速度rps/s
void Taccelerated(u32 accelerated,u8* p)
{	
	u32 data;
	//DEC=[(Rps/s*65536*编码器分辨率)/4000000]
	data = accelerated*983;
	*(p+0) = ((data<<24)&0xFF000000)>>24;
	*(p+1) = ((data<< 8)&0x00FF0000)>>16;
	*(p+2) = ((data>> 8)&0x0000FF00)>>8;
	*(p+3) = (data>> 24)&0x000000FF;
}

//写减速度rps/s
void Tdeceleration(u32 deceleration,u8* p)
{	
	u32 data;
	//DEC=[(Rps/s*65536*编码器分辨率)/4000000]
	data = deceleration*983;
	*(p+4) = ((data<<24)&0xFF000000)>>24;
	*(p+5) = ((data<< 8)&0x00FF0000)>>16;
	*(p+6) = ((data>> 8)&0x0000FF00)>>8;
	*(p+7) = (data>> 24)&0x000000FF;
}

//写工作模式
void Tmode(u8 mode,u8* p)
{
	*p = mode;
}

//写目标速度
void Tspeed(s32 speed,u8* p)
{
	s32 data;
	//data = value*512*60000/1875;  //速度换算DEC十进制
	data = speed*16384;  //简化后	
	*(p+1) = ((data<<24)&0xFF000000)>>24;
	*(p+2) = ((data<< 8)&0x00FF0000)>>16;
	*(p+3) = ((data>> 8)&0x0000FF00)>>8;
	*(p+4) = (data>> 24)&0x000000FF;
}

//写控制字
void Tword(u16 word,u8* p)
{
	*(p+5) = ((word<<8)&0xFF00)>>8;
	*(p+6) = ((word>>8)&0x00FF);
}

//电流换算
s16 current(s16 value)
{
	float aps;
	aps = value/(2048/(120/1.414));
	return aps;
}

//相对/绝对运动  目标位置和轮廓速度 设定
void Move_400(u16 id, s32 postion, u32 speed)
{
	u8 C_400[8];
	Tpostion(postion,C_400);
	TKspeed(speed,C_400);
	Can_Send_Msg(id,C_400,8);
}

//相对/绝对运动加速度和减速度设定
void Move_300(u16 id, u32 accelerated, u32 deceleration)
{
	u8 C_300[8];
	Taccelerated(accelerated,C_300);
	Tdeceleration(deceleration,C_300);
	Can_Send_Msg(id,C_300,8);
}

//相对/绝对运动工作模式和目标速度和控制字设定
void Move_200(u16 id, u8 mode,s32 speed, u16 ControlWord)
{
	u8 C_200[8];
	Tmode(mode,C_200);
	Tspeed(speed,C_200);
	Tword(ControlWord,C_200);
	Can_Send_Msg(id,C_200,8);
}

//速度模式运行
void SpeedMode(u16 id,u8 mode,s32 Tspeed,u16 ControlWord)
{	
	Move_200(id,mode,Tspeed,ControlWord);
}


/*
数据的接收
当前位置;
当前速度
当前电流
状态字
*/

/*
当前位置-2147483647~2147483647
当前速度
*/
s32 a_acturlvalue(u8* p)
{	
	return ((*(p+7)<<24)+(*(p+6)<<16)+(*(p+5)<<8)+(*(p+4)));
}

u16 a_statusword(u16* p)
{
	return (*(p+5)<<8) + (*(p+4));
}

//LCD显示
void Receive_status(void)
{
	u8 key;
	s32 postion;
	s32 speed;
	u16 s_word;
	u16 c_crrunt;
	CanRxMsg RxMessage;
	key = Can_Receive_Msg(&RxMessage);
	
	if(key)
	{		
		if(RxMessage.StdId == std_id1)	//181
		{
			
			LCD_ShowHexNum(96,40,std_id1,24,4,0);	//ID

			//实际位置
			postion = (RxMessage.Data[3]<<24) + (RxMessage.Data[2]<<16) + (RxMessage.Data[1]<<8) + RxMessage.Data[0];
			if(RxMessage.Data[3]&0x80)
			{
				LCD_ShowString(96,100,96 ,16,24, "-");	
				LCD_ShowxNum(96+12,100,((postion^0xFFFFFFFF)+1),10,24,0x80);				
			}
			else
			{
				LCD_ShowString(96,100,96 ,16,24, " ");	
				LCD_ShowxNum(96+12,100,postion,10,24,0x80);
			}
			
			//实际速度-32767--32767
			speed = (RxMessage.Data[5]<<8) + RxMessage.Data[4];
			if(RxMessage.Data[5] & 0x80)
			{
				//LCD_ShowString(96,130,96,16,24, "-");
				//LCD_ShowxNum(96+12,130,((speed^0xFFFF)+1),10,24,0x80);
				LCD_ShowHexNum(96,130,speed,24,4,0);
			}
			else
			{
				//LCD_ShowString(96,130,96 ,16,24, " ");	
				//LCD_ShowxNum(96+12,130,speed,10,24,0x80);
				LCD_ShowHexNum(96,130,speed,24,4,0);
			}	
		}
		else if(RxMessage.StdId == std_id2)	//281
		{
			LCD_ShowHexNum(96,40,std_id2,24,4,0);	//ID
			s_word = (RxMessage.Data[1]<<8) + RxMessage.Data[0];
			LCD_ShowHexNum(96,70,s_word,24,4,0);	//状态字
			c_crrunt = (RxMessage.Data[3]<<8) + RxMessage.Data[2];
			LCD_ShowHexNum(96,160,c_crrunt,24,4,0);	//实际电流
		}
		
		
		
		else if(RxMessage.StdId == std_id3)	//182
		{
			LCD_ShowHexNum(96+240,40,std_id3,24,4,0);	//ID;
			
			//实际位置
			postion = (RxMessage.Data[3]<<24) + (RxMessage.Data[2]<<16) + (RxMessage.Data[1]<<8) + RxMessage.Data[0];
			if(RxMessage.Data[3]&0x80)
			{
				LCD_ShowString(96+240,100,96 ,16,24, "-");	
				LCD_ShowxNum(96+240+12,100,((postion^0xFFFFFFFF)+1),10,24,0x80);				
			}
			else
			{
				LCD_ShowString(96+240,100,96 ,16,24, " ");	
				LCD_ShowxNum(96+240+12,100,postion,10,24,0x80);
			}
			
			//实际速度-32767--32767
			speed = (RxMessage.Data[5]<<8) + RxMessage.Data[4];
			if(RxMessage.Data[5] & 0x80)
			{
				LCD_ShowHexNum(96+240,130,speed,24,4,0);
			}
			else
			{
				LCD_ShowHexNum(96+240,130,speed,24,4,0);
			}	
		}
		else if(RxMessage.StdId == std_id4)	//282
		{
			s_word = (RxMessage.Data[1]<<8) + RxMessage.Data[0];
			LCD_ShowHexNum(96+240,70,s_word,24,4,0);	//状态字
			c_crrunt = (RxMessage.Data[3]<<8) + RxMessage.Data[2];
			LCD_ShowHexNum(96+240,160,c_crrunt,24,4,0);	//实际电流
		}	
		
		
		
		else if(RxMessage.StdId == std_id5)	//183
		{
			LCD_ShowHexNum(96,40+170,std_id3,24,4,0);	//ID;
			
			//实际位置
			postion = (RxMessage.Data[3]<<24) + (RxMessage.Data[2]<<16) + (RxMessage.Data[1]<<8) + RxMessage.Data[0];
			if(RxMessage.Data[3]&0x80)
			{
				LCD_ShowString(96,100+170,96 ,16,24, "-");	
				LCD_ShowxNum(96+12,100+170,((postion^0xFFFFFFFF)+1),10,24,0x80);				
			}
			else
			{
				LCD_ShowString(96,100+170,96 ,16,24, " ");	
				LCD_ShowxNum(96+12,100+170,postion,10,24,0x80);
			}
			
			//实际速度-32767--32767
			speed = (RxMessage.Data[5]<<8) + RxMessage.Data[4];
			if(RxMessage.Data[5] & 0x80)
			{
				LCD_ShowHexNum(96,130+170,speed,24,4,0);
			}
			else
			{
				LCD_ShowHexNum(96,130+170,speed,24,4,0);
			}	
		}
		else if(RxMessage.StdId == std_id6)	//283
		{
			s_word = (RxMessage.Data[1]<<8) + RxMessage.Data[0];
			LCD_ShowHexNum(96,70+170,s_word,24,4,0);	//状态字
			c_crrunt = (RxMessage.Data[3]<<8) + RxMessage.Data[2];
			LCD_ShowHexNum(96,160+170,c_crrunt,24,4,0);	//实际电流
		}
		
		
		
		else if(RxMessage.StdId == std_id7)	//184
		{
			LCD_ShowHexNum(96+240,40+170,std_id3,24,4,0);	//ID;
			
			//实际位置
			postion = (RxMessage.Data[3]<<24) + (RxMessage.Data[2]<<16) + (RxMessage.Data[1]<<8) + RxMessage.Data[0];
			if(RxMessage.Data[3]&0x80)
			{
				LCD_ShowString(96+240,100+170,96 ,16,24, "-");	
				LCD_ShowxNum(96+240+12,100+170,((postion^0xFFFFFFFF)+1),10,24,0x80);				
			}
			else
			{
				LCD_ShowString(96+240,100+170,96 ,16,24, " ");	
				LCD_ShowxNum(96+240+12,100+170,postion,10,24,0x80);
			}
			
			//实际速度-32767--32767
			speed = (RxMessage.Data[5]<<8) + RxMessage.Data[4];
			if(RxMessage.Data[5] & 0x80)
			{
				LCD_ShowHexNum(96+240,130+170,speed,24,4,0);
			}
			else
			{
				LCD_ShowHexNum(96+240,130+170,speed,24,4,0);
			}	
		}
		else if(RxMessage.StdId == std_id8)	//284
		{
			s_word = (RxMessage.Data[1]<<8) + RxMessage.Data[0];
			LCD_ShowHexNum(96+240,70+170,s_word,24,4,0);	//状态字
			c_crrunt = (RxMessage.Data[3]<<8) + RxMessage.Data[2];
			LCD_ShowHexNum(96+240,160+170,c_crrunt,24,4,0);	//实际电流
		}
		
	}
	
}

总结

我也是刚开始学习单片机。这个弄了很久算是最终弄出来了。写的不好的地方还希望大家多包涵,给我提点建议和意见。如果大家觉得有用请点个赞

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐