单片机串口通信问题

[复制链接]
3168|8
 楼主| victor3l 发表于 2012-6-15 15:52 | 显示全部楼层 |阅读模式
通过串口调试助手想单片机发送0x24,0x6a,0x45,0x0d这几个命令后单片机要返回16个字节的数据。我用出啊寻方法做了。但是在整个过程中要执行其他的功能,乳沟用这个程序就停在那里,当我用超时查询后就接不到数据了。我现在用中断
程序写成  
void  ser()interrupt 4
{
        uchar tempBuf[4] = {0};
        uchar i;
        uint count = 0;
        ES = 0;
        if(RI)        //这里表示有数据到了
        {
                RI = 0;
                for(i = 0; i < 4; i++)
                {
                        while(!RI&&(++count < 250) )//查询接收,并且超时检测  ,这里会等待数据,但也不是无限制的等待。
                        count = 0;
                        RI = 0        ;  //其实每接收一字节数据都会产生中断,当接收到一字节数据后就会退出,又去接收下一个字节的数据,直到接收4个后就退出循环
                        tempBuf[i] = SBUF;
                        delay(1);
                }
                if((0x24 == tempBuf[0]) && (0x6a == tempBuf[1]) && (0x45 == tempBuf[2]) && (0x0d == tempBuf[3]))
                        flag = 1;
        }
        ES = 1;
}

当我在串口调试助手中写入0x24 0x6a 0x45 0x0d 后要点5次发送才能在上面的接受栏中返回我要的数据,但是当重新上电时第一按下就能返回正常的数据。我的实际应用中上位机要求如果多次发送命令后没有数据返回,那么他就认为出错了,导致系统不能用了。我该如何处理这种发送不灵敏问题?我在主函数中判断flag如果他为1,我就让单片机发送返回数据。
阮天宇00 发表于 2012-6-15 16:18 | 显示全部楼层
用全局变量,别在函数里面定义变量。
RI=1后函数被调用你的 tempBuf[4] = {0}; count = 0;等等变量又要重定义。
你的做法,理论上应该实现不了你的功能的。
我是菜鸟别拍啊。

我在单位写程序,全局变量都要慎用,因为用的是C8051f的,没必要的全局变量一律不给用.做我旁边的哥们玩ARM的,我问他怎么用单片机接收1K的数据,回答:定义一个a[1000]数组……其实是大实话。

串口通了,单片机就差不多能上手了。加油哥们。
阮天宇00 发表于 2012-6-15 16:26 | 显示全部楼层
void Uart_Isr() interrupt 4 using 1
{
        static unsigned char cReceivedData;
        static unsigned char cCheckSum;
        if (RI)
        {   
                cReceivedData = SBUF;
                RI = 0;
                if (g_bReceiveAA)
                {
                        g_bReceiveAA = 0;
                        if (0xBB == cReceivedData)
                        {
                                g_bReceivePackageStart = 1;
                                g_cReceiveCounter = 0;
                                cCheckSum = 0;
                        }
                }
                else
                {
                        if (0xAA == cReceivedData)
                        {   
                                g_bReceiveAA = 1;
                        }
                        if (g_bReceivePackageStart)
                        {
                                g_cReceiveBuffer[g_cReceiveCounter] = cReceivedData;
                                cCheckSum ^= cReceivedData;

                                if (g_cReceiveCounter == g_cReceiveBuffer[0] && g_cReceiveCounter > 1)
                                {
                                        if (0 == cCheckSum)
                                        {
                                                g_bReceiveOK = 1;
                                                ES = 0;
                                        }
                                        g_bReceiveAA = 0;
                                        g_cReceiveCounter = 0;
                                        g_bReceivePackageStart = 0;
                                }
                                else
                                {
                                        g_cReceiveCounter++;
                                }
                                if (g_cReceiveCounter >= sizeof(g_cReceiveBuffer))
                                {
                                        g_cReceiveCounter = 0;
                                        g_bReceiveAA = 0;
                                        g_bReceivePackageStart = 0;
                                }
                        }
                }
        }
        if (TI)
        {
                TI = 0;
        }
}

程序很简单所以没注释,
举例:g_cReceiveCounter,G代表全局变量,C代表char型,后面的就英文变中文就明白了。(老板让我把程序写的不用注释就能很简单的看明白……)
这段程序实现 指令头0XAA,0XBB,以及长度字,校验码(异或)判断接受数据与否。

不知道对你有用没。
wangkangming 发表于 2012-6-28 13:20 | 显示全部楼层
LS的哥们牛啊!
LZR13179 发表于 2012-6-28 14:23 | 显示全部楼层
楼主你好,我最近也在研究串口通信。遇到一个问题想请教你。在51单片机和Proteus 虚拟串口调试时,单片机可以向电脑发送数据,但是电脑发给单片机的数据不可以接收
LZR13179 发表于 2012-6-28 14:23 | 显示全部楼层
  1. #include <reg52.h>
  2. #include<stdio.h>
  3. #define uchar unsigned char
  4. #define uint unsigned int
  5. uchar code table[]="I get";
  6. bit flag;//外部接收数据标志位
  7. uchar a;//串口接收数据寄存
  8. send()
  9.         {
  10.                 uint i;
  11.                 ES=0;
  12.                 for(i=0;i<6;i++)
  13.                         {
  14.                                 SBUF=table[i];
  15.                                 while(!TI);       
  16.                                 TI=0;
  17.                         }
  18.                  SBUF=a;
  19.                  while(!TI);
  20.                  TI=0;
  21.                  ES=1;
  22.                  flag=0;
  23.         }
  24. Init_com()
  25.         {        P1=0XFF;
  26.                 TMOD=0x20;  //定时器T1 PCON &= 0xef;
  27.                 SCON=0x50;  //sm0=0,sm1=1为方式1;sm2=0;ren=1;
  28.                 TH1=0xfd; //波特率设置为9600
  29.                 TL1=0xfd;
  30.                 TR1=1; //开定时器T1运行控制位
  31.                 P1=0xff;//关闭led
  32.         }
  33. main()
  34.         {
  35.                 Init_com();          
  36.                   while(1)
  37.         {       
  38.                 if(flag==1)//只有先收到来自电脑的信号后单片机才将数据发给电脑
  39.                         {
  40.                                 send();
  41.                         }
  42.                  
  43.         }       
  44. }
  45. void ser() interrupt 4
  46.         {
  47.                 RI=0;
  48.                 a=SBUF;
  49.                 flag=1;
  50.                 P1=0;//用来测试有收到电脑的信号
  51.         }
chrishardy 发表于 2012-11-20 19:18 | 显示全部楼层
3楼好牛!
demaxiya 发表于 2012-11-23 09:44 | 显示全部楼层
6# LZR13179
看了下 这个是郭天祥那书里的程序吧 程序本身应该是没问题的 我调试过这个程序 你看下你COMPIM里的设置和串口调试助手的设置是否一致 另外就是虚拟串口一定要使用配对的
zf_015820 发表于 2012-11-23 10:20 | 显示全部楼层
各位,使用各种中断的兄弟 们,如果 在中断中,禁止中断了,处理完中断程序后,再开中断,理论上OK,但,实际上,你这么操作时,经常会出问题,导致单片机不响应了; 我们正常要在中断禁止后,DELAY一些时间再开中断;我当前的做法:比较少禁止中断,中断后,处理即可(只用到串口与外部中断);如果用的中断多,等级也多,还是建议禁止中断后,再开,但是,一定要延时,否则,会出现,不能及时响应的情况
您需要登录后才可以回帖 登录 | 注册

本版积分规则

77

主题

308

帖子

5

粉丝
快速回复 在线客服 返回列表 返回顶部