Axis_action.c 34.1 KB
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090
#include "hardware.h"
#include "all_value.h"



/*********************************************************************************
函数名:CanMc_W4_Message 
功能:SDO轴写4B参数
参数:
返回:无返回。
实现方法:
编程:
日期:2021-12-16
*********************************************************************************/


void CanMc_W4_Message(u8 id,unsigned int Index,unsigned int Va)		//写轴参数函数4byte
{
		CanTxMsg tx_message1; 
    tx_message1.IDE = CAN_ID_STD;    //标准帧
    tx_message1.RTR = CAN_RTR_DATA;  //数据帧0
    tx_message1.DLC = 0x08;          //帧长度为8
    tx_message1.StdId = 0x600+id;      //帧ID为传入参数的CAN_ID
		tx_message1.ExtId = 0;
    tx_message1.Data[0] = L_4byte;//D【4-7】数据段中核心数据长度4个字节,便于接收方截取数据=D【4-7】
    tx_message1.Data[1] = Index>>8;
    tx_message1.Data[2] = Index>>16;
    tx_message1.Data[3] = Index;
    tx_message1.Data[4] = Va;
    tx_message1.Data[5] = Va>>8;
    tx_message1.Data[6] = Va>>16;
    tx_message1.Data[7] = Va>>24;
	
    CAN_Transmit(CAN1,&tx_message1);
		OSTimeDly(1);//必要通信间隔
}

/*********************************************************************************
函数名:CanMc_W2_Message 
功能:SDO轴写2B参数
参数:
返回:无返回。
实现方法:
编程:
日期:2021-12-16
*********************************************************************************/


void CanMc_W2_Message(u8 id,unsigned int Index,unsigned short Va)		//写轴参数函数2byte
{
		CanTxMsg tx_message1; 
    tx_message1.IDE = CAN_ID_STD;    //标准帧
    tx_message1.RTR = CAN_RTR_DATA;  //数据帧0
    tx_message1.DLC = 0x08;          //帧长度为8
    tx_message1.StdId = 0x600+id;      //帧ID为传入参数的CAN_ID
		tx_message1.ExtId = 0;
    tx_message1.Data[0] = L_2byte;//D【4-5】数据段中核心数据长度2个字节,便于接收方截取数据=D【4-5】
    tx_message1.Data[1] = Index>>8;
    tx_message1.Data[2] = Index>>16;
    tx_message1.Data[3] = Index;
    tx_message1.Data[4] = Va;
    tx_message1.Data[5] = Va>>8;
    tx_message1.Data[6] = 0;
    tx_message1.Data[7] = 0;
	
    CAN_Transmit(CAN1,&tx_message1);
		OSTimeDly(1);//必要通信间隔
}

/*********************************************************************************
函数名:CanMc_W1_Message 
功能:SDO轴写1B参数
参数:
返回:无返回。
实现方法:
编程:
日期:2021-12-16
*********************************************************************************/


void CanMc_W1_Message(u8 id,unsigned int Index,unsigned char Va)		//写轴参数函数1byte
{
		CanTxMsg tx_message1; 
    tx_message1.IDE = CAN_ID_STD;    //标准帧
    tx_message1.RTR = CAN_RTR_DATA;  //数据帧0
    tx_message1.DLC = 0x08;          //帧长度为8
    tx_message1.StdId = 0x600+id;      //帧ID为传入参数的CAN_ID=0x600+id
		tx_message1.ExtId = 0;
    tx_message1.Data[0] = L_1byte;//D【4】数据段中核心数据长度1个字节,便于接收方截取数据=D【4】
    tx_message1.Data[1] = Index>>8;
    tx_message1.Data[2] = Index>>16;
    tx_message1.Data[3] = Index;
    tx_message1.Data[4] = Va;
    tx_message1.Data[5] = 0;
    tx_message1.Data[6] = 0;
    tx_message1.Data[7] = 0;
	
    CAN_Transmit(CAN1,&tx_message1);
		OSTimeDly(1);//必要通信间隔
}


///*********************************************************************************
//函数名:CanTPDO_4_Message 
//功能:PDO发送包1函数
//参数:
//返回:无返回。
//实现方法:
//编程:
//日期:2021-12-16
//*********************************************************************************/


void CanTPDO_1_Message(u8 id,u16 Cont_Word,u8 Mode,signed int Speed)		//包1函数
{

		CanTxMsg tx_message1;
		Speed=Speed*10;//步科的内部单位1Rpm=2730.6666DEC
    tx_message1.IDE = CAN_ID_STD;    //标准帧
    tx_message1.RTR = CAN_RTR_DATA;  //数据帧0
    tx_message1.DLC = 0x08;          //帧长度为8
    tx_message1.StdId = 0x200+id;      //电池使用了ID=201/202,为避开这个,驱动器使用400+id
		tx_message1.ExtId = 0;
    tx_message1.Data[0] = Cont_Word;//D【4】数据段中核心数据长度1个字节,便于接收方截取数据=D【4】
    tx_message1.Data[1] = Cont_Word>>8;
    tx_message1.Data[2] = Mode;
    tx_message1.Data[3] = Speed;
    tx_message1.Data[4] = Speed>>8;
    tx_message1.Data[5] = Speed>>16;
    tx_message1.Data[6] = Speed>>24;
    tx_message1.Data[7] = 0;
	
    CAN_Transmit(CAN1,&tx_message1);
		OSTimeDly(1);//必要通信间隔
}

/*********************************************************************************
函数名:CanTPDO_2_Message 
功能:PDO发送包2函数
参数:
返回:无返回。
实现方法:
编程:
日期:2021-12-16
*********************************************************************************/


void CanTPDO_2_Message(u8 id,signed int TargetPos,unsigned int TargetSpeed)		//包2函数
{

		CanTxMsg tx_message1; 
		TargetSpeed=TargetSpeed*10;//步科的内部单位1Rpm=2730.6666DEC
    tx_message1.IDE = CAN_ID_STD;    //标准帧
    tx_message1.RTR = CAN_RTR_DATA;  //数据帧0
    tx_message1.DLC = 0x08;          //帧长度为8
    tx_message1.StdId = 0x300+id;      //帧ID为传入参数的CAN_ID=0x600+id
		tx_message1.ExtId = 0;
    tx_message1.Data[0] = TargetPos;//D【4】数据段中核心数据长度1个字节,便于接收方截取数据=D【4】
    tx_message1.Data[1] = TargetPos>>8;
    tx_message1.Data[2] = TargetPos>>16;
    tx_message1.Data[3] = TargetPos>>24;
    tx_message1.Data[4] = TargetSpeed;
    tx_message1.Data[5] = TargetSpeed>>8;
    tx_message1.Data[6] = TargetSpeed>>16;
    tx_message1.Data[7] = TargetSpeed>>24;
	
    CAN_Transmit(CAN1,&tx_message1);
		OSTimeDly(1);//必要通信间隔
}

/*********************************************************************************
函数名:CanTPDO_3_Message 
功能:PDO发送包3函数
参数:
返回:无返回。
实现方法:
编程:
日期:2021-12-16
*********************************************************************************/


void CanTPDO_3_Message(u8 id,unsigned int Acc,unsigned int Dcc)//包3函数
{

		CanTxMsg tx_message1; 
    tx_message1.IDE = CAN_ID_STD;    //标准帧
    tx_message1.RTR = CAN_RTR_DATA;  //数据帧0
    tx_message1.DLC = 0x08;          //帧长度为8
    tx_message1.StdId = 0x400+id;      //帧ID为传入参数的CAN_ID=0x600+id
		tx_message1.ExtId = 0;
    tx_message1.Data[0] = Acc;//D【4】数据段中核心数据长度1个字节,便于接收方截取数据=D【4】
    tx_message1.Data[1] = Acc>>8;
    tx_message1.Data[2] = Acc>>16;
    tx_message1.Data[3] = Acc>>24;
    tx_message1.Data[4] = Dcc;
    tx_message1.Data[5] = Dcc>>8;
    tx_message1.Data[6] = Dcc>>16;
    tx_message1.Data[7] = Dcc>>24;
	
    CAN_Transmit(CAN1,&tx_message1);
		OSTimeDly(1);//必要通信间隔
}

/*********************************************************************************
函数名:CanMc_R_Message 
功能:SDO读取轴读参数
参数:
返回:无返回。
实现方法:
编程:
日期:2021-12-16
*********************************************************************************/
void CanMc_R_Message(u8 id,unsigned int Index)		//读轴参数函数
{
		CanTxMsg tx_message1; 
    tx_message1.IDE = CAN_ID_STD;    //标准帧
    tx_message1.RTR = CAN_RTR_DATA;  //数据帧0
    tx_message1.DLC = 0x08;          //帧长度为8
    tx_message1.StdId = 0x600+id;      //帧ID为传入参数的CAN_ID=0x600+id
    tx_message1.Data[0] = LR_byte;//D【4-7】数据段中核心数据长度,由驱动回复的报文功能码来确定
    tx_message1.Data[1] = Index>>8;//主索引地址的低字节16位中的低8位 
    tx_message1.Data[2] = Index>>16;//主索引地址的低字节16位中的高8位 
    tx_message1.Data[3] = Index;//子索引地址
    tx_message1.Data[4] = 0;
    tx_message1.Data[5] = 0;
    tx_message1.Data[6] = 0;
    tx_message1.Data[7] = 0;
	
    CAN_Transmit(CAN1,&tx_message1);
		OSTimeDly(1);//必要通信间隔

}



/*********************************************************************************
函数名:Fc_MC_Power 
功能:轴使能函数
参数:                                    返回:
实现方法:
编程:                                日期:2021-11-23
*********************************************************************************/

void MC_Power(u8 id,u8 Enable)//轴使能函数
{
	if (Enable)
		{	if (Motor[id].MToPc.Powered|VaIndexW_R(&Motor[id].MToPc.StatusWord,3)){;}
			else if (Motor[id].PcToM.PowerOn_Step==0)Motor[id].PcToM.PowerOn_Step=1;
		}
	else
	{ Motor[id].PcToM.ContWord=0x05;
		Motor[id].PcToM.PowerOn_Step=0;
	}
	
	switch(Motor[id].PcToM.PowerOn_Step)
	{
		case 1:
						Motor[id].PcToM.ContWord=0x06;
						if (Motor[id].MToPc.ContWord==0x06) Motor[id].PcToM.PowerOn_Step++;								
						break;
		case 2:
						Motor[id].PcToM.ContWord=0x07;
						if (Motor[id].MToPc.ContWord==0x07)Motor[id].PcToM.PowerOn_Step++;
						break;
		case 3:
						Motor[id].PcToM.ContWord=0x0F;
						if ((Motor[id].MToPc.ContWord==0x0F)&&Motor[id].MToPc.Powered)Motor[id].PcToM.PowerOn_Step=100; 
						break;
		case 100:
						Motor[id].PcToM.PowerOn_Step=0; 
						break;
		default:
						break;
	}		
	
}


/*********************************************************************************
函数名:Fc_MC_Reset 
功能:轴复位函数
参数:                                    返回:
实现方法:
编程:                                 日期:2021-11-23
*********************************************************************************/

void MC_Reset(u8 id,u8 Execute)//轴复位函数 
{
	if (Execute)
	{	if (VaIndexW_R(&Motor[id].MToPc.StatusWord,3)) {Motor[id].PcToM.Reset_Step=1;}
		else Motor[id].PcToM.Reset_Step=0;
		Motor[id].PcToM.Reset=0;
	}

	
	switch(Motor[id].PcToM.Reset_Step)
	{
		case 1:
					Motor[id].PcToM.ContWord=0x06;
					if (Motor[id].MToPc.ContWord==0x06) Motor[id].PcToM.Reset_Step++;
					break;
		case 2:
					Motor[id].PcToM.ContWord=0x80;
					if (Motor[id].MToPc.ContWord==0x80) Motor[id].PcToM.Reset_Step=100;
					break;
		case 100:
					Motor[id].PcToM.Reset_Step=0;
					break;							
																	
	}
			
}

