久久久久久久999_99精品久久精品一区二区爱城_成人欧美一区二区三区在线播放_国产精品日本一区二区不卡视频_国产午夜视频_欧美精品在线观看免费

 找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索
查看: 2524|回復(fù): 4
打印 上一主題 下一主題
收起左側(cè)

51單片機(jī)485通訊 MODBUS-RTU程序源碼

  [復(fù)制鏈接]
跳轉(zhuǎn)到指定樓層
樓主






//本示例在Keil開發(fā)環(huán)境下請選擇Intel的8058芯片型號進(jìn)行編譯
//若無特別說明,工作頻率一般為11.0592MHz

#include "STC89C52RC.h"
#include "intrins.h"
#define uchar unsigned char//宏定義無符號字符型
#define uint unsigned int  //宏定義無符號整型

typedef unsigned char BYTE;
typedef unsigned int WORD;

#define FOSC 11059200L          //系統(tǒng)頻率
#define BAUD 9600             //串口波特率

#define NONE_PARITY     0       //無校驗(yàn)
#define ODD_PARITY      1       //奇校驗(yàn)
#define EVEN_PARITY     2       //偶校驗(yàn)
#define MARK_PARITY     3       //標(biāo)記校驗(yàn)
#define SPACE_PARITY    4       //空白校驗(yàn)

#define PARITYBIT NONE_PARITY   //定義校驗(yàn)位

/*Declare SFR associated with the IAP */
sfr IAP_DATA    =   0xE2;           //Flash data register
sfr IAP_ADDRH   =   0xE3;           //Flash address HIGH
sfr IAP_ADDRL   =   0xE4;           //Flash address LOW
sfr IAP_CMD     =   0xE5;           //Flash command register
sfr IAP_TRIG    =   0xE6;           //Flash command trigger
sfr IAP_CONTR   =   0xE7;           //Flash control register

/*Define ISP/IAP/EEPROM command*/
#define CMD_IDLE    0               //Stand-By
#define CMD_READ    1               //Byte-Read
#define CMD_PROGRAM 2               //Byte-Program
#define CMD_ERASE   3               //Sector-Erase

/*Define ISP/IAP/EEPROM operation const for IAP_CONTR*/
//#define ENABLE_IAP 0x80           //if SYSCLK<40MHz
#define ENABLE_IAP   0x81           //if SYSCLK<20MHz
//#define ENABLE_IAP x82            //if SYSCLK<10MHz
//#define ENABLE_IAP 0x83           //if SYSCLK<5MHz

//Start address for STC89C58xx EEPROM
#define IAP_ADDRESS 0x02000

sbit  IN1= P2^0;
sbit  IN2= P2^1;
sbit  IN3= P2^2;
sbit  IN4= P2^3;

sbit out1= P1^0;
sbit out2= P1^1;
sbit out3= P1^2;
sbit out4= P1^3;


bit flagTxd=0,flagFrame=0,flag=0;
unsigned char cntRxd = 0;   //接收字節(jié)計(jì)數(shù)器
unsigned char xdata bufRxd[10];
unsigned char xdata qjc[22];
bit k1=0,kt=0;
unsigned char addr=0,addr1=0;
void UartWrite(unsigned char *buf, unsigned char len);

unsigned int GetCRC16(unsigned char *ptr,  unsigned char len);
unsigned int  crc;
unsigned char crch, crcl;

bit bz1=0,bz2=0,bz3=0,bz4=0,ks=0,bk1=0,bzw=0;
uchar input=0;
uchar xx_1=0x00,xx_2=0x00,xx_3=0x00,xx_4=0x00;
uchar y_1=0x00,y_2=0x00,y_3=0x00,y_4=0x00;
uchar dat1=0x00,dat2=0x00,yy_1=0,zt1=0x00;
uchar dat4=0,dat5=0,dat6=0,dat7=0,dat8=0,dat9=0;
uint js=0;
/********************************************************************
                                        E2P函數(shù)
*********************************************************************/
void IapIdle();
BYTE IapReadByte(WORD addr);
void IapProgramByte(WORD addr, BYTE dat);
void IapEraseSector(WORD addr);
/*******************************************************************
*                        配置串口
********************************************************************/
void ConfigUART(unsigned int baud)
{
#if (PARITYBIT == NONE_PARITY)
SCON = 0x50;                //8位可變波特率
#elif (PARITYBIT == ODD_PARITY) || (PARITYBIT == EVEN_PARITY) || (PARITYBIT == MARK_PARITY)
SCON = 0xda;                //9位可變波特率,校驗(yàn)位初始為1
#elif (PARITYBIT == SPACE_PARITY)
SCON = 0xd2;                //9位可變波特率,校驗(yàn)位初始為0
#endif

TMOD &= 0x0F;  //清零T1的控制位
TMOD |= 0x20;  //配置T1為模式2
TH1 = 256 - (11059200/12/32)/baud;  //計(jì)算T1重載值
TL1 = TH1;     //初值等于重載值
ET1 = 0;       //禁止T1中斷
ES  = 1;       //使能串口中斷
TR1 = 1;       //啟動T1
//    SCON = 0x50;                //8位可變波特率
//    T2L = (65536 - (FOSC/4/BAUD));   //設(shè)置波特率重裝值
//    T2H = (65536 - (FOSC/4/BAUD))>>8;
//    AUXR = 0x14;                //T2為1T模式, 并啟動定時器2
//    AUXR |= 0x01;               //選擇定時器2為串口1的波特率發(fā)生器
}
/*******************************************************************
*                        配置定時器
********************************************************************/
void Timer0Init(void)                //1毫秒@11.0592MHz
{
AUXR |= 0x80;                //定時器時鐘1T模式
TMOD &= 0xF0;                //設(shè)置定時器模式
TL0 = 0xCD;                //設(shè)置定時初值
TH0 = 0xD4;                //設(shè)置定時初值
TF0 = 0;                //清除TF0標(biāo)志
TR0 = 1;                //定時器0開始計(jì)時
ET0 = 1;        //使能T0中斷
TR0 = 1;        //啟動T0
}

/*******************************************************************
*                        串口檢測
********************************************************************/
void UartRxMonitor(unsigned char ms){//串口接收監(jiān)控,由空閑時間判定幀結(jié)束,需在定時中斷中調(diào)用,ms-定時間隔
static unsigned char cntbkp = 0;
static unsigned char idletmr = 0;
if (cntRxd > 0){  //接收計(jì)數(shù)器大于零時,監(jiān)控總線空閑時間
if (cntbkp != cntRxd){  //接收計(jì)數(shù)器改變,即剛接收到數(shù)據(jù)時,清零空閑計(jì)時
cntbkp = cntRxd;
idletmr = 0;
}else{                   //接收計(jì)數(shù)器未改變,即總線空閑時,累積空閑時間
if (idletmr < 30){  //空閑計(jì)時小于30ms時,持續(xù)累加
idletmr += ms;
if (idletmr >= 30){  //空閑時間達(dá)到30ms時,即判定為一幀接收完畢
        flagFrame = 1;  //設(shè)置幀接收完成標(biāo)志
}
}
}
}else{
cntbkp = 0;
}
}
/*******************************************************************
*                        串口接收函數(shù)
********************************************************************/
void UartDriver(){//串口1接收
unsigned char xdata buf[20];
unsigned char len=0,lenx=0,bz=0,i=0;
if(flagFrame==1)
{
flagFrame=0;   //定時器0檢測接收的數(shù)據(jù)
len = cntRxd; //讀取接收的字節(jié)數(shù)量
lenx = cntRxd;
cntRxd = 0;  //接收計(jì)數(shù)器清零
if(bufRxd[0]==addr)
{
crc = GetCRC16(bufRxd, len-2); //計(jì)算CRC校驗(yàn)值
crch = crc >> 8;
crcl = crc & 0xFF;
if ((bufRxd[len-2] == crch) && (bufRxd[len-1] == crcl)) //判斷CRC校驗(yàn)是否正確
{
switch (bufRxd[1]) //按功能碼執(zhí)行操作
{                                                 
case 0x01://讀取輸出狀態(tài)
if((bufRxd[2]==0x00)&&(bufRxd[4]==0x00)&&(bufRxd[5]==0x01)&&((len-2)==6))
{
switch(bufRxd[3])
{
case 0x00:if(out1==0){yy_1=0x01;}else{yy_1=0x00;}break;
case 0x01:if(out2==0){yy_1=0x01;}else{yy_1=0x00;}break;
case 0x02:if(out3==0){yy_1=0x01;}else{yy_1=0x00;}break;
case 0x03:if(out4==0){yy_1=0x01;}else{yy_1=0x00;}break;
default:break;                                                                 
}
buf[0] = addr;          //地址位
buf[1] = 0x01; //功能位
buf[2] = 0x01; //數(shù)據(jù)長度位
buf[3] = yy_1;//輸出狀態(tài)2進(jìn)制表示有輸入為1,沒輸入為0
len = 4;
crc = GetCRC16(buf, len); //計(jì)算CRC校驗(yàn)值
buf[len++] = crc >> 8;    //CRC高字節(jié)
buf[len++] = crc & 0xFF;  //CRC低字節(jié)
UartWrite(buf, len);//發(fā)送其他數(shù)據(jù)用串口1
}

if((bufRxd[2]==0x00)&&(bufRxd[4]==0x00)&&(bufRxd[5]==0x02)&&((len-2)==6))
{
switch(bufRxd[3])
{
case 0x00:if(out1==0){y_1=0x01;}else{y_1=0x00;}
                                if(out2==0){y_2=0x02;}else{y_2=0x00;}
                                yy_1=(y_1|y_2);
                                break;
case 0x01:if(out2==0){y_2=0x01;}else{y_2=0x00;}
                                if(out3==0){y_3=0x02;}else{y_3=0x00;}
                                yy_1=(y_2|y_3);
                                break;                                                                     
case 0x02:if(out3==0){y_3=0x01;}else{y_3=0x00;}
                                if(out4==0){y_4=0x02;}else{y_4=0x00;}
                                yy_1=(y_3|y_4);
                                break;
case 0x03:if(out4==0){y_4=0x01;}else{y_4=0x00;}
                                                                                                                                        yy_1=y_4;                                                               
                                break;
default:break;                                                                 
}
buf[0] = addr;          //地址位
buf[1] = 0x01; //功能位
buf[2] = 0x01; //數(shù)據(jù)長度位
buf[3] = yy_1;//輸出狀態(tài)2進(jìn)制表示有輸入為1,沒輸入為0
len = 4;
crc = GetCRC16(buf, len); //計(jì)算CRC校驗(yàn)值
buf[len++] = crc >> 8;    //CRC高字節(jié)
buf[len++] = crc & 0xFF;  //CRC低字節(jié)
UartWrite(buf, len);//發(fā)送其他數(shù)據(jù)用串口1
}

if((bufRxd[2]==0x00)&&(bufRxd[4]==0x00)&&(bufRxd[5]==0x03)&&((len-2)==6))
{
switch(bufRxd[3])
{
case 0x00:if(out1==0){y_1=0x01;}else{y_1=0x00;}
                                if(out2==0){y_2=0x02;}else{y_2=0x00;}
                                if(out3==0){y_3=0x04;}else{y_3=0x00;}
                                yy_1=(y_1|y_2|y_3);
                                break;
case 0x01:if(out2==0){y_2=0x01;}else{y_2=0x00;}
                                if(out3==0){y_3=0x02;}else{y_3=0x00;}
                                if(out4==0){y_4=0x04;}else{y_4=0x00;}
                                yy_1=(y_2|y_3|y_4);
                                break;                                                                     
default:break;                                                                 
}
buf[0] = addr;          //地址位
buf[1] = 0x01; //功能位
buf[2] = 0x01; //數(shù)據(jù)長度位
buf[3] = yy_1;//輸出狀態(tài)2進(jìn)制表示有輸入為1,沒輸入為0
len = 4;
crc = GetCRC16(buf, len); //計(jì)算CRC校驗(yàn)值
buf[len++] = crc >> 8;    //CRC高字節(jié)
buf[len++] = crc & 0xFF;  //CRC低字節(jié)
UartWrite(buf, len);//發(fā)送其他數(shù)據(jù)用串口1
}                          

if((bufRxd[2]==0x00)&&(bufRxd[3]==0x00)&&(bufRxd[4]==0x00)&&(bufRxd[5]==0x04)&&((len-2)==6))
{
if(out1==0){y_1=0x01;}else{y_1=0x00;}
if(out2==0){y_2=0x02;}else{y_2=0x00;}
if(out3==0){y_3=0x04;}else{y_3=0x00;}
if(out4==0){y_4=0x08;}else{y_4=0x00;}
dat1=(y_1|y_2|y_3|y_4);
buf[0] = addr;          //地址位
buf[1] = 0x01; //功能位
buf[2] = 0x01; //數(shù)據(jù)長度位
buf[3] = dat1;//輸出狀態(tài)2進(jìn)制表示有輸入為1,沒輸入為0                                                
len = 4;
crc = GetCRC16(buf, len); //計(jì)算CRC校驗(yàn)值
buf[len++] = crc >> 8;    //CRC高字節(jié)
buf[len++] = crc & 0xFF;  //CRC低字節(jié)
UartWrite(buf, len);//發(fā)送其他數(shù)據(jù)用串口1
}
break;


case 0x02://查詢輸入狀態(tài)
if((bufRxd[2]==0x00)&&(bufRxd[4]==0x00)&&(bufRxd[5]==0x01)&&((len-2)==6))
{
switch(bufRxd[3])
{
case 0x00:if(IN1 == 0){xx_1 = 0x01;}else{xx_1 = 0x00;} dat1=xx_1;break;//查詢輸入狀態(tài)打開為1,關(guān)閉為0
case 0x01:if(IN2 == 0){xx_2 = 0x01;}else{xx_2 = 0x00;} dat1=xx_2;break;
case 0x02:if(IN3 == 0){xx_3 = 0x01;}else{xx_3 = 0x00;} dat1=xx_3;break;
case 0x03:if(IN4 == 0){xx_4 = 0x01;}else{xx_4 = 0x00;} dat1=xx_4;break;
default:break;
}

buf[0] = addr;          //地址位
buf[1] = 0x02; //功能位
buf[2] = 0x01; //數(shù)據(jù)長度位
buf[3] = dat1; //輸入狀態(tài)2進(jìn)制表示有輸入為1,沒輸入為0
len = 4;
crc = GetCRC16(buf, len); //計(jì)算CRC校驗(yàn)值
buf[len++] = crc >> 8;    //CRC高字節(jié)
buf[len++] = crc & 0xFF;  //CRC低字節(jié)
UartWrite(buf, len);//發(fā)送其他數(shù)據(jù)用串口1
}

if((bufRxd[2]==0x00)&&(bufRxd[4]==0x00)&&(bufRxd[5]==0x02)&&((len-2)==6))
{
switch(bufRxd[3])
{
case 0x00:if(IN1 == 0){xx_1 = 0x01;}else{xx_1 = 0x00;} //查詢輸入狀態(tài)打開為1,關(guān)閉為0
                                 if(IN2 == 0){xx_2 = 0x02;}else{xx_2 = 0x00;}
                                 dat1=(xx_1|xx_2);
                                 break;
case 0x01:if(IN2 == 0){xx_2 = 0x01;}else{xx_2 = 0x00;}
                                 if(IN3 == 0){xx_3 = 0x02;}else{xx_3 = 0x00;}                                                                                                         
                                 dat1=(xx_2|xx_3);
                                 break;
case 0x02:if(IN3 == 0){xx_3 = 0x01;}else{xx_3 = 0x00;}
                                 if(IN4 == 0){xx_4 = 0x02;}else{xx_4 = 0x00;}
                                 dat1=(xx_3|xx_4);
                                 break;
case 0x03:if(IN4 == 0){xx_4 = 0x01;}else{xx_4 = 0x00;} dat1=xx_4;break;
default:break;
}

buf[0] = addr;          //地址位
buf[1] = 0x02; //功能位
buf[2] = 0x01; //數(shù)據(jù)長度位
buf[3] = dat1; //輸入狀態(tài)2進(jìn)制表示有輸入為1,沒輸入為0
len = 4;
crc = GetCRC16(buf, len); //計(jì)算CRC校驗(yàn)值
buf[len++] = crc >> 8;    //CRC高字節(jié)
buf[len++] = crc & 0xFF;  //CRC低字節(jié)
UartWrite(buf, len);//發(fā)送其他數(shù)據(jù)用串口1
}

if((bufRxd[2]==0x00)&&(bufRxd[4]==0x00)&&(bufRxd[5]==0x03)&&((len-2)==6))
{
switch(bufRxd[3])
{
case 0x00:if(IN1 == 0){xx_1 = 0x01;}else{xx_1 = 0x00;} //查詢輸入狀態(tài)打開為1,關(guān)閉為0
                                 if(IN2 == 0){xx_2 = 0x02;}else{xx_2 = 0x00;}
                                 if(IN3 == 0){xx_3 = 0x04;}else{xx_3 = 0x00;}
                                 dat1=(xx_1|xx_2|xx_3);
                                 break;
case 0x01:if(IN2 == 0){xx_2 = 0x01;}else{xx_2 = 0x00;}
                                 if(IN3 == 0){xx_3 = 0x02;}else{xx_3 = 0x00;}
                                 if(IN4 == 0){xx_4 = 0x04;}else{xx_4 = 0x00;}
                                 dat1=(xx_2|xx_3|xx_4);
                                 break;
default:break;
}

buf[0] = addr;          //地址位
buf[1] = 0x02; //功能位
buf[2] = 0x01; //數(shù)據(jù)長度位
buf[3] = dat1; //輸入狀態(tài)2進(jìn)制表示有輸入為1,沒輸入為0
len = 4;
crc = GetCRC16(buf, len); //計(jì)算CRC校驗(yàn)值
buf[len++] = crc >> 8;    //CRC高字節(jié)
buf[len++] = crc & 0xFF;  //CRC低字節(jié)
UartWrite(buf, len);//發(fā)送其他數(shù)據(jù)用串口1
}

if((bufRxd[2]==0x00)&&(bufRxd[3]==0x00)&&(bufRxd[4]==0x00)&&(bufRxd[5]==0x04)&&((len-2)==6))
{

if(IN1 == 0){xx_1 = 0x01;}else{xx_1 = 0x00;} //查詢輸入狀態(tài)打開為1,關(guān)閉為0
if(IN2 == 0){xx_2 = 0x02;}else{xx_2 = 0x00;}
if(IN3 == 0){xx_3 = 0x04;}else{xx_3 = 0x00;}
if(IN4 == 0){xx_4 = 0x08;}else{xx_4 = 0x00;}
dat1=(xx_1|xx_2|xx_3|xx_4);

buf[0] = addr;          //地址位
buf[1] = 0x02; //功能位
buf[2] = 0x01; //數(shù)據(jù)長度位
buf[3] = dat1; //輸入狀態(tài)2進(jìn)制表示有輸入為1,沒輸入為0
len = 4;
crc = GetCRC16(buf, len); //計(jì)算CRC校驗(yàn)值
buf[len++] = crc >> 8;    //CRC高字節(jié)
buf[len++] = crc & 0xFF;  //CRC低字節(jié)
UartWrite(buf, len);//發(fā)送其他數(shù)據(jù)用串口1
}
break;

case 0x03://讀取寄存器狀態(tài)
if((bufRxd[2]==0x00)&&(bufRxd[4]==0x00)&&(bufRxd[5]==0x01)&&((len-2)==6))//讀取2個字節(jié)
{
dat5=addr;
buf[0] = addr;          //地址位
buf[1] = 0x03; //功能位
buf[2] = 0x02; //數(shù)據(jù)長度位
buf[3] = dat4;//高
buf[4] = dat5;//低                                                               
len = 5;
crc = GetCRC16(buf, len); //計(jì)算CRC校驗(yàn)值
buf[len++] = crc >> 8;    //CRC高字節(jié)
buf[len++] = crc & 0xFF;  //CRC低字節(jié)
UartWrite(buf, len);//發(fā)送其他數(shù)據(jù)用串口1
}                                                       
break;

case 0x04://讀取寄存器狀態(tài)
if((bufRxd[2]==0x00)&&(bufRxd[4]==0x00)&&(bufRxd[5]==0x01))//讀取2個字節(jié)
{
switch(bufRxd[3])
{
case 0x00: dat4=qjc[0];dat5=qjc[1];break;
case 0x01: dat4=qjc[2];dat5=qjc[3];break;
case 0x02: dat4=qjc[4];dat5=qjc[5];break;
case 0x03: dat4=qjc[6];dat5=qjc[7];break;
case 0x04: dat4=qjc[8];dat5=qjc[9];break;
case 0x05: dat4=qjc[10];dat5=qjc[11];break;
case 0x06: dat4=qjc[12];dat5=qjc[13];break;
case 0x07: dat4=qjc[14];dat5=qjc[15];break;
case 0x08: dat4=qjc[16];dat5=qjc[17];break;
case 0x09: dat4=qjc[18];dat5=qjc[19];break;
case 0x0A: dat4=qjc[20];dat5=qjc[21];break;
default:break;
}
buf[0] = addr;          //地址位
buf[1] = 0x04; //功能位
buf[2] = 0x02; //數(shù)據(jù)長度位
buf[3] = dat4;//高
buf[4] = dat5;//低                                                               
len = 5;
crc = GetCRC16(buf, len); //計(jì)算CRC校驗(yàn)值
        buf[len++] = crc >> 8;    //CRC高字節(jié)
        buf[len++] = crc & 0xFF;  //CRC低字節(jié)
        UartWrite(buf, len);//發(fā)送其他數(shù)據(jù)用串口1
}
if((bufRxd[2]==0x00)&&(bufRxd[4]==0x00)&&(bufRxd[5]==0x02))//讀取4個字節(jié)
{
switch(bufRxd[3])
{
case 0x00: dat4=qjc[0];dat5=qjc[1];dat6=qjc[2];dat7=qjc[3];break;
case 0x01: dat4=qjc[2];dat5=qjc[3];dat6=qjc[4];dat7=qjc[5];break;
case 0x02: dat4=qjc[4];dat5=qjc[5];dat6=qjc[6];dat7=qjc[7];break;
case 0x03: dat4=qjc[6];dat5=qjc[7];dat6=qjc[8];dat7=qjc[9];break;
case 0x04: dat4=qjc[8];dat5=qjc[9];dat6=qjc[10];dat7=qjc[11];break;
case 0x05: dat4=qjc[10];dat5=qjc[11];dat6=qjc[12];dat7=qjc[13];break;
case 0x06: dat4=qjc[12];dat5=qjc[13];dat6=qjc[14];dat7=qjc[15];break;
case 0x07: dat4=qjc[14];dat5=qjc[15];dat6=qjc[16];dat7=qjc[17];break;
case 0x08: dat4=qjc[16];dat5=qjc[17];dat6=qjc[18];dat7=qjc[19];break;
case 0x09: dat4=qjc[18];dat5=qjc[19];dat6=qjc[20];dat7=qjc[21];break;
case 0x0A: dat4=qjc[20];dat5=qjc[21];dat6=0x00;dat7=qjc[22];break;
default:break;
}
buf[0] = addr;          //地址位
buf[1] = 0x04; //功能位
buf[2] = 0x04; //數(shù)據(jù)長度位
buf[3] = dat4;//高
buf[4] = dat5;//低                 
buf[5] = dat6;//高
buf[6] = dat7;//低                                                                       
len = 7;
crc = GetCRC16(buf, len); //計(jì)算CRC校驗(yàn)值
        buf[len++] = crc >> 8;    //CRC高字節(jié)
        buf[len++] = crc & 0xFF;  //CRC低字節(jié)
        UartWrite(buf, len);//發(fā)送其他數(shù)據(jù)用串口1
}
break;


case 0x05://設(shè)置單個輸出狀態(tài)
if((bufRxd[2]==0x00)&&(bufRxd[5]==0x00))//輸出1
{
if((bufRxd[3]==0x00)&&(bufRxd[4]==0xFF)){out1=0;}//打開第一路輸出
if((bufRxd[3]==0x00)&&(bufRxd[4]==0x00)){out1=1;}//關(guān)閉第一路輸出
if((bufRxd[3]==0x01)&&(bufRxd[4]==0xFF)){out2=0;}//打開第二路輸出
if((bufRxd[3]==0x01)&&(bufRxd[4]==0x00)){out2=1;}//關(guān)閉第二路輸出
if((bufRxd[3]==0x02)&&(bufRxd[4]==0xFF)){out3=0;}//打開第二路輸出
if((bufRxd[3]==0x02)&&(bufRxd[4]==0x00)){out3=1;}//關(guān)閉第二路輸出
if((bufRxd[3]==0x03)&&(bufRxd[4]==0xFF)){out4=0;}//打開第二路輸出
if((bufRxd[3]==0x03)&&(bufRxd[4]==0x00)){out4=1;}//關(guān)閉第二路輸出                                                                   
                         buf[0] = addr;          //地址位
                         buf[1] = 0x05; //功能位
                         buf[2] = 0x00; //線圈地址高
                         buf[3] = bufRxd[3]; //線圈地址低
                         buf[4] = bufRxd[4]; //打開FF/關(guān)閉00
                         buf[5] = 0x00;
                         len = 6;
        crc = GetCRC16(buf, len); //計(jì)算CRC校驗(yàn)值
        buf[len++] = crc >> 8;    //CRC高字節(jié)
        buf[len++] = crc & 0xFF;  //CRC低字節(jié)
        UartWrite(buf, len);//發(fā)送其他數(shù)據(jù)用串口1
}
break;

case 0x06://寫單個寄存器
if((bufRxd[2]==0x00)&&(bufRxd[3]==0x00)&&(bufRxd[4]==0x00))
{
addr=bufRxd[5];//k1=1;
IapEraseSector(0x2000);
IapProgramByte(0x2001,addr);  //寫入扇區(qū)
buf[0] = addr;          //地址位
buf[1] = 0x06; //功能位
buf[2] = bufRxd[2]; //線圈地址高
buf[3] = bufRxd[3]; //線圈地址低
buf[4] = bufRxd[4]; //發(fā)什么回什么
buf[5] = bufRxd[5];
len = 6;
crc = GetCRC16(buf, len); //計(jì)算CRC校驗(yàn)值
buf[len++] = crc >> 8;    //CRC高字節(jié)
buf[len++] = crc & 0xFF;  //CRC低字節(jié)
UartWrite(buf, len);//發(fā)送其他數(shù)據(jù)用串口1
}

break;

case 0x10://寫多個寄存器
if((bufRxd[2]==0x00)&&(bufRxd[4]==0x00)&&(bufRxd[5]==0x02)&&(bufRxd[6]==0x04))
{
switch(bufRxd[3])
{
case 0x00: qjc[0]=bufRxd[7];qjc[1]=bufRxd[8];qjc[2]=bufRxd[9];qjc[3]=bufRxd[10];break;
case 0x01: qjc[2]=bufRxd[4];qjc[3]=bufRxd[5];qjc[4]=bufRxd[9];qjc[5]=bufRxd[10];break;
case 0x02: qjc[4]=bufRxd[4];qjc[5]=bufRxd[5];qjc[6]=bufRxd[9];qjc[7]=bufRxd[10];break;
case 0x03: qjc[6]=bufRxd[4];qjc[7]=bufRxd[5];qjc[8]=bufRxd[9];qjc[9]=bufRxd[10];break;
case 0x04: qjc[8]=bufRxd[4];qjc[9]=bufRxd[5];qjc[10]=bufRxd[9];qjc[11]=bufRxd[10];break;
case 0x05: qjc[10]=bufRxd[4];qjc[11]=bufRxd[5];qjc[12]=bufRxd[9];qjc[13]=bufRxd[10];break;
case 0x06: qjc[12]=bufRxd[4];qjc[13]=bufRxd[5];qjc[14]=bufRxd[9];qjc[15]=bufRxd[10];break;
case 0x07: qjc[14]=bufRxd[4];qjc[15]=bufRxd[5];qjc[16]=bufRxd[9];qjc[17]=bufRxd[10];break;
case 0x08: qjc[16]=bufRxd[4];qjc[17]=bufRxd[5];qjc[18]=bufRxd[9];qjc[19]=bufRxd[10];break;
case 0x09: qjc[18]=bufRxd[4];qjc[19]=bufRxd[5];qjc[20]=bufRxd[9];qjc[21]=bufRxd[10];break;
case 0x0A: qjc[20]=bufRxd[4];qjc[21]=bufRxd[5];qjc[22]=bufRxd[10];break;
default:break;
}
buf[0] = addr;          //地址位
buf[1] = 0x10; //功能位
buf[2] = bufRxd[2]; //線圈地址高
buf[3] = bufRxd[3]; //線圈地址低
buf[4] = bufRxd[4]; //發(fā)什么回什么
buf[5] = bufRxd[5];
len = 6;
crc = GetCRC16(buf, len); //計(jì)算CRC校驗(yàn)值
        buf[len++] = crc >> 8;    //CRC高字節(jié)
        buf[len++] = crc & 0xFF;  //CRC低字節(jié)
        UartWrite(buf, len);//發(fā)送其他數(shù)據(jù)用串口1
}

break;

case 0x0F://多路控制
if((bufRxd[2]==0x00)&&(bufRxd[3]==0x00)&&(bufRxd[4]==0x00)&&(bufRxd[5]==0x04)&&(bufRxd[6]==0x01))
{
zt1=bufRxd[7];        //                                          
P1=~zt1;
buf[0] = addr;          //地址位
buf[1] = 0x0F; //功能位
buf[2] = bufRxd[2]; //數(shù)據(jù)長度位
buf[3] = bufRxd[3];
buf[4] = bufRxd[4];
buf[5] = bufRxd[5];
len = 6;
crc = GetCRC16(buf, len); //計(jì)算CRC校驗(yàn)值
        buf[len++] = crc >> 8;    //CRC高字節(jié)
        buf[len++] = crc & 0xFF;  //CRC低字節(jié)
        UartWrite(buf, len);//發(fā)送其他數(shù)據(jù)用串口1
}

break;
default:break;

}

}               

}  
if((bufRxd[0]==0xAA)&&(bufRxd[1]==0x00)&&(bufRxd[2]==0x00)&&(bufRxd[3]==0x00)&&(bufRxd[4]==0xBB)&&(len==5))
{
addr1=IapReadByte(0x2001);
buf[0]=0xAA;
buf[1]=addr;
buf[2]=addr1;
buf[3]=0x00;
buf[4]=0xBB;
len=5;
UartWrite(buf, len);//發(fā)送其他數(shù)據(jù)用串口1
}
for(bz=0;bz<lenx;bz++){bufRxd[bz] = 0;}         //把串口接收的數(shù)據(jù)緩存清零
}


}

void senddate()//發(fā)送輸入狀態(tài)
{
unsigned char xdata buf[10];
unsigned char len=0;
if((k1==1)&&(bk1==0))       
{
bk1=1;
switch(input)
{
case 1:if(IN1 == 0){xx_1 = 0x01;}else{xx_1 = 0x00;} dat1=xx_1;break;//查詢輸入狀態(tài)打開為1,關(guān)閉為0
case 2:if(IN2 == 0){xx_2 = 0x01;}else{xx_2 = 0x00;} dat1=xx_2;break;
case 3:if(IN3 == 0){xx_3 = 0x01;}else{xx_3 = 0x00;} dat1=xx_3;break;
case 4:if(IN4 == 0){xx_4 = 0x01;}else{xx_4 = 0x00;} dat1=xx_4;break;
default:break;
}

buf[0] = addr; //地址位
buf[1] = 0x02; //功能位
buf[2] = 0x01; //數(shù)據(jù)長度位
buf[3] = dat1; //輸入狀態(tài)2進(jìn)制表示有輸入為1,沒輸入為0
len = 4;
crc = GetCRC16(buf, len); //計(jì)算CRC校驗(yàn)值
buf[len++] = crc >> 8;    //CRC高字節(jié)
buf[len++] = crc & 0xFF;  //CRC低字節(jié)
UartWrite(buf, len);//發(fā)送其他數(shù)據(jù)用串口1
k1=0;
ks=1;
}       
if(bzw==1){bzw=0;bk1=0;}//消抖延時后清零       
}

