打印
[51单片机]

【求助】救命啊!写的通信程序只能跑一遍...

[复制链接]
1004|14
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
用的是STC89C52RC的单片机,程序想实现的功能大概是通过计时器0计时学习板上的两个按键开关分别闭合的时间间隔t,得到t以后和一些常数运算得到v,然后再将v传输到另一个单片机上去,波特率由计时器1设置。

但是我把程序下载好了以后,用串口监视器查看传输的数据却发现,只有打开单片机后的第一次运行能得到可以正确反映开关闭合时间差异的数据,后面得到的都是00。
在下单片机新手,苦寻半天也未能发现原因,恳请各位前辈高人不吝赐教:'(

#include <reg52.h>

unsigned int time,t,v;

const s=3000;

void Delay(unsigned int xms);
void Init();
void Transmit();

void main()
{
  Init();
  while(1)
  {
    if(k1==0)
        {
          Delay(10);  //开关消抖
          if(k1==0)
          {
                time=0;
                TH0=0x4c;
                TL0=0x00;
                TR0=1;
                while(k2==1);
                TR0=0;
                Transmit();
          }
        }
  }
}

void Delay(unsigned int xms)
{
    unsigned int i,j;
        for(i=xms;i>0;i--)
          for(j=112;j>10;j--);
}

void Init()
{
  TMOD=0x21;                //计数器0计时用,计数器1波特率
  TH0=0x4c;                        //计数器0初值,一次循环为50ms
  TL0=0x00;
  TH1=0xfd;                        //设置计数器1的初值,决定波特率
  TL1=0xfd;               
  PCON=0x00;      // 波特率不倍增
  SCON=0x50;                //设置工作方式1 开启接受允许
  EA=1;
  ES=1;
  ET0=1;
  TR1=1;
}

void count() interrupt 1
{
  TH0=0x4c;
  TL0=0x00;
  time++;
}

void Transmit()
{
  t=50*time;
  v=s/t;
  SBUF=time;
  while(!TI);
  TI=0;
}

相关帖子

沙发
舟锐央|  楼主 | 2015-8-24 17:10 | 只看该作者
不好意思忘了说...k1和k2是开关,电路图如下

QQ截图20150824162937.png (67.6 KB )

串口监视器

串口监视器

QQ截图20150824170812.png (6.53 KB )

开关电路图

开关电路图

使用特权

评论回复
板凳
kafeng| | 2015-8-24 19:03 | 只看该作者
SBUF是个8位的,以ASCII码传输,这样直接把一个16位的unsigned int扔进去恐怕不行吧,LZ。

使用特权

评论回复
地板
努力的微笑| | 2015-8-24 19:56 | 只看该作者
我也是啊  用gsm模块  接受短信 控制灯的开关  明明写在大循环里  只能执行一次 开关 然后就失效了

用P3.0 和P3.1口的通信

更悲剧的是  单片机写进这个程序以后 重新写程序写不进去了  之前写的程序一直在里面运行  

是不是之前的程序覆盖了下载程序的信号啊

希望有前辈能不吝赐教   小弟先行谢过了

使用特权

评论回复
5
舟锐央|  楼主 | 2015-8-24 23:21 | 只看该作者
kafeng 发表于 2015-8-24 19:03
SBUF是个8位的,以ASCII码传输,这样直接把一个16位的unsigned int扔进去恐怕不行吧,LZ。 ...

啊!谢谢帮忙!
我忽略了这点...这样直接把一个16位的数据输入是不是会丢失高八位啊?
不过我修改之后还是不能运行...程序问题应该不是出在这里

使用特权

评论回复
6
songchenping| | 2015-8-25 07:30 | 只看该作者
是不是没有清什么东西啊。只运行一次。

使用特权

评论回复
7
ningling_21| | 2015-8-25 08:24 | 只看该作者
开串口中断却没有 中断服务程序,串口发送数据时先关串口中断,发送完再开中断

使用特权

评论回复
8
kafeng| | 2015-8-25 08:47 | 只看该作者
本帖最后由 kafeng 于 2015-8-25 11:20 编辑
ningling_21 发表于 2015-8-25 08:24
开串口中断却没有 中断服务程序,串口发送数据时先关串口中断,发送完再开中断 ...

哇,大神果然厉害,LZ把Transmit()改成这样试试
void Transmit()
{
ES=0;
*
*
*
*
ES=1;
}

我也是新手~~:),然后还想向大神求教一下,把楼主的程序改成上面那样之后用Proteus仿真,确实输出了16位的数据,那样数据貌似没有丢失。那是不是只要在接收程序里组合处理一下就可以得到正确的值。但这个的串口缓存SBUF只有8位呀,感觉怎么像BUG一样,大神能不能再解释下:dizzy:。

使用特权

评论回复
9
舟锐央|  楼主 | 2015-8-25 09:53 | 只看该作者
ningling_21 发表于 2015-8-25 08:24
开串口中断却没有 中断服务程序,串口发送数据时先关串口中断,发送完再开中断 ...

...一语惊醒梦中人!多谢多谢!:lol
不过还想问一下开了全局中断和中断源允许却没有写中断服务程序会怎么样?为什么我的程序一直输出00呢?

使用特权

评论回复
10
舟锐央|  楼主 | 2015-8-25 10:01 | 只看该作者
kafeng 发表于 2015-8-25 08:47
哇,大神果然厉害,LZ把Transmit()改成这样试试
void Transmit()
{

对啊!我这程序根本不需要用串口中断...
我直接把 Init() 函数里的 ES=1; 删掉了,运行就正常了,不过我不明白为什么没写串口中断服务程序就会一直输出00.....
想问一下怎么输出的16位数据?我也想不通...因为我没有用Proteus,串口监视器上只有输出8位,能不能请你截个图给我看看?谢谢!

使用特权

评论回复
11
ningling_21| | 2015-8-25 10:01 | 只看该作者
kafeng 发表于 2015-8-25 08:47
哇,大神果然厉害,LZ把Transmit()改成这样试试
void Transmit()
{

16位数据肯定要分2次接收,第二个数据到来也需要时间,一般数据处理不会有问题

使用特权

评论回复
12
kafeng| | 2015-8-25 10:51 | 只看该作者
本帖最后由 kafeng 于 2015-8-25 11:30 编辑
舟锐央 发表于 2015-8-25 10:01
对啊!我这程序根本不需要用串口中断...
我直接把 Init() 函数里的 ES=1; 删掉了,运行就正常了,不过 ...

其实输出的是两个8位的,加起来16位,LZ的 00 不就是16bit吗,一个8bit,把串口监视器调到16进制模式。下面是调到16进制接收到的数据,然后程序是这样,其他没改。下面仿真里这些翻译出来貌似都不是可打印字符,如果用字符形式接收貌似都会是空白。
void Transmit()
{
  ES=0;
  t=50*time;
  v=s/t;
  SBUF=time;
  while(!TI);
  TI=0;
  ES=1;
}


E:\MCU\1

使用特权

评论回复
13
kafeng| | 2015-8-25 10:55 | 只看该作者
本帖最后由 kafeng 于 2015-8-25 11:24 编辑
舟锐央 发表于 2015-8-25 10:01
对啊!我这程序根本不需要用串口中断...
我直接把 Init() 函数里的 ES=1; 删掉了,运行就正常了,不过 ...

把数据放入SBUF自动发送,应该不需要特别写一个中断函数。LZ能不能把改了之后的程序再发上来,总感觉一次扔16位到SBUF里有点不对劲。

使用特权

评论回复
14
舟锐央|  楼主 | 2015-8-25 12:30 | 只看该作者
kafeng 发表于 2015-8-25 10:51
其实输出的是两个8位的,加起来16位,LZ的 00 不就是16bit吗,一个8bit,把串口监视器调到16进制模式。下 ...

我还不太会用串口监视器...我按下两个开关之后单片机只会触发一次Transmit(),串口监视器上也只有八位,所以我不知道16位丢进SBUF到底是发送两次还是一次.....
字符的话,我传输的本来就是数据,要传输到另一个单片机上处理的,所以不是可打印字符也正常吧。
我改过的程序和原来基本一样,只是把串口中断关了。
#include <reg52.h>

unsigned int time,t,v;

const s=3000;

void Delay(unsigned int xms);
void Init();
void Transmit();

void main()
{
  Init();
  while(1)
  {
    if(k1==0)
        {
          Delay(10);  //开关消抖
          if(k1==0)
          {
                time=0;
                TH0=0x4c;
                TL0=0x00;
                TR0=1;
                while(k2==1);
                TR0=0;
                Transmit();
          }
        }
  }
}

void Delay(unsigned int xms)
{
    unsigned int i,j;
        for(i=xms;i>0;i--)
          for(j=112;j>10;j--);
}

void Init()
{
  TMOD=0x21;           
  TH0=0x4c;                  
  TL0=0x00;
  TH1=0xfd;                        
  TL1=0xfd;               
  PCON=0x00;     
  SCON=0x50;              
  EA=1;
  ET0=1;
  TR1=1;
}

void count() interrupt 1
{
  TH0=0x4c;
  TL0=0x00;
  time++;
}

void Transmit()
{
  t=50*time;
  v=s/t;
  SBUF=v;
  while(!TI);
  TI=0;
}

使用特权

评论回复
15
ningling_21| | 2015-8-25 13:01 | 只看该作者
舟锐央 发表于 2015-8-25 10:01
对啊!我这程序根本不需要用串口中断...
我直接把 Init() 函数里的 ES=1; 删掉了,运行就正常了,不过 ...

输出16位数据需要分2次,先发送高8位,再发送低8位

使用特权

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

本版积分规则

1

主题

11

帖子

0

粉丝