Chinaunix首页 | 论坛 | 博客
  • 博客访问: 15535782
  • 博文数量: 2005
  • 博客积分: 11986
  • 博客等级: 上将
  • 技术积分: 22535
  • 用 户 组: 普通用户
  • 注册时间: 2007-05-17 13:56
文章分类

全部博文(2005)

文章存档

2014年(2)

2013年(2)

2012年(16)

2011年(66)

2010年(368)

2009年(743)

2008年(491)

2007年(317)

分类: LINUX

2007-12-13 08:43:57

双路7512b+at89c2051无线通信slave端源码

文章来源:http://gliethttp.cublog.cn

//--------------------------
//gliethttp_20071211
//注意:外振6M,timer0中断的代码如果比较长,需要考虑到,所执行代码可能耗费很多处理器时间
#include <reg51.h>
#define uint8 unsigned char
#define uint16 unsigned short

#define ___LED_MOD 2

#define DBGU_WATCH_PULS 0
#if DBGU_WATCH_PULS
sbit puls_pin =P1^6;
#endif
struct _sr
{
    #define _sr_max 4
    
    #define PRE_CMD0 0x75
    #define PRE_CMD1 0xa5
    #define PRE_CMD2 0x55
    #define PRE_CMD3 0x55
    
    /*
    #define PRE_CMD0 0xff
    #define PRE_CMD1 0xff
    #define PRE_CMD2 0xff
    #define PRE_CMD3 0xff*/

    char buf[_sr_max+4];
    char *cur;
    uint8 len;
    char rcve_buf[_sr_max];
    uint8 rcve_len;
};
//--------------------------
sbit _S_CTRL =P3^5;
sbit _LED_RUN =P1^7;
sbit _LED_W =P3^7;
sbit _LED_G =P1^0;
sbit _G7512b_RS_pin =P1^3;
sbit _G7512b_MOD1_pin =P1^2;
sbit _G7512b_RD_pin =P3^2;
sbit _G7512b_XD_pin =P1^4;
#define _G7512b_send1() _G7512b_XD_pin = 1
#define _G7512b_send0() _G7512b_XD_pin = 0
#define _G7512b_getdata() _G7512b_RD_pin
#define _G7512b_setrs(x) _G7512b_RS_pin = x

#define led_run_off() _LED_RUN = 1
#define led_run_on() _LED_RUN = 0
#define led_w_off() _LED_W = 1
#define led_w_on() _LED_W = 0
#define led_g_off() _LED_G = 1
#define led_g_on() _LED_G = 0

sbit _W7512b_RS_pin =P1^5;
sbit _W7512b_MOD1_pin =P1^1;
sbit _W7512b_RD_pin =P3^3;
sbit _W7512b_XD_pin =P3^4;
#define _W7512b_send1() _W7512b_XD_pin = 1
#define _W7512b_send0() _W7512b_XD_pin = 0
#define _W7512b_getdata() _W7512b_RD_pin
#define _W7512b_setrs(x) _W7512b_RS_pin = x

#define _S_CTRL2G() _S_CTRL = 0
#define _S_CTRL2W() _S_CTRL = 1
#define _C_CTRLisG() (_S_CTRL == 0)

#define _GEnable_send() \
_G7512b_setrs(0);\
_G7512b_MOD1_pin = 0

#define _GEnable_rcve() \
_G7512b_setrs(1);\
_G7512b_MOD1_pin = 1

#define _GHalt_7512b() \
_G7512b_setrs(1);\
_G7512b_MOD1_pin = 0

#define _WEnable_send() \
_W7512b_setrs(0);\
_W7512b_MOD1_pin = 0

#define _WEnable_rcve() \
_W7512b_setrs(1);\
_W7512b_MOD1_pin = 1

#define _WHalt_7512b() \
_W7512b_setrs(1);\
_W7512b_MOD1_pin = 0

//--------------------------
#define __step_waiting 1
#define __step_receiving_precode0 2
#define __step_receiving 3
#define __step_precoding 4
#define __step_sending 5
#define __step_receiving_precode1 6
#define __step_receiving_precode2 7
#define __step_receiving_precode3 8
#define __step_over 9
#define __step_erro 10
static uint8 __step = __step_waiting;
static uint8 __step_pre = 0xff;
bit send_rdy;
bit rcve_rdy;
struct _sr sr;
uint16 time_ticks,hold_ticks,hold_continue_ticks;
static uint8 tmp_data,rcve_data;
static uint16 led_count;
static uint16 chanel_line1_time_out,chanel_line2_time_out;
//线路切换函数
#define chanel_line_1 1
#define chanel_line_2 2
#define chanel_line_max 2
static char chanel_line;
static char chanel_line_pre;
static char chanel_line_status[chanel_line_max+1];
static char chanel_line_status_pre1,chanel_line_status_pre2;
//--------------------------
void env_ini(void);
void var_ini(void);
/*inline*/void timer0_restart(void);
void recvieving_var_reset(void);
//void __enable_rcve(void);
void com_send_char( char cd);
void com_ini(void);
void com_send_string( char *string);
char *__get_cur_chanel(void);
void set_led_g(void);
void set_led_w(void);
//--------------------------
int main(void)
{
    var_ini();
    env_ini();
    TR0 = 1;
    EX0 = 1;EX1 = 1;

    com_send_string("\r\n上电启动!\r\n");

    for(;;)
    {uint8 tmp;
     const char convert_table[]={'0','1','2','3','4','5','6','7','8','9','a','b'};

              if(led_count < 600*4)led_run_on();
        else if(led_count < 1200*4)led_run_off();
        else
            {
                EA = 0;
                led_count = 0;
                EA = 1;
            };
         
         tmp = chanel_line_status[chanel_line_1];
        if(tmp != chanel_line_status_pre1)
        {
            chanel_line_status_pre1 = tmp;
            set_led_g();
        }
        tmp = chanel_line_status[chanel_line_2];
        if(tmp != chanel_line_status_pre2)
        {
            chanel_line_status_pre2 = tmp;
            set_led_w();
        }
        tmp = __step;
        if(__step_pre != tmp)
        {
            __step_pre = tmp;
            tmp = chanel_line;
            if(tmp != chanel_line_pre)
            {
                chanel_line_pre = tmp;
                if(tmp == chanel_line_1)com_send_string("\r\nA ");
                if(tmp == chanel_line_2)com_send_string("\r\nB ");
                com_send_string(__get_cur_chanel());
                //com_send_string("\r\n");
            }
            com_send_char(',');
            com_send_char(convert_table[__step_pre]);
        }
    }
}

void env_ini(void)
{
    EA = 0;
    PCON = 0x00;
    TMOD = 0x12;
    timer0_restart();
    recvieving_var_reset();
    _S_CTRL2G();//默认光线链路 

    //slave添加
    chanel_line = chanel_line_1;
    __step = __step_receiving_precode0;
    rcve_rdy = 1;
    //__enable_rcve();
    _GEnable_rcve();
    _WEnable_rcve();


    TF1 = 0;
    TF0 = 0;
    IE1 = 0;
    IE0 = 0;
    //IT1 = 1;//下降边沿触发,具有记忆功能,导致不稳定
    //IT0 = 1;//下降边沿触发,具有记忆功能,导致不稳定
    IT1 = 0;//低电平中断触发,不具备记忆能力,每个clock采样
    IT0 = 0;//低电平中断触发,不具备记忆能力,每个clock采样

    ET0 = 1;//允许timer0进行向量中断
    EX0 = 0;//禁用外部中断0进行向量中断
    EX1 = 0;

    IP = 0;
    PT0 = 1;//提高定时器0的中断优先级

    com_ini();
    
    set_led_g();//安装指示灯
    set_led_w();

    EA = 1;
}
void var_ini(void)
{
    chanel_line1_time_out = 0;
    chanel_line2_time_out = 0;
}
void set_led_g(void)
{
    /*
          if(chanel_line_status_pre1)led_g_on();
    else led_g_off();
    */

         if(chanel_line_status_pre1)led_w_on();
    else led_w_off();
}
void set_led_w(void)
{
    /*
         if(chanel_line_status_pre2)led_w_on();
    else led_w_off();
    */

          if(chanel_line_status_pre2)led_g_on();
    else led_g_off();
}
/*inline*/
void timer0_restart(void)
{
    //TH0=0x98;TL0=0x98; //timer0,mode2,6M晶振 
    TH0=0x00;TL0=0x00;
}
void recvieving_var_reset(void)
{
    send_rdy = 0;
    rcve_rdy = 0;
    sr.cur = sr.buf;
    sr.len = 0;
    sr.rcve_len = 0;
    time_ticks = 0;
    hold_ticks = 0;
    tmp_data = 0;
    rcve_data= 0;
    /*
    _GHalt_7512b();
    _WHalt_7512b();
    */

    _GEnable_rcve();
    _WEnable_rcve();
}
void rcve2default(void)
{
    time_ticks = 0;
    rcve_data = 0;
    tmp_data = 0;
    EX0 = 0;EX1 = 0;
}
void send2_7512b(char *buf,uint8 len,bit ea)
{uint8 i;
 char *to;
    EA = 0;
    recvieving_var_reset();
    if(len > _sr_max)len = _sr_max;
    to = sr.buf;
    *to++ = PRE_CMD0;
    *to++ = PRE_CMD1;
    *to++ = PRE_CMD2;
    *to++ = PRE_CMD3;
    for(i = 0;i < len;i++)
    {
        *to++ = *buf++;
    }
    sr.len = len + 4;
    EX0 = 0;EX1 = 0;//禁止接收
    send_rdy = 1;
    __step = __step_precoding;
    if(ea)EA = 1;
}
void __set_out_data(uint8 dat)
{
         if(chanel_line == chanel_line_1){if(dat)_G7512b_send1();else _G7512b_send0();}
    else if(chanel_line == chanel_line_2){if(dat)_W7512b_send1();else _W7512b_send0();}
// if(dat)_G7512b_send1();
// else _G7512b_send0();
}
bit __get_in_data(void)
{
          if(chanel_line == chanel_line_1)return _G7512b_getdata();
    else if(chanel_line == chanel_line_2)return _W7512b_getdata();
}
void __enable_send(void)
{
         if(chanel_line == chanel_line_1){_GEnable_send();}
    else if(chanel_line == chanel_line_2){_WEnable_send();}
}
/*
void __enable_rcve(void)
{
         if(chanel_line == chanel_line_1){_GEnable_rcve();}
    else if(chanel_line == chanel_line_2){_WEnable_rcve();}
}
*/

