這是
zhangxinchun的貼子 有這段沒看明白 da1527[rep][ii]&=~(1<<((7-k)));數組里的值是最后多少
特別是這里~(1<<((7-k))) 望高人們指點
單片機源程序如下:
- //測試單片機:STC15W408AS
- //晶振:內部 11.0592mHZ
- //復位方式:內部復位
-
- //串口通訊:波特率9600/數據位8/停止位1/無校驗
- //調試環境:KEIL3
- //程序功能:實現2262解碼,學習、自適應多阻值,片內EEPROM,存儲60個遙控器數據
-
- // 不依賴硬件,不占用硬件資源。移植更加方便
- // 學習遙控器:按一下學習鍵,學習燈點亮,松開學習鍵,按動要學習的遙控器按鍵,學習燈熄滅,學習成功。重復上述操作可學習多個遙控器.
- //
- // 清除:按住學習鍵不放,直到學習燈自動熄滅,擦除成功.
- /**********************************************************/
- #include <STC15W408AS.h>
- #include <intrins.h>
- #define uchar unsigned char
- #define uint unsigned int
- sbit RF = P1^1; //信號輸入
- sbit LED = P3^3; //學習指示燈
- sbit set = P1^2; //學習鍵
- sbit D0 = P3^4; //1號繼電器解碼輸出
- sbit D1 = P3^5; //2號繼電器
- sbit D2 = P3^6; //3號繼電器
- sbit D3 = P3^7; //4號繼電器
- sbit deng1 = P1^7; //K1指示燈
- sbit deng2 = P5^4; //K2指示燈
- sbit deng3 = P5^5; //K3指示燈
- sbit deng4 = P3^2; //K4指示燈
- sbit VT = P1^0; //接收指示燈
- sbit aj1 = P1^3; //K1
- sbit aj2 = P1^4; //K2
- sbit aj3 = P1^5; //K3
- sbit aj4 = P1^6; //K4
- bit decode_ok; //解碼成功
- bit rf_ok; //收到有效數據
- bit study; //學習標志
- bit jmnx; //編碼類型 0是2262,1是1527
- bit m=0,ba=0,ca=0,da=0,ea=0,za=0,aa=0,hv=0,ff=0,ra=0,rb=0,rc=0,rd=0,g=0,hm=0,biao=0,kt=0;
- bit biao_1=0,g_1=0,kt_1=0,hm_1=0;
- bit biao_2=0,g_2=0,kt_2=0,hm_2=0;
- bit biao_3=0,g_3=0,kt_3=0,hm_3=0;
- uchar da1527[2][3]; //解碼過程中臨時數組
- uchar key_d; //遙控器按鍵碼
- uchar short_k; //窄脈沖寬度
- uchar ss=0,sn=0,h=0,yz=0,hh=0,yy=0,yk=0,yu=0;hk=0,sj=0,so=0,jk=0,hu=0,t1=0,t2=0,t3=0,t4=0;
- uint dt=0,dr=0,dq=0,rv=0,rv_1=0,rv_2=0,rv_3=0;
- uchar trg=0,trg_1=0,trg_2=0,trg_3=0,cont=0,cont_1=0,cont_2=0,cont_3=0;
- uchar ReadData=0,ReadData_1=0,ReadData_2=0,ReadData_3=0;
- static uint sk=0;
- uchar xdata key_number[181]; //遙控器編碼數組,存放60個遙控器
- 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--;
- }
- }
- //====================================================
- /////////片內EEPROM讀寫驅動程序///////////////////////////
- //====================================================
- void IAP_Disable() //關閉IAP
- {
- //關閉IAP 功能, 清相關的特殊功能寄存器,使CPU 處于安全狀態,
- //一次連續的IAP 操作完成之后建議關閉IAP 功能,不需要每次都關
- IAP_CONTR = 0; //關閉IAP 功能
- IAP_CMD = 0; //清命令寄存器,使命令寄存器無命令,此句可不用
- IAP_TRIG = 0; //清命令觸發寄存器,使命令觸發寄存器無觸發,此句可不用
- IAP_ADDRH = 0;
- IAP_ADDRL = 0;
- }//
- //讀一字節,調用前需打開IAP 功能,入口:DPTR = 字節地址,返回:A = 讀出字節
- uchar read_add(uint addr) //讀EEPROM
- {
- IAP_DATA = 0x00;
- IAP_CONTR = 0x84; //打開IAP 功能, 設置Flash 操作等待時間
- IAP_CMD = 0x01; //IAP/ISP/EEPROM 字節讀命令
- IAP_ADDRH = addr>>8; //設置目標單元地址的高8 位地址
- IAP_ADDRL = addr&0xff; //設置目標單元地址的低8 位地址
- EA = 0;
- IAP_TRIG = 0x5a; //先送 46h,再送B9h 到ISP/IAP 觸發寄存器,每次都需如此
- IAP_TRIG = 0xa5; //送完 B9h 后,ISP/IAP 命令立即被觸發起動
- _nop_();
- EA = 1;
- IAP_Disable(); //關閉IAP 功能, 清相關的特殊功能寄存器,使CPU 處于安全狀態,
- //一次連續的IAP 操作完成之后建議關閉IAP 功能,不需要每次都關
- return (IAP_DATA);
- }//------------------------------------------------------------------------------
- //字節編程,調用前需打開IAP 功能,入口:DPTR = 字節地址, A= 須編程字節的數據
- void write_add(uint addr,uchar ch) //直接寫EEPROM
- {
- IAP_CONTR = 0x84; //打開 IAP 功能, 設置Flash 操作等待時間
- IAP_CMD = 0x02; //IAP/ISP/EEPROM 字節編程命令
- IAP_ADDRH = addr>>8; //設置目標單元地址的高8 位地址
- IAP_ADDRL = addr&0xff; //設置目標單元地址的低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 = 0x84; //打開IAP 功能, 設置Flash 操作等待時間
- IAP_CMD = 0x03; //IAP/ISP/EEPROM 扇區擦除命令
- IAP_ADDRH =addr>>8; //設置目標單元地址的高8 位地址
- IAP_ADDRL =addr&0xff; //設置目標單元地址的低8 位地址
- EA = 0;
- IAP_TRIG = 0x5a; //先送 46h,再送B9h 到ISP/IAP 觸發寄存器,每次都需如此
- IAP_TRIG = 0xa5; //送完 B9h 后,ISP/IAP 命令立即被觸發起動
- _nop_();
- EA = 1;
- }//------------------------------------------------------------------------------
- //============================接收解碼部分========================================//
- void RF_decode()
- {
- uchar ii=0,j=0,k=0,rep=0;
- uint head_k=0; //短脈沖寬度
- uchar s;
- //-------------------------------數據接收-----------------------------------------
- short_k=0;
- while(RF && j<250) //檢測頭信號前一個高脈沖的寬度
- {
- delay(1);
- short_k++;
- }
- while(!RF)
- {
- delay(1);
- head_k++;
- } //檢測頭脈沖的寬度
- if(((short_k*24)<head_k) && (head_k<(short_k*38))) //引導碼寬度是窄脈沖的32倍 24/38
- {
- for(rep=0;rep<2;rep++)
- {
- for(ii=0;ii<3;ii++)//3字節
- {
- for(k=0;k<8;k++)//每個字節8位
- {
- j=0;
- while(RF && j<245)
- {
- delay(1);
- j++;
- }//
- if(j>(short_k-short_k/2-short_k/3)&&j<(short_k*1.96))
- {
- da1527[rep][ii]&=~(1<<((7-k)));
- }
- else if(j>(short_k*1.96)&&j<(short_k*5))da1527[rep][ii]|=(1<<(7-k));
- else {return;} //亂碼退出
- j=0;
- while(!RF && j<150){delay(2);j++;} //跳過低電平
- }
- }//for(ii=0;ii<12;ii++)
- j=0;while(RF && (j<200)){delay(1);j++;} //跳個最后一個高脈沖
- head_k=0;while(!RF) {delay(1);head_k++;} //檢測下一個前導信號的寬度
- if((head_k<(short_k*26)) || (head_k>(short_k*38))) {return;} //引導碼寬度是窄脈沖的32倍 //亂碼退出
- }
- //+++++++++++++++++++++++++2262與1527數據分離處理++++++++++++++++++++++++++++++++++++++++
- if((da1527[0][0]==da1527[1][0]) && (da1527[0][1]==da1527[1][1]) && (da1527[0][2]==da1527[1][2])) //兩次接收到的數據相同
- {
- uchar u,i,x;
- rf_ok=1;
- for(i=0;i<3;i++) //判定2262與1527
- {
- for(u=0;u<4;u++) {if(((da1527[0][i]>>(u*2)) & 3)==2) {i=80;break;}} //有10則為1527
- if(i==80) break;
- }
- if(i==80) //1527
- {
- key_d=da1527[1][2] & 0x0f; //分出1527的按鍵值
- da1527[0][2]=da1527[1][2]>>4; //分出1527的后4位地址
- jmnx=1; //為0是2262,1是1527
- }
- else //2262
- {
- key_d=0;
- for(i=0;i<4;i++){if(((da1527[0][2]>>(i*2))&3)==3) key_d|=1<<i;} //計算出2262的按鍵數據
- da1527[0][2]=0x00; //2262無后4位地址,全為0
- jmnx=0; //為0是2262,1是1527
- jk++;//自鎖用,作用:按下按鍵不松手繼電器狀態不變,松開再按下改變,一次只改變一次狀態,因為按下按鍵后遙控會一直發碼,所以讓jk一直自加,但是只取jk=1的值的狀態
- }
-
- if (!study) //非學習狀態
- {
- rf_ok=0;
- for(x=0;x<60;x++)
- {
- if((da1527[0][0]==key_number[x*3+1])&&(da1527[0][1]==key_number[x*3+2])
- &&(da1527[0][2]==key_number[x*3+3]))//判斷是否已學習過的編碼
- {
- // D0=!(key_d&0x08); //取得按鍵碼
- // D1=!(key_d&0x04);
- // D2=!(key_d&0x02);
- // D3=!(key_d&0x01);
- if(m==1) //互鎖
- {
- if(key_d == 0x01){D0=0;D1=1;D2=1;D3=1;}//D4=1;D5=1;D6=1;D7=1;D8=1;D9=1;D10=1;D11=1;}//else{D0=1;}
- if(key_d == 0x02){D0=1;D1=0;D2=1;D3=1;}//D4=1;D5=1;D6=1;D7=1;D8=1;D9=1;D10=1;D11=1;}
- // if(key_d == 0x03){D0=1;D1=1;D2=0;D3=1;D4=1;D5=1;D6=1;D7=1;D8=1;D9=1;D10=1;D11=1;}
- if(key_d == 0x04){D0=1;D1=1;D2=0;D3=1;}//D4=1;D5=1;D6=1;D7=1;D8=1;D9=1;D10=1;D11=1;}
- // if(key_d == 0x05){D0=1;D1=1;D2=1;D3=1;D4=0;D5=1;D6=1;D7=1;D8=1;D9=1;D10=1;D11=1;}
- // if(key_d == 0x06){D0=1;D1=1;D2=1;D3=1;D4=1;D5=0;D6=1;D7=1;D8=1;D9=1;D10=1;D11=1;}
- // if(key_d == 0x07){D0=1;D1=1;D2=1;D3=1;D4=1;D5=1;D6=0;D7=1;D8=1;D9=1;D10=1;D11=1;}
- if(key_d == 0x08){D0=1;D1=1;D2=1;D3=0;}//D4=1;D5=1;D6=1;D7=0;D8=1;D9=1;D10=1;D11=1;}
- // if(key_d == 0x09){D0=1;D1=1;D2=1;D3=1;D4=1;D5=1;D6=1;D7=1;D8=0;D9=1;D10=1;D11=1;}
- // if(key_d == 0x0a){D0=1;D1=1;D2=1;D3=1;D4=1;D5=1;D6=1;D7=1;D8=1;D9=0;D10=1;D11=1;}
- // if(key_d == 0x0b){D0=1;D1=1;D2=1;D3=1;D4=1;D5=1;D6=1;D7=1;D8=1;D9=1;D10=0;D11=1;}
- // if(key_d == 0x0c){D0=1;D1=1;D2=1;D3=1;D4=1;D5=1;D6=1;D7=1;D8=1;D9=1;D10=1;D11=0;}
- }
- else
- {
- if(ba==0) //B按鍵自鎖
- {
- if(key_d == 0x04)
- {
- if(jk==1)
- {
- D2=~D2;
- }
- }
- } //B自鎖
- if(da==0) //A按鍵自鎖
- {
- if(key_d == 0x08)
- {
- if(jk==1)
- {
- D3=~D3;
- }
- }
- } //A自鎖
- if(ca==0) //C按鍵自鎖
- {
- if(key_d == 0x02)
- {
- if(jk==1)
- {
- D1=~D1;
- }
- }
- } //C自鎖
- if(ea==0) //D按鍵自鎖
- {
- if(key_d == 0x01)
- {
- if(jk==1)
- {
- D0=~D0;
- }
- }
- } //D自鎖
- if(ba==1)//B按鍵點動,ba為自鎖轉點動標志位
- {
- if(key_d == 0x04){D2=0;}
- }
- if(da==1)//A按鍵點動,da為自鎖轉點動標志位
- {
- if(key_d == 0x08){D3=0;}
- }
- if(ca==1)//C按鍵點動,da為自鎖轉點動標志位
- {
- if(key_d == 0x02){D1=0;}
- }
- if(ea==1)//D按鍵點動,da為自鎖轉點動標志位
- {
- if(key_d == 0x01){D0=0;}
- }
- }
- decode_ok=1;
- ss=1;
- sn=1;
- sj=1;
- so=1;
- VT=0;
- s=30;
- break;
- }
-
- }
-
-
- }
- }
-
- }
復制代碼
|