/*********************************************************************************
函数名:Fc_MC_Stop 
功能:轴急停函数
参数:                                    返回:
实现方法:
编程:                                 日期:2021-11-23
*********************************************************************************/

void Fc_MC_Stop(u8 id,u8 Execute)//轴急停函数
{
	if (Execute)
	{	Motor[id].PcToM.ContWord=0x02;
		if (Motor[id].MToPc.ContWord==0x02)
		{ Motor[id].PcToM.Stop=0;
			Motor[id].PcToM.Reset=1;
			Motor[id].PcToM.PowerOn_Step=0;
			Motor[id].PcToM.Absolute_Step=0;
			Motor[id].PcToM.Relative_Step=0;
		}
	}	
}



/*********************************************************************************
函数名:MC_MoveAbsolute 
功能:轴绝对距离运动函数
参数:                                    返回:
实现方法:
编程:                                日期:2021-11-23
*********************************************************************************/

void MC_MoveAbsolute(u8 id)//轴绝对距离运动函数

{	
	switch(Motor[id].PcToM.Absolute_Step)
	{
		case 0:
					if (Motor[id].MToPc.Powered) Motor[id].PcToM.Absolute_Step++;
					break;
		case 1:
					Motor[id].PcToM.Absolute_Step=3;		
					break;	
//		case 2:	
//					Motor[id].PcToM.PowerOn=1;
//					if (Motor[id].MToPc.Powered)Motor[id].PcToM.Absolute_Step=3;			
//					break;	
		case 3:			
					Motor[id].PcToM.WorkMode=1;	
					if (Motor[id].MToPc.WorkModeNow==1)Motor[id].PcToM.Absolute_Step++;									
					break;
		case 4:			
					Motor[id].PcToM.ContWord=0x0F;
					if (Motor[id].MToPc.ContWord==0x0F)Motor[id].PcToM.Absolute_Step++;									
					break;
		case 5:
					Motor[id].PcToM.TargetSpeed=1000;			
					CanTPDO_2_Message(AxisNo_NodeIdChange(id),Motor[id].PcToM.TargetPos,Motor[id].PcToM.TargetSpeed);	
					Motor[id].PcToM.Absolute_Step++;									
					break;	
		case 6:			
					Motor[id].PcToM.ContWord=0x1F;	
					CanTPDO_1_Message(AxisNo_NodeIdChange(id),Motor[id].PcToM.ContWord,Motor[id].PcToM.WorkMode,Motor[id].PcToM.Speed);
					if (Motor[id].MToPc.ContWord==0x1F|Motor[id].PcToM.ContWord==0x1F )
					{ Motor[id].PcToM.ContWord=0x0F;
						Motor[id].PcToM.Absolute_Step++;}									
					break;	
		case 7://到达目标位置且目标位置偏差较小			
					if (VaIndexW_R(&Motor[id].MToPc.StatusWord,10) && abs(Motor[id].MToPc.Pos_Actual-Motor[id].PcToM.TargetPos)<40)Motor[id].PcToM.Absolute_Step=100;		
					break;	
		case 100:
					Motor[id].PcToM.Absolute_Step=0;
					break;				
		default:
					break;	
	}

}


/*********************************************************************************
函数名:Fc_MC_MoveHoldAbsolute 
功能:轴持续绝对位置距离运动函数
参数:
返回:无返回。
实现方法:
编程:pcy
日期:2021-12-16
*********************************************************************************/
float PosDelta;
u8 ContWordSendLock;
 void MC_MoveHoldAbsolute(u8 id)//轴持续绝对位置距离运动函数
{						
	PosDelta=Motor[id].MToPc.Angle_Actual-Motor[id].PcToM.Angle_Target;
	switch(Motor[id].PcToM.AbsoluteHold_Step)
	{
		
		case 1://若误差较小则不调节
					if(fabs(PosDelta)<DeltaAngPerm_Helmzhuan)  
					{ if (Motor[id].PcToM.AbsoluteHold_Enable==0)
							Motor[id].PcToM.AbsoluteHold_Step=100;//为了点动已经到位后,同向再次点动
						else Motor[id].PcToM.AbsoluteHold_Step++;
					}
					else 
						Motor[id].PcToM.AbsoluteHold_Step++;
					break;
		case 2://舵轮转轴转向之前先判断轴无故障+转向轴原点已找到或者行走轴置过零
					if ( (VaIndexW_R(&Motor[id].MToPc.StatusWord,3)==0) && Motor[id].MToPc.Home_Found && Motor[id].MToPc.Powered)
						Motor[id].PcToM.AbsoluteHold_Step=10;
					else 
						Motor[id].PcToM.AbsoluteHold_Step++;
					break;
		case 3://启动调向前给出使能指令
					if(VaIndexW_R(&Motor[id].MToPc.StatusWord,3)==0)
					{ Motor[id].PcToM.PowerOn=1;
					  Motor[id].PcToM.AbsoluteHold_Step++;}
					break;			
		case 4://完成使能
					if (Motor[id].MToPc.Powered ) Motor[id].PcToM.AbsoluteHold_Step=10;
					break;
		case 10://下发选择位置模式+速度			
					Motor[id].PcToM.WorkMode=1;
					Motor[id].PcToM.ContWord=0x0F;
					if (Motor[id].MToPc.WorkModeNow==1&&Motor[id].MToPc.ContWord==0x0F)
					{ Motor[id].PcToM.TargetSpeed=Speed_HelmZhuan;
						Motor[id].PcToM.AbsoluteHold_Step++;}									
					break;
		case 11://执行下发走位置指令

					if ( (id==2)|(id==4) ){ FirstPosOk=0;Motor[id].PcToM.AbsoluteHold_Step=20;}
					else Motor[id].PcToM.AbsoluteHold_Step=30;
					Motor[id].MToPc.Tim4_AxisDelayNum=0;
					ContWordSendLock=0;
					break;
		case 20://舵轮转向轴走目标位置
					if ( (Motor[id].PcToM.Angle_Target>=-91 && Motor[id].PcToM.Angle_Target<=135) )//目标距离在舵轮角度范围之内
					{	Motor[id].PcToM.TargetSpeed=Speed_HelmZhuan;
 						Motor[id].PcToM.TargetPos=(signed int)(((float)F_Ang_HelmZerToAgvX*0.01f-Motor[id].PcToM.Angle_Target)*(float)Motor[id].PulseS_Unit);
					
						if( (fabs(Motor[id].MToPc.Angle_Actual-Motor[id].PcToM.Angle_Target)<0.08) && VaIndexW_R(&Motor[id].MToPc.StatusWord,10) )//位置变化很小+到达目标位置
						{ 
							if (Motor[id].PcToM.AbsoluteHold_Enable==0)//无继续运动指令则结束。若有继续指令则等待新的目标位置
							{	Motor[id].PcToM.ContWord=0x0F;//
								Motor[id].PcToM.AbsoluteHold_Step=90;}
						}
						else Motor[id].PcToM.ContWord=0x3F;	
					}				
					break;
		case 30://舵轮行走轴走目标位置


						Motor[id].PcToM.TargetSpeed=Speed_HelmGo;

						Motor[id].PcToM.TargetPos=(signed int)(Motor[id].PcToM.Angle_Target*(float)Motor[id].PulseS_Unit);
						
						if( (fabs(Motor[id].MToPc.Angle_Actual-Motor[id].PcToM.Angle_Target)<DeltaAngPerm_HelmGo) && VaIndexW_R(&Motor[id].MToPc.StatusWord,10)&& ContWordSendLock )//位置变化很小+到达目标位置
						{ 
							if (Motor[id].PcToM.AbsoluteHold_Enable==0)//无继续运动指令则结束
							{	Motor[id].PcToM.ContWord=0x0F;//
								Motor[id].PcToM.AbsoluteHold_Step=90;}
						}
						else 
						{ 
							Motor[id].PcToM.ContWord=0x3F;
							if (  ((Motor[id].MToPc.ContWord==0x3F)&&((Motor[id].MToPc.Tim4_AxisDelayNum>25)) ) ) ContWordSendLock=1;
								
//							if(ContWordSendLock==0)Motor[id].PcToM.ContWord=0x3F;
//							else Motor[id].PcToM.ContWord=0x0F;
						}

					break;					
					
		case 90:
					Motor[id].PcToM.AbsoluteHold_Step=100;			
					break;						
		case 100:		
					break;				

	}
//	if (Enable!=1 &&Motor[id].MToPc.Powered &&Motor[id].PcToM.AbsoluteHold_Step==5)Motor[id].PcToM.AbsoluteHold_Step=10;				
}





#define  Dis1 40//mm
#define  Dis2 100//mm
#define  Dis5 1000//mm
#define  Overide1 0.25f//mm
#define  Overide2 2.4f//mm
#define  Overide3 3.2f//mm
#define  Overide5 5.0f//mm

u8 SpeedAbsoC_Fc(u8 id)//速度模式下控制电机到达目标位置的函数
{	float DeltaDis;
	float Override;
  if( (fabs(Motor[id].MToPc.Angle_Actual-Motor[id].PcToM.Angle_Target)<DeltaAngPerm_HelmGo)  )//到达目标位置允许范围
	{ 
		Motor[id].PcToM.Speed=0;							
		if (Motor[id].MToPc.Tim4_AxisDelayNum>12) return 1;	
		else return 0;
	}
	else 
	{ 				
		DeltaDis=fabs(Motor[id].MToPc.Angle_Actual-Motor[id].PcToM.Angle_Target);

		if (DeltaDis<Dis1)Override=Overide1;
		else if (DeltaDis<Dis2)Override=Overide2;
		else if (DeltaDis>Dis5)Override=Overide5;
		else Override=(Overide5-Overide3)/(Dis5-Dis2)*(DeltaDis-Dis2)+Overide3;
														
		Motor[id].PcToM.Speed=(int)(Override*0.01f*(float)Motor[id].Max_rpm);							
		if (Motor[id].MToPc.Angle_Actual>Motor[id].PcToM.Angle_Target) Motor[id].PcToM.Speed=Motor[id].PcToM.Speed*(-1);									
		return 0;	
	}	
}
/*********************************************************************************
函数名:MC_MoveSpeedAbsolute 
功能:轴速度模式运动到绝对位置距离运动函数
参数:
返回:无返回。
实现方法:
编程:
日期:2022-2-22
*********************************************************************************/

