求助,上面的程序我单片机上电后可以正常串口通信收到数据,也可以按照设定返回给串口助手相应信息,电机也可以转动指定的脉冲数,但接下来接不能正常通信了,再发数据串口助手就没有反映了,电机也不转了,单片机关掉再上电就又可以正确接收一次数据。我想不明白哪里的问题,特来求助,望指导。
单片机源程序如下:
- #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();
- }
- }
复制代码
|