打印

急:单片机接收字符串

[复制链接]
10532|20
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
yy温控|  楼主 | 2009-10-19 12:07 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
本帖最后由 yy温控 于 2009-10-20 08:30 编辑

小弟最近做了一个关于单片机和PC机通信(485通信)的题目,需要单片机接收PC机发送的字符串,但是小弟实在是不明白怎么处理字符串,单个字符我还可以处理。
下面是我的程序,请各位大侠指点迷津。下面红色的地方我不知道怎么改。

(谢谢大家的支持,路过的兄弟给点意见)
#include<reg52.h>
#include<intrins.h>
#include<stdio.h>
#define uchar unsigned char
#define uint unsigned int
void send(unsigned char i);
unsigned char inportb (unsigned int addr);
void Uart_init();
unsigned char receive;
uchar str[]={""} ;
sbit P20=P2^0;
void Timer0_Routine() interrupt 1  //定时器中断   
{
     TH0=0xb8;
     TL0=0X00;      
           
}
void serial_port() interrupt 4   //串口中断
{
if(RI==1)  
{
      str[0]=SBUF;
   str[1]=str[0];
  if(str[0]=='a'&&str[1]=='a')          //当上位机发送字符 aa  ,单片机动作

    {
   receive=1;
   TI=0;
   RI=0;
   P20=1;
    }
  else
    {
   receive=0;
   TI=0;
   RI=0;
   P20=0;
     }
}
}
void   DelayNS(unsigned int dly)   //延时函数
{   unsigned int   i;
    for(; dly>0; dly--)
       for(i=0; i<5000; i++)
     _nop_();
}

void main()
{

     Uart_init();                             
     while (1)
      {               
            
if(receive==1)
    {   
         send(65);   //发送内容 A   ASCII码
       DelayNS(1); //延时
       send(66);   //B
       DelayNS(1);
       send(67);   //C
       DelayNS(1);
      
       send(32); //空格
       send(32); //空格                    
               
         receive=0;
         P20=0;                     
    }
      }   
}
void Uart_init()    //串口初始化函数
{
TMOD=0x21;
TCON=0x69;
TH0=0xb8;
TL0=0X00;
TR0=1;
EA=1;
ET0=1;
SCON=0x50;
TH1=0xfd;
    TL1=0xfd;
    REN=1;
ES=1;
    TR1=1;
     
    P20=0;   
receive=0;  
}
void send(unsigned char i)    //单片机发送函数
{
TI=0;
SBUF=i;
while(!TI);TI=0;
}

相关帖子

沙发
Mindist| | 2009-10-19 12:23 | 只看该作者
将你那字符串中的字符用for循环一个一个发送应该就行了吧。。。

使用特权

评论回复
板凳
yy温控|  楼主 | 2009-10-19 12:55 | 只看该作者
我点晕,接收字符串怎么加for循环,这个大哥可否说的更详细点。 2# Mindist

使用特权

评论回复
地板
yy温控|  楼主 | 2009-10-19 12:56 | 只看该作者
我主要是接收字符串 2# Mindist

使用特权

评论回复
5
yy温控|  楼主 | 2009-10-19 13:40 | 只看该作者
那位大侠帮帮俺,俺急的如热锅上的蚂蚁!

使用特权

评论回复
6
Mindist| | 2009-10-19 13:42 | 只看该作者
4# yy温控
先定义一个字符串数组:
char code string[]="Mindist";

然后发送的时候:
for(i=0;i<6;i++)
{
    SBUF=string;
    while(!TI);
    TI=0;
}

这样就行了。。。

使用特权

评论回复
7
ecomputer| | 2009-10-19 13:50 | 只看该作者
在接收中断里面处理,每次接收一个后放到缓冲区内,当接到一个字符串结束标志时,将某个设定的标志位置1就可以了,然后再处理缓冲区的字符串

使用特权

评论回复
8
yy温控|  楼主 | 2009-10-19 13:55 | 只看该作者
接收时是不是应该保存到数组里,比如上面的程序,红字的地方怎么修改 7# ecomputer

使用特权

评论回复
9
yy温控|  楼主 | 2009-10-19 13:56 | 只看该作者
大哥,你的回答很好,但是发送字符串我是会的,关键是接收字符串应该怎么接收? 6# Mindist

使用特权

评论回复
10
yy温控|  楼主 | 2009-10-19 14:16 | 只看该作者
大家帮忙出出意见,在此谢过了!

使用特权

评论回复
11
原野之狼| | 2009-10-19 14:49 | 只看该作者
str[0]=SBUF;
   str[1]=str[0];
  if(str[0]=='a'&&str[1]=='a')

这样str[0] str[1]的内容岂不是相等了?
相等的话还比较两次干嘛呢?

定义一个字符缓冲,然后把接收到的字符放到缓冲里,最好在字符串末尾带上结束标志,这样好确定何时去解码。
另外,在通讯的时候要带上校验,要不然你的程序就不安全了。

接收中断伪代码:
if (SBUF == 结束符)
{
置标志位flag,提示main LOOP去解码。
}
else
{
向缓冲末尾填入SBUF;
}

使用特权

评论回复
12
yy温控|  楼主 | 2009-10-19 14:54 | 只看该作者
本帖最后由 yy温控 于 2009-10-19 15:04 编辑

回复: 11# 原野之狼

修改如下:但是没法判断是不是字符串"aa"啊!

if(RI==1)  
{
        if(SBUF=='#')          //当上位机发送字符 aa  ,单片机动作
    {
   receive=1;
   TI=0;
   RI=0;
   P20=1;
    }
  else
    {
   向缓冲末尾填入SBUF;//怎么回事
     }
}

使用特权

评论回复
13
Mindist| | 2009-10-19 16:13 | 只看该作者
9# yy温控
接收只能一个一个字符来了吧~接收到一个字符进入中断后把接收到的单个字符送到一个事先定义好的数组中,知道把全部接收到的字符全部送到数组内~

使用特权

评论回复
14
yy温控|  楼主 | 2009-10-19 16:16 | 只看该作者
回复: 13# Mindist

是啊,我现在就会接收一个字符,字符串就不行了。

应该怎么改呢

使用特权

评论回复
15
shinerj| | 2009-10-19 17:19 | 只看该作者
我一般都发一个收一个,所以好像也是属于不会收发字符串的啦。。。。

使用特权

评论回复
16
Mindist| | 2009-10-19 18:03 | 只看该作者
14# yy温控
好像不行。。。接收到一个字符才进入一次中断。。。

使用特权

评论回复
17
hnnzzh| | 2009-10-19 21:12 | 只看该作者
这是我们做蓝牙接收的程序,没有问题,我把部分粘贴出来,你可以 参考一下!

bool RIwait(uint i)     
{        //等待时间到,返回1
  while(i--){if(RI) return 0;};        //等待时间内 RI = 1 ,返回0
  return 1;        //串行接收停止位的中间时,RI  置1
}


uchar ReadSbuf(void)
{
//从SBUF  读数据,可得到接收的数据
   uchar TmpSbuf;
   TmpSbuf=SBUF;
   SCON=0x50;
   return TmpSbuf;
}

void ComService(void) interrupt 4
{  
uchar TmpSBUF,i=0;
  EA=0;
  ES=0;      
  if(RIwait(RiWaitTimer))  goto ExitCom;      
  switch(ReadSbuf())
{
        case 'R'://current call  
                                   for(i=0;i<20;i++)   
                                   {
                               if(RIwait(RLongiWaitTimer)) break;//goto ExitCom;
                                BlueTooth.TelNum[i]=ReadSbuf();
                                TelTmpNum[i]=BlueTooth.TelNum[i];  //   new add  09.4.08
                                if(BlueTooth.TelNum[i]=='\r')break;
                                   }
                                   BlueTooth.TelNum[i]='\n';
                                TelTmpNum[i]='\n';  // new   add 09.4.08
                                   if(StandbyStatus==IsStandby)
                                   {
                                 BlueTooth._bIRKey=IR_BLUETOOTHPOWERON;
                                   }
                                   else
                                   {
                                       if(BlueTooth.WorkMode==BlueToothWorkInCalling)
                                          BlueTooth._bIRKey=IR_BLUETOOTHINTEL;                           
                                        else          
                                 //        BlueTooth._bIRKey=IR_BLUETOOTHIN;
                                    _bIRKey= IR_BTPHONECAllIN;
                                  //   BlueTooth._bIRKey=IR_BTPHONECAllIN;
                                   }  
                                   break;                               
  }
ExitCom:  
  SCON = 0x50;        //模式1 ,REN = 1 ,允许接收数据
  ES=1;      
  EA=1;                        //Enable  UART  
}

使用特权

评论回复
评分
参与人数 1威望 +1 收起 理由
yy温控 + 1 谢谢这位大侠! 好好学学。
18
yy温控|  楼主 | 2009-10-20 08:09 | 只看该作者
谢谢大家的支持,小弟先谢过大家!:D

使用特权

评论回复
19
hyg1984| | 2009-10-20 10:34 | 只看该作者
呃~~~~~你这个程序还真是特殊
首先一个问题,你那个aa是16进制的,还是就是字符的?
如果是16进制的,就是只有一个字符,而不是字符串了。这样简单-------可以这样
if(RI==1)  
{
      unsigned char u_data;
      u_data = SBUF;
      if(u_data == 0xaa)          //当上位机发送字符 aa  ,单片机动作

如果是字符的,那就是2个字符,是字符串,不过看你的程序,好像
就只是用来做判断的吧,难道一个字符(0x00~0xff)用作判断不行吗?
用字符串来做判断,好像没有意义,或者你有其他的目的?如果有其他的
目的,请把问题描述清楚一点,不然人家怎么回答你得问题?论坛里的牛人
那么多,就你问的问题不清不楚的,谁会理你啊。。。。。。。
就像11楼的回答已经很好了,可是人家也是给个朦胧的概念给你,为什么?
因为你问的问题不清不楚的,谁知道怎么回答清楚?
如果你真是用2个字符aa来做判断的话,嘿嘿。。。。。。无意义。。。
你看看,回答你得问题的,都是说如何接收字符串的,这个还要你自己去添加程序呢
你叫人家该红色那部分吧,,,,那部分明明就是一个判断语言!!!怎么改?
我就写写,怎么判断2个字符吧。。。。。。。唉。。。。。。。
bit flag;        //定义一个标志位
bit flag1;     //要完成无意义的改动还真是麻烦,思想有点乱,因为进一次中断只能接受一字符
            //如果是要存储多个数据,用11楼的想法就很好,可是你这里只是用来做判断。。。。。
if(RI==1)
{ //就以2个字符为例,所以就不用for了,谁叫你是用来做判断的呢,我有点
   //怀疑是不是你概念搞错了。。。。
      if(flag1 == 0)
      {
             str[1] = SBUF;
             flag = 0;
             flag1 = 1;//设置一下,下次中断就接收第二个字符   
      }
       else
      {
             str[0] = SBUF;
             flag1 = 0;
             flag = 1;//已经接受到2个字符了,让标志位置1,然后下面判断。。。      
      }   
      if(flag == 1 && str[1] == 'a' && str[0] == 'a')          //当上位机发送字符 aa  ,单片机动作

使用特权

评论回复
评分
参与人数 1威望 +1 收起 理由
yy温控 + 1 谢谢这位大哥!
20
yy温控|  楼主 | 2009-10-20 11:20 | 只看该作者
回复: 19# hyg1984

这位大哥说的很对。那我就把设计的这个题目好好说说。

我设计的项目主要是控制继电器,外加显示和键盘还有通信。

通信部分是要输入指令给单片机,然后让继电器工作。因为继电器很多,每个继电器对应的值分别是2.5,3.75,5,6.25类似的值,我现在用的串口通信软件是串口助手V2.2,其实要是输入16进制数那应该很简单,但是老板非让我输入2.5,3.75,这样的数。

现在我又跟老板讨论了,我准备自己做一个串口通信界面,设置一些按钮,不过VB没学过,不知道能不能做出来。

大家的支持!非常感谢hyg1984的回复!

使用特权

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

本版积分规则

14

主题

71

帖子

0

粉丝