⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 rxr_cs.c

📁 714771878051_MODBUS_RTU.rar
💻 C
📖 第 1 页 / 共 2 页
字号:
#include "STC89C51RC_RD_PLUS.h"
#include "math.h"
#include "intrins.h"


#define uchar unsigned char
#define uint unsigned int
#define ulong unsigned long

extern volatile uchar IN_IO,OUT_IO;   //定义IO输入输出映射
extern void input_io(void);  //输入处理函数
extern void jd_on(uchar x);  //接通继电器函数
extern void jd_off(uchar x); //断开继电器函数
extern uint CRC16(uchar *pushMsg,unsigned short usDataLen);//modbus crc 函数
extern uchar *pushMsg;       /*要进行CRC校验的消息*/

uchar idata recebuf[16]=0;      //接收数据缓冲区
uchar idata recebuf_com[16]=0;  //接收命令数据缓冲区
uchar idata command_Len=0;      //待处理命令消息字节长度
uchar idata command_ok=0;       //接收到一个命令结束,等待处理时为1;否则为0.
uchar idata sendbuf[16]=0;      //发送数据缓冲区
uchar idata send_Len=1;         //发送数据长度
uchar idata rece_Len=0;         //接收数据长度

uint  idata ad1,ad2,ad3,ad4;                             //模拟量输入寄存器
uint  idata ad_1[5],ad_2[5],ad_3[5],ad_4[5];   //模拟量滤波器
uchar idata addr;                                       //本机地址
uint  idata crc_z;                                       //crc校验结果
uchar idata timer0_cn=0;
uchar code  check=1;            //奇偶校验。check=0时,偶校验;check=1时;奇校验
uchar idata js_check=0;         //奇偶校验检查位。js_check=1时正确,js_check=2时错误!

uint TLC2543(uchar prot);//AD转换函数
void group_out_ad(void); //数据上传函数
void group_out_io(void); //数据上传函数
void delay(uchar x);     //短延时函数
void AV_in(void);        //模拟量输入函数
void Serial(void);       //串口配置函数
void chenck_fun(uchar x);//
void command(void);      //接收到的消息命令处理函数
void command_01(void);
void command_02(void);
void command_03(void);
void command_04(void);
void command_05(void);
void command_06(void);

void  jc(void);

/*以下定义LED指示状态*/
sbit XJ=P3^7;
sbit RUN=P3^6;

/*以下定义为TLC2543 SPI口软件模拟及转换表数组*/
sbit cs=P3^5;
sbit clk=P3^2;
sbit din=P3^3;
sbit dout=P3^4;
uint code r[8]={128,64,32,16,8,4,2,1};

/*====延时函数=====*/
void delay(uchar x)
     {
     uchar i;
     while(x--){for(i=0;i<25;i++);}
     }


/*======================*/
/*======AD转换函数======*/
/*     prot:通道号     */
/*   return:函数返回值 */
/*======================*/
uint TLC2543(uchar prot)
     {
     uchar i;
	 uchar ad_reg;     //通道号寄存器
     uint rdsh=0,rdsl=0;
     cs=0;             //使能AD转换
     ad_reg=prot;      //取通道号
	 ad_reg=ad_reg<<4;
	 /*先写入通道号*/
     for(i=0;i<8;i++)
        {
         din=(bit)(ad_reg&0x80);
         clk=1;clk=0;
		 ad_reg=ad_reg<<1;
        }
     for(i=0;i<4;i++){din=0;clk=1;clk=0;} //补4个时钟
     cs=1;delay(1);cs=0;                  //等待转换
	 ad_reg=prot;                         //取通道号
	 ad_reg=ad_reg<<4;
	 /*读AD转换结果*/
     for(i=0;i<8;i++)
        {
	     if(dout==1){rdsh+=r[i];}
		 din=1;
         clk=1;clk=0;ad_reg=ad_reg<<1;
        }
     for(i=0;i<4;i++)
	    {
		if(dout==1){rdsl+=r[i];}
		din=0;
        clk=1;clk=0;
		}
     cs=1;
	 return((rdsh<<4)+(rdsl>>4));
     }
/*=========================*/
/*======模拟量输入函数=====*/
/*===4路模拟量读取及滤波===*/
/*=========================*/
void AV_in(void)
    {
	uchar i;
	uint result;

	for(i=0;i<=3;i++){ad_1[i]=ad_1[i+1];}
    ad_1[4]=TLC2543(0);
    result=0;
	for(i=0;i<=4;i++){result+=ad_1[i];}
    ad1=(result/5);

	for(i=0;i<=3;i++){ad_2[i]=ad_2[i+1];}
    ad_2[4]=TLC2543(1);
    result=0;
	for(i=0;i<=4;i++){result+=ad_2[i];}
    ad2=(result/5);
	
	for(i=0;i<=3;i++){ad_3[i]=ad_3[i+1];}
    ad_3[4]=TLC2543(2);
    result=0;
	for(i=0;i<=4;i++){result+=ad_3[i];}
    ad3=(result/5);

	for(i=0;i<=3;i++){ad_4[i]=ad_4[i+1];}
    ad_4[4]=TLC2543(3);
    result=0;
	for(i=0;i<=4;i++){result+=ad_4[i];}
    ad4=(result/5);
	}

/*===========================*/
/*=====下位机发送数据函数====*/
/*===========================*/
void group_out_ad(void)
     {
	  uchar i;
      uint k;
      pushMsg=&sendbuf[0];
	  crc_z=CRC16(pushMsg,send_Len);
      k=crc_z;
      sendbuf[send_Len]=(uchar)(crc_z>>8); //+CRC_Hi
      send_Len++;
      sendbuf[send_Len]=(uchar)k;   //+CRC_Li
	  EA=0;
      for(i=0;i<=send_Len;i++)
	       {
           chenck_fun(sendbuf[send_Len]);
		   SBUF=sendbuf[i];while(!TI);TI=0;
		   }
	  EA=1;
      send_Len=send_Len-2; //恢复
	  RUN=1;
     }


/*==============*/
/*==系统主函数==*/
/*==============*/
void main (void)
    {
     AUXR  = 0x01;
     Serial();
	 IE    =0x92;
     IP    =0x00;
	 TR0=1;RUN=1;XJ=1;
	 jd_off(0xff);
	 P0=0xFF;
    while(1)
         {
         WDT_CONTR = 0x36;
         addr=P0;     //取地址
         AV_in();
		 if(command_ok==1)
		   {XJ=0;command();}
         }
    }

