- 打卡等级:偶尔看看II
- 打卡总天数:25
- 最近打卡:2025-03-25 22:26:27
注册会员
- 积分
- 174
|
以下为程序代码:#include <intrins.h>
#include <STC8G.h>
#define uchar unsigned char
#define uint unsigned int
sbit RF = P3^2; //信号输入
sbit WE = P3^0; //指示灯
sbit set = P3^3; //学习键
sbit D0 = P5^4; //机械手正极
sbit D2 = P5^5; //机械手负极
bit decode_ok; //解码成功
bit rf_ok; //收到有效数据
bit study; //学习标志
bit jmnx; //编码类型 0是2262,1是1527
uchar da1527[2][3]; //解码过程中临时数组
uchar key_d; //遥控器按键码
uchar short_k; //窄脉冲宽度
//uchar temp=0; //延时时间值S
uchar idata key_number[60]; //遥控器编码数组,存放10个遥控器
void delay_1ms(uint x) //1毫秒延时
{
uchar b,c;
for(x;x>0;x--)
{
for(b=3;b>0;b--)
{
for(c=150;c>0;c--);
}
}
}
void delay(uint ms)//
{
while(ms--)
{
ms++;
ms++;
ms--;
ms--;
}
}
//====================================================
/////////片内EEPROM读写驱动程序///////////////////////////
//====================================================
void IAP_Disable() //关闭IAP
{
//关闭IAP 功能, 清相关的特殊功能寄存器,使CPU 处于安全状态,
//一次连续的IAP 操作完成之后建议关闭IAP 功能,不需要每次都关
IAP_CONTR = 0; //关闭IAP 功能
IAP_CMD = 0; //清命令寄存器,使命令寄存器无命令,此句可不用
IAP_TRIG = 0; //清命令触发寄存器,使命令触发寄存器无触发,此句可不用
IAP_ADDRH = 0x80;
IAP_ADDRL = 0;
}//
//读一字节,调用前需打开IAP 功能,入口:DPTR = 字节地址,返回:A = 读出字节
uchar read_add(uint addr) //读EEPROM
{
uchar dat;
IAP_CONTR = 0x80; //打开IAP 功能, 设置Flash 操作等待时间
IAP_TPS = 12;
IAP_CMD = 0x01; //IAP/ISP/EEPROM 字节读命令
IAP_ADDRH = addr>>8; //设置目标单元地址的高8 位地址
IAP_ADDRL = addr; //设置目标单元地址的低8 位地址
EA = 0;
IAP_TRIG = 0x5a; //先送 46h,再送B9h 到ISP/IAP 触发寄存器,每次都需如此
IAP_TRIG = 0xa5; //送完 B9h 后,ISP/IAP 命令立即被触发起动
_nop_();
IAP_DATA = dat;
EA = 1;
IAP_Disable(); //关闭IAP 功能, 清相关的特殊功能寄存器,使CPU 处于安全状态,
//一次连续的IAP 操作完成之后建议关闭IAP 功能,不需要每次都关
return dat;
}//------------------------------------------------------------------------------
//字节编程,调用前需打开IAP 功能,入口:DPTR = 字节地址, A= 须编程字节的数据
void write_add(uint addr,uchar ch) //直接写EEPROM
{
IAP_CONTR = 0x80; //打开 IAP 功能, 设置Flash 操作等待时间
IAP_TPS = 12;
IAP_CMD = 0x02; //IAP/ISP/EEPROM 字节编程命令
IAP_ADDRH = addr>>8; //设置目标单元地址的高8 位地址
IAP_ADDRL = addr; //设置目标单元地址的低8 位地址
IAP_DATA = ch; //要编程的数据先送进IAP_DATA 寄存器
EA = 0;
IAP_TRIG = 0x5a; //先送 46h,再送B9h 到ISP/IAP 触发寄存器,每次都需如此
IAP_TRIG = 0xa5; //送完 B9h 后,ISP/IAP 命令立即被触发起动
_nop_();
EA = 1;
IAP_Disable(); //关闭IAP 功能, 清相关的特殊功能寄存器,使CPU 处于安全状态,
//一次连续的IAP 操作完成之后建议关闭IAP 功能,不需要每次都关
}//------------------------------------------------------------------------------
//擦除扇区, 入口:DPTR = 扇区地址
void Sector_Erase(uint addr) //扇区擦除
{
IAP_CONTR = 0x80; //打开IAP 功能, 设置Flash 操作等待时间
IAP_TPS = 12;
IAP_CMD = 0x03; //IAP/ISP/EEPROM 扇区擦除命令
IAP_ADDRH =addr>>8; //设置目标单元地址的高8 位地址
IAP_ADDRL =addr; //设置目标单元地址的低8 位地址
EA = 0;
IAP_TRIG = 0x5a; //先送 46h,再送B9h 到ISP/IAP 触发寄存器,每次都需如此
IAP_TRIG = 0xa5; //送完 B9h 后,ISP/IAP 命令立即被触发起动
_nop_();
EA = 1;
IAP_Disable();
}//------------------------------------------------------------------------------
void key_buffer() //把遥控器码从 EEPROM 复制到DATA
{
uchar n;
for(n=0;n<60;n++)
{
key_number[n]=read_add(0x0000+n);
}
}
void KEY_study() //遥控器学习
{
uchar num_rf;
uint d_num;
if(study)
{
rf_ok=0;
d_num=0;
while(!rf_ok)
{
RF_decode();
d_num++;
if(d_num>50000) break;
}
d_num=0;
if(rf_ok==1)
{
num_rf=key_number[0];
if(num_rf>60){num_rf=0;} //
key_number[num_rf*3+1]=da1527[0][0];
key_number[num_rf*3+2]=da1527[0][1];
key_number[num_rf*3+3]=da1527[0][2];
key_number[0]=num_rf+1;
Sector_Erase(0x0000);
for(num_rf=0;num_rf<60;num_rf++)
{
write_add(0x0000+num_rf,key_number[num_rf]);
}
rf_ok=0;
WE=1; //学习成功
}
else
{
rf_ok=0;
for(num_rf=0;num_rf<8 ;num_rf++) //操作超时
{
WE=!WE;
delay_1ms(100);
}
WE=1;
}
d_num=0;
study=0;
}
}
void system_res() //系统清零
{
Sector_Erase(0x0000);
write_add(0x0000,0x00);
key_buffer();
}
void set_scan() //判断学习键状态
{
uint h=0;
while(!set)
{
if(h>8)
{
D0=~D0;D2=~D2;
WE=1;
delay_1ms(1000);
WE=0;
while(!set)
{
delay_1ms(50);
h++;
if(h>240)
{
study=1;
h=0;
WE=1;
while(!set)
{
delay_1ms(50);
h++;
if(h>360)
{
study=0;
h=0;
system_res();
WE=1;
delay_1ms(1500);
WE=0;
delay_1ms(1500);
WE=1;
delay_1ms(1500);
WE=0;
delay_1ms(1500);
WE=1;
delay_1ms(1500);
WE=0;
while(!set);
}
}
}
}
}
delay_1ms(50);
h++;
}
if(study)
{
KEY_study();
}
}
void system_start() //上电初始化
{
P3=0xff;
P3M1&=~(1<<0);
P3M0|=(1<<0); //设置 P3.0为推挽输出
P5M1&=~(1<<4);
P5M0|=(1<<4); //设置 P5.4为推挽输出
P5M1&=~(1<<5);
P5M0|=(1<<5); //设置 P5.5为推挽输出
//P1=0xff;
key_buffer();
D0=0;D2=1;WE=0;
}
void main()
{
system_start();
while(1)
{
RF_decode();
set_scan();
}
}
|
|