当前位置:文档之家› 单片机与上位机通信协议的制定解析

单片机与上位机通信协议的制定解析

单片机与上位机通信协议的制定

单片机和上位机的串口通信协议分为上行协议和下行协议,要分别制定!

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

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

而通信协议又要分固定长度和不定长度两种

本文所介绍的协议属于简单的固定字长的通信协议!

下行协议由四个字节构成

上表是简单的上位机对单片机的控制指令

下述函数是C#中封装的串口通信类中的发送函数的封装

public void SerSendCommu(byte orderDef, byte data)//参数1为命令字,参数二为要发送的数

//据,需要时可直接调用

{

Byte[] BSendTemp = new Byte[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)//串口接收中断

{

unsigned char status,data;

status = UCSRA; //**首先读取UCSRA的值,再读取UDR值,顺序不能颠倒,否则读取UDR后的UCSRA的

//值即会改变**

data = UDR;

if(!Uart_RecvFlag)//判断缓存中的数据是否读完,读完则接收指令

{

if((status&((1<

{

rx_buffer[rx_counter]=data;

rx_counter++;

switch(rx_counter)

{

case 1:

if(data!=USART_BEGIN_STX)

rx_counter=0;

break;

case 4:

rx_counter=0;

if(data==USART_END_STX)

Uart_RecvFlag=1;

break;

}

}

}

}

在单片机主循环程序的最前部分进行指令译码

if(Uart_RecvFlag)//接收到命令

{

switch(rx_buffer[1])

{

case 0xAA://单片机状态命令控制;

ucWorkStatue=rx_buffer[2];//指令数据

break;

case 0xDD://PWM值修改指令

OCR2=rx_buffer[2];

break;

case 0xFF://初始温度设定

break;

}

Uart_RecvFlag=0;

}

//随后进行执行指令

switch(ucWorkStatue)

{

case 1://空闲模式

break;

case 2://测量模式,但不输出

break;

case 3://测量模式,由串口输出

break;

case 4://PWM输出测试

break;

default:

break;

}

这样就可以利用串口对单片机进行在线命令控制了;

上行协议的制定!

和下行协议基本一致!

在AVR单片机程序中定义了串口通信输出缓冲区,缓冲区的字长正好为协议的长度;

//串口发送缓冲区变量声明

volatile unsigned char tx_buffer[TX_BUFFER_SIZE];//定义串口发送缓冲区

volatile unsigned char

tx_wr_index=0,tx_rd_index=0,tx_counter=0;//rx_wr_index写指

针,rx_rd_index读指针,rx_counter缓冲区数据个数

//USART发送函数

void USART_Transmit(unsigned char data)//发送数据函数

{

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()来分析协议

private void serialPort1_DataReceived(object sender, SerialDataReceivedEventArgs e)

{

相关主题