时间在2021年2月7日,寒假放假在家好好学一学nRF52840
感冒快好了,休息一波
开发板:初雪的100出头那块 NRF52840 EVAL KIT
下载工具:JINLK V11(最好是JLINK V9以上 也有人用JLINK OB也行,其他的下载器诸如STLINK,DAP不建议用)
版本号: KEIL5编程环境,CMSIS为5.3.0, NRF52840的CMSIS为8.35.0
参考资料: NRF52840-Eval-Kit-Schematic.pdf(原理图)
nRF5_SDK_17.0.2_d674dde(官方例程)
nRF5_SDK_17.0.0_offline_doc(官方文档)
nRF52840_PS_v1.1.pdf(官方数据手册)
------------------------------------------------------------------------------
------------------------------------------------------------------------------
已用IO
0.96OLED / 1.29彩色OLED
D0(CLK) -> 12
D1(SDA) -> 23
RES -> 7
DC -> 21
CS -> 19
按键
KEY0 ->11
KEY1 ->24
KEY2 ->20
KEY3->17
LED
LED0 ->13
LED1->14
LED2->32+9=41
LED3->16
串口
TX ->6
RX ->8
ADC
光敏 -> 5
摇杆X -> 28
摇杆Y -> 29
IIC_0.96OLED
SDA -> 32
SCL -> 22
还没用到(空闲)
P0.0 1 2 3 9 10 15 26 27 30 31
P1.1 2 3 4 5 6 7 8 10 11 12 13 14 15
添加WS2812B 幻彩RGB
DAT ->25(1路)
DAT->15(第2路)
添加正交编码器: (与LED冲突,最好把LED的跳线帽拔掉)
A相 ->13
B相 ->14
------------------------------------------------------------------------------
------------------------------------------------------------------------------
正交编码器(QDEC)
QDEC通过采样QDEC相位输入引脚(A和B)来解码增量运动编码器的输出。
片外正交编码器是一种输出两种波形、相位的增量式运动编码器
A和B相的两个输出波形总是90度的相位,这意味着一个总是在另一个之前改变电平。运动的方向由这两种波形中哪一种首先改变水平来表示。当两个波形同时切换时,可能会发生无效的跃迁。如果车轮相对于为解码器设置的采样速率旋转得太快,可能会发生这种情况,如果滑轮相对于为解码器设置的采样速率旋转得太快,可能会发生这种情况
QDEC通过采样QDEC相位输入引脚(A和B)在采样寄存器中指定的固定速率解码芯片外编码器的输出。
如果采样器的值需要改变,QDEC应该使用STOP任务停止。然后可以在接收到停止事件时更改SAMPLEPER,并使用START任务重新启动QDEC。如果不这样做,可能会导致不可预测的行为。
只有当QDEC停止时,更改其他寄存器(LEDPOL, REPORTPER, DBFEN and LEDPRE)是很好的做法
当启动时,解码器对两种输入波形进行连续采样,并将当前采样对(n)与前一采样对(n-1)进行比较解码。
下表描述了示例对的解码过程
可以看出 输出ACC状态就可以知道正/反转
判断标准为 1)当ACCDBL为NO change的时候, 判断 ACC即可
代码如下:
中断函数
int16_t p_acc;
uint16_t p_accdbl;
void MY_QDEC_INTERRUPT(nrfx_qdec_event_t event)
{
static uint8_t flag=0;;
static int cnt = 0;
if(NRF_QDEC_EVENT_REPORTRDY == event.type)
{
nrfx_qdec_disable();//关闭QDEC正交编码器
// int8_t dat;
// dat = nrf_qdec_sample_get();
// printf("ACC:%d\r\n", dat );
p_acc = event.data.report.acc;
p_accdbl = event.data.report.accdbl;
// printf("p_acc=%d,p_accdbl=%d\r\n", p_acc,p_accdbl);
nrfx_qdec_enable();//启动QDEC正交编码器
if(0==p_accdbl)
{
if(p_acc<0)
cnt++;
else
cnt--;
}
printf("cnt=%d\r\n",cnt);
}
}
初始化
void QDEC_INIT(void)
{
nrfx_qdec_config_t p_config;
p_config.dbfen = true; // 打开双采样过滤器
p_config.interrupt_priority = 3; //中断优先等级
p_config.ledpol = NRF_QDEC_LEPOL_ACTIVE_LOW ;//QDEC LED active on output pin low.
p_config.ledpre = 0; //Time (in microseconds) how long LED is switched on before sampling
p_config.psela = 13; //A引脚
p_config.pselb = 14; //B引脚
p_config.pselled = 0xffffffff; //不要灯(第31位为1即可不要灯)
p_config.reportper = NRF_QDEC_REPORTPER_80 ;//每80个采样次数,产生一个报告中断
p_config.sampleper = NRF_QDEC_SAMPLEPER_2048us; //大概2ms采样一次
p_config.sample_inten = 0;
nrfx_qdec_init(&p_config,MY_QDEC_INTERRUPT); //写入寄存器,配置中断事件
nrfx_qdec_enable();//启动QDEC正交编码器
printf("nrfx_qdec_enable_OK\r\n");
}
主函数
QDEC_INIT();
while(1)
{
// printf("hello world! \r\n");
}
------------------------------------------------------------------------------------------------------------------------------------------------------------
------------------------------------------------------------------------------------------------------------------------------------------------------------
------------------------------------------------------------------------------------------------------------------------------------------------------------
代码讲解
正交编码器初始化
1开启滤波器,注意开了滤波器之后,LED会一直出于开启状态(我这边没有开启LED引脚,而且用的是机械式编码器,不是光电鼠标编码器)
2和3:配置A,B相IO引脚,这个引脚随便设的
4:不要LED灯
5:每80个报告产生一次中断, 报告产生时间为80 *2ms =160ms左右,又开启了滤波器,可能时间还会延迟一倍
6: 每次对A,B相采样的时间间隔为2ms左右
7: 不要开采样中断,开了会每2ms(就是上面NRF_QDEC_SAMPLEPER_2048us)产生一次中断的,没什么用,不要开
8:把配置写入寄存器, 配置中断函数
9 开启编码器,跑起来
这个为中断函数:
1定义了获取两个变量, 至于为什么定义, 看下面的图
2 为触发的QDEC中断函数入口
3 当产生报告之后(我这边配置的是80个报告), 再来判断ACC
4 采集完之后, 先关掉编码器,这样防止下次数据入来
5 获取上面图的两个数据值
6 然后开启编码器,继续下次采集
7 为按上图ACCDBL的要求来的, 至于正还是反, 自己测试之后调整就好
8 输出cnt变化值
实验结果:
其中1为正转
2看到是有抖动, 无法避免, 你别转太快就不会产生
3是正转, 也有1个抖动, 别转太快
4是反转
最后 EC11的电路设计也有讲究,最好加上一阶RC滤波
还有,EC11的工作电压手册上面是5V,我这边用3.3V也是可以的, 因为nrf52840单片机是3.3V电平
代码我就不给了, 你们按我上面给的两段代码就能够用了,而且讲解的也很详细了,其他人的资料都没有给能用的代码, 我这边还是找数据手册一次次看过来尝试出来的