void MC_MoveSpeedAbsolute(u8 id)//轴持续绝对位置距离运动函数
{						
//	PosDelta=abs(Motor[id].MToPc.Angle_Actual-Motor[id].PcToM.Angle_Target);

 	switch(Motor[id].PcToM.SpeedAbsolute_Step)
	{		
		case 1://若误差较小则不调节
					if( (fabs(Motor[id].MToPc.Angle_Actual-Motor[id].PcToM.Angle_Target)<DeltaAngPerm_Helmzhuan) && Motor[id].MToPc.Powered ) Motor[id].PcToM.SpeedAbsolute_Step=100;
					else Motor[id].PcToM.SpeedAbsolute_Step++;
					break;
		case 2://舵轮转轴转向之前先判断轴无故障+转向轴原点已找到
					if ( (VaIndexW_R(&Motor[id].MToPc.StatusWord,3)==0) && Motor[id].MToPc.Home_Found )Motor[id].PcToM.SpeedAbsolute_Step++;
					break;
		case 3://启动调向前给出使能指令
					Motor[id].PcToM.PowerOn=1;
					Motor[id].PcToM.SpeedAbsolute_Step++;
					break;			
		case 4://完成使能
					if (Motor[id].MToPc.Powered ) Motor[id].PcToM.SpeedAbsolute_Step=10;
					break;
		case 10://下发选择位置模式+速度			
					Motor[id].PcToM.WorkMode=3;
					Motor[id].PcToM.ContWord=0x0F;
					if (Motor[id].MToPc.WorkModeNow==3&&Motor[id].MToPc.ContWord==0x0F)
					{ Motor[id].PcToM.SpeedAbsolute_Step++;}									
					break;
		case 11://执行下发走位置指令
					if ( (id==2)|(id==4) )Motor[id].PcToM.SpeedAbsolute_Step=20;
					else Motor[id].PcToM.SpeedAbsolute_Step=30;
					Motor[id].MToPc.Tim4_AxisDelayNum=0;
					ContWordSendLock=0;
					break;
		case 20://舵轮转向轴走目标位置
					break;
		case 30://舵轮行走轴走目标位置			
					if (SpeedAbsoC_Fc(id))Motor[id].PcToM.SpeedAbsolute_Step=90;		
					break;					
					
		case 90:
					Motor[id].PcToM.SpeedAbsolute_Step=100;			
					break;						
		case 100:		
					break;				

	}
			
}
/*********************************************************************************
函数名:MC_MoveRelative 
功能:轴相对距离行走函数
参数:
返回:无返回。
实现方法:
编程:
日期:2021-12-16
*********************************************************************************/
void MC_MoveRelative(u8 id)//轴相对距离行走函数
{
	//Motor[i].PcToM.Relative_Execute
	switch(Motor[id].PcToM.Relative_Step)
	{
		case 0:
//					if (Execute) Motor[id].PcToM.Relative_Step++;
					break;
		case 1://若要走的量较小则不调节

					if( (fabs(Motor[id].PcToM.Angle_Delta)<DeltaAngPerm_Helmzhuan)&& Motor[id].MToPc.Powered) Motor[id].PcToM.Relative_Step=100;//为了点动已经到位后,同向再次点动
					else Motor[id].PcToM.Relative_Step++;
					
					break;
		case 2://轴无故障+转向轴原点已找到
					if ( (VaIndexW_R(&Motor[id].MToPc.StatusWord,3)==0) && Motor[id].MToPc.Home_Found )Motor[id].PcToM.Relative_Step++;
					break;
		case 3://启动调向前给出使能指令
					Motor[id].PcToM.PowerOn=1;
					Motor[id].PcToM.Relative_Step++;
					break;			
		case 4://完成使能,电机位置记位清空
					if (Motor[id].MToPc.Powered ) 
						{Motor[id].PcToM.Relative_Step=9;
							VaIndexW_W(&Motor[id].MToPc.Ax_Status,1,0);//Ax_Status位0:->节点是否在线;位1:->收到1号报文;位2:->收到2号报文;位3:->收到3号报文;位4:->左限位触发;位5:->右限位触发;
						}
					break;	
		case 9://下发选择位置模式+速度			
					Motor[id].PcToM.WorkMode=1;
					Motor[id].PcToM.ContWord=0x0F;
					if (Motor[id].MToPc.WorkModeNow==1&&Motor[id].MToPc.ContWord==0x0F)
					{ Motor[id].PcToM.TargetSpeed=1000;
						Motor[id].PcToM.Relative_Step++;}									
					break;
		case 10://执行下发走位置指令

//						Motor[id].PcToM.TargetSpeed=1000;
					if (VaIndexW_R(&Motor[id].MToPc.Ax_Status,1))
					{	if((id==2)|(id==4))
							{ Motor[id].PcToM.TargetPos=(signed int)(-Motor[id].PcToM.Angle_Delta*(float)Motor[id].PulseS_Unit);}
						else if((id==1)|(id==3)) 
							{ Motor[id].PcToM.TargetPos=(signed int)(Motor[id].PcToM.Angle_Delta*(float)Motor[id].PulseS_Unit);}
														
						Motor[id].PcToM.Angle_Target=Motor[id].PcToM.Angle_Delta+Motor[id].MToPc.Angle_Actual;
						CanTPDO_2_Message(AxisNo_NodeIdChange(id),Motor[id].PcToM.TargetPos,Motor[id].PcToM.TargetSpeed);
						Motor[id].PcToM.Relative_Step++;	
					}							
					break;
		case 11://相对行走延时执行下发对应控制字			
					Motor[id].PcToM.ContWord=0x5F;	
					CanTPDO_1_Message(AxisNo_NodeIdChange(id),Motor[id].PcToM.ContWord,Motor[id].PcToM.WorkMode,Motor[id].PcToM.Speed);
//					Motor[id].PcToM.Relative_Step++;
					Motor[id].PcToM.ContWord=0x0F;
					Motor[id].PcToM.Relative_Step=14;		
					break;		
		case 12:			
					if (VaIndexW_R(&Motor[id].MToPc.StatusWord,10)==0){Motor[id].PcToM.Relative_Step++;Motor[id].MToPc.Tim4_AxisDelayNum=0;}								
					break;
		case 13:			
					if ((Motor[id].MToPc.Tim4_AxisDelayNum>15)&&(Motor[id].MToPc.ContWord==0x5F) ){Motor[id].PcToM.Relative_Step++;Motor[id].PcToM.ContWord=0x0F;	}								
					break;
		case 14:
					if((id==2)|(id==4))
					{ if( (fabs(Motor[id].MToPc.Angle_Actual-Motor[id].PcToM.Angle_Target)<DeltaAngPerm_Helmzhuan) && VaIndexW_R(&Motor[id].MToPc.StatusWord,10) )//位置变化很小+到达目标位置			
						Motor[id].PcToM.Relative_Step=90;	
					}
					else
					{ if( (fabs(Motor[id].MToPc.Angle_Actual-Motor[id].PcToM.Angle_Target)<DeltaAngPerm_HelmGo) && VaIndexW_R(&Motor[id].MToPc.StatusWord,10) )//位置变化很小+到达目标位置			
						Motor[id].PcToM.Relative_Step=90;
					}
					break;
		case 90:
					Motor[id].PcToM.Relative_Step=100;				
					break;					
		case 100:		
					break;				
			
		
	}
}


