分类 Code 下的文章

最近想在 f429 上面使用 mdk526 版本的 IDE,配合 HAL 和ucosiii。考虑到的方法是对比 v7 开发板的 ucosiii 和裸机程序,找出需要修改的地方,然后对比 v6 开发板的 ucosiii 和 裸机程序,然后把相应的修改融合起来即可。

- 阅读剩余部分 -

在 qt 中想要把 qvector 转化为原始数据构成的数组,有几种方法:

  1. 直接使用循环读取
double *bytes = new double[vec.size()];
for (int i = 0; i < vec.size(); ++i) {
   bytes[i] = vec[i];
}
QByteArray array = QByteArray::fromRawData(reinterpret_cast<void*>(bytes));
delete []bytes;
  1. 使用 qvector 自带的 constData 和 data

    QByteArray data = QByteArray::fromRawData(
        reinterpret_cast<const char*>(vec.constData()),
        sizeof(double) * vec.size()
    );
  2. 使用 stream 来输出
    QVector<double> vec;
    QByteArray data;
    QDataStream stream(&data, QIODevice::WriteOnly);
    for (auto x : vec)
    stream << x;

或者

QVector<double> vec;
// populate vector
QByteArray data;
QDataStream stream(&data, QIODevice::WriteOnly);
stream << vec;

调试 mcu 的时候,使用 jlink 的 rtt 可以方便的输出信息。

输出有两种模式, client 和 logger。 client 必须依附其他程序,比如说 mdk 调试状态,或者 logger 程序。

logger 可以不依附其他程序,但是 rtt 默认的代码只支持 client 的通道 0,想要使用 logger,需要修改代码,具体如下:

static SEGGER_RTT_CB _SEGGER_RTT = {
  "SEGGER RTT",
  SEGGER_RTT_MAX_NUM_UP_BUFFERS,
  SEGGER_RTT_MAX_NUM_DOWN_BUFFERS,
  {{ "Terminal",         &_acUpBuffer[0],           BUFFER_SIZE_UP,   0, 0, SEGGER_RTT_MODE_NO_BLOCK_SKIP },
   { "Log",                 &_acUpBuffer1[0],          BUFFER_SIZE_UP,   0, 0, SEGGER_RTT_MODE_NO_BLOCK_SKIP }},
  {{ "Terminal",         &_acDownBuffer[0],         BUFFER_SIZE_DOWN, 0, 0, SEGGER_RTT_MODE_NO_BLOCK_SKIP },
   { "Log",                 &_acDownBuffer1[0],  BUFFER_SIZE_DOWN, 0, 0, SEGGER_RTT_MODE_NO_BLOCK_SKIP }},
};

这段代码是给予 4.90e 的 rtt 代码,增加了一个通道,在调用 rtt 的时候,通道写 1 即可通过 logger 来输出了。

qt 中直接使用 c 语言文件,c 文件可以直接包含,h 文件包含的时候,需要在 c++ 中添加额外信息,如下:


#ifdef __cplusplus
extern "C" {

#include "c头文件.h"

#endif
#ifdef __cplusplus
}
#endif

1. 概念:

坐标轴-QAbstractAxis:

图表中,一般都有 X、Y 坐标轴,复杂一些的还带有 Z 轴。对应到 Qt 的图表也有 X、Y 轴对象。但是今天,我们先不展开介绍。如果我们不创建轴坐标对应的对象,可以使用 Qt 的默认轴对象。后面我们会介绍用法。

系列-QAbstractSeries:

不论是曲线、饼图、棒图还是其他图表,其中展示的内容本质都是数据。一条曲线是一组数据,一个饼图也对应一组数据。在 Qt Charts 中,这些一组组的数据被称作系列。对应不同类型的图表 Qt 提供了不同的系列。系列除了负责存储、访问数据,应该还提供了数据的绘制方法,比如折线图和曲线图分别对应 QLineSerie 和 QSPLineSerie。我们可以用不同的系列达到不同的展示目的。

图例-Legend:

类似于 Excel,Qt Charts 中也提供了图例,并且还可以显示或者隐藏图例。

图表-QChart:

Qt 提供了 QChart 类来封装前面所说的内容,比如坐标轴、系列、图例等。QChart 承担了一个组织、管理的角色。QChart 派生自 QGraphicsObject,因此它实际上是一个图元 item。我们可以从 QChart 获取到坐标轴对象、数据系列对象、图例等等,并且可以设置图表的主题、背景色等样式信息。

视图-QChartView:

负责 QChart 的展示。QChart 本身只负责图表内容的组织、管理。图表的展示由视图负责,这个视图就是 QChartView。QChartView 派生自 QGraphicsView,只是它专门提供了几个面向 QChart 的接口,比如 setChart(QChart*)等。

2. 使用

要使用QtCharts 需要几个步骤:

1. pro 文件中 修改

QT       += charts

2. 把 chart 相关的头文件放在 ui 相关的头文件上面,否则会导致 编译错误,找不到 chartView 相关。

#include <QtCharts/QChartView>
#include <QtCharts/QLineSeries>
QT_CHARTS_USE_NAMESPACE

3. 在 ui 中放入 widget,然后右键 widget,选择 promote to 选项,选项卡里面:

base class name: QWidget promoted class name: QChartView Header file: QChartView

4. 注意 setChart 之后需要把 旧的给删除掉。否则内存占用越来越多。

    QChart *oldChart = ui->widget->chart();
    QChart *chart = new QChart();
    ui->widget->setChart(chart);

    if (oldChart != nullptr) {
        delete  oldChart;
    }

参考: https://www.cnblogs.com/ybqjymy/p/13253152.html https://www.cnblogs.com/linuxAndMcu/p/11381839.html

3. charts 如果需要图像进行滚动显示,那么可以参考自带的例程 dynamicspline;如果需要再图像上显示具体的 坐标,可以参考自带例程 callout.

参考: https://www.cnblogs.com/shenLong1356/p/11230390.html

4. charts 里面使用 chart.scroll(x, 0); 这个 x 注意不是 chart.plotArea().width() / m_axis.tickCount(); 而应该是 m_chart->plotArea().width() / (X_RANGE_MAX - X_RANGE_MIN); 是和 setRange 这个设置相对应,而不是和 setTickCount 这个设置的值相对应。

1. 首先把 release 版本的 exe 复制到其他文件夹,比如 Desktop\test

2. 使用开始菜单中 qt 里面的控制台窗口,使用 cd 命令打开到 Desktop\test 位置,然后使用打包命令:

windeployqt test.exe

然后 qt 会自动把依赖复制到 Desktop\test 文件夹里面。

3. 安装 enigma virtual box.

4. 使用 enigma virtual box.

  1. enter input file name 后面的 browse 里面选择,Desktop\test 中的 test.exe 文件。
  2. 左下角 files 里面的 add 中选择 add folder recursive 里面选择 Desktop\test 文件夹。
  3. 点击右下角 process 进行封包。

1. qt 中两个字符的字符串直接转换为 hex,类似于 ”1A" 要转换成 16进制的 0x1A,使用 int QString::toInt(bool *ok, int base)。具体如下:

QString  str = "0x1A";
int value = str.toInt(nullptr, 16);
uint8_t tmp = static_cast<uint8_t>(str.toUInt(nullptr, 16));

2. 如果是字符串本身转换为16进制,类似于 "1" 要转换成 0x31,使用 QByteArray,其中有方法 toLatin1、toLocal8Bit, Latin1代表ASCII,Local8Bit代表unicode

QByteArray ar = str.toLatin1().toHex();

3. 如果是16进制转为 QByteArray,可以用 setNum 函数

QByteArray().setNum( hex )

软件模拟 spi 时序有以下几个点需要注意:

  1. cs 使能后到第一个 sck 边沿需要延时。
  2. 最后一个sck 边沿到下一个 cs 需要延时。
  3. sck 的高电平和低电平本身需要维持时间。
  4. mosi 需要先把数据放上去,然后启动上升沿,然后延时 sck 高电平的时间。
  5. 在延时了 sck 高电平的时间后,读取 miso 的电平,然后启动下降沿,然后延时 sck 低电平的时间。