本次使用MSP430F149这款芯片,因为最近正在用。
MSP430中断向量地址使用16位地址,其中GPIO中断只有P1口和P2口有中断功能,并且P1口中断和P2口中断是多中断源公用一个中断入口,如果使用了P1口或者P2口的多个引脚作为中断输入,需要在中断服务函数中判断具体的中断引脚。
P1口和P2口使用中断方式,比较简单。
以上波形是一体化红外接收头1838接收后,逻辑分析仪捕获到的5个按键的波形。红外信号无效时,1838输出高电平,当有按键按下时,会发射红外编码信号,根据图中可以看到比较有规则的脉冲波形,有12个周期。“0”和“1”的周期是一样的,大概1.27ms,区别是代表“0”和代表“1”的高电平和低电平持续时间正好相反。根据这个特性,再结合MSP430 gpio的下降沿中断作为接收开始信号,就可以得到最后的结果,从而判断遥控器按下的是哪个按键。
#define CPU_F ((double)8000000)
#define delay_us(x) __delay_cycles((long)(CPU_F*(double)x/1000000.0))
#define delay_ms(x) __delay_cycles((long)(CPU_F*(double)x/1000.0))
#define IR_PIN 2 //这里使用P1.2
#define bit(X) (1<<X)
#define READ_P1_GPIO_PIN_INVERT(GPIO_PIN) ( (P1IN & bit(GPIO_PIN)) ^ bit(GPIO_PIN) ) //低电平有效转换成高电平有效
#define READ_P1_GPIO_PIN(GPIO_PIN) (P1IN & bit(GPIO_PIN))
#define READ_IR() READ_P1_GPIO_PIN_INVERT(IR_PIN)
/**
* @description:开中断
* @return {none}
*/
void ir_irq_enable()
{
P1IE |= (bit(IR_PIN)); // 1:ENABLE
P1IFG &= ~(bit(IR_PIN));
}
/**
* @description:关中断
* @return {none}
*/
void ir_irq_disable()
{
P1IE &= ~(bit(IR_PIN)); // 0:DISABLE
}
/**
* @description:红外接收头初始化
* @return {none}
*/
void ir_init(void)
{
P1DIR &= ~(bit(IR_PIN)); // 0:INPUT
P1IES |= (bit(IR_PIN)); // FALLING EDGE
ir_irq_enable();
}
volatile static uint8_t ir_cnt;
volatile uint16_t ir_code;//保存红外遥控器键值
/**
* @description:红外接收中断服务函数
* @return {none}
*/
#if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__)
#pragma vector = PORT1_VECTOR
__interrupt
#elif defined(__GNUC__)
__attribute__((interrupt(PORT1_VECTOR)))
#endif
void exti_ISR(void)
{
uint16_t t = 0;
//红外中断
if (P1IFG & bit(IR_PIN))
{
P1IFG &= ~(bit(IR_PIN));
ir_irq_disable();
ir_cnt = 0;
ir_code = 0;
while(ir_cnt <=12)
{
delay_us(600);
if(READ_IR())
{
ir_code |= (1<<ir_cnt);
while(READ_IR());
}
if(ir_cnt == 12)
{break;}
else
{
ir_cnt++;
while (READ_IR() == 0)
{
delay_us(5);
if(t++ >500)
{
ir_cnt = 13;
break;
}
}
t = 0;
}
}
delay_ms(10);
LED_OFF();
ir_irq_enable();
}
}