您好,欢迎访问三七文档
当前位置:首页 > 办公文档 > 理论文章 > 单片机与上位机通信协议的制定
单片机与上位机通信协议的制定单片机和上位机的串口通信协议分为上行协议和下行协议,要分别制定!上行协议,即由单片机向上位机发送数据。下行协议,即由上位机向单片机发送数据。而通信协议又要分固定长度和不定长度两种本文所介绍的协议属于简单的固定字长的通信协议!下行协议由四个字节构成起始字PRE命令字ORD值VAL结束字END附注1byte1byte1byte1byteBBHAAH(ORD_SATA)单片机状态转换命令标识01HEEH模式1:空闲02HEEH模式2:温度采集03HEEH模式3:温度采集向上位机传送采集值04HEEH模式4:PWM测试BBHDDH(ORD_PWM)valueEEHPWM占空比值修改指令BBHFFH(ORD_TEM)valueEEH目标温度控制指令上表是简单的上位机对单片机的控制指令下述函数是C#中封装的串口通信类中的发送函数的封装publicvoidSerSendCommu(byteorderDef,bytedata)//参数1为命令字,参数二为要发送的数//据,需要时可直接调用{Byte[]BSendTemp=newByte[SEND_LENTH];BSendTemp[0]=PRE;BSendTemp[1]=orderDef;BSendTemp[2]=data;BSendTemp[3]=END;this.serialPort1.Write(BSendTemp,0,SEND_LENTH);}下位机中用中断方式接收字符,本文用的是GCC语言,下面是串口接收数据中断ISR(USART_RXC_vect)//串口接收中断{unsignedcharstatus,data;status=UCSRA;//**首先读取UCSRA的值,再读取UDR值,顺序不能颠倒,否则读取UDR后的UCSRA的//值即会改变**data=UDR;if(!Uart_RecvFlag)//判断缓存中的数据是否读完,读完则接收指令{if((status&((1FE)|(1PE)|(1DOR)))==0){rx_buffer[rx_counter]=data;rx_counter++;switch(rx_counter){case1:if(data!=USART_BEGIN_STX)rx_counter=0;break;case4:rx_counter=0;if(data==USART_END_STX)Uart_RecvFlag=1;break;}}}}在单片机主循环程序的最前部分进行指令译码if(Uart_RecvFlag)//接收到命令{switch(rx_buffer[1]){case0xAA://单片机状态命令控制;ucWorkStatue=rx_buffer[2];//指令数据break;case0xDD://PWM值修改指令OCR2=rx_buffer[2];break;case0xFF://初始温度设定break;}Uart_RecvFlag=0;}//随后进行执行指令switch(ucWorkStatue){case1://空闲模式break;case2://测量模式,但不输出break;case3://测量模式,由串口输出break;case4://PWM输出测试break;default:break;}这样就可以利用串口对单片机进行在线命令控制了;上行协议的制定!和下行协议基本一致!在AVR单片机程序中定义了串口通信输出缓冲区,缓冲区的字长正好为协议的长度;//串口发送缓冲区变量声明volatileunsignedchartx_buffer[TX_BUFFER_SIZE];//定义串口发送缓冲区volatileunsignedchartx_wr_index=0,tx_rd_index=0,tx_counter=0;//rx_wr_index写指针,rx_rd_index读指针,rx_counter缓冲区数据个数//USART发送函数voidUSART_Transmit(unsignedchardata)//发送数据函数{while(tx_counter==TX_BUFFER_SIZE);//输出缓冲区满,等待asm(cli);if(tx_counter||((UCSRA&DATA_REGISTER_EMPTY)==0)){tx_buffer[tx_wr_index]=data;if(++tx_wr_index==TX_BUFFER_SIZE)tx_wr_index=0;++tx_counter;}elseUDR=data;asm(sei);}//发送中断服务程序ISR(USART_TXC_vect)//USART发送数据中断{if(tx_counter){--tx_counter;UDR=tx_buffer[tx_rd_index];if(++tx_rd_index==TX_BUFFER_SIZE){tx_rd_index=0;}}}在C#编写的上位机中,利用串口接收事件响应方法定义serialPort1.ReceivedBytesThreshold=RECEIVE_LENTH;在时间响应事件中调用协议分析处理函数serialPortCaculate()来分析协议privatevoidserialPort1_DataReceived(objectsender,SerialDataReceivedEventArgse){this.label_dispzedNum.Invoke(newMethodInvoker(delegate{//匿名方法intinNumSData=0;try{inNumSData=this.serialPort1.BytesToRead;this.lab_serial_bufin_diplay.Text=inNumSData.ToString();//串行数据处理//图像显示bytedataID=0x00;doubletemp=this.serialPortCaculate(refdataID);switch(dataID){caseTEMVAL:break;default:this.serialPort1.DiscardInBuffer()break;}}catch{}}));}///////接收转换协议,接收数据时直接调用privatedoubleserialPortCaculate(refbytedataID){Byte[]BReceiveTemp=newByte[RECEIVE_LENTH];for(inti=0;iRECEIVE_LENTH;i++)//接收定长数据字符串{BReceiveTemp[i]=Convert.ToByte(this.serialPort1.ReadByte());}dataID=BReceiveTemp[1];switch(BReceiveTemp[1]){caseTEMVAL:default:}}
本文标题:单片机与上位机通信协议的制定
链接地址:https://www.777doc.com/doc-387526 .html