-
error 1347
can't find 0x16 words (0x16 withtotal) for psect "text9" in class "CODE" (largest unused contiguous range 0x12)
解决方案:
Article URL
简要说明:
你遇到了编译器的优化极限。这个时候需要把编译器的优化级别调整一下,位置在:
Project Properties -> XC8 global options -> XC8 compiler -> Optimizations categories = Optimizations
对我而言,从o0->o2,问题解决。
另外,你可能需要将函数处理为可重入的,意思就是不同的中断级别以及主线程各自有独立的栈。
你可能需要修改堆栈的大小,为此可能需要修改编译器c的类别,由c99->c90。
-
error can't mix prototyped and non-prototyped arguments
偶然看到招聘广告上看到有公司在招对C90,或者C99有了解的工程师。
很大的可能性,就是他们遭遇了类似的编译错误。因为这个问题在C99 - C90两种编译模式切换时才会发生。
解决这类问题没有必要对C标准有多么深入的理解。
解决方案:你可能遗留了重要的头文件包含,比如size_t的定义("string.h"),或者uint8_t的定义(" stdint.h")
补上即可。这是编译器输出没有那么精确导致的。
-
关于手工进行adc采样
对于单片机,要特别注意采样间隔。这个采样间隔不仅仅是mcc提示你的采样间隔。你还需要考虑到单片机本身的运算极限。
MHz级别的单片机,对应uS的间隔,它的运算速度与人工的速度相似,它此时仅能完成有限条数的指令。要特别留神,你只能依据自动计数的定时器,你绝不可以通过中断计数来记录时间间隔。
-
内存受限的编程环境,必知必会
首先你需要在代码中使用<stdint.h>
要非常熟悉 uint8_t int16_t这类变量。以及INT16_MAX 这类UINT16_MAX常量。
注意float可能为24bits或者32 bits.知晓它们的有效位数。
知道编译器double 和float的位宽是可以定制的。并且不同的位宽,相关的数学库的尺寸也不一致。
注意你的堆栈配置:参见下节:
-
函数自动复制与堆栈配置
这是一个很神奇的概念,我从未在其他的编译环境中看到过。
PIC单片机首先为了保证执行的过程不会因为堆栈溢出造成运行时错误,它把栈中出现的变量,固定到了data ram的确定位置,它的后果有两个:
-
它无法支持函数迭代。
-
出现了函数重入的问题。
为了解决这个问题,部分解决这个问题,PIC引入了函数复制的概念,凡是可能会同步运行的函数,都会额外复制一份。另外,为了避免在中断函数中出现同一个函数重入,PIC引入了三个独立的堆栈——主线程堆栈,低优先级堆栈和高优先级堆栈。。。
这就是那个警告的由来:
non-reentrant function “_foo” appears in multiple call graphs and has been duplicated by the compiler
为了避免出现因此引发的内存暴增问题,建议这样处理:
将堆栈模式改为hybrid
但是这样做会有风险——你的程序可能以为堆栈溢出跑飞。
它的实际效果:
stack = hybrid |
stack=reentrant,如果是compile模式内存会爆掉. |
PIC单片机怀疑在宇航,军品这类场合用过。默认的堆栈模式,不涉及动态内存分配。基本上不可能有运行时故障。
-
为什么程序又卡死了?
嵌入式单片机,未引入分时操作系统之前,要注意,一旦你卡在中断里出不来,整个程序的运行会失去响应——这是很显然的事情,因为中断优先级高,主线程将无法得到运行的机会。
在程序卡死的时候,不要慌张,逐个扫描各个重要的分支跳转和循环语句,看看是否会卡死。
-
TTL电平usb->uart乱码的原因及处置策略
TTL电平的 USB->UART有时候会出现乱码,这大概率不是设备出现了故障,而是因为收发两侧,时钟频率和波特率不匹配造成的,比如,看这款芯片:
编辑
在采用64MHz的时候,波特率设置为115200波特率,会出现-3.55%的偏差。这个偏差如果不校准,仅仅使用Tx,Rx,Gnd异步盲发会偏得越来越厉害。
解决方案是什么呢?
1.软件上,选择特定波特率
可以选择那些理论上不可能有偏差的特殊波特率:比如,上图给出的64M晶振下,10417的波特率,是准的,64M可以被10417波特率下的单字节发送所需时间整除。(有时候,你发现公司的既有产品出现了一个很特别的波特率:1200, 38400差不多就是这个缘故。)
2.硬件上,选择特定振荡器
选择与特定波特率匹配的外部振荡器,来实现更精确的波特率输出。现代的代码生成器,有些会提供波特率的时钟误差验算,误差在0.01%的波特率已经可以启用异步收发大段数据了。
3.软件或者硬件:引入握手
握手有两种,硬握手和软握手。硬握手,单向传输需要额外的两根握手线;对于软握手,整个传输过程只需要三根线——TX,RX,GND
4.软件发送延时:最笨的方法
延时发送,在一次发送完即将产生错位的波形时,就需要停止下来,延时后再次发送。注意,一个字符的发送至少需要1起始位+8数据位+1停止位 = 10个bit.则如果对于3.55%的偏差,发送完一个字符,偏差就会增加至35.5%,基本上,这种模式,只能连续发送两个字符。第三个字符发送时必然会出错。
-
复数运算
单片机环境,复数类型公式的验算可能会受限,将复数运算转换为标量运算很容易出错。我所使用的芯片,支持复数运算的xc8 v2.0更新的地方很多,如果是新项目,可以大胆尝试。
MPLAB® XC8 v2.0 Updates - Developer Help
PIC github上发布了一个使用自定义结构,实现复数运算的例程:Lab Exercise 15: Arrays of Structures - Developer Help