0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看威廉希尔官方网站 视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

QT编写一个JLINK烧录工具

Rice嵌入式开发威廉希尔官方网站 分享 来源:Rice 嵌入式开发威廉希尔官方网站 分享 作者:Rice 嵌入式开发技 2023-01-09 11:53 次阅读

概述

作者一直有一个想法,就是写一个功能强大的桌面小工具,里面集成各种平时开发要用的工具。例如:串口助手,网络助手,下载工具等。那么如何也带来几个问题:

问题1:那么如何呈现在桌面上也是一个非常重要的问题 -- 桌面悬浮窗。

问题2:工具的名字 -- RTOOL(米饭工具)

问题3:是否贡献整个工具 -- 分为两个版本:开源版本和公司项目版本(已经发布了V1.0版本)。

236e849e-8fd1-11ed-92c9-dac502259ad0.png

本篇文章介绍RTOOL的JLINK烧录小工具,那为什么要在RTOOL中集成JLINK的烧录工具呢?原因:

MCU,我们如果使用GCC构建我们的程序后,没有IDE的支撑,就需要使用JFLASH这样的工具进行烧录,这个操作流程还是挺多步骤的。

2385c492-8fd1-11ed-92c9-dac502259ad0.png

方便我们对固件进行动手术,如对固件进行加密处理,对芯片ram,flash进行随心所欲的操作。

原理说明

我们在使用JFlash烧录工具时,实际JFlash是通过调用JLinkARM.dll动态库提供的接口进行操作的。那么我们可以通过Dependency walker对JLinkARM.dll进行分析。获取到dll库中所有函数符号。

23930238-8fd1-11ed-92c9-dac502259ad0.png

QT提供了QLibrary类可以动态加载dll,所以结合获取的函数符号,我们可以定义一些列函数指针指向对应的符号。

239f7d6a-8fd1-11ed-92c9-dac502259ad0.png

开发流程

UI设计,实际可以很简单,目的也是简化JFlash的操作流程:

2482e8c0-8fd1-11ed-92c9-dac502259ad0.png

定义对接动态库JLinkARM.dll的一系列函数指针,头文件RJlinkARM.h:

#ifndefRJLINKARMH
#defineRJLINKARMH

//JLINKTIF
#defineJLINKARM_TIF_JTAG0
#defineJLINKARM_TIF_SWD1
#defineJLINKARM_TIF_DBM32
#defineJLINKARM_TIF_FINE3
#defineJLINKARM_TIF_2wire_JTAG_PIC324

//RESETTYPE
#defineJLINKARM_RESET_TYPE_NORMAL0
#defineJLINKARM_RESET_TYPE_CORE1
#defineJLINKARM_RESET_TYPE_PIN2

typedefbool(*rjlinkOpenFunc)(void);
typedefvoid(*rjlinkCloseFunc)(void);
typedefbool(*rjlinkIsOpenFunc)(void);
typedefunsignedint(*rjlinkTIFSelectFunc)(int);
typedefvoid(*rjlinkSetSpeedFunc)(int);
typedefunsignedint(*rjlinkGetSpeedFunc)(void);
typedefvoid(*rjlinkResetFunc)(void);
typedefint(*rjlinkHaltFunc)(void);
typedefvoid(*rjlinkGoFunc)(void);

typedefint(*rjlinkReadMemFunc)(unsignedintaddr,intlen,void*buf);
typedefint(*rjlinkWriteMemFunc)(unsignedintaddr,intlen,void*buf);
typedefint(*rjlinkWriteU8Func)(unsignedintaddr,unsignedchardata);
typedefint(*rjlinkWriteU16Func)(unsignedintaddr,unsignedshortdata);
typedefint(*rjlinkWriteU32Func)(unsignedintaddr,unsignedintdata);

typedefint(*rjlinkEraseChipFunc)(void);
typedefint(*rjlinkDownloadFileFunc)(constchar*file,unsignedintaddr);
typedefvoid(*rjlinkBeginDownloadFunc)(intindex);
typedefvoid(*rjlinkEndDownloadFunc)(void);
typedefbool(*rjlinkExecCommandFunc)(constchar*cmd,inta,intb);

typedefunsignedint(*rjlinkReadRegFunc)(intindex);
typedefint(*rjlinkWriteRegFunc)(intindex,unsignedintdata);

