打印

单片机串口通信问题

[复制链接]
2567|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的哥们牛啊!

使用特权

评论回复
5
LZR13179| | 2012-6-28 14:23 | 只看该作者
楼主你好,我最近也在研究串口通信。遇到一个问题想请教你。在51单片机和Proteus 虚拟串口调试时,单片机可以向电脑发送数据,但是电脑发给单片机的数据不可以接收

使用特权

评论回复
6
LZR13179| | 2012-6-28 14:23 | 只看该作者
#include <reg52.h>
#include<stdio.h>
#define uchar unsigned char
#define uint unsigned int
uchar code table[]="I get";
bit flag;//外部接收数据标志位
uchar a;//串口接收数据寄存
send()
        {
                uint i;
                ES=0;
                for(i=0;i<6;i++)
                        {
                                SBUF=table[i];
                                while(!TI);       
                                TI=0;
                        }
                 SBUF=a;
                 while(!TI);
                 TI=0;
                 ES=1;
                 flag=0;
        }
Init_com()
        {        P1=0XFF;
                TMOD=0x20;  //定时器T1 PCON &= 0xef;
                SCON=0x50;  //sm0=0,sm1=1为方式1;sm2=0;ren=1;
                TH1=0xfd; //波特率设置为9600
                TL1=0xfd;
                TR1=1; //开定时器T1运行控制位
                P1=0xff;//关闭led
        }
main()
        {
                Init_com();          
                  while(1)
        {       
                if(flag==1)//只有先收到来自电脑的信号后单片机才将数据发给电脑
                        {
                                send();
                        }
                 
        }       
}
void ser() interrupt 4
        {
                RI=0;
                a=SBUF;
                flag=1;
                P1=0;//用来测试有收到电脑的信号
        }

使用特权

评论回复
7
chrishardy| | 2012-11-20 19:18 | 只看该作者
3楼好牛!

使用特权

评论回复
8
demaxiya| | 2012-11-23 09:44 | 只看该作者
6# LZR13179
看了下 这个是郭天祥那书里的程序吧 程序本身应该是没问题的 我调试过这个程序 你看下你COMPIM里的设置和串口调试助手的设置是否一致 另外就是虚拟串口一定要使用配对的

使用特权

评论回复
9
zf_015820| | 2012-11-23 10:20 | 只看该作者
各位,使用各种中断的兄弟 们,如果 在中断中,禁止中断了,处理完中断程序后,再开中断,理论上OK,但,实际上,你这么操作时,经常会出问题,导致单片机不响应了; 我们正常要在中断禁止后,DELAY一些时间再开中断;我当前的做法:比较少禁止中断,中断后,处理即可(只用到串口与外部中断);如果用的中断多,等级也多,还是建议禁止中断后,再开,但是,一定要延时,否则,会出现,不能及时响应的情况

使用特权

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

本版积分规则

77

主题

308

帖子

5

粉丝