?? redcode.c
字號:
testconend2:
for(j=2;j<codelen-1;j++){//檢查首幀和重復(fù)幀的數(shù)據(jù)吻合性,若數(shù)據(jù)不吻合,則認(rèn)為出錯(cuò)
if(abs(sigdata[j]-sigdata[j+200])>200){
error();
goto testend;
}
}
//EEPROM第0頁和1頁存儲(chǔ)代碼的長度
tcf.tempval=keysave/CODELEN;//tcf.tempval為代碼索引號,即按鍵值
tcf.tempval*=2;//代碼長度為2字節(jié)存儲(chǔ),所以要索引號乘2
flashwa(tcf.bytek.hi,tcf.bytek.low);//寫入EEPROM存儲(chǔ)地址,即tcf.tempval值
tcf.tempval=codelen;
flashwb(tcf.bytek.hi,0);
flashwb(tcf.bytek.low,1);//寫入代碼長度
tcf.tempval=keysave;//代碼數(shù)據(jù)的存儲(chǔ)首地址
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);//代碼結(jié)束時(shí)寫入0x0000,其作用是再最后一次寫操作后產(chǎn)生幀結(jié)束信號
//結(jié)束當(dāng)前寫操作
flashwb(0x00,1);
//若要完善程序,可在此加入校驗(yàn)代碼
//即讀取EEPROM存入的數(shù)據(jù)與緩沖區(qū)內(nèi)數(shù)據(jù)比較,若數(shù)據(jù)不吻合,則重新寫入
EA=0;
ledl=1;
testend:;
}
void readdata(void){//將EEPROM數(shù)據(jù)讀入緩沖區(qū),即為待發(fā)送代碼
j=0;
//讀取發(fā)送指令代碼的長度
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;
//讀取代碼數(shù)據(jù)
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);//此作用是在最后一次讀數(shù)據(jù)時(shí),產(chǎn)生幀結(jié)束信號,結(jié)束讀取操作
}
void pca0ini(){//T2產(chǎn)生38KHZ方波,要52芯片才有此功能(89c52或89s52均可),51不具備
T2MOD=0x02;
T2CON=0x00;
RCAP2H=0xff;
RCAP2L=0x6f;
TH2=RCAP2H;
TL2=RCAP2L;
}
void encode(void){//將指令發(fā)送出去
ledl=0;
ledg=1;
pca0ini();
TR2=1;
TR0=0;
sigout=0;
isodd=0;
for(k=0;k<codelen;k++){
TR0=0;
//設(shè)置定時(shí)時(shí)間,即代碼中的數(shù)據(jù)值
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){//若脈寬時(shí)間值大于0xfff0,則不發(fā)送紅外,即sigout=0
sigout=1;
}
while(!TF0);
}
}
sigout=0;
ledg=0;
ledl=1;
}
void error(){
for(k=0;k<20;k++){//指示燈閃爍4秒,指示代碼接收錯(cuò)誤
ledl=0;
delay1ms(100);
ledl=1;
delay1ms(100);
}
iserror=1;//并將全局變量錯(cuò)誤標(biāo)志位iserror置1
}
uchar scankey(){//鍵盤掃描函數(shù)
//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逐口掃描,確定按鍵值,
//若出現(xiàn)串鍵,則取khi中最大的為有效值
P2|=0xfc;//將kh5-kh0置1
scantmp=0x02<<k;//將控制位左移k位
scantmp=~scantmp;//變?yōu)榉创a,即控制位為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;//其他方式認(rèn)為是無效按鍵,返回0
}
else{//對MCU并口接口的處理,即由另一個(gè)MCU控制其發(fā)射接收
kv5=0;//告訴MCU要取鍵值,對方MCU檢測到kv5為0,則發(fā)送鍵值
delay1ms(10);//由于對方MCU可能在處理其它程序,延時(shí)一段時(shí)間確保
//對方MCU能檢測到kv5為0,kv5可接到對方MCU外部事件中斷口/INT0
//或/INT1上提高實(shí)時(shí)性
P2|=0xfc;//端口應(yīng)遵循先置1后讀取
scantmp=keyv2()<<6;//讀取kv1-kv0,并將其作為數(shù)據(jù)第7位和第6位
scantmp+=P2>>2;//讀取kh5-kh0,作為數(shù)據(jù)的低6位
keysave=scantmp;//數(shù)據(jù)有效值為1-255,共可處理255個(gè)按鍵值
P2|=0xfc;//再讀一次鍵值
scantmp=keyv2()<<6;
scantmp+=P2>>2;
kv5=1;//讀完指令將kv5置1,告知對方MCU已經(jīng)獲取其鍵值
//所以對方MCU的處理方法為保持鍵值電平至kv5為1為止
delay1ms(10);
if(keysave!=scantmp)//將兩次讀取值比較,若不一致,則返回0
return 0;
ledl=0;
return scantmp;
}
}
void decode(){//將按鍵值轉(zhuǎn)化成EEPROM首入地址,并對紅外接收處理
getkey();
if(!iskeyboard)
kv5=1;
testcon();
}
void copyflash(uint adr,uchar len){//EEPROM拷貝測試程序
//讀者可將此程序稍加修改,成為拷貝sigdata數(shù)組數(shù)據(jù)到EEPROM指定地址的拷貝函數(shù)
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(){//發(fā)送紅外指令
if(iskeyboard)
while(scankey()==0);//一直等待按鍵輸入
getkey();
readdata();//將EEPROM代碼數(shù)據(jù)讀入外部內(nèi)存緩沖區(qū)
do{
encode();
_nop_();
encode();
sigout=0;
delay1ms(400);//每隔400ms連續(xù)發(fā)送2次代碼,一般紅外接收器均須2次重復(fù)代碼
}while(scankey()!=0);
}
uchar keyv2(){//由MCU接口模式下調(diào)用
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(){//由鍵盤接口模式下調(diào)用
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(){//外部內(nèi)存檢測程序
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;
}
}
}
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -