Files
2026-01-13 14:52:42 +08:00

211 lines
7.6 KiB
C

#include "stm32f4xx.h" // Device header
#include "stm32f4xx_conf.h"
#include "RefereeSystem_CRCTable.h"
#include "UART.h"
/****************************************************************************************************
此处裁判系统只接收0x0201命令,获取机器人性能体系数据,主要获取发射机构是否上电
帧格式:
0xA5 0x0D 0x00 包序号 帧头CRC8校验 0x01 0x02 13ByteData 整包CRC16校验
|___________________________________| |_______| |
帧头 命令码 数据
****************************************************************************************************/
/*接收数据缓冲区数组元素数=命令码对应数据段长度+9*/
uint8_t RefereeSystem_RxHEXPacket1[22]={0xA5,0x0D,0x00,0x00,0x00,0x01,0x02,0};//裁判系统0x0201命令码接收数据缓冲区
uint8_t RefereeSystem_RxHEXPacket2[25]={0xA5,0x10,0x00,0x00,0x00,0x02,0x02,0};//裁判系统0x0202命令码接收数据缓冲区
uint8_t RefereeSystem_ShooterStatus=1;//发射机构状态,0-发射机构未上电,1-发射机构上电
uint16_t RefereeSystem_Ref=120,RefereeSystem_Buffer=30.0f;//底盘功率上限,底盘功率缓冲能量(若无裁判系统,默认功率上限80W,缓冲能量30J)
float RefereeSystem_Power;//底盘实时功率
uint8_t RefereeSystem_RobotID=0;//机器人ID(无裁判系统时一直为0,4号步兵ID为4/104)
/*
*函数简介:裁判系统CRC8查表计算
*参数说明:校验数据
*参数说明:数据长度
*参数说明:CRC初始值(默认给参数0xFF)
*返回类型:无
*备注:表格位于Referee System_CRCTable.h文件中CRC8_Table数组
*/
uint8_t RefereeSystem_GetCRC8CheckSum(uint8_t *Data,uint16_t Length,uint8_t Initial)
{
uint8_t Minuend;
while(Length--)
{
Minuend=Initial^(*Data);
Data++;
Initial=CRC8_Table[Minuend];
}
return Initial;
}
/*
*函数简介:裁判系统CRC8校验
*参数说明:校验数据(含尾端CRC校验码)
*参数说明:数据长度
*返回类型:校验正确返回1,否则返回0
*备注:无
*/
uint8_t RefereeSystem_VerifyCRC8CheckSum(uint8_t *Data,uint16_t Length)
{
uint8_t CRC8CheckSum=0;
if((Data==0) || (Length<=2))return 0;//特殊情况处理
CRC8CheckSum=RefereeSystem_GetCRC8CheckSum(Data,Length-1,CRC8_Initial);//获取CRC8计算值
return CRC8CheckSum==Data[Length-1];//测量值与计算值相比较
}
/*
*函数简介:裁判系统CRC16查表计算
*参数说明:校验数据
*参数说明:数据长度
*参数说明:CRC初始值(默认给参数0xFFFF)
*返回类型:无
*备注:表格位于Referee System_CRCTable.h文件中CRC16_Table数组
*/
uint16_t RefereeSystem_GetCRC16CheckSum(uint8_t *Data,uint32_t Length,uint16_t Initial)
{
uint8_t Minuend;
while(Length--)
{
Minuend=*Data;
Data++;
Initial=((uint16_t)(Initial)>>8)^CRC16_Table[((uint16_t)(Initial)^(uint16_t)(Minuend))&0x00FF];
}
return Initial;
}
/*
*函数简介:裁判系统CRC16校验
*参数说明:校验数据(含尾端CRC校验码)
*参数说明:数据长度
*返回类型:校验正确返回1,否则返回0
*备注:无
*/
uint32_t RefereeSystem_VerifyCRC16CheckSum(uint8_t *Data, uint32_t Length)
{
uint16_t CRC16CheckSum=0;
if((Data==0)||(Length<=2))return 0;//特殊情况处理
CRC16CheckSum=RefereeSystem_GetCRC16CheckSum(Data,Length-2,CRC16_Initial);//获取CRC16计算值
return ((CRC16CheckSum&0xFF)==Data[Length-2]&&((CRC16CheckSum>>8)&0xff)==Data[Length-1]);//测量值与计算值相比较
}
/*
*函数简介:裁判系统接收初始化
*参数说明:无
*返回类型:无
*备注:默认使用UART1(USART6),默认Rx引脚PG9
*/
void RefereeSystem_Init(void)
{
UART1_Init();
//while(RefereeSystem_RobotID==0);
}
/*
*函数简介:UART1串口中断接收裁判系统数据
*参数说明:无
*返回类型:无
*备注:数据帧格式在最上方注释
*/
void USART6_IRQHandler(void)
{
/*有效数据位数=命令码对应数据段长度+2*/
#define DataLength1 15//裁判系统0x0201命令码有效数据位数
#define DataLength2 18//裁判系统0x0202命令码有效数据位数
static int RxHEXState=0;//定义静态变量用于接收模式的选择
static int pRxHEXState=0;//定义静态变量用于充当计数器
uint8_t RefereeSystem_RxData;//裁判系统接收数据
int RefereeSystem_PowerRow;//底盘实时功率原始数据
if(USART_GetITStatus(USART6,USART_IT_RXNE)==SET)//查询接收中断标志位
{
USART_ClearITPendingBit(USART6,USART_IT_RXNE);//清除接收中断标志位
RefereeSystem_RxData=USART_ReceiveData(USART6);//将数据存入缓存区
/*=====检查帧头=====*/
if(RxHEXState==0){if(RefereeSystem_RxData==0xA5)RxHEXState=1;}
/*=====检查数据段长度,区分命令码=====*/
else if(RxHEXState==1)
{
if(RefereeSystem_RxData==0x0D)RxHEXState=2;//0x0201命令码
else if(RefereeSystem_RxData==0x10)RxHEXState=8;//0x0202命令码
else RxHEXState=0;//其他命令码直接跳过
}
/*=====0x0201命令码=====*/
/*=====检查帧头其他部分=====*/
else if(RxHEXState==2){if(RefereeSystem_RxData==0x00)RxHEXState=3;else RxHEXState=0;}
else if(RxHEXState==3){RefereeSystem_RxHEXPacket1[3]=RefereeSystem_RxData;RxHEXState=4;}
else if(RxHEXState==4)
{
RefereeSystem_RxHEXPacket1[4]=RefereeSystem_RxData;
if(RefereeSystem_VerifyCRC8CheckSum(RefereeSystem_RxHEXPacket1,5)==1)RxHEXState=5;//检查CRC8
else RxHEXState=0;
}
/*=====检查命令码=====*/
else if(RxHEXState==5){if(RefereeSystem_RxData==0x01)RxHEXState=6;else RxHEXState=0;}
else if(RxHEXState==6){if(RefereeSystem_RxData==0x02){RxHEXState=7;pRxHEXState=0;}else RxHEXState=0;}
/*=====接收有效数据=====*/
else if(RxHEXState==7)
{
RefereeSystem_RxHEXPacket1[pRxHEXState+7]=RefereeSystem_RxData;//接收数据
pRxHEXState++;
if(pRxHEXState>=DataLength1)
{
if(RefereeSystem_VerifyCRC16CheckSum(RefereeSystem_RxHEXPacket1,22)==1)//CRC校验
{
RefereeSystem_RobotID=RefereeSystem_RxHEXPacket1[7];//获取机器人ID
RefereeSystem_ShooterStatus=(RefereeSystem_RxHEXPacket1[19]&0x04)>>2;//获取发射机构状态
RefereeSystem_Ref=RefereeSystem_RxHEXPacket1[17]|((uint16_t)RefereeSystem_RxHEXPacket1[18]<<8);//获取功率上限
}
RxHEXState=0;
}
}
/*=====0x0202命令码=====*/
/*=====检查帧头其他部分=====*/
else if(RxHEXState==8){if(RefereeSystem_RxData==0x00)RxHEXState=9;else RxHEXState=0;}
else if(RxHEXState==9){RefereeSystem_RxHEXPacket2[3]=RefereeSystem_RxData;RxHEXState=10;}
else if(RxHEXState==10)
{
RefereeSystem_RxHEXPacket2[4]=RefereeSystem_RxData;
if(RefereeSystem_VerifyCRC8CheckSum(RefereeSystem_RxHEXPacket2,5)==1)RxHEXState=11;
else RxHEXState=0;
}
/*=====检查命令码=====*/
else if(RxHEXState==11){if(RefereeSystem_RxData==0x02)RxHEXState=12;else RxHEXState=0;}
else if(RxHEXState==12){if(RefereeSystem_RxData==0x02){RxHEXState=13;pRxHEXState=0;}else RxHEXState=0;}
/*=====接收有效数据=====*/
else if(RxHEXState==13)
{
RefereeSystem_RxHEXPacket2[pRxHEXState+7]=RefereeSystem_RxData;//接收数据
pRxHEXState++;
if(pRxHEXState>=DataLength2)
{
if(RefereeSystem_VerifyCRC16CheckSum(RefereeSystem_RxHEXPacket2,25)==1)//CRC校验
{
RefereeSystem_Buffer=RefereeSystem_RxHEXPacket2[15]|((uint16_t)RefereeSystem_RxHEXPacket2[16]<<8);//获取缓冲能量
RefereeSystem_PowerRow=(int32_t)((uint32_t)RefereeSystem_RxHEXPacket2[11]|((uint32_t)RefereeSystem_RxHEXPacket2[12]<<8)|((uint32_t)RefereeSystem_RxHEXPacket2[13]<<16)|((uint32_t)RefereeSystem_RxHEXPacket2[14]<<24));
RefereeSystem_Power=*((float *)(&RefereeSystem_PowerRow));//获取底盘实时功率
}
RxHEXState=0;
}
}
}
}