打印

关于通信的一个问题20分啊 不够我再加

[复制链接]
2436|15
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
zxx6176|  楼主 | 2011-7-30 17:41 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式
#include<reg52.h>          //包含单片机寄存器的头文件
/******************************************************
函数功能:结合搜一个字节数据
*****************************************************/
unsigned char Receive(void)
{
unsigned char dat;
while(RI==0);            //只要接受中毒那标志位RI没有被置"1"
RI=0;                    //等待,直至接受完毕(RI=1)
dat=SBUF;                //将接受缓冲器中的数据存于dat
return dat;
}
unsigned char const dofly[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};// 显示段码值01234567
unsigned char code  seg[]= { 0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f}  ;        //分别对应相应的数码管点亮,即位码
unsigned char flag_get,count,num,minute,second;
void delay(unsigned int cnt)  //延时函数
{
while(--cnt);
}
/*******************************************************
函数功能:主函数
*******************************************************/
void main(void)
{
TMOD=0X20;               //定时器 T1 工作于方式2
SCON=0X50;               //SCON=0101 0000B,串口工作方式1,允许接受(REN=1)
PCON=0X00;               //PCON=0000 0000B,波特率9600
TH1=0xfd;                //根据规定给定时器T1 赋初值
TL1=0xfd;                //根据规定给定时器T1 赋初值
TR1=1;                   //启动定时器T1
REN=1;                  //允许接受
while(1)
{
   P0=Receive();
}
}

这是原程序, 程序没有问题。 就是想问的是 最后 P0=Receive();
这里只能加这一句,加个别的 或者加 delay 函数 都无用, 是不是通信 需要加中断函数啊
还是 我的函数太简单了  可是在网上搜了很多 都运行不出来 这个 起码 能传一个 字符
请各位大虾指教,  在下 不甚感激  在下的通信这方面 知识匮乏, 希望大家不要一句一带而过 能不能 指出的详细一些  或者 说个资料 小弟 自己去查 谢谢!!!

相关帖子

沙发
acgean| | 2011-7-30 18:16 | 只看该作者
由于这里没有使用中断方式, 而是查询的方式, 所以, 要求不停地执行 Receive(); 否则(比如 delay 后) 可能响应不够, 甚至丢失部分接收的数据.
所以这样的程序通常不能用作实用. 比较好的办法, 就是用 中断方式.
软件设置个 FIFO 队列, 由中断将接收到的数据放入 FIFO 中, 然后主程序可以忙别的事情, 只要隔段时间能来处理一下 FIFO 接收的数据就行了.

使用特权

评论回复
板凳
NE5532| | 2011-7-30 20:27 | 只看该作者
中断不中断要看你咋写了,如果上位机发一个过来就不会再发了,等着这边回应,而且程序也没有其他事情需要做,就可以这样。楼主的问题在于没有从整个系统的高度去考虑程序结构,所以出现捉襟见肘的问题。

使用特权

评论回复
地板
forget121| | 2011-7-30 22:32 | 只看该作者
看你接收的设计咯...

使用特权

评论回复
5
torin| | 2011-7-31 22:00 | 只看该作者
没有采用接收中断,而是不断查询,又想兼顾其他程序的运行,就会两败俱伤了,Receive()等待接收,其它函数就没法运行,

使用特权

评论回复
6
lixiaoxu2meng| | 2011-8-1 09:03 | 只看该作者
建议楼主 还是采用接收中断
通常使用串口 接收都是用中断的 发送可以不用
你这样写不太符合编程习惯 而且如果你再想添加别的代码就不太好办  因为 Receive();
始终占用CPU,导致别的程序不能运行。

使用特权

评论回复
7
lixiaoxu2meng| | 2011-8-1 09:08 | 只看该作者
楼主可以参考下
//***************************//
//函数名:main()
//函数描述:主函数
//***************************//
void main()
   {
     P0=0xff;       //将P0口置1
     SCON=0x50;     //置串行口工作方式1,此时REN为1允许接收
     PCON=0x00;     //置SMOD=0
     TMOD=0x20;     //置定时/计数器1工作方式2
     EA=1;          //CPU开中断
     ES=1;          //串口开中断
     TH1=0xFD;            //产生9600波特率的时间常数(晶振频率为11.0592MHZ)
     TL1=0xFD;
     TR1=1;          //启动定时/计数器1
     while(1)
           {}
   }
//***************************//
//函数名:void uart(void)interrupt 4
//函数描述:串口接收中断函数
//***************************//

void uart(void)interrupt 4    //串行口中断服务程序
{
    ES=0;                              //串口关中断
   if(RI==1)                  //如果RI=1则说明这个中断是我们要产生的 顺序执行这个中断
   {
         RI=0;                //清中断标志
         P0=SBUF;         //接收数据送缓冲区recive中  即读出接收到的数据         
   }
    ES=1;                           //串口开中断
}

使用特权

评论回复
8
zxx6176|  楼主 | 2011-8-1 17:34 | 只看该作者
#include <reg51.h>
#include <intrins.h>
#define uchar unsigned char
#define uint  unsigned int
sbit dianji=P1^5; //控制电机开关
unsigned char recdata;   //RS232收到的值
void rs232(void);
void delay(uint t);
void main(void)  //串口初始化
{
E=0;   //取消LCD对LED的影响
RW=0;
RS=1;
TMOD=0x20;   // 定时器1定时方式2
TH1=0xfd;     //  11.0592MHz  9600波特率
TL1=0xfd;
SCON=0x50;  //串口方式1,允许接收
TR1=1;  // 启动定时器1
REN=1;
IE=0x90;
while(1)
{
   if(recdata==0x01)
   {
   dianji=1;
   delay(10000);
          dianji=0
   }
}  
}
//以下为串口中断程序
void rs232(void) interrupt 4
{
  if(RI==1)
{
  RI=0;
  recdata=SBUF;      
  SBUF=recdata;
}
else{TI=0;}
}      
  
//延时程序 延时t毫秒
void delay(uint t)
{
   while(t--);
}
我又找了个 步进电机的程序,可是 我只能传一个0x01字符 他开始转, 经过延时后,不会 自己停,我现在有思路了 就是 加中断,不断的 检查程序,可是 怎么加啊 郁闷!!!
7# lixiaoxu2meng

使用特权

评论回复
9
zxx6176|  楼主 | 2011-8-1 17:42 | 只看该作者
哦 谢谢诶  我也感觉自己做的程序 思路就是有很大的问题,
我就是想 加进去中断, 把中中断打开,我看 常用的 就是 ,查询RI 然后 把缓存的 提取进来进来,帮我看下 这段 中断 行不行 我的程序 就是想 完成DELAY(),然后让一个电机能够持续运行1S 左右

void rs232(void) interrupt 4
{
  if(RI==1)
{
  RI=0;
  recdata=SBUF;      
  SBUF=recdata;
}
else{TI=0;}
}  
我看很多书上写的 TI和 RI 是需要软件清零 取消此中断申请的 不知道 我的理解 对不对


3# NE5532

使用特权

评论回复
10
joyme| | 2011-8-1 18:14 | 只看该作者
SBUF=recdata;

这个语句会将发送的数据传回,不需要的话,就不用

delay(10000);dianji =0; 加一句recdata =0;不要让recdata一直等于0x01,否则程序还没停电机又马上开了,所以你看不多电机停

使用特权

评论回复
11
NE5532| | 2011-8-1 19:27 | 只看该作者
别写程序,画流程图。

使用特权

评论回复
12
zxx6176|  楼主 | 2011-8-2 19:01 | 只看该作者
11# NE5532
这是我的 流程图 我就是想 接收到0x01时,电机转0.1S 然后自动停止, 不知道 为什么 灯可以做到,但 电机 却 自己 在那里不停的转!!!

1.jpg (29.1 KB )

1.jpg

使用特权

评论回复
13
zxx6176|  楼主 | 2011-8-3 18:26 | 只看该作者
请问 谁有 中断方式的 串口通信啊?

使用特权

评论回复
14
joyme| | 2011-8-4 09:07 | 只看该作者
#include <reg51.h>
#define uchar unsigned char
uchar xdata r_buf[32];
uchar xdata t_buf[32];
uchar r_in,r_out,t_in,t_out;   /*定义发送、接收“指针”*/
bit r_full,t_empty,t_done;     /*定义接收区满,发送区空,发送完成标志*/
code uchar m[]={"this is a test program\r\n"};
serial()interrupt 4 using 1
{if(RI&&~r_full)               /*是接收中断且接收缓冲区未满*/
    {r_buf[r_in]=SBUF;        /*接收*/
     RI=0;                    /*淸标志*/
     r_in=++r_in&0x1f;        /*下标+1*/
     if(r_in==r_out)r_full=1; /*判断是否要置r_full标志*/
     }
else if (RI&&~t_empty)       /*是发送中断且发送缓冲区未空*/
         {SBUF=t_buf[t_out];  /*接收*/
          TI=0;               /*淸标志*/
          t_out=++t_out&0x1f; /*下标+1*/
          if(t_out==t_in)t_empty=1;/*判断是否要置t_empty标志*/
          }
else if (TI)                 /*是发送中断且发送缓冲区已空*/
         {TI=0;t_done=1;}     /*置t_done标志*/
}
void loadmsg(uchar code *msg)
{while((*msg!=0)&&((((t_in+1)^t_out)&0x1f)!=0))
      {t_buf[t_in]=*msg;
       msg++;
       t_in=++t_in&0x1f;
       if(t_done)
         {TI=1;
          t_empty=t_done=0;
          }
       }
}
void process(uchar ch){return;}
void processmsg(void)
{while(((r_out+1)^r_in)!=0)
      {process(r_buf[r_out]);
       r_out=++r_out&0x1f;
       }
}
main()
{TMOD=0x20;TH1=0xfd;TR1=1;SCON=0x50;IE=0x90;
t_empty=t_done=1;     /*初始化为“发送完成“*/
r_full=0;       /*允许接收*/
r_out=t_in=t_out=0;   /*接收发送区边界*/
r_in=1;       /*接收“指针”为0*/
for(;;){
         loadmsg(&m);
         processmsg();
         }
}

使用特权

评论回复
15
lixiaoxu2meng| | 2011-8-4 09:24 | 只看该作者
12# zxx6176
unsigned char data;
unsigned char ID;

//***************************//
//函数名:main()
//函数描述:主函数
//***************************//
void main()
   {
     P0=0xff;       //将P0口置1
     SCON=0x50;     //置串行口工作方式1,此时REN为1允许接收
     PCON=0x00;     //置SMOD=0
     TMOD=0x20;     //置定时/计数器1工作方式2
     EA=1;          //CPU开中断
     ES=1;          //串口开中断
     TH1=0xFD;            //产生9600波特率的时间常数(晶振频率为11.0592MHZ)
     TL1=0xFD;
     TR1=1;          //启动定时/计数器1
     ID = 0;
     data = 0;
     while(1)
           {
            if(ID == 1)
            {
                 ID  = 0;
                 //电机转
                 //延时 0.1s
                  //电机停止
             }
}
   }
//***************************//
//函数名:void uart(void)interrupt 4
//函数描述:串口接收中断函数
//***************************//

void uart(void)interrupt 4    //串行口中断服务程序
{
    ES=0;                              //串口关中断
   if(RI==1)                  //如果RI=1则说明这个中断是我们要产生的 顺序执行这个中断
   {
         RI=0;                //清中断标志
         data=SBUF;         //接收数据送缓冲区recive中  即读出接收到的数据   
         if(dat == 0x01)   
         ID = 1;   
   }
    ES=1;                           //串口开中断
}

使用特权

评论回复
16
草履虫| | 2011-8-4 23:10 | 只看该作者
本帖最后由 草履虫 于 2011-8-4 23:18 编辑

楼上:程序中的关中断和开中断这两句,很没用.
不知道LZ是想写一个实用的,还只是想让电机按串口接收的数据动一下就行了.
main()
{
变量初始化.
串口初始化.
定时器初始化.
开串口中断.
while(1){
           if(串口接收到数据){
              if(目前电机是关的且数据==0x01){
                     打开电机;
                     定时器清0;
                     打开定时器中断;
              }
              清串口数据或接收到数据的标志;
   
           }
           if(电机是开的且到了0.1S){
                 关电机;
                 关定时器中断;
           }
      }
}
串口中断程序
{
}

定时器中断程序
{

}

使用特权

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

本版积分规则

0

主题

60

帖子

1

粉丝