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 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'\r\n), getverinfo.wmajor,getverinfo.wminor,csbuf);
}
else {
outputmessage(text(send command:%d failed!!!\r\n), 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!!!\r\n), 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!!!\r\n), 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;
// 处理实时数据......
}
TC-08温度数据记录仪的特性及应用优势
信号调制的工作原理
Docker和容器技术为什么会这么火爆
我们该如何有效预防电气火灾的产生
DS3231+TM1650制作4位0.56寸数码管迷你时钟
英创信息技术WinCE主板与STM32多功能模块通讯介绍
美国国税局是如何对虚拟货币进行定义的
苹果将在今年上半年推出第二代AirPods Pro
Weex如何支撑200w+同时在线的优酷猫晚直播?
ST-Link也能当J-Link使用?
基于移动物联网和433Mhz电力行业无线测温解决方案
英飞凌推出全新LED驱动器ICL8201 助力中国照明能效升级
ADI单导联心率监护仪模拟前端,助中卫莱康“心搏士”再上新台阶
如何在区块链上进行安全的数据运行计算
看Qorvo如何“料理”射频上的汽车?
三星将提前推出打压iPhone 12的势头的新一代Galaxy S旗舰手机
魅族16T搭载骁龙855移动平台和LPDDR4X内存,购买享3期免息
电动汽车需求增加,特斯拉的V3超充站技术能否普及
Allegro推出ATS19580节能解决方案简化客户速度传感器的集成
无人驾驶公交车来了 百度Apollo联合金龙推首款L4级自动驾驶中巴