509 lines
15 KiB
C
509 lines
15 KiB
C
#include "MAIN.H"
|
||
//can信息
|
||
UnInfCan UnInfCan_1 = {0};
|
||
UnSwSample UnSwSample_1 = {0};
|
||
UnSwOut UnSwOut_1 = {0};
|
||
UnRemoteControlOutput UnRemoteControlOutput_1 = {0,0,0,0,0,0,0,0};//遥控器数据发送
|
||
UnRemoteControlOutput UnRemoteControlOutput_2 = {0,0,0,0,0,0,0,0};//遥控器数据发送
|
||
|
||
SBusData sbus_data;
|
||
|
||
//CAN发送周期
|
||
uword CntCan_1 = 0;
|
||
bit FlgCan_1 = 0;
|
||
|
||
//第一次采集到有效数据指示
|
||
bit FlgOneTime = 0;
|
||
ubyte uart2RxFlag = 0;
|
||
uword RgCanPerid = 50;
|
||
|
||
ubyte can_error_cnt = 0;
|
||
ubyte can_error_flg = 0;
|
||
|
||
//PWM 20181227
|
||
ubyte PwmH[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
|
||
//-----------------------------------------------------------------------
|
||
//RTC定时器
|
||
//-----------------------------------------------------------------------
|
||
void RTCProcess(void)
|
||
{
|
||
//************************************************************************
|
||
//////CAN发送周期
|
||
if(FlgCan_1){CntCan_1++;if(CntCan_1 >= RgCanPerid){FlgCan_1=0; CntCan_1=0;}}else{CntCan_1=0;}
|
||
|
||
//************************************************************************
|
||
}
|
||
|
||
// SBus 数据解析函数
|
||
SBusData* parseSBusData(const uint8_t *input_data)
|
||
{
|
||
// 解析16个通道的数据,每个通道为11位
|
||
sbus_data.channels[0] = (input_data[1] | input_data[2] << 8) & 0x07FF;
|
||
sbus_data.channels[1] = (input_data[2] >> 3 | input_data[3] << 5) & 0x07FF;
|
||
sbus_data.channels[2] = (input_data[3] >> 6 | input_data[4] << 2 | input_data[5] << 10) & 0x07FF;
|
||
sbus_data.channels[3] = (input_data[5] >> 1 | input_data[6] << 7) & 0x07FF;
|
||
sbus_data.channels[4] = (input_data[6] >> 4 | input_data[7] << 4) & 0x07FF;
|
||
sbus_data.channels[5] = (input_data[7] >> 7 | input_data[8] << 1 | input_data[9] << 9) & 0x07FF;
|
||
|
||
sbus_data.channels[6] = (input_data[9] >> 2 | input_data[10] << 6) & 0x07FF;
|
||
sbus_data.channels[7] = (input_data[10] >> 5 | input_data[11] << 3) & 0x07FF;
|
||
sbus_data.channels[8] = (input_data[12] | input_data[13] << 8) & 0x07FF;
|
||
sbus_data.channels[9] = (input_data[13] >> 3 | input_data[14] << 5) & 0x07FF;
|
||
sbus_data.channels[10] = (input_data[14] >> 6 | input_data[15] << 2 | input_data[15] << 10) & 0x07FF;
|
||
sbus_data.channels[11] = (input_data[16] >> 1 | input_data[17] << 7) & 0x07FF;
|
||
sbus_data.channels[12] = (input_data[17] >> 4 | input_data[18] << 4) & 0x07FF;
|
||
sbus_data.channels[13] = (input_data[18] >> 7 | input_data[19] << 1 | input_data[20] << 9) & 0x07FF;
|
||
sbus_data.channels[14] = (input_data[20] >> 2 | input_data[21] << 6) & 0x07FF;
|
||
sbus_data.channels[15] = (input_data[21] >> 5 | input_data[22] << 3) & 0x07FF;
|
||
|
||
// 解析标志字节
|
||
sbus_data.flags = input_data[23];
|
||
uart2RxFlag = 1;
|
||
|
||
// for(ubyte i=0;i<8;i++)
|
||
// {
|
||
// printf( "%d ",i);
|
||
// printf( "%04x\r\n",sbus_data.channels[i]);
|
||
// }
|
||
// printf("%d\r\n",sbus_data.channels[0]);
|
||
return &sbus_data;
|
||
}
|
||
|
||
//can错误处理
|
||
void CanErrorProcess(void)
|
||
{
|
||
ubyte ubNSRL;
|
||
ubyte ubNSRH;
|
||
ubyte ubResetLEC = 0x3F;
|
||
//-------------------------------------------
|
||
EA = 0;
|
||
|
||
CAN_pushAMRegs(); // push the CAN Access Mediator Registers
|
||
SFR_PAGE(_su0, SST0); // switch to page 0
|
||
|
||
CAN_vWriteCANAddress(CAN_NSR0);
|
||
CAN_vReadEN();
|
||
ubNSRL = CAN_DATA0;
|
||
ubNSRH = CAN_DATA1;
|
||
if (ubNSRL & 0x20) // if ALERT
|
||
{
|
||
CAN_vInit();
|
||
}
|
||
if (ubNSRL & 0x07) // if LEC
|
||
{
|
||
ubResetLEC = 0x38;
|
||
}
|
||
//// Reset LEC, TXOK, RXOK, ALERT, EWRN, BOFF, LLE, LOE (if set)
|
||
CAN_vWriteCANAddress(CAN_NSR0); // Addressing CAN_NSR0
|
||
CAN_DATA0 = ~(ubNSRL & ubResetLEC); // load CAN_NSR0 status register[7-0]
|
||
CAN_DATA1 = ~(ubNSRH); // load CAN_NSR0 status register[15-8]
|
||
CAN_vWriteEN(D0_VALID+D1_VALID); // Data0 and Data1 are Valid for
|
||
|
||
SFR_PAGE(_su0, RST0); // restore the old SCU page
|
||
CAN_popAMRegs(); // restore the CAN Access Mediator Registers
|
||
|
||
EA = 1;
|
||
}
|
||
|
||
|
||
void CanTransmit(ubyte index,ubyte *buf)
|
||
{
|
||
ubyte CanTransmitbuf[8] = {0,0,0,0,0,0,0,0};
|
||
//----------------- --------
|
||
CanTransmitbuf[2] = buf[0];
|
||
CanTransmitbuf[3] = buf[1];
|
||
CanTransmitbuf[0] = buf[2];
|
||
CanTransmitbuf[1] = buf[3];
|
||
CanTransmitbuf[6] = buf[4];
|
||
CanTransmitbuf[7] = buf[5];
|
||
CanTransmitbuf[4] = buf[6];
|
||
CanTransmitbuf[5] = buf[7];
|
||
|
||
CAN_waitTransmit(index);//发送前等待上一帧发送完毕,这样不会丢帧
|
||
CAN_vLoadData(index, (ulong *)CanTransmitbuf);// 装载数据
|
||
CAN_vTransmit(index);
|
||
}
|
||
|
||
typedef enum {
|
||
STT_INIT_LIGHT, // 必须保留的初始状态
|
||
STT_STABLE, // 稳定态
|
||
STT_BLINK_CHECK, // 闪烁检测
|
||
STT_BLINKING // 闪烁保持
|
||
} BlinkState;
|
||
|
||
typedef struct {
|
||
BlinkState current_state;
|
||
uint8_t last_input;
|
||
uint16_t unified_timer; // 统一计时器[7](@ref)
|
||
uint8_t trans_count; // 保留必要的事件计数器
|
||
uint8_t stable_type;
|
||
} BlinkDetector;
|
||
|
||
BlinkDetector blink_detector = {0};
|
||
|
||
/* LED状态检测核心状态机(统一计时器优化版)
|
||
* 参数:
|
||
* ctx - 状态机上下文指针(需保证非空)
|
||
* current_input- 当前输入电平(0:灭 1:亮)
|
||
* output - 输出状态指针(0:无效 1:稳定亮 2:稳定灭 3:闪烁)
|
||
* 设计原则:
|
||
* 1. 单一定时器复用机制[8](@ref)
|
||
* 2. 防御性清零策略[1](@ref)
|
||
* 3. 状态迁移原子操作[9](@ref)
|
||
*/
|
||
void detectLedState(BlinkDetector* ctx, uint8_t current_input, uint8_t* output)
|
||
{
|
||
*output = 0;
|
||
|
||
switch(ctx->current_state)
|
||
{
|
||
/* 关键初始状态:确保首次正确捕获输入 */
|
||
case STT_INIT_LIGHT:
|
||
{
|
||
ctx->last_input = current_input; // 强制记录初始值
|
||
ctx->stable_type = current_input ? 1 : 2;
|
||
ctx->current_state = STT_STABLE; // 立即进入稳定态
|
||
ctx->unified_timer = 0; // 初始化计时器
|
||
*output = 0;
|
||
break;
|
||
}
|
||
|
||
case STT_STABLE:
|
||
{
|
||
if(current_input != ctx->last_input)
|
||
{
|
||
ctx->current_state = STT_BLINK_CHECK;
|
||
ctx->trans_count = 1;
|
||
ctx->unified_timer = 0;
|
||
ctx->last_input = current_input;
|
||
ctx->stable_type = current_input ? 1 : 2; // 同步状态类型[4](@ref)
|
||
}
|
||
else if(ctx->unified_timer >= STABLE_CONFIRM_TIME)
|
||
{
|
||
*output = ctx->stable_type;
|
||
ctx->unified_timer = 0;
|
||
ctx->stable_type = current_input ? 1 : 2; // 二次确认[10](@ref)
|
||
}
|
||
else
|
||
{
|
||
ctx->unified_timer++;
|
||
*output = ctx->stable_type;
|
||
}
|
||
break;
|
||
}
|
||
/* 闪烁检测态:在时间窗口内统计电平跳变次数 */
|
||
case STT_BLINK_CHECK:
|
||
{
|
||
if(ctx->unified_timer >= BLINK_WINDOW) // 达到检测窗口时长[8](@ref)
|
||
{
|
||
if(ctx->trans_count >= MIN_BLINKS) // 满足最小闪烁次数
|
||
{
|
||
ctx->current_state = STT_BLINKING;// 进入闪烁保持态
|
||
ctx->unified_timer = 0; // 重置超时计时器
|
||
}
|
||
else // 未达闪烁阈值
|
||
{
|
||
ctx->current_state = STT_STABLE; // 返回稳定态
|
||
ctx->unified_timer = 0; // 跨状态复用计时器
|
||
}
|
||
}
|
||
else // 窗口期内检测
|
||
{
|
||
ctx->unified_timer++; // 窗口期计时累计
|
||
if(current_input != ctx->last_input)
|
||
{
|
||
ctx->trans_count++; // 跳变次数累计
|
||
ctx->last_input = current_input; // 更新最新输入值
|
||
}
|
||
}
|
||
break;
|
||
}
|
||
|
||
/* 闪烁保持态:监测闪烁活动持续性 */
|
||
case STT_BLINKING:
|
||
{
|
||
// 新增输入变化检测
|
||
if(current_input != ctx->last_input)
|
||
{
|
||
ctx->unified_timer = 0; // 重置超时计时器
|
||
ctx->last_input = current_input;
|
||
*output = 3; // 持续输出闪烁状态
|
||
}
|
||
else if(ctx->unified_timer >= BLINK_TIMEOUT)
|
||
{
|
||
ctx->current_state = STT_STABLE;
|
||
ctx->stable_type = current_input ? 1 : 2; // 根据最终状态更新类型[4](@ref)
|
||
ctx->unified_timer = 0;
|
||
}
|
||
else
|
||
{
|
||
ctx->unified_timer ++; // 仅当输入稳定时累计计时
|
||
*output = 3; // 持续输出闪烁状态
|
||
}
|
||
break;
|
||
}
|
||
|
||
default:break;
|
||
}
|
||
}
|
||
|
||
//SBUS和CAN的数据转换
|
||
void sbusCanDecode(void)
|
||
{
|
||
float SBUS2CANdecodeTemp = 0.0;
|
||
|
||
//----------------------------------------------
|
||
if(uart2RxFlag == 1)
|
||
{
|
||
uart2RxFlag = 0;
|
||
|
||
//转弯
|
||
SBUS2CANdecodeTemp = (float)(sbus_data.channels[0]);
|
||
SBUS2CANdecodeTemp = (DF_ZeroValue - SBUS2CANdecodeTemp)*23;//需要变换一下符号,因为加油是正
|
||
DF_Curvature = (int16_t)SBUS2CANdecodeTemp;//曲率
|
||
if( (DF_Curvature > (-50)) && (DF_Curvature < 50) ) //增加回0的死区,解决会中问题。
|
||
{
|
||
DF_Curvature = 0;
|
||
}
|
||
|
||
//转速
|
||
SBUS2CANdecodeTemp = (float)(sbus_data.channels[1]);
|
||
SBUS2CANdecodeTemp = (DF_ZeroValue - SBUS2CANdecodeTemp)*2.3;//需要变换一下符号,因为加油是正
|
||
DF_Speed = (int16_t)SBUS2CANdecodeTemp;//转速
|
||
if( (DF_Speed > (-50)) && (DF_Speed < 50) ) //增加回0的死区,解决会中问题。
|
||
{
|
||
DF_Speed = 0;
|
||
}
|
||
|
||
//备用
|
||
SBUS2CANdecodeTemp = (float)(sbus_data.channels[7]);
|
||
SBUS2CANdecodeTemp = (DF_ZeroValue - SBUS2CANdecodeTemp);//需要变换一下符号,因为加油是正
|
||
DF_Reserve = (int16_t)SBUS2CANdecodeTemp;//转速
|
||
if( (DF_Reserve > (-50)) && (DF_Reserve < 50) ) //增加回0的死区,解决会中问题。
|
||
{
|
||
DF_Reserve = 0;
|
||
}
|
||
|
||
|
||
//SwA
|
||
if(sbus_data.channels[1] >= 1700)//按下
|
||
{
|
||
DF_SwA = 1;
|
||
}
|
||
else
|
||
{
|
||
DF_SwA = 0;
|
||
}
|
||
|
||
//SwB
|
||
if(sbus_data.channels[6] >= 1700)//第三档
|
||
{
|
||
DF_SwB = 2;
|
||
}
|
||
else if(sbus_data.channels[6] <= 250)//第二档
|
||
{
|
||
DF_SwB = 0;
|
||
}
|
||
else//第一档
|
||
{
|
||
DF_SwB = 1;
|
||
}
|
||
|
||
//SwC
|
||
if(sbus_data.channels[4] >= 1700)//第三档
|
||
{
|
||
DF_SwC = 2;
|
||
}
|
||
else if(sbus_data.channels[4] <= 250)//第二档
|
||
{
|
||
DF_SwC = 0;
|
||
}
|
||
else//第一档
|
||
{
|
||
DF_SwC = 1;
|
||
}
|
||
|
||
//SwD
|
||
if(sbus_data.channels[5] >= 1700)//按下
|
||
{
|
||
DF_SwD = 1;
|
||
}
|
||
else
|
||
{
|
||
DF_SwD = 0;
|
||
}
|
||
|
||
if(0 == sbus_data.flags)//23通道数据 为0标志手柄连接正常
|
||
{
|
||
DF_RCHSta = 1;//手柄在线
|
||
}
|
||
else
|
||
{
|
||
DF_RCHSta = 0;//手柄离线
|
||
}
|
||
|
||
SBUS2CANdecodeTemp = (float)(sbus_data.channels[2]);
|
||
UnRemoteControlOutput_2.bit_data.speed = (int16_t)SBUS2CANdecodeTemp;//保留轴
|
||
|
||
SBUS2CANdecodeTemp = (float)(sbus_data.channels[3]);
|
||
UnRemoteControlOutput_2.bit_data.curvature = (int16_t)SBUS2CANdecodeTemp;//保留轴
|
||
|
||
}
|
||
|
||
UnRemoteControlOutput_2.bit_data.switch_a = P1_2;//
|
||
UnRemoteControlOutput_2.bit_data.switch_d = P1_3;//
|
||
}
|
||
|
||
|
||
//CAN发送接收
|
||
void CanRXTX(void)
|
||
{
|
||
stCAN_SWObj StrCanRx = {0};
|
||
uword tmp = 0;
|
||
ubyte i = 0,j = 0;
|
||
ubyte sbus_temp[2] = {0,0};
|
||
|
||
static ubyte match_freq_sta = 0;
|
||
static uword match_freq_cnt = 0;
|
||
static uword match_freq_time = 0;
|
||
//------------------------------------
|
||
if(CAN_ubNewData(DF_SwRx))
|
||
{
|
||
CAN_vGetMsgObj(DF_SwRx, &StrCanRx);
|
||
|
||
UnInfCan_1.ArrData.ArrRX[0][3] = StrCanRx.ulDATAL.ubDB[0];
|
||
UnInfCan_1.ArrData.ArrRX[0][2] = StrCanRx.ulDATAL.ubDB[1];
|
||
UnInfCan_1.ArrData.ArrRX[0][1] = StrCanRx.ulDATAL.ubDB[2];
|
||
UnInfCan_1.ArrData.ArrRX[0][0] = StrCanRx.ulDATAL.ubDB[3];
|
||
UnInfCan_1.ArrData.ArrRX[0][7] = StrCanRx.ulDATAH.ubDB[0];
|
||
UnInfCan_1.ArrData.ArrRX[0][6] = StrCanRx.ulDATAH.ubDB[1];
|
||
UnInfCan_1.ArrData.ArrRX[0][5] = StrCanRx.ulDATAH.ubDB[2];
|
||
UnInfCan_1.ArrData.ArrRX[0][4] = StrCanRx.ulDATAH.ubDB[3];
|
||
|
||
CAN_vReleaseObj(DF_SwRx);
|
||
}
|
||
|
||
if(CAN_ubNewData(DF_SwRxPwm))
|
||
{
|
||
// CAN_vGetMsgObj(DF_SwRxPwm, &StrCanRx);
|
||
|
||
// UnInfCan_1.ArrData.ArrRX[1][2] = StrCanRx.ulDATAL.ubDB[0];
|
||
// UnInfCan_1.ArrData.ArrRX[1][3] = StrCanRx.ulDATAL.ubDB[1];
|
||
// UnInfCan_1.ArrData.ArrRX[1][0] = StrCanRx.ulDATAL.ubDB[2];
|
||
// UnInfCan_1.ArrData.ArrRX[1][1] = StrCanRx.ulDATAL.ubDB[3];
|
||
// UnInfCan_1.ArrData.ArrRX[1][6] = StrCanRx.ulDATAH.ubDB[0];
|
||
// UnInfCan_1.ArrData.ArrRX[1][7] = StrCanRx.ulDATAH.ubDB[1];
|
||
// UnInfCan_1.ArrData.ArrRX[1][4] = StrCanRx.ulDATAH.ubDB[2];
|
||
// UnInfCan_1.ArrData.ArrRX[1][5] = StrCanRx.ulDATAH.ubDB[3];
|
||
|
||
// CAN_vReleaseObj(DF_SwRxPwm);
|
||
//// //接收的数据保存到PWM数据结构中20181227
|
||
//// PwmH[0 ] = (ubyte)UnInfCan_1.BitData.Pwm_01;
|
||
//// PwmH[1 ] = (ubyte)UnInfCan_1.BitData.Pwm_02;
|
||
//// PwmH[2 ] = (ubyte)UnInfCan_1.BitData.Pwm_03;
|
||
//// PwmH[3 ] = (ubyte)UnInfCan_1.BitData.Pwm_04;
|
||
//// PwmH[4 ] = (ubyte)UnInfCan_1.BitData.Pwm_05;
|
||
//// PwmH[5 ] = (ubyte)UnInfCan_1.BitData.Pwm_06;
|
||
//// PwmH[6 ] = (ubyte)UnInfCan_1.BitData.Pwm_07;
|
||
//// PwmH[7 ] = (ubyte)UnInfCan_1.BitData.Pwm_08;
|
||
//// PwmH[8 ] = (ubyte)UnInfCan_1.BitData.Pwm_09;
|
||
//// PwmH[9 ] = (ubyte)UnInfCan_1.BitData.Pwm_10;
|
||
//// PwmH[10] = (ubyte)UnInfCan_1.BitData.Pwm_11;
|
||
//// PwmH[11] = (ubyte)UnInfCan_1.BitData.Pwm_12;
|
||
//// PwmH[12] = (ubyte)UnInfCan_1.BitData.Pwm_13;
|
||
//// PwmH[13] = (ubyte)UnInfCan_1.BitData.Pwm_14;
|
||
//// PwmH[14] = (ubyte)UnInfCan_1.BitData.Pwm_15;
|
||
//// PwmH[15] = (ubyte)UnInfCan_1.BitData.Pwm_16;
|
||
|
||
}
|
||
|
||
//50ms发送一帧
|
||
if(!FlgCan_1)
|
||
{
|
||
FlgCan_1 = 1;
|
||
|
||
sbus_temp[0] = P1_3;
|
||
|
||
// sbus_temp[1] = 3;
|
||
detectLedState(&blink_detector, sbus_temp[0], &sbus_temp[1]);
|
||
// UnRemoteControlOutput_2.bit_data.enable = blink_detector.current_state;//
|
||
// UnRemoteControlOutput_2.bit_data.reserve1 = sbus_temp[1];
|
||
|
||
|
||
if( (MATCH_CMD == UnInfCan_1.ArrData.ArrRX[0][0]) || (CHANGE_CMD == UnInfCan_1.ArrData.ArrRX[0][0]) )//对频或者切换
|
||
{
|
||
if(MATCH_CMD == UnInfCan_1.ArrData.ArrRX[0][0])//对频
|
||
{
|
||
match_freq_time = MATCH_TIME;
|
||
}
|
||
else
|
||
{
|
||
match_freq_time = CHANGE_TIME;
|
||
}
|
||
|
||
switch(match_freq_sta)
|
||
{
|
||
case 0:
|
||
if(match_freq_cnt >= match_freq_time)//时间根据命令确定
|
||
{
|
||
SwOut01 = 0;//取消对频
|
||
match_freq_sta = 1;
|
||
match_freq_cnt = 0;
|
||
}
|
||
else
|
||
{
|
||
SwOut01 = 1;//对频指令
|
||
match_freq_sta = 0;
|
||
match_freq_cnt ++;
|
||
}
|
||
break;
|
||
|
||
case 1:
|
||
if(match_freq_cnt >= MATCH_WAIT_TIME)//
|
||
{
|
||
SwOut01 = 0;//取消对频
|
||
match_freq_sta = 0;
|
||
match_freq_cnt = 0;
|
||
UnInfCan_1.ArrData.ArrRX[0][0] = 0;
|
||
}
|
||
else
|
||
{
|
||
SwOut01 = 0;//对频指令
|
||
match_freq_sta = 1;
|
||
match_freq_cnt ++;
|
||
}
|
||
break;
|
||
default:;
|
||
}
|
||
}
|
||
|
||
CanTransmit(DF_SwTx,(ubyte *)&UnRemoteControlOutput_1.arr[0]);
|
||
CanTransmit(DF_SwTx1,(ubyte *)&UnRemoteControlOutput_2.arr[0]);
|
||
}
|
||
|
||
if( (0x40 == can_error_cnt) || (0x80 == can_error_cnt) )//20250625判断是否出现总线错误
|
||
{
|
||
can_error_flg = can_error_cnt;
|
||
CAN_vInit();
|
||
can_error_cnt = 0;
|
||
}
|
||
|
||
|
||
|
||
}
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|