1、stm32cubemx如何修改芯片型号
cd /cygdrive/d
vim stm32f103_xx.ioc
% s/STM32F103VETx/STM32F103ZET6/gc
然后重新双击:stm32f103_xx.ioc
这样改完后,会提示说,生成了工程了,但是有点问题。所以还是重新来吧,不要用这个方法了。
2、stm32CubeMX-->点击:GENERATE CODE-->出现错误:but mdk-arm V5project generation have a problem
解决:(1)卸载原来的stm32CubeMX
(2)卸载jdk
(3)打开:STM32CubeMX - STM32Cube initialization code generator - STMicroelectronics
选择5.6.0版本,就是:en.stm32cubemx_v5-6-0.zip
(4)解压en.stm32cubemx_v5-6-0.zip,然后安装
(5)双击STM32CubeMX,提示安装jre1.8.0_341,并打开网页。
新的STM32CubeMX版本会自动安装jdk。
(6)下载jre-8u341-windows-x64.exe,安装,然后设置环境变量(网上搜环境变量方法)
(7)关掉STM32CubeMX,然后重新打开。
3、出现这样的错误:../Drivers/STM32F1xx_HAL_Driver/Inc/stm32f1xx_hal_def.h(30): error: #5: cannot open source input file "stm32f1xx.h": No such file or directory
#include "stm32f1xx.h"
解决:方法一:设置按钮-->C/C++-->点击添加图标-->点击...-->选择Drivers\CMSIS\Device\ST\STM32F1xx\Include-->点击“选择文件夹”-->点击“OK”
方法二:打开stm32f103_xx.ioc,重新生成代码。
4、.\AppStm32f103.axf: Error: L6218E: Undefined symbol SNetInterface_InitPara (referred from netinterface.o).最怕就是遇到这种错误。如果是其他错误,那么双击错误,就能打开错误的地方。双击这种错误,什么都没有,而且在keil里面搜不到。
解决:(1)如果是函数,那么删除掉出除startup_stm32f103xe.s,xx.uvoptx,xx.uvprojx外的所有文件,然后重新打开xx.uvprojx,重新编译,那么就会出现不见的函数在哪里。
(2)如果是extern修饰的全部变量,那么只能打开文件一个一个找了,或者使用其他工具帮忙找了,例如:source insight,可以用在vim的软件ctags,cscope等。没有其他办法。
5、想把几个函数变成bin文件,而不是库文件,怎么办呢?
解决:研究了很久,没有找到办法,但是想到类似的办法。不知道有没有更好的办法。
方法一:
[1]打开MDK-ARM\AppStm32f103\AppStm32f103.map文件,找到这几行:
Memory Map of the image
Image Entry point : 0x08000131
Load Region LR_IROM1 (Base: 0x08000000, Size: 0x0000cf5c, Max: 0x0001a800, ABSOLUTE, COMPRESSED[0x0000cc88])
Execution Region ER_IROM1 (Base: 0x08000000, Size: 0x0000cbf8, Max: 0x0001a800, ABSOLUTE)
Base Addr Size Type Attr Idx E Section Name Object
0x08000000 0x00000130 Data RO 3190 RESET startup_stm32f103xe.o
在这里找到你要的那几个函数占用的空间;
这里可以回答这个问题:如何知道某个函数的地址和占用空间。上面就是解决办法。
[2]先看下面方法
********************************************************
attribute 属性
1,将函数加载到指定位置
示例将 main.c 中的 delay 函数指定到 0x08020000 地址,可以在 c 文件中函数的定义处指定 delay 函数。
void delay(void) __attribute__ ((section(".ARM.__at_0x08020000")));
2,将数组加载到指定位置
int Temp[] __attribute__ ((section(".ARM.__at_0x08020000"))) = {0x1, 0x2};
3,将变量加载到指定位置
示例可以直接将 c 代码修改如下:
const int Temp __attribute__ ((section(".ARM.__at_0x08020000"))) = 10; // RO
int Temp __attribute__ ((section(".ARM.__at_0x20000000"))) = 10; // RW
********************************************************
设置这几个函数的地址,函数地址的差刚好等于函数的大小;
[3]编译工程,然后使用j-link或st-link读取这个范围的代码,生成一个文件,这个文件就相当于库了。(网上搜用j-link或st-link读写代码的方法,下同)
方法二:
[1]把几个函数都放在一个文件里面;
[2]先看下面方法
*******************************************************************
修改.sct 文件,将目标文件加载到指定位置,在 Keil 中使用修改.sct 文件进行分散加载需要对工程配置进行如下修改,修改.sct 方法的详细使用请参考.sct 的语法规则。
(1)-->打开keil-->点击第3行第7个按钮-->打开Options for Target 'AppStm32f103'对话框-->点击Linker-->(取消)Use Memory Layout from Target Dialog-->马上在Scatter File里面出现:.\AppStm32f103\AppStm32f103.sct
(2)点击 Scatter File 栏后的 Edit对.sct 文件进行编辑。点不动的话,直接用记事本打开AppStm32f103.sct,然后编辑。
示例将 core_main.c 的目标文件进行分散加载。
; *************************************************************
; *** Scatter-Loading Description File generated by uVision ***
; *************************************************************
LR_IROM1 0x08000000 0x00020000 { ; load region size_region
ER_IROM1 0x08000000 0x00020000 { ; load address = execution address
*.o (RESET, +First)
*(InRoot$$Sections)
.ANY (+RO)
}
RW_IRAM1 0x20000000 0x00038000 { ; RW data
.ANY (+RW +ZI)
}
}
LR_IROM2 0x08020000 0x00020000 { ; load region size_region
ER_IROM2 0x08020000 0x00020000 { ; load address = execution address
core_main.o (+RO)
}
}
红色区域表示将以上.c 文件加载到 0x08020000 地址,大小为 0x00020000。在这里,其目的通俗来说就是将以上.c 文件编译生成的目标文件链接到 MCU 芯片内部 flash 的 128KB 区域之后,区域大小为 128KB。
*******************************************************************
[3]编译工程,然后使用j-link或st-link读取这个范围的代码,生成一个文件,这个文件就相当于库了。
6、一个工程里面有几个文件夹,如果想把其中几个文件夹编译成库,然后把这个库放在其他工程里面,编译成可执行文件,怎么办?
STM32/keil把多个c文件编译为静态库lib_暴躁的野生猿的博客-优快云博客_c文件怎么编译成lib文件
这篇文字已经很详细了,我就不说了。
7、单片机远程升级是怎么回事?怎么测试?
[1]单片机里面分成两部分独立编译的可以运行的,起始地址不一样的程序。
起始地址在最开头部分称为boot,其他地址的称为app。
一开机执行boot,
从flash读出标识,如果需要拷贝程序,那么从设置好的位置,拷贝到app的位置,然后执行下一步,否则直接执行下一步。
boot把app的起始地址转换成函数指针,然后跳转到这个函数。
[2]怎样把程序放到单片机的flash里面呢?
(1)通过网络等方法。
方法有两种:1、在单片机里面执行ftp等协议,前提是单片机能正常连网。如果单片机使用AT执行,通过其他模块联网,那么这个方法不好用了;2、把bin文件看成一个一维数组,然后通过自定义协议,把这个一维数组的数据发送给单片机,单片机调用写flash函数,把数据保存到单片机某个区域。
(2)通过jlink方法,把Hex文件烧写到单片机的某一个区域。
8、怎样把Hex文件烧写到指定位置?
[1]下载:SEGGER - The Embedded Experts - Downloads
[2]安装:上面下载的JLink_Windows_V782d_x86_64.exe
[3]windows10-->点击左下角的“开始”-->J-Flash V8.2d-->打开Welcome to J-Flash对话框
-->点击Start J-Flash
不能使用Hex文件,否则没法指定位置。
9、打印串口打印几下就停住了,没反应,是怎么回事啊?
我打开Cube,加大线程的栈空间,把线程的优先级设为最高级,确认没有打开串口中断,还是没有用,怎么板呢?
我打开其他的Cube比较,发现我打开的看门口,但是没有喂狗,我把看门口关掉,终于可以一直打印了。
10、20221130,今天我弄单片机调试串口的重定向。输入函数总是不行,卡住动不了。我弄来弄去,都不行。我修改Cube的配置,改了很多种方法都不行。我后面不用fputc和fgetc,直接在线程里面调用HAL_UART_Receive和HAL_UART_Transmit,发现串口确实没有问题。这个时候我又反过来使用fputc和fgetc,结果好了。我检查一下Cube的配置,没有变,我把应用层的逻辑改到不行的样子,结果还是可以了。真实不解之谜,有一个。不过我注意到的是:我改了CubeMx,然后有改为回去,跟原来完全一样,发现文件还是跟原来不一样。是不是这个原因啊?
我把关键配置贴出来吧:
Keil配置
[1]Options for Target 'xx'-->Target-->打勾Use MicroLIB
CubeMx设置
[1] Categories-->GPIO-->USART
PA9:USART1_TX GPIO mode:Alternate Function Push Pull Maximum ouput speed:High
PA9:USART1_RX GPIO mode:Input mode GPIO Pull-up/Pull-down:No pull-up and no pull-down
[2]Categories-->Connectivity-->USART1
NVIC Settings:USART1 global interrupt 不要打勾
Parameter Settings:
Basic Parameters
Baud Rate:115200 Bit/s
Word Length: 8 Bits(including Parity)
Parity: None
Stop Bits:1
Advanced Parameters
Data Direction :Receive and Transmit
Over Sampling:16 Samples
Categories-->Middleware-->Tasks and Queues
点击执行输入函数的任务,配置如下:
Priority: osPriorityNormal
Stack Size (Words):200
代码:
[1]重定向
int fputc(int ch, FILE *f)
{
HAL_UART_Transmit(&huart1, (uint8_t *)&ch, 1, 1000);
return ch;
}
int fgetc(FILE *f)
{
uint8_t ch;
while(HAL_UART_Receive(&huart1, (uint8_t *)&ch, 1, 0xffff) != HAL_OK){}
return (int)ch;
}
[2]输入输出
while(1){
printf("input please...\n");
scanf("%d", &wV);
printf("%d-->come on!\n", wV);
}
调式助手
[1]“不选择”按十六进制发送
[2]输入12,然后输入回车。回车是看不到的,如果这时选择按十六进制发送,会看到后面有0D 0A。注意要输入回车。
[3]点击一次发送,上面就会打印一行。
11、设置了断点,然后点击全速运行后,没法再断点上停住,为什么?
原因一:可能是我用单数读取flash造成的问题。
解决办法:
在MDK-ARM文件夹里面,删除除*.uvoptx、*.uvprojx、*.s外的其他文件,然后打开*.uvprojx,重新编译。
这里重点说明一下:出问题的话,可以考虑删除,重新来;尝试感觉不可能的方法。
原因二:任务的优先级有问题
解决:
如果是使用CubeMx的话,可能是设置成Categories-->Middleware-->FREERTOS-->Tasks and Queues,双击其中一个Tasks,Priority:osPriorityldle改成osPriorityNormal
原因三:打开了调试助手
解决:
[1]在调试助手界面,点击按钮,关闭调试助手的串口
[2]在Keil界面,点击按钮,进入调试界面,
[3]在调试助手界面,点击按钮,打开调试助手的串口
[4]在Keil界面,点击按钮,进入全速运行。这个时候就可以在断点停住了。
看第16个问题,一般情况下不会出现这个问题,是因为开发板的问题。
12、单步调试的时候,光标不按照代码一行一行执行,总是乱跳。
解决:Options for Target ‘xxxx’-->Optimization:Level 0(-O0)
重新编译,然后重新单步调试,这样就不会乱跳了。
13、我想一份代码根据宏定义编译出多个程序,怎么办?
改一下*.c或*.h里面的宏定义,然后重新编译,这样吗?这样不好啊,动力里面的代码。
解决:假设原来有a.uvprojx,拷贝a.uvprojx,变成b.uvprojx。分别打开a.uvprojx和b.uvprojx。打开输入框:Options for Target ‘xxxx’,然后在Preprocessor Symbols-->Define:输入不同的宏定义。然后分别在a.uvprojx和b.uvprojx编译。这样就可以编译出不同的程序了。
宏定义例子:即 MDK 中的 VERSION_INFO_hw="'a'" 和 #define VERSION_INFO_hw 'a' 等效
要注意的是:换宏定义不同的*.uvprojx时,一定要点重新编译,否则还是原来的*.bin文件
14、前面讲了怎么把程序烧写到某个位置,现在问题来了,如果我不想用keil下载新的程序后,擦掉原来用J-FLASH直接下载的程序,怎么办呢?
解决:打开Keil-->点击第三排,第7个按钮-->Options for Target 'xxxx'-->Debug-->use:J-LINK/J-TRACE Cortex Settings-->Flash Download-->(*)Erase Sectors-->Programming Algorithm-->点击,然后修改Start和Size。
15、Keil生成Bin文件的时候,出现Bin文件夹,而不是Bin文件。
解决:
最后也不知道怎么回事,反正我这样操作一下就可以了。
[1]Options for Target 'xxxx' -->User-->After Build/Rebuild -->(*)Run #1 fromelf.exe --bin -o "$L@L.bin" "#L" 改一下其他的,然后还原。
[2]点击Options for Target 'xxxx' -->Target-->(*)IROM1: Start Size
点击Options for Target 'xxxx' -->Debug -->(*)Use: Settings-->Cortex JLink/JTrace Target Driver Setup -->Download-->Programming Algorithm -->点击其中一项,下面的Start: Size:就有值了。
核对一下上面两项。
[3]注释掉:const uint16_t testData0B[3000] __attribute__((at( 0x08070000 )));
有时候不注释也可以,无解。
[4]上面注释掉后,后面出现这个错误
After Build - User command #1: fromelf.exe --bin -o
... ...
Error: Q0108E: Could not create output file ... ...Permission denied
原因是上面出问题了,多出一个文件夹:*.bin。删除这个文件夹就可以了。
16、看代码:
void rebootDevice(void){
__set_FAULTMASK(1); //关闭所有中断
HAL_NVIC_SystemReset(); /* 重启 */
}
void runTask(void){
scanf("%d", &wV);
switch(wV){
case 3:
printf("%d >>>>>>>>-->reboot...\n", wV);
rebootDevice();
break;
}
}
意思就是说,打开调试串口,输入3后,单片机重启。如果没有意外的话,一定会有意外。输入3后,Keil就卡住了,单片机也没重启。怎么回事呢?
想啊想,我突然灵光一现。前面第11个问题的原因三提到了,如果单片机在Keil仿真状态启动,同时调试助手也打开串口的情况下,会出现卡住不动的现象。
我想到办法了。就是执行重启函数前,延时几秒,在这个时间段关闭调试串口,等重启完成后,再打开调试助手。
void rebootDevice(void){
osDelay(1000); //如果打开了调试串口,现在马上关闭,否则没法启动。
osDelay(1000);
osDelay(1000);
osDelay(1000);
osDelay(1000);
__set_FAULTMASK(1); //关闭所有中断
HAL_NVIC_SystemReset(); /* 重启 */
}
输入执行rebootDevice的前面延时的时候关闭调试助手的串口。几秒后在打开调试助手的串口。
后来发现原来是这个原因:开发板上面有USB转串口。这个口既是供电,又是把板上的调试串口,转成USB,然后电脑又把USB转成串口。这样虽然能打印,但是出现上面一对的奇怪问题。改成这样就可以了:插另外一个USB口,仅仅是给板供电;调试串口直接接到板上的专用的调试串口插针。
17、明明串口没问题,为什么printf没法打印呢?
解决:两个线程都调用了printf函数,导致不行了。不要执行另外一个线程的printf就可以了。
18、把串口设置成中断接收,串口中断输出函数,没有中断?
解决:
[1]注意执行:初始化的时候,执行HAL_UART_Receive_IT函数
[2]有些调试串口线有问题。开发板独立供电。调试串口先连接开发板只有三个脚:RX,TX,GND。在开发板不断电的情况下,拔掉USB转串口线后,这三个脚能反向影响到USB转串口线。这个时候插回去,USB转串口线没法用。必须断了开发板的电,然后再给USB转串口线通电。这样才行。有些USB转串口线没有这个问题。
简单地说:要初始化串口;先给USB转串口线供电,然后再打开开发板的电。
19、点击调试按钮后,没法进入调试状态?
原因:
我调试的程序是APP。我使用BOOT。APP的执行位置是0x0800B000,BOOT跳转到这个位置执行。
我不小心把APP的执行位置设成0x08000000,其他没有变。就是main函数的最前面那一句还在:SCB->VTOR = ((uint32_t)0x08000000) | ((0xB000) & (uint32_t)0x1FFFFF80);。
解决方法就是:(1)重烧boot;(2)起始地址改为0x0800B000。其他不变。
20、怎么不需要硬件,软件仿真?
(1).\GatewayRelayAppStm32f103\GatewayRelayAppStm32f103.sct(7): error: L6235E: More than one section mat
下面是不需要要的步骤。按照网上说的,选择了System Startup,去掉就好了,不需要这个,方法如下:
解决方法:
点击第三行,倒数第3个按钮-->Manage Run-Time Environment-->Software Component-->Device-->Startup-->[取消打勾]System Startup for STMicroelectronics STM32F1xx device series
(2)*** error 65: access violation at 0x40021000 : no 'write' permission
下面是软件需要的步骤。如果没有填对,就会出现这个错误。
解决方法:
1、第三排第七个按钮-->Options for Target 'xx'-->Device-->选择STM32F103ZE
2、第三排第七个按钮-->Options for Target 'xx'-->Target-->
1、[打勾]Use MicroLIB
2、Read/Only Memory Arease-->IROM1: Start:0x8000000,Size:0x1A000
3、第三排第七个按钮-->Options for Target 'xx'-->Debug-->
1、(选中)Use Simulator
2、[打勾]Load Application at Startup [打勾]Run to main()
1、左边的Dialog DLL:DARMSTM.DLL,Parameter:-pSTM32F103ZE。不能填错
(2)*** error 65: access violation at 0xFFFFFFF4 : no 'write' permission
*** error 65: access violation at 0xFFFFFFD4 : no 'write' permission
下面是不需要要的步骤。我的软件原来是使用boot的,app的位置是0x0800B000,main函数里面有下面这两句。
解决方法:
1、注释掉下面两行:
__disable_irq();
SCB->VTOR = ((uint32_t)0x08000000) | ((0xB000) & (uint32_t)0x1FFFFF80);
2、修改flash地址:
第三排第七个按钮-->Options for Target 'xx'-->Target-->Read/Only Memory Areas-->[打勾]IROM1:Start:0x08000000, Size:0x1A000(前面已经讲了,这里再说一遍。)
21、前面弄好了在没有硬件的情况下进行软件仿真。问题又来了。这样的情况下,怎么看调试串口的信息?
解决:
第一步:
在弄好硬件调试串口的情况下,改成这样:
//
#define ITM_Port8(n) (*((volatile unsigned char *)(0xE0000000+4*n)))
#define ITM_Port16(n) (*((volatile unsigned short*)(0xE0000000+4*n)))
#define ITM_Port32(n) (*((volatile unsigned long *)(0xE0000000+4*n)))
#define DEMCR (*((volatile unsigned long *)(0xE000EDFC)))
#define TRCENA 0x01000000
struct __FILE { int handle; /* Add whatever you need here */ };
FILE __stdout;
FILE __stdin;
int fputc(int ch, FILE *f) {
if (DEMCR & TRCENA) {
while (ITM_Port32(0) == 0);
ITM_Port8(0) = ch;
}
return(ch);
}
第二步:
打开Keil-->点击调试按钮-->点击第三排,第16个按钮-->选择:“Debug (printf) Viewer”。
22、前面第10点说了硬件调试串口的方法,第21点又说了Keil界面看调试信息的方法。问题来了,在Keil界面看调试串口的方法没法往Keil发送数据吧?怎么办呢?
思路:
实际硬件是:Keil-->单片机通过串口收发数据-->调试串口助手收发数据
方法就是:1、用一个软件,虚拟出两个串口,然后把这两个串口连接在一起。
2、调试串口打开其中一个串口,Keil通过命令,让Keil可以像真实单片机一样收发另一个串口的数据。
这样,调试串口就可以直接收发Keil的串口数据了。
解决方法:
第一步:
(1)下载vspd虚拟串口软件,然后安装。
(2)双击桌面的Configure Virtual Serial Port Driver-->Continue demo-->Virtual Serial Port Driver 7.2 Eltima Software-->右边Manage ports-->First port:COM1,Second port:COM4-->点击Add pair-->左边Serial ports explorer-->自动出现:Virtual ports -->+COM1,+COM2
第二步:
(1)双击串口调试助手
(2)串口设置-->串口号:选择COM1-->点击:打开
第三步:
(1)打开Keil-->点击第三排,第七个按钮-->打开界面:Options for Target 'xx' -->Target-->STMicroelectronics STM32F103ZE Xtal(MHz):8.0, Code Generation [打勾]Use MicroLIB, Read/Only Memory Areas [打勾]IROM1: Start:0x8000000, Size:0x1A000。
第四步:
方法一:
(1)新建文件:D:\usart_debug.ini
文件内容如下:
MODE COM2 38400, 0, 8, 1
ASSIGN COM2 <S1IN> S1OUT
(2)打开Keil-->点击第三排,第七个按钮-->打开界面:Options for Target 'xx' -->Debug -->(选择)Use Simulator,[打勾]Limit Speed to Real-Time,[打勾]Load Application at Startup,[打勾]Run to main()-->Initialization File:点击...,选择:D:\usart_debug.ini-->Dialog DLL:DARMSTM.DLL,Parameter:-pSTM32F103ZE
(3)点击调试启动按钮。
(4)点击全速运行按钮。
(5)调试助手可以看到打印信息,在发送窗口点击发送,Keil能收到。
方法二:
(1)点击调试启动按钮。
(2)Command窗口的>输入:
MODE COM2 38400, 0, 8, 1
然后回车
(3)Command窗口的>输入:
ASSIGN COM2 <S1IN> S1OUT
然后回车
(4)点击全速运行按钮。
(5)调试助手可以看到打印信息,在发送窗口点击发送,Keil能收到。