/*******************************************************************
*                        主函數(shù)
********************************************************************/
void main()
{
P1=0XFF;
ES = 1;                     //使能串口1中斷
EA = 1;
ConfigUART(9600);
Timer0Init();
if(IapReadByte(0x2001)==0xff){addr=0x01;}//首次讀取,如果讀到0xFF說明沒有存過數(shù)據(jù),直接付給00值
else
{
addr=IapReadByte(0x2001);
}
while(1)
{

if((IN1==0)&&(bz1==0)){bz1=1;k1=1;input=1;}
if((IN1==1)&&(bz1==1)){bz1=0;k1=1;input=1;}

if((IN2==0)&&(bz2==0)){bz2=1;k1=1;input=2;}
if((IN2==1)&&(bz2==1)){bz2=0;k1=1;input=2;}

if((IN3==0)&&(bz3==0)){bz3=1;k1=1;input=3;}
if((IN3==1)&&(bz3==1)){bz3=0;k1=1;input=3;}

if((IN4==0)&&(bz4==0)){bz4=1;k1=1;input=4;}
if((IN4==1)&&(bz4==1)){bz4=0;k1=1;input=4;}


senddate();
UartDriver();
//    if(k1==1)
//          {
//           IapEraseSector(0x08000);
//                 IapProgramByte(0x08001,addr);  //寫入扇區(qū)
//                 k1=0;
//          }
}

}
void InterruptTimer0() interrupt 1{//T0中斷服務(wù)函數(shù),執(zhí)行串口接收監(jiān)控
TL0 = 0xCD;                //設(shè)置定時初值
TH0 = 0xD4;
if(ks==1){js++;if(js==150){js=0;bzw=1;ks=0;}}
UartRxMonitor(1);  //串口接收監(jiān)

}
/*******************************************************************
*                       串口中斷
********************************************************************/
void Uart() interrupt 4 using 1
{
if (RI)
{
RI = 0;                 //清除RI位
ACC=SBUF;
if(P==RB8){flag=1;}else{flag=0;}
if (cntRxd < sizeof(bufRxd)) {//接收緩沖區(qū)尚未用完時,保存接收字節(jié),并遞增計(jì)數(shù)器
bufRxd[cntRxd++] = SBUF;        // cntRxd++這個很重要,一開始 cntRxd < sizeof(bufRxd)當(dāng)進(jìn)入函數(shù)的次數(shù)增加,cntRxd慢慢變大,當(dāng)傳入的數(shù)據(jù)不滿的時候就        用時間檢測,判斷是否是傳輸完成
}
}
if (TI)
{
TI = 0;                 //清除TI位
flagTxd = 1;
}
}
/*******************************************************************
*                        串口發(fā)送函數(shù)
********************************************************************/
void UartWrite(unsigned char *buf, unsigned char len){//串口數(shù)據(jù)寫入,即串口發(fā)送函數(shù),buf-待發(fā)送數(shù)據(jù)的指針,len-指定的發(fā)送長度

while (len--){   //循環(huán)發(fā)送所有字節(jié)
flagTxd = 0;      //清零發(fā)送標(biāo)志
ACC = *buf;
if (P)                      //根據(jù)P來設(shè)置校驗(yàn)位
{
#if (PARITYBIT == ODD_PARITY)
TB8 = 0;                //設(shè)置校驗(yàn)位為0
#elif (PARITYBIT == EVEN_PARITY)
TB8 = 1;                //設(shè)置校驗(yàn)位為1
#endif
}
else
{
#if (PARITYBIT == ODD_PARITY)
TB8 = 1;                //設(shè)置校驗(yàn)位為1
#elif (PARITYBIT == EVEN_PARITY)
TB8 = 0;                //設(shè)置校驗(yàn)位為0
#endif
}
SBUF = ACC;    //發(fā)送一個字節(jié)數(shù)據(jù)
buf++;
while (!flagTxd); //等待該字節(jié)發(fā)送完成
}

}
/*----------------------------
Disable ISP/IAP/EEPROM function
Make MCU in a safe state
----------------------------*/
void IapIdle()
{
IAP_CONTR = 0;                  //Close IAP function
IAP_CMD = 0;                    //Clear command to standby
IAP_TRIG = 0;                   //Clear trigger register
IAP_ADDRH = 0x80;               //Data ptr point to non-EEPROM area
IAP_ADDRL = 0;                  //Clear IAP address to prevent misuse
}

