问题记录:解决C语言与STM32常见问题的关键点
问题1:
C++编译出现错误:'…undefined reference to…'
通常是由于链接错误导致的,是编译器在链接过程中无法找到相关的函数或变量的定义引起的。
1. 函数/变量未定义:在使用某个函数或变量时,如果没有在代码中找到相应的定义,就会出现"undefined reference"错误。这可能是由于函数/变量的名称拼写错误、函数/变量声明或定义不一致、函数/变量未被正确包含等所致。
>>>>>检查函数/变量定义和声明:首先,要确保函数/变量的名称拼写没有错误,特别要注意大小写。其次,要检查函数/变量的声明和定义是否一致,包括参数类型、返回值类型等。如果函数/变量是在其他源文件中定义的,要确保引用了正确的头文件并将源文件编译链接在一起。
2. 链接顺序错误:如果在代码中存在多个源文件,并且它们之间有相互依赖的关系,那么编译器在链接时需要按照正确的顺序进行链接。如果链接顺序错误,就会导致"undefined reference"错误。
>>>>>检查链接顺序:如果代码中存在多个源文件,并且它们之间有相互依赖的关系,编译器在链接时需要按照正确的顺序进行链接。我们可以通过将源文件按正确的顺序传递给编译器来解决此问题,或者使用链接器提供的命令行选项指定链接顺序。
问题2:
RS485和串口通信的区别
参考链接:
https://zhuanlan.zhihu.com/p/647978304
https://m.elecfans.com/article/2257815.html
其中,A、B为总线接口,用于连接 485 总线。
RO 是接收输出端,DI 是发送数据收入端,RE是接收使能信号(低电平有效),DE 是发送使能信号(高电平有效)。将串口的TTL电平,经过该芯片变成了485电平。TX发送,DI收入。反之
其中DE和RE连接,当DE高电平,使能输出;让RE 低电平时,使能接收
问题3:
PWM波占空比
参考链接:
https://blog.csdn.net/wanglong3713/article/details/134938244
CNT计数值
ARR自动重装载值
CCRx通道x电平跳变值
PSC预分频值
例:
PWM频率 = 72 000 000 / (100 – 1 + 1)*(720 – 1 + 1)=1000Hz
问题4:
ModBus协议
参考链接:
STM32HAL库RS485-ModBus协议控制伺服电机_stm32实现 modbus-CSDN博客
读数据
发送
接收
写数据
发送
问题5:
STM32F103系列DMA各个通道一览表
参考链接:
【DMA】认识 DMA 及其工作流程(与传统CPU存取方式的区别)_cpu dma-CSDN博客
https://blog.csdn.net/challenglistic/article/details/132109276
问题6:
上面提到的 Program Size 包含以下几个部分:
(1)Code:代码段,存放程序的代码部分;
(2)RO-data:只读数据段,存放程序中定义的常量;
(3)RW-data:读写数据段,存放初始化为非 0 值的全局变量;
(4)ZI-data:0 数据段,存放未初始化的全局变量及初始化为 0 的变量;
问题7:
boost::asio::serial_port 串口通信类
参考链接:
C++ boost::asio::serial_port 串口通信类 使用 封装-CSDN博客
如先前所述,serial_port类成功打开串口后,串口对于serial_port类来说就成了一种文件流。咱们就可以使用serial_port类中的成员函数往“流”写和读数据了。
向串口发送数据时是采用boost::asio::serial_port下含write字符串的函数将程序中的数据写入到串口流,接收串口数据时是用含read字符串的函数从串口读出数据,再放到程序变量中。比如用串口对象调用的write_some(),read_some()一类属于serial_port的成员函数,还有在函数内部指明串口对象的write(),read()等非serial_port类的成员函数,但它们是boost::asio下的函数。看名就知道“只写/读一些”的函数(比如读到空格或者其它特殊字符就会停止读下去)不如“写/读”函数功能完好。所以,咱都还是用write(),read()一类的函数从串口写、读完整的数据串吧。
问题8:
设置抢占优先级和子优先级有什么讲究
设置STM32的抢占优先级和子优先级的讲究如下:
抢占优先级(Preemption Priority):这是最高层次的优先级。如果两个中断具有相同的抢占优先级,那么它们的子优先级会被用来决定哪个中断首先被处理。抢占优先级决定了哪个中断可以打断正在执行的中断1。
子优先级(Sub Priority):在抢占优先级相同的情况下,子优先级决定了中断的处理顺序。如果两个中断具有相同的抢占优先级,那么子优先级较高的中断会首先被处理1。
在设置抢占优先级和子优先级时,需要考虑到中断的重要性和处理时间。一般来说,重要的、需要尽快处理的中断应该设置较高的抢占优先级,而次要的、可以稍后处理的中断可以设置较低的抢占优先级。同时,子优先级可以用来进一步区分具有相同抢占优先级的中断,以确保正确的处理顺序1。
需要注意的是,STM32的优先级设置可能会根据具体的微控制器型号和库版本有所不同,因此建议查阅相关的数据手册、参考手册和库文档,以获取最准确的信息。
问题9:
read_some()和async_read_some()的区别
在需要实时读取串口数据并进行处理的情况下,通常推荐使用async_read_some(),因为async_read_some()是异步的,它不会阻塞当前线程,允许你的程序在等待数据到达的同时继续执行其他任务。这对于实时系统来说非常重要,因为它可以提高程序的响应性和效率。
使用async_read_some()时,你可以定义一个回调函数来处理接收到的数据。当数据到达时,这个回调函数会被自动调用,你可以在回调函数中执行必要的处理逻辑。这种方式非常适合需要实时处理串口数据的场景。
问题10:
0x1FFFF3AE 0549 LSLS r1,r1,#21
0x1FFFF3B0 D5FB BPL 0x1FFFF3AA
0x1FFFF3B2 F8D01808 LDR r1,[r0,#0x808]
打开仿真后指针无法进入Main()中,并停在这附近。
1. BOOT两跳线帽接错,记得仿真时需要两个跳线帽都接GND并将开关按下;需要外接单独供电,在JLink下载时单独加上外部供电可以解决。
2. 检查板子晶振是否起振
3. 同时要注意Keil仿真最多只支持5个断点,大于等于5个断电,则会出现该问题。
[1] 问题解决方法来源于网络
[2] 图片来源于网络
作者:小凌Candy