第一阶段C#串口上位机练习--stm32F4总结

2023-05-16

1、实验目的

掌握上位机编程;
掌握F4串口;
掌握两者通信数据帧的约定;

2、实验设备

stm32F4核心板,Lcd屏幕,下载器,电脑。

3、完成的任务

(1)已经完成定长数据帧的约定(采用帧头、帧尾以及和检验三方面的方式);
(2)已经完成超时重发的内容(这里完成的是32端的超时重发函数,应答信号采取连续发送方式,没有超时。);
(3)完成浮点数、整型数据的数据的传送到上位机;上位机接收到数据,然后发送应答信号,32停止发送,不然32在约定的超时时间内收不到上位机的应答信号,将继续重发N次,N次都收不到上位机的应答信号,那么就报错(报错将重新运行32的程序,这里没做,后面有时间再做,类似于看门狗监测,还没学到看门狗,后面再说。)
(4)完成IO信号的发送,单片机发送IO信号给上位机,上位机接收到IO信号,就发应答信号给单片机,单片机在超时重发机制下,将不再发IO信号给上位机,完成一次有效的发送。
(5)完成上位机C#端的编写。
在这里插入图片描述

4、串口通信数据帧的格式约定

(1)说明1:定长数据发送,总共13个 字节,没用到的数据位,默认用0x55;
(2)帧头用两个0x21,0x22;
(3)采用和校验方法,和校验的数据是D2—D9,得到的结果放在D10中;
(4)帧尾用0x0D,0x0A;
整体说明:包括六个步进电机,每个步进电机有三个传感器,左限位开关,右限位开关,原点开关,有六个IO开关,比如电磁阀等。
步进电机:
包括:行程,mm单位,脉冲单位;速度,mm/s单位,pul/s单位;
这里特别注定一下:
所设定的应答信号,不管是单片机给电脑发信息,电脑给单片机发应答号的情况,,,,还是,,电脑给单片机发信号,单片机回发应答信号。这里两种情况,都是用同样的应答信号,而没有区分不同的数据下的应答信号。就是说,应答号都一模一样。
这里是为了简化。
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

5、单片机给电脑发信号,电脑接收到,解码之后,马上回发应答信号给单片机。

5.1单片机端的串口代码usart.c和usart.h
usart…h

#ifndef __USART_H
#define __USART_H

#include "stdio.h"
#include "stm32f4xx.h"
#include "delay.h"
#include "Lcd_Driver.h"

#define	USART1_RX_MAX	200	//串口最大接收长度

extern union FloatChar floattemp;
extern union Int32Char int32temp;


extern u8  USART1_RX_BUF[USART1_RX_MAX];	// 定义串口接收数组
extern u8  USART1_RX_Flag ;  // 接收状态标志位
extern u16 USART1_RX_Size ;  // 接收的数据大小
extern u16 USART1_RX_STA; //--接收状态标记	
extern u8  USART_RecAckFlag;//是否收到应答的标记
extern u16 USART_RecAckTime;//接收应答的超时时间1秒钟,1000毫秒
extern u8  USART_RetrySendCount;//接收应答不成功,最多重新发5次数据
extern u8  USART1_RecFrameAckFlag;//接收到应答信号的标记
extern u8  USART1_RecFrameFlag;//接收完一帧数据的标记,0,没有一帧数据,1,接收一帧数据
extern u8  USART1_RecCheckFrameFlag;//校验成功一帧数据的标记,0:不成功,1成功
extern u8  USART1_RecDoubleBufRxd[64];  //接收字节缓冲区

/*----------定长数据帧的宏定义------------------------------------*/
#define UART1_Rec_Head0 0x21 //D0帧头0  ascii码:!
#define UART1_Rec_Head1 0x22 //D1帧头1  ascii码:"
//D2----设备码---0x00-0xFF
//D3----功能码--(六轴0x00--0x10--0x20---0x30--0x40--0x50,限位开关)-
//----------------0x00:x位移,0x01:x速度,0x02:x方向,0x03--0x04--0x05(限位开关)
//---------------0x10:y位移,0x11,y速度,0x12,y方向
//---------------0x20--------0x21 ----------0x22
//---------------0x50---ABCXYZ六轴
//---------------0x60---0x61---电磁阀开关信号
//如果数据是浮点数,比如运动的距离等,用这个联合体,但是要注意是大端模式和小端模式
//D4----数据0  (float)dat0(注意大端模式小端模式)-----(int32)dat0
//D5----数据0	 (float)dat1(使用联合体)---------------(int32) dat1
//D6----数据0  (float)dat2															(int32)	  dat2
//D7----数据0	 (float)dat3																(int32)  dat3
//D8----数据0   0x55																			  0x55
//D9----数据0   0x55																			   0x55
//D10---和校验(D2+D3+D4+...+D9)%256
#define UART1_Default_Char 0x55
#define UART1_Rec_Tail0 0x0D//D11帧尾0      回车
#define UART1_Rec_Tail1 0x0A//D12帧尾1      换行
//****************************************************************
//***********************************设备号码--0x00--0xFF
//设备=MotorXDev01:0x01-------功能码:位移0x00
//---------------------------速度0x01
//---------------------------方向0x02
#define DevMotorX			0x00
#define DevMotorY			0x01
#define DevMotorZ			0x02
#define DevMotorA			0x03
#define DevMotorB			0x04
#define DevMotorC			0x05
//限位开关:左限位开关,右限位,原点开关
#define DevXLeftLimit    0x50
#define DevXRightLimit   0x51
#define DevXOrigin       0x52  
//---------------------------
#define DevYLeftLimit    0x53
#define DevYRightLimit   0x54
#define DevYOrigin       0x55
//---------------------------
#define DevZLeftLimit    0x56
#define DevZRightLimit   0x57
#define DevZOrigin       0x58
//---------------------------
#define DevALeftLimit    0x59
#define DevARightLimit   0x5A
#define DevAOrigin       0x5B
//---------------------------
#define DevBLeftLimit    0x5C
#define DevBRightLimit   0x5D
#define DevBOrigin       0x5E
//---------------------------
#define DevCLeftLimit    0x5F
#define DevCRightLimit   0x60
#define DevCOrigin       0x61
//***************************************
//-------IO开关:比如电磁铁,电磁阀等
#define DevIO_S1         0x80
#define DevIO_S2					0x81
#define DevIO_S3					0x82
#define DevIO_S4         0x83
#define DevIO_S5					0x84
#define DevIO_S6					0x85
//************************************
//------------------------------------------功能号码
//设备电机------对应的功能码
#define FunMotorMM      0x00  //电机位移,单位mm
#define FunMOTORPUL     0x01  //电机位移,单位脉冲个数
#define FunMotorVELMM   0x02  //电机速度,单位:mm/s
#define FunMotorVELPUL  0x03  //电机速度,单位:mm/s
#define FunMotorDIR     0x04  //电机方向
#define FunMotorRUN			0x05  //运动
#define FunMotorSTOP		0x06
//开关信号-----对应的功能码
#define FunIO_Sig              0x00
#define FunLimitSense_Sig      0x01
//---------------------应答功能
#define Fun_Ack        0xDD//
//---------------------------------------------有效数码
//限位开关
#define DatLimitSenseUP   0x00  //松开
#define DatLimitSenseDown 0x01  //触碰到按下
//------------电机方向,CW,正方向,CCW反方向
#define DatDirCW1  0
#define DatDirCCW1 1
#define DatDirCW2  0
#define DatDirCCW2 1
#define DatDirCW3  0
#define DatDirCCW3 1
#define DatDirCW4  0
#define DatDirCCW4 1
#define DatDirCW5  0
#define DatDirCCW5 1
#define DatDirCW6  0
#define DatDirCCW6 1
//IO信号
#define DatIO_S1_OFF_Sig   0x00
#define DatIO_S1_ON_Sig    0x01
#define DatIO_S2_OFF_Sig   0x00
#define DatIO_S2_ON_Sig    0x01
#define DatIO_S3_OFF_Sig   0x00
#define DatIO_S3_ON_Sig    0x01
#define DatIO_S4_OFF_Sig   0x00
#define DatIO_S4_ON_Sig    0x01
#define DatIO_S5_OFF_Sig   0x00
#define DatIO_S5_ON_Sig    0x01
#define DatIO_S6_OFF_Sig   0x00
#define DatIO_S6_ON_Sig    0x01
//-----------------------------应答成功标记
#define Dat_AckOK      0xf0//应答成功
#define Dat_AckNG      0xf1//应答失败



/*----------------------USART配置宏 ------------------------*/
#define UART1_TXD_PIN             GPIO_Pin_9     		    // LED1 引脚      
#define UART1_TXD_PORT            GPIOA                 // LED1 GPIO端口     
#define UART1_TXD_CLK             RCC_AHB1Periph_GPIOA  // LED1 GPIO端口时钟_
#define UART1_TXD_CLK_ENABLE()    {RCC_AHB1PeriphClockCmd(UART1_TXD_CLK,ENABLE);} //使能GPIOA时钟
#define UART1_TXD_PINSOURCE       GPIO_PinSource9

#define UART1_RXD_PIN            GPIO_Pin_10     		    // LED1 引脚      
#define UART1_RXD_PORT            GPIOA                 // LED1 GPIO端口     
#define UART1_RXD_CLK             RCC_AHB1Periph_GPIOA  // LED1 GPIO端口时钟_
#define UART1_RXD_CLK_ENABLE()    {RCC_AHB1PeriphClockCmd(UART1_RXD_CLK,ENABLE);} //使能GPIOA时钟
#define UART1_RXD_PINSOURCE       GPIO_PinSource10

#define UART1_CLK_ENABLE()   {RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);}

/*---------------------- 函数声明 ----------------------------*/
extern void Uart1Action(unsigned char *buf, unsigned char len);//主函数中定义,主要是解码得到信息
//*********************************
void Usart1_Config(u32 BaudRate);
unsigned char Uart1Read(unsigned char *buf, unsigned char len);
void Uart1Driver();
void Usart1_send(u8 byte);//发送一个字节
u8 Usart1_GetCheckSum(u8 *ptr,u8 csumbegin,u8 CsumCalLen);
void Usart1_CheckAndDoAction();//校验成功进行操作
void Usart1_DoAction(unsigned char *buf, unsigned char len);//校验成功进行操作
u8 uart1SendSucAckCmd(u8 DeviceNum,u8 DeviceACKOK,u8 RetryNum,u16 timeout);
u8 uart1SendIOCmd(u8 DeviceNum,u8 sendiostatus,u8 RetryNum,u16 timeout);
u8 Uart1SendFloatDataCmd(u8 DeviceNum,u8 DevFunNum,float sendFloatdata,u8 RetryNum,u16 timeout);
u8 Uart1SendInt32DataCmd(u8 DeviceNum,u8 DevFunNum,int32_t sendint32,u8 RetryNum,u16 timeout);
void aaa(void);//校验成功进行操作

#endif //__USART_H


usart.c

#include "usart.h"  


//浮点数联合体,一个浮点数等于四个字节空间
union FloatChar
{
  char floatchararray[4];
  float floatdata;
};
//整型联合体,一个整型32位等于4个字节空间
union Int32Char
{
  char intchararray[4];
  int32_t	intdata;
};

union FloatChar floattemp;
union Int32Char int32temp;

u8	USART1_RX_BUF[USART1_RX_MAX];	// 定义串口接收数组
u8  USART1_RX_Flag = 0;	 // 接收状态标志位
u16 USART1_RX_Size = 0;	 // 接收的数据大小
u16 USART1_RX_STA=0; //--接收状态标记	
u16 UART1_REC_Length=0;
u8 USART_RecAckFlag=0;//是否发送收到应答的标记
u16 USART_RecAckTime=1000;//接收应答的超时时间1秒钟,1000毫秒
u8  USART_RetrySendCount=5;//接收应答不成功,最多重新发5次数据
u8 USART1_RecFrameAckFlag=0;//接收到应答信号的标记
u8 USART1_RecFrameFlag=0;//接收完一帧完整长度数据的标记,0,没有一帧数据,1,接收一帧数据
u8 USART1_RecCheckFrameFlag=0;//校验成功一帧数据的标记,0:不成功,1成功
u8  USART1_RecDoubleBufRxd[64];  //接收字节缓冲区

// 函数:USART 口初始化
void Usart1_Config(u32 BaudRate)//Usart1_Config
{		
	
	  GPIO_InitTypeDef GPIO_InitStructure;
	USART_InitTypeDef USART_InitStructure;	
		NVIC_InitTypeDef NVIC_InitStructure;	


	UART1_TXD_CLK_ENABLE();
	//USART1端口配置TXD
  GPIO_InitStructure.GPIO_Pin = UART1_TXD_PIN;//GPIOA9与GPIOA10
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;//复用功能
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;	//速度50MHz
	GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; //推挽复用输出
	GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; //上拉
	GPIO_Init(UART1_TXD_PORT,&GPIO_InitStructure); //初始化PA9,PA10
	
	UART1_RXD_CLK_ENABLE();
	//USART1端口配置RXD
  GPIO_InitStructure.GPIO_Pin = UART1_RXD_PIN;//GPIOA9与GPIOA10
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;//复用功能
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;	//速度50MHz
	GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; //推挽复用输出
	GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; //上拉
	GPIO_Init(UART1_RXD_PORT,&GPIO_InitStructure); //初始化PA9,PA10
	
	//使能USART1时钟
	UART1_CLK_ENABLE();
	//串口1对应引脚复用映射
	GPIO_PinAFConfig(UART1_TXD_PORT,UART1_TXD_PINSOURCE,GPIO_AF_USART1); //GPIOA9复用为USART1
	GPIO_PinAFConfig(UART1_RXD_PORT,UART1_RXD_PINSOURCE,GPIO_AF_USART1); //GPIOA10复用为USART1

   //USART1 初始化设置
	USART_InitStructure.USART_BaudRate = BaudRate;//波特率设置
	
	USART_InitStructure.USART_WordLength = USART_WordLength_8b;//字长为8位数据格式
	USART_InitStructure.USART_StopBits = USART_StopBits_1;//一个停止位
	USART_InitStructure.USART_Parity = USART_Parity_No;//无奇偶校验位
	USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;//无硬件数据流控制
	USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;	//收发模式
  USART_Init(USART1, &USART_InitStructure); //初始化串口1
	
	
		NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);	//设置中断分组2
	USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);//开启相关中断
	NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn; // 选择 USART1 通道
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; //抢占优先级设置为3
	NVIC_InitStructure.NVIC_IRQChannelSubPriority =0; //响应优先级设置为1
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //开启中断
	
	
  USART_Cmd(USART1, ENABLE);  //使能串口1 	
  NVIC_Init(&NVIC_InitStructure); //初始化配置

	//================================
}

// 函数:重定义fputc函数
//
int fputc(int c, FILE *fp)
{
	USART_SendData( USART1,(u8)c );	// 发送单字节数据
	while (USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);	//等待发送完毕 
	return (c); //返回字符
}

/*-------------------串口1中断服务函数-----------------------------*/
//功能:帧头0,帧头1,帧尾0,帧尾1校验,得到一帧数据,接收到USART1_RecFrameFlag=1
//读取的数据放在USART1_RX_BUF[USART1_RX_STA]中;
//**********************************************************
void USART1_IRQHandler(void)                	//串口1中断服务程序
{
	u8 RES;
	u8 csumtemp=0;
	static u8 counttemp=1;
	if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)  //接收中断
	{
		
		RES =USART_ReceiveData(USART1);//(USART1->DR);	//读取接收到的数据		
		//***************校验
		if((USART1_RX_STA & 0x8000)==0)//接收未完成1000 0000 0000 0000
		{			
			//接收到了0x0d   0100 0000 0000 0000
			if(USART1_RX_STA&0x4000)
			{
				//不等于0x0a
				if(RES!=UART1_Rec_Tail1)
					  USART1_RX_STA=0;//接收错误,重新开始
				 //等于0x0a
				else 
				{
					USART1_RX_STA|=0x8000;	//接收完成了
					USART1_RecFrameFlag=1;//接收标记完整		
					//------------------------------------------------------------执行对应的动作
         //显示数据
					//LCD_ShowNumAsc32(0,32,RED,WHITE,USART1_RX_BUF[0],2);
					//LCD_ShowNumAsc32(64,32,RED,WHITE,USART1_RX_BUF[1],2);
//					LCD_ShowCharAsc32(0,32,RED, WHITE,USART1_RX_BUF[0]);
//					LCD_ShowCharAsc32(64,32,RED, WHITE,USART1_RX_BUF[1]);

//					LCD_ShowNumAsc32(0,64,RED,WHITE,USART1_RX_BUF[2],3);
//					LCD_ShowNumAsc32(64,64,RED,WHITE,USART1_RX_BUF[3],3);
//					
//					LCD_ShowNumAsc32(0,96,RED,WHITE,USART1_RX_BUF[4],3);
//					LCD_ShowNumAsc32(64,96,RED,WHITE,USART1_RX_BUF[5],3);
//					
//					LCD_ShowNumAsc32(0,128,RED,WHITE,USART1_RX_BUF[6],3);
//					LCD_ShowNumAsc32(64,128,RED,WHITE,USART1_RX_BUF[7],3);
//					
//					LCD_ShowNumAsc32(0,160,RED,WHITE,USART1_RX_BUF[8],3);
//					LCD_ShowNumAsc32(64,160,RED,WHITE,USART1_RX_BUF[9],3);
//					
//					LCD_ShowNumAsc32(0,192,RED,WHITE,USART1_RX_BUF[10],3);
//					
//					delay_ms(2000);
					//Lcd_Clear(BLUE);
				//	LCD_ShowNumAsc32(64,192,RED,WHITE,USART1_RX_BUF[9],2);
//				
//				  csumtemp=Usart1_GetCheckSum(USART1_RX_BUF,2,8);
//					LCD_ShowNumAsc32(64,192,GREEN,WHITE,csumtemp,3);

	     	Usart1_CheckAndDoAction();					
				}					
			}	
			else //还没收到0X0D
			{	
				//..............0x0D
				if(RES==UART1_Rec_Tail0)
				{
					USART1_RX_STA|=0x4000;//0100 0000 0000 0000
				}
				//...............
				else
				{
									//判断第一个帧头帧头
								if(USART1_RX_STA==0)
								{
									if(RES==UART1_Rec_Head0)//
									{						//				LCD_ShowCharAsc32(0,32,RED, WHITE,USART1_RX_BUF[0]);
							 USART1_RX_BUF[0]=RES ;
										USART1_RX_STA=1;
									}
									else 
										USART1_RX_STA=0;//接收错误,重新开始
								}
								//判断第二个帧头
								else if(USART1_RX_STA==1)
								{
									if(RES==UART1_Rec_Head1)//0x22
									{			 USART1_RX_BUF[1]=RES ;		
										USART1_RX_STA=2;	
									}
									else 
										USART1_RX_STA=0;//接收错误,重新开始
								}
								
								//第三个数据,完整接收
							 else if(USART1_RX_STA>1)//0-1---2.....---0x0d+0x0a
							 {//0011 1111 1111 1111
								 USART1_RX_BUF[USART1_RX_STA]=RES ;
						  	 USART1_RX_STA++;								 	
								if(USART1_RX_STA>(USART1_RX_MAX-1))
									   USART1_RX_STA=0;//接收数据错误,重新开始接收	 
							 }								
				}		 
			}
		}  
//		//*****************************************以上是校验的
		
  } 

}


/* 串口驱动函数,监测数据帧的接收,调度功能函数,需在主循环中调用 */
void Uart1Driver()
{
    unsigned char len;
    unsigned char  buf[15];//约定是13个字节数据,足够了

    if (USART1_RecFrameFlag) //有命令到达时,读取处理该命令
    {
        USART1_RecFrameFlag = 0;
        len = Uart1Read(buf, sizeof(buf));  //将接收到的命令读取到缓冲区中
        Usart1_DoAction(buf, len);  //传递数据帧,调用动作执行函数
    }
}
/* 串口数据读取函数,buf-接收指针,len-指定的读取长度,返回值-实际读到的长度 */
unsigned char Uart1Read(unsigned char *buf, unsigned char len)
{
    unsigned char i;
    for (i=0; i<len; i++)  //拷贝接收到的数据到接收指针上
    {
        *(buf+i) = USART1_RX_BUF[i];
    }
					
//					LCD_ShowCharAsc32(0,32,RED, WHITE,buf[0]);
//					LCD_ShowCharAsc32(64,32,RED, WHITE,buf[1]);

//					LCD_ShowNumAsc32(0,64,RED,WHITE,buf[2],3);
//					LCD_ShowNumAsc32(64,64,RED,WHITE,buf[3],3);
//					
//					LCD_ShowNumAsc32(0,96,RED,WHITE,buf[4],3);
//					LCD_ShowNumAsc32(64,96,RED,WHITE,USART1_RX_BUF[5],3);
//					
//					LCD_ShowNumAsc32(0,128,RED,WHITE,USART1_RX_BUF[6],3);
//					LCD_ShowNumAsc32(64,128,RED,WHITE,USART1_RX_BUF[7],3);
//					
//					LCD_ShowNumAsc32(0,160,RED,WHITE,USART1_RX_BUF[8],3);
//					LCD_ShowNumAsc32(64,160,RED,WHITE,USART1_RX_BUF[9],3);
//					
//					LCD_ShowNumAsc32(0,192,RED,WHITE,USART1_RX_BUF[10],3);
		
//		     delay_ms(3000);
//					LCD_ShowCharAsc32(0,32,GREEN, WHITE,*(buf));
//					LCD_ShowCharAsc32(64,32,GREEN, WHITE,*(buf+1));

//					LCD_ShowNumAsc32(0,64,GREEN,WHITE,*(buf+2),3);
//					LCD_ShowNumAsc32(64,64,GREEN,WHITE,*(buf+3),3);
//					
//					LCD_ShowNumAsc32(0,96,GREEN,WHITE,*(buf+4),3);
//					LCD_ShowNumAsc32(64,96,GREEN,WHITE,*(buf+5),3);
//					
//					LCD_ShowNumAsc32(0,128,GREEN,WHITE,*(buf+6),3);
//					LCD_ShowNumAsc32(64,128,GREEN,WHITE,*(buf+7),3);
//					
//					LCD_ShowNumAsc32(0,160,GREEN,WHITE,*(buf+8),3);
//					LCD_ShowNumAsc32(64,160,GREEN,WHITE,*(buf+9),3);
//					
//					LCD_ShowNumAsc32(0,192,GREEN,WHITE,*(buf+10),3);
				//	LCD_ShowNumAsc32(64,192,RED,WHITE,USART1_RX_BUF[9],2);
    return len;  //返回实际读取长度
}


//和校验,在Usart1_FunAction中使用
//参数:传入数据,和计算开始下标(从D0开始),计算长度,
//这里用Usart1_GetCheckSum(*ptr,2,8)
u8 Usart1_GetCheckSum(u8 *ptr,u8 csumbegin,u8 CsumCalLen)
{
	u8 t;
	u8 checksumtemp=0;
	//UART1_REC_Length=  USART1_RX_STA&0x3fff;buflen=10
	//这里的长度,是帧头和数据的,不包括校验码和帧尾
	//帧尾0和帧尾1不计算如长度,长度=帧头0+帧头1+数据。。。(D2-D9)
	//校验码只计算D2-D9
	//buflen=10 ,csumbegin=2,csumlen=8
	//D0  D1  D2 3 4 5 6 7 8 9  10 11 12
	//因为是计算D2---D9的数据,所以,求和的csumbegin=2,csumlen=8
  for(t=csumbegin;t<=(csumbegin+CsumCalLen-1);t++)//2+8-1
			{	 
				 checksumtemp+=*(ptr+t);	
			}
			checksumtemp=checksumtemp%256;//得到校验和
	return checksumtemp;

}
	//接收一帧数据,进入这个函数
//1、计算校验码,如果相等,1把数据复制到双缓冲区,2进行后面的动作解码、
//2、动作解码
void Usart1_CheckAndDoAction()
{
		u8 checksumtemp=0;	
		u8 lentemp=0;
		u8 usart1_doublebuffer[20];
  	checksumtemp=Usart1_GetCheckSum(USART1_RX_BUF,2,8);//D2---D2+8-1
		if(checksumtemp!=USART1_RX_BUF[10])//不等于校验码
		{
			// LCD_ShowNumAsc32(0,192,RED,WHITE,USART1_RX_BUF[10],3);
			// LCD_ShowNumAsc32(0,192+32,GREEN,WHITE,22,2);
			return;
		}
		else
		{			
		//	LCD_ShowNumAsc32(0,192,RED,WHITE,USART1_RX_BUF[10],3);
		//	LCD_ShowNumAsc32(0,192+32,GREEN,WHITE,55,2);
			
			USART1_RecCheckFrameFlag=1;	
			USART1_RX_STA=0;

			//关闭串口
			 // USART_Cmd(USART1, DISABLE);  //使能串口1 	
			//复制到双缓冲区
	  lentemp=Uart1Read(usart1_doublebuffer,sizeof(usart1_doublebuffer));
			//在缓冲区中进行处理
			//	USART_Cmd(USART1, ENABLE);  //使能串口1 	
		  Usart1_DoAction(usart1_doublebuffer,sizeof(usart1_doublebuffer));
		//	Usart1_DoAction0();
		//	USART_Cmd(USART1, DISABLE); 
		//	aaa();
		//	USART_Cmd(USART1, ENABLE);
			//校验成功进行操作
		}
	
}
/************************************************
函数名称 :usart_send()
功    能 :串口发送函数
参    数 :发送的字节
返 回 值 :无
作    者 :
*************************************************/
void usart1_send(u8 byte)
{
  USART_SendData(USART1,byte);
  while(USART_GetFlagStatus(USART1,USART_FLAG_TC) == RESET);//发送完成标志位
}

/*******************************************/
//函数功能:发送的应答信号
//设备号码,功能号码,应答信号
//第二个参数:Dat_AckOK
//==Dat_AckNG
//重发次数,超时时间,在超过一定时间没收到应答信号,那么就重发
u8 uart1SendSucAckCmd(u8 DeviceNum,u8 DeviceACKOK,u8 RetryNum,u16 timeout)
{
   unsigned char csum0;		
	 u8 i=0;
	 u16 count=0;//USART_RecAckFlag
  csum0=(DeviceNum+Fun_Ack+Dat_AckOK+UART1_Default_Char*5)%256;
	 for(i=0;i<RetryNum;i++)
	{
		 usart1_send(UART1_Rec_Head0);
		 usart1_send(UART1_Rec_Head1);
		 usart1_send(DeviceNum);//器件码
		 usart1_send(Fun_Ack);//功能码0xDD
		 usart1_send(Dat_AckOK);//应答是不是成功0xf0
		 usart1_send(UART1_Default_Char);//data1:0x55
		 usart1_send(UART1_Default_Char);//data2
		 usart1_send(UART1_Default_Char);//data3
		 usart1_send(UART1_Default_Char);//data4
		 usart1_send(UART1_Default_Char);//data5
		 usart1_send(csum0);//csum
		 usart1_send(UART1_Rec_Tail0);//帧尾0
		 usart1_send(UART1_Rec_Tail1);//帧尾1			
		 delay_ms(100);
	}
	return 1;
	//如果程序运行到了这里,那么就是没收到信号,发送不成功
	
}

/*******************************************/
//函数功能:发送的IO信号
//设备号码,IO状态
//2个参数:设备标签,IO状态
u8 uart1SendIOCmd(u8 DeviceNum,u8 sendiostatus,u8 RetryNum,u16 timeout)
{
    unsigned char csum0;		
	 u8 i=0;
	 u16 count=0;//USART_RecAckFlag8000/20=400
	 USART_RecAckFlag=0;
	 csum0=(DeviceNum+FunIO_Sig+sendiostatus+UART1_Default_Char*5)%256;
	 for(i=0;i<RetryNum;i++)
		{
			 usart1_send(UART1_Rec_Head0);
			 usart1_send(UART1_Rec_Head1);
			 usart1_send(DeviceNum);//器件码
			 usart1_send(FunIO_Sig);//功能码0x00,IO口信号
			 usart1_send(sendiostatus);//IO信号
			 usart1_send(UART1_Default_Char);//data1:0x55
			 usart1_send(UART1_Default_Char);//data2
			 usart1_send(UART1_Default_Char);//data3
			 usart1_send(UART1_Default_Char);//data4
			 usart1_send(UART1_Default_Char);//data5
			 usart1_send(csum0);//csum
			 usart1_send(UART1_Rec_Tail0);//帧尾0
			 usart1_send(UART1_Rec_Tail1);//帧尾1	
			//20ms计算一次---15*13=
			 while(USART_RecAckFlag == 0)//在接收的doaction函数中,改变
			 {
				delay_ms(15);
				count++;
				if (count >=timeout/15)//如果超时,跳出循环,再发一次
						 break;
			 }			 
		//如果在规定的时间内收到了应答,则直接返回,如果没有应答则继续重发        
			 if (count<timeout/15) 			 
			 {
			   return 1 ;
			 }		
			 count = 0;
		}
		return 0;

}
/*******************************************/
//函数功能:发送的浮点数
//设备号码,功能号码,数据
//第二个参数:Fun_AckOK
//==Fun_AckNG
//应答类型
u8 Uart1SendFloatDataCmd(u8 DeviceNum,u8 DevFunNum,float sendFloatdata,u8 RetryNum,u16 timeout)
{
   unsigned char csum0;		
	 u8 i=0;
	 u8 count=0;//USART_RecAckFlag
	 USART_RecAckFlag=0;
	floattemp.floatdata= sendFloatdata;
	
  csum0=(DeviceNum+DevFunNum+floattemp.floatchararray[0]+floattemp.floatchararray[1]\
	+floattemp.floatchararray[2]+floattemp.floatchararray[3]+UART1_Default_Char+UART1_Default_Char)%256;
	
		 for(i=0;i<RetryNum;i++)
		{
			 usart1_send(UART1_Rec_Head0);
			 usart1_send(UART1_Rec_Head1);
			 usart1_send(DeviceNum);//器件码
			 usart1_send(DevFunNum);//功能码0xDD
			 usart1_send(floattemp.floatchararray[0]);//应答是不是成功
			 usart1_send(floattemp.floatchararray[1]);//data1:0x55
			 usart1_send(floattemp.floatchararray[2]);//data2
			 usart1_send(floattemp.floatchararray[3]);//data3
			 usart1_send(UART1_Default_Char);//data4
			 usart1_send(UART1_Default_Char);//data5
			 usart1_send(csum0);//csum
			 usart1_send(UART1_Rec_Tail0);//帧尾0
			 usart1_send(UART1_Rec_Tail1);//帧尾1
			
				//20ms计算一次
			 while(USART_RecAckFlag == 0)//在接收的doaction函数中,改变
			 {
				delay_ms(20);
				count++;
				if (count >=timeout/20)//如果超时,跳出循环,再发一次
						 break;
			 }
		//如果在规定的时间内收到了应答,则直接返回,如果没有应答则继续重发        
			 if (count<timeout/20) 
					 return 1 ;
			 count = 0;
		}
		return 0;

}

/*******************************************/
//函数功能:发送的浮点数
//设备号码,功能号码,数据
//第二个参数:Fun_AckOK
//==Fun_AckNG
//应答类型
u8 Uart1SendInt32DataCmd(u8 DeviceNum,u8 DevFunNum,int32_t sendint32,u8 RetryNum,u16 timeout)
{
   unsigned char csum0;		
	 u8 i=0;
	 u8 count=0;//USART_RecAckFlag
	 USART_RecAckFlag=0;
	int32temp.intdata= sendint32;
	 
	csum0=(DeviceNum+DevFunNum+int32temp.intchararray[0]+int32temp.intchararray[1]\
	+int32temp.intchararray[2]+int32temp.intchararray[3]+UART1_Default_Char+UART1_Default_Char)%256;
	
	 for(i=0;i<RetryNum;i++)
	{
	 usart1_send(UART1_Rec_Head0);
	 usart1_send(UART1_Rec_Head1);
	 usart1_send(DeviceNum);//器件码
   usart1_send(DevFunNum);//功能码0xDD
   usart1_send(int32temp.intchararray[0]);//应答是不是成功
   usart1_send(int32temp.intchararray[1]);//应答是不是成功
	 usart1_send(int32temp.intchararray[2]);//应答是不是成功
	 usart1_send(int32temp.intchararray[3]);//应答是不是成功
	 usart1_send(UART1_Default_Char);//data4
	 usart1_send(UART1_Default_Char);//data5
	 usart1_send(csum0);//csum
	 usart1_send(UART1_Rec_Tail0);//帧尾0
	 usart1_send(UART1_Rec_Tail1);//帧尾1
		
				//20ms计算一次
	 while(USART_RecAckFlag == 0)//在接收的doaction函数中,改变
	 {
		delay_ms(20);
		count++;
		if (count >=timeout/20)//如果超时,跳出循环,再发一次
				 break;
	 }
//如果在规定的时间内收到了应答,则直接返回,如果没有应答则继续重发        
	 if (count<timeout/20) 
			 return 1;
	 count = 0;
		
	}
	return 0;

}

void Usart1_DoAction(unsigned char *buf, unsigned char len)//校验成功进行操作
{
	u8 AckResult=0;
	//已经校验成功
	switch(buf[2])//判断设备码
	{
		//电机设备
		case DevMotorX:
		{
			switch(buf[3])//功能码
		  {
				case FunMotorMM://mm,浮点数
					floattemp.floatchararray[0]=buf[4];
					floattemp.floatchararray[1]=buf[5];
					floattemp.floatchararray[2]=buf[6];
					floattemp.floatchararray[3]=buf[7];
					AckResult=uart1SendSucAckCmd(DevMotorX,Dat_AckOK,5,200);//发送应答号码
					if(AckResult==0)//不成功应答,退出程序
					{
						return;
					}
					//成功应答
					//将浮点数运动位移(直线位移或者角位移)获取,赋值给下位机的Xmm
					//将xmm转换成脉冲数
							
				break;
				
			  case FunMOTORPUL://pul,整数
					int32temp.intchararray[0]=buf[4];
				  int32temp.intchararray[1]=buf[5];	
				  int32temp.intchararray[2]=buf[6];		
				  int32temp.intchararray[3]=buf[7];
					AckResult=uart1SendSucAckCmd(DevMotorX,Dat_AckOK,5,200);//发送应答号码
					if(AckResult==0)//不成功应答,退出程序
					{
						return;
					}
					//成功应答
					//将整数脉冲赋值给xpul	
				break;
							
				case FunMotorVELMM://mm/s,浮点数
					floattemp.floatchararray[0]=buf[4];
					floattemp.floatchararray[1]=buf[5];
					floattemp.floatchararray[2]=buf[6];
					floattemp.floatchararray[3]=buf[7];
					AckResult=uart1SendSucAckCmd(DevMotorX,Dat_AckOK,5,200);//发送应答号码
					if(AckResult==0)//不成功应答,退出程序
					{
						return;
					}
					//成功应答
					//将浮点数运动速度获取,赋值给下位机的Xvelmmps
					//将xvelmmps转换成pulps;
				
				break;
										
				case FunMotorVELPUL://pul/s,整数
					int32temp.intchararray[0]=buf[4];
				  int32temp.intchararray[1]=buf[5];	
				  int32temp.intchararray[2]=buf[6];		
				  int32temp.intchararray[3]=buf[7];
					AckResult=uart1SendSucAckCmd(DevMotorX,Dat_AckOK,5,200);//发送应答号码
					if(AckResult==0)//不成功应答,退出程序
					{
						return;
					}
					//成功应答
					//将整数脉冲速度赋值给xpulps
				
				break;
				
				case FunMotorDIR://整数,0
				  //XDIR=buf[4];//方向信号
					AckResult=uart1SendSucAckCmd(DevMotorX,Dat_AckOK,5,200);//发送应答号码

				break;
				
				case FunMotorRUN:
					//xrunflag=1;//运动标记=1
					AckResult=uart1SendSucAckCmd(DevMotorX,Dat_AckOK,5,200);//发送应答号码

					break;
				case FunMotorSTOP:
						AckResult=uart1SendSucAckCmd(DevMotorX,Dat_AckOK,5,200);//发送应答号码
					//xrunflag=0;//运动标记=0		
					break;
				
				case Fun_Ack://收到应答信号
				{
					USART_RecAckFlag=1;
				}
				break;
				
				default:break;
			}
		}
			break;
		case DevMotorY:
		{
				switch(buf[3])//功能码
		  {
				case FunMotorMM:
				break;
				
			  case FunMOTORPUL:
				break;
							
				case FunMotorVELMM:
				break;
										
				case FunMotorVELPUL:
				break;
				
				case FunMotorDIR:
				break;
				
				case FunMotorRUN:
					break;
				case FunMotorSTOP:
					break;
				case Fun_Ack://收到应答信号
					USART_RecAckFlag=1;
				break;
				
				default:break;
			}
		}
			break;
		case DevMotorZ:
		{
				switch(buf[3])//功能码
		  {
				case FunMotorMM:
				break;
				
			  case FunMOTORPUL:
				break;
							
				case FunMotorVELMM:
				break;
										
				case FunMotorVELPUL:
				break;
				
				case FunMotorDIR:
				break;
				
				case FunMotorRUN:
					break;
				case FunMotorSTOP:
					break;
				case Fun_Ack://收到应答信号
					USART_RecAckFlag=1;
				break;
				
				default:break;
			}
		}
			break;
		case DevMotorA:
		{
				switch(buf[3])//功能码
		  {
				case FunMotorMM:
				break;
				
			  case FunMOTORPUL:
				break;
							
				case FunMotorVELMM:
				break;
										
				case FunMotorVELPUL:
				break;
				
				case FunMotorDIR:
				break;
				
				case FunMotorRUN:
					break;
				case FunMotorSTOP:
					break;
				case Fun_Ack://收到应答信号
					USART_RecAckFlag=1;
				break;
				
				default:break;
			}
		}
			break;
		case DevMotorB:
		{
				switch(buf[3])//功能码
		  {
				case FunMotorMM:
				break;
				
			  case FunMOTORPUL:
				break;
							
				case FunMotorVELMM:
				break;
										
				case FunMotorVELPUL:
				break;
				
				case FunMotorDIR:
				break;
				
				case FunMotorRUN:
					break;
				case FunMotorSTOP:
					break;
				case Fun_Ack://收到应答信号
					USART_RecAckFlag=1;
				break;
				
				default:break;
			}
		}
			break;
		case DevMotorC:
		{
				switch(buf[3])//功能码
		  {
				case FunMotorMM:
				break;
				
			  case FunMOTORPUL:
				break;
							
				case FunMotorVELMM:
				break;
										
				case FunMotorVELPUL:
				break;
				
				case FunMotorDIR:
				break;
				
				case FunMotorRUN:
					break;
				case FunMotorSTOP:
					break;
				case Fun_Ack://收到应答信号
					USART_RecAckFlag=1;
				break;
				
				default:break;
			}
		}
			break;
		//X限位传感器设备
		case DevXLeftLimit:
		{
			switch(buf[3])
			{
				case DatLimitSenseUP://没碰到开关
					//xleftLimitSense=0;
						AckResult=uart1SendSucAckCmd(DevMotorX,Dat_AckOK,5,200);//发送应答号码

					break;
				case DatLimitSenseDown://触碰到限位开关
						AckResult=uart1SendSucAckCmd(DevMotorX,Dat_AckOK,5,200);//发送应答号码

					//xleftLimitSense=1;
					break;

				case Fun_Ack://收到应答信号
					USART_RecAckFlag=1;
				break;
				
				default:break;			
			}
		}
			break;
		case DevXRightLimit:
		{
				switch(buf[3])
			{
				case DatLimitSenseUP://没碰到开关
					AckResult=uart1SendSucAckCmd(DevMotorX,Dat_AckOK,5,200);//发送应答号
					//xrightLimitSense=0;
					break;
				case DatLimitSenseDown://触碰到限位开关
					AckResult=uart1SendSucAckCmd(DevMotorX,Dat_AckOK,5,200);//发送应答号
					//xrightLimitSense=1;
					break;
				
				
				case Fun_Ack://收到应答信号
					USART_RecAckFlag=1;
				break;
				
				default:break;			
			}
		}
			break;
		case DevXOrigin:
		{
			switch(buf[3])
			{
				case DatLimitSenseUP://没碰到开关
						AckResult=uart1SendSucAckCmd(DevMotorX,Dat_AckOK,5,200);//发送应答号码
					//xoriginLimitSense=0;
					break;
				case DatLimitSenseDown://触碰到限位开关
				  AckResult=uart1SendSucAckCmd(DevMotorX,Dat_AckOK,5,200);//发送应答号码
					//xoriginLimitSense=1;
					break;
				case Fun_Ack://收到应答信号
					USART_RecAckFlag=1;
				break;
				
				default:break;			
			}
		}
			break;
		//Y限位传感器设备
		case DevYLeftLimit:
		{
				switch(buf[3])
			{
				case DatLimitSenseUP://没碰到开关
					
					break;
				case DatLimitSenseDown://触碰到限位开关
					
					break;
				case Fun_Ack://收到应答信号
					USART_RecAckFlag=1;
				break;
				
				default:break;			
			}
		}
			break;
		case DevYRightLimit:
		{
				switch(buf[3])
			{
				case DatLimitSenseUP://没碰到开关
					
					break;
				case DatLimitSenseDown://触碰到限位开关
					
					break;
				case Fun_Ack://收到应答信号
					USART_RecAckFlag=1;
				break;
				
				default:break;			
			}
		}
			break;
		case DevYOrigin:
		{
				switch(buf[3])
			{
				case DatLimitSenseUP://没碰到开关
					
					break;
				case DatLimitSenseDown://触碰到限位开关
					
					break;
				case Fun_Ack://收到应答信号
					USART_RecAckFlag=1;
				break;
				
				default:break;			
			}
		}
			break;
		//Z限位传感器设备
		case DevZLeftLimit:
		{
				switch(buf[3])
			{
				case DatLimitSenseUP://没碰到开关
					
					break;
				case DatLimitSenseDown://触碰到限位开关
					
					break;
				case Fun_Ack://收到应答信号
					USART_RecAckFlag=1;
				break;
				
				default:break;			
			}
		}
			break;
		case DevZRightLimit:
		{
			switch(buf[3])
			{
				case DatLimitSenseUP://没碰到开关
					
					break;
				case DatLimitSenseDown://触碰到限位开关
					
					break;
				case Fun_Ack://收到应答信号
					USART_RecAckFlag=1;
				break;
				
				default:break;			
			}
		}
			break;
		case DevZOrigin:
		{
			switch(buf[3])
			{
				case DatLimitSenseUP://没碰到开关
					
					break;
				case DatLimitSenseDown://触碰到限位开关
					
					break;
				case Fun_Ack://收到应答信号
					USART_RecAckFlag=1;
				break;
				
				default:break;			
			}
		}
			break;
		//A限位传感器设备
		case DevALeftLimit:
		{
			switch(buf[3])
			{
				case DatLimitSenseUP://没碰到开关
					
					break;
				case DatLimitSenseDown://触碰到限位开关
					
					break;
				case Fun_Ack://收到应答信号
					USART_RecAckFlag=1;
				break;
				
				default:break;			
			}
		}
			break;
		case DevARightLimit:
		{
			switch(buf[3])
			{
				case DatLimitSenseUP://没碰到开关
					
					break;
				case DatLimitSenseDown://触碰到限位开关
					
					break;
				case Fun_Ack://收到应答信号
					USART_RecAckFlag=1;
				break;
				
				default:break;			
			}
		}
			break;
		case DevAOrigin:
		{
			switch(buf[3])
			{
				case DatLimitSenseUP://没碰到开关
					
					break;
				case DatLimitSenseDown://触碰到限位开关
					
					break;
				case Fun_Ack://收到应答信号
					USART_RecAckFlag=1;
				break;
				
				default:break;			
			}
		}
			break;
		//B限位传感器设备
		case DevBLeftLimit:
		{
			switch(buf[3])
			{
				case DatLimitSenseUP://没碰到开关
					
					break;
				case DatLimitSenseDown://触碰到限位开关
					
					break;
				case Fun_Ack://收到应答信号
					USART_RecAckFlag=1;
				break;
				
				default:break;			
			}
		}
			break;
		case DevBRightLimit:
		{
			switch(buf[3])
			{
				case DatLimitSenseUP://没碰到开关
					
					break;
				case DatLimitSenseDown://触碰到限位开关
					
					break;
				case Fun_Ack://收到应答信号
					USART_RecAckFlag=1;
				break;
				
				default:break;			
			}
		}
			break;
		case DevBOrigin:
		{
			switch(buf[3])
			{
				case DatLimitSenseUP://没碰到开关
					
					break;
				case DatLimitSenseDown://触碰到限位开关
					
					break;
				case Fun_Ack://收到应答信号
					USART_RecAckFlag=1;
				break;
				
				default:break;			
			}
		}
			break;
		//C限位传感器设备
		case DevCLeftLimit:
		{
			switch(buf[3])
			{
				case DatLimitSenseUP://没碰到开关
					
					break;
				case DatLimitSenseDown://触碰到限位开关
					
					break;
				case Fun_Ack://收到应答信号
					USART_RecAckFlag=1;
				break;
				
				default:break;			
			}
		}
			break;
		case DevCRightLimit:
		{
			switch(buf[3])
			{
				case DatLimitSenseUP://没碰到开关
					
					break;
				case DatLimitSenseDown://触碰到限位开关
					
					break;
				case Fun_Ack://收到应答信号
					USART_RecAckFlag=1;
				break;
				
				default:break;			
			}
		}
			break;
		case DevCOrigin:
		{
			switch(buf[3])
			{
				case DatLimitSenseUP://没碰到开关
					
					break;
				case DatLimitSenseDown://触碰到限位开关
					
					break;
				case Fun_Ack://收到应答信号
					USART_RecAckFlag=1;
				break;
				
				default:break;			
			}
		}
			break;
		
		//------------IO开关
		case DevIO_S1://D0=0x21,D1=0x22,D2=0x80,D3=0xDD/0x00,D4=0xf0/(0x00-0x01)
		{
			switch(buf[3])//0x
			{
				case FunIO_Sig://0x00
					switch(buf[4])
					{
							case DatIO_S1_OFF_Sig://没碰到开关
							//IO_S1=buf[4];
							
							break;
						 case DatIO_S1_ON_Sig://触碰到限位开关
							//IO_S1=buf[4];
							break;
						 default:break;
					}
				break;
				case Fun_Ack://DD
					  if(buf[4]==Dat_AckOK)//f0
						{	
							USART_RecAckFlag=1;//
							LCD_ShowNumAsc32(160,0,GREEN,WHITE,99,2);//
						//	delay_ms(2000);
							Lcd_Clear(BLUE);//清屏,颜色
						}
						else if(buf[4]==Dat_AckNG)
						{
								USART_RecAckFlag=1;//
							LCD_ShowNumAsc32(160,0,GREEN,WHITE,55,2);//
					//		delay_ms(2000);
							Lcd_Clear(BLUE);//清屏,颜色
						}
				break;
				default:break;			
			}
		}
			break;
		case DevIO_S2:
		{
			switch(buf[3])//0x
			{
				case FunIO_Sig://0x00
					switch(buf[4])
					{
							case DatIO_S2_OFF_Sig://没碰到开关
							//IO_S1=buf[4];
							break;
						 case DatIO_S2_ON_Sig://触碰到限位开关
							//IO_S1=buf[4];
							break;
						 default:break;
					}
				break;
				case Fun_Ack:
					  if(buf[4]==Dat_AckOK)
						{	
							USART_RecAckFlag=1;
							LCD_ShowNumAsc32(160,0,GREEN,WHITE,99,2);
						}
				break;
				default:break;			
			}
		}
			break;
		//---------------------------------------------------------
		case DevIO_S3:
		{
			switch(buf[3])//0x
			{
				case FunIO_Sig://0x00
					switch(buf[4])
					{
							case DatIO_S3_OFF_Sig://没碰到开关
							//IO_S1=buf[4];
							break;
						 case DatIO_S3_ON_Sig://触碰到限位开关
							//IO_S1=buf[4];
							break;
						 default:break;
					}
				break;
				case Fun_Ack:
					  if(buf[4]==Dat_AckOK)
						{	
							USART_RecAckFlag=1;
							LCD_ShowNumAsc32(160,0,GREEN,WHITE,99,2);
						}
				break;
				default:break;			
			}
		}
			break;
		//-------------------------------------
		case DevIO_S4:
		{
			switch(buf[3])//0x
			{
				case FunIO_Sig://0x00
					switch(buf[4])
					{
							case DatIO_S4_OFF_Sig://没碰到开关
							//IO_S1=buf[4];
							break;
						 case DatIO_S4_ON_Sig://触碰到限位开关
							//IO_S1=buf[4];
							break;
						 default:break;
					}
				break;
				case Fun_Ack:
					  if(buf[4]==Dat_AckOK)
						{	
							USART_RecAckFlag=1;
							LCD_ShowNumAsc32(160,0,GREEN,WHITE,99,2);
						}
				break;
				default:break;			
			}
		}
			break;
		//-----------------------------
	  case DevIO_S5:
		{
		switch(buf[3])//0x
			{
				case FunIO_Sig://0x00
					switch(buf[4])
					{
							case DatIO_S5_OFF_Sig://没碰到开关
							//IO_S1=buf[4];
							break;
						 case DatIO_S5_ON_Sig://触碰到限位开关
							//IO_S1=buf[4];
							break;
						 default:break;
					}
				break;
				case Fun_Ack:
					  if(buf[4]==Dat_AckOK)
						{	
							USART_RecAckFlag=1;
							LCD_ShowNumAsc32(160,0,GREEN,WHITE,99,2);
						}
				break;
				default:break;			
			}
		}
			break;
		//------------------------------------------
		case DevIO_S6:
		{
	switch(buf[3])//0x
			{
				case FunIO_Sig://0x00
					switch(buf[4])
					{
							case DatIO_S6_OFF_Sig://没碰到开关
							//IO_S1=buf[4];
							break;
						 case DatIO_S6_ON_Sig://触碰到限位开关
							//IO_S1=buf[4];
							break;
						 default:break;
					}
				break;
				case Fun_Ack:
					  if(buf[4]==Dat_AckOK)
						{	
							USART_RecAckFlag=1;
							LCD_ShowNumAsc32(160,0,GREEN,WHITE,99,2);
						}
				break;
				default:break;			
			}
		}
			break;
		//--------------------------------
		default:break;
		
		
	}
}


//------------------------

main.c

#include "stm32f4xx.h"
#include "led.h"  
#include "key.h"
#include "delayzd.h" 
#include "usart.h"
#include "Lcd_Driver.h"
#include "stdio.h"
#include "sys.h" //位操作
int main(void)
{
	u8 i = 0;
	delay_init(168);
  Usart1_Config(115200);
	Lcd_Init();
	delay_ms(20);
	Lcd_Clear(BLUE);//清屏,颜色
	LED_Init();	
	//LCD_ShowStringAsc32(0,0,RED,WHITE,"LMF222000");
	LCD_ShowCharAsc32(0,0,RED, WHITE,0x35);
	LCD_ShowCharAsc32(64,0,RED, WHITE,0x22);
	delay_ms(1000);
//	printf("STM32F103ZET6核心板串口测试\r\n");
//	printf("反客科技\r\n");		
	while(1)
	{		
//		LED1=0;
//		delay_ms(5000);
//		LED1=1;
//		delay_ms(5000);
			uart1SendSucAckCmd(DevMotorX,Dat_AckOK,5,1000);
//			// 21 22 00 DD 01 55 55 55 55 55 87 0D 0A 
  		uart1SendIOCmd(DevIO_S1,DatIO_S1_OFF_Sig,5,2000);
	   delay_ms(2000);
		//	Lcd_Clear(BLUE);//清屏,颜色

		   uart1SendIOCmd(DevIO_S1,DatIO_S1_ON_Sig,5,2000);
			 	   delay_ms(2000);

		

//			// 串口助手收80 00 00 55 55 55 55 55 29 0D 0A 
			Uart1SendFloatDataCmd(DevMotorX,FunMotorMM,52.65,5,2000);
//			//串口助手收21 22 00 00 9A 99 52 42 55 55 71 0D 0A  
//			//fd3 d2 d1 d0
//			// 9a 99 52 42(高字节在低地址空间)
//			//fc0 c1 c2 c3,联合体中,carray0==fd3高地址,对应低字节
//			//32发送的时候,注意,发chararray0,1,2,3,还是char 3 2 1 0,
//			//将决定了接收端的大端小端模式
//			//http://www.speedfly.cn/tools/hexconvert/
//			//52.65浮点数的IE表示是42 52 99 99
//			//单片机接收到的是9A 99 52 42,说明是
//			//测试结论:c0--低,c1,次低,c2次高,c3高
//			//stm32是小端模式,如一个32位无符号数0x12345678,
//			//从低地址到高地址依次储存 78h  56h 34h 12h。
  		Uart1SendInt32DataCmd(DevMotorX,FunMOTORPUL,1000,5,2000);
//			//串口助手收:21 22 00 01 E8 03 00 00 55 55 96 0D 0A 
//			//1000-------0x00 00 03 E8 
//			//联合体,intd3  d2   d1   d0
//			//    arr    00  00  03    E8
//			//arr0对应数据的高字节,特别注意,因为联合体中int32和char数组联用同一个内存
//			//int 存放的

	}
}


5.2上位机的串口代码
代码接收

    private void serialPort1_DataReceived(object sender, SerialDataReceivedEventArgs e)
        {
            byte[] Data = new byte[serialPort1.BytesToRead];    //定义缓冲区,因为串口接收事件触发时字节数不固定
            bool Rec_Flag = true;
            bool UpdateData = false;
            byte[] bytestemp = new byte[4];
             ushort AckResult=0;
     //单设备,如果是接收的数据字节长度小于13,接收标记等于假
    //帧头0+帧头1+------功能码+器件码+数据码1+数据码2+数据码3+数据码4+数据码5+数据码6+校验码CSUM+帧尾0+帧尾1。(0-12)
            if (Data.Length < 13)
            {
                Rec_Flag = false;
            }    
            //接收到一帧数据
            if (Rec_Flag == true)
            {
                try
                {
                    //将缓冲区的数据读取,放在data数组中
                    serialPort1.Read(Data, 0, Data.Length);
                    //在文本框中显示信息
                    textBox15.AppendText("[" + DateTime.Now.ToString("HH:mm:ss") + "]" + "收 <- ");  
                    foreach (byte Member in Data)        //遍历用法
                    {
                        string str = Convert.ToString(Member, 16).ToUpper();//转换成16进制的字符
                        textBox15.AppendText((str.Length == 1 ? "0" + str : str) + " ");
                    }
                    textBox15.AppendText("\r\n");
                }
                catch { }

                //数据校验
                if (Data.Length == 13)  //单设备模式
                {
           //帧头0+帧头1+------功能码+器件码+数据码1+数据码2+数据码3+数据码4+数据码5+数据码6+校验码CSUM+帧尾0+帧尾1。
               //校验和
                    //判断帧头0和帧头1是不是相等,是的话,进行后面的处理,否则退出
                    if (Data[0] == Head[0])
                    {
                        if (Data[1] == Head[1])
                        {
                            int csum = CheckSumAction(Data, 13);
                            if (Data[10] == csum)  //校验正确
                            {
                                UpdateData = true;
                            }
                            else //校验错误  
                            {
                                textBox15.AppendText("\r\n和校验值错误,请检查校验算法!!\r\n");
                            }
                        }
                        else
                            return;
                    }
                    else
                        return;     
                }
                else
                {
                    textBox15.AppendText("\r\n返回的字节数不对!!\r\n");
                }


                数据解析,校验正确,那么显示在文本框中
                if (UpdateData == true)
                {               
                    UpdateChanData(textBox1, Data, 1);
                    UpdateChanData(textBox2, Data, 2);
                    UpdateChanData(textBox3, Data, 3);
                    UpdateChanData(textBox4, Data, 4);
                    UpdateChanData(textBox5, Data, 5);
                    UpdateChanData(textBox6, Data, 6);
                    UpdateChanData(textBox7, Data, 7);
                    UpdateChanData(textBox8, Data, 8);
                    UpdateChanData(textBox9, Data, 9);
                    UpdateChanData(textBox10, Data, 10);
                    UpdateChanData(textBox11, Data, 11);
                    UpdateChanData(textBox12, Data, 12);
                    UpdateChanData(textBox13, Data, 13);
                    //接收的数据OK,判断是什么信息
                    //根据接收到的设备号进行判断,
                    switch (Data[2])
                    { 
            //应答信号处理,3秒内进行处理,超过3秒没有收到应答,进行应答错误提示-------------------
                        case 0x00://X电机
                            switch (Data[3])//功能码
                            {
                                    //---------------------------------------------------------------------------
                                case 0x00://mm,浮点数              
                                     AckResult = SendAckToSerialPort(serialPort1,0x00,0xDD, 0xf0,5,200);//发送应答号码,没有超时间界定,只有连续发N次
                                  
                                    //成功应答
                                    //将浮点数运动位移(直线位移或者角位移)获取,赋值给下位机的Xmm
                                    //将xmm转换成脉冲数
                                    bytestemp[0] = Data[4];
                                    bytestemp[1] = Data[5];
                                    bytestemp[2] = Data[6];
                                    bytestemp[3] = Data[7];
                                    float fdata = BitConverter.ToSingle(bytestemp, 0);;
                                    textBox16.Text = Convert.ToString(fdata);
                                    textBox17.Text ="xxx";
                                    textBox18.Text = "XMNC";

                                    break;
                                    //---------------------------------------------------------------------------------
                                case 0x01://pul,整数
                                   
                                    AckResult = SendAckToSerialPort(serialPort1,0x00,0xDD, 0xf0,5,200);//发送应答号码
                                    //if (AckResult == 0)//不成功应答,退出程序
                                    //{
                                    //    return;
                                    //}
                                    //成功应答
                                    //将浮点数运动位移(直线位移或者角位移)获取,赋值给下位机的Xmm
                                    //将xmm转换成脉冲数  
         	                        bytestemp[0] = Data[4];
                                    bytestemp[1] = Data[5];
                                    bytestemp[2] = Data[6];
                                    bytestemp[3] = Data[7];
                                    Int32 intdata = BitConverter.ToInt32(bytestemp,0);
                                    textBox16.Text = "xxx";
                                    textBox17.Text = Convert.ToString(intdata);
                                    textBox18.Text = "XMNC";

                                    break;
                                    //----------------------------------------------------------------
                                case 0xDD://应答
                                    Program.USART1_RecAckFlag = 1;
                                    textBox18.Text = "XMACK";
                                    break;

                            }
                            break;
                            //---------------------------------------------------------------------------
                            //---------------------------------------------------------------------------
                        case 0x80://第一个IO口D2=0x80,D3=0xDD/0x00,
                                      switch (Data[3])//功能码---IO口的话,D3=0xDD/0x00,D4=0xf0/(0x00-0x01)
                                    {
                                        case 0x00://IO状态
                                            if(Data[4]==0x00)
                                            {
                                                button17.BackColor = Color.Red;
                                                AckResult = SendAckToSerialPort(serialPort1, 0x80, 0xDD, 0xF0,3, 1000);//发送应答号码

                                            }
                                            else if(Data[4]==0x01)
                                           { 
                                              button17.BackColor = Color.Green;
                                              AckResult = SendAckToSerialPort(serialPort1, 0x80, 0xDD, 0xF0,3, 1000);//发送应答号码
                                            }

                                            break;
                                              //--------------------------------
                                          case 0xDD://收到应答信号

                                            break;
                                              //-------------------------------
                                          default: break;
                                    }
                                      break;
                        default:break;
                    }
                }
            }
        }

代码发送应答信号

 private ushort SendAckToSerialPort(SerialPort MyPort, byte DeviceNum, byte AckFunCodetemp, byte AckType, ushort retrynum, Int16 timeoutset)//AckFunCodetemp
        {
            byte csumtemp = 0x00;
            int sumtemp = 0;
            ushort i = 0;
            Program.USART1_RecAckFlag = 0;
            sumtemp = DeviceNum + AckFunCodetemp + AckType + 0x55 + 0x55 + 0x55 + 0x55 + 0x55;//AckFunCodetemp=0xDD
            csumtemp = (byte)(sumtemp % 256);
            byte[] AckTempData0 = new byte [13]{0x21,0x22,DeviceNum,AckFunCodetemp, AckType, 0x55, 0x55, 0x55, 0x55, 0x55, csumtemp, 0x0D, 0x0A };
            byte[] AckTempData00 = new byte[1];
            AckTempData00[0] = AckTempData0[0];
            byte[] AckTempData01 = new byte[1];
            AckTempData01[0] = AckTempData0[1];
            byte[] AckTempData02 = new byte[1];
            AckTempData02[0] = AckTempData0[2];
            byte[] AckTempData03 = new byte[1];
            AckTempData03[0] = AckTempData0[3];
            byte[] AckTempData04 = new byte[1];
            AckTempData04[0] = AckTempData0[4];
            byte[] AckTempData05 = new byte[1];
            AckTempData05[0] = AckTempData0[5];
            byte[] AckTempData06 = new byte[1];
            AckTempData06[0] = AckTempData0[6];
            byte[] AckTempData07 = new byte[1];
            AckTempData07[0] = AckTempData0[7];
            byte[] AckTempData08 = new byte[1];
            AckTempData08[0] = AckTempData0[8];
            byte[] AckTempData09 = new byte[1];
            AckTempData09[0] = AckTempData0[9];
            byte[] AckTempData10 = new byte[1];
            AckTempData10[0] = AckTempData0[10];
            byte[] AckTempData11 = new byte[1];
            AckTempData11[0] = AckTempData0[11];
            byte[] AckTempData12 = new byte[1];
            AckTempData12[0] = AckTempData0[12];

            ushort tt =2;
            if (serialPort1.IsOpen)
            {
                for (i = 0; i < retrynum; i++)
                {
                    serialPort1.Write(AckTempData00, 0, 1); System.Threading.Thread.Sleep(tt);
                    serialPort1.Write(AckTempData01, 0, 1); System.Threading.Thread.Sleep(tt);
                    serialPort1.Write(AckTempData02, 0, 1); System.Threading.Thread.Sleep(tt);
                    serialPort1.Write(AckTempData03, 0, 1); System.Threading.Thread.Sleep(tt);
                    serialPort1.Write(AckTempData04, 0, 1); System.Threading.Thread.Sleep(tt);
                    serialPort1.Write(AckTempData05, 0, 1); System.Threading.Thread.Sleep(tt);
                    serialPort1.Write(AckTempData06, 0, 1); System.Threading.Thread.Sleep(tt);
                    serialPort1.Write(AckTempData07, 0, 1); System.Threading.Thread.Sleep(tt);
                    serialPort1.Write(AckTempData08, 0, 1); System.Threading.Thread.Sleep(tt);
                    serialPort1.Write(AckTempData09, 0, 1); System.Threading.Thread.Sleep(tt);
                    serialPort1.Write(AckTempData10, 0, 1); System.Threading.Thread.Sleep(tt);
                    serialPort1.Write(AckTempData11, 0, 1); System.Threading.Thread.Sleep(tt);
                    serialPort1.Write(AckTempData12, 0, 1); System.Threading.Thread.Sleep(tt);
                }
                   

            }
           
            return 1;//没应答,返回0                     
        }

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

第一阶段C#串口上位机练习--stm32F4总结 的相关文章

  • STM32中SysTick、FCLK、SYSCLK、HCLK

    http rmingwang com the stm32 systick fclk sysclk hclk html 转载原文 在STM32中 xff0c 有五个时钟源 xff0c 为HSI HSE LSI LSE PLL HSI是高速内部
  • qglobal.h:45: error: C1083: 无法打开包括文件:

    看了很多人的错误调试记录就是不行 xff0c 后来在百度知道里面看到这个 xff0c 添加进入后就可以了 在系统环境变量path 添加下面内容即可 SystemRoot system32
  • 卡尔曼滤波器学习笔记(二)

    扩展卡尔曼滤波器的原理及应用 经典的卡尔曼滤波只适用于线性且满足高斯分布的系统 xff0c 但实际工程中并不是这么简单 xff0c 比如飞行器在水平运动时有可能伴随着自身的自旋 xff0c 此时的系统并不是线性的 xff0c 这时就需要应用
  • 串口回环测试

    串口lookback测试 基础知识 通用异步收发传输器 xff08 Universal Asynchronous Receiver Transmitter xff09 xff0c 通常称作UART UART 是一种通用的数据通信协议 xff
  • STM32学习--USART

    串口工作方式 1 查询 xff1a 串口程序不断循环查询 xff0c 看看有没有数据需要它发送 2 中断 xff1a 平时串口只要打开中断即可 如果有中断来即需要传输数据 xff0c 它就马上进行数据的传输 STM32编程 xff1a 1
  • Atitit HTTP 认证机制基本验证 (Basic Authentication) 和摘要验证 (Digest Authentication)attilax总结Atitit HT

    Atitit HTTP 认证机制 基本验证 Basic Authentication 和摘要验证 Digest Authentication attilax总结 1 1 最广泛使用的是基本验证 Basic Authentication 和摘
  • 实验二 读取和理解激光雷达数据

    1 体验内容 xff08 1 xff09 为rplidar添加USB权限 注 xff1a 实验室的rplidar A2买得比较早 xff0c 硬件版本可能与github程序不匹配 xff0c 出现运行错误 xff0c 解决方法为到 Wind
  • Linux下使用Netfilter框架编写内核模块(统计协议层ping特定地址丢包数)

    一 linux内核中neitfilter的处理过程 1 5个HOOK点的执行点说明 xff1a 数据包从进入系统 xff0c 进行IP校验以后 xff0c 首先经过第一个HOOK函数NF IP PRE ROUTING进行处理 xff1b 然
  • 基于TCP 实现客户端之间通信【1】

    前段时间学习了基于TCP协议下实现服务器与一个客户端的通信 xff0c 服务器与多个客户端之间的通信 xff0c 以及客户端之间的互相通信 下面就是我写的利用TCP和多线程技术实现客户端之间互相通信的代码 xff1a 服务器端 xff1a
  • 回环接口(loop-back/loopback)

    回环接口 xff08 loop back loopback xff09 Moakap 整理 Loopback 接口是一个虚拟网络接口 xff0c 在不同的领域 xff0c 其含义也大不一样 1 xff0e TCP IP 协议栈中的 loop
  • socket封装HTTP请求

    之前写过两个socket封装的HTTP GET请求 xff0c 可是知其然 xff0c 不知所以然 这次写POST请求就有点懵逼了 还是从大佬的文章出发 xff1a https blog csdn net a19881029 article
  • access中,如何删除不可见空格

    1 可以使用 Trim 函数 xff0c 删除字符串 首 尾 的正常空格 span class token keyword update span 表名 span class token keyword set span 字段 span c
  • Raspberry Pi树莓派分类和其相似产品介绍

    文章目录 前言一 1代树莓派二 2代树莓派三 3代树莓派四 4代树莓派五 树莓派Pico六 目前可替代板子介绍引用 前言 树莓派官网 作为小型计算机的代表 xff0c 树莓派可是作为开山鼻祖 xff0c 本文聊一下目前树莓派几代板子发展历程
  • ARM汇编指令ldr和MOV的区别

    1 八位图 数据 2 MOV指令 MOV指令可以把立即数或者寄存器内容 xff08 注意 xff1a 这里绝对不可以是内存 xff01 xff01 xff09 传递给一个寄存器 MOV对于立即数是有要求的 xff0c 就是上边的 8位图 数
  • GPS NEMA 0183协议

    一 NMEA0183标准语句 GPS常用语句 GPGGA 例 xff1a GPGGA 092204 999 4250 5589 S 14718 5084 E 1 04 24 4 19 7 M 0000 1F 字段0 xff1a GPGGA
  • 使用setvbuf更改printf的默认buffer 行为

    有3种buffer行为 xff0c 不缓冲 xff0c 基于块的缓冲 和 基于行的缓冲 stdout xff08 printf xff09 默认是基于行的缓冲 xff0c 即写到stdout的字符都会被缓冲起来直到一个换行符输出的时候 xf
  • linux 下 tcpdump详解 后篇(自己实现抓包过滤)

    一 概述 在了解了tcpdump的原理后 xff0c 你有没有想过自己去实现抓包过滤 xff1f 可能你脑子里有个大概的思路 xff0c 但是知道了理论知识 xff0c 其实并不能代表你完全的理解 只要运用后 xff0c 你才知道哪些点需要
  • 结构体与共同体(联合体)的妙用

    结构体与共同体 xff08 联合体 xff09 的妙用 学习过C语言后 xff0c 大家都了解了结构体与共同体 两者之间的区别是 xff1a 共同体 xff1a 使几个不同类型的变量共占一段内存 相互覆盖 所占内存长度是各最长的成员占的内存
  • [北力电子] 无人机4G图传数传一体 pixhawk mavlink GSLINK 720P

    随着无人机和4G技术的发展 xff0c 实时监看空中视角的画面已经成为可能GSLINK突破传统的传输方式 xff0c 利用了4G网络将数据和视频流融为一体进行无限距离的传输 用户使用EC2地面站 xff08 Mission Planner
  • C#笔记(基础篇)

    简介 第一次发博客 xff0c 欢迎交流沟通 因为学习虚拟现实需要所以暑假一个月学了点C xff0c 做了笔记 xff0c 在这进行分享 xff0c 欢迎浏览 有些代码打在VS中 没有记录在笔记里 请见谅 xff08 视频指路 xff09

随机推荐