xiatianzhang 发表于 2011-9-13 12:37:45

zqy517 发表于 2011-9-13 12:40:08

不知道你那边RS485硬件是怎么接法的?一般串口用就可以了,

xiatianzhang 发表于 2011-9-13 12:45:33

yklstudent 发表于 2011-9-13 13:17:01

modbus是你需要的

snail0204 发表于 2011-9-13 14:03:50

是对协议不了解吧,485多个方向控制而已

supreme42 发表于 2011-9-13 15:44:00

看下协议吧

coleyao 发表于 2011-9-14 09:41:24

http://cache.amobbs.com/bbs_upload782111/files_45/ourdev_676363H33XVV.JPG
(原文件名:HubUp_485.JPG)

一个RS485中继器,分两个单片机,例子是与上位机通讯的单片机的,仅供参考!

//Program(cpu 8052) of Part of RS-485 repeater (UpLink)in C51
//Started at 2002/07/17
//Author FenglinYao at Nanjing
//说明:
      // 1、平时UpLink部分监视上位机状态,DownLink部分巡检下位机报警数据。
      // 2、如果UpLink部分收到登录命令,则关闭DownLink部分巡检通道,打开上位机——下位机通道。
      // 3、如果UpLink部分收到退出登录命令,则关闭上位机——下位机通道,恢复DownLink部分巡检。
      // 4、如果UpLink部分收到报警查询命令,则转换为上位机与DownLink部分通讯。
      // 5、初始化时DownLink部分从UpLink部分获取波特率。

//-----------------------------------------------------------------------------------------
#include <reg52.h>
#include <intrins.h>
#define uchar unsigned char
#define uint unsigned int
#define nop _nop_();
#define ETX 0X03      /* 消息结束标识 */
#define STX 0X02      /* 消息开始标识 */

bdata uchar Status1    _at_   0x20;       //中继器状态标志
sbitWrite_Not_Need         = Status1^0;       //显示是否需要写24C04
sbitLog_In                   = Status1^1;       //上位机已登陆到中继器标志位
sbitLog_Out                  = Status1^2;       //上位机退出登陆标志位
sbitAsk_for_Alarm            = Status1^3;       //上位机查询报警标志位
sbitAsk_for_Baud             = Status1^4;       //交换波特率状态
sbitInit                     = Status1^5;       //单片机正处于初始化状态
sbitPower_Off                = Status1^6;       //电源电压低标志位
sbitAlarm_Data_Interchange   = Status1^7;       //交换报警数据状态

bdata uchar Status2    _at_   0x21;       //中继器状态标志
sbitRead_Error               = Status2^0;       //读24C04错误
sbitWrite_Error            = Status2^1;       //写24C04错误
sbitData_Received            = Status2^2;       //发出数据已被接收到
sbitData_Ver_Send            = Status2^3;       //发出数据偶校验标志
sbitBroadCasting             = Status2^4;       //收到上位机对下位机的广播信号(时间、日期)
sbitCom1Data_Sent            = Status2^5;       //串口1已发送一字节
sbittem_bit                  = Status2^6;       //临时位变量
sbitCom1_Finished            = Status2^7;       //串口1数据已接收完毕

bdata uchar Status3    _at_   0x22;       //中继器状态标志
sbitAlarm_Over               = Status3^0;       //掉电时下位机侧传来的报警数据结束
sbitPowerTest                = Status3^1;       //掉电中断口检测位
sbitOK                     = Status3^2;       //临时变量
sbitCom1_deal                = Status3^3;       //串口收到数据要进行处理
sbitCom2_Finished            = Status3^4;       //并口数据接收完毕
sbitPTN                      = Status3^5;       //并口有数据需发送
sbitPTI                      = Status3^6;       //并口数据已发出
sbitnotusedbit               = Status3^7;       //

bdata uchar ParData    _at_   0x23;       //并行输出通讯缓冲区
sbitParData0               = ParData^0;
sbitParData1               = ParData^1;
sbitParData2               = ParData^2;
sbitParData3               = ParData^3;
sbitParData4               = ParData^4;
sbitParData5               = ParData^5;
sbitParData6               = ParData^6;
sbitParData7               = ParData^7;

bdata uchar PaOData    _at_   0x24;       //并行读入通讯缓冲区
sbitPaOData0               = PaOData^0;
sbitPaOData1               = PaOData^1;
sbitPaOData2               = PaOData^2;
sbitPaOData3               = PaOData^3;
sbitPaOData4               = PaOData^4;
sbitPaOData5               = PaOData^5;
sbitPaOData6               = PaOData^6;
sbitPaOData7               = PaOData^7;

bdata uchar SData    _at_   0x25;       //串行通讯缓冲区
sbitSD_0                   = SData^0;
sbitSD_1                   = SData^1;
sbitSD_2                   = SData^2;
sbitSD_3                   = SData^3;
sbitSD_4                   = SData^4;
sbitSD_5                   = SData^5;
sbitSD_6                   = SData^6;
sbitSD_7                   = SData^7;
bdata uchar Repeater_Address   _at_ 0x26;          //中继器地址
sbitRA_0                   = Repeater_Address^0;
sbitRA_1                   = Repeater_Address^1;
sbitRA_2                   = Repeater_Address^2;
sbitRA_3                   = Repeater_Address^3;
sbitRA_4                   = Repeater_Address^4;
sbitRA_5                   = Repeater_Address^5;
sbitRA_6                   = Repeater_Address^6;
sbitRA_7                   = Repeater_Address^7;

bdata uchar Repeater_Status   _at_ 0x27;          //中继器状态标志位
sbitDHead_Arrived          = Repeater_Status^0;
sbitSdog_Feed            = Repeater_Status^1;
sbitDog_Feedback         = Repeater_Status^2;
sbitSdog_Play            = Repeater_Status^3;
sbitAsk_for_Status         = Repeater_Status^4;
sbitRS_5                   = Repeater_Status^5;
sbitRS_6                   = Repeater_Status^6;
sbitRS_7                   = Repeater_Status^7;

uchar data baud               _at_ 0x30;          //通讯参数-波特率的设置参数
uchar data W_P_Data_Buf1      _at_ 0x32;          //Com1写数据缓冲区指针1
uchar data R_P_Data_Buf1      _at_ 0x33;          //Com2读数据缓冲区指针1
uchar data W_P_Data_Buf2      _at_ 0x34;          //并口写数据缓冲区指针2
uchar data R_P_Data_Buf2      _at_ 0x35;          //并口读数据缓冲区指针2
uchar data W_P_24C32Buf       _at_ 0x36;          //写24C32缓冲区指针
uchar data R_P_24C32Buf       _at_ 0x37;          //读24C32缓冲区指针
uchar data Buf_of_Com1      _at_ 0x38;          //串口1缓冲区
uchar data Buf_of_Com2      _at_ 0x39;          //并口缓冲区
uchar data i,j,k,l            _at_ 0x3a;          //临时变量
uchar data ErrorCode          _at_ 0x3e;          //用于返回出错代码
uintdata ET               _at_ 0x3f;          //用于测试
uchar data Timer_tem1         _at_ 0x41;          //时间临时变量
uchar data Timer_1m         _at_ 0x42;          //分
uchar data Timer_1s         _at_ 0x43;          //秒
uchar data Timer_1h         _at_ 0x44;          //小时
uchar data Timer_1d         _at_ 0x45;          //天
uchar data Timer_dog          _at_ 0x46;          //按秒记数,上位机巡检过清零,溢出时复位
uchar data Tem_Buf            _at_ 0x47;          //串口溢出后临时缓冲区
uchar data Timer_tem          _at_ 0x48;          //时间临时变量
uchar data PAlarmData         _at_ 0x49;          //保存报警数据到24C04时的报警堆栈区指针
uchar data sum                _at_ 0x4a;          //作校验和运算用
uchar data Buf_of_Com2a       _at_ 0x4b;
uchar data Buf_of_Com2b       _at_ 0x4c;
uchar data m,n                _at_ 0x4d;          //临时变量
uchar data ExchangeTemp       _at_ 0x4e;
uchar data Timer_Error      _at_ 0x4f;
uchar data StackBuf       _at_ 0x50;          //堆栈区


uchar idata Timer_Over;
uchar idata Com_Buff;                        //并口收数据缓冲区
uchar idata Data_Buf;                        //串口收数据缓冲区
uchar idata Buf_of_WR;                         //页读写24C64的缓冲区

sbit PData0=P1^0;
sbit PData1=P1^1;
sbit PData2=P1^2;
sbit PData3=P1^3;
sbit PData4=P1^4;
sbit PData5=P1^5;
sbit PData6=P1^6;
sbit PData7=P1^7;
sbit TXD2=P2^7;
sbit RXD2=P2^6;
sbit DogHand=P2^5;
sbit LED=P2^4;
sbit sda=P2^3;
sbit scl=P2^2;
sbit WDI=P2^1;
sbit DR1=P2^0;
sbit PTest=P3^2;
sbit PR1=P3^4;
sbit PR2=P3^3;
sbit AnS=P3^5;
sbit Bd1=P3^6;
sbit Bd2=P3^7;

char code RepeaterVer={"Repeater1.1 Author Yaofenglin NJ"};//记录中继器的版本及相关资料
char code NumConver={"0123456789abcdef"};
char code LetterConver={"ABCDEFGHIJKLMNOPQRSTUVWXYZ"};


voidsc_recieve(void);

//------------------------- 用于掉电保护,提醒保存未中继的报警数据到24C04 ------------------------------------
void Int0(void) interrupt 0
{
    Power_Off=1;
    REN=0;
    EX0=0;
}
//------------------------- 用于掉电保护,保存未中继的报警数据到24C04-----------------------------------------


//----------------------------------------定时中断0,发送并口数据----------------------------------------
void int_time_1ms(void) interrupt 1       //total 160T, Max 56T in use,Min 14T,Normal 38T
{
   if(PTN)
   {
      P1=ParData;
      nop; nop; nop;                  //等待数据稳定
      PR1=0;
      nop; nop; nop; nop; nop; nop;nop;
      nop; nop; nop; nop; nop; nop;nop;      //等待下位机侧中断
      PTN=0;
      nop;
      PR1=1;
       if(ParData==0x03){   nop; nop; nop; nop; nop; nop; nop; nop;
                                  nop; nop; nop; nop; nop; nop; nop; P1=0xff;}
      }
}
//------------------------------------定时中断0,发送并口数据--------------------------------------

//----------------------------------------外部中断1,接收并口数据----------------------------------------
void parData_Receive(void) interrupt 2using 3
{
   AnS=0;
   Buf_of_Com2=P1;      nop;
   Buf_of_Com2a=P1;       nop;
   Buf_of_Com2b=P1;
    if(Buf_of_Com2==Buf_of_Com2a)Buf_of_Com2=Buf_of_Com2a;
       else   Buf_of_Com2=Buf_of_Com2b;
   if(Buf_of_Com2==0x02)   W_P_Data_Buf2=0;
   if(W_P_Data_Buf2==0)
      {
         if(Buf_of_Com2==0x02)
             {    DHead_Arrived=1;
                  Com_Buff=Buf_of_Com2;
                  W_P_Data_Buf2++;
               goto L3;
            }
         }
   if((W_P_Data_Buf2>0)&&(W_P_Data_Buf2<32))
         {
             Com_Buff=Buf_of_Com2;
             W_P_Data_Buf2++;
          }
   if(W_P_Data_Buf2==32)
         W_P_Data_Buf2=0;
L3:if((Buf_of_Com2==0x03)&&( W_P_Data_Buf2!=0))
      {    DHead_Arrived=0; Com2_Finished=1;}
         else   AnS=1;
}
//----------------------------------------外部中断1,接收并口数据----------------------------------------


//--------------------------------------定时中断2,使用定时器2-------------------------------------------
void int_time_st(void) interrupt 5   using 2         //1.25ms
{
   Timer_tem++;
   if(Timer_tem>8)
   {
       Timer_tem-=8;
       Timer_tem1++;
   }
    Timer_Over++;
    if (Timer_tem1>100)
         {
            Timer_1s++;
            Timer_dog++;
            Timer_tem1-=100;
            LED=!LED;
         }
   if ((Timer_tem1%16)==0)   Sdog_Feed=1;
   if ((Timer_tem1%16)==1)   Sdog_Play=1;
   if (Timer_1s>59)   { Timer_1m++; Timer_1s-=60; }
   if (Timer_1m>59)   { Timer_1h++; Timer_1m-=60; }
   if (Timer_1h>23)   { Timer_1d++; Timer_1h-=24; }
   if (Timer_1d>29)   { Timer_1d-=30;}
        TF2=0;
}
//-----------------------------------------定时中断2结束----------------------------------------------------


//------------------------------------串口中断,接收和发送串口数据------------------------------------
void rs_485() interrupt 4   using 1
{
if(RI)
   {
      sc_recieve();
      RI=0;
   }
   else { Com1Data_Sent=1;TI=0; }
}
//------------------------------------串口中断,接收和发送串口数据------------------------------------

//------------------------------------------------串口数据接收---------------------------------------------------
voidsc_recieve(void)
{
   Buf_of_Com1=SBUF;
    if(W_P_Data_Buf1!=0)
      {
         Data_Buf=Buf_of_Com1;
         W_P_Data_Buf1++;
      }
   if((Buf_of_Com1==0x02)&!Com1_Finished)W_P_Data_Buf1=0;
   if(W_P_Data_Buf1==0)
      {
         if(Buf_of_Com1==0x02)
             {
                  BroadCasting=0;                      //接收前清零
                  Data_Buf=Buf_of_Com1;
                  W_P_Data_Buf1++;
            }
         }
    if(W_P_Data_Buf1==32)   W_P_Data_Buf1=0;
    if(W_P_Data_Buf1!=0)
      {
      while(PTN) nop;
      if((PAlarmData!=0)&Ask_for_Alarm&(Buf_of_Com1==0x03))Buf_of_Com1=0x04;
         ParData=Buf_of_Com1;
         Data_Ver_Send=0;
         PTN=1;
       }                                             //串口1送来数据一律转发给下位机侧
    if(Buf_of_Com1==0x03)
      {                                             //已登陆时收到结束符即认为该数据包有效,
         if((Log_In)|(Data_Buf==Repeater_Address)) //否则只有中继器地址相同时才认为有效
         {
             W_P_Data_Buf1=0;
             Com1_Finished=1;
         }
       }
    if((W_P_Data_Buf1==2)&&((Data_Buf==Repeater_Address)||(Data_Buf==0x01)))
      Com1_deal=1;
    if((W_P_Data_Buf1==3)&&(Data_Buf==0x01))
      BroadCasting=1;                               //上位机对下位机进行广播
    if(Com1_deal)
      {
         if(W_P_Data_Buf1==5)
             {
            if((Data_Buf=='Q')&&(Data_Buf=='?'))   Ask_for_Alarm=1;
            if((Data_Buf=='S')&&(Data_Buf=='?'))   Ask_for_Status=1;
            if((Data_Buf=='?')&&(Data_Buf=='?'))   Ask_for_Alarm=1;
            if((Data_Buf=='L')&&(Data_Buf=='I'))   Log_In=1;
            if((Data_Buf=='L')&&(Data_Buf=='O'))   Log_Out=1;
            Com1_deal=0;
             }
      }
   }
//------------------------------------------------串口数据接收---------------------------------------------------


//------------------------------喂狗程序------------------------------------
void Feed_dog(void)
{
    WDI=!WDI;
}
//------------------------------喂狗程序------------------------------------


//-------------------------------------------发送命令-----------------------------------------
voidSend_command(uchar let1,let2)
{
   Ask_for_Baud=1;
   Data_Buf=STX;
   Data_Buf=Repeater_Address;
   Data_Buf=0x00;
   Data_Buf=let1;
   Data_Buf=let2;
   Data_Buf=0x30;
   Data_Buf=0x30+baud;
   sum=Data_Buf+Data_Buf+Data_Buf+Data_Buf+Data_Buf+Data_Buf+Data_Buf;
//   for(i=0;i<7;i++) sum+=Data_Buf;
   sum=~sum+1;
   Data_Buf=NumConver;
   Data_Buf=NumConver;
   Data_Buf=ETX;
   W_P_Data_Buf1=0;
   PTN=0;
   do{
         ParData=Data_Buf;
         Data_Ver_Send=0;
         PTN=1;    Timer_Over=0;
         while(PTN&(Timer_Over<2))nop;
         for(i=0;i<2;i++) nop;
         while(!AnS&(Timer_Over<2))nop;
         W_P_Data_Buf1++;
         }
   while(Data_Buf!=ETX);
      ParData=Data_Buf;
      Data_Ver_Send=0;
      PTN=1;      Timer_Over=0;
   while(PTN&(Timer_Over<4))nop;
   for(i=0;i<2;i++) nop;
   while(!AnS&(Timer_Over<4)) nop;
      AnS=0;
   for(i=0;i<2;i++) nop;
      AnS=1;
      W_P_Data_Buf1=0;
}
//-------------------------------------------发送命令-----------------------------------------

bit Ver_Command(void)
{
      WDI=!WDI;
      Timer_Over=0;
   while(!Com2_Finished&(Timer_Over<10))   nop;
       if((Com_Buff=='B')&&(Com_Buff=='D'))
          {
            sum=Com_Buff+Com_Buff+Com_Buff+Com_Buff+Com_Buff+Com_Buff+Com_Buff;
//         for(i=0;i<7;i++) sum+=Com_Buff;
            if(Com_Buff>96)Com_Buff-=87; else Com_Buff-=48;
            sum+=Com_Buff*16;
            if(Com_Buff>96)Com_Buff-=87; else Com_Buff-=48;
            sum+=Com_Buff;
            if(sum==0)
             {
                AnS=1;
                Com2_Finished=0;
                W_P_Data_Buf2=0;
               return(0);
             }
         }
       if((Com_Buff=='B')&&(Com_Buff=='K')&&(Com_Buff==ETX))
           {
          sum=Com_Buff+Com_Buff+Com_Buff+Com_Buff+Com_Buff+Com_Buff+Com_Buff+
            Com_Buff+Com_Buff+Com_Buff+Com_Buff+Com_Buff+Com_Buff+Com_Buff+
            Com_Buff+Com_Buff+Com_Buff+Com_Buff+Com_Buff+Com_Buff+Com_Buff;
//                for(i=0;i<21;i++) sum+=Com_Buff;
      if(Com_Buff>96)Com_Buff-=87; else Com_Buff-=48;
          sum+=Com_Buff*16;
      if(Com_Buff>96)Com_Buff-=87; else Com_Buff-=48;
          sum+=Com_Buff;
                if(sum==0)
                  {
                  AnS=1;
                  Com2_Finished=0;
                  W_P_Data_Buf2=0;
                  return(0);
                   }
          }
       AnS=1;
       Com2_Finished=0;
       ET++;
       W_P_Data_Buf2=0;
       return(1);
   }
//-------------------------------------------发送、校验波特率和中继器地址-----------------------------------------


//----------------------------------初始化子程序------------------------------------------
void Init1(void)
{
    EA=0;
    P3=0xff;
    P1=0xff;
    P2=0xff;
    P0=0xff;
    Status1=0;
    Status2=0;
    Status3=0;
    ParData=0;
    SData=0;
    Timer_dog=0;
    Repeater_Address=P0;
    tem_bit=RA_0;RA_0=RA_7;   RA_7=tem_bit;
    tem_bit=RA_1;RA_1=RA_6;   RA_6=tem_bit;
    tem_bit=RA_2;RA_2=RA_5;   RA_5=tem_bit;
    tem_bit=RA_3;RA_3=RA_4;   RA_4=tem_bit;
    Repeater_Address=~Repeater_Address;
    Repeater_Address+=16;
    baud=P3;
    baud>>=6;
   if((baud==0)|(baud==3))
    {
       PCON&=0X7f;
       TH1 = 0xfd;                  //设置波特率为9.6k
    }
   if(baud==1)
    {
      PCON|=0x80;
      TH1 = 0xfd;               //设置波特率为19.2k
    }
   if(baud==2)
    {
      PCON|=0x80;
      TH1 = 0xff;               //设置波特率为57.6k
    }
    SCON=0x50;                   //定义串口使用8位数据,波特率由T1决定的方式
    TMOD=0x22;                   //定义定时器0,1为自动重载的八位计数器
    TH0=0x60;                  //定义T0的溢出时间为160T
    ET0=1;
    TR0=1;                     //开定时器0
    TR1=1;                     //开定时器1
    RCAP2H=0xfb;
    RCAP2L=0x80;
    C_T2=0;
    RCLK=0;
    TCLK=0;
    ET2=1;
    TR2=1;                        //定时器2溢出时间为1.25ms
    ES=1;                         //开窜口中断
    PT0=1;                        //定时中断0中断优先处理
    EX0=1;                        //允许掉电中断
    IT1=1;                        //中断1设为边沿触发方式
    EX1=1;
    PX1=1;
    ET=0;
//    PS=1;
    Timer_tem1=0;
    PAlarmData=0;
//    W_P_Com_Buff=0;
//    R_P_Com_Buff=0;
    W_P_Data_Buf1=0;
    R_P_Data_Buf1=0;
    W_P_Data_Buf2=0;
    R_P_Data_Buf2=0;
    DR1=0;
    for(i=0;i<32;i++)Com_Buff=0;
    for(i=0;i<32;i++)Data_Buf=0;
    for(i=0;i<32;i++)Buf_of_WR=0;
    REN=0;
    EA=1;                        //开中断
}
//----------------------------------初始化子程序------------------------------------------


//--------------------------24C04的读写操作函数集----------------------------

void start_24(void)                  //提供I2C总线的起使位
{
   scl=1; nop; sda=0; nop ;scl=0; nop; sda=1;
}

void stop_24(void)                   //提供I2C总线的停止位
{
   sda=0; scl=1; nop; sda=1; scl=0;
}

void init_24(void)                   //I2C总线初始化
{
   scl=0;stop_24();
}

unsigned char read_24(void)
{
    sda=1;
    for(k=0;k<7;k++)
   {
      scl=1; nop; SD_0=sda; nop; scl=0; nop;
      SData<<=1;
   }
    scl=1; nop; SD_0=sda; nop; scl=0; nop;
    scl=1; nop; sda=1;    nop; scl=0;
    return(SData);
}

unsigned char Sread_24(void)
{
    sda=1;
    for(k=0;k<7;k++)
   {
      scl=1; nop; SD_0=sda; nop; scl=0; nop;
      SData<<=1;
   }
    scl=1; nop; SD_0=sda; nop; scl=0; nop;
    sda=0; scl=1; nop;scl=0;sda=1;
    return(SData);
}


bitwrite_24(unsigned char dd)
{
   bit sample1;
   SData=dd;
   for(k=0;k<8;k++)
    {
       sda=SD_7; nop; scl=1; nop; scl=0; nop;
       SData<<=1;
   }
   sda=1; nop; scl=1; nop; sample1=sda;nop; scl=0; nop; nop;
   return(!sample1);
}

bit Sread64(unsigned int address)         //读取24C64指定地址的十六字节数据
{
   unsigned char Addr_Hi,Addr_Lo;
   Addr_Hi=(address&0x1fff)/256;
   Addr_Lo=(address&0xff);
   start_24();
    if(write_24(0xa0))
      {if(write_24(Addr_Hi))
         { if(write_24(Addr_Lo))
               {start_24();
                  if(write_24(0xa1))
                     {
                        for(i=0;i<31;i++)
                        Buf_of_WR=Sread_24();
                        Buf_of_WR=read_24();
                        stop_24();return(1);
                      }
                  else { Read_Error=1;stop_24(); return(0); }
                }
               else { Read_Error=1;stop_24(); return(0); }
         }
          else { Read_Error=1;stop_24();return(0); }
      }
    else { Read_Error=1;stop_24();return(0); }
}


/*
unsigned char read(unsigned int address)         //读取24C04指定地址的一字节数据
{
   unsigned char dd,ee;
   dd=((address&0x7ff)/256)<<1;                  //得到块地址
   start_24();
   ee=0xa0|dd;
    if(write_24(ee))
      {if(write_24(address))
         {
               if(write_24(0xa1|dd))
               {dd=read_24(); stop_24(); Read_Error=0; return(dd); }
               else { Read_Error=1;stop_24(); return(0); }
         }
          else { Read_Error=1;stop_24();return(0); }
      }
    else { Read_Error=1;stop_24();return(0); }
}
*/
unsigned char read64(unsigned int address)         //读取24C64指定地址的一字节数据
{
   unsigned char Addr_Hi,Addr_Lo,dd;
   Addr_Hi=(address&0x1fff)/256;
   Addr_Lo=(address&0xff);
   nop;
   start_24();
   nop;
    if(write_24(0xa0))
      {if(write_24(Addr_Hi))
         { if(write_24(Addr_Lo))
               {start_24();
                  if(write_24(0xa1))
                     {dd=read_24(); stop_24(); Read_Error=0; return(dd); }
                  else { Read_Error=1;stop_24(); return(0); }
                }
               else { Read_Error=1;stop_24(); return(0); }
         }
          else { Read_Error=1;stop_24();return(0); }
      }
    else { Read_Error=1;stop_24();return(0); }
}

/*
bit write(unsigned int address,unsigned char dd)    //写入24C04指定地址的一字节数据
{
   unsigned char ddd;
    ddd=((address&0x7ff)/256)<<1;
    start_24();
    if(write_24(0xa0|ddd))
      {if(write_24(address))
            {if(write_24(dd));stop_24();
                Timer_Over=0;while(Timer_Over<10) nop;return(1);   }
      }
   Write_Error=1;
   stop_24();
   return(0);
}
*/
bit write64(unsigned int address,unsigned char dd)    //写入24C64指定地址的一字节数据
{
   unsigned char Addr_Hi,Addr_Lo;
   Addr_Hi=(address&0x1fff)/256;
   Addr_Lo=(address&0xff);
    start_24();
    if(write_24(0xa0))
      {if(write_24(Addr_Hi))
          { if(write_24(Addr_Lo))
            {if(write_24(dd))
                   {stop_24(); Timer_Over=0;while(Timer_Over<8) nop; return(1); }
            }
          }
      }
   Write_Error=1;
   stop_24();
   return(0);
}

bit Swrite64(unsigned int address)
{
   unsigned char Addr_Hi,Addr_Lo;
   Addr_Hi=(address&0x1fff)/256;
   Addr_Lo=address&0xff;
          start_24();
      if(write_24(0xa0))
          {if(write_24(Addr_Hi))
               { if(write_24(Addr_Lo))
                  for(i=0;i<32;i++)
                      { if(!(write_24(Buf_of_WR)))
                        {stop_24(); return(0); }
                      }
               }
         }
      Write_Error=0;
      stop_24();
      Timer_Over=0;while(Timer_Over<8) nop;
      return(1);
   }

bit clear(void)
{
   unsigned int Ver1;
   for(i=0;i<16;i++)
   {
       for(j=0;j<32;j++)   Buf_of_WR=0;
      Swrite64(32*i);
      WDI=!WDI;
   }
   Ver1=0;
   for(i=0;i<16;i++)
   {
      Sread64(32*i);
      for(j=0;j<32;j++)   Ver1+=Buf_of_WR;
      WDI=!WDI;
   }
   if(Ver1==0) return(1); else return(0);
   }

void SaveTo_24C04(bit First,uchar Location)
   {
    if(First)
      {
      if(Com_Buff==0) Write_Not_Need=1; elseWrite_Not_Need=0;
      for(j=0;j<8;j++)
         {
            Buf_of_WR=Com_Buff;
            Buf_of_WR=Com_Buff;
         if(Buf_of_WR==0)
            { ExchangeTemp=PAlarmData;PAlarmData=(32*Location-64)+j+ExchangeTemp;   Alarm_Over=1;   break; }
         }
       }
    else
   {
   for(j=0;j<8;j++)
       {
          if(Alarm_Over) break;
          Buf_of_WR=Com_Buff;
          Buf_of_WR=Com_Buff;
         if(Buf_of_WR==0)
          { ExchangeTemp=PAlarmData;PAlarmData=(32*Location-64)+j+8+ExchangeTemp;   Alarm_Over=1;break; }
       }
   if(!Write_Not_Need)Swrite64(32*Location+ExchangeTemp);
   }
   }
//-----------------------------24C04的读写操作函数集----------------------------


//---------------------------------主程序体-------------------------------------

