[教程]手把手教你用AVR Studio+WinAVR+QTouch Lib点亮蜗牛触摸板
鉴于早期的QTouch Lib都只支持用IAR编译的,官方的程序范例也是IAR的,所以特别针对AVR Studio和论坛上的蜗牛触摸板,教大家在AVR Studio中使用QTouch Lib。由于本人水平有限,难免有错漏之处,欢迎大家指正。首先,确定你有下面这些东西。
1、爱特梅尔QTouch库用户指南(原名:Atmel QTouch Library User Guide)。这里建议大家使用最新版本。
http://www.atmel.com/dyn/resources/prod_documents/doc8207.pdf
2、AVR Studio 4.17 build 666
http://www.atmel.com/forms/software_download.asp?fn=dl_AvrStudio417Setup.exe(下载前需注册)
3、WinAVR-20090313
http://downloads.sourceforge.net/project/winavr/WinAVR/20090313/WinAVR-20090313-install.exe
4、Atmel QTouch Library 3.0
http://www.atmel.com/forms/software_download.asp?fn=dl_Atmel_QTouch_Libraries_3.0.exe
安装好AVR Studio、WinAVR和Atmel QTouch Library后,运行AVR Studio,新建一个工程,在左方工程名上点击右键,选择“Edit Configuration Options...”。
http://cache.amobbs.com/bbs_upload782111/files_20/ourdev_491219.JPG
在工程名上点击右键 (原文件名:1.JPG)
选择“Include Directories”,再点右上方的按钮“New(Insert)”,添加库里面包含文件的路径。默认安装的话,路径是“C:\Program Files\Atmel\Atmel QTouch Libraries 3.0\include\”。
http://cache.amobbs.com/bbs_upload782111/files_20/ourdev_491220.JPG
设置包含文件目录 (原文件名:2.JPG)
选择“Libraries”,同样点击右上方的按钮“New(Insert)”,添加库文件的路径。默认安装的话,路径是“C:\Program Files\Atmel\Atmel QTouch Libraries 3.0\megaAVR, tinyAVRand XMEGA libray\QTouch library\library files\”。此时,再在“Available Link”里选“libavr4g2-8qt-k-2rs.a”,点击“Add Library --”按钮。下文将解释为什么要选这个。
http://cache.amobbs.com/bbs_upload782111/files_20/ourdev_491221.JPG
加入库 (原文件名:3.JPG)
接下来就可以动手写代码了。
要使用QTouch Lib里的函数,必须包含touch_api.h。这个文件在默认的情况下,在“C:\Program Files\Atmel\Atmel QTouch Libraries 3.0\include\”里面。而上面我们已经把这个目录添加为包含目录了,所以就可以省去冗长的路径,直接写出文件名。
#include"touch_api.h"
然而,在包含这个目录之前,QTouch Lib还要求我们先对几个参数进行定义,定义的方法是预编译。
#define _QTOUCH_
#define QT_NUM_CHANNELS 8
#define QT_MAX_NUM_ROTORS_SLIDERS 2
#define _ROTOR_SLIDER_
#define SNSK B
#define SNS D
#define QT_DELAY_CYCLES 10
_QTOUCH_
使用QTouch技术,而非其它时,需作此声明。
QT_NUM_CHANNELS
这是感应通道的总数。应注意,这个定义必须和所选的库一致,即为8。即使你只使用了1个通道,也务必请你定义成“8”,否则将不能正常工作。
QT_MAX_NUM_ROTORS_SLIDERS 2
这是滑轮和滑条的最大总数目。这里,我们包含的库最多只支持两个,而蜗牛触摸板上也刚好只有一个滑轮和一个滑条,1+1=2。
_ROTOR_SLIDER_
若使用滑轮和滑条,需作此声明。
SNSK
这是感应按键的端口。这一端通过一个电阻连接到按键。
SNS
这是感应端口,通过一个电容后连接到SNSK。
QT_DELAY_CYCLES
延迟的时钟周期个数,需要根据工作频率设定。
再次提醒,包含touch_api.h前,需作上述定义。
定义好以后,就可以包含头文件了。这里我们用到了三个头文件。
#include"avr\io.h"
#include"avr\interrupt.h"
#include"touch_api.h"
要使用QTouch技术的话,I/O口的内部上拉电阻必须禁用。方法是让MCUCR里的PUD置位。
MCUCR|=(1<<PUD);
接下来就可以定义按键、滑轮和滑条了。定义按键,用qt_enable_key()函数。这个函数有四个参数,分别是通道编号、邻键抑制组、重校正门限百分比和滞后百分比。
按照手册上的说法,连接I/O口第1位的,为通道1,以次类推。按照这个说法,A键应为通道6。实际试验下,A键也确实为通道6,B键为通道7。原理图上的标注有误。
我们来定义A键。
qt_enable_key(CHANNEL_6, NO_AKS_GROUP, RECAL_12_5, HYST_25);
如果想同时使用A键和B键,只需在定义完A键后,继续定义B键即可。我们再来定义B键。
qt_enable_key(CHANNEL_7, NO_AKS_GROUP, RECAL_12_5, HYST_25);
定义滑轮和滑条的方法与按键一样,只是所使用的函数和参数不一样,在这里不再展开叙述,请参考官方说明文档。
定义滑轮用qt_enable_rotor()。
qt_enable_rotor(CHANNEL_3, CHANNEL_5, NO_AKS_GROUP, 10u, HYST_50, RES_2_BIT, HYST_50);
滑条用qt_enable_slider()
qt_enable_slider(CHANNEL_0, CHANNEL_2, NO_AKS_GROUP, 10u, HYST_50, RES_2_BIT, HYST_50);
这样,我们的整个定义过程就完成了。
qt_enable_key(CHANNEL_6, NO_AKS_GROUP, RECAL_12_5, HYST_25);
qt_enable_key(CHANNEL_7, NO_AKS_GROUP, RECAL_12_5, HYST_25);
qt_enable_rotor(CHANNEL_3, CHANNEL_5, NO_AKS_GROUP, 10u, HYST_50, RES_2_BIT, HYST_50);
qt_enable_slider(CHANNEL_0, CHANNEL_2, NO_AKS_GROUP, 10u, HYST_50, RES_2_BIT, HYST_50);
定义完成后,需要让各个感应器初始化,方法是使用qt_init_sensing()函数。
qt_init_sensing();
这样,感应器就可以工作了。
QTouch的感应器,是不能产生中断的,所以我们要用查询的方法来检测按键、滑轮等的状态是否发生了变化。并且这个检测过程,也是要我们手动调用函数来进行的。想让QTouch检测各个通道的状态,需要调用qt_measure_sensors()。这个函数有一个参数,是当前系统的运行时间(或曰QTouch被开启的时间,手册上未明确说明)。这个时间是以毫秒为单位的,类型是unsigned int。所以,我们还需要开启一个定时器,来计算时间。在8MHz的时钟频率下,T1采用64分频,记数125次,恰好是1毫秒。于是我们定义一个全局变量hw_time_ms。
volatile unsigned int hw_time_ms;
每次命令QTouch去检测各通道的情况时,我们就用
qt_measure_sensors(hw_time_ms);
调用完这个函数后,可以通过查询sensor_states数组(其元素为unsigned char类型)来获取各感应器当前的状态。对于滑轮和滑条,则需查询数组rotor_slider_values。sensor_states位于结构体qt_touch_status_t里,而qt_touch_status_t则位于另一个结构体qt_touch_lib_measure_data_t当中。并且,qt_touch_lib_measure_data_t不需要我们去定义,touch_api.h已经帮我们做好了这个工作了。touch_api.h里有这样的语句
typedef struct tag_qt_touch_lib_measure_data_t
{
/* measured signal on each channel*/
uint16_t channel_signals;
/* reference signal for each channel */
uint16_t channel_references;
/* state of sensors*/
qt_touch_status_t qt_touch_status;
} qt_touch_lib_measure_data_t;
……
extern qt_touch_lib_measure_data_t qt_measure_data;
所以,在实际应用中,我们只需要这样写,便能查询按键A是否被按下了。
qt_measure_data.qt_touch_status.sensor_states[0]&0x01
sensor_states这个数组,第1个元素的第一位,记录着第1个感应器的状态。比如说上面的那条语句,就可以判断第1个感应器是否被触摸了。在这里,第1个感应器是A键。若为1,则表明A键被按下了;若为0,则表明未被按下。为什么第1位就代表按键A(通道6)呢?这涉及到一个顺序问题,将在下面统一讲解。
于是,查询程序可以这样编写。下面这段代码可以实现A键被按下时,A灯亮起;松开时,A灯熄灭。
while(1)
{
qt_measure_sensors(hw_time_ms);
if(qt_measure_data.qt_touch_status.sensor_states[0]&0x01)
PORTC&=~(1<<PC0);//A灯亮
else
PORTC|=(1<<PC0);//A灯灭
}
下面来解释感应器的顺序问题。如上文所述,为什么sensor_states[0]的第1位表示着按键A,即通道6的状态呢?原来我们在定义按键等时,是这样定义的。
qt_enable_key(CHANNEL_6, NO_AKS_GROUP, RECAL_12_5, HYST_25);//A键
qt_enable_key(CHANNEL_7, NO_AKS_GROUP, RECAL_12_5, HYST_25);//B键
qt_enable_rotor(CHANNEL_3, CHANNEL_5, NO_AKS_GROUP,10u,HYST_50, RES_2_BIT, HYST_50);//滑轮
qt_enable_slider(CHANNEL_0, CHANNEL_2, NO_AKS_GROUP,10u,HYST_50, RES_2_BIT, HYST_50);//滑条
我们第1行语句,就定义了通道6,这决定了通道6为感应器1。第2行语句定义了通道7,所以通道7为感应器2。同理,通道3——通道5(整个滑轮)为感应器3,通道0——通道2(整个滑条)为感应器4。而sensor_states是8位的,它的第1位告诉我们感应器1的通道(通道6)有没有被触摸,第2位告诉我们感应器2的通道(通道7)有没有被触摸。被触摸,即为1;未被触摸,当然就是0。而通道3、4、5(即感应器3的各个通道)中的任何一个通道被触摸,都会使sensor_states的第3位为1。同样,通道0、1、2(即感应器4的各个通道)中的任何一个通道被触摸,都会使sensor_states的第4位为1。
所以,在这个定义顺序下,当A键和滑条同时被触摸,而其余未被触摸时,sensor_states的值为0bXXXX1001(“X”表示该位因无感应器而无法判断)。而当B键和滑轮同时被触摸,而其它未然时,sensor_states的值应为0bXXXX0110。
若我们改变定义的顺序,成为下面的情形时,就要发生相应的改变了。
qt_enable_key(CHANNEL_6, NO_AKS_GROUP, RECAL_12_5, HYST_25);//A键
qt_enable_rotor(CHANNEL_3, CHANNEL_5, NO_AKS_GROUP, 10u, HYST_50, RES_2_BIT, HYST_50);//滑轮
qt_enable_key(CHANNEL_7, NO_AKS_GROUP, RECAL_12_5, HYST_25);//B键
qt_enable_slider(CHANNEL_0, CHANNEL_2, NO_AKS_GROUP, 10u, HYST_50, RES_2_BIT, HYST_50);//滑条
A键为感应器1,对应sensor_states的第1位;
滑轮为感应器2,对应sensor_states的第2位;
B键位感应器3,对应sensor_states的第3位;
滑条为感应器4,对应sensor_states的第1位。
另外,若通道超过8个,则第9个通道的被触标志位,会被安排到sensor_states的第1位;第10个通道的被触标志位,会被安排到sensor_states的第2位,以次类推。
滑轮和滑条除了能通过查询sensor_states来判断是否被触摸以外,还能通过查询rotor_slider_values来获取角度、位置信息。对于滑轮,rotor_slider_values中记录的是角度;对于滑条,记录的则是被触点离边缘的距离。
rotor_slider_values是个unsigned int类型的数组。它的第1个元素,是第1个被定义的滑轮(或滑条),以次类推。比如上面的两次定义,都是先定义滑轮,再定义滑条的,所以滑轮对应着rotor_slider_values,滑条对应着rotor_slider_values。
应当注意,rotor_slider_values里各感应器的顺序,是独立于sensor_states里的顺序的,即rotor_slider_values与sensor_states无关。如果你先定义了100个按键,再去定义1个滑轮,那么这个滑轮的角度仍然应当用rotor_slider_values去查询。若你想知道这个滑轮是否被碰到了,可以用sensor_states。sensor_states到sensor_states对应的是前面100个按键。
接下来,要讲的是库文件命名规则。我们选的库是libavr4g2-8qt-k-2rs.a。其中,“libavr4g2”是ATmega88这款芯片本身决定的,通过查手册获得。“8qt”表示这个库最多支持8个通道,“2rs”表示最多支持2个滑轮或滑条(两者之和)。
到这里,讲解就全部结束了。其余没有提到的部分(邻键抑制组、重校正门限百分比等)请自行参考手册。最后送上已经调通的代码和HEX文件。工作时钟为8MHz,-0s优化方式,不进行时钟分频。
[相关下载]
代码及HEX文件ourdev_491248.zip(文件大小:6K) (原文件名:Snail Touch.zip) 好帖子,第一个顶! cool, 非常好啊刚好在展会前需要这个 qt_init_sensing()完之后出现错误提示啊
E:\Prog\Avrstudio\QTouch\default/../QTouch.c:25: undefined reference to `burst_10_DC'
请问一下这个是什么问题呢? 楼上的朋友,能说一下详细的情况吗?
AVR Studio和QTouch Lib的版本是多少呢?
最后请你把代码发上来。 我后来比较了一下好像不能设置 D和C 的口要不然就是那个提示 请查阅手册7.1.5.1节,关于端口组合问题。红色部分是不能用的。
当SNSK为D时,SNS只能是D、E、F、G。 Thank you very much! mark 又被顶起了,标题还搞成了蓝色,呵呵。
可惜我的蜗牛小板板已经死翘翘了,唉。 好贴,不顶不行啊,用的你的程序,A点不知道为什么点不亮,再仔细看看。 ding! 讲得很好! 讲得好详细谢谢了啊 讲得好详细谢谢了 受益了,谢谢,讲得好 我现在做了一个qmatrix,现在主攻防水部分,现在还没头绪的,希望楼顶指教下下。谢谢 大家好 好貼,頂一下! 行!!!!!!!!!!!!!11 好贴,楼主真是热心 mark 顶 不知道这个库能用在MEGA8上面吗?88比较难找 是不是用什么AVR芯片都可以吗楼主这是用什么芯片的呢 想试试 好教程 马克一下 我编译了一下通不过,请楼主分析一下:
a88pa -Wall -gdwarf-2 -Os -std=gnu99 -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums -MD -MP -MT main.o -MF dep/main.o.d-c../main.c
../main.c:15: warning: 'SIG_OVERFLOW1' appears to be a misspelled signal handler
avr-gcc -mmcu=atmega88pa -Wl,-Map=qtouch10.map main.o -L"C:\Program Files\atmel\Atmel_QTouch_Libraries_4.3\Generic_QTouch_Libraries\AVR_Tiny_Mega_XMega\QTouch\library_files"-lavr4g1-8qt-k-2rs-o qtouch10.elf
C:\Program Files\atmel\Atmel_QTouch_Libraries_4.3\Generic_QTouch_Libraries\AVR_Tiny_Mega_XMega\QTouch\library_files\libavr4g1-8qt-k-2rs.a(burst_0_1_00_0.o): In function `burst_0_1_00_0':
burst_0_1_00_0.c:(.text+0x28): undefined reference to `_0111010111_'
burst_0_1_00_0.c:(.text+0x54): undefined reference to `_01001010111_'
burst_0_1_00_0.c:(.text+0xf6): undefined reference to `_0101110111_'
make: *** Error 1
Build failed with 3 errors and 1 warnings...
AVR studio 4.18 sp3.
Qtouch Lib 4.3
winAVR 20100110
刚好有个项目要用到,急呀 请问 通道1~7 怎么知道他对应于单片机的那一个IO口呀??
初学 希望高手赐教!不胜感激!@ 回复【27楼】zhang1007
我编译了一下通不过,请楼主分析一下:
a88pa -wall -gdwarf-2 -os -std=gnu99 -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums -md -mp -mt main.o -mf dep/main.o.d-c../main.c
../main.c:15: warning: 'sig_overflow1' appears to be a misspelled signal handler
avr-gcc -mmcu=atmega88pa -wl,-map=qtouch10.map main.o -l"c:\program files\atmel\atmel_qtouch_libraries_4.3\generic_qtouch_libraries\avr_tiny_m......
-----------------------------------------------------------------------
请把Atmel\Atmel_QTouch_Libraries_4.3\Generic_QTouch_Libraries\AVR_Tiny_Mega_XMega\QTouch\common_files下面的qt_asm_tiny_mega.S拷贝到项目文件夹下,然后再source files里添加该.S文件,即可编译通过 thanks for sharing, and thank you very much 我正在找,就顶一下.... 先看看再说。 看不懂,winavr在这里起什么作用?avr studio又起什么作用,C程序编写、编译是在avrstudio里进行的? 请问楼主你们的抗干扰算法怎样弄的?我也弄出一个,但放在工业上就有干扰 正好有套QT600的板,多谢楼主了 mark 回复【楼主位】qlb1234清蓝冰
-----------------------------------------------------------------------
mark 又找到這個帖子了,太好了 辛苦楼主了,谢谢了 大哥,有没有完整的程序,只一个通道发出信号就行 不错这个帖子。 好...资料! 楼主能把代码重新上传下么? wtk001 发表于 2012-6-26 15:27 static/image/common/back.gif
楼主能把代码重新上传下么?
衹能儘量找一下。 qlb1234 发表于 2012-6-26 16:18 static/image/common/back.gif
衹能儘量找一下。
十分的谢谢··· qlb1234 发表于 2012-6-26 16:18 static/image/common/back.gif
衹能儘量找一下。
大侠看看这个贴子呗,我就是看你的帖子写的,不知为何不行:
http://www.amobbs.com/thread-5483517-1-1.html
IO口没有震荡啊? 突然不知道怎么往里灌程序了。我现在有个JTAGICE ,能用吗? Gorgon_Meducer 发表于 2009-10-15 10:25 static/image/common/back.gif
好帖子,第一个顶!
请教我的qtouch studio软件打开,file中就exit选项,不能新建,也不能配置,求解 leicai05 发表于 2012-8-10 11:58 static/image/common/back.gif
请教我的qtouch studio软件打开,file中就exit选项,不能新建,也不能配置,求解 ...
那个软件是配合官方的QT600评估板用的。 好貼,頂一個咧
MARK,产品需要用到了,学习 {:lol:}{:lol:}{:lol:}{:lol:}{:lol:}{:lol:} 谢谢楼主...... 太好了,一直不知道这个怎么玩 好贴,顶一个!{:lol:}
页:
[1]