typedefvoid(*rjlinkSetLogFileFunc)(char*file);
typedefunsignedint(*rjlinkGetDLLVersionFunc)(void);
typedefunsignedint(*rjlinkGetHardwareVersionFunc)(void);
typedefunsignedint(*rjlinkGetFirmwareStringFunc)(char*buff,intcount);
typedefunsignedint(*rjlinkGetSNFunc)(void);
typedefunsignedint(*rjlinkGetIdFunc)(void);
typedefbool(*rjlinkConnectFunc)(void);
typedefbool(*rjlinkIsConnectedFunc)(void);

#endif//RJLINKARMH

通过QT提供了QLibrary类加载dll,然后函数指针指向对应的函数符号:

通过头文件RJlinkARM.h定义的函数指针类型定义对应的变量:

private:
rjlinkOpenFuncrjlinkOpenFuncPtr=NULL;
rjlinkCloseFuncrjlinkCloseFuncPtr=NULL;
rjlinkIsOpenFuncrjlinkIsOpenFuncPtr=NULL;
rjlinkTIFSelectFuncrjlinkTIFSelectFuncPtr=NULL;
rjlinkSetSpeedFuncrjlinkSetSpeedFuncPtr=NULL;
rjlinkGetSpeedFuncrjlinkGetSpeedFuncPtr=NULL;
rjlinkResetFuncrjlinkResetFuncPtr=NULL;
rjlinkHaltFuncrjlinkHaltFuncPtr=NULL;
rjlinkGoFuncrjlinkGoFuncPtr=NULL;
rjlinkReadMemFuncrjlinkReadMemFuncPtr=NULL;
rjlinkWriteMemFuncrjlinkWriteMemFuncPtr=NULL;
rjlinkWriteU8FuncrjlinkWriteU8FuncPtr=NULL;
rjlinkWriteU16FuncrjlinkWriteU16FuncPtr=NULL;
rjlinkWriteU32FuncrjlinkWriteU32FuncPtr=NULL;
rjlinkEraseChipFuncrjlinkEraseChipFuncPtr=NULL;
rjlinkDownloadFileFuncrjlinkDownloadFileFuncPtr=NULL;
rjlinkBeginDownloadFuncrjlinkBeginDownloadFuncPtr=NULL;
rjlinkEndDownloadFuncrjlinkEndDownloadFuncPtr=NULL;
rjlinkExecCommandFuncrjlinkExecCommandFuncPtr=NULL;
rjlinkReadRegFuncrjlinkReadRegFuncPtr=NULL;
rjlinkWriteRegFuncrjlinkWriteRegFuncPtr=NULL;
rjlinkSetLogFileFuncrjlinkSetLogFileFuncPtr=NULL;
rjlinkGetDLLVersionFuncrjlinkGetDLLVersionFuncPtr=NULL;
rjlinkGetHardwareVersionFuncrjlinkGetHardwareVersionFuncPtr=NULL;
rjlinkGetFirmwareStringFuncrjlinkGetFirmwareStringFuncPtr=NULL;
rjlinkGetSNFuncrjlinkGetSNFuncPtr=NULL;
rjlinkGetIdFuncrjlinkGetIdFuncPtr=NULL;
rjlinkConnectFuncrjlinkConnectFuncPtr=NULL;
rjlinkIsConnectedFuncrjlinkIsConnectedFuncPtr=NULL;

通过动态库(JLinkARM.dll)获取对应的函数指针

voidRJLinkView::jlinkLibLoadHandle(void)
{
jlinkLib=newQLibrary("JLinkARM.dll");
if(jlinkLib->load())
{
rjlinkOpenFuncPtr=(rjlinkOpenFunc)jlinkLib->resolve("JLINKARM_Open");//打开设备
rjlinkCloseFuncPtr=(rjlinkCloseFunc)jlinkLib->resolve("JLINKARM_Close");//关闭设备
rjlinkIsOpenFuncPtr=(rjlinkIsOpenFunc)jlinkLib->resolve("JLINKARM_IsOpen");//判断设备是否打开
rjlinkTIFSelectFuncPtr=(rjlinkTIFSelectFunc)jlinkLib->resolve("JLINKARM_TIF_Select");//选择设备
rjlinkSetSpeedFuncPtr=(rjlinkSetSpeedFunc)jlinkLib->resolve("JLINKARM_SetSpeed");//设置烧录速度
rjlinkGetSpeedFuncPtr=(rjlinkGetSpeedFunc)jlinkLib->resolve("JLINKARM_GetSpeed");//获取烧录速度
rjlinkResetFuncPtr=(rjlinkResetFunc)jlinkLib->resolve("JLINKARM_Reset");//复位设备
rjlinkHaltFuncPtr=(rjlinkHaltFunc)jlinkLib->resolve("JLINKARM_Halt");//中断程序执行
rjlinkReadMemFuncPtr=(rjlinkReadMemFunc)jlinkLib->resolve("JLINKARM_ReadMem");//读取内存
rjlinkWriteMemFuncPtr=(rjlinkWriteMemFunc)jlinkLib->resolve("JLINKARM_WriteMem");//写入内存
rjlinkEraseChipFuncPtr=(rjlinkEraseChipFunc)jlinkLib->resolve("JLINK_EraseChip");//擦除芯片
rjlinkExecCommandFuncPtr=(rjlinkExecCommandFunc)jlinkLib->resolve("JLINKARM_ExecCommand");//执行命令
rjlinkGetDLLVersionFuncPtr=(rjlinkGetDLLVersionFunc)jlinkLib->resolve("JLINKARM_GetDLLVersion");//获取DLL版本号
rjlinkGetSNFuncPtr=(rjlinkGetSNFunc)jlinkLib->resolve("JLINKARM_GetSN");//获取sn号
rjlinkGetIdFuncPtr=(rjlinkGetIdFunc)jlinkLib->resolve("JLINKARM_GetId");//获取ID
rjlinkConnectFuncPtr=(rjlinkConnectFunc)jlinkLib->resolve("JLINKARM_Connect");//连接设备
rjlinkIsConnectedFuncPtr=(rjlinkIsConnectedFunc)jlinkLib->resolve("JLINKARM_IsConnected");//判断是否连接设备
}
}

上述的函数指针,其实对访问操作一点也不友好,所以通过类方法重新对其封装,也避免的空指针的访问:

boolRJLinkView::jlinkOpen(void)
{
if(rjlinkOpenFuncPtr){
returnrjlinkOpenFuncPtr();
}
returnfalse;
}
voidRJLinkView::jlinkClose(void)
{
if(rjlinkCloseFuncPtr){
rjlinkCloseFuncPtr();
}
}
boolRJLinkView::jlinkIsOpen(void)
{
if(rjlinkIsOpenFuncPtr){
returnrjlinkIsOpenFuncPtr();
}
returnfalse;
}
unsignedintRJLinkView::jlinkTIFSelectFunc(inttype)
{
if(rjlinkTIFSelectFuncPtr){
returnrjlinkTIFSelectFuncPtr(type);
}
returnfalse;
}
voidRJLinkView::jlinkSetSpeedFunc(unsignedintspeed)
{
if(rjlinkSetSpeedFuncPtr){
rjlinkSetSpeedFuncPtr(speed);
}
}
unsignedintRJLinkView::jlinkGetSpeedFunc(void)
{
if(rjlinkGetSpeedFuncPtr){
returnrjlinkGetSpeedFuncPtr();
}
return0;
}
voidRJLinkView::jlinkResetFunc(void)
{
if(rjlinkResetFuncPtr){
rjlinkResetFuncPtr();
}
}
intRJLinkView::jlinkHaltFunc(void)
{
if(rjlinkHaltFuncPtr){
returnrjlinkHaltFuncPtr();
}
return0;
}
intRJLinkView::jlinkReadMemFunc(unsignedintaddr,intlen,void*buf)
{
if(rjlinkReadMemFuncPtr){
returnrjlinkReadMemFuncPtr(addr,len,buf);
}
return0;
}
intRJLinkView::jlinkWriteMemFunc(unsignedintaddr,intlen,void*buf)
{
if(rjlinkWriteMemFuncPtr){
returnrjlinkWriteMemFuncPtr(addr,len,buf);
}
return0;
}
intRJLinkView::jlinkEraseChipFunc(void)
{
if(rjlinkEraseChipFuncPtr){
returnrjlinkEraseChipFuncPtr();
}
return0;
}
boolRJLinkView::jlinkExecCommandFunc(constchar*cmd,inta,intb)
{
if(rjlinkExecCommandFuncPtr){
returnrjlinkExecCommandFuncPtr(cmd,a,b);
}
returnfalse;
}
unsignedintRJLinkView::jlinkGetDLLVersionFunc(void)
{
if(rjlinkGetDLLVersionFuncPtr){
returnrjlinkGetDLLVersionFuncPtr();
}
return0;
}
unsignedintRJLinkView::jlinkGetSNFunc(void)
{
if(rjlinkGetSNFuncPtr){
returnrjlinkGetSNFuncPtr();
}
return0;
}
unsignedintRJLinkView::jlinkGetIdFunc(void)
{
if(rjlinkGetIdFuncPtr){
returnrjlinkGetIdFuncPtr();
}
return0;
}
boolRJLinkView::jlinkConnectFunc(void)
{
if(rjlinkConnectFuncPtr){
returnrjlinkConnectFuncPtr();
}
returnfalse;
}
boolRJLinkView::jlinkIsConnectedFunc(void)
{
if(rjlinkIsConnectedFuncPtr){
returnrjlinkIsConnectedFuncPtr();
}
returnfalse;
}

下载信息窗体的显示格式设置,为了方便预览我们的操作步骤,所以规定一个显示格式,增加时间戳的显示:

voidRJLinkView::infoShowHandle(QStringinfo)
{
QStringtimestamp=QDateTime::currentDateTime().toString("[hhss.zzz]==>");
ui->burnInfoTextBrowser->append(timestamp+info);
}

连接芯片设备,以下是按照STM32F407IG为例,下载方式采用SWD,下载速度未4000kHz:

boolRJLinkView::jlinkConnectHandle(void)
{
if(jlinkIsOpen())
{
infoShowHandle(tr("设备连接成功"));
returntrue;
}
jlinkOpen();
if(jlinkIsOpen())
{
jlinkExecCommandFunc("device=STM32F407IG",0,0);
jlinkTIFSelectFunc(JLINKARM_TIF_SWD);
jlinkSetSpeedFunc(4000);
jlinkConnectFunc();
if(jlinkIsConnectedFunc()){
infoShowHandle(tr("设备连接成功"));
returntrue;
}else
{
infoShowHandle(tr("连接设备失败!请检查设备连接..."));
}
}
else
{
infoShowHandle(tr("连接设备失败!请检查烧录器连接..."));
}
returnfalse;
}

断开芯片设备:

voidRJLinkView::jlinkdisconnectHandle(void)
{
jlinkClose();
if(!jlinkIsOpen())
{
infoShowHandle(tr("断开设备成功!"));
}
else{
infoShowHandle(tr("断开设备失败..."));
}
}

获取CPU ID,原理其实很简单,通过读取对应UUID寄存器,就可以获取过去到芯片的UUID

QStringRJLinkView::jlinkGetCpuIdHandle(void)
{
unsignedcharcpuId[12]={0};
charcpuIdTemp[128]={0};
jlinkReadMemFunc(0x1FFF7A10,12,cpuId);
sprintf(cpuIdTemp,"%02X%02X%02X%02X-%02X%02X%02X%02X-%02X%02X%02X%02X",
cpuId[3],cpuId[2],cpuId[1],cpuId[0],
cpuId[7],cpuId[6],cpuId[5],cpuId[4],
cpuId[11],cpuId[10],cpuId[9],cpuId[8]);
returnQString(cpuIdTemp);
}

选择固件按钮实现,这里指定了文件后缀为.bin格式:

voidRJLinkView::on_fwFilePathSelectPushButton_clicked()
{
QStringfwFileName=QFileDialog::getOpenFileName(this,"Firmwarefile",QCoreApplication::applicationDirPath(),"fwfile(*.bin)");
ui->fwFilePathLineEdit->setText(fwFileName);
}

清除信息显示窗体按钮实现:

voidRJLinkView::on_cleanInfoPushButton_clicked()
{
ui->burnInfoTextBrowser->clear();
}

获取芯片ID按钮实现,需要先连接上设备,然后调用jlinkGetCpuIdHandle方案获取ID之后,断开连接:

voidRJLinkView::on_getCpuIdPushButton_clicked()
{
if(jlinkConnectHandle())
{
infoShowHandle(tr("获取CPUID中,请稍后..."));
infoShowHandle(tr("获取CPUID成功:")+jlinkGetCpuIdHandle());
jlinkdisconnectHandle();
}
}

同理,擦除flash也是要先连接上设备,然后通过调用jlinkEraseChipFunc方法进行擦除之后,断开连接:

voidRJLinkView::on_clearFlashPushButton_clicked()
{
if(jlinkConnectHandle())
{
infoShowHandle(tr("擦除flash中,请稍后..."));
jlinkEraseChipFunc();
infoShowHandle(tr("擦除flash成功!"));
jlinkdisconnectHandle();
}
}

一键烧录按钮原理,获取固件内容存储到一个缓冲区中,然后启动一个定时器,然后将固件内容搬运到对应的Flash区域:

voidRJLinkView::on_burnPushButton_clicked()
{
boolburnAddrIsOk=false;
QFileburnFile;

burnFileSize=0;
burnFileContent.clear();

if(ui->fwFilePathLineEdit->text()==tr(""))
{
infoShowHandle(tr("请选择要烧录的固件!"));
return;
}

if(jlinkConnectHandle())
{
burnAddr=ui->burnAddrLineEdit->text().trimmed().toInt(&burnAddrIsOk,16);
if(!burnAddrIsOk)
{
infoShowHandle(tr("烧录起始地址格式有误,请正确输入地址..."));
jlinkdisconnectHandle();
return;
}
burnFile.setFileName(ui->fwFilePathLineEdit->text());
burnFile.open(QIODevice::ReadOnly);
if(burnFile.isOpen())
{
burnFileContent=burnFile.readAll();
burnFileSize=burnFileContent.size();
burnFile.close();

infoShowHandle(tr("开始烧录固件,请稍后..."));

burnFileTimer->start(RJLINK_BURN_TIME_INTERVAL);
}
else
{
infoShowHandle(tr("烧录固件打开失败,请检查文件是否存在..."));
jlinkdisconnectHandle();
}
}
}

定时器处理函数,每次烧录从缓冲区提取1k数据进行烧录:

voidRJLinkView::burnFileTimerHandle(void)
{
intburnPercent=0;
if(burnFileTimer)
{
burnFileTimer->stop();

if(burnFileContent.isEmpty())
{
ui->burnProgressBar->setValue(100);
jlinkdisconnectHandle();
infoShowHandle(tr("烧录完成!"));
return;
}
else
{
if(burnFileContent.size()>RJLINK_BURN_CONTENT_SIZE)//每次搬运1K数据
{
jlinkWriteMemFunc(burnAddr,RJLINK_BURN_CONTENT_SIZE,burnFileContent.data());
burnAddr+=RJLINK_BURN_CONTENT_SIZE;
burnFileContent.remove(0,RJLINK_BURN_CONTENT_SIZE);
}
else
{
jlinkWriteMemFunc(burnAddr,burnFileContent.size(),burnFileContent.data());
burnAddr+=burnFileContent.size();
burnFileContent.clear();
}

burnPercent=(burnFileSize-burnFileContent.size())*100/burnFileSize;
ui->burnProgressBar->setValue(burnPercent);
burnFileTimer->start(RJLINK_BURN_TIME_INTERVAL);
}
}
}

演示实例

获取CPU ID演示,点击"获取CPU ID"按钮,在显示窗体便可以看到对应的ID:

2491f798-8fd1-11ed-92c9-dac502259ad0.png

擦除flash演示,点击"擦除flash"按钮,会调用SEGGER应用,然后进行flash擦除:

24a6ad50-8fd1-11ed-92c9-dac502259ad0.png

烧录程序,点击"一键烧录"按钮,同样会调用SEGGER应用,然后进行烧录:

24b1697a-8fd1-11ed-92c9-dac502259ad0.png24bb2ff0-8fd1-11ed-92c9-dac502259ad0.png

审核编辑hhy

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 芯片
    +关注

    关注

    456

    文章

    50919

    浏览量

    424582
  • Qt
    Qt
    +关注

    关注

    1

    文章

    306

    浏览量

    37958
  • 烧录
    +关注

    关注

    8

    文章

    261

    浏览量

    35625
收藏 人收藏

    评论

    相关推荐

    嵌入式Qt-动手编写并运行自己的第1ARM-Qt程序

    本篇详细介绍了如何自己编写Qt程序,如何通过交叉编译,最终放到开发板中执行的过程。
    的头像 发表于 06-02 09:06 8621次阅读
    嵌入式<b class='flag-5'>Qt</b>-动手<b class='flag-5'>编写</b>并运行自己的第1<b class='flag-5'>个</b>ARM-<b class='flag-5'>Qt</b>程序

    编写一个QT程序

    学习种编程语言或编程环境,通常会先编写“Hello World”程序。我们也用 Qt Creator
    发表于 11-21 10:41 1033次阅读

    MCU_JLINK的相关资料推荐

    MCU_JLINK批处理脚本烧录工具-JFlash关于JLINK升级烧录脚本指令指令解释合理的创建标题,有助于目录的生成如何改变文本的样式插
    发表于 01-26 06:43

    JLINK-V8固件及烧录指导教程

    J-link 是使用过程中,如果内部固件意外损坏或丢失,请参考下面操作步骤说明,重新烧录Jlink固件。
    发表于 01-08 16:20 24次下载

    qt编写的触摸小键盘

    使用qt5编写qt程序小键盘,对于qLineedit的重写
    发表于 03-03 15:06 7次下载

    Qt图形编程基础之使用Qt编写“Hello,World”程序实验

    分享到:标签:Qt图形编程 Linux 操作系统 12.3 实验内容使用Qt编写Hello,World程序 1.实验目的 通过编写
    发表于 10-18 14:44 1次下载
    <b class='flag-5'>Qt</b>图形编程基础之使用<b class='flag-5'>Qt</b><b class='flag-5'>编写</b>“Hello,World”程序实验

    stm32怎么烧录程序

    STM32烧录程序目前笔者知道的有三种:JLink ,Ulink和串口烧录,使用工具分别为:JLink,ULink以及USB转TTL线。
    的头像 发表于 11-16 16:09 8.2w次阅读

    使用Qt编写的串口调试工具的应用程序和源代码资料免费下载

    本文档的主要内容详细介绍的是使用qt编写的串口调试工具的应用程序和源代码资料免费下载。
    发表于 12-18 08:00 82次下载
    使用<b class='flag-5'>Qt</b><b class='flag-5'>编写</b>的串口调试<b class='flag-5'>工具</b>的应用程序和源代码资料免费下载

    QT 编写 STC系列MCU烧录软件

    由于产品上用到了STC的单片机,而需要自行写烧录软件,该软件可以实现STC系列MCU文件的烧录。本软件最终取自开源的库,因此感谢为开源无私奉献的人们!
    发表于 10-25 20:36 17次下载
    <b class='flag-5'>QT</b> <b class='flag-5'>编写</b> STC系列MCU<b class='flag-5'>烧录</b>软件

    jlink烧录软件_使用 MCU BootUtility 工具烧录I.MXRT

    使用MDK/MCUXpresso IDE/IAR工具编译生成烧录固件文件。使用MCU BootUtility来加载hex文件或者bin文件或者是.srec文件进行站式烧录。默认情况下
    发表于 10-28 20:36 10次下载
    <b class='flag-5'>jlink</b><b class='flag-5'>烧录</b>软件_使用 MCU BootUtility <b class='flag-5'>工具</b>来<b class='flag-5'>烧录</b>I.MXRT

    单片机程序生产烧录工具

    背景:有的公司在生产时做单片机软件烧录,工人不会操作JFlash,就自己写简单版本的生产用的软件烧录工具。环境:Visual Studi
    发表于 11-23 17:36 12次下载
    单片机程序生产<b class='flag-5'>烧录</b><b class='flag-5'>工具</b>

    使用MCUXpresso直接烧录hex文件

    这里介绍种使用不需要源代码烧录hex文件的方法。打开MCUXpresso软件,并新建工程(工程的芯片选型要和需要烧录的芯片型号
    发表于 12-07 12:51 8次下载
    使用MCUXpresso直接<b class='flag-5'>烧录</b>hex文件

    AN017 基于Jlink烧录文件到SPI Nor Flash的方法

    AN017 基于Jlink烧录文件到SPI Nor Flash的方法
    发表于 02-27 18:21 0次下载
    AN017 基于<b class='flag-5'>Jlink</b><b class='flag-5'>烧录</b>文件到SPI Nor Flash的方法

    手把手教你编写上位机

    本次来教大家编写基于QT的简单的上位机。 学习新的东西我们都从最基础地实例开始,比如学
    发表于 05-08 10:36 1次下载
    手把手教你<b class='flag-5'>编写</b><b class='flag-5'>一</b><b class='flag-5'>个</b>上位机

    QT|编写简单的上位机

    QT | 编写简单的上位机 时间 :2023-03-19文章目录QT | 编写
    发表于 05-08 10:12 3次下载
    <b class='flag-5'>QT</b>|<b class='flag-5'>编写</b><b class='flag-5'>一</b><b class='flag-5'>个</b>简单的上位机