使用SEGGER Embedded Studio越来越多,本文总结了一些有用的小技巧。
本文是对SEGGER Embedded Studio使用技巧一文的延续。

1. 列选择

在编辑器中,按住Alt键并用鼠标框选,将执行列模式选择。

2. 快速找到文件

可以利用这个功能在工程文件堆中快速找到某个文件,比如文件名中包含了uart,点击“漏斗”图标,或使用快捷键Ctrl + ;,调出过滤栏,输入uart,即可列出所有相关文件。
Project File Filter

3. 扫描结果过滤

搜索关键字可能搜出大量匹配项,可以在搜索结果中进一步过滤。

Find Result Filter

4. 隐藏无效代码

工程中经常用#if 0宏开关让代码失效,可以设置无效代码的透明度,获得更好的视觉体验。
Tools --> Options --> Text Editor --> Inactive Code Opacity中设置5%,就可以得到下面效果

Inactive Code Color

5. 编辑工程文件

SES的工程文件(*.emProject)实际上是一个XML文件,某些场景下可以直接编辑它。
点击Project --> Open Solution in Editor,即可打开emProject文件。

Edit emproject file

6. 自定义宏标签

SES支持常规的TODO, FIXME宏标签,还支持自定义宏标签。在调试和读其他人代码的时候,尤其有用。
Tools --> Options --> Text Editor --> Attention Tag List中添加一个标签isyq,在代码注释中以isyq开头,即可高亮显示。

Customized Macro Tag

7. 跳转到编译错误

假如编译时报了多个编译错误,这些报错项可能夹在大量的编译信息中,手动查找的方式需要滚动半天,可以点击工具栏按钮或快捷键F4快速跳转到编译错误位置。

Build Warning Jumper

8. 串口终端

SES内置了一个简易的串口打印窗口,在调试时候不用再开第三方串口工具。
使用时候点击Tools --> Terminal Emulator

Intern UART Terminal

9. 预编译代码

代码中有的宏代码经过层层嵌套和拼接操作,无法直观的获知宏背后的原型函数和参数。

SES可以输出预编译后的文件,在当前源文件中,右键 --> Tools --> Show Preprocessor Output,即可打开一个名为xxx_PP.c的文件,该文件即源文件被预处理后的文件。
在追踪代码时候很有用。

Show Preprocessor Output

10. 工具栏大图标

现在显示器分辨率越来越高,小图标看着吃力。SES的工具栏图标可以设置为大图标,护眼。
Tools --> Options --> Environment --> Show Large Icon In Toolbars设置为Yes。

Toolbar Big Icon

(未完待续)

调试时遇到一段代码,精简后如下:

double val = 1 / (0 * 1.0);
uint32_t result = (uint32_t) val;

在Keil环境下(armcc v5.06)下,变量val = 0,result = 0,在Gcc环境下(arm-none-eabi-gcc v6.3.1)下,val = Inf(一个很大的数),result = 0xFFFFFFFF。

除法运算,除数不能为0。如果除数为0,该行为未定义(Undefined):

C99 6.5.5p5 – The result of the / operator is the quotient from the division of the first operand by the second; the result of the % operator is the remainder. In both operations, if the value of the second operand is zero, the behavior is undefined. [link]

实践中,如果被除数是0,编译器会给出警告(Warning),但是上面代码里( 0 * 1.0 )的操作骗过了编译器的检查。

于是,Keil和Gcc两个不同平台的编译器给出了不同的结果。

猜测虽然C语言的规范没有定义,但具体到编译器身上,还是要给出一个数值结果——Keil给0,Gcc给Inf。

这种基础运算经常出现在库函数里不起眼的角落,并且会被重重嵌套。这个例子背后真实的代码是Thingy52里面sx1509的驱动代码[link]:

uint32_t fade_in_time_low_mult_reg = 
(uint32_t) round(
        (real_val->fade_in_time_ms /
        (REG_RISEFALL_TIME_LOW_MULTIPLIER *
        (reg_val->on_intensity - (4 * reg_val->off_intensity)) *
        (255 / m_clkx_tics_pr_sec))) / 1000);

这一行代码中涉及到了多种数据类型:uint8_t,整形宏,float,double, uint32_t,此外还有常量。不同类型数据混合运算,会发生隐式类型转换,代码中也同时使用了显式类型转换。这些东西混在一起写成一行,很容易产生BUG。

(完)

查芯片手册时候会经常遇到LDO和DC-DC这两个概念,它们都属于电源管理模块,将高电压(向下)转换到目标电压。

LDO Regulator

LDO的基本原理图如下:(参考

LDO_Diagram

误差放大器(Error Amplifier)强迫两个输入端的电压相等,这样两个电阻之间的电压降趋于V_REF,于是得到V_OUT与V_REF的关系:(参考

V_out = V_ref × (1 + R1 / R2)

不考虑常数项,这可以看做是一个分压电路。

由于它实现起来很简单,几乎所有的芯片都会内置一个LDO,有些地方也称为线性稳压器(regulator)。

使用LDO无需额外的外围电路。

LDO的不足是,如果输入输出电压的压差大,那么许多功率都浪费在分压电阻上,不利于实现低功耗。

DC-DC Converter

DC-DC的基本原理图如下:(参考

DCDC_Diagram

当左侧开关打开,右边的电容开始充电,当左侧开关关闭,右边电容开始放电。

控制开关打开和关闭的频率,即可让右侧电容的电压维持在一个稳定数值。

开关的波动频率设为D,则有如下关系:

V_out = V_in × D

即输出电压与输入电压成正比例。如果比例系数小于1,为降压转换器,如果比例系数大于1,为升压转换器。

输出电压的波形如下图所示:(参考

DCDC_Output_Voltage

对输出电压进行滤波即可获得直流输出。

所以,使用DC-DC电压转换器,通常要额外加滤波电路。下面两个图为Silabs的BLE芯片EFR32BG12的参考连线图,上图为不使用内部DC-DC转换器,下图为使用了内部DC-DC转换器:

DCDC_Not_Used

DCDC_Used

比较两个电路,如果使用了DC-DC转换器,需要在VREGSW管脚外接一个LC滤波电路。

参考

DC to DC Converters

(完)