void command(void)
     {
	 uint js_CRC,star_fun,sl_n,AI;
	 RUN=0;
	 pushMsg=&recebuf_com[0];
	 crc_z=CRC16(pushMsg,command_Len-2);

     js_CRC=recebuf_com[command_Len-2];
     js_CRC=(js_CRC<<8)|((uint)(recebuf_com[command_Len-1]));

	 if((recebuf_com[0]==addr)&&(js_CRC==crc_z))//是否发给本机,并CRC正确?
	   {
	   switch (recebuf_com[1])
	         {
			 case 0x01:    //读取线圈状态
			     {
                  star_fun=recebuf_com[2];star_fun=(star_fun<<8)|(recebuf_com[3]);//取开始地址
                  sl_n=recebuf_com[4];sl_n=(sl_n<<8)|(recebuf_com[5]);     //读取地址
				  switch (star_fun)
				       {
						case 0:
						    {
							command_01();
							sendbuf[3]=(0x01&OUT_IO)?1:0;      //低
							group_out_ad();
							break;
							}
						case 1:
						    {
							command_01();
							sendbuf[3]=(0x02&OUT_IO)?1:0;      //低
							group_out_ad();
							break;
							}
						case 2:
						    {
							command_01();
							sendbuf[3]=(0x04&OUT_IO)?1:0;      //低
							group_out_ad();
							break;
							}
						case 3:
						    {
							command_01();
							sendbuf[3]=(0x08&OUT_IO)?1:0;      //低
							group_out_ad();
							break;
							}
						case 4:
						    {
							command_01();
							sendbuf[3]=(0x10&OUT_IO)?1:0;      //低
							group_out_ad();
							break;
							}
						case 5:
						    {
							command_01();
							sendbuf[3]=(0x20&OUT_IO)?1:0;      //低
							group_out_ad();
							break;
							}
						default:
						    sendbuf[0]=addr;             //取地址
	                        sendbuf[1]=0xff;             //命令号
							send_Len=2;                  //发送数据长度
							group_out_ad();
						    break;
					    }
				  break;
				 }
			 case 0x02:    //读取输入状态
			    {
				star_fun=recebuf_com[2];star_fun=(star_fun<<8)+recebuf_com[3];//取开始地址
                //sl_n=recebuf_com[4];sl_n=(sl_n<<8)|(recebuf_com[5]);        //读取的数量
				switch  (star_fun)
				        {
						case 1:
						    {
							command_02();
							sendbuf[3]=(0x01&P1)?1:0;      //低
							group_out_ad();
							break;
							}
						case 2:
						    {
							command_02();
							sendbuf[3]=(0x02&P1)?1:0;      //低
							group_out_ad();
							break;
							}
						case 3:
						    {
							command_02();
							sendbuf[3]=(0x04&P1)?1:0;      //低
							group_out_ad();
							break;
							}
						case 4:
						    {
							command_02();
							sendbuf[3]=(0x08&P1)?1:0;      //低
							group_out_ad();
							break;
							}
						case 5:
						    {
							command_02();
							sendbuf[3]=(0x10&P1)?1:0;      //低
							group_out_ad();
							break;
							}
						case 6:
						    {
							command_02();
							sendbuf[3]=(0x20&P1)?1:0;      //低
							group_out_ad();
							break;
							}
						case 7:
						    {
							command_02();
							sendbuf[3]=(0x40&P1)?1:0;      //低
							group_out_ad();
							break;
							}
						case 8:
						    {
							command_02();
							sendbuf[3]=(0x80&P1)?1:0;      //低
							group_out_ad();
							break;
							}
						default :
						    sendbuf[0]=addr;             //取地址
	                        sendbuf[1]=0xff;             //命令号
							send_Len=2;                  //发送数据长度
							group_out_ad();
						    break;
						}
				  break;
				  }
			 case 0x03:    //读取保持寄存器
			      {
                  star_fun=recebuf_com[2];star_fun=(star_fun<<8)+recebuf_com[3];//取开始地址
                  sl_n=recebuf_com[4];sl_n=(sl_n<<8)|(recebuf_com[5]);          //读取的数量
                  switch(star_fun)     //必须从地址0开始
                        {
                        case 0:
                             {
                             switch (sl_n)
				                   {
						           case 1:
						                 {
							             command_03();
							             sendbuf[2]=(uchar)(sl_n*2);     //返回字节数
							             AI=ad1;
                                         sendbuf[3]=(uchar)(AI>>8);      //高
							             sendbuf[4]=(uchar)(ad1);        //低
							             send_Len=(sendbuf[2]+3);        //发送数据长度
							             group_out_ad();
							             break;
							             }
						           case 2:
						                 {
							             command_03();
							             sendbuf[2]=(uchar)(sl_n*2);     //返回字节数
						 	             AI=ad1;
                                         sendbuf[3]=(uchar)(AI>>8);      //高
							             sendbuf[4]=(uchar)(ad1);        //低
							             AI=ad2;
                                         sendbuf[5]=(uchar)(AI>>8);      //高
							             sendbuf[6]=(uchar)(ad2);        //低

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -