6916|15

71

帖子

0

TA的资源

一粒金砂(初级)

楼主
 

串口如何正确发送接收数组?(附程序) [复制链接]

#include
   #include   
   
   #define INBUF_LEN 5 //数据长度  
   
   unsigned char ch;   
   bit read_flag= 0 ;  
   unsigned char temp[]={0,1,2,3,0};
   unsigned char *str=temp;
   void init_serialcom( void )  
   {  
       SCON = 0x50 ;  //SCON: serail mode 1, 8-bit UART, enable ucvr  
           TMOD |= 0x20 ; //TMOD: timer 1, mode 2, 8-bit reload  
           PCON &= 0xef ; //SMOD=0;  
           TH1 = 0xFD ;   //Baud:19200 fosc=11.0592MHz  
           IE |= 0x90 ;   //Enable Serial Interrupt  
           TR1 = 1 ;     // timer 1 run  
           TI=1;            
        }  
            
//向串口发送一个字符  
          void send_char_com( unsigned char ch)  
          {  
          //unsigned char point;
         // for(point=0;point<20;point++)
         //{SBUF=str[point];
             SBUF=ch;  
             while (TI== 0);  
                 TI= 0 ;  
           }  

            
//向串口发送一个字符串,strlen为该字符串长度  
void send_string_com( unsigned char *str, unsigned int strlen)
   {  
     unsigned int k= 0 ;  
         do  
    {  
          send_char_com(*(str + k));
      k++;
    }  
         while (k < strlen);  
   }



//串口接收中断函数  
void serial () interrupt 4 using 3  
{ unsigned char ch;
    if (RI)  
           {   
                   RI = 0 ;
                     
                     ch=SBUF;                     
                   read_flag= 1 ; //就置位取数标志  
                    
                }
}  

main()  
    {   
            init_serialcom(); //初始化串口  
                    while ( 1 )  
                           {  
                               if (read_flag) //如果取数标志已置位,就将读到的数从串口发出  
                                       {  
                                            read_flag= 0 ; //取数标志清0  
                                                //        send_char_com(ch);  
                                                    send_string_com(str,5);
                                                
                                                }  
                                }  
        }  
//现希望串口调试助手发来数组0 1 2 3 0,单片机接收后返回该数组(或另一个数组),请问程序应如何修改才能正确,现在发送和接受不一致...

最新回复

众位楼主,如果想要用单片机实现真彩液晶显示的话,可以跟我索取资料的。dwin99@live.cn   详情 回复 发表于 2009-8-29 20:27
点赞 关注

回复
举报

54

帖子

0

TA的资源

一粒金砂(初级)

沙发
 
学习
 
 

回复

62

帖子

0

TA的资源

一粒金砂(初级)

板凳
 
学习
 
 
 

回复

61

帖子

0

TA的资源

一粒金砂(初级)

4
 
第一点,你的ch是一个局部变量。
 
 
 

回复

83

帖子

0

TA的资源

一粒金砂(初级)

5
 
  1. 第二点,你用read_flag这种方法并不好使,一般使用循环缓冲区

  2. unsigned char rp = 0;
  3. unsigned char sp = 0;
  4. unsigned char buf[ 0x10 ];

  5. //向串口发送一个字符串,strlen为该字符串长度  
  6. void send_string_com( unsigned char *str, unsigned int strlen)
  7. {  
  8.     unsigned int k= 0 ;  
  9.         do  
  10.     {  
  11.           send_char_com(*(str + k));
  12.       k++;
  13.     }  
  14.         while (k < strlen);  
  15.   }


  16. //串口接收中断函数  
  17. void serial () interrupt 4 using 3  
  18. {
  19.         EA = 0;
  20.     if (RI)  
  21.         {  
  22.                 RI = 0 ;
  23.                
  24.                 buf[ rp++ ] = SBUF;
  25.                 rp &= 0x0f;       
  26.         }
  27.     EA = 1;

  28. }
  29. main()  
  30. {  
  31.     init_serialcom(); //初始化串口  
  32.     while ( 1 )  
  33.         {
  34.                 if( rp ^ sp )
  35.                 {
  36.                         send_char_com( buf[ sp++ ] );
  37.                         sp &= 0x0f;
  38.                 }
  39.         }
  40. }
复制代码
 
 
 

回复

79

帖子

0

TA的资源

一粒金砂(初级)

6
 
谢谢,就jennyvenus的程序问两个问题,首先:
//串口接收中断函数  
void serial () interrupt 4 using 3  
{
    EA = 0;
    if (RI)  
    {  
        RI = 0 ;
        
        buf[ rp++ ] = SBUF;
        rp &= 0x0f;   
    }
    EA = 1;

}
1.EA是全局中断使能开关标志,EA的置零与置1是否为了在接收阶段屏蔽发送,待接收完再开启发送?这是必须的吗?
2,循环缓冲区这个概念我第一次接触,依程序看
buf[ rp++ ] = SBUF;
rp &= 0x0f;
等同于:
for(rp=0;rp<16;rp++)
buf[ rp++ ] = SBUF;
那就是说单片机接收到PC发送16个数的数组后,再返回16个数的数组到PC.我理解对不?
先用KEIL单步看看吧.............
 
 
 

回复

71

帖子

0

TA的资源

一粒金砂(初级)

7
 
谢谢,就jennyvenus的程序问两个问题,首先:
//串口接收中断函数  
void serial () interrupt 4 using 3  
{
    EA = 0;
    if (RI)  
    {  
        RI = 0 ;
        
        buf[ rp++ ] = SBUF;
        rp &= 0x0f;   
    }
    EA = 1;

}
1.EA是全局中断使能开关标志,EA的置零与置1是否为了在接收阶段屏蔽发送,待接收完再开启发送?这是必须的吗?
2,循环缓冲区这个概念我第一次接触,依程序看
buf[ rp++ ] = SBUF;
rp &= 0x0f;
等同于:
for(rp=0;rp<16;rp++)
buf[ rp++ ] = SBUF;
那就是说单片机接收到PC发送16个数的数组后,再返回16个数的数组到PC.我理解对不?
先用KEIL单步看看吧.............
 
 
 

回复

84

帖子

0

TA的资源

一粒金砂(初级)

8
 
谢谢,就jennyvenus的程序问两个问题,首先:
//串口接收中断函数  
void serial () interrupt 4 using 3  
{
    EA = 0;
    if (RI)  
    {  
        RI = 0 ;
        
        buf[ rp++ ] = SBUF;
        rp &= 0x0f;   
    }
    EA = 1;

}
1.EA是全局中断使能开关标志,EA的置零与置1是否为了在接收阶段屏蔽发送,待接收完再开启发送?这是必须的吗?
2,循环缓冲区这个概念我第一次接触,依程序看
buf[ rp++ ] = SBUF;
rp &= 0x0f;
等同于:
for(rp=0;rp<16;rp++)
buf[ rp++ ] = SBUF;
那就是说单片机接收到PC发送16个数的数组后,再返回16个数的数组到PC.我理解对不?
先用KEIL单步看看吧.............
 
 
 

回复

77

帖子

0

TA的资源

一粒金砂(初级)

9
 
1.EA是全局中断使能开关标志,EA的置零与置1是否为了在接收阶段屏蔽发送,待接收完再开启发送?这是必须的吗?
是防止别的中断将串口中断处理程序打断,形成嵌套;

2,循环缓冲区这个概念我第一次接触,依程序看
buf[ rp++ ] = SBUF;
rp &= 0x0f;
等同于:
for(rp=0;rp <16;rp++)
buf[ rp++ ] = SBUF;
应该是不一样的。 jennyvenus的程序中,由于rp是全局变量,因此每次串口中断都会执行“存放数据,指针加1”的操作,从而构成一个循环缓冲区,超过16个字节以后的第17字节将覆盖第一字节。而LZ你写的for循环会在每次串口中断中执行一遍,在缓冲区中填入16个相同的值。
 
 
 

回复

80

帖子

0

TA的资源

一粒金砂(初级)

10
 
//向串口发送一个字符  
          void send_char_com( unsigned char ch)  
          {  
          //unsigned char point;
        // for(point=0;point <20;point++)
        //{SBUF=str[point];
            SBUF=ch;  
            while (TI== 0);  
                TI= 0 ;  
          }  
另外红色部分有错
 
 
 

回复

59

帖子

0

TA的资源

一粒金砂(初级)

11
 
谢谢flypig8321的解答,明白了,红色部分有错么?我的理解是
while (TI== 0);  //等待数据发送完毕
TI= 0 ; //软件清0
中断服务程序里不用软件清0的话TI一直是1,继续请教~
 
 
 

回复

86

帖子

0

TA的资源

一粒金砂(初级)

12
 
unsigned char recv_state;//接收字节步骤定义
void uart_rx_isr(void)    //接收中断函数
{
        uchar j,x,c;
        c=sbuf;//c等于接收的字节;
        switch (recv_state) {
        case 0:
                if (c==0)                                          // 是数组第一字节
                        recv_state=1;         // 进入下一个状态
                else                 recv_state=0;                 // 回到初始状态       
         break;
        case 1:                                         // 是数组第二字节
                if (c==0x01){
                        recv_state=2;                 // 进入下一个状态
                }
                else {         recv_state=0;                 // 回到初始状态
                }
        break;
        case 2:                                         // 是数组第二字节
                if (c==0x02){
                //        recv_state=2;                 // 进入下一个状态       
                  //这里添加 发送数组代码       
                 }
                else {         recv_state=0;                 // 回到初始状态               
             }
        break;

}
只给你两个字符判断的程序,其余的你自己添加即可!
判断到你认为对的数组顺序时,发送你要发送的数组就可以了,
 
 
 

回复

71

帖子

0

TA的资源

一粒金砂(初级)

13
 
楼上使用的是基于状态基的方法,用于判断单片机接收的字符是否与要求发送的一致,排除干扰码吧,很好!学习了!我现在反而对循环缓冲区的使用方法怀有浓厚兴趣,使用这种方法有什么好处呢~呵呵
 
 
 

回复

77

帖子

0

TA的资源

一粒金砂(初级)

14
 
 

回复

82

帖子

0

TA的资源

一粒金砂(初级)

15
 
引用 9 楼 flypig8321 的回复:
//向串口发送一个字符?
? ? ? ? ? void send_char_com( unsigned char ch)?
? ? ? ? ? {?
? ? ? ? ? //unsigned char point;
? ? ? ? // for(point=0;point <20;point++)
? ? ? ? //{SBUF=str[point];
? ? ? ? ? ? SBUF=ch;?
? ? ? ? ? ?while (TI== 0);?
? ? ? ? ? ? ? ? TI= 0 ;?? ? ? ? ? }?
另外红色部分有错



是我看错了,用while等待发送完毕是对的。
 
 
 

回复

80

帖子

0

TA的资源

一粒金砂(初级)

16
 
众位楼主,如果想要用单片机实现真彩液晶显示的话,可以跟我索取资料的。dwin99@live.cn
 
 
 

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

随便看看
查找数据手册?

EEWorld Datasheet 技术支持

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

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

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

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

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

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