串口数据传输格式
波特率:38400
起始结束: 数据由起始位0x3A开始,结束位0x0D结束。
LRC检验:从起始位的下一byte开始到LRC位前一byte计算LRC,置入LRC byte。
状态Byte说明:
7bit |
6bit |
5bit |
4bit |
3bit |
2bit |
1bit |
0bit |
故障位
1:故障 |
0:恒压
1:恒流 |
保留 |
保留 |
保留 |
保留 |
保留 |
1:开机
0:关机 |
1 单片机向PC发送功能号0x09数据(即PC会收到的数据格式)
0 |
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
0x3A |
0x09 |
电压值 |
电流值 |
保留0x00 |
状态Byte |
LRC |
0x0D |
注:电压值、电流值为float类型
例:
fV = *((float*)&pu8Temp[2]);
fI = *((float*)&pu8Temp[6]);
此数据格式为单片机向PC发送的电源信息。如:电流电压值,恒流、开关机等
2 单片机向PC发送功能号0x00 数据(即PC会收到的数据格式)
0 |
1 |
2 |
3 |
0x3A |
0x00 |
LRC |
0x0D |
当PC收到此数据格式,说明单片机需要跟PC沟通。PC收到此数据格式后立即向单片机回复数据,格式如3。
3 PC向单片机发送设置数据
0 |
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
0x3A |
0x00 |
电压值 |
电流值 |
保留0x00 |
状态位 |
LRC |
0x0D |
注:电压值、电流值为float类型
例:(请自行按照所处运行环境定义BYTE(8位BIT变量))
BYTE * pu8Temp = (BYTE*)&m_fSetV;
szu8Re[2] = pu8Temp[0];
szu8Re[3] = pu8Temp[1];
szu8Re[4] = pu8Temp[2];
szu8Re[5] = pu8Temp[3];
pu8Temp = (BYTE*)&m_fSetI;
szu8Re[6] = pu8Temp[0];
szu8Re[7] = pu8Temp[1];
szu8Re[8] = pu8Temp[2];
szu8Re[9] = pu8Temp[3];
当PC收到0x00号功能数据时,立即按照此格式回复电流电压设置值。
关机操作:回复此格式,状态位最小bit为0即可。
开机操作:亦发送此格式,状态为最小bit为1即可。
注:开机操作应由PC主动向单片机发送数据。其他(设置电流电压、或者关机)应收到单片机0x00功能号时立即回复。
Example Code
#define FRAME_START 0x3A
#define FRAME_END 0x0D
//-- 计算LRC
BYTE CalLRC(BYTE * pu8Buf, int i32Len)
{
BYTE u8LRC = 0;
for(int i = 0; i < i32Len; i++)
u8LRC += pu8Buf[i];
u8LRC = ~u8LRC;
u8LRC++;
return u8LRC;
}
Void OnComm(WPARAM ch, LPARAM port)
{
m_szu8RevBuf[m_i32RevLen] = (char)ch;
m_i32RevLen++;
if(ch == FRAME_END)
{
if(m_i32RevLen >= 4 &&
m_szu8RevBuf[m_i32RevLen - 4] == FRAME_START &&
m_szu8RevBuf[m_i32RevLen - 3] == 0x00)
{//-- 0号功能
BYTE u8LRC = CalLRC(&m_szu8RevBuf[m_i32RevLen - 3], 1);
if(u8LRC == m_szu8RevBuf[m_i32RevLen - 2])
{
memset(m_szu8RevBuf, 0, sizeof(m_szu8RevBuf));
m_i32RevLen = 0;
//-- 回复信息---------
if(!m_bSerialPortOpened) return 0;
BYTE szu8Re[14] = {0};
szu8Re[0] = FRAME_START;
szu8Re[13] = FRAME_END;
szu8Re[1] = 0;//-- 地址0
BYTE * pu8Temp = (BYTE*)&m_fSetV;
szu8Re[2] = pu8Temp[0];
szu8Re[3] = pu8Temp[1];
szu8Re[4] = pu8Temp[2];
szu8Re[5] = pu8Temp[3];
pu8Temp = (BYTE*)&m_fSetI;
szu8Re[6] = pu8Temp[0];
szu8Re[7] = pu8Temp[1];
szu8Re[8] = pu8Temp[2];
szu8Re[9] = pu8Temp[3];
szu8Re[10] = 0;
if(!m_bMacOn)
szu8Re[11] = 0x01;
szu8Re[12] = CalLRC(&szu8Re[1], 11);
WriteToPort((char*)&szu8Re, sizeof(szu8Re));
return 0;
}
}
if(m_i32RevLen >= 8 &&
m_szu8RevBuf[m_i32RevLen - 8] == FRAME_START &&
m_szu8RevBuf[m_i32RevLen - 7] == 0x01)
{//-- 1号功能
BYTE u8LRC = CalLRC(&m_szu8RevBuf[m_i32RevLen - 7], 5);
if(u8LRC == m_szu8RevBuf[m_i32RevLen - 2])
{
//-- 1号功能数据,PC不关心这个数据,丢弃
memset(m_szu8RevBuf, 0, sizeof(m_szu8RevBuf));
m_i32RevLen = 0;
return 0;
}
}
if(m_i32RevLen >= 14 &&
m_szu8RevBuf[m_i32RevLen - 14] == FRAME_START &&
m_szu8RevBuf[m_i32RevLen - 13] == 0x09)
{//-- 9号功能 单片机机向PC发送信息
BYTE u8LRC = CalLRC(&m_szu8RevBuf[m_i32RevLen - 13], 11);
if(u8LRC == m_szu8RevBuf[m_i32RevLen - 2])
{
//-- 9号功能数据,主机向PC发送信息
ParseFunction(9, 10, &m_szu8RevBuf[2]); //-- 分析数据获取开关电源信息,如:电流 //-- 电压等
m_wndShow.Invalidate();
memset(m_szu8RevBuf, 0, sizeof(m_szu8RevBuf));
m_i32RevLen = 0;
return 0;
}
}
}
if(m_i32RevLen >= 250)
{
memset(m_szu8RevBuf, 0, sizeof(m_szu8RevBuf));
m_i32RevLen = 0;
}
return 0;
}
PC机和单片机的交互流程
1 PC机发送开机数据给单片机(此数据和PC机设置单片机的电流电压数据一样):
3a 00 00 00 00 00 00 00 00 00 00 01 ff 0d 蓝色的为需要计算LRC的数据,红色为LRC结果。
注:此数据格式为电压0V,电流0A,状态为0x01,即开机。
2 单片机收到开机数据后开机,然后不断的向PC发送0x09、0x00 功能号的数据。
PC收到0x09功能号数据,即是开关电源上传给PC的信息。其中包含电流电压和状态,格式见上面说明。此格式不用回复。
PC收到0x00功能号数据,即是开关电源要跟PC沟通,PC应该立即回复需要设置的信息。其中包括电流电压和状态(状态中包含了开机或者关机信息,最低bit为1即开机,0为关机)。
关机:即回复给单片机的状态Byte最低位为0即可。电流电压的位置可以设置为0。
举例说明:
|