微波EDA网,见证研发工程师的成长!
首页 > 研发问答 > 嵌入式设计讨论 > MCU和单片机设计讨论 > 51单片机串口通信问题。

51单片机串口通信问题。

时间:10-02 整理:3721RD 点击:

预期实现功能:单片机通过两外部中断计数外部脉冲。两计数脉冲可在数码管上显示。脉冲数可由按键或指令flag发送至PC。

出现问题为:不管单片机一何种方法向PC发送数据,只要有外部干扰,能自动向PC发送数据。数码管上显示的数值并不是按我想的15s变化一次。为什么?

#include <reg52.h>  

#include <string.h>

#define uchar unsigned char

#define uint  unsigned int


sbit M_RE= P2^5;       //接收器低电平有效

sbit M_DE= P2^6;           //驱动器高电平有效

sbit KEY1 = P3^2;         //按键S19


uchar code table[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x40};

sbit HC138A0 = P2^0;     

sbit HC138A1 = P2^1;   

sbit HC138A2 = P2^2;     

uchar led[8];


sbit D1=P1^0;          

sbit flag=P1^1;          //单片机是否收到主机发过来的指令

int Num1=0,Num2=0;m=0,D_all=0,X_all=0;

/****************************/


//初始化设置

void coun()            

{

    EA=1;         //开总中断

EX0=1;         //开外部中断0

EX1=1;         //开外部中断1

IT0=1;         //外部中断0的中断触发控制位:此为下降沿触发方式。

IT1=1;         //外部中断1的中断触发控制位:此为下降沿触发方式。

    ET0=1; //开定时/计数器T0中断

    TR0=1;                 //T0运行控制位,置1,开始工作。

           TMOD=0x01;         //T0定时,工作方式选择方式1。

    TH0=(65536-50000)/256;         //一个机器周期时间为1/11.0592*12=1.085us        50000机器周期时间为50000*1.085us=54.25ms

TL0=(65536-50000)%256;

}


  //初始化串口

void init_serialcomm( void )

{

SCON = 0x50 ;       //SCON: serail mode 1, 8-bit UART, enable ucvr   串口模式1,允许接收(选择串口的工作方式和某些控制功能)

TMOD = 0x20 ;      //TMOD: timer 1, mode 2, 8-bit reload  定时1,方式2,

PCON = 0x80 ;      //SMOD=1  波特率提高一倍

TH1 = 0xFa ;        //Baud:9600 fosc=11.0592MHz

//        IE = 0x90 ;        //Enable Serial Interrupt  允许串口中断

TR1 = 1 ;           // timer 1 run         // TI=1;

ES=1;

EA=1;                            

}


//延时函数

void delay(int z)               

{

    unsigned char x,y;

    for(x=0;x<50;x++)

    for(y=z;y>0;y--) ;

}


//1ms延时

void Delay_1ms(uint i)

{

uchar x,j;

for(j=0;j<i;j++)

for(x=0;x<=148;x++);

}


//向串口发送一个字符

void send_char_com( unsigned char ch)

{

SBUF=ch;

while (TI== 0 );  

TI= 0 ;

}


//向串口发送一个数组,length为该数组长度

void send_array_com( unsigned char *str, unsigned int length)

{

uint k= 0 ;

do

{

send_char_com(*(str + k));

   k++;

}

while (k<length);

}


//显示函数   138译码器显示

void display()   

{  

char i;

//        X_all=1234;

//        D_all=5678;

led[0]=table[X_all/1000];

    led[1]=table[X_all%1000/100];

    led[2]=table[X_all%100/10];

    led[3]=table[X_all%10];

led[4]=table[D_all/1000];

    led[5]=table[D_all%1000/100];

    led[6]=table[D_all%100/10];

    led[7]=table[D_all%10];


    for( i=0; i<8; i++)  //实现8位动态扫描循环

    {

             P0 = led;  //将字模送到P0口显示            

        switch(i)                  

        {   

case 0:HC138A0=0; HC138A1=0; HC138A2=0;  break;   

            case 1:HC138A0=1; HC138A1=0; HC138A2=0;  break;

            case 2:HC138A0=0; HC138A1=1; HC138A2=0;  break;               

            case 3:HC138A0=1; HC138A1=1; HC138A2=0;  break;

case 4:HC138A0=0; HC138A1=0; HC138A2=1;  break;   

            case 5:HC138A0=1; HC138A1=0; HC138A2=1;  break;

            case 6:HC138A0=0; HC138A1=1; HC138A2=1;  break;               

            case 7:HC138A0=1; HC138A1=1; HC138A2=1;  break;

        }

        delay(10);

}


}

//条件发送(按键闭合或收到主机指令,单片机像主机发送指令)

void send()

{

PS=1;

if(KEY1 ==0)  

{

Delay_1ms(30);           //30ms软件防抖          

while(!KEY1);


M_RE=1;

M_DE=1;            // 串口处于发送状态


send_array_com(led,8);

M_RE=0;

M_DE=0;         //设置串口再次处于接收状态

}


/*        if(flag=1)         //单片机接受到主机上的指令,想主机发送数据。

{

flag=0;

M_RE=1;

M_DE=1;            // 串口处于发送状态


send_array_com(led,8);

M_RE=0;

M_DE=0;         //设置串口再次处于接收状态

}

*/

PS=0;


}


/*************主函数***************/


void main()

{

P0=table[0];

display();

D1=0;         //对灯D1赋值,开始时为亮,当有外部中断,则灯灭。


delay(50);

        coun();          //初始化

init_serialcomm(); //初始化串口

    while(1)

   {

  if(m==300)    //   1200采样时间1分钟,达到时间后停止采样   (300为15s)

    {

EX0=0;

EX1=0;

m=0;  


D_all=Num1;

X_all=Num2;

   X_all-=D_all;

Num1=0;Num2=0;

EX0=1;

EX1=1;


}

send();

display();



   }   

}


/*************中断函数***************/

void int0() interrupt 0  using 1

{

    EX0=0;

    Num1++;

    EX0=1;

D1=1;

}


void int1() interrupt 1 using 2

{


TH0=(65536-50000)/256;

TL0=(65536-50000)%256;

m++;


}


void timer0() interrupt 2  using 3

{

    EX1=0;

    Num2++;

    EX1=1;

}

/*


//串口接收中断函数

void serial () interrupt 4 using 0

{

if (RI)

{            

uchar temp;      

RI = 0 ;


temp=SBUF;

flag=1;

if(temp='a')

flag=1;


}  

}  */


粗劣看一下这里就有一个不严谨的错误coun();          //初始化
init_serialcomm(); //初始化串口

程序中共用的寄存器应该用或与操作才不容易犯这种正确的错误。coun()中TMOD设置了定时器0为方式1而在init_serialcomm()设置波特率初始化时又把定时器0设置成了方式0.共用寄存器应该写成TMOD|=0X01;TMOD|=0X10形式就不会因为其他地方没有意识到而被粗心更改

两个函数共用TMOD,你把第二个中的改成TMOD|=0X20

两个函数共用TMOD,你把第二个中的改成TMOD|=0X20
恩,谢谢

这个不错,多谢小编

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top