/*----------------------------
Read one byte from ISP/IAP/EEPROM area
Input: addr (ISP/IAP/EEPROM address)
Output:Flash data
----------------------------*/
BYTE IapReadByte(WORD addr)
{
BYTE dat;                       //Data buffer

IAP_CONTR = ENABLE_IAP;         //Open IAP function, and set wait time
IAP_CMD = CMD_READ;             //Set ISP/IAP/EEPROM READ command
IAP_ADDRL = addr;               //Set ISP/IAP/EEPROM address low
IAP_ADDRH = addr >> 8;          //Set ISP/IAP/EEPROM address high
IAP_TRIG = 0x46;                //Send trigger command1 (0x46)
IAP_TRIG = 0xb9;                //Send trigger command2 (0xb9)
_nop_();                        //MCU will hold here until ISP/IAP/EEPROM operation complete
dat = IAP_DATA;                 //Read ISP/IAP/EEPROM data
IapIdle();                      //Close ISP/IAP/EEPROM function

return dat;                     //Return Flash data
}

/*----------------------------
Program one byte to ISP/IAP/EEPROM area
Input: addr (ISP/IAP/EEPROM address)
dat (ISP/IAP/EEPROM data)
Output:-
----------------------------*/
void IapProgramByte(WORD addr, BYTE dat)
{
IAP_CONTR = ENABLE_IAP;         //Open IAP function, and set wait time
IAP_CMD = CMD_PROGRAM;          //Set ISP/IAP/EEPROM PROGRAM command
IAP_ADDRL = addr;               //Set ISP/IAP/EEPROM address low
IAP_ADDRH = addr >> 8;          //Set ISP/IAP/EEPROM address high
IAP_DATA = dat;                 //Write ISP/IAP/EEPROM data
IAP_TRIG = 0x46;                //Send trigger command1 (0x46)
IAP_TRIG = 0xb9;                //Send trigger command2 (0xb9)
_nop_();                        //MCU will hold here until ISP/IAP/EEPROM operation complete
IapIdle();
}

/*----------------------------
Erase one sector area
Input: addr (ISP/IAP/EEPROM address)
Output:-
----------------------------*/
void IapEraseSector(WORD addr)
{
IAP_CONTR = ENABLE_IAP;         //Open IAP function, and set wait time
IAP_CMD = CMD_ERASE;            //Set ISP/IAP/EEPROM ERASE command
IAP_ADDRL = addr;               //Set ISP/IAP/EEPROM address low
IAP_ADDRH = addr >> 8;          //Set ISP/IAP/EEPROM address high
IAP_TRIG = 0x46;                //Send trigger command1 (0x46)
IAP_TRIG = 0xb9;                //Send trigger command2 (0xb9)
_nop_();                        //MCU will hold here until ISP/IAP/EEPROM operation complete
IapIdle();
}

/********************************************************************
                                        結(jié)束
*********************************************************************/


RS485通信 MODBUS-RTU標(biāo)準(zhǔn)程序.rar

79.45 KB, 下載次數(shù): 127, 下載積分: 黑幣 -5

分享到:  QQ好友和群QQ好友和群 QQ空間QQ空間 騰訊微博騰訊微博 騰訊朋友騰訊朋友
收藏收藏8 分享淘帖 頂3 踩
回復(fù)

使用道具 舉報(bào)

