⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 talktocardlg.cpp

📁 用VC++编的通过串口控制STC12C5410AD单片机的程序
💻 CPP
📖 第 1 页 / 共 2 页
字号:
	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 + -