打印
[51单片机]

新人求助,关于51单片机串口接收问题

[复制链接]
1297|14
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
孤独枫|  楼主 | 2015-7-10 21:29 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
论坛新人,向各位大侠求助


才学习单片机串口通信,现在需要编写一段程序,实现电脑向单片机发送数据,单片机通过动态显示在数码管上,单片机接收出现问题


程序编写看教程和郭天祥的都是使用串口中断SBUF接收到一个电脑传过来的数据后再将这个数据发送回电脑上去,我这样写也没问题,电脑串口助手调试正常。但是一旦我关闭掉主程序mian中的发送语句后就无法再接收到新数据了。
这是单片机接到数据后发送回去的语句
if(flag==1)                //等待中断里边接收数据,没有数据无法进入
                {                            
                        ES=0;            //flag为1,说明有接收到数据,进入循环,关掉中断
                        flag=0;            //flag重新置为0,发送完成后退出if语句
                        SBUF=a;            //将变量a的数值放进发送存储器
                        while(!TI); //等待发送完毕(发送完后TI自动置1,结束循环)
                        TI=0;            //重新将TI置0
                        ES=1;            //重新开启串行中断
                }

现象是这样的,如果程序以接收到后再发送回去(就是带上边IF语句),就能正常显示,电脑也能接收到单片机发送回来的数据,
但是如果我把这段发送回的语句删掉,那么单片机能收到电脑发送过来的第一个数据,比如AA,数码管会正常显示170,但是之后再发送任何数据都无法显示,一直显示170,数码管也在正常动态显示,就是无法接收到电脑再发的数据。每次重启都只能接收到第一个数据.
程序如下(一旦去掉mian中返回的IF语句就不能正常接收了,很纳闷,返回与接收毫无关联,如果程序卡死又为什么能够正常动态显示?串口中断里边已经把RI置0,照常理完全可以接收接下来的数据呀):
单片机使用的是宏晶STC90C516RD+;求大侠们指点,帮忙分析下问题出在哪里;
#include<reg52.h>
unsigned char flag,a;

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

void dynamic_led(unsigned long z);   //声明动态扫描子程序

void main()
{
        TMOD=0x20;//设置定时器1为工作方式2(自动回装)
        TH1=0xfd;  //装自动回装的初值(确定波特率)
        TL1=0xfd;  //装定时器的第一次初值(以后的就可以通过自动回装完成)
        TR1=1;           //启动定时器1
        REN=1;           //让串口允许接收数据
        SM0=0;           //设置串口的工作方式
        SM1=1;           //设置串口的工作方式
        EA=1;           //开启总中断
        ES=1;           //开启串口中断
        while(1)
        {
                if(flag==1)                //等待中断里边接收数据,没有数据无法进入
                {                            //if循环,于是一直在while循环里等待
                        ES=0;            //flag为1,进入循环,关掉中断
                        flag=0;            //flag重新置为0,发送完成后退出if语句
                        SBUF=a;            //将变量a的数值放进发送存储器
                        while(!TI); //等待发送完毕(发送完后TI自动置1,结束循环)
                        TI=0;            //重新将TI置0
                        ES=1;            //重新开启串行中断
                }
                dynamic_led(a);    //数码管动态显示子程序,显示数据A

        }
}

void ser() interrupt 4
{
        RI=0;                 //把中断清零,使其能够继续接收数据
        P1=SBUF;                //在P1口显示数据
        a=SBUF;                 //把接收等到的数据存入变量a,待会再返发回去
        flag=1;                  //接收到数据后flag置1,主函数才能进入if语句
}


//动态扫描子程序
void dynamic_led(unsigned long z)
{
        unsigned long x;
        unsigned char a,weila,ledwei;
        weila=0x1c;
        x=z;
        for(ledwei=0;ledwei<=7;ledwei++)
        {
                a=x%10;
                x=x/10;
                P0=table[a];
                P2=weila;
                weila=weila-0x04;
        }
}



相关帖子

沙发
孤独枫|  楼主 | 2015-7-10 21:33 | 只看该作者
其实我的想法很简单,就是只需要单片机接收,然后显示出来就是了,不需要它再把数据返回,为什么就不行呢,是我忘记哪个环节了?

使用特权

评论回复
板凳
bryanlee512| | 2015-7-11 21:18 | 只看该作者
我也在看郭的书,板子应该和你的一样,但是你的代码似乎不对啊,把你的代码烧入 我的51芯片数码管都不亮啊,我段选口是P2^6  位选P2^7。
按照你的要求我也试写了一下,不过我的问题是接收到SBUF的数据在显示到数码管就乱码了。不知道这个SBUF数据怎么转换。

使用特权

评论回复
地板
bryanlee512| | 2015-7-11 21:22 | 只看该作者
孤独枫 发表于 2015-7-10 21:33
其实我的想法很简单,就是只需要单片机接收,然后显示出来就是了,不需要它再把数据返回,为什么就不行呢, ...

补充下,我把你所谓的if去掉是可以显示的,不过数码管就乱码了。我的代码你看下。
#include <reg52.h>
#define uchar unsigned char
#define uint unsigned int
unsigned  char flag,a,i;
//uchar code table[]="i get ";

uchar code table1[]={
0x3f,0x06,0x5b,0x4f,
0x66,0x6d,0x7d,0x07,
0x7f,0x6f};
sbit dula=P2^6;
sbit wela=P2^7;
void delay(uchar z)
{        uchar i,j;
        for(i=z;i>0;i--)
                for(j=0;j>0;j--);
}
void init()
{
TMOD=0x20;
TH1= 0xfD;
TL1= 0xfD;
SM0=0;
SM1=1;
REN=1;

TR1=1;
EA=1;
ES=1;


}
void kk(unsigned long z)//数码管只显示1位
{
        P0=0xff;
                delay(100);
                dula=1;
                P0=table1[z];
                dula=0;
                P0=0xff;

                wela=1;
                P0=0xdf;
                wela=0;
}
void main()
{
init();
while(1)
{         kk(SBUF);
       

}
}
void ser() interrupt 4
{
RI=0;

a=SBUF;
flag=1;
}

使用特权

评论回复
5
孤独枫|  楼主 | 2015-7-12 10:19 | 只看该作者
bryanlee512 发表于 2015-7-11 21:22
补充下,我把你所谓的if去掉是可以显示的,不过数码管就乱码了。我的代码你看下。
#include
#define uch ...

恩恩,今晚回去试试你的程序

使用特权

评论回复
6
ningling_21| | 2015-7-12 10:47 | 只看该作者
发送数据是查询发送,应先关串口中断,否则肯定不正常

使用特权

评论回复
7
孤独枫|  楼主 | 2015-7-12 11:16 | 只看该作者
ningling_21 发表于 2015-7-12 10:47
发送数据是查询发送,应先关串口中断,否则肯定不正常

发送是正常的,问题出在接收,现在是接收后再发送正常,接收收后不发送就不正常了,发送里边关了串口中断的

使用特权

评论回复
8
孤独枫|  楼主 | 2015-7-12 11:25 | 只看该作者
bryanlee512 发表于 2015-7-11 21:18
我也在看郭的书,板子应该和你的一样,但是你的代码似乎不对啊,把你的代码烧入 我的51芯片数码管都不亮啊 ...

我用的是普中6800EM3的开发板,数码管动态显示,段选是P0口,位选是接的74LS138译码器,通过P2^2,P2^3,P2^4控制位选,您看你显示乱码是不是和我的位选控制方式不一样。

然后8个循环,比如数据时12345678,每次除以10,对个位取余,这样来分离出每一位。

动态扫描这个子程序没得问题,已经用过很多次了。

如果显示乱码应该是我们在位选设置上不一样

使用特权

评论回复
9
bryanlee512| | 2015-7-12 11:36 | 只看该作者
难怪不一样 我的段选在P2^6,位选在P2^7

使用特权

评论回复
10
bryanlee512| | 2015-7-12 11:46 | 只看该作者
问下你输入aa怎么输出170的?
a应该是从a=SBUF语句获取到的数据吧?

使用特权

评论回复
11
孤独枫|  楼主 | 2015-7-12 12:34 | 只看该作者
bryanlee512 发表于 2015-7-12 11:46
问下你输入aa怎么输出170的?
a应该是从a=SBUF语句获取到的数据吧?

忘说了,我电脑串口助手输入的是十六进制,单片机数码管显示的是十进制,换算过来就是显示170,

使用特权

评论回复
12
孤独枫|  楼主 | 2015-7-12 12:36 | 只看该作者
bryanlee512 发表于 2015-7-12 11:46
问下你输入aa怎么输出170的?
a应该是从a=SBUF语句获取到的数据吧?

AA是输入的16进制数据,这个数据通过串口由存入单片机读取寄存器SBUF,再把数据赋值给变量a

使用特权

评论回复
13
ningling_21| | 2015-7-12 12:50 | 只看该作者
本帖最后由 ningling_21 于 2015-7-12 15:18 编辑
孤独枫 发表于 2015-7-12 12:36
AA是输入的16进制数据,这个数据通过串口由存入单片机读取寄存器SBUF,再把数据赋值给变量a ...

显示部分自己改下
#include<reg52.h>
#define uchar unsigned char

unsigned char flag,a=0;

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

void dynamic_led(unsigned char   z);   //声明动态扫描子程序
void delay(uchar dly)
{
        while(dly--);

}

void main()
{
        TMOD=0x20;//设置定时器1为工作方式2(自动回装)
        TH1=0xfd;  //装自动回装的初值(确定波特率)
        TL1=0xfd;  //装定时器的第一次初值(以后的就可以通过自动回装完成)
        TR1=1;           //启动定时器1
        REN=1;           //让串口允许接收数据
        SM0=0;           //设置串口的工作方式
        SM1=1;           //设置串口的工作方式
        EA=1;           //开启总中断
        ES=1;           //开启串口中断
                a =0;
        while(1)
        {
                if(flag==1)                //等待中断里边接收数据,没有数据无法进入
                {                            //if循环,于是一直在while循环里等待
                        ES=0;            //flag为1,进入循环,关掉中断
                        flag=0;            //flag重新置为0,发送完成后退出if语句
                        SBUF=a;            //将变量a的数值放进发送存储器
                        while(!TI); //等待发送完毕(发送完后TI自动置1,结束循环)
                        TI=0;            //重新将TI置0
                        ES=1;            //重新开启串行中断
                }
                dynamic_led(a);    //数码管动态显示子程序,显示数据A

        }
}

void ser() interrupt 4
{
        RI=0;                 //把中断清零,使其能够继续接收数据
        P1=SBUF;                //在P1口显示数据
        a=SBUF;                 //把接收等到的数据存入变量a,待会再返发回去
        flag=1;                  //接收到数据后flag置1,主函数才能进入if语句
}


//动态扫描子程序
void dynamic_led(unsigned char  z)
{
        unsigned char x;
                uchar bai,shi ,ge;

        unsigned char weila,ledwei;
        weila=0x1c;
        x=z;
        for(ledwei=0;ledwei<=3;ledwei++)
        {
                ge  =x%100%10;
                shi =x%100/10;
                                bai =x/100;
               
                                switch( ledwei)
                                {
                       
                                        case 0:P2=~0x01;
                                                   P0=~table[0];
                                        break;
                                        case 1:P2=~0x02;
                                               P0=~table[bai];
                                        break;
                                        case 2:P2=~0x04;
                                                   P0=~table[shi];
                                        break;
                                        case 3:P2=~0x08;
                                                   P0=~table[ge];
                                        break;
                                }
//              weila=weila-0x04;
                                delay(200);
        }
}

使用特权

评论回复
14
bryanlee512| | 2015-7-12 13:24 | 只看该作者
孤独枫 发表于 2015-7-12 12:36
AA是输入的16进制数据,这个数据通过串口由存入单片机读取寄存器SBUF,再把数据赋值给变量a ...

嗯,如果串口助手不选择16进制输入,输出的是什么类型的你知道么?我测了下貌似不是ascii码

使用特权

评论回复
15
孤独枫|  楼主 | 2015-7-15 21:33 | 只看该作者
bryanlee512 发表于 2015-7-12 13:24
嗯,如果串口助手不选择16进制输入,输出的是什么类型的你知道么?我测了下貌似不是ascii码 ...

就是ascii码

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

1

主题

19

帖子

0

粉丝