串口通信协议

时间:2024-03-19 07:26:15

T613通信协议

T613与客户使用的Soc通信方式有两种:

  • Uart 方式通信
  • I2C  方式通信                                              

下面我们分别介绍一下通信过程中,具体的实现原理和通信细节。

 

第一部分:  Uart 方式通信

帧格式:

帧头

Cmd

Cmd_Val

X_Val

Y_Val

Z_Val

CheckSum

 

帧详解:                                                                                              

UART

Head

0x55AA55AA

4bytes

Cmd

命令字

1byte

Cmd_Val

对应命令的值

1byte

X_Val

X方向的角度值

2bytes

Y_Val

Y方向的角度值

2bytes

Z_Val

Z方向的角度值

2bytes

CheckSum

校验位

2bytes

 

 

 

 

 

 

 

 

Head:固定4bytes, 0x55AA55AA

Cmd_Val:相应命令字对应的值大小。比如:

         CmdLT_ON,

      Cmd_Val = 0xf2;LT_ON的时候设置的值为0xf2,

      CommandLT_OFF,

      Cmd_Val = 0xf2,那么此时的Func_Val值无效。

X_Val: X方向的实时角度值。

Y_Val: Y方向的实时角度值。

Z_Val: Z方向的实时角度值。

CheckSum: 校验位。

      CheckSum = Cmd + Cmd_Val + X_Val + Y_Val + Z_Val

 

2、命令字

Typedefenum  I2C_UART_CMD{

CMD_ZRota_ON = 0,      // 0x00开启左右梯形校正

CMD_ZRota_OFF,         // 0x01关闭左右梯形校正

CMD_VCali_ON,          // 0x02开启上下梯形校正

CMD_VCali_OFF,         // 0x03关闭上下梯形校正

CMD_HCali_ON,         // 0x04开启画面旋转

CMD_HCali_OFF,         // 0x05关闭画面旋转

CMD_DigFocus_ON,       // 0x06开启数字校正

CMD_DigFocus_OFF,      // 0x07关闭数字校正

CMD_UnifoBri_ON,       // 0x08开启亮度校正

CMD_UnifoBri_OFF,      // 0x09关闭亮度校正

CMD_HLinear_ON,        // 0x0a开启水平方向线性校正

CMD_HLinear_OFF,       // 0x0b关闭水平方向线性校正

CMD_VLinear_ON,        // 0x0c开启垂直方向线性校正

CMD_VLinear_OFF,       // 0x0d关闭垂直方向线性校正

 

//陀螺仪原点参考位置选取

CMD_CaliLoca,          // 0x0e选取参考位置,此时将XYZ置零

CMD_Rectify_ON,        // 0x0f开启自动校正,APP自动更新

CMD_Rectify_OFF,       // 0x10关闭自动校正,APP不更新

CMD_Reset,             // 0x11复位APP所有设定的值到初始态

CMD_Raspberry,         // 0x12 切换树莓派控制

//四点位置校正

//FPCORR打开时,后面的四点坐标数据才会有效,否则无效

CMD_FPCorr_ON,         // 0x13开启四点校正

CMD_FPCorr_OFF,        // 0x14关闭四点校正

CMD_CorrA_PX,          // 0x15 A点校正X方向值

CMD_CorrA_PY,          // 0x16 A点校正Y方向值

CMD_CorrB_PX,          // 0x17 B点校正X方向值

CMD_CorrB_PY,          // 0x18 B点校正Y方向值

CMD_CorrC_PX,          // 0x19 C点校正X方向值

CMD_CorrC_PY,          // 0x1a C点校正Y方向值

CMD_CorrD_PX,          // 0x1b D点校正X方向值

CMD_CorrD_PY,          // 0x1c D点校正Y方向值

CMD_Deflt_Val,         // 0x1d 恢复四点初始值

CMD_ReturnBefore,      // 0x1e恢复四点校正前的值

CMD_Rotate_ON,         // 0x1f打开画面上下翻转180

CMD_Rotate_OFF,        // 0x20关闭画面上下翻转180

};

注:以上指令中Cmd_Val

CMD_CaliLoca,          // 0x0e选取参考位置,此时将XYZ置零

CMD_Rectify_ON,        // 0x0f开启自动校正,APP自动更新

CMD_Rectify_OFF,       // 0x10关闭自动校正,APP不更新

CMD_Reset,             // 0x11复位APP所有设定的值到初始态

CMD_RASPBERRY,         // 0x12切换RASPBERRYLIGTHING

CMD_Deflt_Val,         // 0x1d 恢复四点初始值

CMD_ReturnBefore       // 0x1e恢复四点校正前的值  

CMD_Rotate_ON,         // 0x1f打开画面上下翻转180

CMD_Rotate_OFF,        // 0x20关闭画面上下翻转180

这些Cmd中值无效(Invalid)

 

CMD_HCali_ON

55AA55AA 00 45 FF 9B 00 7B FF AB 00 06

Head

0x55AA55AA

4bytes

Cmd

0x00

1byte

Cmd_Val

0x45

1byte

X_Val

0xFF9B

2bytes

Y_Val

0x007B

2bytes

Z_Val

0xFFAB

2bytes

CheckSum

0x0006

2bytes

此时,Command = 0x00,即左右梯形是打开的。故Func_Val = 0x45是有效值(Valid)

检验位:CheckSum = 0(0x00)+69(0x45)+(-101)(0xFF9B)+123(0x7B)+(-085)(0xFFAB) = 6(0x06)

 

CMD_HCali_OFF

55AA55AA 01 45 FF 9B 00 7B FFAB 00 07

Head

0x55AA55AA

4bytes

Cmd

0x01

1byte

Cmd_Val

0x45

1byte

X_Val

0xFF9B

2bytes

Y_Val

0x007B

2bytes

Z_Val

0xFFAB

2bytes

CheckSum

0x0007

2bytes

此时,Cmd = 0x01,即左右梯形是关闭的。故Func_Val = 0x45是无效值(Invalid)

检验位:CheckSum = 1(0x01)+69(0x45)+(-101)(0xFF9B)+123(0x7B)+(-085)(0xFFAB)  = 7(0x0007)

注:此时虽然Cmd_Val值无效,但是校验时依然要计算。

 

CMD_FPCorr_ON

55AA55AA 13 45 FF 9B 00 7B FFAB 00 19

Head

0x55AA55AA

4bytes

Cmd

0x13

1byte

Cmd_Val

0x45

1byte

X_Val

0xFF9B

2bytes

Y_Val

0x007B

2bytes

Z_Val

0xFFAB

2bytes

CheckSum

0x0019

2bytes

此时,Cmd = 0x13,即四点校正是打开的。接下来的CMD_CorrX_PX/CMD_CorrX_PYcmd才有效(Valid)

检验位:CheckSum = 19(0x13)+69(0x45)+(-101)(0xFF9B)+123(0x7B)+(-085)(0xFFAB)  = 25(0x0019)

 

CMD_FPCorr_OFF

55AA55AA 14 45 FF 9B 00 7B FF AB 00 1A

Head

0x55AA55AA

4bytes

Cmd

0x14

1byte

Cmd_Val

0x45

1byte

X_Val

0xFF9B

2bytes

Y_Val

0x007B

2bytes

Z_Val

0xFFAB

2bytes

CheckSum

0x001A

2bytes

此时,Cmd = 0x14,即四点校正是关闭的。接下来的CMD_CorrX_PX/CMD_CorrX_PYcmd无效(Invalid)

检验位:CheckSum = 20(0x14)+69(0x45)+(-101)(0xFF9B)+123(0x7B)+(-085)(0xFFAB) = 26(0x001a)

 

注:在我们发送数据的时候,使用者可能会存在一下疑虑?

  1. 我们通过串口发送数据的时候,数据的具体转换方式是什么?

答:在传输的时候,需要先把数据全部转成unsigned char类型,然后分别切成高八位和低八位,再传输。举个例子:

我们要传输的数据是:

Cmd = 2,

Cmd_Val = -3,

X_Val = -22;

Y_Val = 12;

Z_Val = 4;

那么 CheckSum = 2 + (-3) + (-22) + 12 + 4 = -7

这样的话:数据格式是什么样子的?

由上面的数据格式可以知道,

Cmd = 2,         //(unsigned char) 1Byte  (8B 0x02)

Cmd_Val = -3,   //(signed char) 1Byte  (8B 0xFD)

X_Val = -22;    //(signed short) 2bytes  (16B 0xFFEA)

Y_Val = 12;     //(signed short) 2bytes  (16B 0x000C)

Z_Val = 4;       //(signed short) 2bytes  (16B 0x0004)

CheckSum = -7;  //(signed short) 2bytes  (16B 0xFFF9)

     由这些数据我们得到对应的表示格式,那么我们下面写一下伪代码,如下:

    

 

//. . . 伪代码部分 . . .

unsigned char arr_uart[14] = 0;

unsigned char cmd_t;

unsigned char cmd_val_t;

unsigned short x_val_t;

unsigned short y_val_t;

unsigned short z_val_t;

unsigned short CheckSum_t;

//数据转换部分

cmd_t = (unsigned char)Cmd;

cmd_val_t = (unsigned char)Cmd_Val;

x_val_t = (unsigned short)X_Val;

y_val_t = (unsigned short)Y_Val;

z_val_t = (unsigned short)Z_Val;

CheckSum_t = (unsigned short)CheckSum;

//帧头数据设置

arr_uart[0] = 0x55;

arr_uart[1] = 0xAA;

arr_uart[2] = 0x55;

arr_uart[3] = 0xAA;

//有效数据放置

arr_uart[4] = cmd_t;

 arr_uart[5] = cmd_val_t;

arr_uart[6] = (x_val_t >> 8) & 0xFF;  //先传高位

arr_uart[7] = (x_val_t >> 0) & 0xFF;  //在传低位

arr_uart[8] = (y_val_t >> 8) & 0xFF;  //先传高位

arr_uart[9] = (y_val_t >> 0) & 0xFF;  //在传低位

arr_uart[10] = (z_val_t >> 8) & 0xFF;  //先传高位

arr_uart[11] = (z_val_t >> 0) & 0xFF;  //在传低位

arr_uart[12] = (CheckSum_t >> 8) & 0xFF;  //先传高位

arr_uart[13] = (CheckSum _t >> 0) & 0xFF;  //在传低位

     

uart_send(uart_x, arr_uart);  //调用uart传输数据函数。

//. . . 伪代码部分 . . .

 

  1. 我们通过串口传输数据的时候,Cmd的指令和Cmd_Val,X_ValY_ValZ_Val等这些值要如何下到T613?

答:首先我们需要先下Cmd = CMD_Rectify_ON,如下:

注意这个指令只要发一次即可,后面就不用再发送了!!!

帧头

Cmd

Cmd_Val

X_Val

Y_Val

Z_Val

CheckSum

55

AA

55

AA

0F

XX

XX

XX

XX

XX

XX

XX

XX

XX

                           

后面当我们要进行梯形校正的ZRotation的时候,我们就需要下如下命令:

帧头

Cmd

Cmd_Val

X_Val

Y_Val

Z_Val

CheckSum

55

AA

55

AA

00

XX

XX

XX

XX

XX

XX

XX

XX

XX

                           

然后第二次还是要进行ZRotation的时候,我们下的命令如下:

帧头

Cmd

Cmd_Val

X_Val

Y_Val

Z_Val

CheckSum

55

AA

55

AA

00

XX

XX

XX

XX

XX

XX

XX

XX

XX

                           

也就是说,当我们要修改ZRotation的时候,我们的Cmd一直都是下0x00,然后配置对应的值就好了。以此类推,当我们要改XYZ其中任何一个方向校正的时候,我们的命令就下对应的Cmd就好了。

 

  1. 客户在使用的时候我们一般都会用PC_UI这个软件来下数据给T613,但是问题是这个是手动下去T613的数据,如何自动呢?

答:这个时候因为我们是用手动去拨动PC_UI上面的进度条,数据也就是我们手动去改的,当我们把PC_UI的工作内容交给前端的Soc的时候,就会变成Soc自动去下载数据,这个时候就能看到我们的现象是自动调整的。

 

第二部分:  I2C 方式通信

  1. T613中存放一帧数据的地址范围:0x10000000~0x1000000E
  2. I2C帧数据对应的地址

Head

0x55AA55AA

4bytes

0x10000000~0x10000003

Cmd

命令字

1byte

0x10000004

Func_Val

对应命令的值

1byte

0x10000005

X_Val

X方向的角度值

2bytes

0x10000006~0x10000007

Y_Val

Y方向的角度值

2bytes

0x10000008~0x10000009

Z_Val

Z方向的角度值

2bytes

0x1000000A~0x1000000B

CheckSum

校验位

2bytes

0x1000000C~0x1000000D

I2C_FALG

I2C标志位

1byte

0x1000000E

 

 

 

 

 

 

 

 

前端Soc和我们的T613通过IIC通信方式如下图:

    串口通信协议                                                                                            

注:首先声明一下T613IIC通信速率最高可达1MHz

3、数据传输

(1) T613 上电将I2C_FLAG 0x00

(2) Soc读取I2C_FLAG0x00,表示可以发送数据给T613,发送完成将I2C_FLAG0x01(即每帧数据最后一个字节都为0x01)用来告诉T613 ,已经写完一帧数据,可以读取数据;

(3) T613读取完数据,将I2C_FLAG清零,用以告知Soc,可以继续发送数据。

帧头

Cmd

Cmd_Val

X_Val

Y_Val

Z_Val

CheckSum

I2C_FLAG

 

 

串口通信协议

(4)IIC通信与Uart通信数据格式相同,客户在使用过程中要实现具体的功能请参考Uart部分。

(5)socT613的通信时序如下图:

1 写时序图第一部分

 

串口通信协议

2 写时序图第二部分

串口通信协议

3 读时序第一部分

 

串口通信协议

4 读时序第二部分

 

注:我们采用Single byte write mode,

SlaveAddr = 0x60;

RegAddr : 0x10000000开始,在传输的过程中我们需要将RegAddr切割成4部分分别发送出去。

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

伪代码实现如下:

写数据到T613,代码例程:

//现在我们要写数据到T6130x10000000地址

// . . .伪代码 Write data to T613. . .

const unsigned char SLAVE_ADDR_WRITE = 0x60;

unsigned char REG_ADDR1,

REG_ADDR2,

REG_ADDR3,

REG_ADDR4;

unsigned int  test_addr  = 0x10000000;  //寄存器地址

unsigned char test_Wdata = 0x5A;        //写入的内容

unsigned char DUMMY = 0x00;

REG_ADDR1 = (test_addr >> 24) & 0xFF;  //把要被写入的地址拆分

REG_ADDR2 = (test_addr >> 16) & 0xFF;  //把要被写入的地址拆分

REG_ADDR3 = (test_addr >> 8)  & 0xFF;  //把要被写入的地址拆分

REG_ADDR4 = (test_addr >> 0)  & 0xFF;  //把要被写入的地址拆分

 

//Write data to reg

//第一次写入从设备地址和regAddr的前2bytes,最后跟一个byte dummy数据。

IIC_WriteSingleByte(SLAVE_ADDR_WRITE1, REG_ADDR1, REG_ADDR2, &DUMMY);

//第二次写入从设备地址和regAddr的后2bytes,然后写入要写的内容。     

IIC_WriteSingleByte(SLAVE_ADDR_WRTIE2, REG_ADDR3, REG_ADDR4, &test_Wdata); 

// . . .伪代码 Write data to T613. . .

 

下面我们再举一个从T613寄存器中读数据的例子:

// . . .伪代码 Read data from T613. . .

const unsigned char SLAVE_ADDR_READ  = 0x60;

unsigned char REG_ADDR1,

REG_ADDR2,

REG_ADDR3,

REG_ADDR4;

unsigned char DUMMY = 0x00;

unsigned int  test_addr  = 0x10000000; //寄存器地址

unsigned char test_Rdata = 0x00; //读出的内容,存放到这里

 

REG_ADDR1 = (test_addr >> 24) & 0xFF;  //把要被写入的地址拆分

REG_ADDR2 = (test_addr >> 16) & 0xFF;  //把要被写入的地址拆分

REG_ADDR3 = (test_addr >> 8)  & 0xFF;  //把要被写入的地址拆分

REG_ADDR4 = (test_addr >> 0)  & 0xFF;  //把要被写入的地址拆分

 

 

//Read data from T613

//第一次写入从设备地址和regAddr的前2bytes,最后跟一个byte dummy数据。

IIC_WriteSingleByte(SLAVE_ADDR_READ1, REG_ADDR1, REG_ADDR2, &DUMMY);     

//第二次写入从设备地址和regAddr的后2bytes,然后读出数据内容。       

IIC_ReadSingleRegValue(SLAVE_ADDR_READ2, REG_ADDR3, REG_ADDR4, &test_Rdata); 

// . . .伪代码 Read data from T613. . .