5784|17

78

帖子

0

TA的资源

一粒金砂(初级)

楼主
 

请教串口程序问题 [复制链接]

  1. #include
  2. #define uchar unsigned char
  3. #define uint unsigned int
  4. unsigned char flag,a,i;
  5. uchar code table[]="I get ";
  6. void init()
  7. {
  8.         TMOD=0x20;     //确定T1的工作方式
  9.         TH1=0xfd;                //计算T1的初值,装载TH1,TL1
  10.         TL1=0xfd;
  11.         TR1=1;                        //启动T1
  12.         REN=1;                        //确定串行口的工作方式
  13.         SM0=0;
  14.         SM1=1;
  15.         EA=1;
  16.         ES=1;
  17. }

  18. void main()
  19. {
  20.         init();
  21.         while(1)
  22.         {
  23.                 if(flag==1)
  24.                 {
  25.                         ES=0;                        //关闭串口中断,否则发送数据时同样申请中断,程序进入死循环
  26.                         for(i=0;i<6;i++)
  27.                         {
  28.                                 SBUF=table[i];
  29.                                 while(!TI);
  30.                                 TI=0;
  31.                         }
  32.                         SBUF=a;
  33.                         while(!TI);                //发送完毕后,TI会被硬件置1,跳出循环,说明数据发送完毕
  34.                         TI=0;                        //
  35.                         ES=1;
  36.                         flag=0;
  37.                 }
  38.         }
  39. }

  40. void ser() interrupt 4
  41. {
  42.         RI=0;                                //接受数据完成后,内部硬件置1,进入串口中断函数后
  43.         a=SBUF;                                //必须有软件清0
  44.         flag=1;                                //将flag置1,方便在主程序中检测
  45. }
复制代码

这个程序的功能是在上位机上用串口调试助手发送一个字符X,单片机收到后返回给上位机"I get X"
请问如何修改可以在上位机上用串口调试助手发送两个个字符X,单片机收到后返回给上位机"I get XX"

我弄了很久也没有弄出来了,麻烦各位了

最新回复

谢谢楼上大师级的回复  详情 回复 发表于 2010-4-24 16:07
点赞 关注

回复
举报

91

帖子

0

TA的资源

一粒金砂(初级)

沙发
 
我觉得这个你的定义好通信协议,比如上位机发送一个X给单片机,不能是单独的一个X,而是一个完整的命令桢,打个比方,你以:#作为起始符 %作为结束符号,那么命令桢就是:#X% 不过单片机通信你的把它们转换为ASC码:23 58 25;单片机再收到了这个命令桢后,就可以分析出的出X,从而返回给上位机:I Get X

同样的道理,当上位机发送:#XX%给单片机,单片机分析得出:XX,返回给上位机:I Get XX
 
 

回复

81

帖子

0

TA的资源

一粒金砂(初级)

板凳
 
问题的关键在于:介于通信起始符和结束符之间的内容!
通信协议对于串口通信很重要。
 
 
 

回复

82

帖子

0

TA的资源

一粒金砂(初级)

4
 
这就是普通51单片机的串口通信
 
 
 

回复

81

帖子

0

TA的资源

一粒金砂(初级)

5
 
for(i=0;i<6;i++) 改成i<7发两个X就行了
 
 
 

回复

59

帖子

0

TA的资源

一粒金砂(初级)

6
 
引用 4 楼 qzf368 的回复:

for(i=0;i<6;i++) 改成i<7发两个X就行了

不可以的
 
 
 

回复

75

帖子

0

TA的资源

一粒金砂(初级)

7
 
先定义一个数组,然后在中断程序里每接收一个字符就赋给这个数组。发送的时候循环取出发给上位机就行了。
 
 
 

回复

71

帖子

0

TA的资源

一粒金砂(初级)

8
 
粗略的看了下发送接收的代码,应该没问题的,初始化串口和配置方式代码就不知道了,因为很久没搞51了,

想问一下,具体的现象是什么?单片机什么都没接收到?还是单片机接收到了X,反馈给PC的时候,PC没收到?或者收到错误信息?

我觉得会不会是你PC串口配置和51的串口配置不对应,比如波特率,停止位,校验位等,,,,,,
 
 
 

回复

67

帖子

0

TA的资源

一粒金砂(初级)

9
 
试试看。
...//你原来的程序

uchar a[2]; //定义变量中把a去了,加一个数组a[2]。如果是更长的字符,数组长度要相应改变

...//你原来的程序

void main()
{
    init();
    while(1)
    {
        if(flag==1)
        {
            ES=0;            //关闭串口中断,否则发送数据时同样申请中断,程序进入死循环
            for(i=0;i<6;i++)
            {
                SBUF=table;
                while(!TI);
                TI=0;
            }
          for(i=0;i<2;i++) //发送数组内容
            {
                SBUF=a;
                while(!TI);
                TI=0;
            }
            ES=1;
            flag=0;
        }
    }
}

void ser() interrupt 4
{                    
     uchar j;
     for(j=0; j<2; i++) //接收两个字符
       {
         while(!RI);
         RI=0;
         a=SBUF;
        }
    flag=1;                //将flag置1,方便在主程序中检测
}

 
 
 

