AVR單片機(jī)與上位機(jī)通信協(xié)議的制定
在單片機(jī)主循環(huán)程序的最前部分進(jìn)行指令譯碼
if(Uart_RecvFlag)//接收到命令
{
switch(rx_buffer[1])
{
case 0xAA://單片機(jī)狀態(tài)命令控制;
ucWorkStatue=rx_buffer[2];//指令數(shù)據(jù)
break;
case 0xDD://PWM值修改指令
OCR2=rx_buffer[2];
break;
case 0xFF://初始溫度設(shè)定
break;
}
Uart_RecvFlag=0;
}
//隨后進(jìn)行執(zhí)行指令
switch(ucWorkStatue)
{
case 1://空閑模式
break;
case 2://測(cè)量模式,但不輸出
break;
case 3://測(cè)量模式,由串口輸出
break;
case 4://PWM輸出測(cè)試
break;
default:
break;
}
這樣就可以利用串口對(duì)單片機(jī)進(jìn)行在線命令控制了;
上行協(xié)議的制定和下行協(xié)議基本一致!
在AVR單片機(jī)程序中定義了串口通信輸出緩沖區(qū),緩沖區(qū)的字長(zhǎng)正好為協(xié)議的長(zhǎng)度;
//串口發(fā)送緩沖區(qū)變量聲明
volatile unsigned char tx_buffer[TX_BUFFER_SIZE];//定義串口發(fā)送緩沖區(qū)
volatile unsigned char tx_wr_index=0,tx_rd_index=0,tx_counter=0;//rx_wr_index寫指針,rx_rd_index讀指針,rx_counter緩沖區(qū)數(shù)據(jù)個(gè)數(shù)
//USART發(fā)送函數(shù)
void USART_Transmit(unsigned char data)//發(fā)送數(shù)據(jù)函數(shù)
{
while(tx_counter==TX_BUFFER_SIZE);//輸出緩沖區(qū)滿,等待
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");
}
//發(fā)送中斷服務(wù)程序
ISR(USART_TXC_vect)//USART發(fā)送數(shù)據(jù)中斷
{
if(tx_counter)
{
--tx_counter;
UDR=tx_buffer[tx_rd_index];
if(++tx_rd_index==TX_BUFFER_SIZE)
{
tx_rd_index=0;
}
}
}
在C#編寫的上位機(jī)中,利用串口接收事件響應(yīng)方法定義
serialPort1.ReceivedBytesThreshold = RECEIVE_LENTH;
在時(shí)間響應(yīng)事件中調(diào)用協(xié)議分析處理函數(shù)serialPortCaculate()來(lái)分析協(xié)議
private void serialPort1_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
this.label_dispzedNum.Invoke(new MethodInvoker(delegate
{ //匿名方法
int inNumSData=0;
try
{
inNumSData = this.serialPort1.BytesToRead;
this.lab_serial_bufin_diplay.Text = inNumSData.ToString();
//串行數(shù)據(jù)處理
//圖像顯示
byte dataID = 0x00;
double temp = this.serialPortCaculate(ref dataID);
switch(dataID)
{
case TEMVAL:
break;
default:
this.serialPort1.DiscardInBuffer
()
break;
}
}
catch
{ }
}));
}
///////接收轉(zhuǎn)換協(xié)議,接收數(shù)據(jù)時(shí)直接調(diào)用
private double serialPortCaculate(ref byte dataID)
{
Byte[] BReceiveTemp = new Byte[RECEIVE_LENTH];
for (int i = 0; i RECEIVE_LENTH; i++)//接收定長(zhǎng)數(shù)據(jù)字符串
{
BReceiveTemp[i] = Convert.ToByte(this.serialPort1.ReadByte());
}
dataID=BReceiveTemp[1];
switch (BReceiveTemp[1])
{
case TEMVAL:
default :
}
}
評(píng)論