久久久久久久999_99精品久久精品一区二区爱城_成人欧美一区二区三区在线播放_国产精品日本一区二区不卡视频_国产午夜视频_欧美精品在线观看免费
標題:
STC15系列單片機RS-485通訊例程(帶CRC校驗)
[打印本頁]
作者:
ai__si
時間:
2018-8-23 15:36
標題:
STC15系列單片機RS-485通訊例程(帶CRC校驗)
STC15系列單片機RS-485通訊例程
單片機源程序如下:
#include <uart.h>
sbit bitCtrl_485Eable = P1^3;//
sbit bitCtrl_485_2Eable = P7^3;//
xdata unsigned char mod_comd[9]={0x01,0x04,0x75,0x31,0x02,0x00,0x00,0x08,0x09};
unsigned char freq = 0;
/****************************************************************************************/
// unsigned char MyDeviceAddr _at_ 0x06000;
// unsigned char PODeviceAddr _at_ 0x05999;
unsigned char MyDeviceAddr;
unsigned char PODeviceAddr;
/*********************************
串口1變量定義
**********************************/
bit busy1 = 0;
xdata unsigned char u8Uart1TxBuffer[USART1_TX_BUFFER_SIZE];
xdata unsigned char u8Uart1RxBuffer[USART1_RX_BUFFER_SIZE];
unsigned char u8Rx1Head = 0;
unsigned char u8Rx1Tail = 0;
unsigned char u8Tx1Head = 0;
unsigned char u8Tx1Tail = 0;
unsigned char mdbs1_stat = 0;
unsigned char mdbs1_len = 0;
unsigned char mdbs1_cnt = 0;
unsigned char mdbs1_maxlen = 0;
xdata unsigned char mdbs1_Rxbuf[16];
xdata unsigned char mdbs1_Txbuf[16];
unsigned char mdbs1_pos = 0;
unsigned char mdbs1_timerflag = 0;
unsigned char mdbs1_overtime = 0;
unsigned char mdbs1_data_len = 0;
/****************************************************************************************/
/****************************************************************************************/
/*********************************
串口2變量定義
**********************************/
bit busy2 = 0;
xdata unsigned char u8Uart2TxBuffer[USART2_TX_BUFFER_SIZE];
xdata unsigned char u8Uart2RxBuffer[USART2_RX_BUFFER_SIZE];
unsigned char u8Rx2Head = 0;
unsigned char u8Rx2Tail = 0;
unsigned char u8Tx2Head = 0;
unsigned char u8Tx2Tail = 0;
unsigned char mdbs2_stat = 0;
unsigned char mdbs2_len = 0;
unsigned char mdbs2_cnt = 0;
unsigned char mdbs2_maxlen = 0;
xdata unsigned char mdbs2_Rxbuf[16];
xdata unsigned char mdbs2_Txbuf[16];
unsigned char mdbs2_pos = 0;
unsigned char mdbs2_timerflag = 0;
unsigned char mdbs2_overtime = 0;
unsigned char mdbs2_data_len = 0;
/****************************************************************************************/
/*定時器0初始化,采用16位自動重裝技術模式*/
void Timer0Init(void) //10毫秒@11.0592MHz //16位重裝計數器
{
AUXR &= 0x7F; //定時器時鐘12T模式
TMOD &= 0xF0; //設置定時器模式
TL0 = -(FOSC/12/100); //設置定時初值
TH0 = -(FOSC/12/100) >> 8; //設置定時初值
// RL_TH0
TF0 = 0; //清除TF0標志
TR0 = 1; //定時器0開始計時
Timer0_InterruptFirst();
ET0 = 1; //enable timer0 interrupt
}
/***定時器0中斷服務函數**/
void tm0_isr() interrupt 1 using 1
{
TF0 = 0; //清除TF0標志
TL0 = -(FOSC/12/100); //設置定時初值
TH0 = -(FOSC/12/100) >> 8; //設置定時初值
++freq;
}
/************************************************************************/
//8位數據 波特率可變 無奇偶檢驗位 1位起始位 1位停止位
//使用定時器1作為波特率發生器
void Uart1Init(void) //9600bps@11.0592MHz
{
PCON &= 0x3F; //波特率不倍速
SCON = 0x50; //8位數據,可變波特率
AUXR &= 0xBF; //定時器1時鐘為Fosc/12,即12T 傳統51速度
AUXR &= 0xFE; //串口1選擇定時器1為波特率發生器
// AUXR |=0X01; //串口1選擇定時器2為波特率發生器
TMOD &= 0x0F; //清除定時器1模式位
TMOD |= 0x20; //設定定時器1為8位自動重裝方式
// TMOD &= 0xF0; //清除定時器2模式位
// TMOD |= 0x02; //設定定時器2為8位自動重裝方式
TL1 = -(FOSC/12/32/BAUD); //設定定時初值
TH1 = -(FOSC/12/32/BAUD); //設定定時器重裝值
/*****
定時器2工作方式為固定16位自動重裝載 裝在值需重新計算
*/
// T2L = -(FOSC/12/32/BAUD); //設定定時初值
// T2H = -(FOSC/12/32/BAUD); //設定定時器重裝值
ET1 = 0; //禁止定時器1中斷
TR1 = 1; //啟動定時器1
// S1_USE_P36P37(); //定義串口1管腳
UART1_InterruptFirst(); //中斷優先級設定
ES = 1; //????????
bitCtrl_485Eable=0;
}
/****************** *****************************************************/
/*************串口2初始化************/
/************************************************************************/
//#define S3_Int_en() IE2 |= 8
void Uart2Init(void) //10毫秒@11.0592MHz
{
/*
T2MOD = 0; //初始化模式寄存器
T2CON = 0; //初始化控制寄存器
TL2 = -(FOSC/12/100); //設置定時初值
TH2 = -(FOSC/12/100) >> 8; //設置定時初值
RCAP2L = -(FOSC/12/100); //設置定時重載值
RCAP2H = -(FOSC/12/100) >> 8; //設置定時重載值
TR2 = 1; //定時器2開始計時
ET2 = 1; //enable timer2 interrupt
*/
// Timer2_12T();
// Timer2_AsTimer();
// T2L = -(FOSC/12/100); //設置定時初值
// T2H = -(FOSC/12/100) >> 8; //設置定時初值
// Timer2_Run();
// Timer2_InterruptEnable();
//Timer2_InterruptDisable();
S2CON = 0x50;
Timer2_12T();
T2L = (65536-(FOSC/4/12/BAUD));
T2H = (65536-(FOSC/4/12/BAUD))>> 8;
Timer2_Run();
Timer2_InterruptDisable();
// S2_USE_P10P11();//使用默認端口
S2_Int_en(); //中斷允許
// S3CON = 0x10;
// Timer2_12T();
// T2L = -(FOSC/12/4/BAUD);
// T2H = -(FOSC/12/4/BAUD) >> 8;
// Timer2_Run();
// Timer2_InterruptDisable();
// S3_USE_P50P51();
// S3_Int_en();
bitCtrl_485_2Eable = 0;
InternalRAM_enable(); ////禁止外部XRAM,允許使用內部1024RAM
}
/****************************************************************************************/
/****************************************************************************************/
/**串口1中斷服務函數!!!!!!!!!!!!!!!
!!!!!!!!!!!!*/
/*******************************
接收數據緩存區滿時,丟棄接收到的數據,數據處理后釋放數據緩存區
********************************/
void Uart1_Isr() interrupt 4 using 2
{
// EA = 0;
if (RI==1)
{
RI = 0; //Clear receive interrupt flag
if(u8Rx1Head+1 != u8Rx1Tail)
{
u8Uart1RxBuffer[u8Rx1Head++] = SBUF;
u8Rx1Head &= USART1_RX_BUFFER_MASK;
}
}
if (TI==1)
{
TI=0; //Clear transmit interrupt flag
busy1 = 0; //Clear transmit busy flag
if(u8Tx1Head != u8Tx1Tail)
{
bitCtrl_485Eable =1;
SBUF = u8Uart1TxBuffer[u8Tx1Tail++];
u8Tx1Tail &= USART1_TX_BUFFER_MASK;
}
else
{
bitCtrl_485Eable =0;
}
}
// EA = 1;
}
/********串口2中斷服務函數******/
/*******************************
接收數據緩存區滿時,丟棄接收到的數據,數據處理后釋放數據緩存區
********************************/
#define S2RI 0x01
#define S2TI 0x02
void Uart2_Isr() interrupt 8 using 2
{
// EA = 0;
if (S2CON&S2RI)
{
S2CON &= ~S2RI; //Clear receive interrupt flag
if(u8Rx2Head+1 != u8Rx2Tail)
{
u8Uart2RxBuffer[u8Rx2Head++] = S2BUF;
u8Rx2Head &= USART2_RX_BUFFER_MASK;
}
}
if (S2CON&S2TI)
{
S2CON &= ~S2TI; //Clear transmit interrupt flag
busy2 = 0; //Clear transmit busy flag
if(u8Tx2Head != u8Tx2Tail)
{
bitCtrl_485_2Eable = 1;
S2BUF = u8Uart2TxBuffer[u8Tx2Tail++];
u8Tx2Tail &= USART2_TX_BUFFER_MASK;
}
else
{
bitCtrl_485_2Eable = 0;
}
}
// EA = 1;
}
/********************************************************************************************/
/*******讀串口1緩沖區1字節函數********************************************************
讀取一個字節的接收緩存數據 ,釋放一個字節的緩存空間 讀取的數據存放在*pdat
返回0,表示緩存區有未讀數據
返回-1,表示緩存區沒有未讀數據
****************************/
BYTE Recv1Data(BYTE *pdat)
{
if(u8Rx1Head != u8Rx1Tail) //有未處理數據
{
*pdat = u8Uart1RxBuffer[u8Rx1Tail++];
u8Rx1Tail &= USART1_RX_BUFFER_MASK;
return 0;
}
return -1;
}
/****************************************************************************************/
/********************************************************************************************/
/**********讀串口2緩沖區1字節函數*****************************************************
讀取一個字節的接收緩存數據 ,釋放一個字節的緩存空間 讀取的數據存放在*pdat
返回0,表示緩存區有未讀數據
返回-1,表示緩存區沒有未讀數據
****************************/
BYTE Recv2Data(BYTE *pdat)
{
if(u8Rx2Head != u8Rx2Tail) //有未處理數據
{
*pdat = u8Uart2RxBuffer[u8Rx2Tail++];
u8Rx2Tail &= USART2_RX_BUFFER_MASK;
return 0;
}
return -1;
}
/****************************************************************************************/
/* Send a byte data to UART
Input: dat (data to be sent)
Output:None
串口1發送一個字節的數據
u8UartTxBuffer 用于發送數據的緩存 防止數據未及時發送時的數據堆積
----------------------------*/
BYTE Send1Data(BYTE dat)
{
if((u8Tx1Head == u8Tx1Tail) && (0 == busy1))
{
busy1 = 1;
bitCtrl_485Eable =1;
// S3BUF = dat;
// S2BUF = dat;
SBUF = dat;
return 0;
}
if(u8Tx1Head+1 == u8Tx1Tail)
{
return -1; // full
}
u8Uart1TxBuffer[u8Tx1Head++] = dat; //如果發送繁忙 則數據保存在發送緩存區
u8Tx1Head &= USART1_TX_BUFFER_MASK;
return 1;
}
/****************************************************************************************/
/****************************************************************************************/
/* Send a byte data to UART
Input: dat (data to be sent)
Output:None
串口2發送一個字節的數據
u8UartTxBuffer 用于發送數據的緩存 防止數據未及時發送時的數據堆積
----------------------------*/
BYTE Send2Data(BYTE dat)
{
if((u8Tx2Head == u8Tx2Tail) && (0 == busy2))
{
busy2 = 1;
bitCtrl_485_2Eable = 1;
// S3BUF = dat;
S2BUF = dat;
// SBUF = dat;
return 0;
}
if(u8Tx2Head+1 == u8Tx2Tail)
{
return -1; // full
}
u8Uart2TxBuffer[u8Tx2Head++] = dat; //如果發送繁忙 則數據保存在發送緩存區
u8Tx2Head &= USART2_TX_BUFFER_MASK;
return 1;
}
/****************************************************************************************/
/****************************************************************************************/
/****************************************
從串口1數據緩存區讀取數據函數
讀取數據緩存區數據,釋放緩存空間 讀取的數據保存在mdbs_Rxbuf中!!
并判斷接收數據 的有效性 (本地地址校驗,讀寫位校驗,數據長度校驗,CRC校驗)
返回0,表示已接收完成一組有效數據
返回-1,表示,緩存區沒有數據或數據不完整! 或與本機地址不匹配
!!!如果緩存中有數據,單數據不完整,則把已有數據保存在 mdbs_Rxbuf中,下次進入此函數,數據繼續保存
mdbs1_Rxbuf[] 接收數據存儲區
mdbs1_len 接收數據長度
mdbs1_maxlen 接收指令數據區的長度
mdbs1_stat 接收狀態
mdbs1_pos 數據存儲地址
mdbs1_overtime 接收超時標志
mdbs1_timerflag 連續接收標志
freq 時鐘節拍
如果中間有數據錯誤,則重新尋找數據開始位置!!!
************************************************/
unsigned char link_recv1_pkt(void)
{
unsigned char u8dat;
if(mdbs1_timerflag)
{
if(freq - mdbs1_overtime >= 10)
{
Link1ClearState();
}
}
while(0 == Recv1Data(&u8dat))//
{
switch(mdbs1_stat) //初次進入 mdbs_stat=0
{
case 0:
{
if(u8dat > 256) //地址不能大于247? 255?
{
break;
}
if(PODeviceAddr!=u8dat) return -1; //不是目標地址返回-1
mdbs1_Rxbuf[mdbs1_pos++] = u8dat;
mdbs1_len++;
mdbs1_stat = 1;
freq=mdbs1_overtime;
mdbs1_timerflag = 1;
} break;
case 1: //功能碼
{
mdbs1_Rxbuf[mdbs1_pos++] = u8dat;
mdbs1_len++;
if((READ_INPUT == u8dat)||(WRITE_INPUT==u8dat))
{
mdbs1_stat = 2;
//mdbs_cnt = 0;
//mdbs_maxlen = 4;
}
else
{
Link1ClearState();
break;
}
freq=mdbs1_overtime;
mdbs1_timerflag = 1;
} break;
case 2: //標識碼高字節,不做處理直接保存
{
mdbs1_Rxbuf[mdbs1_pos++] = u8dat;
mdbs1_len++;
mdbs1_stat = 3;
freq=mdbs1_overtime;
mdbs1_timerflag = 1;
} break;
case 3: //標識碼底字節,不做處理直接保存
{
mdbs1_Rxbuf[mdbs1_pos++] = u8dat;
mdbs1_len++;
mdbs1_stat = 4;
freq=mdbs1_overtime;
mdbs1_timerflag = 1;
} break;
case 4: //數據長度
{
mdbs1_Rxbuf[mdbs1_pos++] = u8dat;
mdbs1_len++;
mdbs1_cnt++;
//if(mdbs_cnt >= mdbs_maxlen)
//{
mdbs1_stat = 5;
mdbs1_cnt = 0;
mdbs1_maxlen = u8dat;
if(u8dat==0) //如果數據長度為0 只剩下CRC校驗數據
{
mdbs1_stat = 100;
mdbs1_cnt = 0;
mdbs1_maxlen = 2;
}
//}
freq=mdbs1_overtime;
mdbs1_timerflag = 1;
} break;
case 5: //數據長度不為0,繼續接收有效數據
{
mdbs1_Rxbuf[mdbs1_pos++] = u8dat;
mdbs1_len++;
mdbs1_cnt++;
if(mdbs1_cnt >= mdbs1_maxlen)
{
mdbs1_stat = 100;
mdbs1_cnt = 0;
mdbs1_maxlen = 2;
}
freq=mdbs1_overtime;
mdbs1_timerflag = 1;
} break;
case 100: //CRC校驗位
{
mdbs1_Rxbuf[mdbs1_pos++] = u8dat;
mdbs1_len++;
mdbs1_cnt++;
if(mdbs1_cnt >= mdbs1_maxlen)
{
mdbs1_timerflag = 0;
mdbs1_data_len = mdbs1_len;
if((CRC16(mdbs1_Rxbuf, mdbs1_len) == 0) && (PODeviceAddr == mdbs1_Rxbuf[0]))
{
Link1ClearState();
return 0;
}
Link1ClearState();
}
freq=mdbs1_overtime;
mdbs1_timerflag = 1;
} break;
default:
Link1ClearState();
break;
}
}
return -1;
}
/****************************************************************************************/
/****************************************
從串口2數據緩存區讀取數據函數
讀取數據緩存區數據,釋放緩存空間 讀取的數據保存在mdbs2_Rxbuf中!!
并判斷接收數據 的有效性 (本地地址校驗,讀寫位校驗,數據長度校驗,CRC校驗)
返回0,表示已接收完成一組有效數據
返回-1,表示,緩存區沒有數據或數據不完整! 或與本機地址不匹配
!!!如果緩存中有數據,單數據不完整,則把已有數據保存在 mdbs_Rxbuf中,下次進入此函數,數據繼續保存
mdbs2_Rxbuf[] 接收數據存儲區
mdbs2_len 接收數據長度
mdbs2_maxlen 接收指令數據區的長度
mdbs2_stat 接收狀態
mdbs2_pos 數據存儲地址
mdbs2_overtime 接收超時標志
mdbs2_timerflag 連續接收標志
freq 時鐘節拍
如果中間有數據錯誤,則重新尋找數據開始位置!!!
************************************************/
unsigned char link_recv2_pkt(void)
{
unsigned char u8dat;
if(mdbs2_timerflag)
{
if(freq - mdbs2_overtime >= 10)
{
Link2ClearState();
}
}
while(0 == Recv2Data(&u8dat))//
{
switch(mdbs2_stat) //初次進入 mdbs_stat=0
{
case 0:
{
if(u8dat > 256) //地址不能大于247? 255?
{
break;
}
if(MyDeviceAddr!=u8dat) return -1; //不是目標地址返回-1
mdbs2_Rxbuf[mdbs2_pos++] = u8dat;
mdbs2_len++;
mdbs2_stat = 1;
freq=mdbs2_overtime;
mdbs2_timerflag = 1;
} break;
case 1: //功能碼
{
mdbs2_Rxbuf[mdbs2_pos++] = u8dat;
mdbs2_len++;
if((READ_INPUT == u8dat)||(WRITE_INPUT==u8dat))
{
mdbs2_stat = 2;
//mdbs_cnt = 0;
//mdbs_maxlen = 4;
}
else
{
Link2ClearState();
break;
}
freq=mdbs2_overtime;
mdbs2_timerflag = 1;
} break;
case 2: //標識碼高字節,不做處理直接保存
{
mdbs2_Rxbuf[mdbs2_pos++] = u8dat;
mdbs2_len++;
mdbs2_stat = 3;
freq=mdbs2_overtime;
mdbs2_timerflag = 1;
} break;
case 3: //標識碼底字節,不做處理直接保存
{
mdbs2_Rxbuf[mdbs2_pos++] = u8dat;
mdbs2_len++;
mdbs2_stat = 4;
freq=mdbs2_overtime;
mdbs2_timerflag = 1;
} break;
case 4: //數據長度
{
mdbs2_Rxbuf[mdbs2_pos++] = u8dat;
mdbs2_len++;
mdbs2_cnt++;
//if(mdbs_cnt >= mdbs_maxlen)
//{
mdbs2_stat = 5;
mdbs2_cnt = 0;
mdbs2_maxlen = u8dat;
if(u8dat==0) //如果數據長度為0 只剩下CRC校驗數據
{
mdbs2_stat = 100;
mdbs2_cnt = 0;
mdbs2_maxlen = 2;
}
//}
freq=mdbs2_overtime;
mdbs2_timerflag = 1;
} break;
case 5: //數據長度不為0,繼續接收有效數據
{
mdbs2_Rxbuf[mdbs2_pos++] = u8dat;
mdbs2_len++;
mdbs2_cnt++;
if(mdbs2_cnt >= mdbs2_maxlen)
{
mdbs2_stat = 100;
mdbs2_cnt = 0;
mdbs2_maxlen = 2;
}
freq=mdbs2_overtime;
mdbs2_timerflag = 1;
} break;
case 100: //CRC校驗位
{
mdbs2_Rxbuf[mdbs2_pos++] = u8dat;
mdbs2_len++;
mdbs2_cnt++;
if(mdbs2_cnt >= mdbs2_maxlen)
{
mdbs2_timerflag = 0;
mdbs2_data_len = mdbs2_len;
if((CRC16(mdbs2_Rxbuf, mdbs2_len) == 0) && (MyDeviceAddr == mdbs2_Rxbuf[0]))
{
Link2ClearState();
return 0;
}
Link2ClearState();
}
freq=mdbs2_overtime;
mdbs2_timerflag = 1;
} break;
default:
Link2ClearState();
break;
}
}
return -1;
}
/******************************/
/**************************************************/
/*****串口1發送數據函數***********/
/*******發送指定長度的數據*****/
void link1_send_pkt(unsigned char *buf, unsigned char len)
{
unsigned char i,k;
for(i=0; i<len; i++)
{
k = Send1Data(buf[i]);
}
}
/****************************************************************************************/
/*****串口2發送數據函數***********/
/*******發送指定長度的數據*****/
void link2_send_pkt(unsigned char *buf, unsigned char len)
{
unsigned char i,k;
for(i=0; i<len; i++)
{
k = Send2Data(buf[i]);
}
}
/*****串口2發送數據函數
對指定長度的數據加CRC校驗,并發送
*********//*(發送串口1接收的的數據)*/
void svr1_msg(unsigned char *command_buf,unsigned char sentlen)
{
unsigned int crc;
if(sentlen < 4) //指令長度不應小于4,否則是無效數據
{
return;
}
// if(0 == sentlen)return;
crc = CRC16(command_buf,sentlen);
command_buf[sentlen]=crc>>8;
sentlen++;
command_buf[sentlen]=crc;
sentlen++;
link1_send_pkt(command_buf,sentlen);
}
/******************************************************************************/
/*****串口2發送數據函數
對指定長度的數據加CRC校驗,并發送
*********//*(發送串口1接收的的數據)*/
void svr2_msg(unsigned char *command_buf,unsigned char sentlen)
{
unsigned int crc;
if(sentlen < 4) //指令長度不應小于4,否則是無效數據
{
return;
}
// if(0 == sentlen)return;
crc = CRC16(command_buf,sentlen);
command_buf[sentlen]=crc>>8;
sentlen++;
command_buf[sentlen]=crc;
sentlen++;
link2_send_pkt(command_buf,sentlen);
}
/*16位CRC校驗表*/
code const unsigned char auchCRCHi[]={
0x00,0xc1,0x81,0x40,0x01,0xc0,0x80,0x41,0x01,0xc0,0x80,0x41,0x00,0xc1,0x81,0x40,
0x01,0xc0,0x80,0x41,0x00,0xc1,0x81,0x40,0x00,0xc1,0x81,0x40,0x01,0xc0,0x80,0x41,
0x01,0xc0,0x80,0x41,0x00,0xc1,0x81,0x40,0x00,0xc1,0x81,0x40,0x01,0xc0,0x80,0x41,
0x00,0xc1,0x81,0x40,0x01,0xc0,0x80,0x41,0x01,0xc0,0x80,0x41,0x00,0xc1,0x81,0x40,
0x01,0xc0,0x80,0x41,0x00,0xc1,0x81,0x40,0x00,0xc1,0x81,0x40,0x01,0xc0,0x80,0x41,
0x00,0xc1,0x81,0x40,0x01,0xc0,0x80,0x41,0x01,0xc0,0x80,0x41,0x00,0xc1,0x81,0x40,
0x00,0xc1,0x81,0x40,0x01,0xc0,0x80,0x41,0x01,0xc0,0x80,0x41,0x00,0xc1,0x81,0x40,
0x01,0xc0,0x80,0x41,0x00,0xc1,0x81,0x40,0x00,0xc1,0x81,0x40,0x01,0xc0,0x80,0x41,
0x01,0xc0,0x80,0x41,0x00,0xc1,0x81,0x40,0x00,0xc1,0x81,0x40,0x01,0xc0,0x80,0x41,
0x00,0xc1,0x81,0x40,0x01,0xc0,0x80,0x41,0x01,0xc0,0x80,0x41,0x00,0xc1,0x81,0x40,
0x00,0xc1,0x81,0x40,0x01,0xc0,0x80,0x41,0x01,0xc0,0x80,0x41,0x00,0xc1,0x81,0x40,
0x01,0xc0,0x80,0x41,0x00,0xc1,0x81,0x40,0x00,0xc1,0x81,0x40,0x01,0xc0,0x80,0x41,
0x00,0xc1,0x81,0x40,0x01,0xc0,0x80,0x41,0x01,0xc0,0x80,0x41,0x00,0xc1,0x81,0x40,
0x01,0xc0,0x80,0x41,0x00,0xc1,0x81,0x40,0x00,0xc1,0x81,0x40,0x01,0xc0,0x80,0x41,
0x01,0xc0,0x80,0x41,0x00,0xc1,0x81,0x40,0x00,0xc1,0x81,0x40,0x01,0xc0,0x80,0x41,
0x00,0xc1,0x81,0x40,0x01,0xc0,0x80,0x41,0x01,0xc0,0x80,0x41,0x00,0xc1,0x81,0x40
};
code const unsigned char auchCRCLo[]={
0x00,0xc0,0xc1,0x01,0xc3,0x03,0x02,0xc2,0xc6,0x06,0x07,0xc7,0x05,0xc5,0xc4,0x04,
0xcc,0x0c,0x0d,0xcd,0x0f,0xcf,0xce,0x0e,0x0a,0xca,0xcb,0x0b,0xc9,0x09,0x08,0xc8,
0xd8,0x18,0x19,0xd9,0x1b,0xdb,0xda,0x1a,0x1e,0xde,0xdf,0x1f,0xdd,0x1d,0x1c,0xdc,
0x14,0xd4,0xd5,0x15,0xd7,0x17,0x16,0xd6,0xd2,0x12,0x13,0xd3,0x11,0xd1,0xd0,0x10,
0xf0,0x30,0x31,0xf1,0x33,0xf3,0xf2,0x32,0x36,0xf6,0xf7,0x37,0xf5,0x35,0x34,0xf4,
0x3c,0xfc,0xfd,0x3d,0xff,0x3f,0x3e,0xfe,0xfa,0x3a,0x3b,0xfb,0x39,0xf9,0xf8,0x38,
0x28,0xe8,0xe9,0x29,0xeb,0x2b,0x2a,0xea,0xee,0x2e,0x2f,0xef,0x2d,0xed,0xec,0x2c,
0xe4,0x24,0x25,0xe5,0x27,0xe7,0xe6,0x26,0x22,0xe2,0xe3,0x23,0xe1,0x21,0x20,0xe0,
0xa0,0x60,0x61,0xa1,0x63,0xa3,0xa2,0x62,0x66,0xa6,0xa7,0x67,0xa5,0x65,0x64,0xa4,
0x6c,0xac,0xad,0x6d,0xaf,0x6f,0x6e,0xae,0xaa,0x6a,0x6b,0xab,0x69,0xa9,0xa8,0x68,
0x78,0xb8,0xb9,0x79,0xbb,0x7b,0x7a,0xba,0xbe,0x7e,0x7f,0xbf,0x7d,0xbd,0xbc,0x7c,
0xb4,0x74,0x75,0xb5,0x77,0xb7,0xb6,0x76,0x72,0xb2,0xb3,0x73,0xb1,0x71,0x70,0xb0,
0x50,0x90,0x91,0x51,0x93,0x53,0x52,0x92,0x96,0x56,0x57,0x97,0x55,0x95,0x94,0x54,
0x9c,0x5c,0x5d,0x9d,0x5f,0x9f,0x9e,0x5e,0x5a,0x9a,0x9b,0x5b,0x99,0x59,0x58,0x98,
0x88,0x48,0x49,0x89,0x4b,0x8b,0x8a,0x4a,0x4e,0x8e,0x8f,0x4f,0x8d,0x4d,0x4c,0x8c,
0x44,0x84,0x85,0x45,0x87,0x47,0x46,0x86,0x82,0x42,0x43,0x83,0x41,0x81,0x80,0x40
};
/****************************************************************************************/
/*----------------------------
***********************************************/
/*LRC校驗子程序
unsigned char LRC(unsigned char *auchMsg, unsigned char usDataLen)
{
unsigned char uchLRC = 0;
while (usDataLen--) { uchLRC += *auchMsg++ ; }
// return ((uint8)(~uchLRC+1));
return ((unsigned char)(-((char)uchLRC)));
}*/
/*16位CRC校驗子程序*/
unsigned int CRC16(unsigned char* puchMsg, unsigned char usDataLen)
{
unsigned char uchCRCHi=0xff;
unsigned char uchCRCLo=0xff;
unsigned char uIndex;
while(usDataLen--)
{
uIndex=uchCRCHi^*(puchMsg++);
uchCRCHi=uchCRCLo^auchCRCHi[uIndex];
uchCRCLo=auchCRCLo[uIndex];
}
return uchCRCHi<<8|uchCRCLo;
}
//
//void Timer0Init(void) //10毫秒@11.0592MHz
//{
// AUXR &= 0x7F; //定時器時鐘12T模式
// TMOD &= 0xF0; //設置定時器模式
// //TMOD |= 0x01; //設置定時器模式
// TL0 = -(FOSC/12/100); //設置定時初值
// TH0 = -(FOSC/12/100) >> 8; //設置定時初值
// TF0 = 0; //清除TF0標志
// TR0 = 1; //定時器0開始計時
// Timer0_InterruptFirst();
// ET0 = 1; //enable timer0 interrupt
//}
/********************************************\
/****************************************************************************************/
/****************************************************************************************/
/*
*/
unsigned char MODbus_flag=0;//接收到指令標志
unsigned long int MODbus_flag_time=0;
unsigned long int MODbus_flag_Rtime=0;
unsigned int MODbus_flag2=0;
void Modbus_task(void)
{
unsigned int crc1;
unsigned char i;
if(0 == link_recv2_pkt()) //串口2接收到有效命令
{
for(i=0;i<16;i++)
{
mdbs1_Txbuf[i]=mdbs2_Rxbuf[i];
}
mdbs1_Txbuf[0]=PODeviceAddr; //本機地址改為目標地址
svr1_msg(mdbs1_Txbuf, mdbs2_data_len-2) ; //發送更改后的數據 //svr1_msg只能發送1ci?
MODbus_flag=1;
}
if(MODbus_flag==1)
{
MODbus_flag_time++;
if(0==link_recv1_pkt()) //串口2接收應答 進行數據校驗 存儲
{
for(i=0;i<16;i++)
{
mdbs2_Txbuf[i]=mdbs1_Rxbuf[i];
}
mdbs2_Txbuf[0]= MyDeviceAddr; //本機地址改為目標地址
svr2_msg(mdbs2_Txbuf, mdbs1_data_len-2) ; //發送更改后的數據
MODbus_flag=0;
MODbus_flag_time=0;
}
else if(MODbus_flag_time>50000)
{
svr1_msg(mdbs1_Txbuf, mdbs2_data_len-2) ;
// svr2_msg(mdbs1_Rxbuf, mdbs1_data_len-2) ; //chongxin發送更改后的數據
MODbus_flag_time=0;
}
}
else
{
MODbus_flag_Rtime++;
if(MODbus_flag_Rtime%500==0)
{
bitCtrl_485Eable = 1;
mod_comd[0]=PODeviceAddr;
crc1 = CRC16(mod_comd,7);
mod_comd[7]=crc1>>8;
mod_comd[8]=crc1;
link1_send_pkt(mod_comd,9);
MODbus_flag2=1;
MODbus_flag_Rtime=0;
}
if(MODbus_flag2==1)
{
Delay_nMS(10);
bitCtrl_485Eable = 0;
delay(20);
if(0==link_recv1_pkt())
{
// TM_CloseAllDisplay();
DisplayTem(mdbs1_Rxbuf[5],mdbs1_Rxbuf[6]) ;//濕度
DisplayRH(mdbs1_Rxbuf[7],mdbs1_Rxbuf[8]) ;//溫度
MODbus_flag2=0;
MODbus_flag_time=0;
}
else
{
MODbus_flag_time++;
if(MODbus_flag_time>2000)
{
MODbus_flag_time=0;
TM_OpenAllDisplay();
}
}
}
}
}
/*****************************************************************************************/
/**根據modbus1接收區的數據指令,賦值modbus的發送區數據***/
/**返回指令長度***/
/*data_num接收區指令的數據長度
ack_num 發送區的指令長度
data_start 接收區標識碼
/****************************************************************************************/
/*
unsigned int modbus_data(unsigned char *command_buf, unsigned char *ack_buf)
{
unsigned int data_start;
unsigned char data_num;
unsigned char ack_num;
unsigned char tempdata;
switch(command_buf[1])
{
case READ_INPUT: //讀輸入寄存器值讀3區
ack_buf[0]=command_buf[0];
ack_buf[1]=command_buf[1];
ack_buf[2]=command_buf[2];
ack_buf[3]=command_buf[3];
data_start=(command_buf[2]<<8)+command_buf[3]; //標識碼
//data_num=(command_buf[4]<<8)+command_buf[5];
data_num = command_buf[4]; //數據長度
if(data_num>2) data_num=2; //防止數據超界 //接收的指令數據長度要么是0要么是2
//ack_buf[2]=data_num*2;
ack_num=5; //應答信號從ack_buf【5】數據開始, ack_buf【4】中要存放數據長度
if(Addr_RH_Start == data_start)
{
ack_buf[ack_num]=Sensor_Data[0]; ack_num++;
ack_buf[ack_num]=Sensor_Data[1]; ack_num++; //7???
ack_buf[4] = 2; //應答指令數據長度
if(2 == data_num)
{
ack_buf[ack_num]=Sensor_Data[2]; ack_num++;
ack_buf[ack_num]=Sensor_Data[3]; ack_num++;
ack_buf[4] = 4; //應答指令數據長度
}
}
if(Addr_Temp_Start == data_start)
{
ack_buf[ack_num]=Sensor_Data[2]; ack_num++;
ack_buf[ack_num]=Sensor_Data[3]; ack_num++;
ack_buf[4] = 2;
}
//modify by cjt 2016-07-08
if(Addr_RHSet_Start == data_start)
{
ack_buf[ack_num]=0; ack_num++;
ack_buf[ack_num]=u8DefaultRH; ack_num++;
ack_buf[4] = 2;
}
if(Addr_TempSet_Start == data_start)
{
ack_buf[ack_num]=0; ack_num++;
ack_buf[ack_num]=u8DefaultTemp; ack_num++;
ack_buf[4] = 2;
}
if(Addr_RDTemp_Start == data_start)
{
ack_buf[ack_num]=0; ack_num++;
ack_buf[ack_num]=u8ds18b20_temp; ack_num++;
ack_buf[4] = 2;
……………………
…………限于本文篇幅 余下代碼請從51黑下載附件…………
復制代碼
所有資料51hei提供下載:
RS-485.rar
(7.05 KB, 下載次數: 621)
2018-8-23 15:36 上傳
點擊文件名下載附件
下載積分: 黑幣 -5
作者:
hyl21000
時間:
2018-9-18 15:53
請放一個完整的代碼, 不然看的太累了
作者:
dg0099
時間:
2019-5-20 16:15
不錯的東西,下來試試
作者:
rtc900
時間:
2019-5-20 17:42
⊙⊙!牛逼啊
作者:
gongzhu
時間:
2019-6-5 22:29
調用方法也得簡單寫一個啊,這樣得完全消化才行
作者:
kepuple
時間:
2019-6-6 20:36
謝謝樓主,牛人!
作者:
lvxinchao
時間:
2019-6-28 08:04
樓主 自己調試過嗎
作者:
懶散專業戶
時間:
2019-7-17 17:14
感謝樓主分享,正好用的到,謝謝
作者:
engcyh
時間:
2019-7-18 18:26
這個程序看不懂,有沒有完整的工程
作者:
wubangdi
時間:
2019-9-24 22:54
謝謝,學習學習
作者:
94情節
時間:
2019-10-11 14:07
確實很棒
作者:
94情節
時間:
2019-10-11 14:08
牛人,這代碼確實很棒
作者:
zhangjianhu
時間:
2019-10-11 18:04
代碼寫的太流暢了,邏輯清晰。
作者:
zhangjianhu
時間:
2019-10-12 08:51
已經下載,正在研讀,準備用在項目上。
作者:
zwj695535100
時間:
2019-10-28 13:59
這個帖子不錯!
作者:
rotga
時間:
2019-12-15 20:09
正好在用15的片子,拿來學習一下。感謝樓主的代碼。
作者:
DataBus
時間:
2020-3-7 11:10
感謝樓主的分享,想學一下485通信有時間研究一下。
作者:
chcmn
時間:
2020-3-11 19:13
不錯的東西,下來試試
作者:
啟晨
時間:
2020-5-19 18:31
謝謝分享!!!
作者:
xllin
時間:
2020-5-20 10:33
謝謝分享
作者:
goty2000
時間:
2020-8-8 06:00
正需要,下載來看看,謝謝樓主!
作者:
yinshan82064
時間:
2020-11-18 23:56
程序都不全,沒什么參考價值
作者:
timeabcd
時間:
2020-11-23 09:28
支持一個,不知道好用不!
作者:
dxj54991
時間:
2020-12-20 16:00
能多機通訊嗎?
作者:
silenRay
時間:
2021-1-20 08:32
這個是標準的MODBUS RTU嗎?可以和PLC通信嗎?PLC地址如何設置呢?
作者:
人人學會單片機
時間:
2021-1-20 10:39
標題錯誤,485只是一個硬件。具體什么協議,最好說清楚。我用485芯片做過的協議,最少20多種了
作者:
yhy08090
時間:
2021-7-5 09:43
人人學會單片機 發表于 2021-1-20 10:39
標題錯誤,485只是一個硬件。具體什么協議,最好說清楚。我用485芯片做過的協議,最少20多種了
20多種協議???定制的?還是都是通用標準的哦
作者:
anzhidianzi
時間:
2021-7-29 14:20
真需要 研究一下
作者:
wlhhzg5
時間:
2021-8-21 13:27
學習中,感謝貢獻
作者:
雪玉寐影
時間:
2022-5-25 15:34
看代碼好像是modbus協議,接收和校驗了modbus指令,沒進行指令解析。
作者:
yxdz1358
時間:
2022-8-22 10:59
感謝樓主的分享,想學一下485通信有時間研究一下,只是如果有一點程序方面的說明就更好了。
作者:
hepen2002
時間:
2023-9-9 12:35
好東西必回貼
作者:
yupeng000
時間:
2023-9-13 18:58
好東西 一定要看看 研究一下
歡迎光臨 (http://m.zg4o1577.cn/bbs/)
Powered by Discuz! X3.1
主站蜘蛛池模板:
一级做a爱片性色毛片
|
亚洲偷
|
丨国产丨调教丨91丨
|
免费一区二区
|
在线免费观看黄色片
|
午夜久久久久久
|
精品久久久一区二区
|
亚洲区一区二
|
亚洲激情欧美激情
|
在线色综合
|
玖玖视频在线
|
亚洲免费黄色
|
欧美精品日韩少妇
|
男女啪啪网站
|
婷婷综合网
|
国产免费一级
|
91们嫩草伦理
|
a级片网站
|
三级a毛片
|
免费看a级片
|
中文字幕在线播放视频
|
黄色在线视频播放
|
精品国产成人
|
国产精品福利一区
|
三级黄网站
|
欧美福利在线观看
|
一级黄色录相
|
又黄又爽又色视频
|
久久久久久久久国产精品
|
国产伦精品一区二区三区视频黑人
|
久久综合影院
|
亚洲综合伊人
|
香蕉看片
|
成人免费网站
|
亚洲视频色
|
av免费在线观看网站
|
成人欧美视频
|
亚洲午夜天堂
|
黄色免费大片
|
国产99热
|
狠狠操狠狠操
|