完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
ETA321是英创推出的基于STM32单片机的多功能扩展模块,可为英创现有的WinCE系统增加AD、DA、PWM、脉冲计数等功能。ETA321使用了一片STM32F103RCT6单片机,STM32F103RCT6通过其USB Device接口与英创工控主板连接通讯,STM32在WinCE系统中被当做一个串口设备,英创主板作为上位机已经固化了STM32的USB驱动程序,同时我们封装了一组STM32与英创WinCE系统通讯的API接口函数,客户可以利用我们提供的接口函数,把成熟的实时控制算法移植到ETA321上,快速实现与英创主板的数据通讯。在使用这些API函数时,需要遵从以下约定: 1、通讯以数据包(结构体)作为基本单元,每次通讯收/发一个数据包,每个数据包最大为255字节,数据包第一个字节为本数据包的字节长度,第二个字节为命令码,数据包的其它内容由用户自定义。 2、数据包的第二个命令码字节用于表明本数据包的“身份”。当STM32接收到数据包,得到命令码后,会根据命令码执行相应的操作,当上位机接收到数据包后,根据命令码就可以知道接收到了什么数据。0~127命令码表示常规命令和数据,128~255表示实时数据或实时命令。 3、数据包和命令码的定义在WinCE上位机端和STM32端必须完全一致。STM32必须对接收到的每个命令数据包回复一个相同命令码的应答包,如果没有数据需要回复,可简单回复通用应答数据包。 下面是命令码和数据包定义示例: /************************* 定义命令代码*************************/ #define MCU_GENERIC_VER_INFO 0 #define MCU_GENERIC_ADC 1
// STM32返回的实时数据命令码 #define MCU_REALtiME_ADC (0 + MCU_REALTIME_DATA)
/*********************** 定义数据包(结构体) **********************/ // 获取单片机固件版本信息 typedef struct { BYTE ucSize; // size of the structure < 256 BYTE ucCmd; // = MCU_GENERIC_VER_INFO WORD wMajor; // major version number WORD wMinor; // minor version number char ucName[24]; // name of realtime driver } MCU_VER_INFO, *PMCU_VER_INFO; // struct for Version Info // ADC命令 typedef struct { BYTE ucSize; // size of the structure < 256 BYTE ucCmd; // = MCU_GENERIC_ADC BYTE ucCH; // AD通道 DWORD dwSamplingRate; // 采样率 } MCU_ADC, *PMCU_ADC; // struct for Version Info
// STM32通用应答数据包 typedef struct { BYTE ucSize; // size of the structure < 256 BYTE ucCmd; // BYTE ucRerult; }MCU_GENERIC_REPLY, *PMCU_GENERIC_REPLY; WinCE上位机API函数 在WinCE上使用我们提供的API函数时,需要在工程中包含以下3个文件 #include "mcu_class.h" // API接口函数定义 #include "mcuCmdInfo.h" // 命令码和数据包定义 #pragma comment(lib, "mcu_class.lib") // 包含库文件 下面是API函数说明: /** @Brief 打开MCU设备,初始化相关环境 @param None @retval = 返回true 打开成功 **/ BOOL OpenMCU();
/** @brief 给STM32发送控制指令 @param *pCmdInfo[in]:符合约定数据结构的命令数据 @param *pBuf[out]: 接收STM32返回数据的数据缓存,此参数可为NULL @param dwBufSize[in]:数据缓存大小 @retval = true 发送成功,返回true仅表示数据通讯成功,命令执行情况可查看pBuf返回的数据 **/ BOOL SendCmd(BYTE *pCmdInfo, BYTE *pBuf, DWORD dwBufSize = 0);
/** @brief 关闭MCU,释放相关资源 @param None @retval = true 关闭成功 **/ BOOL CloseMCU();
/** @brief 接收STM32实时回传数据的回调函数指针,当接收到128~255命令码时被调用 **/ REPLYPRO MCUReplyPro; STM32单片机API函数 在编写STM32程序时,同样应该包含和上位机定义一致的"mcuCmdInfo.h"文件。STM32使用API函数定义如下: /** * @brief USBD初始化及CDC类初始化 * @param None * @retval None **/ void USBCDC_Init(void);
/** * @brief 查检是否有上位机发来的命令 * @param pBuf:用于接收命令的数据缓存 * @param pBuf:用于接收命令的数据缓存大小 * @retval =0:未接收到命令 >0:接收到数据包的长度(字节数) **/ uint8_t CheckCommand(uint8_t *pBuf, uint32_t nBufSize);
/** * @brief 向上位机发送数据 * @param 要发送的数据缓存 * @param 要发送的数据字节数 * @retval 返回发送字节数 **/ uint8_t SendData(uint8_t *pBuf, uint32_t nSendBytes); STM32应用程序首先需要调用USBCDC_Init初始化USB接口,然后调用CheckCommand函数检查是否接收到上位机发来的命令,再根据命令码执行相应的操作,调用SendData函数发送应答数据或实时数据。 下面是WinCE系统中实现读取ETA321版本信息和实时波形数据采样的示例程序: #include "stdafx.h" #include "mcu_class.h" // API接口函数定义 #include "mcuCmdInfo.h" // 命令码和数据包定义 #pragma comment(lib, "mcu_class.lib") // 包含库文件
// 声明实时数据处理回调函数 static void CALLBACK MCUReplyPro(BYTE *buf, DWORD buflen);
int _tmain(int argc, _TCHAR* argv[]) { MCU_CLASS mcu; BYTE Buf[MAX_BUF_SIZE]; TCHAR csBuf[MAX_BUF_SIZE]; DWORD dwSize, dwCnt = 0; MCU_VER_INFO getVerInfo; MCU_ADC adc; size_t RetrunSize;
// 打开MCU设备 if(!mcu.OpenMCU()) { return -1; }
// 指定MCU实时数据处理回调函数 mcu.MCUReplyPro = MCUReplyPro;
// 调用SenCmd函数之前必须初始化的个变量 getVerInfo.ucSize = sizeof(MCU_VER_INFO); // 发送的命令结构体大小(字节数) getVerInfo.ucCmd = MCU_GENERIC_VER_INFO; // 命令代码:获取MCU版本信息 dwSize = sizeof(Buf); // 用于接收MCU数据的缓存大小 if(mcu.SendCmd((BYTE *)(&getVerInfo), (BYTE *)&getVerInfo, dwSize)) { // 窄字符转宽字符 mbstowcs_s(&RetrunSize, csBuf, _countof(csBuf), getVerInfo.ucName, _TRUNCATE); OutputMessage(TEXT("mcu-ver %x-%x '%s'rn"), getVerInfo.wMajor,getVerInfo.wMinor,csBuf); } else { OutputMessage(TEXT("send command:%d failed!!!rn"), getVerInfo.ucCmd); }
// 调用SenCmd函数之前必须初始化的变量 adc.ucSize = sizeof(MCU_ADC); // 发送的命令结构体大小(字节数) adc.ucCmd = MCU_GENERIC_ADC; // 命令代码:获取MCU版本信息 adc.ucCH = 0; // 设备ADC通道 adc.dwSamplingRate = 10000; // 设置ADC采样率KHz if(!mcu.SendCmd((BYTE *)(&adc), NULL)) { OutputMessage(TEXT("send command:%d failed!!!rn"), adc.ucCmd); }
while(1) { Sleep(1000); if(dwCnt > 10) // 10S后退出 break; }
adc.dwSamplingRate = 0; // 停止ADC采集 if(!mcu.SendCmd((BYTE *)(&adc), NULL)) { OutputMessage(TEXT("send command:%d failed!!!rn"), adc.ucCmd); }
Sleep(1000); // 关闭MCU设备,释放相关资源 mcu.CloseMCU(); return 0; }
// 实时数据处理回调函数 void CALLBACK MCUReplyPro(BYTE *buf, DWORD buflen) { PMCU_ADC_DATA pADCData; static DWORD cnt = 0;
pADCData = (PMCU_ADC_DATA)buf; cnt += pADCData->ucSize;
// 处理实时数据......
} |
|
相关推荐 |
|
只有小组成员才能发言,加入小组>>
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-11-27 07:49 , Processed in 0.718899 second(s), Total 37, Slave 28 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号