📄 saa3010解码测试.txt
字号:
引用请保留版权信息,转载请注明出处~谢谢!
********************************************************************************************
* 功 能:红外解码。
* 硬件条件:1.CPU型号:AT89C2051
* 2.晶振:12.0000MHz
* 3.MC14889 驱动4位4寸大LED
* 4.一体化红外接收头接P3.2
* 5.遥控器,型号为SAA-3010T。
*
* 下面是通过本程序解码SAA-3010T电视遥控器的键值表
* **********************************************************
* *[开关PWOER]0C [静音MUTE]0D
* *[1]01 [2]02 [3]03 [4]04
* *[5]05 [6]06 [7]07 [8]08
* *[9]09 [0]00 [单/双 _/__]0A [调谐SEARCH]1E
* *[节目PROG+]20 [节目PROG-]21 [微调+]2B [微调-]2C
* *[音量VOL+]10 [存储STORE]29 [返回RECALL]0F
* *[音量VOL- ]11 [爱好P.P]OE [定时SLEEP]26
* *[对比+]14 [色彩+]1C [亮度+]12 [录像AV]38
* *[对比-] 15 [色彩- ]1D [亮度- ]13 [电视TV]3F
* *********************************************************
*
* 作 者:JACK
* 日 期:2007年06月23号
* 博客:http://yeyudo.cn/
SAA3010.h
//==============================================================================
#ifndef __SAA3010__H__INCLUDED__
#define __SAA3010__H__INCLUDED__
//==============================================================================
#include <AT89X52.h> // MCS-51单片机
//==============================================================================
//==============================================================================
// 定义红外接收的接口(根据实际的硬件接线进行修改)
//==============================================================================
sbit SAA3010_RECV = P3^2; // INT0
// 由外部模块实现的处理函数
extern void SAA3010ProcessCommand( int remotecode );
// 初始化函数(注意:使用中断INT0及定时器T0)
void SAA3010Init();
//==============================================================================
#endif
//==============================================================================
SAA3010.c
#include "SAA3010.h"
//==============================================================================
//
// 状态机的含义:
//
// 状态S0: 初始状态
// 状态S1: 1,1 状态,在两个bit中间触发中断
// 状态S2: 0 状态
//
// S1->S1: 1个周期
// S1->S2: 1.5个周期
// S2->S2: 1个周期或2个周期
// S2->S1: 1.5个周期
//
//==============================================================================
//==============================================================================
// 时间常数(使用晶震频率为12MHz,周期为1.688ms)
//==============================================================================
#define CYCLE_1_0 0x698 // 1688us
#define CYCLE_1_5 0x9E4 // 2532
#define CYCLE_2_0 0xD30 // 3376us
#define TH_CYCLE_1_0 ( CYCLE_1_0 >> 8 )
#define TH_CYCLE_1_5 ( CYCLE_1_5 >> 8 )
#define TH_CYCLE_2_0 ( CYCLE_2_0 >> 8 )
// 用于解码的变量
unsigned int SAA3010RecvCode = 0; // 保存解码数值(1个控制位 5个地址位 6个命令位)
unsigned char SAA3010BitCount = 0; // 记录已经解码的位数
unsigned char SAA3010State = 0; // 初始状态
// 初始化中断及定时器
void SAA3010Init()
{
// 允许中断
EA = 1;
// 定时器0
TMOD = 0x01; // T0工作于方式1,即16位定时器
ET0 = 1; // 关定时器0中断允许
TR0 = 1; // 关闭定时器0
TH0 = 0;
TL0 = 0;
// 外部中断源INT0
EX0 = 1; // 允许外部中断源INT0
PX0 = 1; // 外部中断源为高优先级
IT0 = 1; // 边缘触发
// 初始化变量
SAA3010BitCount = 0;
SAA3010RecvCode = 0;
SAA3010State = 0;
}
// 定时器T0的中断处理函数
void SAA3010Timer0(void) interrupt 1
{
// 出现了超时
if( SAA3010BitCount == 13 )
{
if( SAA3010State == 1 || // 1,1
SAA3010State == 2 ) // 0,1
{
SAA3010BitCount ++;
SAA3010RecvCode = SAA3010RecvCode << 1;
SAA3010RecvCode = SAA3010RecvCode + 1;
}
}
// 检查是否有合理数据
if( SAA3010BitCount == 14 )
{
// 停止中断0
EX0 = 0;
// 处理遥控命令
SAA3010ProcessCommand((~SAA3010RecvCode) & 0x0FFF );
}
// 重新初始化初始化
SAA3010BitCount = 0;
SAA3010State = 0;
// 启用中断
EX0 = 1;
}
// 外部中断0的处理函数
void SAA3010Int0(void) interrupt 0
{
// 保存计数器的高位,作为判断周期长短的依据
unsigned char HighTick = TH0;
// 重置计数器
TH0=0;TL0=0;TR0=1;ET0=1;
// 状态转移图
switch( SAA3010State )
{
case 0: // 第一个起始位
SAA3010State = 2;
SAA3010BitCount = 1;
SAA3010RecvCode = 0;
break;
case 1: // 状态1
if( HighTick == TH_CYCLE_1_0 ) // S1->S1
{
SAA3010State = 1;
SAA3010BitCount++;
SAA3010RecvCode = SAA3010RecvCode << 1;
SAA3010RecvCode = SAA3010RecvCode + 1;
}
else if( HighTick == TH_CYCLE_1_5 ) // S1->S2 ( 1,1,0 )
{
SAA3010State = 2;
SAA3010BitCount = SAA3010BitCount+2;
SAA3010RecvCode = SAA3010RecvCode << 1;
SAA3010RecvCode = SAA3010RecvCode + 1;
SAA3010RecvCode = SAA3010RecvCode << 1;
}
else // 错误状态
{
SAA3010BitCount = 0;
SAA3010State = 0;
}
break;
case 2: // 状态2
if( HighTick == TH_CYCLE_1_0 ) // S2->S2
{
SAA3010State = 2;
SAA3010BitCount++;
SAA3010RecvCode = SAA3010RecvCode << 1;
}
else if( HighTick == TH_CYCLE_1_5 ) // S2->S1
{
SAA3010State = 1;
SAA3010BitCount++;
SAA3010RecvCode = SAA3010RecvCode << 1;
SAA3010RecvCode = SAA3010RecvCode + 1;
}
else if( HighTick == TH_CYCLE_2_0 ) // S2->S2
{
// 0->1->0
SAA3010State = 2;
SAA3010BitCount = SAA3010BitCount+2;
SAA3010RecvCode = SAA3010RecvCode << 1;
SAA3010RecvCode = SAA3010RecvCode + 1;
SAA3010RecvCode = SAA3010RecvCode << 1;
}
else // 错误状态
{
SAA3010BitCount = 0;
SAA3010State = 0;
}
break;
}
}
Main.c
#include <DS1302.h>
#include <MC14489.h>
void Timer0_Init();
void ShowTime();
void DelayMs(unsigned int a);
unsigned char SwitchFlag = 0;
// 延时1ms
void DelayMs(unsigned int a)
{
unsigned char i = 0;
while( --a != 0)
{
for(i = 0; i < 125; i++); //一个 ; 表示空语句,CPU空转。
} //i 从0加到125,CPU大概就耗时1毫秒
}
// 显示时间
void ShowTime()
{
// 从DS1302读取时间信息
unsigned char hour = CLOCK_READ_TIME_PART( TIME_PART_HOUR ); // 小时
unsigned char minute = CLOCK_READ_TIME_PART( TIME_PART_MINUTE);// 分钟
unsigned char second = CLOCK_READ_TIME_PART( TIME_PART_SECOND);// 秒
unsigned char buffer[3];
buffer[1] = minute;
buffer[2] = second;
// 显示到MC14489
// 显示分钟和秒钟
if( SwitchFlag == 0 )
{
SwitchFlag = 1;
buffer[0] = 0x80;
}
else
{
SwitchFlag = 0;
buffer[0] = 0xB0;
}
MC14489Write( buffer,3 );
}
// 处理红外命令
void SAA3010ProcessCommand(int remotecode)
{
unsigned char buffer[3];
buffer[0] = 0x80;
buffer[1] = (unsigned char)((remotecode >> 8)& 0xFF);
buffer[2] = (unsigned char)(remotecode & 0xFF);
MC14489WriteCmd( 0x01 );
MC14489Write( buffer,3 );
}
// 主函数
void main()
{
// 初始化红外接收设备
SAA3010Init();
// 初始化MC14489
MC14489WriteCmd( 0x01 ); // 显示器处于正常工作状态
// CLOCK_INIT();
while( 1 )
{
// MC14489WriteCmd( 0x01 );
// ShowTime();
DelayMs(495);
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -