求助,上面的程序我單片機上電后可以正常串口通信收到數據,也可以按照設定返回給串口助手相應信息,電機也可以轉動指定的脈沖數,但接下來接不能正常通信了,再發數據串口助手就沒有反映了,電機也不轉了,單片機關掉再上電就又可以正確接收一次數據。我想不明白哪里的問題,特來求助,望指導。
單片機源程序如下:
- #include<reg52.h> //共陽極接法
- #define uint unsigned int
- #define uchar unsigned char
- #define N 8 //可一次接收數據量 幀頭(# ascii碼)0x23 幀頭(+/-號)+——0x2b --0x2d 5位數據 幀尾(* ascii碼)0x2a
- sbit dula=P2^6;
- sbit wela=P2^7;
- sbit pul=P1^0; //脈沖端
- sbit dir=P1^2; //方向端
- sbit ena=P1^1; // 電機軸使能端
- sbit limita=P1^3; //起始端極限位
- sbit limitb=P1^4;//遠端極限位
- sbit origin=P1^5;//原點位
- sbit led=P1^1;
- sbit led2=P1^3;
- uchar forward=0,backward=0,flag,i,w,j=0,serial_con;
- uint n,m,l,k,r,a,b,c,d,e,sum;
- uchar code table[]={ //數碼管編碼組
- 0x3f,0x06,0x5b,0x4f,
- 0x66,0x6d,0x7d,0x07,
- 0x7f,0x6f,0x77,0x7c,
- 0x39,0x5e,0x79,0x71};
- uchar code table1[]="MCU gets ";
- uchar code table2[]=" pluses!\r\n";
- uchar code table3[]="Error 1!\r\n"; //幀頭錯誤反饋代碼
- uchar code table4[]="Error 2!\r\n"; //幀尾錯誤反饋代碼
- uchar code table5[]="Error 3!\r\n";//脈沖數超過38500
- uchar rectable[N]; //用于接收串口通信數據的數組
- void delayms(uint xms) //延時子程序
- {
- uint i,j;
- for(i=xms;i>0;i--)
- for(j=110;j>0;j--);
- }
- void display(uchar num) //顯示子函數
- {
- P0=table[num];
- dula=1;
- dula=0;
- }
- void tmod(uint m) //設置定時器0中斷時間的子函數
- {
- TMOD=0x01;//設定定時器0 工作方式1(16位定時/計數器)
- TH0=(65536-m)/256; //設定中斷發生時間
- TL0=(65536-m)%256;
- ET0=1; //開定時器0中斷
- EA=1; //開總中斷
- TR0=1; //開啟定時器0
- }
- void rs232_init() //串口通信初始化子程序
- {
- TMOD=0x20;
- TH1=0xfd; //9600波特率
- TL1=0xfd;
- TR1=1; //波特率的發生利用定時器1
- SM0=0;
- SM1=1;
- REN=1; //先設定好工作方式,再打開允許接收
- EA=1; //打開總中斷
- ES=1; //打開串口中斷
- }
- void serial_control() //根據串口通信收到脈沖數轉動子程序
- {
- if(serial_con==1)
- {
- r=0; //進入幾次定時器0中斷計數用
- serial_con=0;
- /* a=rectable[2]-'0';
- b=rectable[3]-'0';
- c=rectable[4]-'0';
- d=rectable[5]-'0';
- e=rectable[6]-'0';
- sum=a*10000+b*1000+c*100+d*10+e; //把輸入的脈沖數的字符型字轉變成數字 */
- if(limita==1&&limitb==1)
- {
- switch(rectable[1]) //判斷方向 +號ASC碼 0x2b
- {
- case 0x2b:
- dir=0;
- tmod(500);
- n=2;
- forward=1;
- break;
- case 0x2d: ////判斷方向 -號ASC碼 0x2d
- dir=1;
- tmod(500);
- n=2;
- backward=1;
- break;
- }
- }
- serial_con=0;
- }
-
-
- }
- void serial_com() //串口通信子程序
- {
- if(flag==1)
- {
- a=rectable[2]-'0';
- b=rectable[3]-'0';
- c=rectable[4]-'0';
- d=rectable[5]-'0';
- e=rectable[6]-'0';
- sum=a*10000+b*1000+c*100+d*10+e; //把輸入的脈沖數的字符型字轉變成數字
- if(sum<=38500) //判斷是否超限,如果沒有超限
- {
- ES=0; //關閉串口中斷
- for(i=0;i<9;i++) //發送既定字符
- {
- SBUF=table1[i];
- while(!TI);
- TI=0;
- }
- for(j=2;j<(N-1);j++) //發送接收數組
- {
- SBUF=rectable[j];
- while(!TI);
- TI=0;
- }
- for(i=0;i<12;i++) //發送既定字符
- {
- SBUF=table2[i];
- while(!TI);
- TI=0;
- }
- j=0;
- ES=1;
- flag=0;
- serial_con=1; //進入根據收到脈沖數運動的子函數的標志位
- }
- if(sum>38500) //如果輸入脈沖超限
- {
- ES=0;
- for(i=0;i<12;i++)
- {
- SBUF=table5[i];
- while(!TI);
- TI=0;
- }
- }
- j=0;
- ES=1;
- flag=0;
- }
- if(flag==2) //幀頭不正確的報錯
- {
- ES=0;
- for(i=0;i<12;i++)
- {
- SBUF=table3[i];
- while(!TI);
- TI=0;
- }
- ES=1;
- flag=0;
- }
- if(flag==3) //幀尾不正確的報錯
- {
- ES=0;
- for(i=0;i<12;i++)
- {
- SBUF=table4[i];
- while(!TI);
- TI=0;
- }
- ES=1;
- flag=0;
- }
- }
- void time0() interrupt 1 //定時器0中斷子程序 中斷頻率在此函數內設置不同的頻率,即不同的轉速
- {
- switch(n)
- {
- // case 0:
- // TH0=(65536-12500)/256; //n=12500 頻率為40Hz 400脈沖/圈時轉速為 6r/m
- // TL0=(65536-12500)%256;
- // break;
- case 0:
- TH0=(65536-5000)/256; //n=5000 頻率為100Hz 400脈沖/圈時轉速為 15r/m
- TL0=(65536-5000)%256;
- break;
- // case 0:
- // TH0=(65536-2500)/256; //n=2500 頻率為200Hz 400脈沖/圈時轉速為 30r/m
- // TL0=(65536-2500)%256;
- // break;
- case 1:
- TH0=(65536-1250)/256; //n=1250 頻率為400Hz 400脈沖/圈時轉速為 60r/m
- TL0=(65536-1250)%256;
- break;
- // case 0:
- // TH0=(65536-1000)/256; //n=1000 頻率為500Hz 400脈沖/圈時轉速為 75r/m
- // TL0=(65536-1000)%256;
- // break;
- // case 0:
- // TH0=(65536-800)/256; //n=800 頻率為625Hz 400脈沖/圈時轉速為 93.75r/m
- // TL0=(65536-800)%256;
- // break;
- case 2:
- TH0=(65536-500)/256; //n=500 頻率為1KHz 400脈沖/圈時轉速為 150r/m
- TL0=(65536-500)%256;
- break;
- // case 2:
- // TH0=(65536-312)/256; //n=312 頻率為1.6KHz 400脈沖/圈時轉速為 240r/m
- // TL0=(65536-312)%256;
- // break;
- case 3:
- TH0=(65536-200)/256;//根據調整n的數值,n為200時,速度較快且可正常運行,n為150時啟動不正常(n=150時,頻率為3.33KHz,可能這個頻率對于起步太快了)
- TL0=(65536-200)%256; //n為200 頻率為2.5KHz 400脈沖/圈時轉速為 375r/m
- break;
- //case 1:
- // TH0=(65536-175)/256; //n=175 頻率為2.86KHz 400脈沖/圈時轉速為 430r/m
- // TL0=(65536-175)%256;
- // break;
- // case 4:
- // TH0=(65536-150)/256; //n=150 頻率為3.33KHz 400脈沖/圈時轉速為 500r/m
- // TL0=(65536-150)%256;
- // break;
- case 4:
- TH0=(65536-125)/256; //n=125 頻率為4KHz 400脈沖/圈時轉速為 600r/m
- TL0=(65536-125)%256;
- break;
- case 5:
- TH0=(65536-100)/256; //n=100 頻率為5KHz 400脈沖/圈時轉速為 750r/m
- TL0=(65536-100)%256;
- break;
- case 6:
- TH0=(65536-75)/256; //n=75 頻率為6.67KHz 400脈沖/圈時轉速為 1000r/m
- TL0=(65536-75)%256;
- break;
- case 7:
- TH0=(65536-50)/256; //n=50 頻率為10KHz 400脈沖/圈時轉速為 1500r/m
- TL0=(65536-50)%256;
- break;
- }
- // REN=0;//禁止串口接收數據
- ES=0;
- pul=~pul; //進入中斷后,開始高低電平變換以產生脈沖
- r++;
- if(r==(sum*2))
- {
- pul=1;
- TR0=0;
- r=0;
- n=0; //0檔最慢速度
- forward=0;
- backward=0;
- // REN=1;
- ES=1;
- }
- if(limita==0||limitb==0) //如果起始方向極限或遠端極限被觸發,pul輸出高電平,停止轉動并關閉定時器0
- {
- pul=1;
- TR0=0;
- n=0; //0檔最慢速度
- forward=0;
- backward=0;
- // REN=1;
- ES=1;
- }
- }
- void ser()interrupt 4 //串口中斷子程序
- {
- RI=0;
- rectable[j++]=SBUF; //存數據到接收緩存
- if(rectable[0]!=0x23) //幀頭驗證
- {
- flag=2;
- }
- if(j==N) //數組滿時,驗證幀尾再把flag置相應數值
- {
- if(rectable[7]!=0x2a) //幀尾驗證
- {
- flag=3;
- }
- else
- {
- flag=1;
- }
- }
- }
- void main()
- {
- P0=0;
- dula=1;
- dula=0;
- P0=0xc0;
- wela=1;
- wela=0;
- rs232_init(); //串口通信初始化設置
- while(1)
- {
- serial_com();
- serial_control();
- }
- }
復制代碼
|