当前位置:文档之家› (合同制定方法)单片机与上位机通信协议的制定

(合同制定方法)单片机与上位机通信协议的制定

(合同制定方法)单片机与上位机通信协议的制定
单片机和上位机通信协议的制定
单片机和上位机的串口通信协议分为上行协议和下行协议,要分别制定!上行协议,即由单片机向上位机发送数据。

下行协议,即由上位机向单片机发送数据。

而通信协议又要分固定长度和不定长度俩种
本文所介绍的协议属于简单的固定字长的通信协议!
下行协议由四个字节构成
上表是简单的上位机对单片机的控制指令
下述函数是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&((1<<FE)|(1<<PE)|(1<<DOR)))==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_i ndex写指针,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;
}
else
UDR=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,SerialDataReceivedEv entArgse)
{
bel_dispzedNum.Invoke(newMethodInvoker(delegate
{//匿名方法
intinNumSData=0;
try
{
inNumSData=this.serialPort1.BytesToRead;
b_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;i<RECEIVE_LENTH;i++)//接收定长数据字符串
{
BReceiveTemp[i]=Convert.ToByte(this.serialPort1.ReadByte()); }
dataID=BReceiveTemp[1];
switch(BReceiveTemp[1])
{
caseTEMVAL:
default:
}。

相关主题