/*********************************************************************************
函数名:MC_FindHome 
功能:轴找原点函数
参数:
返回:无返回。
实现方法:一旦触发就执行,若有故障则利用外部停止借助外部报错
编程:pcy
日期:2021-12-16
*********************************************************************************/


void MC_FindHome(u8 id)//轴找原点函数
{
			switch(Motor[id].PcToM.FindHome_Step)
				{
					case 1://找原点之前先判断轴无故障
									if (VaIndexW_R(&Motor[id].MToPc.StatusWord,3)==0)Motor[id].PcToM.FindHome_Step++;
									break;					
					case 2://启动找原点信号时先清除原点标记并给出使能指令
									Motor[id].MToPc.Home_Found=0;
									VaIndexW_W(&Motor[id].MToPc.Ax_Status,2,0);//Ax_Status位0:->节点是否在线;位1:->收到1号报文;位2:->收到2号报文;位3:->收到3号报文;位4:->左限位触发;位5:->右限位触发;
									Motor[id].PcToM.PowerOn=1;					
									Motor[id].PcToM.FindHome_Step++;
									break;
#if ZHUANJDZen					
					case 3://找原点之前判断轴已使能
									if (Motor[id].MToPc.Powered)Motor[id].PcToM.FindHome_Step=19;
									break;
					case 19://绝对值电机
								  if( abs(Motor[id].MToPc.Angle_Actual)<135)Motor[id].PcToM.FindHome_Step=50;									
									break;
#else
					case 3://找原点之前判断轴已使能
									if (Motor[id].MToPc.Powered)Motor[id].PcToM.FindHome_Step++;
									break;					
					case 4://判断是否在左限位处(限位信号已采集)
									if (VaIndexW_R(&Motor[id].MToPc.Ax_Status,2))
									{if (VaIndexW_R(&Motor[id].MToPc.Ax_Status,4))Motor[id].PcToM.FindHome_Step++;
										else Motor[id].PcToM.FindHome_Step=10;
									}
									break;
					case 5://转至限位信号消失
									if (VaIndexW_R(&Motor[id].MToPc.Ax_Status,4))
									{	if (id==2)Fc_Matrix_RPM_Axis(1,0,100,0,0,0,0);
										else if (id==4)Fc_Matrix_RPM_Axis(1,0,0,0,100,0,0);
										Motor[id].MToPc.Tim4_AxisDelayNum=0;
									}
									else 
									{ if (Motor[id].MToPc.Tim4_AxisDelayNum>40)
										{ Fc_Matrix_RPM_Axis(1,0,0,0,0,0,0);
										  Motor[id].MToPc.Tim4_AxisDelayNum=0;
										  Motor[id].PcToM.FindHome_Step++;
										}	
									}										
									break;
					case 6://延时一定时间200ms
									if (Motor[id].MToPc.Tim4_AxisDelayNum>20)Motor[id].PcToM.FindHome_Step=10;										
									break;										
					case 10://下发位置模式
									Motor[id].PcToM.WorkMode=1;
									if (Motor[id].MToPc.WorkModeNow==1)Motor[id].PcToM.FindHome_Step++;									
									break;		
					case 11://控制字0x0F-->0x800F启动找原点
									Motor[id].PcToM.ContWord=0x0F;
									if (Motor[id].MToPc.ContWord==0x0F)Motor[id].PcToM.FindHome_Step++;									
									break;	
					case 12://下发找原点控制字0x800F-->0x0F
									Motor[id].PcToM.ContWord=0x800F;	
									if (Motor[id].MToPc.ContWord==0x800F)
									{	Motor[id].PcToM.FindHome_Step++;
											Motor[id].PcToM.ContWord=0x0F;
									}
									break;	
					case 13://StatusWord 位15:->原点反馈到位;+位置变为0
								 if( VaIndexW_R(&Motor[id].MToPc.StatusWord,15)&& (abs(Motor[id].MToPc.Pos_Actual)<400) )Motor[id].PcToM.FindHome_Step=50;									
									break;	
#endif					
					case 50://标记完成找原点
									Motor[id].MToPc.Home_Found=1;
									Motor[id].PcToM.FindHome_Step=100;
									break;	
					case 100:									
									break;						
		

			}	
}

/*********************************************************************************
函数名:MC_SendNodeProtTime 
功能:轴节点保护时间下发
参数:
返回:无返回。
实现方法:
编程:
日期:2021-12-16
*********************************************************************************/

void MC_SendNodeProtTime(u8 id)//轴节点保护时间下发
{
	u8 Nodeid;
	Nodeid=AxisNo_NodeIdChange(id);

				switch(Motor[id].PcToM.NodeProtTime_Step)
				{
					case 0: 
									break;					
					case 1:	
									Motor[id].PcToM.NodeProtTime_Step=2;
									break;		
					case 2:	
									CanMc_W2_Message(Nodeid,MC_TimeGuard_Index,TimeGuard_Node);								
									if (Motor[id].PcToM.NodeProtTime_Step==2)//发送完由于中断原因,有可能直接跳到中断处更改此步骤
									{
									 Motor[id].PcToM.NodeProtTime_Step=3;	
									 Motor[id].MToPc.Tim4_AxisDelayNum=0;
									}
									break;	
					case 3://40ms若未收到反馈信息则再发送
									if (Motor[id].MToPc.Tim4_AxisDelayNum>40)
									{Motor[id].PcToM.NodeProtTime_Step=2;	}
									break;
										
					case 20://节点保护时间下发成功,开始发送节点系数	(由接收单元更改步骤)
									CanMc_W1_Message(Nodeid,MC_TimeFactor_Index,TimeFactor_Node);
									if (Motor[id].PcToM.NodeProtTime_Step==20)
									{Motor[id].PcToM.NodeProtTime_Step=21;Motor[id].MToPc.Tim4_AxisDelayNum=0;}
									break;	
					case 21://40ms若未收到反馈信息则再发送
									if (Motor[id].MToPc.Tim4_AxisDelayNum>40){Motor[id].PcToM.NodeProtTime_Step=20;}
									break;	
					case 40://40ms若未收到反馈信息则再发送
									Motor[id].MToPc.Tim4_AxisDelayNum=0;
									Motor[id].PcToM.NodeProtTime_Step=100;
									break;						
					case 100:								
									break;						
		
				}
}

