51单片机NEC协议状态机编程示例
时间: 2023-10-04 16:10:51 浏览: 100
51 单片机编程实例
以下是一个基于51单片机的NEC协议状态机编程示例:
```c
#include <reg51.h>
#define IR_IN P3_2
// NEC协议定义的高低电平时间
#define T1 560
#define T2 1690
#define T3 45000
#define T4 22500
// 状态定义
#define STATE_IDLE 0
#define STATE_START 1
#define STATE_BIT 2
// 全局变量
unsigned char ir_state = STATE_IDLE; // 初始化为IDLE状态
unsigned char ir_code = 0;
unsigned char ir_count = 0;
void delay_us(unsigned int us)
{
while(us--)
{
_nop_();
}
}
// NEC协议解码函数
void ir_decode(unsigned char code)
{
// 解码操作
}
void ir_timer_handler()
{
static unsigned int ir_timer_count = 0;
static unsigned char ir_last_state = 0;
// 读取当前状态
unsigned char ir_cur_state = IR_IN;
// 状态转移
switch (ir_state)
{
case STATE_IDLE:
if (ir_cur_state == 0 && ir_last_state == 1)
{
ir_timer_count = 0;
ir_state = STATE_START;
}
break;
case STATE_START:
if (ir_cur_state == 1 && ir_last_state == 0)
{
if (ir_timer_count >= T1 && ir_timer_count <= T2)
{
ir_code = 0;
ir_count = 0;
ir_state = STATE_BIT;
}
else
{
ir_state = STATE_IDLE;
}
}
break;
case STATE_BIT:
if (ir_cur_state == 1 && ir_last_state == 0)
{
if (ir_timer_count >= T1 && ir_timer_count <= T2)
{
ir_code >>= 1;
if (ir_timer_count > T2 - T1)
{
ir_code |= 0x80;
}
ir_count++;
if (ir_count >= 8)
{
ir_decode(ir_code);
ir_state = STATE_IDLE;
}
}
else
{
ir_state = STATE_IDLE;
}
}
break;
default:
ir_state = STATE_IDLE;
break;
}
// 更新last_state并清零计数器
ir_last_state = ir_cur_state;
ir_timer_count = 0;
}
void main()
{
TMOD = 0x01; // 定时器0工作在模式1
TH0 = 0xFC; // 定时器初值
TL0 = 0x67;
ET0 = 1; // 打开定时器0中断
EA = 1; // 打开总中断
while(1)
{
// 等待中断处理
}
}
// 定时器0中断
void timer0_isr() interrupt 1
{
TH0 = 0xFC; // 定时器初值
TL0 = 0x67;
ir_timer_handler(); // 处理红外信号
}
```
以上代码通过定时器0中断处理来实现NEC协议的红外信号解码。整个解码过程是通过状态机实现的,分为三个状态:IDLE、START和BIT。在IDLE状态下,等待红外信号开始;在START状态下,检测红外信号开始;在BIT状态下,解码红外信号。在定时器中断处理函数中,会根据当前状态和红外信号的高低电平时间来进行状态转移和解码操作。
阅读全文