打印

51单片机串口收发字符串求助

[复制链接]
10237|43
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
stcome|  楼主 | 2012-9-19 10:57 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
大家好,
小弟始终搞不懂串口中断与处理问题,是上位机发送数据是按时间一个个发的呢还是我程序中出现错误,下面程序我基于对单片机来说还不太懂,望大家指点指点是什么地方出错了,     程序目的是从上位机发送字符串,回车结束,下位机接受后返回原值!望各位大侠指教指教!!!!!!!!!谢谢

#include <reg52.h>

#define uchar unsigned char
#define uint  unsigned int


void delay(uint z)
{
        uint a,b;
        for (a=z; a>0; a--)
        for (b=114; b>0; b--);
}

void uartinit()                 //初始化子函数
{
        TMOD = 0X20;
        SCON = 0X50;
        TH1 = TL1 = 0XFD;    //晶振11.0592MHZ  波特率 9600
        TR1 = 1;
        ES = 1;
        EA = 1;
}


uchar *str;                                //指针存数据
uchar *cleanstr = "\0";         //清空数据的指针
uint Rflag = 0;                        //按受数据标志位
uint Tflag = 0;                        //发送数据标志位

void main()
{
        uartinit();
        while(1)
        {
                if(Rflag)                //按受数据标志位溢出
                {
                        Rflag = 1;                //归零
                        for (str; *str!='\n'; str++)  //从底位开始送数 回车结束
                        {
                                *str = SBUF;
                        }
                }

                if (Tflag)
                {
                        Tflag = 0;
                        for (str; *str!= '\0'; str++)
                        {
                                SBUF = *str;
                        }
                        if ('\0' == *str)
                        str = cleanstr;                                //发送完毕后指针清零
                }
        }
}

void uart() interrupt 4                                //串口中断函数
{
        ES = 0;
        if(RI)
        {
                Rflag = 1;
                RI = 0;
        }

        if (TI)
        {
                Tflag = 1;
                TI = 0;
        }
        ES = 1;
}

相关帖子

沙发
stcome|  楼主 | 2012-9-19 11:00 | 只看该作者
Rflag = 1;  改为 Rflag = 0
这有错,
还是不行!

使用特权

评论回复
板凳
xzhihui| | 2012-9-19 11:03 | 只看该作者
晶振和波特率,搭配的真有特点。
我也是新入门的,以为浅显的知识,我认为11.0592对波特率9600容易丢码,出错。

使用特权

评论回复
地板
xzhihui| | 2012-9-19 11:11 | 只看该作者
4M或12M晶振对应9600的波特率。
若还是出错,我的建议是多调试几次,加一些指示灯的指令在程序里面,看是哪一步没执行到。我有问题就是这样做的,虽然笨了点,但是简单,有效。

使用特权

评论回复
5
joyme| | 2012-9-19 11:16 | 只看该作者
把这些for都去掉,主程序本来就是循环执行的,不管是发送还是接受都是一个一个来的
接收:
*str++ = SBUF;
if(*(str-1) == '\n')
      Tflag = 1;                //碰到回车开始发送,注意这时PC要停止发送,防止冲突(半双工的情况)
发送:
SBUF = *str++;

使用特权

评论回复
6
stcome|  楼主 | 2012-9-19 16:10 | 只看该作者
呵呵,不行,接收不了数据,照你所说的,我修改了程序,如下:
#include <reg52.h>
#include <string.h>
#define uchar unsigned char
#define uint  unsigned int



void delay(uint z)
{
        uint a,b;
        for (a=z; a>0; a--)
        for (b=114; b>0; b--);
}

void uartinit()                 //初始化子函数
{
        TMOD = 0X20;
        SCON = 0X50;
        TH1 = TL1 = 0XFD;    //晶振11.0592MHZ  波特率 9600
        TR1 = 1;
        ES = 1;
        EA = 1;
}


uchar *str  ;                                //指针存数据
uchar *cleanstr = "\0";         //清空数据的指针
uint Rflag = 0;                        //按受数据标志位
uint Tflag = 0;                        //发送数据标志位

void main()
{
        uartinit();
        while(1)
        {
                if(Rflag)                //按受数据标志位溢出
                {
                 *str++ = SBUF;
          if(*(str-1) == '\n')
                  REN = 0;
                          


                }

                if (strcmp(str,"good")== 0)
                P1 = 0X00;
                delay(500);
                if( 0x00 != *str && 0xff != *str)
                SBUF = *str++ ;
        }
}

void uart() interrupt 4                                //串口中断函数
{
        ES = 0;
        if(RI)
        {
                Rflag = 1;
                RI = 0;
        }

        if (TI)
        {
                Tflag = 1;
               
                TI = 0;
               
        }
        ES = 1;
}
接收到good按回车确定输入,判断是good的话则关闭P1口,一开始时指针为什么是输出FF呢?
请教谢谢

使用特权

评论回复
7
joyme| | 2012-9-19 18:09 | 只看该作者
指针概念还有待学习
str每接收一个字节就会+1,比较不能这么用,同样后面的*str肯定是初值(没初始化就是0xff)

使用特权

评论回复
8
stcome|  楼主 | 2012-9-19 22:02 | 只看该作者
那么,这程序是要比较的话那怎么比较呢,STRCMP不是用指针变量去比较的么

使用特权

评论回复
9
teddeng| | 2012-9-20 01:27 | 只看该作者
3# xzhihui

你这个认识完全错了哈。

使用特权

评论回复
10
stcome|  楼主 | 2012-9-20 08:51 | 只看该作者
那请10楼发个小程序我看看

使用特权

评论回复
11
joyme| | 2012-9-20 10:48 | 只看该作者
//先要保证你的单片机相关配置没有问题,写一段程序供你参考吧

#define                MAX_BUF_LEN                  50

#define                SETBIT(val,bitnum)    val |= (1<<bitnum)
#define                CLRBIT(val,bitnum)          val &= ~(1<<bitnum)
#define                isBitSet(val,bitnum)  (val & (1<<bitnum) != 0)

#define                RXD_FIN                          0
#define                TXD_START                  1


uchar                rxd_buf[MAX_BUF_LEN] = {0};                                  //接收缓冲区
uchar                rxd_rdptr = 0;                                                            //缓冲区操作指针
uchar                rxd_wrptr = 0;
uchar                bflags = 0;

void uart() interrupt 4                                //串口中断函数
{
    uchar tmp;
        if(RI)
        {
                   RI = 0;
                   tmp = SBUF;
                  if(tmp == '\n')
                           SETBIT(bflags, RXD_FIN);
                  else
                     rxd_buf[rxd_wrptr++] = tmp;
        }
        if(TI)
        {
              TI = 0;
                  SBUF = rxd_buf[rxd_rdptr++];
                  if(rxd_rdptr == (rxd_wrptr - 1))         //发送完毕(结束符不发送),重新启动串口接受功能
                  {
                             rxd_rdptr = 0;
                          rxd_wrptr = 0;
                          REN = 1;
                  }
        }
}

void main()
{
  sys_config();
  uartinit();
  while(1)
  {
           if(isBitSet(bflags, RXD_FIN))
        {
                 SETBIT(bflags,TXD_START);                            
                CLRBIT(bflags,RXD_FIN);
                rxd_buf[rxd_rdptr++] = '\0';                 //加个字符串结束符,以便进行字符串比较
                REN = 0;
        }
       
        if(strcmp(str,"good") == 0)
            P0 = 0x0f;
       
        if(isBitSet(bflags,TXD_START))
        {
                 CLRBIT(bflags,TXD_START);
                SBUF = rxd_buf[rxd_rdptr++];                   //启动发送,后续字节在发送成功中断自动加载
        }
  }

}

使用特权

评论回复
12
mcuexplore| | 2012-9-20 11:32 | 只看该作者
#include <reg52.h>

#define uchar unsigned char
#define uint unsigned int

#define BUF_LEN 50

sbit dula = P2 ^ 6;
sbit wela = P2 ^ 7;

uint inbuf[BUF_LEN];

uchar flag, a, i, count;

void init();

void main()
{
    uint len = 0;

    init();   
    while (1)
    {
        while (inbuf[len] != '\0')

    len++;

        if (flag == 1)
        {
            flag = 0;   
            ES = 0;
            for (i = 0; i < len - 1; i++)
            {
                SBUF = inbuf[i];
                while (!TI);
                TI = 0;
            }
            ES = 1;     

        }
    }
}

void init()
{
    TMOD = 0x20;  
    TH1 = 0xfd;   
    TL1 = 0xfd;
    REN = 1;      
    SM0 = 0;      
    SM1 = 1;     
    EA = 1;      
    ES = 1;      
    TR1 = 1;      
}

void ser() interrupt 4
{
    uchar ch;

    if (RI)
    {
        RI = 0;
        count++;
        ch = SBUF;
        inbuf[count - 1] = ch;
        if (ch == '\n')
        {
            inbuf[count] = '\0';
            count = 0;
            flag = 1;
        }
    }
}

使用特权

评论回复
13
stcome|  楼主 | 2012-9-20 13:52 | 只看该作者
12楼的JOYME 程序不全,我也补了点,还是不行!呵
#include <reg52.h>
#include <string.h>

#define uchar unsigned char
#define uint unsigned int

#define                MAX_BUF_LEN                  50

#define                SETBIT(val,bitnum)    val |= (1<<bitnum)
#define                CLRBIT(val,bitnum)          val &= ~(1<<bitnum)
#define                isBitSet(val,bitnum)  (val & (1<<bitnum) != 0)

#define                RXD_FIN                          0
#define                TXD_START                  1


uchar                rxd_buf[MAX_BUF_LEN] = {0};                                  //接收缓冲区
uchar                rxd_rdptr = 0;                                                            //缓冲区操作指针
uchar                rxd_wrptr = 0;
uchar                bflags = 0;
uchar                                 * str;
void uart() interrupt 4                                //串口中断函数
{
    uchar tmp;
        if(RI)
        {
                   RI = 0;
                   tmp = SBUF;
                  if(tmp == '\n')
                           SETBIT(bflags, RXD_FIN);
                  else
                     rxd_buf[rxd_wrptr++] = tmp;
        }
        if(TI)
        {
              TI = 0;
                  SBUF = rxd_buf[rxd_rdptr++];
                  if(rxd_rdptr == (rxd_wrptr - 1))         //发送完毕(结束符不发送),重新启动串口接受功能
                  {
                             rxd_rdptr = 0;
                          rxd_wrptr = 0;
                          REN = 1;
                  }
        }
}

void main()
{
//  sys_config();
//  uartinit();
        TMOD = 0X20;
        SCON = 0X50;
        TH1 = TL1 = 0XFD;
        TR1 = 1;

  while(1)
  {
           if(isBitSet(bflags, RXD_FIN))
        {
                 SETBIT(bflags,TXD_START);                           
                CLRBIT(bflags,RXD_FIN);
                rxd_buf[rxd_rdptr++] = '\0';                 //加个字符串结束符,以便进行字符串比较
                REN = 0;
        }
        
        if(strcmp(str,"good") == 0)
            P0 = 0x0f;
        
        if(isBitSet(bflags,TXD_START))
        {
                 CLRBIT(bflags,TXD_START);
                SBUF = rxd_buf[rxd_rdptr++];                   //启动发送,后续字节在发送成功中断自动加载
        }
  }

}

使用特权

评论回复
14
stcome|  楼主 | 2012-9-20 13:53 | 只看该作者
13楼的mcuexplore,你的程序是可以,我正慢慢吸收,不过程序没有加消除旧数据的程序,呵呵

使用特权

评论回复
15
mcuexplore| | 2012-9-20 14:31 | 只看该作者
消除旧数据两个方法:
方法1:
在主函数ES=1;后面加上一句inbuf[0]='\0';

方法2:
在主函数ES=1;后面加上memset(inbuf, 0, len);
同时需要加上头文件: #include <string.h>

使用特权

评论回复
16
stcome|  楼主 | 2012-9-20 15:59 | 只看该作者
mcuexplore,
你的程序有D问题,一开始的时候会输出一串乱码,加上消除旧数据的其中一个方法都试过了,效果不太明显,我也正寻找是否其它地方有问题

使用特权

评论回复
17
stcome|  楼主 | 2012-9-20 16:18 | 只看该作者
for(clean=0; clean<=BUF_LEN; clean++)
                        inbuf[clean++] = '\0';
我在ES = 1后加了这两句,结果好多了,不过时不时还会出现上次残留下来的数据!

使用特权

评论回复
18
joyme| | 2012-9-20 16:28 | 只看该作者
我的程序是没有初始化,因为不知道你用的什么单片机,很显然你自己的初始化也不对,因为你没有使能串口中断,当然就不行啦,用中断必须保证ES = 1,否则连中断函数都进不了

程序思想是一样的,除了发送方式控制,他用的while(TI),我的程序是通过中断,运行的条件是你要配置好串口中断,即发送、接受中断都需要使能,另还要看你用的MCU,发送、接受中断是否共用同一个中断向量,如果是,这个软件就可以用(因你的程序是RI、TI在一个中断响应函数里做的,默认你的MCU是共用的,AVR ATMega系列的是分开的,即需要分别写两个中断处理函数)。

使用特权

评论回复
19
mcuexplore| | 2012-9-20 16:29 | 只看该作者
因为现在在公司 没有办法调试(单片机在家里) 晚上回家调试 确认一下 再回复你

使用特权

评论回复
20
stcome|  楼主 | 2012-9-20 17:07 | 只看该作者
:'(太感激了,那晚点我们再讨论!TKS

使用特权

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

本版积分规则

1

主题

43

帖子

0

粉丝