最近在做一个红外遥控的程序,遇到一些问题,相信会有一些挑战性,我分析了好久没找到原因:需要两次按键才能够正确地执行完中断,按一次遥控器按钮,只执行到
/*if(irin==0) //(第一次按键,程序执行到此就跳出去了)
{
LPC_GPIO1->IE |= (0x1<<bitPosi);
LPC_GPIO1->IC |= (0x1<<bitPosi);
return;
} */
上面这一句就跳出去了。可以判断出是第一次按键的编码没有被正确地读取。但是奇怪的是第二次却能够正确的读取。因为读到的数据,num1=~num2是对的,并没有错码。我调试了好几天,都没有成功。原来以为是中断优先级会影响,后来又以为irin判断语句不行,结果改过来之后错误仍然依旧。
希望您能够认真看一下下面的程序,帮忙分析一下可能的原因是什么?不胜感激!
1、发送的码如下:(解码刚好是电平相反的)
file:///C:/Documents%20and%20Settings/corner/Application%20Data/Tencent/Users/605231119/QQ/WinTemp/RichOle/R(3KEI_1FF4SFGN_%7BM%7DH7ZF.jpg
2、程序如下:
#include <lpc11xx.H>
#include "timer32.h"
#define STATE 0x00000182
#define LED3 0x00000080
#define bitPosi 1
#define LED5 0x00000002
#define LED4 0x00000100
#define GPIO_BASE (0x50000000ul)
#define GPIO1MASKED_ACCESS(bit) (*(volatile unsigned long *)(GPIO_BASE + 0x10000 + (bit)))
#define PRIO_ONE 1
#define priority 1
#define irin GPIO1MASKED_ACCESS(0x01 << 3)
unsigned char addrl,addrh,num1,num2,num3,KeyValue,MaValue,l=0;
void Delay_840us()
{
LPC_TMR32B0->TCR = 0x02; /* reset timer */
LPC_SYSCON->SYSAHBCLKCTRL |= (1 << 9); /* 打开定时器模块 */
LPC_TMR32B0->IR = 1;
LPC_TMR32B0->PR = 0; /* 设置分频系数 */
LPC_TMR32B0->MCR = 4; /* 设置MR0 匹配后复位TC不产生中断 */
LPC_TMR32B0->MR0 = 10080; /* 设置中断时间 */
LPC_TMR32B0->TCR = 0x01; /* 启动定时器 */
while (LPC_TMR32B0->TCR & 0x01);
}
void Delay_2400us()
{
LPC_TMR32B0->TCR = 0x02; /* reset timer */
LPC_SYSCON->SYSAHBCLKCTRL |= (1 << 9); /* 打开定时器模块 */
LPC_TMR32B0->IR = 1;
LPC_TMR32B0->PR = 0; /* 设置分频系数 */
LPC_TMR32B0->MCR = 4; /* 设置MR0 匹配后复位TC不产生中断 */
LPC_TMR32B0->MR0 = 28800; /* 设置中断时间 */
LPC_TMR32B0->TCR = 0x01; /* 启动定时器 */
while (LPC_TMR32B0->TCR & 0x01);
}
void Delay_240ms()
{
unsigned int i,n;
for(i=0;i<100;i++)
{
for(n=0;n<1000;n++);
}
}
unsigned char GetCode()//读码:
{
unsigned char n;
unsigned char temp=0;
for(n=0;n<8;n++)
{ while(irin==0);
Delay_840us();
if(irin != 0) // 0
{ temp=(0x80|(temp>>1));
while(irin != 0);
}
else temp=(0x00|(temp>>1));// 1
}
return temp;
}
void PIOINT1_IRQHandler(void)
{
unsigned char t,n,Count=0;
LPC_GPIO1->IE &= ~(0x1<<bitPosi);
for(n=0;n<10;n++) //检测9ms开始码
{ Delay_840us();
if(irin!=0)
{ Count++;
break;
}
}
if(Count)
{
LPC_GPIO1->IE |= (0x1<<bitPosi);
// LPC_GPIO1->IC |= (0x1<<bitPosi);
return;
}
while(irin==0){};
l++;
if(irin==0) //第一次按键,程序执行到此就跳出去了。
{
LPC_GPIO1->IE |= (0x1<<bitPosi);
LPC_GPIO1->IC |= (0x1<<bitPosi);
return;
}
Delay_2400us();
addrl=GetCode();
addrh=GetCode();
num1=GetCode();
num2=GetCode();
num3=~num2;
if(num1!=num3)//错码;
{
LPC_GPIO1->IE |= (0x1<<bitPosi);
LPC_GPIO1->IC |= (0x1<<bitPosi);
return;
}
KeyValue=num2;
MaValue=addrh;
//led闪烁验证程序是否执行至此
for(t=0;t<5;t++)
{
LPC_GPIO2 ->DATA=~LED3;
Delay_240ms();
LPC_GPIO2 ->DATA|=(0x01<<7);
Delay_240ms();
}
LPC_GPIO1->IC |= (0x1<<bitPosi);
LPC_GPIO1->IE |= (0x1<<bitPosi); //开中断
}
void System_init(void)
{
LPC_GPIO2->DIR=STATE ;
LPC_GPIO1->DIR&=~(0x01<<1);
NVIC->IPR[_IP_IDX(30)] = (NVIC->IPR[_IP_IDX(30)] & ~(0xFF << _BIT_SHIFT(30))) |
(((priority << (8 - __NVIC_PRIO_BITS)) & 0xFF) << _BIT_SHIFT(30));
// Enable AHB clock to the GPIO domain.
LPC_SYSCON->SYSAHBCLKCTRL |= (1<<6);
//zyIsrSet(NVIC_PIOINT1, (unsigned int)PIOINT1_IRQHandler, PRIO_ONE);
//LPC_zyIsrSet(NVIC_PIOINT1, (unsigned long)GPIOIsr, PRIO_ONE);
// Set up NVIC when I/O pins are configured as external interrupts.
NVIC_EnableIRQ(EINT1_IRQn);
LPC_GPIO1->IS &= ~(0x1<<bitPosi);
// single or double only applies when sense is 0(edge trigger,即边缘触发).
LPC_GPIO1->IBE&= ~(0x1<<bitPosi); //IS和IBE加起来再加IEV构成下降沿触发
LPC_GPIO1->IEV|= (0x1<<bitPosi);
LPC_GPIO1->IE |= (0x1<<bitPosi); //开中断
}
int main(void)
{
System_init() ;
while(1)
{
LPC_GPIO2 ->DATA=~LED3;
Delay_240ms();
LPC_GPIO2 ->DATA|=(0x01<<8);
Delay_240ms();
LPC_GPIO2 ->DATA=~LED4;
Delay_240ms();
LPC_GPIO2 ->DATA|=(0x01<<7);
Delay_240ms();
LPC_GPIO2 ->DATA=~LED5;
Delay_240ms();
LPC_GPIO2 ->DATA|=(0x01<<7);
Delay_240ms();
}
}
烧入程序,按一次中断,led停止流水灯闪烁,亮着一颗(led3、4、5都有可能)不动,l会加一,即程序执行到l++处了。再按一次,程序继续往下完整地执行完,结尾我用led闪烁几次来提示执行到了末尾。 |