打印

急啊!单片机串口通信程序问题!(6.4更新中)

[复制链接]
7600|42
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
enjoy21cn|  楼主 | 2009-5-29 18:54 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
在此先感谢大家帮助,感谢大家的积极关注!
现在将原来的程序彻底推翻,重新进行编写,已经在实验板上测试成功。但还有以下几个问题:
1:输出的问题
   目前的输出是:
   TW GX45 MA200000 L000000000  BV40 CIS SK530 FD5000
   而我想要的结果是:
   CIS SK530 FD5000 TW GX45 MA200000 L000000000  BV40。
   但在复位后是可以的,即输出“CIS SK530 FD5000 TW GX45        MA200000 L000000000  BV40。”//
2:这个循环如何跳出去?这个问题已经解决了。在后面有注释的。
3:这个程序加了一段发送回车键0x0D的程序,
void SendEndChar(void)
{
    SBUF=0x0D;
while(TI==0){ }
TI=0;
}
现在可以发送数据了,但为什么驱动那边还是不识别呢?
请高手指点一下。因为驱动器和上位机通讯用的是ASIC码。

/************************************************************************************/
/*                                                                                  */
/*     晶振:11.0592MHZ                                    CPU型号:AT89S52         */
/*                                                                                  */                                             
/*                                                                                  */
/*     功能描述: 通过串口间隔一定时间输出一系列的指令                              */
/*                CIS SK530 FD5000 TW GX45 MA200000 L000000000  BV40。              */ 
/*                                                                                  */
/************************************************************************************/ 

#include <reg52.h>
#define uint unsigned int
#define uchar unsigned char

