1. 程式人生 > >平衡小車之家PC端上位機協議程式碼解讀

平衡小車之家PC端上位機協議程式碼解讀

平臺是基於STM32F103C8T6,資料可從這裡下載連結:連結,提取碼:qskh

一、程式碼再現

DataScope_DP.c

#include "DataScope_DP.h"
unsigned char DataScope_OutPut_Buffer[42] = {0};	   //串列埠傳送緩衝區


//函式說明:將單精度浮點資料轉成4位元組資料並存入指定地址 
//附加說明:使用者無需直接操作此函式 
//target:目標單精度資料
//buf:待寫入陣列
//beg:指定從陣列第幾個元素開始寫入
//函式無返回 
void Float2Byte(float *target,unsigned char *buf,unsigned char beg)
{
    unsigned char *point;
	
    point = (unsigned char*)target;	  //得到float的地址
    buf[beg]   = point[0];//同時也也可以看出STM32是小端模式
    buf[beg+1] = point[1];
    buf[beg+2] = point[2];
    buf[beg+3] = point[3];
}
 
 
//函式說明:將待發送通道的單精度浮點資料寫入傳送緩衝區
//Data:通道資料
//Channel:選擇通道(1-10)
//函式無返回 
void DataScope_Get_Channel_Data(float Data,unsigned char Channel)
{
	if ( (Channel > 10) || (Channel == 0) ) return;  //通道個數大於10或等於0,直接跳出,不執行函式
	else
	{
		switch (Channel)
		{
			case 1:  Float2Byte(&Data,DataScope_OutPut_Buffer,1); break;
			case 2:  Float2Byte(&Data,DataScope_OutPut_Buffer,5); break;
			case 3:  Float2Byte(&Data,DataScope_OutPut_Buffer,9); break;
			case 4:  Float2Byte(&Data,DataScope_OutPut_Buffer,13); break;
			case 5:  Float2Byte(&Data,DataScope_OutPut_Buffer,17); break;
			case 6:  Float2Byte(&Data,DataScope_OutPut_Buffer,21); break;
			case 7:  Float2Byte(&Data,DataScope_OutPut_Buffer,25); break;
			case 8:  Float2Byte(&Data,DataScope_OutPut_Buffer,29); break;
			case 9:  Float2Byte(&Data,DataScope_OutPut_Buffer,33); break;
			case 10: Float2Byte(&Data,DataScope_OutPut_Buffer,37); break;
		}
	}	 
}


//函式說明:生成 DataScopeV1.0 能正確識別的幀格式
//Channel_Number,需要傳送的通道個數
//返回傳送緩衝區資料個數
//返回0表示幀格式生成失敗 
unsigned char DataScope_Data_Generate(unsigned char Channel_Number)
{
	if ( (Channel_Number > 10) || (Channel_Number == 0) ) { return 0; }  //通道個數大於10或等於0,直接跳出,不執行函式
	
	else
	{	
		DataScope_OutPut_Buffer[0] = '$';  //幀頭

		switch(Channel_Number)   
		{ 
			case 1:   DataScope_OutPut_Buffer[5]  =  5; return  6;  
			case 2:   DataScope_OutPut_Buffer[9]  =  9; return 10;
			case 3:   DataScope_OutPut_Buffer[13] = 13; return 14; 
			case 4:   DataScope_OutPut_Buffer[17] = 17; return 18;
			case 5:   DataScope_OutPut_Buffer[21] = 21; return 22;  
			case 6:   DataScope_OutPut_Buffer[25] = 25; return 26;
			case 7:   DataScope_OutPut_Buffer[29] = 29; return 30; 
			case 8:   DataScope_OutPut_Buffer[33] = 33; return 34; 
			case 9:   DataScope_OutPut_Buffer[37] = 37; return 38;
			case 10:  DataScope_OutPut_Buffer[41] = 41; return 42; 
		}	 
	}
	return 0;
}


DataScope_DP.h

#ifndef __DATA_PRTOCOL_H
#define __DATA_PRTOCOL_H
 
extern unsigned char DataScope_OutPut_Buffer[42];	   //待發送幀資料快取區

void DataScope_Get_Channel_Data(float Data,unsigned char Channel);    // 寫通道資料至 待發送幀資料快取區
unsigned char DataScope_Data_Generate(unsigned char Channel_Number);  // 傳送幀資料生成函式 
 
 
#endif 

Minibalance.c

#include "sys.h"
#include "DataScope_DP.h"

unsigned char i;          //計數變數
unsigned char Send_Count; //串列埠需要傳送的資料個數
static float a;

int main(void)
{ 
	Stm32_Clock_Init(9);            //系統時鐘設定
	delay_init(72);                 //延時初始化
	uart_init(72,128000);           //初始化串列埠1
	while(1)
	{
		a+=0.1;
		if(a>3.14)  a=-3.14; 
		DataScope_Get_Channel_Data(500*sin(a), 1 );
		DataScope_Get_Channel_Data(500*tan(a), 2 );
		DataScope_Get_Channel_Data(500*cos(a), 3 ); 
		DataScope_Get_Channel_Data(100*a , 4 );   
		DataScope_Get_Channel_Data(0, 5 );
		DataScope_Get_Channel_Data(0, 6 );
		DataScope_Get_Channel_Data(0, 7 );
		DataScope_Get_Channel_Data(0, 8 ); 
		DataScope_Get_Channel_Data(0, 9 );  
		DataScope_Get_Channel_Data(0, 10);
		Send_Count = DataScope_Data_Generate(10);
		for( i = 0 ; i < Send_Count; i++) 
		{
			while((USART1->SR&0X40)==0);  
			USART1->DR = DataScope_OutPut_Buffer[i]; 
		}
		delay_ms(50); //20HZ
	} 
}

二、快速上手

波特率 128000

程式碼:

處對應10個通道要顯示的資料。

處對應要顯示的總共通道數!

三、程式碼解讀

協議:

  • 上位機通訊的資料幀長度固定為 4*N+1,幀資料位元組之間傳輸延時不可超過 1ms,否則將認為當前幀結束,UI 重新整理沒有限制顯示延時。

  • 串列埠傳送緩衝區一共開了42個位元組,其實用到的只有41個。每個channel佔用4個,共10個channel,再加一個幀頭$。 然後用哪個通道,就不斷哪個通道對應的4位元組就行。比如我一直用4通道(1~10),那麼對應的串列埠傳送緩衝區的位置是13-16!

知道上面兩條,以上的程式碼就很好理解了!