同样的代码在官方开发板上运行正常,在自己板子上就跑不起来,怎么办
同样的代码在Nordic官方开发板上可以运行正常,但在自己板子上就跑不起来,如果你碰到了上述情况,建议按照如下步骤进行自检:
1) 首先确认用户板元器件焊接良好,功能正常。如果你的板子有LED的话,你可以下载Blinky程序去点亮它,Blinky程序所在SDK目录为:SDK安装目录\examples\peripheral\blinky。如果你的板子没有LED,但有UART的话,可以下载CLI代码去进行UART交互,CLI代码所在目录为:SDK安装目录\examples\peripheral\cli。如果这2个程序能运行正常,说明你的焊接问题不大。
2) 确认高频晶振工作正常。由于射频一定要用到外部高频晶振,建议用示波器测一下高频晶振是否可以正常起振,以确保高频晶振工作没问题。这里需要注意的是,Nordic nRF5芯片高频时钟默认使用内部RC作为时钟源,为了让外部高频晶振起振,必须使用代码显式地打开高频晶振,可以使用如下2种方式之一来显式地打开高频高精度外部晶振:
- API方式
ret_code_t err_code = nrf_drv_clock_init(); ASSERT((err_code == NRF_SUCCESS) || (err_code == NRF_ERROR_MODULE_ALREADY_INITIALIZED)); nrf_drv_clock_hfclk_request(NULL); while (!nrf_drv_clock_hfclk_is_running()) { // spin lock }
- 直接操作寄存器方式
NRF_CLOCK->EVENTS_HFCLKSTARTED = 0; NRF_CLOCK->TASKS_HFCLKSTART = 1; while (NRF_CLOCK->EVENTS_HFCLKSTARTED == 0);
3) 确认有没有烧写softdevice以及softdevice版本是否正确。请使用SDK里面自带的softdevice进行测试
4) 确认有没有外部低频32K晶振。Softdevice默认使用外部32K晶振作为低频时钟,如果你的板子没有外部32K晶振,那么需要更改协议栈默认初始化参数,将低频时钟改为内部RC 32K。最新版本SDK需要更改sdk_config.h文件中的如下地方:
老版本SDK(SDK13之前)直接在源文件中做如下更改:
nrf_clock_lf_cfg_t clock_lf_cfg = NRF_CLOCK_LFCLKSRC; clock_lf_cfg.source = NRF_CLOCK_LF_SRC_RC; clock_lf_cfg.rc_ctiv = 16; clock_lf_cfg.rc_temp_ctiv = 2; //nRF52为2;nRF51为1;详情请看SDK相关头文件说明
5) 确认有没有打开DCDC模式。软件打开了DCDC模式,而用户板又没有DCDC相关外围电路,那么板子跑不起来也就正常了。如果属于这种情况,把软件中的调用语句:sd_power_dcdc_mode_set(NRF_POWER_DCDC_ENABLE),删掉即可。
6) 确认用户板芯片型号和DK上的芯片型号是不是一致。nRF51/nRF52系列里面包含多个子产品,每个子产品之间Flash或者RAM空间会有所不同。Nordic DK使用了资源最大最全的那个型号,如果你选择的型号Flash空间或者RAM空间跟DK上的不一样,那么你需要将工具链的链接脚本中Flash和RAM的值进行相应调整,其中Keil调整Flash和RAM空间的界面如下所示:
7) 确认用户板引脚定义有没有与DK相冲突。nRF5芯片在用户板上有可能与传感器,显示屏,GPRS模块,按键等相连,这其中用到的IO引脚有可能被固件初始化为其他用途,比如UART日志打印,也就是说,同样的引脚,用户板定义的功能和DK定义的功能不一致,所以DK可以正常运行,而用户板无法正常运行。此时一定要把相关引脚按照用户板的设计目的重新初始化,这样就可以解决这个冲突问题。常见的资源定义冲突有:
- buttons_leds_init()函数。buttons_leds_init会将某些IO口定义为按键和LED,如果用户板和DK定义不一样,有可能会出问题。
- uart_init()。当采用uart打印log的时候,固件程序会对uart进行初始化,此时有可能会导致资源定义冲突,比如用户板将相关uart引脚用于其他功能,从而导致板子跑不起来。
- SPI,TWI等其他外设资源定义冲突。必须确保所有外设引脚定义跟用户板一致,而不是使用DK默认值,否则有可能导致用户板跑不起来。
8) 请确认外部高频晶振的频率。这个只有nRF51有这个检查项,nRF52不存在这个问题,如果你使用的是nRF52的话,可以跳过这项不看。nRF51同时支持16M和32M外部晶振(注:nRF52只支持32M外部晶振),而且系统默认外部晶振为16M,如果你选择的外部晶振是32M,那么需要在软件中对其进行额外配置,否则系统跑不起来。此种情况有2种解决方法:
- 方法1。修改UICR中的寄存器XTALFREQ,由于UICR是Flash,对UICR的修改可以和代码下载合并在一块去做。(推荐使用方法1)
- 方法2。在main函数的开始处,加入NRF_CLOCK->XTALFREQ=0x00,即可。
9) 最后也是最重要的,debug问题具体出在哪,你可以通过打日志方式进行debug,也可以通过IDE的debug功能去调试,具体请参考:如何调试nRF5 SDK。记住,定位问题的时候,一定要定位到问题具体出在哪一行代码,而不是某个函数,否则问题就不算定位成功。问题没有定位成功,当然就无从下手去解决它。反之,定位到出问题的代码行,你自己就可以很快分析问题原因所在,从而快速解决它。