jiameng18 发表于 2012-9-22 03:44:44

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

小弟刚接触单片机,现在想做一个串口接收控制程序,PC端串口发送一个0X0d,单片机接收后控制点亮一颗LED灯,这个自己研究OK了。问题是:如果PC端每次发送:0x18 0XF7 0X0D3组码,单片机接收程序该怎么写呢?
小弟莫元不多,谢谢大家!

chengzepeng 发表于 2012-9-22 04:03:43

用if语句判断下。

chengzepeng 发表于 2012-9-22 04:42:40

#include<reg51.h>
#include <stdint.h>

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

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

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

void UART(uint8_t TD)                                                   // 串口发送函数
{
        SBUF = TD;
        while(!TI);
        TI = 0;       
}

void main()
{
        P1 = P2 = P3 = 0xFF;
        uart_init();                                                        // 串口初始化
        while(1)
        {
                if(RI)                                                                  // 检测是否收到数据
                {
                        RI = 0;
                        if((SBUF>0x2F)&&(SBUF<0x38))        // 检测是否为0-7的字符
                        {
                                P2 = 0xFF;                                        // 关闭P2口的LED
                                P1 = ~(1<<(SBUF-0x30));                // 输出P1对应IO低电平点亮LED
                                UART('P');                                        // 返回对应IO
                                UART('1');
                                UART(SBUF);
                        }
                        else if((SBUF==0x0D))                          // 检测是否0x0D
                        {
                                P1 = 0xFF;                                           // 关闭P1口的LED
                                P2 = 0xFF;                                        // 关闭P2口的LED
                                L0 = 0;                                                   // 点亮对应LED
                                UART('P');
                                UART('2');
                                UART('0');                                       
                        }
                        else if((SBUF==0x18))
                        {
                                P1 = 0xFF;
                                P2 = 0xFF;
                                L1 = 0;       
                                UART('P');
                                UART('2');
                                UART('1');                                                                       
                        }
                        else if((SBUF==0xF7))
                        {
                                P1 = 0xFF;
                                P2 = 0xFF;
                                L2 = 0;       
                                UART('P');
                                UART('2');
                                UART('2');                                                                       
                        }                                                                 
                        else                                                        // 发现非约定的按键返回错误
                        {
                                UART('E');
                                UART('R');                                       
                        }
                        UART(0x0D);                                          // 回车
                        UART(0x0A);                                                //
                }
        }
}

Rookie_li 发表于 2012-9-22 08:36:18

switch()
{
case:
   break;
........
default:
   break;
}

jiameng18 发表于 2012-9-22 11:11:40

Rookie_li 发表于 2012-9-22 08:36 static/image/common/back.gif
switch()
{
case:


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

jiameng18 发表于 2012-9-22 11:42:49

Rookie_li 发表于 2012-9-22 08:36 static/image/common/back.gif
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组同时发送才闪动呢?

jiameng18 发表于 2012-9-22 12:24:07

有哪位高手能解答下的不{:cry:}

LSZD 发表于 2012-9-22 12:38:25

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

jssd 发表于 2012-9-22 12:38:36

用数组将全部数据接收下来再判断

chengzepeng 发表于 2012-9-22 15:13:09

你的问题刚开始就没说明要收一串来判断!

jiameng18 发表于 2012-9-22 15:47:17

不好意思,可能我没表述清楚吧,就是要收一串的,不是单个的数据

chengzepeng 发表于 2012-9-22 03:44:45

本帖最后由 chengzepeng 于 2012-9-22 17:01 编辑

#include<reg51.h>
#include <stdint.h>

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

uint8_t MODE;

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

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

void UART(uint8_t TD)                                   // 串口发送函数
{
        SBUF = TD;
        while(!TI);
        TI = 0;       
}

void int_uart(void) interrupt 4                // 串口中断函数
{
        uint8_t ZFC,i,j;
        for(i=0;i<3;i++)
        {
                ZFC = SBUF;
                RI = 0;
                for(j=20;j;j--)                                  // 超时设置为2mS,循环检测20次
                {
                        delay_us(1);       
                        if(RI)
                        {
                                break;                               
                        }
                }
                if(!RI)
                {
                        break;
                }       
        }
        j = 0;
        if(!RI)
        {
                if(i==0)
                {
                        switch(ZFC)
                        {
                                case 0x18:
                                MODE = 1;
                                break;
                                case 0x7F:
                                MODE = 2;
                                break;
                                case 0x0D:
                                MODE = 3;
                                break;
                                default:
                                j = 1;
                                break;
                        }               
                }
                else if((i==2)&&(ZFC==0x18)&&(ZFC==0x7F)&&(ZFC==0x0D))
                {
                        MODE = 4;
                }
                else
                {
                        j = 1;
                }
        }
        if((j!=0)||RI)                                        // 串口数据长度超出3个处理
        {
                while(1)                                        // 等待串口数据停止
                {
                        RI = 0;
                        delay_us(20);                  // 间隔2mS检测一次是否有串口数据来
                        if(!RI)
                        {
                                break;                      // 无数据来后退出
                        }
                }
                UART('E');
                UART('R');
                UART('R');
                UART('O');
                UART('R');               
        }
        else
        {
                UART(MODE+0x30);               
        }
        UART('\r');
        UART('\n');
}

void main()
{
        P1 = P2 = P3 = 0xFF;
        MODE = 0;
        uart_init();                                                        // 串口初始化
        while(1)
        {
                P2 = 0xFF;
                delay_us(1000);
                if(MODE==4)
                {
                        L0 = 0;
                        L1 = 0;
                        L2 = 0;
                }
                else if(MODE==1)
                {
                        L0 = 0;
                }
                else if(MODE==2)
                {
                        L1 = 0;
                }
                else if(MODE==3)
                {
                        L2 = 0;
                }
                delay_us(1000);
        }
}

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

jiameng18 发表于 2012-9-22 17:56:35

chengzepeng 发表于 2012-9-22 03:44 static/image/common/back.gif
因为你没有定义有通讯协议所以只能通过判断串口没数据来后再判断,
数据限制一次为1个或者3个,更改间隔为 ...

你是最热心的,谢谢解答,我研究研究{:handshake:}

Rookie_li 发表于 2012-9-22 19:22:59

jiameng18 发表于 2012-9-22 11:42 static/image/common/back.gif
#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;
            }
      }
    }
}

jiameng18 发表于 2012-9-22 23:46:29

Rookie_li 发表于 2012-9-22 19:22 static/image/common/back.gif
void main(void)
{
    init();


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

jiameng18 发表于 2012-9-23 00:21:02

Rookie_li 发表于 2012-9-22 19:22 static/image/common/back.gif
void main(void)
{
    init();


重新修改了下程序,现在可以了,谢谢Rookie_li给的提示,受教了,感谢{:handshake:} ,现在一下发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
            }
      }
    }
}

Rookie_li 发表于 2012-9-24 18:26:20

jiameng18 发表于 2012-9-23 00:21 static/image/common/back.gif
重新修改了下程序,现在可以了,谢谢Rookie_li给的提示,受教了,感谢 ,现在一下发3组码LE ...

客气了!
页: [1]
查看完整版本: 单片机串口接收程序请教各位高手