CSR8675的学习笔记:驱动正交编码器
为了方便大家学习,现与我爱蓝牙网联合推出【QCC300x/CSR867x/QCC30xx/QCC51xx开发板】。
技术交流QQ群号:743434463
开发板会员QQ群号:725398389(凭订单号入群,赠PPT、项目源码、视频教程)
——————————正文分割线———————————–
1. 引言
项目需要使用正交编码器作为音量旋钮。当旋钮顺时针旋转一格,音量即增大一格;当旋钮逆时针旋转一格,音量即减小一格。
2. 正交编码器工作原理
正交编码器又名增量式编码器或光电式编码器,用于检测旋转运动系统的位置和速度。下图是增量式正交编码器的实物图:
从上图可以看出,正交编码器的左下角有三个引脚,分别是A、B、C三个端子,其等效电路如下:
正交编码器的C端子需接地,A、B端子需接5V上拉电阻。当用户旋转正交编码器时,A、B端子的输出信号的时序图如下(图中红色波形代表A端子、黄色波形代表B端子): 上图4个脉冲分别对应用户旋转编码器的4个基本动作:
- 第一个脉冲代表顺时针旋转1格
- 第二个脉冲代表逆时针旋转1格
- 第三个脉冲代表顺时针旋转未到1格又逆时针转回至起始位置
- 第四个脉冲代表逆时针旋转未到1格又顺时针转回至起始位置
3. 解码器工作原理
解码器由采样、量化两个基本步骤组成。
3.1. 采样
假设用户旋转正交编码器所能产生的脉冲的最高频率是fsfsfs,可通过香农定理得知解码器的采样频率最低应不小于2fs2fs2fs,此时可以捕捉到用户的动作1、2。为了捕捉到动作3、4,即需捕捉每个脉冲的2个边沿变化,则需要解码器的采样频率达到2fs∗2=4fs2fs*2=4fs2fs∗2=4fs以上。
3.2. 量化
对章节2中的输出信号时序图进行4倍频采样,可以得到如下一组数据(省略同值样点):
Signal | S01 | S02 | S03 | S04 | S05 | S06 | S07 | S08 | S09 | S10 | S11 | S12 | S13 | S14 | S15 | S16 | S17 |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
B(yellow) | 0 | 0 | 1 | 1 | 0 | 1 | 1 | 0 | 0 | 0 | 1 | 0 | 0 | 1 | 1 | 1 | 0 |
A(red) | 0 | 1 | 1 | 0 | 0 | 0 | 1 | 1 | 0 | 1 | 1 | 1 | 0 | 0 | 1 | 0 | 0 |
上表数据分组如下: 其中红色方框数据对应图上红线超前黄线变化前后的采样值,代表顺时针旋转;蓝色方框对应图上黄线超前红线变化前后的采样值,代表逆时针旋转。 程序上只需用定时器以4fs4fs4fs为频率采样A、B两端子,并在每次采样时将本次采样值连同上次采样值与上述8组值相匹配,即可确定当前的旋转方向和旋转格数。比如本次采样值为B=A=1,上次采样值为B=0、A=1,与S02、S03相匹配,则判定开始顺时针旋转1格;当本次采样值为B=A=0,上次采样值为B=1、A=0时,与S04、S05相匹配,则判定顺时针旋转1格结束。
再观察8组值的特征,有如下几个特点:
- PreA ≠ PreB - CurA = CurB - 顺时针旋转:CurA = PreA
- 逆时针旋转:CurA ≠ PreA PreA:上一次采样时A端子的值 PreB:上一次采样时B端子的值 CurA:本次采样时A端子的值 CurB:本次采样时B端子的值 在编程时利用上述特点可大幅简化程序。
4. 解决方案
4.1. 外部解码芯片+CSR8675
Proto阶段用Cypress的CY8C40xx实现了驱动正交编码器的功能,方案框图如下:
上图中左侧为正交编码器的等效电路。当用户旋转正交编码器时,其A、B两引脚输出正交编码信号。CY8C40xx内部的正交解码器单元支持将正交编码信号转换成旋转方向和旋转格数,通过UART串口发送给CSR8675。CSR8675接收到此数据后将旋转方向和格数转换成音量增大或减小操作。 串口数据格式很简单,如下:
序号 | 命令名称 | 数据格式 |
---|---|---|
1 | 音量增[x]格 | 0x55, 0x01, [x], 0xaa |
2 | 音量减[x]格 | 0x55, 0x02, [x], 0xaa |
CSR8675的串口接收程序很简单,如下:
case 0x55: /* cypress uart message */DEBUG_QUAD_ENC(("QUAD: recv msg %x, %x, %x\n", receiveData[1],receiveData[2],receiveData[3])); if (receiveData[3]) {for (ucIdx = 0; ucIdx < receiveData[2]; ucIdx++) {if (receiveData[1] == 0x01) {MessageSend(&theSink.task, EventUsrMainOutVolumeUp, 0); }else if (receiveData[1] == 0x02){MessageSend(&theSink.task, EventUsrMainOutVolumeDown, 0); }}}else {DEBUG_QUAD_ENC(("QUAD: msg not support\n")); }
break;
4.2. 单CSR8675
上述方案的优点是实现起来简单可靠,支持最多4倍频计数。缺点是成本较高、PCB占用面积大、系统集成度低。 为了克服上述方案的缺点,用CSR8675的DSP驱动正交编码器是一个很好的方案,框图如下:
高通释放的ADK中包含一个DSP驱动正交编码器的库(rotary_enc.asm)。这个库实现的解码器也分采样和量化两部分。采样是通过捕捉PIO的电平边沿变化触发一个定时事件,在定时事件到来时采集PIO的电平,只支持2倍频率采样。这种机制的好处是降低中断事件的次数,坏处是当程序执行到临界区时无法捕捉电平边沿变化,导致丢失用户动作,手感不佳。 在库代码的基础上,改用以2ms为固定采样周期的定时采样机制,不仅克服了上述缺点,还实现了4倍频率采样。解码器的采样、量化和消息发送都在都在定时器中断服务程序里完成,代码如下:
.MODULE $M.rotary_enc.service_routine;
.CODESEGMENT ROTARY_ENC_SERVICE_ROUTINE_PM;
.DATASEGMENT DM; $rotary_enc.service_routine: // push rLink onto stack $push_rLink_macro; r0 = M[$PIO_IN]; r1 = 0x800; r2 = 0x80; // read PIO 11 r3 = 1; null = r0 AND r1; if Z r3 = 0; // read PIO 7 r4 = 1; null = r0 AND r2; if Z r4 = 0; // get last sample pio value r1 = M[$pio_a_last_value]; r2 = M[$pio_b_last_value]; // save current pio value M[$pio_a_last_value] = r3; M[$pio_b_last_value] = r4; // check if pre and cur value is match, // otherwise register timer event // pre pio A != pio B null = r1 - r2; if Z jump register_event; // cur pio A = pio B null = r3 - r4; if NZ jump register_event; // check rotate direction // 1: rotation, -1; anti-rotation // cur = pre pio A r0 = 1; null = r3 - r1; if Z r0 = -1; // send rotation number r2 = $KALIMBA_MSG_ROTARY_ENCODER_RETURN_ID_1; r3 = r0; r4 = 1; call $message.send;register_event: // fire a timer in 'MAX_BOUNCE_US' time r1 = &$timer_struc; r2 = 1000; r3 = &$rotary_enc.service_routine; call $timer.schedule_event_in; // pop rLink from stack jump $pop_rLink_and_rts; .ENDMODULE;
VM收到此消息后,将旋转格方向和旋转数转换成音量控制消息。
if (dspind->id == KALIMBA_MSG_ROTARY_ENCODER_RETURN_ID_1)
{ENC_DEBUG(("HS : rotary encoder 1 [val: %x]\n", dspind->value[0])); if (dspind->value[0] < 10) { MessageCancelAll(&theSink.task, EventUsrMainOutVolumeUp); MessageSend(&theSink.task, EventUsrMainOutVolumeUp, 0); }else if (dspind->value[0] > 0xfff0) {MessageCancelAll(&theSink.task, EventUsrMainOutVolumeDown); MessageSend(&theSink.task, EventUsrMainOutVolumeDown, 0); }
}
MessageCancelAll函数的目的是防止太多同类消息堆积,耗尽系统资源。
5. 总结
CSR8675驱动正交编码器的方案硬件成本低、可支持多组编码器、消耗的RAM资源少,实测响应速度快、不丢脉冲、不影响音频播放,是蓝牙平台深度开发的又一成果。 从另一个角度说,CSR8675的芯片架构设计值得认真学习。这种架构将快速、实时的任务交给DSP,将慢速、非实时任务交给VM,实现了系统的高效率运行。当然这种架构对开发人员的能力提出了更高的要求,这也不断鞭策我们努力提升自己的业务水平,向着更深更难处进军。
CSR8675的学习笔记:驱动正交编码器相关推荐
- 【TensorFlow-windows】学习笔记五——自编码器
前言 上一篇博客介绍的是构建简单的CNN去识别手写数字,这一篇博客折腾一下自编码,理论很简单,就是实现对输入数据的重构,具体理论可以看我前面的[theano-windows]学习笔记十三--去噪自编码 ...
- Linux学习笔记 驱动开发篇
ARM Linux 驱动开发篇 本篇我们将会详细讲解 Linux 中的三大类驱动:字符设备驱动.块设备驱动和网络设备驱动. 字符设备最多,从最简单的点灯到 I2C.SPI.音频等都属于字符设备驱动的类 ...
- 学习笔记STM32F429使用编码器测速HAL库版本
void TIM4_Init(u16 arr,u16 psc) { TIM4_Handler.Instance=TIM4; TIM4_Handler.Init.Prescaler=psc; ...
- ECBM函数库V3学习笔记⑥驱动TM1650
tm1650.h #ifndef _TM1650_H #define _TM1650_H #include "ecbm_core.h" /*-------------------- ...
- Linux学习笔记—驱动篇(二) 刷机和点灯
进行裸机编程的前提条件 1)U-boot启动 ,但是没有自动启动linux (在3秒倒计时中 ,打断自动启 动) 2)U-boot 提供自己的命令行 Hit any key to stop autob ...
- Linux驱动学习笔记 -- 驱动总线实验
驱动总线 在Linux系统中,除了硬件总线,还有一种软件虚拟出来的总线 – 驱动总线bus 这种驱动总线的作用:软件与硬件代码分离,提高程序的复用性 驱动总线分三个部分: 三者都是在/include/ ...
- STM32学习笔记(三)丨中断系统丨EXTI外部中断(对射式红外传感器计次、旋转编码器计次)
本篇文章包含的内容 一.中断系统 1.1 中断的定义 1.2 中断优先级 1.3 中断的嵌套 1.4 STM32中的中断系统 1.4.1 STM32的中断资源 1.4.2 嵌套中断向量控制器 NVIC ...
- STM32学习笔记——基于正点原子例程编码器模式小结
STM32学习笔记--基于正点原子例程编码器模式小结 最近一段时间学习了,STM32f4的编码器功能,经过自己探索和他人的热心帮助,对于编码器模式有了一定了解.STM32f4单片机提供编码器模式,以便 ...
- 深度学习笔记一:稀疏自编码器
开始学习深度学习了,既然确定目标就要努力前行!为自己加油!--2015.6.11 Sparse Encoder 1.神经网络 概念:假设我们有训练样本集 (x(^ i),y(^ i)) ,那么神经网络 ...
最新文章
- Fragment 生命周期:
- Windows Server 2008怎么查看远程桌面登录日志
- SU suspecfk命令学习
- 英特尔多核联合实验室授牌仪式
- java基础之-I/O流和File类解析
- Executors.newFixedThreadPool(NTHREADS)线程池数量设置多少合适?
- redis命令_INCR
- Codeforces Round #584 (Div. 1 + Div. 2)
- 论【软件工程是不是教会不怎么会写程序的人软件开发】
- 一步一步搭建11gR2 rac+dg之配置单实例的DG(八)
- 青鸟BCNT-网络信息安全工程师
- python开发一般用什么工具,最常用的python开发工具
- matlab实验思考,MATLAB实验.doc
- 不用插件,如何将tif格式的影像精准导入到CAD中?
- 深度学习基础篇【5】从0开始搭建YOLOV5 并进行测试
- 阿里巴巴内测全网社交产品来往
- C++编码规范与指导zt
- 针对移动手机漏洞与安全支付现状分析
- 每公里配速9分18秒,双足机器人完成5公里慢跑
- 从零开始构建VUE 客户端和服务端SSR项目