uchar a[3]={'C','I','S'};
uchar b[5]={'S','K','5','3','0'};
uchar c[6]={'F','D','5','0','0','0'};
uchar d[2]={'T','W'};
uchar e[4]={'G','X','4','5'};
uchar f[8]={'M','A','2','0','0','0','0','0'};
uchar g[10]={'L','0','0','0','0','0','0','0','0','0'};
uchar h[4]={'B','V','4','0'};
/*************************************************************************************
延时函数


**************************************************************************************/
void delay(uint i)   
{
  uint k;
  while(i--)
  for(k=0;k <1200;k++){;}
}
/**************************************************************************************
//串口初始化过程


****************************************************************************************/
void uini()   
{
  TMOD=0x20;
  TH1=0xfd;//波特率为9600
  TL1=0xfd;
  TR1=1;
  SCON=0x50;
}
/**************************************************************************************
//主程序

**************************************************************************************/
void main()
{
  uini();
  while(1)
  {
    uint i;
    for(i=0;i <3;i++) //发送第1个字符串
    {
    SBUF=a;
    while(!TI);       
    TI=0;
    }
    delay(1200); //延迟1200ms
    for(i=0;i <5;i++) //发送第2个字符串
    {
    SBUF=b;
    while(!TI);       
    TI=0;
    }
    for(i=0;i <6;i++) //发送第3个字符串
    {
    SBUF=c;
    while(!TI);       
    TI=0;
    }
    delay(1200); //延迟1200ms
    for(i=0;i <2;i++) //发送第4个字符串
    {
    SBUF=d;
    while(!TI);       
    TI=0;
    }
    delay(1200); //延迟1200ms
    for(i=0;i <4;i++) //发送第5个字符串
    {
    SBUF=e;
    while(!TI);       
    TI=0;
    }
    delay(1200); //延迟1200ms
    for(i=0;i <8;i++) //发送第6个字符串
    {
    SBUF=f;
    while(!TI);       
    TI=0;
    }
    delay(1200); //延迟1200ms
    for(i=0;i <10;i++) //发送第7个字符串
    {
    SBUF=g;
    while(!TI);       
    TI=0;
    }
    delay(3600); //延迟1200ms
    for(i=0;i <4;i++) //发送第8个字符串
    {
    SBUF=h;
    while(!TI);       
    TI=0;
    }
    delay(1200); //延迟1200ms
    while(1);程序死在这个地方了。
  }

相关帖子

沙发
ayb_ice| | 2009-5-29 20:08 | 只看该作者

已经开了中断,还查询什么...

使用特权

评论回复
板凳
ningling_21| | 2009-5-29 21:31 | 只看该作者

改成这样试试

#include <reg52.h>
#define uint unsigned int
uint i,j;
unsigned char flag,a;
void delay(uint);
void main()
{

TMOD=0x20;//设置定时器1为工作方式2
TH1=0xfd;//波特率是9600
TL1=0xfd;
TR1=1;
REN=1;
SM0=0;
SM1=1;
EA=1;//中断模式开
ES=1;
while(1)
{
while(1)
{
/* if(RI==1)查询方式
{
RI=0;
P1=SBUF;
}*/
if(flag==1)
{
ES=0;
flag=0;
SBUF='M';//28; 字符串
while(!TI);
TI=0;//定时器关
SBUF='A';//28;
while(!TI);
TI=0;
SBUF='2';//28;
while(!TI);
TI=0;
SBUF='0';//28;
while(!TI);
    TI=0;
SBUF='0';//28;
while(!TI);
    TI=0;
    SBUF='0';//28;
while(!TI);
TI=0;
SBUF='0';//28;
while(!TI);
TI=0;
SBUF='0';//28;
while(!TI);
TI=0;
ES=1;
break;
}

while(1)
{
            if(flag==1)
{
ES=0;
flag=0;
SBUF='F';//28; 字符串
while(!TI);
TI=0;//定时器关
SBUF='D';//28;
while(!TI);
TI=0;
SBUF='h';//28;
while(!TI);
TI=0;
SBUF='b';//28;
while(!TI);
    TI=0;
SBUF='8';//28;
while(!TI);
    TI=0;
    SBUF='0';//28;
while(!TI);
TI=0;
SBUF='0';//28;
while(!TI);
TI=0;
SBUF='0';//28;
while(!TI);
TI=0;
ES=1;
break;
}
}
}
}
}
/*延时i毫秒*/
void delay(uint i)
{
uint j;
    while(i--)
    {
    for(j=120;j <125;j++)
    {}
    }
}

void ser() interrupt 4
{
RI=0;
// P1=SBUF;
a=SBUF;
flag=1;
}

使用特权

评论回复
地板
enjoy21cn|  楼主 | 2009-5-29 22:40 | 只看该作者

是不是我的延时没起作用呢!

回2楼ayb_ice的查询已经关闭
/* if(RI==1)查询方式
{
RI=0;
P1=SBUF;
}*/


回3楼ningling_21,编译通过了,但输出不是所期望的
输出是“FDhb8000MA200000MA200000MA200000”

而我要的是“输出"MA20000"字符串后,延时120毫秒输出“FDhb8000”到串口。”
是不是我的延时没起作用呢!

使用特权

评论回复
5
zyboy| | 2009-5-30 15:25 | 只看该作者

程序写的真的。。。。有种想杀你的冲动

程序写的真的。。。。有种想杀你的冲动!

使用特权

评论回复
6
yzhj| | 2009-5-30 17:27 | 只看该作者

汇编式的c 还是山寨版的

建议这样做!
1、分成几个子函数,至少看起来更条理一些。
2、将要发送的数据赋值到一个数组,建立一个队列,并且赋值数据长度。
3、直接进入中断进行下次发送赋值,根据长度决定判断是否要继续发送。
4、主程序中设立必要的延时,计算一下9600的波特率发送完这些数据需要多长时间。
5、写代码时考虑一下层次感。抱歉,你的代码我根本就不想往下看所以也没有找到原因。

编译通过,只能说明语法正确,不能代表可以正常运行。因为编译器不关心你想干什么,只是检查你可以不可以这样做。

纯属建议,千人千面!!

使用特权

评论回复
7
mohanwei| | 2009-5-30 17:39 | 只看该作者

用printf()

使用特权

评论回复
8
刘前辈| | 2009-5-30 22:01 | 只看该作者

问题在?!这里,可以改一下。

......................

while(1)
{
/* if(RI==1)查询方式
{
RI=0;
P1=SBUF;
}*/
                             // if(flag==1)????!!!!
while(flag!=1);             //    {

ES=0;
flag=0;
SBUF='M';//28; 字符串
while(!TI);
TI=0;//定时器关
SBUF='A';//28;
while(!TI);
TI=0;
SBUF='2';//28;
while(!TI);
TI=0;
SBUF='0';//28;
while(!TI);
    TI=0;
SBUF='0';//28;
while(!TI);
    TI=0;
    SBUF='0';//28;
while(!TI);
TI=0;
SBUF='0';//28;
while(!TI);
TI=0;
SBUF='0';//28;
while(!TI);
TI=0;
ES=1;
                        //  }

while(1)
{
    if(flag==1)
{
ES=0;
flag=0;
SBUF='F';//28; 字符串
while(!TI);
TI=0;//定时器关
SBUF='D';//28;
while(!TI);
TI=0;
SBUF='h';//28;
while(!TI);
TI=0;
SBUF='b';//28;
while(!TI);
    TI=0;
SBUF='8';//28;
while(!TI);
    TI=0;
    SBUF='0';//28;
while(!TI);
TI=0;
SBUF='0';//28;
while(!TI);
TI=0;
SBUF='0';//28;
while(!TI);
TI=0;
ES=1;
}
..........

其它自己改。

使用特权

评论回复
9
刘前辈| | 2009-5-30 22:07 | 只看该作者

7楼说得对,应该调用库函数 printf()。

程序标准多了:

........

 printf(" MA20000" );

DELAY(120);

printf(" FDhb8000" );



........

使用特权

评论回复
10
jxmemail| | 2009-5-30 22:42 | 只看该作者

强悍

   这样的代码,谁能维护.

使用特权

评论回复
11
handrap| | 2009-5-30 23:20 | 只看该作者

哪有一个字符一个字符发的啊!

哪有这样一个一个字符发的啊,要把自己累死吗!
方法1.用前几楼说的printf()试试
方法2:将要发送的字符串给自己定义的发送数组(如TX_BUF[]),并用strlen()求得这个字符串的长度n。先手动发送TX_BUF[0],然后在串口中断程序自动发送乘下的,直到发送了n个字符。

哈,没代码哦,不好意思。

使用特权

评论回复
12
刘前辈| | 2009-5-31 10:28 | 只看该作者

求教11楼。

11楼的方法2挺吸引人,哪本书上有讲解?

我光有代码,虽然大部分看懂了,但还是希望有程序讲解。

能否在此互通有无?

使用特权

评论回复
13
yzhj| | 2009-5-31 13:07 | 只看该作者

11楼 是这个意思吧

void uart0_tx()
{
        if(uart0_tx_count>=uart0_tx_length)
            {
            bit_flag_uart0_tx_over=1;
            uart0_tx_count=0;
            uart0_tx_length=0;
            }
        else
            {
            SBUF=tx_buffer[uart0_tx_count];
            uart0_tx_count++;
            }
}

使用特权

评论回复
14
jweiok| | 2009-5-31 14:38 | 只看该作者

11L的串口中断发送应该是标准的方法吧


串口发送我都这么用的

使用特权

评论回复
15
zyboy| | 2009-5-31 14:46 | 只看该作者

没有什么标准,适用就行

对于串口需要大数据传输时候,用中断发送较好,不暂用CPU时间。

使用特权

评论回复
16
handrap| | 2009-5-31 17:03 | 只看该作者

用的人多了,就成了无形的标准了。

看来很多兄弟都是这么用的,用的人多了,自然就是好方法了!
13楼说的很对啊。

今天放假休息,比较有空就对这些代码做点注释。互通有无啦!

//串口中断程序
void serial_int(void) interrupt 4 using 2
{

    if(RI)        //串口接收中断,略过……
         {
 
         }

         else if(TI)
    {
        TI = 0;
        if(TX_Addr == TX_length)        //如果接收完毕
        {
            TX_ready = 0;    // 本次接收完毕标志
            TX_Addr = 0;     //该归0的都归吧
                            TX_length=0;
        }
           else
           {
            TX_Addr++;
            SBUF = TX_buf[TX_Addr];
        }
    }
}


//在其它要发送的程序里面要写:

sprintf((char *)TX_buf, "WEIGHT");  //要发送的东东给TX_buf,当然不一定要这样给它,自己习惯最好。
TX_length= (unsigned char)strlen((char *)TX_buf); //求长度
TX_ready = 1;    //正在发送标志
TX_Addr=0;
SBUF = TX_buf[TX_Addr];   //先手机发送TX_buf[0],以后的中断自动发送   
while(TX_ready); // 等待发送完毕

//发送OK了

使用特权

评论回复
17
bhsdlmj| | 2009-5-31 17:11 | 只看该作者

对于我这样的新手来说:

结果并不重要。重要的是过程!!!!

建议楼主 把你的程序铲除!!!

重新构思!!

使用特权

评论回复
18
刘前辈| | 2009-5-31 17:19 | 只看该作者

标准不是用数组的。

假定一个协议数据帧长度既可能是10字节,又可能是100字节,是不是要申请一个

char idata tx_buffer[100];   显然不合理。(动态申请太慢了。)

所以,标准是采用环形缓冲器(复用技术)的,例如,只需要uart0_tx_length=16字节数组做环形缓冲区,像如下程序写法:

 if(uart0_tx_count>=uart0_tx_length)
            {
           // bit_flag_uart0_tx_over=1;
            uart0_tx_count=0;
            // uart0_tx_length=0;

SBUF=tx_buffer[uart0_tx_count];
            uart0_tx_count++;


可以写为: SBUF=tx_buffer[uart0_tx_count++ & 15 ];

而判定条件是环形缓冲区的首尾指针if(Ostart!=Oend)

这样的用法显然可以主程序一边向发送缓存区里置放欲发送的数据,中断发送程序又可以一边同时进行发送,100字节长的发送帧从数据区到16字节的发送缓存区没有出现等待延迟。

这里有一个基本概念:UART 和 CPU 像双控制器一样并行工作,互不影响。所以编程序时如果出现:某时间片内只处理发送,另一时间片内只处理数据,是不是没考虑到“2者是同时工作的”这一概念?

所以,书上写的程序很有道理,实现了两者真正的“并发工作”。Ostart并不一定总是小于Oend,
也有Oend < Ostart的时候。

           

使用特权

评论回复
19
playoffs001| | 2009-5-31 22:07 | 只看该作者

刘前辈的方法很理想


环形队列都用上了~ 这样的确是最好的

但对要求不是非常高的串口,通用的“数组+中断”就足够了~



使用特权

评论回复
20
enjoy21cn|  楼主 | 2009-5-31 23:47 | 只看该作者

谢谢大家的启发!

谢谢大家的启发,受益非浅!学习中.

使用特权

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

本版积分规则

24

主题

107

帖子

0

粉丝