沙發(fā)
ID:137005 發(fā)表于 2023-12-18 15:42 | 只看該作者
多路輸出,不是連續(xù)P1,如輸出IO是P10,P16,P17,P54,程序要如何修改?
回復(fù)

使用道具 舉報(bào)

板凳
ID:1109353 發(fā)表于 2024-1-16 09:10 | 只看該作者
這是作為從機(jī)的代碼嗎?可以和modbus poll通訊嗎
回復(fù)

使用道具 舉報(bào)

地板
ID:933601 發(fā)表于 2024-1-16 10:34 | 只看該作者
謝謝分享!樓主有沒有模擬量采集例程讓我們學(xué)習(xí)學(xué)習(xí)?
回復(fù)

使用道具 舉報(bào)

5#
ID:1006852 發(fā)表于 2024-1-17 12:04 | 只看該作者
換STC其它型號改動大嗎?
回復(fù)

使用道具 舉報(bào)

您需要登錄后才可以回帖 登錄 | 立即注冊

本版積分規(guī)則

手機(jī)版|小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術(shù)交流QQ群281945664

Powered by 單片機(jī)教程網(wǎng)

快速回復(fù) 返回頂部 返回列表
主站蜘蛛池模板: 99热视| h视频在线观看免费 | 一区二区不卡 | 亚洲国产aⅴ精品 | 性高湖久久久久久久久aaaaa | 国产精品日韩在线观看 | 99久久精品国产一区二区三区 | 日韩高清中文字幕 | 91精品国产综合久久久久久漫画 | 精品免费国产视频 | 欧美精品欧美精品系列 | 91成人在线| 欧美激情精品久久久久久变态 | 国产精品永久免费观看 | 91国内视频在线 | 国产精品久久午夜夜伦鲁鲁 | 国产一区二区三区欧美 | 国产精品成人品 | 一级黄色录像片子 | 久久精品一区 | 欧美日韩国产一区二区三区不卡 | 99在线国产 | 成人午夜网站 | 久久精品国产亚洲一区二区三区 | 91在线视频播放 | 久久国产一区二区 | 国产成人免费 | 国产亚洲一区二区三区 | 久久免费视频1 | 女女百合av大片一区二区三区九县 | 欧美一级毛片久久99精品蜜桃 | 中文字幕二区三区 | 国产成人高清视频 | 99看片网| 久久久五月天 | 久久69精品久久久久久久电影好 | 久久久久国产一区二区三区 | 视频一区二区在线观看 | 亚洲精品一区二区在线观看 | 久久精品国产一区二区电影 | 国产精品视频网站 |