文章目录
前言
最终目的:是将磁力计 和六轴 的数据通过 USB 虚拟串口 输出至上位机。
需要进行 串口 USB虚拟串口发送数据实验代码的学习与扩展。
一、F4 第三十五章 USB 虚拟串口(Slave)实验
USB是指电脑上这种 通用串行总线,是一种协议。R232全双工串口 R485 半双工串口,是指按bit发送数据的一种设备。
USB 虚拟串口,简称 VCP,是 Virtual COM Port 的简写,它是利用 USB 的 CDC 类来实现的一种通信接口。
二、MiniFLy
usblinkInit(); 在这里面定义了两个队列 一个128长度 每个为 u8 的usbDataDelivery 30个32字节的txQueue
1.usblinkRxTask //接受的是上位机的数据
bool usbGetDataWithTimout(uint8_t *c)
{
if (xQueueReceive(usbDataDelivery, c, 1000) == pdTRUE) //队列句柄 缓冲区 1000是时间
{
return true;
}
*c = 0;
return false;
}
while(1)
{
if (uartslkGetDataWithTimout(&c))
{
switch(rxState)
{
case waitForStartByte1:
rxState = (c == DOWN_BYTE1) ? waitForStartByte2 : waitForStartByte1;
cksum = c;
break;
case waitForStartByte2:
rxState = (c == DOWN_BYTE2) ? waitForMsgID : waitForStartByte1;
cksum += c;
break;
case waitForMsgID:
rxPacket.msgID = c;
rxState = waitForDataLength;
cksum += c;
break;
case waitForDataLength:
if (c <= ATKP_MAX_DATA_SIZE)
{
rxPacket.dataLen = c;
dataIndex = 0;
rxState = (c > 0) ? waitForData : waitForChksum1; /*c=0,Êý¾Ý³¤¶ÈΪ0£¬Ð£Ñé1*/
cksum += c;
} else
{
rxState = waitForStartByte1;
}
break;
case waitForData:
rxPacket.data[dataIndex] = c;
dataIndex++;
cksum += c;
if (dataIndex == rxPacket.dataLen)
{
rxState = waitForChksum1;
}
break;
case waitForChksum1:
if (cksum == c) /*ËùÓÐУÑéÕýÈ·*/
{
atkpPacketDispatch(&rxPacket);
}
else /*УÑé´íÎó*/
{
rxState = waitForStartByte1;
IF_DEBUG_ASSERT(1);
}
rxState = waitForStartByte1;
break;
default:
ASSERT(0);
break;
}
}
else /*³¬Ê±´¦Àí*/
{
rxState = waitForStartByte1;
}
}
每次读取一个 u8 数据 最终集成 上下行 ID 数据 校验 的数据格式。
2.usblinkTxTask //usb发送atkpTxTask的数据 这个任务是获取传感器 姿态 PWM等输出数据
while(1)
{
xQueueReceive(txQueue, &p, portMAX_DELAY);
sendBuffer[0] = UP_BYTE1;
sendBuffer[1] = UP_BYTE2;
sendBuffer[2] = p.msgID;
sendBuffer[3] = p.dataLen;
memcpy(&sendBuffer[4], p.data, p.dataLen);
cksum = 0;
for (int i = 0; i < p.dataLen+4; i++)
{
cksum += sendBuffer[i];
}
dataLen = p.dataLen + 5;
sendBuffer[dataLen - 1] = cksum;
usbsendData(sendBuffer, dataLen);
ledseqRun(DATA_TX_LED, seq_linkup);
}
发送 txQueue队列的数据。
3.atkpTxTask()
读取传感器数据 发送至 txQueue队列
4.对MPU支持另外的IIC接口的理解
IIC设备在硬件上可以直接并联 根据协议匹配地址
例:六轴IIC直接并联磁力计IIC 气压计IIC
根据通讯协议 选定IICx PB6 PB7 发送电平变化 发送不同的 IIC外设的地址 然后进行读写 数据。
/*
0 1 2号从机 读取了三个寄存器的地址(是因为采用的硬件IIC吗 不然多个设备只需要用一个IIC接口)
或者就是为了使用方便 每个寄存器地址直接定义一个IIC 或许跟HAL库有关
软件模拟IIC:
使能一个IIC结构体 定义了引脚 和 IIC配置
IIC结构引脚先发送了开始信号 发送一个设备地址(相当于匹配) 发送了设备地址内部的存储器地址(已经相当于数据) 发送了数据 发送了停止信号
*/
#ifdef SENSORS_ENABLE_MAG_AK8963
if (isMagPresent)
{
// 设置MPU6500主机要读取的寄存器
mpu6500SetSlaveAddress(0, 0x80 | AK8963_ADDRESS_00); // 设置磁力计为0号从机
mpu6500SetSlaveRegister(0, AK8963_RA_ST1); //从机0需要读取的寄存器
mpu6500SetSlaveDataLength(0, SENSORS_MAG_BUFF_LEN); //读取8个字节
mpu6500SetSlaveDelayEnabled(0, true);
mpu6500SetSlaveEnabled(0, true);
}
#endif
if (isBaroPresent && baroType == BMP280)
{
mpu6500SetSlaveAddress(1, 0x80 | BMP280_I2C_ADDR); // 设置气压计状态寄存器为1号从机,其实就是MPU6500第二个IIC设备的地址
mpu6500SetSlaveRegister(1, BMP280_STAT_REG); // 从机1需要读取的寄存器,这是气压计的地址
mpu6500SetSlaveDataLength(1, SENSORS_BARO_STATUS_LEN); // 1个字节
mpu6500SetSlaveDelayEnabled(1, true);
mpu6500SetSlaveEnabled(1, true);
mpu6500SetSlaveAddress(2, 0x80 | BMP280_I2C_ADDR); // 2号从机
mpu6500SetSlaveRegister(2, BMP280_PRESSURE_MSB_REG); // 寄存器
mpu6500SetSlaveDataLength(2, SENSORS_BARO_DATA_LEN); // 6个字节
mpu6500SetSlaveDelayEnabled(2, true);
mpu6500SetSlaveEnabled(2, true);
}
总结
最后是在传感器任务里面 取消了 三处if 的注释 isMag 为 true 以及初始化 后就能使用了
提示:这里对文章进行总结:
例如:以上就是今天要讲的内容,本文仅仅简单介绍了pandas的使用,而pandas提供了大量能使我们快速便捷地处理数据的函数和方法。