ADC按键驱动

来源:互联网 发布:淘宝怎么修改价钱 编辑:程序博客网 时间:2024/05/16 05:05

ADC是有通道的概念的,每一个GPIO可以被复用一个ADC按键,公司芯片有8个ADC通道。

至于为什么要用ADC按键,因为按键可以通过形成一个阵列的方式,每一个开关按键分到不同的电压,通过ADC就能软件判断到底是哪一个按键在产生作用。这样的话就大大提高了gpio管脚 的利用率。

首先设置ADC控制器CFG模块使能位。读取ADC控制器中断位,并且清相对应的中断。当然最终要打开ADC相对应的padmax位。

读取ADC按键的值的时候,首先要选择接下来读取的到底是哪一个通道,最后当然是从相应的寄存器里面读取对应的按键的电压大小。

对于软件来说,区分不同的按键主要的任务还是实现填充好不同按键按下电压的参考值,然后比较,最后判断是哪个按键,并且调用相对应的处理函数。

#define KEY_RANGE(a, b) (((a > b - 100) && (a < b + 100))? 1 : 0)

如果要判断按键是否长按,那么在一开始按键按下的时候,判断得到的确有某一个按键被按下,那么就启动看门狗或者定时器,到了指定的间隔时间后,就再次检测该按键是否按下。这里的应用场景在音频方面主要还是录音的功能。

wd_start(key_priv.wdog_id, SC6138_ADCKEY_TIMEOUT, key_detect_low_level, 1, 0);<span style="white-space:pre"></span>//这里采用看门狗的实现方式
这里对寄存器操作的步骤还是比较简单,所以在linux中没有ADC子系统的概念,通常我们都是将它看成一个misc驱动。然后编写ioctl来打开相应的ADC通道。


同时,今天因为工作任务,看ADC源代码的时候,因为并不是在linux系统中,而是在nuttx系统中,发现就算你调用

task_create("adckey", 5, 8192, adc_main, NULL);
创建一个任务,那么你在该任务中执行while(1);死循环那么你的系统就会在该死循环中,本来以为类似于创建线程的动作,即使是在线程中死循环,那么也不会影响其他的线程,发现并不是这样,如果在
while(1) sleep(1);
那系统还是会在sleep期间将使用权通过时间分片给其他的进程或者线程。

但是如果调用sleep期间就又会出现一个问题,就是你按下开关按键,但是相应的打印不会出现,最后问了同事,同事的答案是watchdog的问题,因为当你定时器到了要处理相应的检测函数,但是此时该进程正在睡眠,里面的之前打开adc文件的文件号,并不会生效,所以相应的read函数也就不起作用了。

最终的解决办法,就是不使用设备驱动注册的那一套方法,直接调用相对应的读写和设备初始化函数,最后就能完成功能目标了。




0 0
原创粉丝点击