?? modbus.c
字號:
alert_value_mid=alert_value_mid<<1;
if(uart1_aa[148]==0x31) alert_value_mid=alert_value_mid+1;
alert_value_mid=alert_value_mid<<1;
if(uart1_aa[143]==0x31) alert_value_mid=alert_value_mid+1;
alert_value_mid=alert_value_mid<<1;
if(uart1_aa[138]==0x31) alert_value_mid=alert_value_mid+1;
alert_value_mid=alert_value_mid<<1;
if(uart1_aa[133]==0x31) alert_value_mid=alert_value_mid+1;
alert_value_mid=alert_value_mid<<1;
if(uart1_aa[128]==0x31) alert_value_mid=alert_value_mid+1;
alert_value_mid=alert_value_mid<<1;
if(uart1_aa[123]==0x31) alert_value_mid=alert_value_mid+1;
alert_value_mid=alert_value_mid<<1;
if(uart1_aa[118]==0x31) alert_value_mid=alert_value_mid+1;
alert_value_mid=alert_value_mid<<1;
}
//CRC校驗(yàn)子函數(shù),入口:數(shù)據(jù)指針+數(shù)據(jù)段長度
unsigned short crc(unsigned char *puchMsg , unsigned short usDataLen)
{
unsigned char uchCRCHi = 0xFF ; /* 高CRC初始化*/
unsigned char uchCRCLo = 0xFF ; /* 低CRC初始化*/
unsigned uIndex ; /* 用來查表 */
while (usDataLen--) /* 整個(gè)數(shù)據(jù)緩沖區(qū),不帶數(shù)據(jù)的CRC兩個(gè)字節(jié) */
{
uIndex = uchCRCHi ^ *puchMsg++ ; /* calculate the CRC */
uchCRCHi = uchCRCLo ^ auchCRCHi[uIndex];
uchCRCLo = auchCRCLo[uIndex] ;
}
return (uchCRCHi << 8 | uchCRCLo) ;
}
//RTU格式化輸出
//入口:本地址緩沖區(qū)+原來數(shù)據(jù)地址緩沖區(qū)+數(shù)據(jù)段長度
void construct_rtu_frm ( unsigned char *dst_buf,unsigned char *src_buf,unsigned char lenth)
{
unsigned short crc_tmp;
crc_tmp = crc(src_buf, lenth); //原地址加數(shù)據(jù)段做CRC計(jì)算
*(src_buf+lenth) = crc_tmp >> 8 ; //把CRC高位防置在隨后的地址
*(src_buf+lenth+1) = crc_tmp & 0xff; //放CRC低位
lenth++; //把數(shù)據(jù)指針指向最后
lenth++;
while ( lenth--) //搬動(dòng)整個(gè)緩沖區(qū)到發(fā)送緩沖區(qū)
{
*dst_buf = *src_buf;
dst_buf++;
src_buf++;
}
}
//讀繼電器狀態(tài)響應(yīng)
//讀的格式為:板本機(jī)地址 讀功能碼 讀的高位地址 讀的低位地址 字節(jié)長度高 字節(jié)長度低 CRC校驗(yàn),共8個(gè)字節(jié)
//響應(yīng)格式為:本機(jī)地址 功能碼 有效數(shù)據(jù)長度 開關(guān)位8位數(shù)據(jù) CRC校驗(yàn)碼
int rtu_read_coil_status ( unsigned char board_adr,int start_address,int lenth)
{
unsigned char tmp[100], tmp_lenth;
unsigned int temp_start;
unsigned char temp1,temp2;
tmp_lenth = lenth;
temp_start = start_address;
if(tmp_lenth<=8)
{
tmp[2]=1;
}
else
{
tmp[2]=2;
}
alert_value_mid=alert_value_mid>>temp_start;
tmp[0] = board_adr;
tmp[1] = READ_COIL;
temp1= alert_value_mid/256;
temp2= alert_value_mid;
if(tmp[2]==1)
{
tmp[3] = temp2; //給出實(shí)際的數(shù)據(jù)1個(gè)字節(jié),可代表8個(gè)繼電器
tmp_lenth = 4;
}
else
{
tmp[3] = temp1; //給出實(shí)際的數(shù)據(jù)1個(gè)字節(jié),可代表8個(gè)繼電器
tmp[4] = temp2;
tmp_lenth = 5;
}
construct_rtu_frm (com_out_aa, tmp, tmp_lenth);
return (tmp_lenth+2);
}
//讀取數(shù)據(jù)輸入狀態(tài)狀態(tài)
int rtu_read_input_status ( unsigned char board_adr,int start_address,int lenth)
{
unsigned char tmp[100], tmp_lenth;
unsigned int temp_start;
unsigned char temp1,temp2;
tmp_lenth = lenth;
temp_start = start_address;
if(tmp_lenth<=8)
{
tmp[2]=1;
}
else
{
tmp[2]=2;
}
alert_value_mid=alert_value_mid>>temp_start;
tmp[0] = board_adr;
tmp[1] = READ_COIL;
temp1= alert_value_mid/256;
temp2= alert_value_mid;
if(tmp[2]==1)
{
tmp[3] = temp2; //給出實(shí)際的數(shù)據(jù)1個(gè)字節(jié),可代表8個(gè)繼電器
tmp_lenth = 4;
}
else
{
tmp[3] = temp1; //給出實(shí)際的數(shù)據(jù)1個(gè)字節(jié),可代表8個(gè)繼電器
tmp[4] = temp2;
tmp_lenth = 5;
}
construct_rtu_frm (com_out_aa, tmp, tmp_lenth);
return (tmp_lenth+2);
}
//讀取采樣保持器
//讀格式:本機(jī)地址+功能碼+讀高位地址+讀地位地址+數(shù)據(jù)段長度高位+數(shù)據(jù)段長度低位+CRC校驗(yàn)碼
//返回格式:本機(jī)地址+功能碼+有效數(shù)據(jù)長度 +數(shù)據(jù)1+數(shù)據(jù)2+++++++
int rtu_read_hldreg ( unsigned char board_adr,int start_address,int lenth)
{
unsigned char tmp[100], tmp_lenth;
unsigned char i,j,k;
unsigned int temp;
tmp_lenth=lenth;
tmp[0] = board_adr;
tmp[1] = READ_HLD_REG;
tmp[2] = tmp_lenth;
j=start_address;
k=2;
for(i=j;i<tmp_lenth;i++)
{
temp=uart1_value[i];
k++;
tmp[k] = temp >> 8 ;
k++;
tmp[k] = uart1_value[i];
}
tmp_lenth = k+1;
construct_rtu_frm (com_out_aa, tmp, tmp_lenth);
return (tmp_lenth+2);
}
//讀取采樣保持器
//讀格式:本機(jī)地址+功能碼+讀高位地址+讀地位地址+數(shù)據(jù)段長度高位+數(shù)據(jù)段長度低位+CRC校驗(yàn)碼
//返回格式:本機(jī)地址+功能碼++有效數(shù)據(jù)長度+數(shù)據(jù)1+數(shù)據(jù)2+++++++
int rtu_read_anloginput( unsigned char board_adr,int start_address,int lenth)
{
unsigned char tmp[100], tmp_lenth;
unsigned char i,j,k;
unsigned int temp;
tmp_lenth=lenth;
tmp[0] = board_adr;
tmp[1] = READ_HLD_REG;
tmp[2] = tmp_lenth;
j=start_address;
k=2;
for(i=j;i<tmp_lenth;i++)
{
temp=uart1_value[i];
k++;
tmp[k] = temp >> 8 ;
k++;
tmp[k] = uart1_value[i];
}
tmp_lenth = k+1;
construct_rtu_frm (com_out_aa, tmp, tmp_lenth);
return (tmp_lenth+2);
}
//RTU數(shù)據(jù)分析
//入口,接收緩沖區(qū)的大小,長度
int rtu_data_anlys(unsigned char fr_lenth)
{
unsigned short crc_result, crc_tmp;
unsigned char tmp1;
unsigned int tmp2,tmp3,tmp4;
unsigned char *source_p;
unsigned char temp;
source_p = uart0_bb;
temp = *source_p;
if(board_address!=temp) return;
crc_tmp = *(source_p + rtu_number_long-2); // 由接收緩沖區(qū)計(jì)算出 crc 第一字節(jié)
crc_tmp = crc_tmp * 256 + *( source_p+rtu_number_long-1); // 得到實(shí)際 CRC 值
crc_result = crc(source_p, fr_lenth-2); // 計(jì)算 CRC 值
if ( crc_tmp != crc_result ) // 對比 CRC 校驗(yàn)正確
{
return -1;
}
source_p=uart1_aa;
tmp1=*source_p;
tmp3=(*(source_p+2)*256)+*(source_p+3);
tmp4=(*(source_p+4)*256)+*(source_p+5);
switch ( *(source_p+1) ) // 功能碼
{
case READ_COIL: /*讀取繼電器狀態(tài) */
tmp2=rtu_read_coil_status (tmp1,tmp3,tmp4);
rtu_out_active(tmp2);
break;
case READ_DI: /*讀取開關(guān)量輸入*/
tmp2=rtu_read_input_status(tmp1,tmp3,tmp4);
rtu_out_active(tmp2);
break;
case READ_HLD_REG: /*讀取保持寄存器*/
tmp2=rtu_read_hldreg(tmp1,tmp3,tmp4);
rtu_out_active(tmp2);
break ;
case READ_AI: /*讀取模擬量輸入*/
tmp2=rtu_read_anloginput (tmp1,tmp3,tmp4);
rtu_out_active(tmp2);
break;
case PROTOCOL_EXCEPTION:
return -1*PROTOCOL_ERR;
default:
return -1*PROTOCOL_ERR;
}
return 0;
}
void rtu_out_active(unsigned char number)
{
unsigned char i;
P1OUT = 0; // P1.0 與自身異或
for(i=0;i<number;i++)
{
TXBUF0 = com_out_aa[i];
while((UTCTL0&0x01)==0);
}
P1OUT = 0xff; // P1.0 與自身異或
}
void timer_Init(void)
{
WDTCTL = WDTPW + WDTHOLD; // Stop WDT
BCSCTL1 |= BIT6; //XTS=1 高速模式
TACTL = TASSEL0 + TACLR; // SMCLK, clear TAR
CCTL0 = CCIE; // CCR0 interrupt enabled
CCR0 = modbus_delay;
P1DIR |= 0xff; // P1.0 output
TACTL |= MC0; // Start Timer_A in continuous mode
_EINT(); // Enable interrupts
}
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -