搜索
bottom↓
回复: 16

单片机串口接收程序请教各位高手

[复制链接]

出0入0汤圆

发表于 2012-9-22 03:44:44 | 显示全部楼层 |阅读模式
小弟刚接触单片机,现在想做一个串口接收控制程序,PC端串口发送一个0X0d,单片机接收后控制点亮一颗LED灯,这个自己研究OK了。问题是:如果PC端每次发送:0x18 0XF7 0X0D  3组码,单片机接收程序该怎么写呢?
小弟莫元不多,谢谢大家!

阿莫论坛20周年了!感谢大家的支持与爱护!!

知道什么是神吗?其实神本来也是人,只不过神做了人做不到的事情 所以才成了神。 (头文字D, 杜汶泽)

出0入0汤圆

发表于 2012-9-22 04:03:43 | 显示全部楼层
用if语句判断下。

出0入0汤圆

发表于 2012-9-22 04:42:40 | 显示全部楼层
  1. #include<reg51.h>
  2. #include <stdint.h>

  3. sbit L0 = P2^0;
  4. sbit L1 = P2^1;
  5. sbit L2 = P2^2;
  6. sbit L3 = P2^3;
  7. sbit L4 = P2^4;
  8. sbit L5 = P2^5;
  9. sbit L6 = P2^6;
  10. sbit L7 = P2^7;

  11. void uart_init()
  12. {
  13.     PCON |= 0x80;                                                   // SMOD = 1,波特率加倍

  14.         SCON = 0x50;                                                         // 串口模式1,开接收  
  15.         TMOD = 0x20;                                                                  
  16.         TH1  = 0xFF;                                                          // 设置为最高波特率,晶体11.0592M时为57600
  17.         TR1  = 1;                                                                       
  18. }

  19. void UART(uint8_t TD)                                                   // 串口发送函数
  20. {
  21.         SBUF = TD;
  22.         while(!TI);
  23.         TI = 0;       
  24. }

  25. void main()
  26. {
  27.         P1 = P2 = P3 = 0xFF;
  28.         uart_init();                                                          // 串口初始化
  29.         while(1)
  30.         {
  31.                 if(RI)                                                                  // 检测是否收到数据
  32.                 {
  33.                         RI = 0;
  34.                         if((SBUF>0x2F)&&(SBUF<0x38))        // 检测是否为0-7的字符
  35.                         {
  36.                                 P2 = 0xFF;                                        // 关闭P2口的LED
  37.                                 P1 = ~(1<<(SBUF-0x30));                // 输出P1对应IO低电平点亮LED
  38.                                 UART('P');                                        // 返回对应IO
  39.                                 UART('1');
  40.                                 UART(SBUF);
  41.                         }
  42.                         else if((SBUF==0x0D))                          // 检测是否0x0D
  43.                         {
  44.                                 P1 = 0xFF;                                           // 关闭P1口的LED
  45.                                 P2 = 0xFF;                                        // 关闭P2口的LED
  46.                                 L0 = 0;                                                   // 点亮对应LED
  47.                                 UART('P');
  48.                                 UART('2');
  49.                                 UART('0');                                       
  50.                         }
  51.                         else if((SBUF==0x18))
  52.                         {
  53.                                 P1 = 0xFF;
  54.                                 P2 = 0xFF;
  55.                                 L1 = 0;       
  56.                                 UART('P');
  57.                                 UART('2');
  58.                                 UART('1');                                                                       
  59.                         }
  60.                         else if((SBUF==0xF7))
  61.                         {
  62.                                 P1 = 0xFF;
  63.                                 P2 = 0xFF;
  64.                                 L2 = 0;       
  65.                                 UART('P');
  66.                                 UART('2');
  67.                                 UART('2');                                                                       
  68.                         }                                                                 
  69.                         else                                                        // 发现非约定的按键返回错误
  70.                         {
  71.                                 UART('E');
  72.                                 UART('R');                                       
  73.                         }
  74.                         UART(0x0D);                                            // 回车
  75.                         UART(0x0A);                                                //
  76.                 }
  77.         }
  78. }

复制代码

出0入0汤圆

发表于 2012-9-22 08:36:18 | 显示全部楼层
switch()
{
  case:
     break;
  ........
  default:
     break;
}

出0入0汤圆

 楼主| 发表于 2012-9-22 11:11:40 | 显示全部楼层
Rookie_li 发表于 2012-9-22 08:36
switch()
{
  case:

谢谢大家解答 ,这个程序具体该怎么写呢?

出0入0汤圆

 楼主| 发表于 2012-9-22 11:42:49 | 显示全部楼层
Rookie_li 发表于 2012-9-22 08:36
switch()
{
  case:

#include <reg51.h>

#define XTAL 11059200       // CPU晶振频率
#define baudrate 9600       // 通信波特率
#define uchar unsigned char
#define uint unsigned int


void init(void)
{
SCON = 0x50;            // 设定串行口工作方式
PCON&= 0x00;            // 波特率不倍增
TMOD = 0x20;            // 定时器1工作于8位自动重载模式, 用于产生波特率
TH1  = (unsigned char)(256 - (XTAL / (32L * 12L * baudrate)));
TL1  = (unsigned char)(256 - (XTAL / (32L * 12L * baudrate))); // T1赋初值
TR1  = 1;                // 启动定时器1
IE   = 0x00;             // 禁止任何中断
//    EA = 1;                 // 中断总允许
}

void delay_ms(uint xms)      //12T单片机ms延时
{
        uint i,j;
        for(i=xms;i>0;i--)
                for(j=110;j>0;j--);
}

void led_shan()
{
        P0=0;
        delay_ms(100);
        P0=0xff;
        delay_ms(100);
        P0=0;
        delay_ms(100);
        P0=0xff;
}

void main(void)
{
    init();
    while(1)
   {
      if(RI)
     {
      RI = 0;
          switch(SBUF)
            {
                  case 0x18:
                  case 0xf7:
                  case 0x0d: led_shan();break;
                  default: P0=0; break;
            }
        }
    }
}

上面这个程序,串口每次发:0x18 0xf7 0x0d  这三组中的任意一组ED都会闪动,怎么才能让他判断0x18 0xf7 0x0d这3组同时发送才闪动呢?

出0入0汤圆

 楼主| 发表于 2012-9-22 12:24:07 | 显示全部楼层
有哪位高手能解答下的不

出0入0汤圆

发表于 2012-9-22 12:38:25 | 显示全部楼层
比如说 通过串口超级终端   发送3个数字 如1 2 3    然后敲回车 表示发送完毕   单片机 接收到1 2 3 就放数组里存起来 接收到回车时   然后就 把数组里的数取出来显示  如:  显示1   延时 显示2 延时 显示3        这个123   可以代表你想要显示的LED亮灭状态……

出0入55汤圆

发表于 2012-9-22 12:38:36 | 显示全部楼层
用数组将全部数据接收下来再判断

出0入0汤圆

发表于 2012-9-22 15:13:09 | 显示全部楼层
你的问题刚开始就没说明要收一串来判断!

出0入0汤圆

 楼主| 发表于 2012-9-22 15:47:17 | 显示全部楼层
不好意思,可能我没表述清楚吧,就是要收一串的,不是单个的数据

出0入0汤圆

发表于 2012-9-22 03:44:45 | 显示全部楼层
本帖最后由 chengzepeng 于 2012-9-22 17:01 编辑
  1. #include<reg51.h>
  2. #include <stdint.h>

  3. sbit L0 = P2^0;
  4. sbit L1 = P2^1;
  5. sbit L2 = P2^2;
  6. sbit L3 = P2^3;
  7. sbit L4 = P2^4;
  8. sbit L5 = P2^5;
  9. sbit L6 = P2^6;
  10. sbit L7 = P2^7;

  11. uint8_t MODE;

  12. void delay_us(uint16_t xus)                        // AT89x51,52延时100uS,这个延时必须要准确,否则串口会错过接收数据
  13. {
  14.         uint8_t yus;
  15.         for(;xus;xus--)
  16.         {       
  17.                 for(yus=42;yus;yus--);
  18.         }
  19. }

  20. void uart_init()
  21. {
  22.     PCON |= 0x80;                                   // SMOD = 1,波特率加倍
  23.         SCON = 0x50;                                         // 串口模式1,开接收  
  24.         TMOD = 0x20;                                                                  
  25.         TH1  = 0xFA;                                          // 设置波特率,晶体11.0592M时为9600
  26.         TR1  = 1;
  27.         ES = 1;
  28.         EA = 1;                                                                       
  29. }

  30. void UART(uint8_t TD)                                   // 串口发送函数
  31. {
  32.         SBUF = TD;
  33.         while(!TI);
  34.         TI = 0;       
  35. }

  36. void int_uart(void) interrupt 4                // 串口中断函数
  37. {
  38.         uint8_t ZFC[3],i,j;
  39.         for(i=0;i<3;i++)
  40.         {
  41.                 ZFC[i] = SBUF;
  42.                 RI = 0;
  43.                 for(j=20;j;j--)                                  // 超时设置为2mS,循环检测20次
  44.                 {
  45.                         delay_us(1);       
  46.                         if(RI)
  47.                         {
  48.                                 break;                               
  49.                         }
  50.                 }
  51.                 if(!RI)
  52.                 {
  53.                         break;
  54.                 }       
  55.         }
  56.         j = 0;
  57.         if(!RI)
  58.         {
  59.                 if(i==0)
  60.                 {
  61.                         switch(ZFC[0])
  62.                         {
  63.                                 case 0x18:
  64.                                 MODE = 1;
  65.                                 break;
  66.                                 case 0x7F:
  67.                                 MODE = 2;
  68.                                 break;
  69.                                 case 0x0D:
  70.                                 MODE = 3;
  71.                                 break;
  72.                                 default:
  73.                                 j = 1;
  74.                                 break;
  75.                         }               
  76.                 }
  77.                 else if((i==2)&&(ZFC[0]==0x18)&&(ZFC[1]==0x7F)&&(ZFC[2]==0x0D))
  78.                 {
  79.                         MODE = 4;
  80.                 }
  81.                 else
  82.                 {
  83.                         j = 1;
  84.                 }
  85.         }
  86.         if((j!=0)||RI)                                        // 串口数据长度超出3个处理
  87.         {
  88.                 while(1)                                        // 等待串口数据停止
  89.                 {
  90.                         RI = 0;
  91.                         delay_us(20);                    // 间隔2mS检测一次是否有串口数据来
  92.                         if(!RI)
  93.                         {
  94.                                 break;                      // 无数据来后退出
  95.                         }
  96.                 }
  97.                 UART('E');
  98.                 UART('R');
  99.                 UART('R');
  100.                 UART('O');
  101.                 UART('R');               
  102.         }
  103.         else
  104.         {
  105.                 UART(MODE+0x30);               
  106.         }
  107.         UART('\r');
  108.         UART('\n');
  109. }

  110. void main()
  111. {
  112.         P1 = P2 = P3 = 0xFF;
  113.         MODE = 0;
  114.         uart_init();                                                          // 串口初始化
  115.         while(1)
  116.         {
  117.                 P2 = 0xFF;
  118.                 delay_us(1000);
  119.                 if(MODE==4)
  120.                 {
  121.                         L0 = 0;
  122.                         L1 = 0;
  123.                         L2 = 0;
  124.                 }
  125.                 else if(MODE==1)
  126.                 {
  127.                         L0 = 0;
  128.                 }
  129.                 else if(MODE==2)
  130.                 {
  131.                         L1 = 0;
  132.                 }
  133.                 else if(MODE==3)
  134.                 {
  135.                         L2 = 0;
  136.                 }
  137.                 delay_us(1000);
  138.         }
  139. }

复制代码
因为你没有定义有通讯协议所以只能通过判断串口没数据来后再判断,
数据限制一次为1个或者3个,更改间隔为约2mS(超时设置)一次,
发送一个对应一个LED闪,一次性发三个都对的话就闪三个LED,其它的你自己去扩展吧!

出0入0汤圆

 楼主| 发表于 2012-9-22 17:56:35 | 显示全部楼层
chengzepeng 发表于 2012-9-22 03:44
因为你没有定义有通讯协议所以只能通过判断串口没数据来后再判断,
数据限制一次为1个或者3个,更改间隔为 ...

你是最热心的,谢谢解答,我研究研究

出0入0汤圆

发表于 2012-9-22 19:22:59 | 显示全部楼层
jiameng18 发表于 2012-9-22 11:42
#include

#define XTAL 11059200       // CPU晶振频率


void main(void)
{
    init();
    while(1)
   {
      if(RI)
     {
      RI = 0;
          switch(rec_step)//rec_step为全局变量,是接收数据的步骤,选择入口使用,初始化的数值为0
            {
                  case 0:
                     if(SBUF==0x18)
                     {
                        rec_step = 1;
                     }
                     else
                     {
                        rec_step = 0;
                     }
                     break;//一定要有这个break
                  case 1:
                     if(SBUF==0xf7)
                     {
                        rec_step = 2;
                     }
                     else
                     {
                        rec_step = 0;
                     }
                     break;//一定要有这个break
                  case 0x0d:
                     if(SBUF==0x0d)
                     {
                        rec_step = 0;
                          led_shan();
                     }
                     else
                     {
                        rec_step = 0;
                     }
                     break;//一定要有这个break
                  default: P0=0; break;
            }
        }
    }
}

出0入0汤圆

 楼主| 发表于 2012-9-22 23:46:29 | 显示全部楼层
Rookie_li 发表于 2012-9-22 19:22
void main(void)
{
    init();

首先谢谢您,这个程序我复制进去还是不行,发送0x18  0xf7  0x0d给单片机,LED灯不闪,只全亮(LED灯低亮) ,前面已经声明了全局变量。

出0入0汤圆

 楼主| 发表于 2012-9-23 00:21:02 | 显示全部楼层
Rookie_li 发表于 2012-9-22 19:22
void main(void)
{
    init();

重新修改了下程序,现在可以了,谢谢Rookie_li给的提示,受教了,感谢 ,现在一下发3组码LED灯能闪动。
程序如下:
void main(void)
{
    init();
        rec_step=0;
    while(1)
   {
      if(RI)
     {
      RI = 0;
          switch(rec_step)//rec_step为全局变量,是接收数据的步骤,选择入口使用,初始化的数值为0
            {
                  case 0:
                     if(SBUF==0x18)
                     {
                        rec_step = 1;
                     }
                     else
                     {
                        rec_step = 0;
                     }
                     break;//一定要有这个break
                  case 1:
                     if(SBUF==0xf7)
                     {
                        rec_step = 2;
                     }
                     else
                     {
                        rec_step = 0;
                     }
                     break;//一定要有这个break
                  case 2:
                     if(SBUF==0x0d)
                     {
                        rec_step = 0;
                          led_shan();
                     }
                     break;//一定要有这个break
            }
        }
    }
}

出0入0汤圆

发表于 2012-9-24 18:26:20 | 显示全部楼层
jiameng18 发表于 2012-9-23 00:21
重新修改了下程序,现在可以了,谢谢Rookie_li给的提示,受教了,感谢 ,现在一下发3组码LE ...

客气了!
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片。注意:要连续压缩2次才能满足要求!!】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-7-23 22:09

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表