完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
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 *(buf+i) = USART1_RX_BUF; } // 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 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 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 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 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 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 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 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核心板串口测试rn"); // printf("反客科技rn"); 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("rn"); } 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("rn和校验值错误,请检查校验算法!!rn"); } } else return; } else return; } else { textBox15.AppendText("rn返回的字节数不对!!rn"); } 数据解析,校验正确,那么显示在文本框中 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 } |
|
|
|
只有小组成员才能发言,加入小组>>
调试STM32H750的FMC总线读写PSRAM遇到的问题求解?
1609 浏览 1 评论
X-NUCLEO-IHM08M1板文档中输出电流为15Arms,15Arms是怎么得出来的呢?
1540 浏览 1 评论
970 浏览 2 评论
STM32F030F4 HSI时钟温度测试过不去是怎么回事?
681 浏览 2 评论
ST25R3916能否对ISO15693的标签芯片进行分区域写密码?
1587 浏览 2 评论
1861浏览 9评论
STM32仿真器是选择ST-LINK还是选择J-LINK?各有什么优势啊?
643浏览 4评论
STM32F0_TIM2输出pwm2后OLED变暗或者系统重启是怎么回事?
515浏览 3评论
528浏览 3评论
stm32cubemx生成mdk-arm v4项目文件无法打开是什么原因导致的?
503浏览 3评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-11-20 13:24 , Processed in 0.936944 second(s), Total 87, Slave 71 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号