Chinaunix首页 | 论坛 | 博客
  • 博客访问: 15496721
  • 博文数量: 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:38:45

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

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

//--------------------------
//gliethttp_20071211

//注意:外振6M,timer0中断的代码如果比较长,需要考虑到,所执行代码可能耗费很多处理器时间
#include <reg51.h>
#define uint8 unsigned char
#define uint16 unsigned short
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;
uint8    send_count;
struct _sr sr;
uint16    time_ticks,hold_ticks,hold_continue_ticks;
static uint8 tmp_data,rcve_data;
static uint16 led_count;
//线路切换函数
#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 com_send_char(    char cd);
void com_ini(void);
void com_send_string( char *string);
void __switch_ini(void);
char *__get_cur_chanel(void);
void set_led_g(void);
void set_led_w(void);
//--------------------------
int main(void)
{
    var_ini();
    env_ini();
    __switch_ini();

    TR0 = 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((chanel_line_status[chanel_line_1]) ? "1:OK\r\n":"1:NO\r\n");
                com_send_string((chanel_line_status[chanel_line_2]) ? "2:OK\r\n":"2:NO\r\n");
                */

                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((chanel_line_status[chanel_line_1]) ? "1:OK ":"1:NO ");
                 //com_send_string((chanel_line_status[chanel_line_2]) ? "2:OK ":"2:NO ");
                //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();//默认光线链路
    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)
{
    send_count = 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();
}
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 __switch_to(void)
{
    //当前A路断开,测尝试若干次之后试B路chanel_line_status
         if( _C_CTRLisG() && !chanel_line_status[chanel_line_1] && chanel_line_status[chanel_line_2])_S_CTRL2W();
    else if( !_C_CTRLisG() && !chanel_line_status[chanel_line_2] && chanel_line_status[chanel_line_1])_S_CTRL2G();
}
//采用时分复用,计算下一个线路
void __switch2next_line(void)
{
    // 1.存储本链路通道的链接通断状态
    chanel_line_status[chanel_line] = (__step == __step_over);
    // 2.计算下一个链路通道
    if(++chanel_line)
    {
        if(chanel_line > chanel_line_max)
         chanel_line = chanel_line_1;
    }
    // 3.尝试执行设备切换
    __switch_to();
}
void __switch_ini(void)
{
    chanel_line = chanel_line_1;
    chanel_line_pre = chanel_line_2;
}
/*
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;
                        send_count++;//发送次数
                    }    
                }
                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();
                            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;
                //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])
                    {
                        __enable_cur_irq();
                    }
                }
                */

            }
            if(time_ticks >= 64)
            {
                switch(    __step)
                {
                     case __step_receiving_precode0:
                         {    
                            //hold_continue_ticks++;            
                            if(rcve_data == PRE_CMD0)
                            {
                                __step = __step_receiving_precode1;
                            }else __enable_cur_irq();
                            /*
                            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超时
                                     }
                                    //gliethttp_20071212
                                    //因为发送做了工作,所以,导频的固定电平持续时间不会大于PRE_CODING_TIME_SEND,如果是真正数据一定不会超过
                                     if( hold_continue_ticks > (PRE_CODING_TIME_SEND / 64) )
                                     hold_continue_ticks = 0;
                                 }//else_disable_cur_irq();//到这,说明已经中断修正过了
                                 else hold_continue_ticks = 0;
                            */

                        }
                        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))
                {
                    //slave导频头的回馈迟迟不到,或错误,那么重发
                    //send2_7512b("ab",2,0);    
                     __step = __step_erro;
                    rcve_rdy = 0;
                    send_rdy = 0;                                        
                }
            }
            if(__get_in_data())tmp_data++;
        }else
            {
                if(__step == __step_over)
                {
                    if(time_ticks >= 64*50)//9600*1)
                    {//1s钟
                        __switch2next_line(); //测试下一个链路
                        send_count = 0;
                        send2_7512b(__get_cur_chanel(),1,0);
                    }
                }else
                    {
                        if(time_ticks >= 64*10)
                        //if(time_ticks >= 64*50
                        {
                            //if( (__step == __step_over) || (send_count > (RESEND_TRY_MAX_COUNT-1)) )
                            if(send_count > (RESEND_TRY_MAX_COUNT-1))
                            {
                                __switch2next_line();
                                send_count = 0;
                            }
                            send2_7512b(__get_cur_chanel(),1,0);
                        }    
                    }
            }
    time_ticks++;
    led_count++;
    EA = 1;
}
void ext0_interrupt(void) interrupt 0
{
    EA = 0;
//原子操作,保护共享数据区,禁止中断嵌套
    if(rcve_rdy)
    {
        timer0_restart();
        rcve2default();
    }
    EA = 1;
}
void ext1_interrupt(void) interrupt 2
{
    EA = 0;
//原子操作,保护共享数据区,禁止中断嵌套
    if(rcve_rdy)
    {
        timer0_restart();
        rcve2default();
    }
    EA = 1;
}

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

chinaunix网友2009-08-06 09:15:02

好,顶 有无硬件图