2166|7

1372

帖子

2

TA的资源

五彩晶圆(初级)

楼主
 

nRF51822 开撸 [复制链接]

  玩了几年的ARM单片机,基本上就在STM32的圈子里;尽管手头囤积的芯片当中还有其它厂商的,都没怎么用,实在惭愧。

  昨天拆了一个几年前的手环(因为LP说APP找不到不能用,就当报废了呗),vidonn的产品。这货做得实在是……彻底装不还原了。除了粘合得融为一体之外(面板拆下来都已经裂了),充电接口用的铜件居然是贯穿塑料再焊在PCB上的。

  拆了之后再不能戴手上去了。电路部分还是完整拆了出来。

 

  于是,获得带12832OLED屏和电池、加速度传感器、触摸传感器、串行Flash 的 NRF51822 开发板一块。QFN的封装毕竟比BGA还是能容易搞,用表笔可以量引脚。

  在屏的那一面还有一些测试点,首先检查 SWDIO, SWCLK 是否引出来了(引出来就不用自己飞线),结论是肯定的。用J-Link测试了SWD可用(顺便把芯片 un-secure 了,也就是擦除已有的程序,就可以任意烧写了)OLED的I2C也连到测试点上了。我对着手册找了一下,直接能用的I/O口就这几个:

  Nordic nRF5系列的硬件风格和 STM32 有明显的不同。(题外,国产替代MCU基本还是仿STM32。)比如 GPIO 的寄存器设置和STM32没有兼容性。我先在 J-link commander 里面写了下GPIO的寄存器,将测试点对应的 P0.28, P0.29 设置成输出,然后改变电平。可以控制——说明复位后初试状态GPIO已经使能了。

 

  要给 nRF51822 写程序,必须要有包含寄存器定义、IRQ定义的头文件——这是最重要的。其次还要个启动文件(主要是包含中断向量表的定义),然后还要个GNU Linker的脚本文件(如果没有也可以用其它的比如STM32的改来用,不是那么关键),就可以开撸了。这几个文件在MCU的SDK里面都应该能找到。

  我找出来两三年前就下载过的一个 nRF5 SDK 压缩包,从里面把必要的文件提出来。SDK 是支持GCC的,很好。examples 目录里面有 blinky 也就是闪灯的程序,写得很简单。我想先编译下例子呗,不过它是要依赖SDK里面的HAL库的,缺什么文件需要逐个单独拿出来。然而弄下来还是因为缺少开发板定义的一些宏而不能编译,虽然要搞定也不会难。但是这样已经把简单的事情复杂化了,算了,直接操作寄存器吧。

  于是就这样写了:

#include <nrf51.h>

int main(void)
{
	NRF_GPIO->DIRSET = 1<<28;
	
	while (1)
    {
		NRF_GPIO->OUTSET = 1<<28;
		delay_ms(500);
		NRF_GPIO->OUTCLR = 1<<28;
		delay_ms(500);
    }
}

  然后呢,这个 delay_ms() 函数我从写过的 stm32 工程里面找一个,用 SysTick 定时器延时的,直接用。因为要用 nRF51822 的 Timer 的话要先学习,就后面再做。

  我把为 STM32 工程写的 Makefile 也移用过来了,用了自己编的通用 Linker 脚本,但是和 nRF SDK 里面的启动汇编文件不兼容,又改了一番启动程序(代码都被我换了,就借用了它的中断向量表。想到这,日后我再写个启动程序生成工具得了)。

  然后编译完成,用nm命令看了一下ELF里面地址分布没有问题了,就用J-link OB来烧写。

  我接在 GPIO0.28 的LED亮了,但是不闪烁,奇怪了。于是GDB进去看,发现在 delay_ms() 函数里面没有返回。怪了,SysTick 是 cortex-m0 都通用的操作方法,怎么会挂了呢?看了反汇编代码我也没有发现异样。再从头单步跟踪下,执行过程也没有问题,不然LED不会亮的。查看对SysTick寄存器的写指令,也是正确的。

  然而我查看了一下写 SysTick 寄存器之后的值,竟然都是 0.  这没写进去也不可能啊。于是网上搜索一下,结果是 nRF51 系列并没有配置 SysTick 模块。这个在 cortex-m0 中的确是可选的,只不过一般MCU都有而已。

  那好吧,暂时就用一长串 NOP 指令来改写 delay_ms() 函数了。

void delay_ms(uint16_t t)
{
	int i;	// no Systick timer in NRF51 series
	for(i=0;i<t;i++)
	{
		int m;
		for(m=0;m<10;m++)
		{
			asm volatile ("nop;\nnop;\nnop;\nnop;\nnop;\nnop;\nnop;\nnop;\n"
			"nop;\nnop;\nnop;\nnop;\nnop;\nnop;\nnop;\nnop;\nnop;\nnop;\n"
			"nop;\nnop;\nnop;\nnop;\nnop;\nnop;\nnop;\nnop;\nnop;\nnop;\n"
			"nop;\nnop;\nnop;\nnop;\nnop;\nnop;\nnop;\nnop;\nnop;\nnop;\n"
			"nop;\nnop;\nnop;\nnop;\nnop;\nnop;\nnop;\nnop;\nnop;\nnop;\n"
			"nop;\nnop;\nnop;\nnop;\nnop;\nnop;\nnop;\nnop;\nnop;\nnop;\n"
			"nop;\nnop;\nnop;\nnop;\nnop;\nnop;\nnop;\nnop;\nnop;\nnop;\n"
			"nop;\nnop;\nnop;\nnop;\nnop;\nnop;\nnop;\nnop;\nnop;\nnop;\n"
			"nop;\nnop;\nnop;\nnop;\nnop;\nnop;\nnop;\nnop;\nnop;\nnop;\n"
			"nop;\nnop;\nnop;\nnop;\nnop;\nnop;\nnop;\nnop;\nnop;\nnop;\n");
		}
	}
}

 

  再编译,烧进去,reset, LED就闪了。用示波器测量闪烁频率,推算出CPU时钟在16MHz,这是复位后默认的时钟。

 

此帖出自单片机论坛

最新回复

赞!非常精彩,楼主厉害了   详情 回复 发表于 2021-4-6 16:27
点赞 关注
 

回复
举报

2939

帖子

0

TA的资源

五彩晶圆(中级)

沙发
 

顶,好帖,楼主也是一个动手达人,都不用买开发板了。

此帖出自单片机论坛
 
 

回复

1372

帖子

2

TA的资源

五彩晶圆(初级)

板凳
 

  接着,来操作下 UART 输出字符。UART 对应的寄存器表:

  寄存器表前面有两个部分分别是 Tasks 和 Events,与常规的寄存器操作有所不同。

  读手册,这里需要了解 nRF51xxx 当中的 task 和 event 概念了。task 并非是操作系统的任务概念,而是硬件设备的一个触发机制。对寄存器表的 Tasks 类进行写 1 操作,将产生一次触发。除了写 Tasks 类的寄存器,还有硬件设备之间通过 Events, Tasks 互连进行触发的方式,可用来实现一些自动操作。Events 并不是 cortex-m0 系统的唤醒事件,我理解它就是一个标志位。UART 的 RX/TX ready 信号在这里都变为了 Tasks.

  在我以前用过的 MCU 中,串口发送只要在配置使能以后写 TX 对应的寄存器就可以了。nRF51 这里还需要用 STARTTX 这个 task.  软件上就是先对 STARTTX 寄存器写 1, (不能写0).

  串口用到的引脚的分配方式,和 STM32 完全不同。nRF51 这里,任何GPIO脚都可以选择成串口的某个功能引脚,灵活性巨大。GPIO的寄存器里面也没有什么复用功能选择的配置了。比如我用 GPIO0.29 作为 TXD, 就在 PSELTXD 寄存器写入29这个值。此外按照需求要把 GPIO0.29 配置为输出模式,输出高电平。

 

  测试成功的代码:

uart_write(uint8_t *buf, int len)
{
	int i;
	NRF_UART0->TASKS_STARTTX = 1;	// task trigger
	for(i=0;i<len;i++)
	{
		NRF_UART0->EVENTS_TXDRDY = 0;	// clear event
		NRF_UART0->TXD = buf[i];
		while(!(NRF_UART0->EVENTS_TXDRDY))	// wait event
		{}
	}
	NRF_UART0->TASKS_STOPTX = 1;	// task trigger
}

int main(void)
{

	NRF_GPIO->DIRSET = 1<<28|1<<29;
	NRF_GPIO->OUTSET = 1<<29;	// UART TXD
	
	NRF_UART0->PSELTXD = 29;
	NRF_UART0->BAUDRATE = UART_BAUDRATE_BAUDRATE_Baud115200;
	NRF_UART0->ENABLE = UART_ENABLE_ENABLE_Enabled;

	while (1)
    {
		NRF_GPIO->OUTSET = 1<<28;
		uart_write("nRF51822 blinking\r\n",19);
		delay_ms(500);
		NRF_GPIO->OUTCLR = 1<<28;
		delay_ms(500);
    }
}

 

  用 J-link OB 带的USB串口接收一下验证:

此帖出自单片机论坛
 
 
 

回复

1万

帖子

25

TA的资源

版主

4
 

你这个比较方便。我淘了一个板子,是WLCSP封装的,看不出引脚。

 

此帖出自单片机论坛

点评

这个我也有。SWDIO, SWCLK 测试点都标出来了。就是没有原配的屏。 I/O好办,编段代码扫一下就测出来了。  详情 回复 发表于 2021-4-5 19:50
 
 
 

回复

266

帖子

0

TA的资源

一粒金砂(高级)

5
 

楼主厉害,这对学习来说是一个不错的锻炼哦

有没电路图,其他传感器对应的引脚,需要慢慢探索了呢~

此帖出自单片机论坛
 
个人签名

gitee/casy

 
 

回复

1372

帖子

2

TA的资源

五彩晶圆(初级)

6
 
dcexpert 发表于 2021-4-4 22:25 你这个比较方便。我淘了一个板子,是WLCSP封装的,看不出引脚。  

这个我也有。SWDIO, SWCLK 测试点都标出来了。就是没有原配的屏。

I/O好办,编段代码扫一下就测出来了。

此帖出自单片机论坛
 
 
 

回复

1万

帖子

25

TA的资源

版主

7
 
cruelfox 发表于 2021-4-5 19:50 这个我也有。SWDIO, SWCLK 测试点都标出来了。就是没有原配的屏。 I/O好办,编段代码扫一下就测出来了 ...

一个个试太麻烦了

此帖出自单片机论坛
 
 
 

回复

1万

帖子

2854

TA的资源

管理员

8
 

赞!非常精彩,楼主厉害了

此帖出自单片机论坛
加EE小助手好友,
入技术交流群
EE服务号
精彩活动e手掌握
EE订阅号
热门资讯e网打尽
聚焦汽车电子软硬件开发
认真关注技术本身
 
个人签名

玩板看这里:

https://bbs.eeworld.com.cn/elecplay.html

EEWorld测评频道众多好板等你来玩,还可以来频道许愿树许愿说说你想要玩的板子,我们都在努力为大家实现!

 
 

回复
您需要登录后才可以回帖 登录 | 注册

随便看看
查找数据手册?

EEWorld Datasheet 技术支持

相关文章 更多>>
关闭
站长推荐上一条 1/10 下一条

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

About Us 关于我们 客户服务 联系方式 器件索引 网站地图 最新更新 手机版

站点相关: 国产芯 安防电子 汽车电子 手机便携 工业控制 家用电子 医疗电子 测试测量 网络通信 物联网

北京市海淀区中关村大街18号B座15层1530室 电话:(010)82350740 邮编:100190

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved
快速回复 返回顶部 返回列表