📄 talktocardlg.cpp
字号:
m_ctrlCommToCar.SetInputLen(0); // 设置当前接收区数据长度为0
m_ctrlCommToCar.GetInput(); // 先预读缓冲区以清除残留数据
m_ucGetBack = m_ucSaveBack; // 初始化接收指针
return(true);
}
// 根据命令取相应数据,构建发送数据帧
void CTalkToCarDlg::makeSendFrame(int iCommand, CByteArray *sendFrame)
{
union
{
UINT all;
BYTE b[4];
}uitemp;
int i;
unsigned short ushDataAddr;
int iRunMode;
BYTE sum = 0;
sendFrame->RemoveAll();
sendFrame->Add(0x55);
sendFrame->Add(0xAA); // 初始化帧头
sendFrame->Add(CAR_ADDR);
sendFrame->Add(PC_ADDR);
switch (iCommand)
{
case READ_BYTE:
{
sendFrame->Add(0x04); // 帧长
sendFrame->Add(READ_MEMORY); // 命令字
sum += READ_MEMORY;
// 将输入的 16 进制地址转换, 因为M51文件中的变量地址通常为 16进制
m_szDataAddr.MakeUpper();
ushDataAddr = HexString2ush(m_szDataAddr);
uitemp.all = ushDataAddr; // 数据地址
sendFrame->Add(uitemp.b[0]); // 低字节
sum += uitemp.b[0];
sendFrame->Add(uitemp.b[1]); // 高字节, 只取低 2 字节
sum += uitemp.b[1];
i = m_ctrlDataType.GetCurSel(); // 读数据类型处理
if( i<= 1)
{
sendFrame->Add(0x01); // 读有无符号字节的字节数
sum += 0x01;
}
else
{
if(i <= 3)
{
sendFrame->Add(0x02); // 读有无符号整形的字节数
sum += 0x02;
}
else
{
sendFrame->Add(0x04); // 读有符号长整的字节数
sum += 0x04;
}
}
sendFrame->Add(~sum); // 校验和
break;
}
case WRITE_BYTE:
{
sendFrame->Add(0x05); // 帧长
sendFrame->Add(WRITE_MEMORY); // 命令字
sum += WRITE_MEMORY;
// 将输入的 16 进制地址转换, 因为M51文件中的变量地址通常为 16进制
m_szDataAddr.MakeUpper();
ushDataAddr = HexString2ush(m_szDataAddr);
uitemp.all = ushDataAddr; // 数据地址
sendFrame->Add(uitemp.b[0]); // 低字节
sum += uitemp.b[0];
sendFrame->Add(uitemp.b[1]); // 高字节
sum += uitemp.b[1];
sendFrame->Add(0x01); // 字节数
sum += 0x01;
sendFrame->Add(m_ucWriteData); // 要写的字节
sum += m_ucWriteData;
sendFrame->Add(~sum); // 校验和
break;
}
case MOTOR_PWM:
{
sendFrame->Add(0x05); // 帧长
sendFrame->Add(MOTOR_PWM_CTRL); // 命令字
sum += MOTOR_PWM_CTRL;
uitemp.all = m_uiPWM_Val[0]; // 左侧电机数据
sendFrame->Add(uitemp.b[0]); // 低字节
sum += uitemp.b[0];
sendFrame->Add(uitemp.b[1]); // 高字节
sum += uitemp.b[1];
uitemp.all = m_uiPWM_Val[1]; // 右侧电机数据
sendFrame->Add(uitemp.b[0]); // 低字节
sum += uitemp.b[0];
sendFrame->Add(uitemp.b[1]); // 高字节
sum += uitemp.b[1];
sendFrame->Add(~sum); // 校验和
break;
}
case RUN_STR:
{
iRunMode = m_ctrlRunMode.GetCurSel();
sendFrame->Add(0x05); // 帧长
switch (iRunMode)
{
case 0:
{
sendFrame->Add(RUN_STRAIGHT); // 命令字
sum += RUN_STRAIGHT;
break;
}
case 1:
{
sendFrame->Add(RUN_ON_LINE); // 命令字
sum += RUN_ON_LINE;
m_ctrlRunDir.SetCurSel(0); // 走轨迹只支持前进
break;
}
case 2:
{
sendFrame->Add(HOLD_GAP); // 命令字
sum += HOLD_GAP;
m_ctrlRunDir.SetCurSel(0); // 只支持前进
break;
}
default: break;
}
CString szButton;
GetDlgItem(IDC_RUN_STRAIGHT) -> GetWindowText(szButton);
if(szButton == "启动")
{
// 启动处理
GetDlgItem(IDC_RUN_STRAIGHT) -> SetWindowText("停止");
if(iRunMode == 2)
{
uitemp.all = m_uiGap2Object; // 取设定的距离
}
else
{
uitemp.all = m_uiLeftRunNum; // 取行走脉冲定值
}
sendFrame->Add(uitemp.b[0]);
sum += uitemp.b[0];
sendFrame->Add(uitemp.b[1]); // 只取低 2 字节
sum += uitemp.b[1];
sendFrame->Add(m_ucBase_PWM);
sum += m_ucBase_PWM;
if(m_ctrlRunDir.GetCurSel() == 0)
{
sendFrame ->Add(0); // 设置 PWM 值方向:前进
}
else
{
sendFrame ->Add(0xFF); // 设置 PWM 值方向:后退
sum += 0xFF;
}
}
else
{
// 停止处理
GetDlgItem(IDC_RUN_STRAIGHT) -> SetWindowText("启动");
sendFrame ->Add(0);
sendFrame ->Add(0);
sendFrame ->Add(BRAKE_PWM); // 发送刹车PWM值作为基值
sum +=BRAKE_PWM;
sendFrame ->Add(0); // PWM值高字节为0
}
sendFrame->Add(~sum); // 校验和
break;
}
case READ_SAMPLE:
{
sendFrame->Add(0x04); // 帧长
sendFrame->Add(READ_MEMORY); // 命令字
sum += READ_MEMORY;
// 将输入的 16 进制地址转换, 因为M51文件中的变量地址通常为 16进制
m_szSampleAddr.MakeUpper();
ushDataAddr = HexString2ush(m_szSampleAddr);
uitemp.all = ushDataAddr; // 数据地址
sendFrame->Add(uitemp.b[0]); // 低字节
sum += uitemp.b[0];
sendFrame->Add(uitemp.b[1]); // 高字节, 只取低 2 字节
sum += uitemp.b[1];
sendFrame->Add(0x05); // 读 5 字节
sum += 0x05;
sendFrame->Add(~sum); // 校验和
break;
}
case READ_DIS:
{
sendFrame->Add(0x04); // 帧长
sendFrame->Add(READ_MEMORY); // 命令字
sum += READ_MEMORY;
// 将输入的 16 进制地址转换, 因为M51文件中的变量地址通常为 16进制
m_szDisValAddr.MakeUpper();
ushDataAddr = HexString2ush(m_szDisValAddr);
uitemp.all = ushDataAddr; // 数据地址
sendFrame->Add(uitemp.b[0]); // 低字节
sum += uitemp.b[0];
sendFrame->Add(uitemp.b[1]); // 高字节, 只取低 2 字节
sum += uitemp.b[1];
sendFrame->Add(0x09); // 读 9 字节
sum += 0x09;
sendFrame->Add(~sum); // 校验和
break;
}
default: break;
}
m_szCommandBack = "失败";
this->UpdateData(false);
}
// 电机 PWM 控制处理
void CTalkToCarDlg::OnPWM_Out()
{
// TODO: Add your control notification handler code here
this->UpdateData(true); // 将对话框中的地址等数据取回
if(open_CommPort())
{
m_uiPWM_Val[0] = m_ucMotorL_PWM;
m_uiPWM_Val[1] = m_ucMotorR_PWM;
switch(m_ctrlMotor_L.GetCurSel())
{
case FORWARD:
{
break;
}
case BACKWARD:
{
m_uiPWM_Val[0] +=0xFF00;
break;
}
case FLOAT_C:
{
m_uiPWM_Val[0] =FLOAT_PWM;
break;
}
case BRAKE_C:
{
m_uiPWM_Val[0] =BRAKE_PWM;
break;
}
default: break;
}
switch(m_ctrlMotor_R.GetCurSel())
{
case FORWARD:
{
break;
}
case BACKWARD:
{
m_uiPWM_Val[1] +=0xFF00;
break;
}
case FLOAT_C:
{
m_uiPWM_Val[1] =FLOAT_PWM;
break;
}
case BRAKE_C:
{
m_uiPWM_Val[1] =BRAKE_PWM;
break;
}
default: break;
}
makeSendFrame(MOTOR_PWM, &m_baSendFrame); // 构建发送帧
m_iRcvStat = NO_RCV; // 初始化接收状态
m_ctrlCommToCar.SetOutput((COleVariant)m_baSendFrame); // 启动发送
m_baSendFrame.RemoveAll();
}
else
{
m_ctrlCommToCar.SetPortOpen(false);
}
}
// 电机刹车处理
void CTalkToCarDlg::OnBrake()
{
// TODO: Add your control notification handler code here
if(open_CommPort())
{
m_uiPWM_Val[0] = BRAKE_PWM;
m_uiPWM_Val[1] = BRAKE_PWM;
makeSendFrame(MOTOR_PWM, &m_baSendFrame); // 构建发送帧
m_iRcvStat = NO_RCV; // 初始化接收状态
m_ctrlCommToCar.SetOutput((COleVariant)m_baSendFrame); // 启动发送
m_baSendFrame.RemoveAll();
}
else
{
m_ctrlCommToCar.SetPortOpen(false);
}
}
// 电机惰行处理
void CTalkToCarDlg::OnFloat()
{
// TODO: Add your control notification handler code here
if(open_CommPort())
{
m_uiPWM_Val[0] = FLOAT_PWM;
m_uiPWM_Val[1] = FLOAT_PWM;
makeSendFrame(MOTOR_PWM, &m_baSendFrame); // 构建发送帧
m_iRcvStat = NO_RCV; // 初始化接收状态
m_ctrlCommToCar.SetOutput((COleVariant)m_baSendFrame); // 启动发送
m_baSendFrame.RemoveAll();
}
else
{
m_ctrlCommToCar.SetPortOpen(false);
}
}
// 走直线测试
void CTalkToCarDlg::OnRunStraight()
{
// TODO: Add your control notification handler code here
this->UpdateData(true); // 将对话框中的地址等数据取回
if(open_CommPort())
{
makeSendFrame(RUN_STR, &m_baSendFrame); // 构建发送帧
m_iRcvStat = NO_RCV; // 初始化接收状态
m_ctrlCommToCar.SetOutput((COleVariant)m_baSendFrame); // 启动发送
m_baSendFrame.RemoveAll();
}
else
{
m_ctrlCommToCar.SetPortOpen(false);
}
}
// 因为读采样值同样需要将 HEX 码地址转换为 unsigned short 值,
// 所以将前面的处理变成函数
unsigned short CTalkToCarDlg::HexString2ush(CString szHexVal)
{
BYTE ucVal,ucLen;
unsigned short ushDataAddr;
int i;
ushDataAddr = 0;
ucLen = szHexVal.GetLength(); // 得到输入的地址长度
if(ucLen >4 )
{
ucLen = 4; // 只处理 4 位
}
for(i =0; i<ucLen; i++)
{
ushDataAddr = ushDataAddr *16;
ucVal = (BYTE) (szHexVal[i]);
if(ucVal > 0x39)
{
ushDataAddr += ucVal - 0x41+10; // 转换 A - F
}
else
{
ushDataAddr += ucVal - 0x30; // 转换 0 - 9
}
}
return (ushDataAddr) ;
}
/*
读取采样处理相关数据:4 路采样模拟量的 AD 结果(8位),以及由此而产生的逻辑值
直接使用读内存功能,根据 M51 得到 AD 结果存放的地址。
注意:为了可以使用一帧命令读出 AD 结果和逻辑值,在单片机程序设计时将逻辑值和
AD 的结果放在一个数组中!!!
*/
void CTalkToCarDlg::OnReadSample()
{
// TODO: Add your control notification handler code here
this->UpdateData(true); // 将对话框中的地址等数据取回
if(open_CommPort())
{
m_iReadMemContent = SAMPLE_DATA;
makeSendFrame(READ_SAMPLE, &m_baSendFrame); // 构建发送帧
m_iRcvStat = NO_RCV; // 初始化接收状态
m_ctrlCommToCar.SetOutput((COleVariant)m_baSendFrame); // 启动发送
m_baSendFrame.RemoveAll();
}
else
{
m_ctrlCommToCar.SetPortOpen(false);
}
}
// 因为读内存处理太多,为便于阅读,将各类数据变成函数
// 此为读通用数据的处理
void CTalkToCarDlg::gatGeneralData()
{
union
{
int all;
BYTE b[4];
}itemp;
union
{
short all;
BYTE b[2];
}shtemp;
int iType;
iType = m_ctrlDataType.GetCurSel(); // 获得数据类型
switch(iType) // 根据数据类型处理返回的数据
{
case 0:
{
// sign char
m_iReadData = (int)((signed char)m_ucBackBuf[m_ucStartPtr+4]);
break;
}
case 1:
{
// BYTE
shtemp.all =0;
shtemp.b[0] = m_ucBackBuf[m_ucStartPtr+4];
m_iReadData = (int)shtemp.all;
break;
}
case 2:
{
// int
shtemp.b[1] = m_ucBackBuf[m_ucStartPtr+4];
shtemp.b[0] = m_ucBackBuf[m_ucStartPtr+5]; // C51 的整形顺序相反
m_iReadData = (int)shtemp.all;
break;
}
case 3:
{
// UINT
itemp.all =0;
itemp.b[1] = m_ucBackBuf[m_ucStartPtr+4];
itemp.b[0] = m_ucBackBuf[m_ucStartPtr+5]; // C51 的整形顺序相反
m_iReadData = itemp.all;
break;
}
case 4:
{
// long
itemp.b[4] = m_ucBackBuf[m_ucStartPtr+4];
itemp.b[3] = m_ucBackBuf[m_ucStartPtr+5];
itemp.b[2] = m_ucBackBuf[m_ucStartPtr+6];
itemp.b[1] = m_ucBackBuf[m_ucStartPtr+7]; // C51 的长整形顺序相反
m_iReadData = itemp.all;
break;
}
default: break;
}
}
// 读取轨迹采样数据处理
void CTalkToCarDlg::getSampleData()
{
m_ucSampleVal1 = m_ucBackBuf[m_ucStartPtr+4];
m_ucSampleVal2 = m_ucBackBuf[m_ucStartPtr+5];
m_ucSampleVal3 = m_ucBackBuf[m_ucStartPtr+6];
m_ucSampleVal4 = m_ucBackBuf[m_ucStartPtr+7];
m_ucSensorStat = m_ucBackBuf[m_ucStartPtr+8];
}
// 读取距离值操作
void CTalkToCarDlg::OnReadDis()
{
// TODO: Add your control notification handler code here
this->UpdateData(true); // 将对话框中的地址等数据取回
if(open_CommPort())
{
m_iReadMemContent = DIS_DATA;
makeSendFrame(READ_DIS, &m_baSendFrame); // 构建发送帧
m_iRcvStat = NO_RCV; // 初始化接收状态
m_ctrlCommToCar.SetOutput((COleVariant)m_baSendFrame); // 启动发送
m_baSendFrame.RemoveAll();
}
else
{
m_ctrlCommToCar.SetPortOpen(false);
}
}
// 取出返回的距离值
void CTalkToCarDlg::getDisData()
{
m_ucDisVal1 = m_ucBackBuf[m_ucStartPtr+4];
m_ucDisVal2 = m_ucBackBuf[m_ucStartPtr+5];
m_ucDisVal3 = m_ucBackBuf[m_ucStartPtr+6];
m_ucDisVal4 = m_ucBackBuf[m_ucStartPtr+7];
m_ucDisVal5 = m_ucBackBuf[m_ucStartPtr+8];
m_ucDisVal6 = m_ucBackBuf[m_ucStartPtr+9];
m_ucDisVal7 = m_ucBackBuf[m_ucStartPtr+10];
m_ucDisVal8 = m_ucBackBuf[m_ucStartPtr+11];
m_ucDisMeanVal = m_ucBackBuf[m_ucStartPtr+12];
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -