?? modbus.c
字號:
//第一步成功,可以通訊,記住:P1.3 為0輸出485,為1輸入485
//撥特率正確,中斷正確
//串口1為儀表串口,串口2為實際MODBUS串口
//模擬量地址范圍0000----0008 共8個數(shù)據(jù),長度按前后減
#include <msp430x14x.h>
#define modbus_delay 10000 //讀繼電器
#define board_address 5 //讀繼電器
//rtu_number_long modbus通訊長度
//uart0_bb[] 通訊緩沖區(qū)
//串口定義
#define FORCEOFF_1 P4OUT |= BIT3; //forceoff is high
#define FORCEOFF_0 P4OUT &= ~BIT3;//forceoff is low
#define INVALID_IN P4DIR &= ~BIT1; //invalid is in
#define FORCEON_OUT P4DIR |= BIT2; //forceon is out
#define FORCEOFF_OUT P4DIR |= BIT3; //forceoff is out
#define EA_OUT P4DIR |= BIT0; //ea is out
#define FORCEON_0 P4OUT &= ~BIT2; //forceon is low
#define FORCEON_1 P4OUT |= BIT2; // forceon is high
#define FORCEOFF_0 P4OUT &= ~BIT3; // forceoff is low
#define FORCEOFF_1 P4OUT |= BIT3; // forceoff is high
#define EA_0 P4OUT &= ~BIT0; //ea is low
#define EA_1 P4OUT |= BIT0; //ea is high
#define TXD_0 P3OUT&=~BIT6;
#define TXD_1 P3OUT |=BIT6;
#define Flag_0 P1OUT&=~BIT4;
#define Flag_1 P1OUT|=BIT4;
//MODBUS功能碼
#define READ_COIL 01 //讀繼電器
#define READ_DI 02 //讀開關量
#define READ_HLD_REG 03 //讀保持器
#define READ_AI 04 //讀模擬量
#define PROTOCOL_EXCEPTION 0x81 //協(xié)議超出
#define PROTOCOL_ERR 1 //協(xié)議錯誤
#define FRM_ERR 2 //格式錯誤
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
} ;
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
};
//ASC碼轉(zhuǎn)換成16進制表
const unsigned char char_tab[128]=
{
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 0, 0, 0, 0, 0,
0, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
};
//16進制的ASC碼
const unsigned char tab_char[16]=
{
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'
};
//各個位
const unsigned int bit_tab[]=
{
BIT0, BIT1, BIT2, BIT3, BIT4, BIT5, BIT6, BIT7,
BIT8, BIT9, BITA, BITB, BITC, BITD, BITE, BITF
};
void Uart1Init(void);
char Data[6]="MSP430";
unsigned char uart1_aa[180]; //串口1接收緩沖區(qū)
unsigned char uart1_aa_temp[180]; //禎接收緩沖區(qū)
unsigned char uart0_bb[50]; //串口0接收緩沖區(qū)
unsigned char uart1_value[13]; //轉(zhuǎn)換后的值
unsigned char uart1_alert[13];
void timer_Init(void);
void value_rtu_cal(void);
void value_asc_cal(void);
unsigned short crc(unsigned char *puchMsg , unsigned short usDataLen);
void construct_rtu_frm ( unsigned char *dst_buf,unsigned char *src_buf,unsigned char lenth);
int rtu_read_coil_status ( unsigned char board_adr,int start_address,int lenth);
int rtu_read_input_status ( unsigned char board_adr,int start_address,int lenth);
int rtu_read_hldreg ( unsigned char board_adr,int start_address,int lenth);
int rtu_read_anloginput( unsigned char board_adr,int start_address,int lenth);
int rtu_data_anlys(unsigned char fr_lenth);
void rtu_out_active(unsigned char number);
unsigned char uart1_point,uart0_point; //兩個串口的輸入指針
unsigned char alert_status; //報警狀態(tài)
unsigned char com_out_aa[100]; //輸出緩沖區(qū)
unsigned char uart_receive_flag;
unsigned char modbus_flag;
unsigned char ascii_flag;
unsigned int rtu_number_long;
unsigned int alert_value_mid;
#pragma vector = TIMERA0_VECTOR
__interrupt void Timer_A (void)
{
rtu_number_long=uart0_point+1;
uart0_point=0; // Toggle P1.0
CCTL0 &= ~CCIE; //一旦定時中斷產(chǎn)生則停止定時中斷
TACTL |= TACLR;
CCR0 = modbus_delay;
modbus_flag=1; //一旦產(chǎn)生定時中斷就證明串口通訊完畢,MODBUS接受完成
}
//串口1初始化
void Uart0Init(void)
{
BCSCTL1 |= BIT6; //XTS=1 高速模式
BCSCTL2 |= 0xc0; //mclk=lfxt1clk
UCTL0&=~SWRST; //SWRST復位,USART允許SWRST=0X01;
UCTL0 |= CHAR; // 8-bit character
UCTL0 |= BIT5; // 8-bit character
UTCTL0 = SSEL0; // UCLK = ACLK
UBR00 = 0x00; // 32k/2400 - 13.65
UBR10 = 0x01; //
UMCTL0 = 0x00; // Modulation
ME1 |= UTXE0 + URXE0; // Enable USART0 TXD/RXD
IE1 |= URXIE0; // Enable USART0 RX interrupt
P3SEL |= 0x30; // P3.4,5 = USART0 TXD/RXD
P3DIR |= 0x10; // P3.4 output direction
_EINT(); // Enable interrupts
}
//儀表方接收子程序
#pragma vector = UART0RX_VECTOR
__interrupt void usart0_rx (void)
{
unsigned char temp;
CCTL0 = CCIE; //一旦有了串行中斷,開啟定時中斷
TACTL |= MC0;
CCR0 = modbus_delay;
TACTL |= TACLR; //定時中斷計數(shù)器清0
if(uart0_point>=49) return;
while ((IFG1 & UTXIFG0) == 0); // USART0 TX buffer ready?
temp = RXBUF0; // RXBUF0 to TXBUF0
uart0_bb[uart0_point] = temp;
uart0_point=uart0_point+1;
}
#pragma vector = UART1RX_VECTOR
__interrupt void usart1_rx (void)
{
unsigned char temp;
while ((IFG2 & UTXIFG1) == 0); // USART1 TX buffer ready?
temp=RXBUF1;
if(temp=='@')
{
uart1_point=0;
}
if(temp=='&') ascii_flag=1;
uart1_aa_temp[uart1_point] = temp;
uart1_point=uart1_point+1;
}
//主功能函數(shù)
void main(void)//out put a strings
{
unsigned char i=0;
WDTCTL=WDTPW+WDTHOLD;
P1DIR |= 0xff; //設置P1方向為向外
P1OUT = 0xff; // P1.0 與自身異或
uart0_point=0;
uart1_point=0;
Uart0Init();
Uart1Init();
timer_Init();
ascii_flag=0;
CCTL0 &= ~CCIE;
while(1)
{
modbus_flag=0;
while(modbus_flag==0)
{
if(ascii_flag==1)
{
for(i=0;i<=180;i++)
{
uart1_aa[i]=uart1_aa_temp[i];
}
value_rtu_cal();
}
ascii_flag = 0;
}
rtu_data_anlys(rtu_number_long);
}
}
//串口1初始化
void Uart1Init(void)
{
INVALID_IN; //P4.1 is in ,invalid
FORCEON_OUT; // P4.2 is out ,forceon
FORCEOFF_OUT; // P4.3 is out ,forceoff
EA_OUT; // P4.0 is out ,ea
FORCEON_0; //P4.2 is low forceon
FORCEOFF_1; //P4.3 is low forceoff
EA_0; // P4.0 ,EA is low
BCSCTL1 |= BIT6; //XTS=1 高速模式
BCSCTL2 |= 0xc0; //mclk=lfxt1clk
UCTL1&=~SWRST; //SWRST復位,USART允許SWRST=0X01;
UCTL1=CHAR; //8位數(shù)據(jù)位,1位停止位,無校驗
UTCTL1 = SSEL0; //選定ACLK(2.4576MHZ)為時鐘源
UBR01=0x00;
UBR11=0x01; //使用2.4576MHZ晶振,波特率9600bps
UMCTL1=0x00; //位調(diào)整
ME2|=UTXE1+URXE1; //UART發(fā)送接收模塊允許
IE2|=URXIE1; //設置發(fā)送中斷
P3SEL |=0xc0; //P3.6由USART1發(fā)送模塊占用
P3DIR |=0x40; //P3.6輸出
// IE2|=URXIE1; //+UTXIE1;//發(fā)送接收中斷允許
}
void value_rtu_cal(void)
{
uart1_value[0]=char_tab[uart1_aa[11]]*100+char_tab[uart1_aa[13]]*10+char_tab[uart1_aa[14]];
uart1_value[1]=char_tab[uart1_aa[20]]*100+char_tab[uart1_aa[22]]*10+char_tab[uart1_aa[23]];
uart1_value[2]=char_tab[uart1_aa[29]]*100+char_tab[uart1_aa[31]]*10+char_tab[uart1_aa[32]];
uart1_value[3]=char_tab[uart1_aa[38]]*100+char_tab[uart1_aa[40]]*10+char_tab[uart1_aa[41]];
uart1_value[4]=char_tab[uart1_aa[47]]*100+char_tab[uart1_aa[49]]*10+char_tab[uart1_aa[50]];
uart1_value[5]=char_tab[uart1_aa[56]]*100+char_tab[uart1_aa[58]]*10+char_tab[uart1_aa[59]];
uart1_value[6]=char_tab[uart1_aa[65]]*100+char_tab[uart1_aa[67]]*10+char_tab[uart1_aa[68]];
uart1_value[7]=char_tab[uart1_aa[74]]*100+char_tab[uart1_aa[76]]*10+char_tab[uart1_aa[77]];
uart1_value[8]=char_tab[uart1_aa[83]]*100+char_tab[uart1_aa[85]]*10+char_tab[uart1_aa[86]];
uart1_value[9]=char_tab[uart1_aa[92]]*100+char_tab[uart1_aa[94]]*10+char_tab[uart1_aa[95]];
uart1_value[10]=char_tab[uart1_aa[101]]*100+char_tab[uart1_aa[103]]*10+char_tab[uart1_aa[104]];
uart1_value[11]=char_tab[uart1_aa[110]]*100+char_tab[uart1_aa[112]]*10+char_tab[uart1_aa[113]];
alert_value_mid=0;
if(uart1_aa[173]==0x31) alert_value_mid=alert_value_mid+1;
alert_value_mid=alert_value_mid<<1;
if(uart1_aa[168]==0x31) alert_value_mid=alert_value_mid+1;
alert_value_mid=alert_value_mid<<1;
if(uart1_aa[163]==0x31) alert_value_mid=alert_value_mid+1;
alert_value_mid=alert_value_mid<<1;
if(uart1_aa[158]==0x31) alert_value_mid=alert_value_mid+1;
alert_value_mid=alert_value_mid<<1;
if(uart1_aa[153]==0x31) alert_value_mid=alert_value_mid+1;
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -