韦东山老师课后作业——ZJ2440裸机模块整合(4):中断信息处理

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/W1107101310/article/details/80495706

简介:

    本文主要介绍完成作业时在触摸屏中断,ADC中断以及IIC中断中碰到的一些问题。

中断简介:

    在没有做这个作业之前我一直没有写过子中断的程序,直到这个作业我使用了ADC中断和触摸屏子中断。而这两个中断的结合使用也让我学到了很多。知道了如何对子中断进行操作,如果判断一个中断是触摸屏中断还是ADC中断。这些都是我在这个作业中学到了。所以也要感谢这次的作业让我认识了更多,了解了更多。

    下面我们来讲解这两个中断,我们先看下面的两幅图:



    从上面的中断处理框图和SRCPND映射图中,我们可以看出不管是触摸屏子中断还是ADC中断,他们在触发时都会使SRCPND位中对应的ADC位(bit[31])设置为高电平。同时在中断触发函数中我们只能注册一个中断处理函数。因为在中断偏移寄存器(INFOFFSET)中只有ADC位(bit[31]),而并无触摸屏的位。

    这里我们遇到了第一个问题:如何来确定我们是触摸屏触发中断还是ADC触发中断?

    这就要通过SUBSRCPND来判断了。不管是触摸屏触发中断还是ADC触发中断,SRCPND位都会被设为高电平。但是SUBSRCPND就不一样了,只有当触摸屏触发时,SUBSRCPND中INT_TC位(bit[9])被设为高电平。而当ADC触发时该位没有变化。所以我们使用该位来确定是触摸屏触发还是ADC触发。这样我们关于ADC和触摸屏的中断程序就可以写出来了。

触摸屏与ADC中断程序为:

void ADCIntHandle(void)
{

	static int cnt;
	static int x[4],y[4];
	int i;
	if(SUBSRCPND & (BIT_SUB_TC)){  //用于判断是否是触摸屏中断,如果不是触摸中断,那么就是ADC中断了
		SRCPND |= (1<<31);
		INTPND |= (1<<31);
		SUBSRCPND |= (1<<9);		
		if(ADCDAT0 & (1<<15)){
			printf("TC up!!!!!!!!!!!\n");
			enter_wait_pen_down_mode();
		}else{
		/* 4.4 在中断中启动ADC,转化XY坐标 */
			printf("TC down!!!!!!!!!!\n");
			while(!ADCDAT0 & (1<<15));
			enter_measure_xy_mode();
			start_adc();
		}	
	}else{  //此时为ADC中断
		SRCPND |= (1<<31);
		INTPND |= (1<<31);
		x[cnt] = ((ADCDAT0)&0x3ff);
		y[cnt] = ((ADCDAT1)&0x3ff);
		draw_x = ((ADCDAT0)&0x3ff);
		draw_y = ((ADCDAT1)&0x3ff);
		cnt++;
		if(ADCDAT0 & (1<<15)){
			printf("ADC up!!!!!!!!!!!!\n");
			enter_wait_pen_down_mode();
			if(cnt >= 4){  //注意这里一定要写为大于等于4
				ADC_x = x[2];
				ADC_y = y[2];		
				for(i=0;i<4;i++){
					x[i]=0;
					y[i]=0;
				}

				printf("adc_irq x= %d, y=%d \n",ADC_x,ADC_y);	
				flag_up = 1;
				cnt = 0;
			}
		}else{
			printf("ADC down!!!!!!!!!!!!\n");			
			enter_wait_pen_up_mode();
		}	

	}

}

    我觉得这里有一个很值得注意的地方是:if(cnt >= 4) 。为什么会对这个地方这么重视?是因为我在这里吃了很大的亏。所以希望日后的自己和看这篇文章的同学以后不要犯同样的错误。我以前的判断是:if(cnt == 4),但是我有时候发现程序会在跑着跑着的时候就没有反应了。我都不知道是什么原因,后来我慢慢看程序,才发现是这里的错误。如果这里用等于4来判断是否进行值确认操作。但是有时候由于一些中断原因cnt的值会超过4,这样cnt的值会越来越大,而我们的程序却回不到我们当初的设想。而当改为>=4后这个问题就迎刃而解了。所以希望大家以后不要和我一样犯这样的错误。 

IIC中断:

    触摸屏和ADC中断写好之后我们就要写另一个中断IIC中断了。由于IIC中断相对于上面的中断就简单一些了,因为他不用对子中断进行判断。所以他只要在中断初始化函数中将自己的处理函数注册进去,然后在中断处理中调用自己的处理函数就好了。程序为:

void init_irq(void)
{
    int i = 0;
    for (i = 0; i < sizeof(isr_handle_array) / sizeof(isr_handle_array[0]); i++)
    {
        isr_handle_array[i] = Dummy_isr;
    }

    INTMOD = 0x0;	      // 所有中断都设为IRQ模式
    INTMSK = BIT_ALLMSK;  // 先屏蔽所有中断

	isr_handle_array[ISR_ADC_OFT]  = ADCIntHandle;
	isr_handle_array[ISR_IIC_OFT]  = I2CIntHandle;
}

void IRQ_Handle(void)
{
    unsigned long oft = INTOFFSET;
    /* 调用中断服务程序 */
    isr_handle_array[oft]();
}
而关于IIC裸机操作OLED的介绍我在文章: 嵌入式Linux——IIC总线驱动(1):2440裸板驱动OLED中已经做了详细的介绍。


猜你喜欢

转载自blog.csdn.net/W1107101310/article/details/80495706