void main(void)
{
   SP=0X4f;
   Init1();
   init_24();
   if(Sread64(0))
   {
      if(Buf_of_WR!='1'||Buf_of_WR!='1'||Buf_of_WR!='Y')
         {
            OK=clear();
             for(i=0;i<32;i++)   Buf_of_WR=RepeaterVer;   //初使化24C64
            Swrite64(0);
            write64(32,0);
         }
   }
   PAlarmData=read64(32);
   tem_bit=1;
   while(tem_bit)
    {
      nop;
      Send_command('B','D');
      tem_bit=Ver_Command();
    }
    Send_command('O','V');
    for(i=0;i<32;i++)   Data_Buf=0;
    REN=1;
   while(1)
    {
ml://if(Timer_dog>240)   while(1)   //调试时停用
                     nop;          //4分钟内没有检测到上位机巡检则复位

       if(Power_Off)                           //检测到电源电压底的转储过程
         {
         REN=0;
         for(l=0;l<14;l++)
             {
               for(n=0;n<2;n++)
               {
                  tem_bit=1;
                   while(tem_bit)
                     {
                     Send_command('B','K');            //要求下位机侧将报警信息按16字节(8个报警数据)一组发给上位机侧
                     tem_bit=Ver_Command();
                      }
                  Send_command('O','V');
                  if(n==0)
                         SaveTo_24C04(1,l+2);
                     else
                         SaveTo_24C04(0,l+2);
                  }
               if(Alarm_Over){ write64(32,PAlarmData);break;}   //写报警数据指针
               }
            while(!PowerTest){ PowerTest=PTest;    WDI=!WDI;}         //试图等待电压恢复正常
            while(1) nop;                                                 //复位
         }


      if(Ask_for_Alarm|Ask_for_Status)                                  //上位机报警查询
          {
            Timer_dog=0;
            Timer_Over=0;
            while(!Com1_Finished&( Timer_Over<8)) nop;         //等待上位机发送数据完毕
             if(Com1_Finished) { DR1=1;Com1_Finished=0; }
             else { Ask_for_Alarm=0; Ask_for_Status=0; goto ml; }
            PAlarmData=read64(32);
            if((PAlarmData==0)|Ask_for_Status)                                 //如果24C04内没有掉电时未来得及中继的数据
             {
               if(Timer_Error>2)    Timer_dog=241;             //下位机侧3次无应答复位中继器
                Timer_Over=0;
               while(!Com2_Finished&( Timer_Over<20)) nop;   //等待下位机侧发送报警数据完毕
                AnS=1;
               if(!Com2_Finished)
                { Timer_Error++;DR1=0; Ask_for_Alarm=0; P1=0xff; Ask_for_Status=0; goto ml; }
                else { Com2_Finished=0;Timer_Error=0; }
             }
            else
             {
               AnS=0;
               Com_Buff=STX;
               Com_Buff=Repeater_Address;
               Com_Buff=read64(2*PAlarmData+62);
               Com_Buff='A';
               Com_Buff='L';
               Com_Buff=0x30;
               Com_Buff=read64(2*PAlarmData+63);
               sum=0;
               for(i=0;i<7;i++) sum+=Data_Buf;
               sum=~sum+1;
               Com_Buff=NumConver;
               Com_Buff=NumConver;
               Com_Buff=ETX;
               W_P_Data_Buf2=10;
             }
            R_P_Data_Buf2=0;   DR1=1;
            while(R_P_Data_Buf2<W_P_Data_Buf2)
             {
               SBUF=Com_Buff;
               //Timer_Over=0;
                while(!Com1Data_Sent) nop;
               Com1Data_Sent=0;
               R_P_Data_Buf2++;
            }
          if(PAlarmData!=0)
         {
             PAlarmData--;
             write64(32,PAlarmData);
         }
            R_P_Data_Buf2=0;
            W_P_Data_Buf2=0;
            AnS=1;
            DR1=0;
            if(Ask_for_Alarm) Ask_for_Alarm=0;else Ask_for_Status=0;
          }

          if(Log_Out&!Log_In)               //防止Log_Out标志位干扰程序运行
            {
               Log_Out=0;
            while(!Com1_Finished)nop;
               Com1_Finished=0;
            }
            
          WDI=DogHand;

          if(Log_In)                            //上位机登陆到下位机
             {
L1:            Timer_Over=0;
               while(!Com1_Finished)            //等待上位机发送数据完毕
               {
                     nop;
             //      if(Timer_Over>40) break;
               }
                Com1_Finished=0;
               if(Log_Out|BroadCasting)
               {
                  BroadCasting=0;
                  Log_In=0;
                  Log_Out=0;
                  gotoL2;
                  }
                Timer_Over=0;
            while(!Com2_Finished)            //等待下位机侧发送数据完毕
               {
                   if(!DHead_Arrived&(Timer_Over>20)){ Log_In=0; goto L2; }   //25mS收不到起始符退出
                   if(DHead_Arrived&(Timer_Over>60))   { Log_In=0; goto L2; }   //75mS左右收不到结束符退出
                   if(Com1_Finished)                   { Log_In=0; goto L2; }   //在等下位机响应时,上位机可要求中断
               }
                DR1=1;
                Com2_Finished=0;
                R_P_Data_Buf2=0;
            while(R_P_Data_Buf2<W_P_Data_Buf2)
                {
                   SBUF=Com_Buff;
                  Timer_Over=0;
                  while(!Com1Data_Sent&(Timer_Over<2)) nop;
                   Com1Data_Sent=0;
                   R_P_Data_Buf2++;
                }
                   R_P_Data_Buf2=0;
                   W_P_Data_Buf2=0;
                   AnS=1;
                   Feed_dog();
                   DR1=0;
                  goto L1;
                   nop;
       L2:         nop;
               }


          }               //End   while(1)
}                      //End   main()


//--------------------------------主程序体结束-------------------------------------

youmeng 发表于 2011-9-27 15:27:31

mark

zx696696 发表于 2011-9-28 09:01:02

最近也在了解485总线 学习下

king000 发表于 2011-10-27 13:51:53

小弟也在学习中,与楼主情况相似

bihan163 发表于 2012-8-28 09:55:10

学习了!

dadongleilei 发表于 2012-8-28 10:38:10

485是半双工的,收发切换注意下延时 其他和232处理起来是一样的

烂泥桑 发表于 2012-10-11 17:31:10

mark{:cry:}

bihan163 发表于 2014-11-2 08:08:16

mark!学习
页: [1]
查看完整版本: 求 MAX485串口程序 例子简单的最好。我会写323的程序,但是485的好像和232的不一样,有