/*********************************************************************************
函数名:MC_NodeProtect 
功能:轴节点保护询问函数
参数:
返回:无返回。
实现方法:
编程:pcy
日期:2021-12-16
*********************************************************************************/
void MC_NodeProtect(u8 id)//轴节点保护询问函数
{	
		CanTxMsg tx_message1; 
		memset(&tx_message1,0,sizeof(tx_message1));
		if (id==0)id=5;	
    tx_message1.IDE = CAN_ID_STD;    //标准帧
    tx_message1.RTR = CAN_RTR_REMOTE;  //远程帧
    tx_message1.StdId = 0x700+id;      //帧ID为传入参数的CAN_ID
		tx_message1.ExtId = 0;
    CAN_Transmit(CAN1,&tx_message1);
		OSTimeDly(1);//必要通信间隔
}



/*********************************************************************************
函数名:Mc_PDOOpen 
功能:轴打开PDO模式开启指令函数
参数:
返回:无返回。
实现方法:
编程:pcy
日期:2021-12-16
*********************************************************************************/


void Mc_PDOOpen(u8 id)		//轴打开PDO模式开启指令函数,有些驱动只要收到这个信息就会自动开启TPDO,定时发送。
{
		CanTxMsg tx_message1; 
    tx_message1.IDE = CAN_ID_STD;    //标准帧
    tx_message1.RTR = CAN_RTR_DATA;  //数据帧0
    tx_message1.DLC = 0x02;          //帧长度
    tx_message1.StdId = 0;      //帧ID为传入参数的CAN_ID
		tx_message1.ExtId = 0;
    tx_message1.Data[0] = 0x01;//开启PDO模式指令
    tx_message1.Data[1] = id;//00:所有节点都打开,01表示1号站
	
    CAN_Transmit(CAN1,&tx_message1);
		OSTimeDly(1);//必要通信间隔
}
/*********************************************************************************
函数名:Mc_PDOOpen 
功能:轴打开PDO模式开启指令函数
参数:
返回:无返回。
实现方法:
编程:pcy
日期:2021-12-16
*********************************************************************************/


void Mc_Get_TPDO(void)		//发送一次获取外部节点TPDO,有些外部节点在开启PDO后就会主动定时发,有些是被动发,此函数主要针对是被动节点
{
		CanTxMsg tx_message1; 
    tx_message1.IDE = CAN_ID_STD;    //标准帧
    tx_message1.RTR = CAN_RTR_DATA;  //数据帧0
    tx_message1.DLC = 0x01;          //帧长度
    tx_message1.StdId = 0x80;      //询问节点TPDO信息
		tx_message1.ExtId = 0;
    tx_message1.Data[0] = 0x00;//
	
    CAN_Transmit(CAN1,&tx_message1);
		OSTimeDly(1);//必要通信间隔
}

///*********************************************************************************
//函数名:CanTPDO_1_Message 
//功能:PDO发送包1函数
//参数:
//返回:无返回。
//实现方法:
//编程:pcy
//日期:2021-12-16
//*********************************************************************************/


void Mc_SetZero(u8 id)		
{	

	switch(Motor[id].PcToM.SetZero_Step)
	{	
		case 1://位置置零前先判断轴是否正常
						if (VaIndexW_R(&Motor[id].MToPc.StatusWord,3)==0)
						{ 
						  Motor[id].MToPc.Home_Found=0;
							if(fabs(Motor[id].MToPc.Pos_Actual)<5)Motor[id].PcToM.SetZero_Step=90;
							else Motor[id].PcToM.SetZero_Step++;
						}
						break;
		case 2://下发置零指令
						CanMc_W1_Message(AxisNo_NodeIdChange(id),MC_SetZero_Index,0x23);
						if (Motor[id].PcToM.SetZero_Step==2){Motor[id].PcToM.SetZero_Step=3;Motor[id].MToPc.Tim4_AxisDelayNum=0;}
						break;	
		case 3://等待
						if(Motor[id].MToPc.Tim4_AxisDelayNum>20)
							Motor[id].PcToM.SetZero_Step=2;
						break;	
		case 20://判断位置是否在0附近
						if (fabs(Motor[id].MToPc.Pos_Actual)<100)
						{ Motor[id].MToPc.Tim4_AxisDelayNum=0;
							Motor[id].PcToM.SetZero_Step=90;
						}
						break;	
		case 90://标记置零成功状态
						Motor[id].MToPc.Home_Found=1;
						Motor[id].PcToM.SetZero_Step=100;
						break;							
		case 100://
						break;		
	}
	
}

//u8 AxisNodeid;
u8 AxisNo_NodeIdChange(u8 AxisNo)		//轴号节点转换
{	
	if (AxisNo==0) return 14;
	else if ( (AxisNo>=1)&&(AxisNo<=4))return AxisNo+9;
	else if (AxisNo==5)return AxisNo=15;	
	else return AxisNo;

}


u8 Electrify_Step;
//u8 Electrify_Step;
u8 TIM5_ElectrifyNums;//上电过程各轴延时使能的延时计数器
void InitCourse(void)		//写轴参数函数1byte
{	u8 i;
	switch(Electrify_Step)
	{
		case 0:	
				if (TIM5_ElectrifyNums>50)Electrify_Step++;
				break;			
		case 1:	
				if (NodeProEn==1)
				{for(i=0;i<MaxMotNums;i++)
					{ if(Motor[i].Y)
						{ Motor[i].PcToM.NodeProtTime_Step=1;}
					}
				}
				TIM5_ElectrifyNums=0;
				Electrify_Step=10;
				break;
		case 10:	
 				if(VaIndexDW_R(&F_AgvContr,0))
				{ if (!Motor[2].MToPc.Home_Found)Motor[2].PcToM.FindHome_Step=1;	
					if (!Motor[4].MToPc.Home_Found)Motor[4].PcToM.FindHome_Step=1;
				}
				Electrify_Step=100;
				break;
		case 100:	
				break;

		}
}

u8 TIM4_CanSend1Nums;//节点保护发送时间计数器
u8 TIM3_CanSend1Nums;//控制器发送PDO给驱动器的间隔时间计数器
void Fc_MC(void)
{
	u8 i;
	if (Electrify_Step==100)
	{	
		AGV.AllAxisOK|=0x1F;//位0-4都置1
		for(i=0;i<MaxMotNums;i++)
		{ if(Motor[i].Y)
			{
				if ( VaIndexW_R(&Motor[i].MToPc.StatusWord,3) ){ VaIndexB_W(&AGV.AllAxisOK,0,0);break;}//AllAxisOK:位0-AGV所有存在轴正常无故障;1-AGV所有存在轴都已使能;2-舵轮使能无故障且原点找到	;3-舵轮都使能无故障		
			}
		}

		
		for(i=0;i<MaxMotNums;i++)
		{ if(Motor[i].Y)
			{
				if ( Motor[i].MToPc.Powered==0){ VaIndexB_W(&AGV.AllAxisOK,1,0);break;}//AllAxisOK:位0-AGV所有存在轴正常无故障;1-AGV所有存在轴都已使能;2-舵轮使能无故障且原点找到	
			}				
		}	
		
		for(i=0;i<MaxMotNums;i++)
		{ if(Motor[i].Y && VaIndexB_R(&AGV.Axis_No,i))
			{
				if ( VaIndexW_R(&NodeOnLine,i)==0 ){ VaIndexB_W(&AGV.AllAxisOK,4,0);break;}//需要用的轴中有离线
			}				
		}
		
		for(i=1;i<MaxMotNums;i++)
		{ if(Motor[i].Y)
			{
				if ( VaIndexW_R(&Motor[i].MToPc.StatusWord,3)|(Motor[i].MToPc.Powered==0) ){ VaIndexB_W(&AGV.AllAxisOK,3,0);break;}//AllAxisOK:3-舵轮都使能无故障		
			}
		}
		
		
		if( VaIndexB_R(&AGV.AllAxisOK,3) && Motor[2].MToPc.Home_Found  && Motor[4].MToPc.Home_Found )VaIndexB_W(&AGV.AllAxisOK,2,1);//2-舵轮都无故障且已使能,且转向轴原点找到
		else VaIndexB_W(&AGV.AllAxisOK,2,0);
		

		for(i=0;i<MaxMotNums;i++)
		{ 
			if(Motor[i].Y)
			{

				MC_SendNodeProtTime(i);
				MC_Power(i,Motor[i].PcToM.PowerOn);
					
				MC_Reset(i,Motor[i].PcToM.Reset);
				Mc_SetZero(i);
			
				Fc_MC_Stop(i,Motor[i].PcToM.Stop);

				
				MC_MoveRelative(i);

				MC_MoveHoldAbsolute(i);
				MC_MoveSpeedAbsolute(i);
				MC_FindHome(i);
				
 
			}
		}
	}
	else
	{ InitCourse();}
}

void FC_PDOMess_Send(void)
{
	u8 i;
	u8 Nodeid;
	if (Electrify_Step==100)
	{	
		for(i=0;i<MaxMotNums;i++)
		{ Nodeid=AxisNo_NodeIdChange(i);
			if(Motor[i].Y)
			{
				if ((Motor[i].PcToM.NodeProtTime_Step==100)|(NodeProEn==0))//轴节点保护设置完毕
				{	
					if(TIM3_CanSend1Nums>=RPDO_dT)
					{	CanTPDO_3_Message(Nodeid,Motor[i].PcToM.Acc,Motor[i].PcToM.Dcc);		
						CanTPDO_1_Message(Nodeid,Motor[i].PcToM.ContWord,Motor[i].PcToM.WorkMode,Motor[i].PcToM.Speed);
						CanTPDO_2_Message(Nodeid,Motor[i].PcToM.TargetPos,Motor[i].PcToM.TargetSpeed);		
					}
					if (TIM4_CanSend1Nums>=Time_NodeProtSend) MC_NodeProtect(Nodeid);//间隔一定时间发送节点保护心跳信息
				}
				
				if (Motor[i].MToPc.Tim4_NodeProNums>100){VaIndexW_W(&Motor[i].MToPc.Ax_Status,0,0);VaIndexW_W(&NodeOnLine,i,0);}
				else 
				{ if (Motor[i].PcToM.NodeProtTime_Step==100)
					{ VaIndexW_W(&Motor[i].MToPc.Ax_Status,0,1);VaIndexW_W(&NodeOnLine,i,1);	}	
				}
			}
		}
		
		if (TIM4_CanSend1Nums>=Time_NodeProtSend){Mc_PDOOpen(0);	TIM4_CanSend1Nums=0;}//开启打开PDO节点
		if (TIM3_CanSend1Nums>=RPDO_dT){TIM3_CanSend1Nums=0;if (TpdoMauGetEn)Mc_Get_TPDO();}
		
	}
}