欧美极品高清xxxxhd,国产日产欧美最新,无码AV国产东京热AV无码,国产精品人与动性XXX,国产传媒亚洲综合一区二区,四库影院永久国产精品,毛片免费免费高清视频,福利所导航夜趣136
標題:
單片機串口通信控制步進電機,為什么每次上電只能接收一次數據控制一次?
[打印本頁]
作者:
ttaniscy
時間:
2019-9-10 18:10
標題:
單片機串口通信控制步進電機,為什么每次上電只能接收一次數據控制一次?
求助,上面的程序我單片機上電后可以正常串口通信收到數據,也可以按照設定返回給串口助手相應信息,電機也可以轉動指定的脈沖數,但接下來接不能正常通信了,再發數據串口助手就沒有反映了,電機也不轉了,單片機關掉再上電就又可以正確接收一次數據。我想不明白哪里的問題,特來求助,望指導。
單片機源程序如下:
#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();
}
}
復制代碼
作者:
ttaniscy
時間:
2019-9-11 11:55
根據我的試驗,問題是在void serial_control()這個函數相關的地方,因為在主程序中如果屏蔽掉這個子程序,就可以實現連續正確接收。但我分析不出來這個子程序的問題在哪了,特在此求助。
作者:
yzwzfyz
時間:
2019-9-11 22:17
經驗不足,
1、排除電機的電磁干擾。
2、排除程序的錯誤。
慢慢找吧。
作者:
ttaniscy
時間:
2019-9-12 08:25
我找到原因了,因為在主函數中我先進行串口通信接收串口助手的脈沖數信息時,TMOD設定的時定時器1的工作方式,然后在驅動步進電機是TMOD是設定定時器0的工作方式,所以在后續接收串口通信時就無法正常接受了。而修改也很簡單,在269行下面加一行代碼 rs232_init(); 就可以實現后續的正常接收了。
歡迎光臨 (http://www.raoushi.com/bbs/)
Powered by Discuz! X3.1