步進電機用的是ULN2003模塊,光敏模塊是LM393通過比較光敏電阻和變阻器的阻值,輸出0,1信號。現在的問題是如果一開始光敏信號輸入為1,電動機正轉,光敏信號變為0時,電動機不反轉。反之如果一開始為0,電機反轉,改變光敏信號無反應。我覺著應該是光敏程序出了問題,光敏程序在下面117行求大佬指點。
單片機源程序如下:
- #include<reg52.h> //包含頭文件,一般情況不需要改動,頭文件包含特殊功能寄存器的定義
- #define uchar unsigned char
- sbit IR=P3^2; //紅外接口標志
- sbit light=P2^3;//定義光敏模塊信號輸入口為P3-5
- sbit upswitch=P2^0;//定義上行程開關為s4
- sbit downswitch=P2^1;//定義下行程開關為s2
- unsigned char irtime;//紅外用全局變量
- bit irpro_ok,irok; //處理OK,接收OK
- unsigned char IRcord[4]; //定義ircord是4個數組構成的數字
- unsigned char irdata[33];//定義irdata是33個b組成的數據,
- unsigned char nt[8]={0x01,0x03,0x02,0x06,0x04,0x0c,0x08,0x09}; //順時針旋轉
- unsigned char st[8]={0x09,0x08,0x0c,0x04,0x06,0x02,0x03,0x01};//逆時針旋轉表
- void delay(unsigned int n) //系統延時用于四步電機控制
- {
- unsigned int i=0,j=0;
- for(i=0;i<n;i++)
- {
- for(j=0;j<120;j++);
- }
- }
- /*定時器0中斷處理*/
- void tim0_isr (void) interrupt 1 using 1
- {
- irtime++; //用于計數2個下降沿之間的時間
- }
- /*外部中斷0中斷處理*/
- void EX0_ISR(void) interrupt 0 //外部中斷0服務函數
- {
- static unsigned char i; //接收紅外信號處理
- static bit startflag; //是否開始處理標志位
- if(startflag)
- {
- if(irtime<63&&irtime>=33)//引導碼 TC9012的頭碼,9ms+4.5ms 頭碼的持續時間的范圍,33(8.448ms)<63(16.128ms),
- i=0;
- irdata[ i]=irtime;//存儲每個電平的持續時間,用于以后判斷是0還是1
- irtime=0;
- i++;
- if(i==33) //33是33位的意思,包括32位的數據和一位的頭碼。
- {
- irok=1;
- i=0;
- }
- }
- else
- {
- irtime=0;
- startflag=1;
- }
- }
- /*定時器0初始化*/
- void TIM0init(void)//定時器0初始化
- {
- TMOD=0x02;//定時器0工作方式2,TH0是重裝值,TL0是初值
- TH0=0x00; //裝初值
- TL0=0x00;
- ET0=1; //開中斷
- TR0=1;
- }
- /*外部中斷0初始化*/
- void EX0init(void)
- {
- IT0 = 1; //指定外部中斷0下降沿觸發,INT0 (P3.2)
- EX0 = 1; //打開外部中斷
- EA = 1; //開總中斷
- }
- /*步進電機控制程序*/
- void stepperdown()//四相步進電機逆時針轉
- {
- // delay(10);加上就變成點動了
- while(1)
- {
- int i=0;
- for(i=0;i<8;i++)
- {
- P1=nt[ i];
- delay(2);//delay2這個時間差不多合適<2無法運行
- }
- if(IR==0) //事實證明可行
- {
- break;
- }
- }
- }
- void stepperup()//四相步進電機順時針旋轉
- {
- while(1)
- {
- int i=0;
- for(i=0;i<8;i++)
- {
- P1=st[ i];
- delay(2);//delay2這個時間差不多合適<2無法運行
- }
- if(IR==0) //事實證明可行
- {
- break;
- }
- }
- }
- void stepperstop()
- {
- P1=0x00;
- }
- /*光敏自動控制模式*/
- void lightmod() //現在的問題:只走一個程序其他if語句完全沒用
- {
- while(1)
- { if(light==1)
- {
- stepperup();
- }
- if(light==0)
- {
- stepperdown();
- }
- if(IR==0) //事實證明可行
- {
- break;
- }
- }
- }
- /*原鍵值處理*/
- void Ir_work(void)//紅外鍵值散轉程序
- {
- P1=0x00;//初始化p1
- switch(IRcord[2])//判斷第三個數碼前兩個是用戶碼,最后一個是反碼,第三個才是真正的數據碼。
- {
- case 0x45:stepperdown();break;//- 按下遙控器上面0-9的按鍵,led亮起相應的數值
- case 0x47:stepperup();break;//+
- case 0x46:stepperstop();break;
- case 0x09:lightmod();break;
- default:break;
- }
- irpro_ok=0;//處理完成標志
- }
- /*紅外碼值處理*/
- void Irpro(void)//紅外碼值處理函數 分析出那些是1那些是0
- {
- unsigned char i, j, k;
- unsigned char cord,value;
- k=1; //前導碼沒數據,從第二個開始,就是用戶碼開始。
- for(i=0;i<4;i++) //處理4個字節
- {
- for(j=1;j<=8;j++) //處理1個字節8位。for語句:先執行j=1;在執行j<=8,為真則繼續執行,否則結束執行;執行完循環體后執行j++,重復執行執行循環和j++直到j<=8為假
- {
- cord=irdata[k]; //
- if(cord>7) //低電平下降沿到下一個下降沿的寬度是0.56+0.565=1.125ms,高電平則是0.56+1.69=2.25ms,同樣我們也給出一個范圍用于區分它們,可以這樣識別 (1.125ms + 2.25ms )/ 2=1.68ms,
- //大于1.68為高,小于1.68為低。
- //假設使用12M晶振 定時器的單位數值時1us,使用8位定時器自動重裝,將得到每個定時周期0.256ms的時長, 1.68/0.256=6.59,約等于7.也就是 定時器0計數次數。
- value|=0x80;//最高位就給1,
- if(j<8)
- {
- value>>=1;
- }
- k++;
- }
- IRcord[ i]=value;
- value=0;
- }
- irpro_ok=1;//處理完畢標志位置1
- }
- /*主函數*/
- void main(void)
- {
- EX0init(); //初始化外部中斷
- TIM0init();//初始化定時器
- while(1)//主循環
- {
- if(irok) //如果接收好了進行紅外處理
- {
- Irpro();
- irok=0;
- }
- if(irpro_ok) //如果處理好后進行工作處理,如按對應的按鍵后顯示對應的數字等
- {
- Ir_work();
- }
- }
- }
- }
復制代碼
|