回复

64

帖子

0

TA的资源

一粒金砂(初级)

10
 

  1. char revbuff[1000000]
  2. void ser() interrupt 4
  3. {
  4.     static int len=0;
  5.     RI=0;                //接受数据完成后,内部硬件置1,进入串口中断函数后
  6.      unsigned char a=SBUFF;
  7.     if(a=='\r'||a=='\n')
  8.     {flag=1;revbuff[len]=0;}
  9.     else
  10.         revbuff[len++]=a;                           
  11. }

  12. 在main内部
  13. void main()
  14. {
  15.   ...
  16.   if(flag)
  17.   {
  18.     flag=0;
  19.     strcpy(buff+6,revbuff);
  20.     uartouts(buff);
  21.   }

  22.   ...
  23. }
复制代码

 
 
 

回复

51

帖子

0

TA的资源

一粒金砂(初级)

11
 
引用 8 楼 xmjulytiger 的回复:

试试看。
...//你原来的程序

uchar a[2]; //定义变量中把a去了,加一个数组a[2]。如果是更长的字符,数组长度要相应改变

...//你原来的程序

void main()
{
    init();
    while(1)
    {
        if(flag==1)
        {
            ES=0;        ……


我之前试的和你的差不多,就是中断函数里少了一句:while(!RI);

现在接受字符的个数是可以达到了,但是有BUG
比如,设置发送4个字符
                发送1234,接受到的是4123(数据大小已设置好)
                发送12345,接收到的是4512(当然越界了,也许没什么课研究性,仅供参考)
      设置发送5个字符
                 发送12345,收到51234
                 发送123456,收到56123
 
 
 

回复

80

帖子

0

TA的资源

一粒金砂(初级)

12
 
我之前试的和你的差不多,就……
[/quote]

如果要发送多个数,试着加一个包头标识,比如0xFF(以十六进制数为例)。 要发12345,发送时就是FF 1 2 3 4 5。中断程序做小小改动,主程序中发送数组从a[1]开始发。
[code]
void ser() interrupt 4
{   
    uchar j;
    for(j=0; j<6; i++) //接收6个字符
    {  
        while(!RI);
        RI=0;
        a[j]=SBUF;
    }
    if(a[0]==0xff)
    {
        flag=1;
    }                //将flag置1,方便在主程序中检测
}
 
 
 

回复

83

帖子

0

TA的资源

一粒金砂(初级)

13
 
楼主用个数组不就可以了么?随便你收几个字符。
 
 
 

回复

60

帖子

0

TA的资源

一粒金砂(初级)

14
 
回LS的,我用的就是数组
  1. #include
  2. #include
  3. #define uchar unsigned char
  4. #define uint unsigned int
  5. unsigned char flag,a,i;
  6. uchar b[4];
  7. uchar code table[]="I get ";
  8. void init()
  9. {
  10.         TMOD=0x20;     //确定T1的工作方式
  11.         TH1=0xfd;                //计算T1的初值,装载TH1,TL1
  12.         TL1=0xfd;
  13.         TR1=1;                        //启动T1
  14.         REN=1;                        //确定串行口的工作方式
  15.         SM0=0;
  16.         SM1=1;
  17.         EA=1;
  18.         ES=1;
  19. }

  20. void main()
  21. {
  22.         init();
  23.         while(1)
  24.         {
  25.                 if(flag==1)
  26.                 {
  27.                         ES=0;                        //关闭串口中断,否则发送数据时同样申请中断,程序进入死循环
  28. //                        for(i=0;i<6;i++)
  29. //                        {
  30. ///                                SBUF=table[i];
  31. //                                while(!TI);
  32. //                                TI=0;
  33. //                        }
  34.                         for(i=0;i<4;i++)
  35.                         {
  36.                         SBUF=b[i];
  37.                         while(!TI);                //发送完毕后,TI会被硬件置1,跳出循环,说明数据发送完毕
  38.                         TI=0;
  39.                         }//
  40.                         ES=1;
  41.                         flag=0;
  42.                 }
  43.         }
  44. }

  45. void ser() interrupt 4
  46. {
  47.         uchar j;
  48.         for(j=0;j<4;j++)
  49.         {
  50.                 while(!RI);
  51.                 RI=0;
  52.                 b[j]=SBUF;
  53.                                                 //接受数据完成后,内部硬件置1,进入串口中断函数后
  54.                
  55.         }                                //必须有软件清0
  56.         flag=1;                                //将flag置1,方便在主程序中检测
  57. }
复制代码
 
 
 

回复

67

帖子

0

TA的资源

一粒金砂(初级)

15
 
void Com_Int(void) interrupt 4
{

         if(RI)
         {  
       RI = 0;
           stringaz[iaz++]=SBUF;
            if(SBUF == '*')
              {
               stringaz[iaz]='\0';
               iaz=0;
               record=1;
           }
          
     }

一个字符好解决,多个字符就是字符串了,字符串接受最好带个结束标志,不然就有问题,这是我的一个中断函数,参考下!
 
 
 

回复

78

帖子

0

TA的资源

一粒金砂(初级)

16
 
  1. #ifndef _SERIAL_CONFIG_H_
  2. #define _SERIAL_CONFIG_H_
  3. #include "const.h"
  4. #include "oscfrequencydef.h"

  5. #ifndef OSC_FREQUENCY
  6. #error undefined OSC_FREQUENCY
  7. #endif
  8. /***********************************************************************
  9. 仅限于串口方式1的工作模式,即1位起始位,8位数据位和1位停止位,无校验位
  10. 波特率不倍增
  11. ************************************************************************/

  12. typedef enum tagBAUD
  13. {
  14.         b_1200 = 1200,
  15.         b_2400 = 2400,
  16.         b_4800 = 4800,
  17.         b_9600 = 9600,
  18.         b_14400 = 14400,
  19.         b_19200 = 19200,
  20.         b_28800 = 28800,
  21.         b_38400 = 38400,
  22.         b_56000 = 56000,
  23.         b_57600 = 57600,
  24.        
  25.         //注意:115200已经超过两个字节的范围

  26.         INVALID_BAUD,

  27. }BAUD;


  28. typedef void (*RECVPROC)(BYTE byte);

  29. BOOL OpenSerial(BAUD Baud, RECVPROC pRecvFunc);
  30. void SendData(const BYTE* pData, BYTE nSize);
  31. void CloseSerial();


  32. #endif
复制代码
 
 
 

回复

68

帖子

0

TA的资源

一粒金砂(初级)

17
 

  1. #include "serialconfig.h"
  2. #include
  3. #include

  4. idata RECVPROC g_pfnRecvFunc = NULL;


  5. BOOL OpenSerial(BAUD Baud, RECVPROC pRecvFunc)
  6. {

  7.         idata BYTE LoadValue = 0;

  8.         if(pRecvFunc == NULL)
  9.                 return FALSE;
  10.                
  11.         g_pfnRecvFunc = pRecvFunc;

  12.         switch(Baud) //确保输入的波特率是正确的
  13.         {
  14. //                case b_1200:
  15. //                case b_2400:
  16.                 case b_4800:
  17.                 case b_9600:
  18.                 case b_14400:
  19.                 case b_28800:
  20.                 case b_19200:
  21.                 case b_38400:
  22.                 case b_57600:
  23.                         break;

  24.                 default:
  25.                         return FALSE;
  26.                         break;
  27.         }       



  28.         /*****************************************************************************
  29.         LoadValue = 256 -        OSC_FREQUENCY * 10^6 / (384 * Baud)
  30.         因每次运算的结果上限限制,故做了变换
  31.         ******************************************************************************/       
  32.         LoadValue = 256 - (BYTE)(1000 * 1.0f * (float)OSC_FREQUENCY / 384 * 1000 * 1.0f / Baud);

  33.           


  34.         TMOD |= T1_M1_;        //定时器T1工作方式2
  35.         TH1 = LoadValue;               
  36.         TL1 = LoadValue;   //不可TL1 = TH1赋值
  37.         PCON = 0x00;        //波特率不倍增   
  38.         SCON = 0x50;        //串行通信方式1,允许接收                  
  39.         TR1 = 1;                //启动定时器1



  40.         ES = 1;                        //开串行中断  
  41.         EA = 1;         //开总中断

  42.         return TRUE;
  43. }


  44. void CloseSerial()
  45. {
  46.         TR1 = 0;                //关定时器1
  47.         ES = 0;                        //关串行中断  
  48. }



  49. void SendData(const BYTE* pData, BYTE nSize)
  50. {
  51.         BYTE i = 0;
  52.         ///////////////////////////////////////////////

  53.         //发送与接收中断不能同时工作,发送时必须关闭接收中断
  54.         ES = 0;
  55. //        if(pData == NULL || nSize == 0)         出于效率,不做检查
  56. //                return FALSE;

  57.         for(i = 0; i < nSize; i++)
  58.         {
  59.                 SBUF = pData[i];
  60.                 while(!TI);
  61.                 TI = 0;
  62.         }
  63.        
  64.         ES = 1;       


  65. }       

  66. void SerialISR() interrupt SIO_VECTOR
  67. {
  68.         RI = 0;
  69.         (*g_pfnRecvFunc)(SBUF);
  70. }
复制代码
 
 
 

回复

72

帖子

0

TA的资源

一粒金砂(初级)

18
 
谢谢楼上大师级的回复
 
 
 

回复
您需要登录后才可以回帖 登录 | 注册

随便看看
查找数据手册?

EEWorld Datasheet 技术支持

相关文章 更多>>
关闭
站长推荐上一条 1/7 下一条

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

About Us 关于我们 客户服务 联系方式 器件索引 网站地图 最新更新 手机版

站点相关: 国产芯 安防电子 汽车电子 手机便携 工业控制 家用电子 医疗电子 测试测量 网络通信 物联网

北京市海淀区中关村大街18号B座15层1530室 电话:(010)82350740 邮编:100190

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2025 EEWORLD.com.cn, Inc. All rights reserved
快速回复 返回顶部 返回列表