/*
void __enable_cur_irq(void)
{
         if(chanel_line == chanel_line_1)EX0 = 1;
    else if(chanel_line == chanel_line_2)EX1 = 1;
}
*/

char *__get_cur_chanel(void)
{
         if(_C_CTRLisG())return "g";
    else return "w";
}
/*
void __disable_cur_irq(void)
{
    EX0 = 0;
}
*/

void com_ini(void)
{
/*
     SCON 7 6 5 4 3 2 1 0
         SM0 SM1 SM2 REN TB8 RB8 TI RI
            SM0 SM1 REN TB8
             0 0 方式0 1 允许接收 发送数据的第9位
             0 1 方式1 0 不允许接收 RB8
             1 0 方式2 RI 为1 表示接收到数据
             1 1 方式3 TI 为1 表示发送数据成功
                                     RI TI必须由软件清0
 */

 /*
        PCON 7 6 5 4 3 2 1
              SMOD - - - GF1 GF0 IDL
 */

    SCON = 0X50;
    TMOD &= 0x0f;
    TMOD |= 0X20;//定时器 选用方式2 自动重装
    //串口采用方式1或3
    PCON = 0x00;//SMOD=1;恢复默认值
    //6M,1200
    TH1 = 0xF3;TL1 = 0xF3;
    TR1 = 1;TI = 1;
}
void com_send_char( char cd)
{
    while(!TI);TI = 0;
    SBUF = cd;
}

void com_send_string( char *string)
{
    while(*string != 0)com_send_char(*string++);
}

#define PRE_CODING_TIME_SEND (160 )
#define PRE_CODING_TIME_RCVE (1600)//对端peer用来__switch2next_line()和send2_7512b()函数执行所花费的时间
#define RESEND_TRY_MAX_COUNT (10 )
void timer0_interrupt(void) interrupt 1
{
    EA = 0;
//原子操作,保护共享数据区,禁止中断嵌套
    if(send_rdy)
    {
        switch(__step)
        {
            case __step_precoding:
                {//发送导频码,信道静默
                 //实测:一个bit即8个ticks占用1.68ms
                     if(time_ticks < 2)
                    {
                        __step = __step_precoding;
                        //出现一个翻转,标示至少有一个电平变化,以使PRE_CODING_TIME_SEND时间内,有一个变化,以使时间记录正常
                        __set_out_data(sr.buf[0] & 0x80);
                        __enable_send();
                    }
                    if(time_ticks == 8)
                    {
                        //发送第一个数据的反位,实现翻转ext0或ext1修正
                        __set_out_data(!(sr.buf[0] & 0x80));
                    }
                    if(time_ticks > PRE_CODING_TIME_SEND)
                    {
                        __step = __step_sending;
                        time_ticks = 64;
                    }
                }
                break;
            case __step_sending:
                {//发送数据
                     if(time_ticks >= 64)
                    {
                        if(sr.len-- == 0)
                        {
                            //数据发送完毕
                            __step = __step_receiving_precode0;
                            send_rdy = 0;
                            rcve_rdy = 1;
                            sr.rcve_len = 0;
                            tmp_data = 0;
                            time_ticks = -1;
                            rcve_data = 0;
                            hold_ticks = 0;
                            hold_continue_ticks = 0;
                            //__enable_rcve();
                            //切到另一个信道检测
                            #if ___LED_MOD == 1
                            //设置建议信道,和irq结合使用 
                            chanel_line = ( (chanel_line == chanel_line_1) ? chanel_line_2:chanel_line_1 );
                            #endif
                            _GEnable_rcve();
                            _WEnable_rcve();
                            break;
                        }
                        time_ticks = 0;
                        tmp_data = *sr.cur++;
                    }
                    if((time_ticks & 0x7) == 0)
                    {
                        __set_out_data(tmp_data & 0x80);
                        tmp_data <<= 1;
                    }
                }
                break;
            default:
                {
                    __step = __step_erro;
                    rcve_rdy = 0;
                    send_rdy = 0;
                }
                break;
        }
    }else if(rcve_rdy)
        {
            if((time_ticks & 0x7) == 0x00)
            {//time_ticks=0时无伤大雅,
                rcve_data <<= 1;
                if(tmp_data > 4)rcve_data |= 0x01;
                tmp_data = 0;

                #if DBGU_WATCH_PULS
                puls_pin = rcve_data & 0x01;
                #endif
                /*
                //gliethttp_20071217 修正接收不稳定bug
                if(__step == __step_receiving_precode0)
                {static uint8 gliethttp_match_array[]={0,
                                             (PRE_CMD0 >> 7)&0x01,
                                             (PRE_CMD0 >> 6)&0x01,
                                             (PRE_CMD0 >> 5)&0x01,
                                             (PRE_CMD0 >> 4)&0x01,
                                             (PRE_CMD0 >> 3)&0x01,
                                             (PRE_CMD0 >> 2)&0x01,
                                             (PRE_CMD0 >> 1)&0x01,
                                             (PRE_CMD0 >> 0)&0x01};
                    //assert
                    //if(time_ticks > 64)time_ticks = 64;
                    if((rcve_data & 0x01) != gliethttp_match_array[time_ticks >> 3])
                    {
                        EX0 = 1;EX1 = 1;
                    }
                }
                */

            }
            if(time_ticks >= 64)
            {
                switch( __step)
                {
                     case __step_receiving_precode0:
                         {//bit do_switch = 0;
                            #if ___LED_MOD == 1
                            hold_continue_ticks++;
                            #endif

                            if(rcve_data == PRE_CMD0)
                            {
                                __step = __step_receiving_precode1;
                            }else
                                {
                                    EX0 = 1;EX1 = 1;

                                    #if ___LED_MOD == 1
                                    if( hold_continue_ticks > (PRE_CODING_TIME_RCVE / 16/*64*/) )
                                    {
                                        //设置建议信道,和irq结合使用 
                                        hold_continue_ticks = 0;
                                        chanel_line_status[chanel_line] = 0;
                                        chanel_line = ( (chanel_line == chanel_line_1) ? chanel_line_2:chanel_line_1 );
                                    }
                                    #endif
                                }
                            /*
                            else if(rcve_data == ((PRE_CMD0 & 0x80)? 0x00:0xff))
                                 {
                                      if(hold_continue_ticks > (((PRE_CODING_TIME_SEND / 64 )* 2) / 3))
                                     {
                                         __enable_cur_irq();
                                        //有可能中断一直未发生,直到hold_ticks超时
                                     }
                                     if( hold_continue_ticks > (PRE_CODING_TIME_SEND / 64) )
                                     do_switch = 1;
                                 }//else_disable_cur_irq();//到这,说明已经中断修正过了
                                 else
                                     {
                                        do_switch = 1;
                                    }
                            //gliethttp_20071212
                            //因为发送做了工作,所以,导频的固定电平持续时间不会大于PRE_CODING_TIME_SEND,如果是真正数据一定不会超过
                            if(do_switch)
                            {
                                //因为信号不好,导致的检测信道切换
                                hold_continue_ticks = 0;
                                 //chanel_line = ( (chanel_line == chanel_line_1) ? chanel_line_2:chanel_line_1 );
                                chanel_line = chanel_line_1;
                            }
                            */

                        }
                        break;
                    case __step_receiving_precode1:
                         {
                            if(rcve_data == PRE_CMD1)
                            {
                                __step = __step_receiving_precode2;
                            }else __step = __step_receiving_precode0;
                        }
                        break;
                    case __step_receiving_precode2:
                         {
                            if(rcve_data == PRE_CMD2)
                            {
                                __step = __step_receiving_precode3;
                            }else __step = __step_receiving_precode0;
                        }
                        break;
                    case __step_receiving_precode3:
                         {
                            if(rcve_data == PRE_CMD3)
                            {
                                __step = __step_receiving;
                            }else __step = __step_receiving_precode0;
                        }
                        break;
                    case __step_receiving:
                        {
                            #define mmmmmm_max _sr_max
                             if(sr.rcve_len < mmmmmm_max)
                             sr.rcve_buf[sr.rcve_len++] = rcve_data;
                             else
                             {
                                  __step = __step_over;
                                 rcve_rdy = 0;
                                 send_rdy = 0;
                             }
                             hold_ticks = 0;
                        }
                        break;
                }
                time_ticks = 0;
                tmp_data = 0;
                rcve_data = 0;
                
                /*
                if(hold_ticks++ > (PRE_CODING_TIME_RCVE / 64))
                {
                    hold_ticks = 0;
                    chanel_line_status[chanel_line] = 0;
                    //设置建议信道,和irq结合使用
                    chanel_line = ( (chanel_line == chanel_line_1) ? chanel_line_2:chanel_line_1 );
                }
                */

                #if ___LED_MOD == 2
                if(chanel_line1_time_out++ > RESEND_TRY_MAX_COUNT*((PRE_CODING_TIME_SEND+PRE_CODING_TIME_RCVE) / 64))
                {
                    chanel_line1_time_out = 0;
                    chanel_line_status[chanel_line_1] = 0;
                }
                if(chanel_line2_time_out++ > RESEND_TRY_MAX_COUNT*((PRE_CODING_TIME_SEND+PRE_CODING_TIME_RCVE) / 64))
                {
                    chanel_line2_time_out = 0;
                    chanel_line_status[chanel_line_2] = 0;
                }
                #endif
            }
            if(__get_in_data())tmp_data++;
        }else
            {
                if(__step == __step_over)
                {
                    send2_7512b("bj",2,0);
                    chanel_line_status[chanel_line] = 1;
                    if(chanel_line == chanel_line_1)chanel_line1_time_out = 0;
                    if(chanel_line == chanel_line_2)chanel_line2_time_out = 0;
                    if(sr.rcve_buf[0] == 'g')
                    {
                        _S_CTRL2G();
                        chanel_line_status[chanel_line_1] = 1;
                        chanel_line1_time_out = 0;
                    }
                    if(sr.rcve_buf[0] == 'w')
                    {
                        _S_CTRL2W();
                        chanel_line_status[chanel_line_2] = 1;
                        chanel_line2_time_out = 0;
                    }
                }else
                    {//异常
                        recvieving_var_reset();
                        //slave添加
                        __step = __step_receiving_precode0;
                        rcve_rdy = 1;
                        //__enable_rcve();
                        _GEnable_rcve();
                        _WEnable_rcve();
                    }
            }
    time_ticks++;
    led_count++;
    EA = 1;
}
void ext0_interrupt(void) interrupt 0
{
    EA = 0;
//原子操作,保护共享数据区,禁止中断嵌套
    if(rcve_rdy)
    {
        timer0_restart();
        rcve2default();
        #if ___LED_MOD == 1
        hold_continue_ticks = 0;
        #endif
        chanel_line = chanel_line_1;
        PX0 = 0;PX1 = 1;
    }
    EA = 1;
}
void ext1_interrupt(void) interrupt 2
{
    EA = 0;
//原子操作,保护共享数据区,禁止中断嵌套
    if(rcve_rdy)
    {
        timer0_restart();
        rcve2default();
        #if ___LED_MOD == 1
        hold_continue_ticks = 0;
        #endif
        chanel_line = chanel_line_2;
        PX0 = 1;PX1 = 0;
    }
    EA = 1;
}

阅读(2678) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~