📄 redcode.c
字号:
testconend2:
for(j=2;j<codelen-1;j++){//检查首帧和重复帧的数据吻合性,若数据不吻合,则认为出错
if(abs(sigdata[j]-sigdata[j+200])>200){
error();
goto testend;
}
}
//EEPROM第0页和1页存储代码的长度
tcf.tempval=keysave/CODELEN;//tcf.tempval为代码索引号,即按键值
tcf.tempval*=2;//代码长度为2字节存储,所以要索引号乘2
flashwa(tcf.bytek.hi,tcf.bytek.low);//写入EEPROM存储地址,即tcf.tempval值
tcf.tempval=codelen;
flashwb(tcf.bytek.hi,0);
flashwb(tcf.bytek.low,1);//写入代码长度
tcf.tempval=keysave;//代码数据的存储首地址
flashwa(tcf.bytek.hi,tcf.bytek.low);
for(k=0,j=0;k<codelen;k++){//页写入,一次性写入1页
tcf.tempval=sigdata[k];
if(j>60){
j=0;
flashwb(tcf.bytek.hi,0);
flashwb(tcf.bytek.low,1);
keysave+=64;
tcf.tempval=keysave;
flashwa(tcf.bytek.hi,tcf.bytek.low);//跳到下一页要先写地址
continue;
}
j+=2;
flashwb(tcf.bytek.hi,0);
flashwb(tcf.bytek.low,0);
}
flashwb(0x00,0);//代码结束时写入0x0000,其作用是再最后一次写操作后产生帧结束信号
//结束当前写操作
flashwb(0x00,1);
//若要完善程序,可在此加入校验代码
//即读取EEPROM存入的数据与缓冲区内数据比较,若数据不吻合,则重新写入
EA=0;
ledl=1;
testend:;
}
void readdata(void){//将EEPROM数据读入缓冲区,即为待发送代码
j=0;
//读取发送指令代码的长度
tcf.tempval=keysave/CODELEN;
tcf.tempval*=2;
flashd.bytek.hi=flashra(tcf.bytek.hi,tcf.bytek.low,0);
flashd.bytek.low=flashrb(1);
codelen=flashd.tempval;
//读取代码数据
tcf.tempval=keysave;
flashd.bytek.hi=flashra(tcf.bytek.hi,tcf.bytek.low,0);
flashd.bytek.low=flashrb(0);
sigdata[0]=flashd.tempval;
j+=2;
for(k=1;k<codelen;){
if(j>60){
keysave+=64;
j=0;
flashd.bytek.hi=flashrb(0);
flashd.bytek.low=flashrb(1);
sigdata[k]=flashd.tempval;
k++;
tcf.tempval=keysave;
flashd.bytek.hi=flashra(tcf.bytek.hi,tcf.bytek.low,0);
flashd.bytek.low=flashrb(0);
sigdata[k]=flashd.tempval;
k++;
j=2;
}
else{
flashd.bytek.hi=flashrb(0);
flashd.bytek.low=flashrb(0);
sigdata[k]=flashd.tempval;
k++;
j+=2;
}
}
flashd.bytek.hi=flashrb(0);
flashd.bytek.low=flashrb(1);//此作用是在最后一次读数据时,产生帧结束信号,结束读取操作
}
void pca0ini(){//T2产生38KHZ方波,要52芯片才有此功能(89c52或89s52均可),51不具备
T2MOD=0x02;
T2CON=0x00;
RCAP2H=0xff;
RCAP2L=0x6f;
TH2=RCAP2H;
TL2=RCAP2L;
}
void encode(void){//将指令发送出去
ledl=0;
ledg=1;
pca0ini();
TR2=1;
TR0=0;
sigout=0;
isodd=0;
for(k=0;k<codelen;k++){
TR0=0;
//设置定时时间,即代码中的数据值
tcf.tempval=0xffff-sigdata[k];
TH0=tcf.bytek.hi;
TL0=tcf.bytek.low;
TF0=0;
TR0=1;
if(isodd){
sigout=0;
isodd=0;
while(!TF0);
}
else{
isodd=1;
if(tcf.tempval<0xfff0){//若脉宽时间值大于0xfff0,则不发送红外,即sigout=0
sigout=1;
}
while(!TF0);
}
}
sigout=0;
ledg=0;
ledl=1;
}
void error(){
for(k=0;k<20;k++){//指示灯闪烁4秒,指示代码接收错误
ledl=0;
delay1ms(100);
ledl=1;
delay1ms(100);
}
iserror=1;//并将全局变量错误标志位iserror置1
}
uchar scankey(){//键盘扫描函数
//need to avoid dead lock
idata uchar scantmp;
ledl=1;
ledg=0;
if(iskeyboard){//键盘接口下的处理
P2&=0x03;//p2.7-p2.2为kh5-kh0,将其置0,则若有按键按下,kv5-kv0不全为1
if(keyv()==0x3f)//kv5-kv0全为1,则无按键按下,返回0
return 0;
delay1ms(20);
for(k=1;k<7;k++){//将kh5-kh0逐口扫描,确定按键值,
//若出现串键,则取khi中最大的为有效值
P2|=0xfc;//将kh5-kh0置1
scantmp=0x02<<k;//将控制位左移k位
scantmp=~scantmp;//变为反码,即控制位为0,其他位为1
P2&=scantmp;//将控制位清零
delay1ms(1);
if(keyv()!=0x3f){//读取kv5-kv0的值
//若kv5-kv0串键,取kvi中i值最大的作为有效值,有效返回值为1-6
scantmp=6*v_val-6;//kv5-kv0的值和kh5-kh0的值确定按键
scantmp+=k;
keysave=scantmp;//键盘返回值为1-36
ledl=0;
return scantmp;
}
}
return 0;//其他方式认为是无效按键,返回0
}
else{//对MCU并口接口的处理,即由另一个MCU控制其发射接收
kv5=0;//告诉MCU要取键值,对方MCU检测到kv5为0,则发送键值
delay1ms(10);//由于对方MCU可能在处理其它程序,延时一段时间确保
//对方MCU能检测到kv5为0,kv5可接到对方MCU外部事件中断口/INT0
//或/INT1上提高实时性
P2|=0xfc;//端口应遵循先置1后读取
scantmp=keyv2()<<6;//读取kv1-kv0,并将其作为数据第7位和第6位
scantmp+=P2>>2;//读取kh5-kh0,作为数据的低6位
keysave=scantmp;//数据有效值为1-255,共可处理255个按键值
P2|=0xfc;//再读一次键值
scantmp=keyv2()<<6;
scantmp+=P2>>2;
kv5=1;//读完指令将kv5置1,告知对方MCU已经获取其键值
//所以对方MCU的处理方法为保持键值电平至kv5为1为止
delay1ms(10);
if(keysave!=scantmp)//将两次读取值比较,若不一致,则返回0
return 0;
ledl=0;
return scantmp;
}
}
void decode(){//将按键值转化成EEPROM首入地址,并对红外接收处理
getkey();
if(!iskeyboard)
kv5=1;
testcon();
}
void copyflash(uint adr,uchar len){//EEPROM拷贝测试程序
//读者可将此程序稍加修改,成为拷贝sigdata数组数据到EEPROM指定地址的拷贝函数
for(k=200;k<len+200;k++){//拷入固定值
sigdata[k]=13000+k;
}
tcf.tempval=adr;
flashwa(tcf.bytek.hi,tcf.bytek.low);
for(k=200,j=0;k<200+len;k++){
tcf.tempval=sigdata[k];
if(j>60){
j=0;
flashwb(tcf.bytek.hi,0);
flashwb(tcf.bytek.low,1);
keysave+=64;
tcf.tempval=keysave;
flashwa(tcf.bytek.hi,tcf.bytek.low);
continue;
}
j+=2;
flashwb(tcf.bytek.hi,0);
flashwb(tcf.bytek.low,0);
}
flashwb(0x00,0);
flashwb(0x00,1);
}
void sendcode(){//发送红外指令
if(iskeyboard)
while(scankey()==0);//一直等待按键输入
getkey();
readdata();//将EEPROM代码数据读入外部内存缓冲区
do{
encode();
_nop_();
encode();
sigout=0;
delay1ms(400);//每隔400ms连续发送2次代码,一般红外接收器均须2次重复代码
}while(scankey()!=0);
}
uchar keyv2(){//由MCU接口模式下调用
idata uchar keytmp;
delay1ms(20);
keydown=kv0;
if(keydown)
keytmp=1;
else{
keytmp=0;
v_val=1;
}
keydown=kv1;
if(keydown)
keytmp+=2;
else
v_val=2;
return keytmp;
}
uchar keyv(){//由键盘接口模式下调用
idata uchar keytmp;
delay1ms(20);
keydown=kv0;
if(keydown)
keytmp=1;
else{
keytmp=0;
v_val=1;
}
keydown=kv1;
if(keydown)
keytmp+=2;
else
v_val=2;
keydown=kv2;
if(keydown)
keytmp+=4;
else
v_val=3;
keydown=kv3;
if(keydown)
keytmp+=8;
else
v_val=4;
keydown=kv4;
if(keydown)
keytmp+=16;
else
v_val=5;
keydown=kv5;
if(keydown)
keytmp+=32;
else
v_val=6;
return keytmp;
}
void xramcheck(){//外部内存检测程序
ramerror=0;
for(k=0;k<400;k++){
sigdata[k]=k+20;
}
for(k=0;k<400;k++){
if(sigdata[k]!=k+20){
ramerror=1;
break;
}
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -