在上一节代码基础上继续编写
一 006节-触摸屏编程_ADC中断(把XY坐标读取出来)
本节目的:检测到触摸屏按下的时候需要启动ADC中断读取xy位置坐标。
//相对于上一节代码本函数修改了ADCDLY寄存器值
//因为之前配置值过小,触摸屏的电压输出尚未稳定,所以需要增大自按下触摸笔到产生触摸屏中断的时间
void adc_ts_reg_init(void)
{
...
/* 按下触摸屏, 延时一会再发出TC中断
* 延时时间 = ADCDLY * 晶振周期 = ADCDLY * 1 / 12000000 = 5ms
*/
ADCDLY = 60000;
}
//中断服务程序
void AdcTsIntHandle(int irq)
{
if (SUBSRCPND & (1<<TC_INT_BIT)) /* 如果是触摸屏中断 */
Isr_Tc();
if (SUBSRCPND & (1<<ADC_INT_BIT)) /* ADC中断 */
Isr_Adc();
SUBSRCPND = (1<<TC_INT_BIT) | (1<<ADC_INT_BIT);
}
//***********************************
//中断服务程序调用子函数1
void Isr_Adc(void)
{
int x = ADCDAT0;//x方向位置坐标
int y = ADCDAT1;//y方向位置坐标
if (!(x & (1<<15))) /* 如果仍然按下才打印 */
{
x &= 0x3ff;
y &= 0x3ff;
printf("x = %08d, y = %08d\n\r", x, y);
}
//此时已经按下,需要等待触摸笔松开
enter_wait_pen_up_mode();
}
//***********************************
//中断服务程序调用子函数2
void Isr_Tc(void)
{
if (ADCDAT0 & (1<<15))
{
//printf("pen up\n\r");
enter_wait_pen_down_mode();
}
else
{
//printf("pen down\n\r");
/* 进入"自动测量"模式 */
enter_auto_measure_mode();
/* 启动ADC */
ADCCON |= (1<<0);//开始ADC转换
}
}
/* 进入"自动测量"模式 */
/* ADCTSC's bits */
#define WAIT_PEN_DOWN (0<<8)
#define WAIT_PEN_UP (1<<8)
#define YM_ENABLE (1<<7)
#define YM_DISABLE (0<<7)
#define YP_ENABLE (0<<6)
#define YP_DISABLE (1<<6)
#define XM_ENABLE (1<<5)
#define XM_DISABLE (0<<5)
#define XP_ENABLE (0<<4)
#define XP_DISABLE (1<<4)
#define PULLUP_ENABLE (0<<3)
#define PULLUP_DISABLE (1<<3)
#define AUTO_PST (1<<2)//自动顺序转换xy坐标
#define WAIT_INT_MODE (0b11)//等待中断
#define NO_OPR_MODE (0)
void enter_auto_measure_mode(void)
{
ADCTSC = AUTO_PST | NO_OPR_MODE;
}
二 007节-触摸屏编程_定时器中断
- 上一节程序编码思路:触摸屏按下的时刻 -> 触摸屏按下中断 -> 配置开始ADC测量中断 -> 等待触摸屏松开
- 缺点:如果触摸屏一直按下就一直卡死在等待触摸屏松开,不会一直驱动adc进行数据转换。
- 解决:添加定时器中断,若触摸屏被按下,定时启动ADC转换和转换中断。
1 定时器中断函数改进
注意:这部分裸机代码设计思路之前没有接触过,这里仔细学习一下
首先,科普一下函数指针的用法:函数指针是指向函数的指针变量,他的本质是一个指针变量。
int (*f) (int x); /* 声明一个函数指针 */
f=func; /* 将func函数的首地址赋给指针f */
其次,定义一个函数指针类型:
typedef void(*variable)();/*声明一个void(*)() 类型的函数指针variable。*/
参见typedef void(*Func)(void) 用法
//本函数是注册的定时器中断服务程序
void timer_irq(void)
{
int i;
//这里比较新鲜:作者计划按照调用几个函数进行执行,使用了函数数组的形式
//TIMER_NUM:最大能够调用函数数量,这里是一个宏
for (i = 0; i < TIMER_NUM; i++)
{
//timer_array是一个结构体数组,fp是一个函数指针
//这里依次定义结构体数组中的每一个函数指针对应的函数
if (timer_array[i].fp)//只要指针非空,则对应的函数被调用;否则,继续调用下一个
{
timer_array[i].fp();
}
}
}
//定义一个函数指针类型
typedef void(*timer_func)(void);
//定义一个结构体类型
typedef struct timer_desc {
char *name;
timer_func fp;
}timer_desc;
//定义一个结构体数组
timer_desc timer_array[TIMER_NUM];
//在结构体数组中添加某个函数
//name:可以理解为函数代号;fp:等待加入的函数指针
int register_timer(char *name, timer_func fp)
{
int i;
for (i = 0; i < TIMER_NUM; i++)
{
//如果这个位置的函数为空,则添加进来;
//否则,继续向后遍历。
if (!timer_array[i].fp)
{
timer_array[i].name = name;
timer_array[i].fp = fp;
return 0;
}
}
return -1;
}
//在结构体数组中去掉某个函数
//name:可以理解为函数代号;
void unregister_timer(char *name)
{
int i;
//遍历结构体数组
for (i = 0; i < TIMER_NUM; i++)
{
//如果遍历到了一个数组中成员的名字与输入参数一致,
//把对应的成员参数置为空!
if (!strcmp(timer_array[i].name, name))
{
timer_array[i].name = NULL;
timer_array[i].fp = NULL;
return 0;
}
}
return -1;
}