|
近段时间,在做一个类似PLC的控制器.控制器的通讯口做成MODBUS ASCII的从站,基本完成.个人觉得程序较长,贴出来请大家指点.
先定义PLC软元件
unsigned char s[8],x[8],y[8],t_in[4],t_out[4],c_in[4],c_out[4],m[32],sm[16];
signed int t_value[32],c_value[32],d[128],sd[32];
软元件对应通讯地址
元件 地址范围 数量
S 00-3F 64
X 400-43F 64
Y 500-53F 64
t_out 600-61F 32
t_value 600-61F 32
M 800-81F 256
SM BE8-C67 128
c_out E00-E17 32
c_value E00-E17 32
D 1000-107F 128
SD 13E8-1407 32
USART的初始化
#define RXB8 1
#define TXB8 0
#define UPE 2
#define OVR 3
#define FE 4
#define UDRE 5
#define RXC 7
#define FRAMING_ERROR (1<<FE)
#define PARITY_ERROR (1<<UPE)
#define DATA_OVERRUN (1<<OVR)
#define DATA_REGISTER_EMPTY (1<<UDRE)
#define RX_COMPLETE (1<<RXC)
//usart 读初始化
void usart0_rxd_initial(void)
{
TXD0_DISABLE;
RXD0_ENABLE;
UCSR0B = 0xD0;
}
//usart 写初始化
void usart0_txd_initial(void)
{
RXD0_DISABLE;
TXD0_ENABLE;
UCSR0B = 0xC8;
}
//usart初始化
void usart0_com_initial(void)
{
// USART initialization
// Communication Parameters: 7 Data, 1 Stop, Even Parity
// USART Receiver: Off
// USART Transmitter: Off
// USART0 Mode: Asynchronous
// USART Baud Rate: 9600
UCSR0A=0x00;
UCSR0B=0xC0;
UCSR0C=0x24;
UBRR0H=0x00;
UBRR0L=0x2F;
TXD0_DISABLE;
RXD0_DISABLE;
}
// USART 接收处理
#define USART0_COM_BUFFER_SIZE0 64
char usart0_com_buffer0[USART0_COM_BUFFER_SIZE0]; //通讯缓冲区
unsigned char usart0_com_counter0 = 0x0;
unsigned char err_code=0x0;
bit usart0_rxd_complete0 = 0;//接收完成标志
// USART Receiver interrupt service routine
interrupt [USART_RXC] void usart_rx_isr(void)
{
char status,data;
status=UCSR0A;
data=UDR0;
if ((status & (FRAMING_ERROR | PARITY_ERROR | DATA_OVERRUN))==0)
{
if((data == 0x3a)||(usart0_com_counter0 >= 64)) usart0_com_counter0 = 0;
if(usart0_com_counter0 == 0)
{
if(data == 0x3a)
{
usart0_com_buffer0[0] = data;
usart0_com_counter0 = 1;
}
}
else
{
usart0_com_buffer0[usart0_com_counter0] = data;
usart0_com_counter0++;
if(data == 0x0a)
{
if(usart0_com_counter0 < 17)
usart0_com_counter0 = 0;
else
{
usart0_com_initial();
usart0_rxd_complete0 = 1;
}
}
}
};
}
//USART 发送处理
unsigned char usart0_txd_index0 = 0x0;
bit usart0_txd_transmiting0 = 0;//发送中标志
// USART Transmitter interrupt service routine
interrupt [USART_TXC] void usart_tx_isr(void)
{
if (usart0_txd_index0 < usart0_com_counter0)
{
UDR0 = usart0_com_buffer0[usart0_txd_index0];
usart0_txd_index0++;
}
else
{
usart0_txd_transmiting0 = 0;
usart0_rxd_complete0 = 0;
usart0_rxd_initial();
}
}
//ASCII 转 CHAR
unsigned char ascii2char(char *a)
{
unsigned char result;
if(*a <= 0x39)
result = (*a-0x30)<<4;
else
result = (*a-0x37)<<4;
a++;
if(*a <= 0x39)
result |= (*a-0x30);
else
result |= (*a-0x37);
return result;
}
//ASCII 转 UNSIGNED INT
unsigned int ascii2uint(char *b)
{
unsigned int result;
result = ascii2char(b);
result <<= 8;
result |= ascii2char(b+2);
return result;
}
//CHAR 转 ASCII
void char2ascii(unsigned char a,char *p)
{
unsigned char temp;
temp = a >>4;
if(temp <= 0x09)
*p = temp + 0x30;
else
*p = temp + 0x37;
temp = a & 0x0f;
if(temp <= 0x09)
*(p+1) = temp + 0x30;
else
*(p+1) = temp + 0x37;
}
//UNSIGNED INT 转 ASCII
void uint2ascii(unsigned int a,char *p)
{
unsigned char temp;
temp = a >> 8;
char2ascii(temp,p);
temp = a;
char2ascii(temp,p+2);
}
//位读取
unsigned char bit_read(unsigned char charbyte,unsigned char bitn)
{
return (charbyte & (1 << bitn));
}
//位设置
void bit_set(unsigned char *chardata,unsigned char bitn)
{
*chardata |= 1 << bitn;
}
//位复零
void bit_reset(unsigned char *chardata,unsigned char bitn)
{
*chardata &= ~(1 << bitn);
}
//位预置
void bit_preset(unsigned char *chardata,unsigned char bitn,unsigned char a)
{
if(a)
*chardata |= 1 << bitn;
else
*chardata &= ~(1 << bitn);
}
//通讯错误处理
void modbus_s_err0(unsigned char func_code,unsigned char err)
{
unsigned char *p1;
unsigned char lrc_code;
p1 = usart0_com_buffer0;
*p1 = 0x3a;
p1++;
lrc_code = LOCAL_ADDRESS;
char2ascii(LOCAL_ADDRESS,p1);
p1 += 2;
lrc_code += func_code;
char2ascii(func_code,p1);
p1 += 2;
lrc_code += err;
char2ascii(err,p1);
p1 += 2;
lrc_code = 0xff-lrc_code+1;
char2ascii(lrc_code,p1);
p1 += 2;
*p1 = 0x0d;
p1++;
*p1 = 0x0a;
p1++;
usart0_com_counter0 = p1 - usart0_com_buffer0;
err_code = 0x00;
}
//MODBUS 01 02功能码处理
void modbus_s_func0102(unsigned char func_code,unsigned char *point,unsigned char bitn,unsigned int bit_lenth)
{
unsigned char *p1;
unsigned char bytes,lrc_code,data;
p1 = usart0_com_buffer0;
*p1 = 0x3a;
p1++;
lrc_code = LOCAL_ADDRESS;
char2ascii(LOCAL_ADDRESS,p1);
p1 += 2;
lrc_code += func_code;
char2ascii(func_code,p1);
p1 += 2;
bytes = bit_lenth >> 3;
if(bit_lenth % 8) bytes++;
lrc_code += bytes;
char2ascii(bytes,p1);
p1 += 2;
while(bytes)
{
if(bitn)
{
data = ((*point) >> bitn) + ((*(point + 1)) << (0x08 - bitn));
}
else
{
data = *point;
}
lrc_code += data;
char2ascii(data,p1);
bytes--;
point++;
p1 += 2;
};
lrc_code = 0xff - lrc_code;
lrc_code++;
char2ascii(lrc_code,p1);
p1 += 2;
*p1 = 0x0d;
p1++;
*p1 = 0x0a;
p1++;
usart0_com_counter0 = p1 - usart0_com_buffer0;
}
//MODBUS 03功能码处理
void modbus_s_func03(unsigned int *point,unsigned int datal)
{
unsigned char *p1;
unsigned char bytes,lrc_code;
p1 = usart0_com_buffer0;
*p1 = 0x3a;
p1++;
lrc_code = LOCAL_ADDRESS;
char2ascii(LOCAL_ADDRESS,p1);
p1 += 2;
lrc_code += 0x03;
char2ascii(0x03,p1);
p1 += 2;
bytes = datal << 1;
lrc_code += bytes;
char2ascii(bytes,p1);
p1 += 2;
while(datal)
{
uint2ascii(*point,p1);
lrc_code += ascii2char(p1);
p1 += 2;
lrc_code += ascii2char(p1);
p1 += 2;
point++;
datal--;
};
lrc_code = 0xff - lrc_code;
lrc_code++;
char2ascii(lrc_code,p1);
p1 += 2;
*p1 = 0x0d;
p1++;
*p1 = 0x0a;
p1++;
usart0_com_counter0 = p1 - usart0_com_buffer0;
}
//MODBUS 05功能码处理
void modbus_s_func05(unsigned char *point,unsigned char bitn,unsigned int bitx)
{
if(bitx==0xff00)
{
*point |= 1<<bitn;
}
else
{
*point &= ~(1<<bitn);
}
}
//MODBUS 06功能码处理
void modbus_s_func06(unsigned int *point,unsigned int datad)
{
*point = datad;
}
//MODBUS 0F功能码处理
void modbus_s_func0f(unsigned char *point,unsigned int rel,unsigned int bitl)
{
unsigned char _bitx,_bitn,x0;
unsigned char *p1;
unsigned char temp;
p1 = usart0_com_buffer0 + 15;
for(x0 = 0x0;x0 < bitl;x0++)
{
_bitx = (rel + x0) >> 3;
_bitn = (rel + x0) % 8;
bit_preset(point + _bitx,_bitn,bit_read(ascii2char(p1+((x0>>3)<<1)),x0 % 8));
}
p1 = usart0_com_buffer0;
temp = ascii2char(p1+1) + ascii2char(p1+3) + ascii2char(p1+5) + ascii2char(p1+7) + ascii2char(p1+9) + ascii2char(p1+11) - 1;
temp =0xff - temp;
p1 += 13;
char2ascii(temp,p1);
p1 += 2;
*p1 = 0x0d;
p1++;
*p1 = 0x0a;
usart0_com_counter0 = 17;
}
//MODBUS 10功能码处理
void modbus_s_func10(unsigned int *point,unsigned int datal)
{
unsigned char *p1,temp;
p1 = usart0_com_buffer0 + 15;
while(datal)
{
*point = ascii2uint(p1);
point++;
p1 += 4;
datal--;
};
p1 = usart0_com_buffer0;
temp = ascii2char(p1+1) + ascii2char(p1+3) + ascii2char(p1+5) + ascii2char(p1+7) + ascii2char(p1+9) + ascii2char(p1+11) - 1;
temp =0xff - temp;
p1 += 13;
char2ascii(temp,p1);
p1 += 2;
*p1 = 0x0d;
p1++;
*p1 = 0x0a;
usart0_com_counter0 = 17;
}
//MODBUS 接收完毕处理,接收信息分析
void usart0_com_s_rxdcomplete0 (void)
{
unsigned char lrc_check_code=0x0,rel,com_command;
unsigned int reg_address,data_lenth,temp;
unsigned char *p;
p = usart0_com_buffer0;
if(ascii2char((p+1)) == LOCAL_ADDRESS)
{
rel = 1;
com_command = usart0_com_counter0 - 3;
while(rel < com_command)
{
lrc_check_code += (ascii2char(p+rel));
rel += 2;
};
if(lrc_check_code == 0x0)
{
com_command = ascii2char(p+3);
reg_address = ascii2uint(p+5);
data_lenth = ascii2uint(p+9);
switch(com_command)
{
case 0x01:
{
if((reg_address >= 0x00) && (reg_address <= 0x3f))
{
if((reg_address + data_lenth) > 0x40) data_lenth = 0x40 - reg_address;
modbus_s_func0102(0x01,s + (reg_address>>3),reg_address % 8,data_lenth);
}
//else if((reg_address >= 0x400) && (reg_address <= 0x43f))
// {
// }
else if((reg_address >= 0x500) && (reg_address <= 0x53f))
{
temp = reg_address - 0x500;
if((reg_address + data_lenth) > 0x540) data_lenth = 0x540 - reg_address;
modbus_s_func0102(0x01,y + (temp>>3),temp % 8,data_lenth);
}
else if((reg_address >= 0x600) && (reg_address <= 0x61f))
{
temp = reg_address - 0x600;
if((reg_address + data_lenth) > 0x620) data_lenth = 0x620 - reg_address;
modbus_s_func0102(0x01,t_out + (temp>>3),temp % 8,data_lenth);
}
else if((reg_address >= 0x800) && (reg_address <= 0x8ff))
{
temp = reg_address - 0x800;
if((reg_address + data_lenth) > 0x900) data_lenth = 0x900 - reg_address;
modbus_s_func0102(0x01,m + (temp>>3),temp % 8,data_lenth);
}
else if((reg_address >= 0xbe8) && (reg_address <= 0xc67))
{
temp = reg_address - 0xbe8;
if((reg_address + data_lenth) > 0xc68) data_lenth = 0xc68 - reg_address;
modbus_s_func0102(0x01,sm + (temp>>3),temp % 8,data_lenth);
}
else if((reg_address >= 0xe00) && (reg_address <= 0xe1f))
{
temp = reg_address - 0xe00;
if((reg_address + data_lenth) > 0xe20) data_lenth = 0xe20 - reg_address;
modbus_s_func0102(0x01,c_out + (temp>>3),temp % 8,data_lenth);
}
else
{
err_code = 0x02;
}
break;
}
case 0x02:
{
if((reg_address >= 0x00) && (reg_address <= 0x3f))
{
if((reg_address + data_lenth) > 0x40) data_lenth = 0x40 - reg_address;
modbus_s_func0102(0x02,s + (reg_address>>3),reg_address % 8,data_lenth);
}
else if((reg_address >= 0x400) && (reg_address <= 0x43f))
{
temp = reg_address - 0x400;
if((reg_address + data_lenth) > 0x440) data_lenth = 0x440 - reg_address;
modbus_s_func0102(0x02,x + (temp>>3),temp % 8,data_lenth);
}
else if((reg_address >= 0x500) && (reg_address <= 0x53f))
{
temp = reg_address - 0x500;
if((reg_address + data_lenth) > 0x540) data_lenth = 0x540 - reg_address;
modbus_s_func0102(0x02,y + (temp>>3),temp % 8,data_lenth);
}
else if((reg_address >= 0x600) && (reg_address <= 0x61f))
{
temp = reg_address - 0x600;
if((reg_address + data_lenth) > 0x620) data_lenth = 0x620 - reg_address;
modbus_s_func0102(0x02,t_out + (temp>>3),temp % 8,data_lenth);
}
else if((reg_address >= 0x800) && (reg_address <= 0x8ff))
{
temp = reg_address - 0x800;
if((reg_address + data_lenth) > 0x900) data_lenth = 0x900 - reg_address;
modbus_s_func0102(0x02,m + (temp>>3),temp % 8,data_lenth);
}
else if((reg_address >= 0xbe8) && (reg_address <= 0xc67))
{
temp = reg_address - 0xbe8;
if((reg_address + data_lenth) > 0xc68) data_lenth = 0xc68 - reg_address;
modbus_s_func0102(0x02,sm + (temp>>3),temp % 8,data_lenth);
}
else if((reg_address >= 0xe00) && (reg_address <= 0xe1f))
{
temp = reg_address - 0xe00;
if((reg_address + data_lenth) > 0xe20) data_lenth = 0xe20 - reg_address;
modbus_s_func0102(0x02,c_out + (temp>>3),temp % 8,data_lenth);
}
else
{
err_code = 0x02;
}
break;
}
case 0x03:
{
if((reg_address >= 0x600) && (reg_address <= 0x061f))
{
if((reg_address + data_lenth) > 0x0620) data_lenth = 0x0620 - reg_address;
if(data_lenth > 8) data_lenth = 0x08;
modbus_s_func03(t_value+(reg_address-0x600),data_lenth);
}
else if((reg_address >= 0xe00) && (reg_address <= 0xe1f))
{
if((reg_address + data_lenth) > 0x0e20) data_lenth = 0x0e20 - reg_address;
if(data_lenth > 8) data_lenth = 0x08;
modbus_s_func03(c_value+(reg_address-0xe00),data_lenth);
}
else if((reg_address >= 0x1000) && (reg_address <= 0x107f))
{
if((reg_address + data_lenth) > 0x01100) data_lenth = 0x01100 - reg_address;
if(data_lenth > 8) data_lenth = 0x08;
modbus_s_func03(d+(reg_address-0x1000),data_lenth);
}
else if((reg_address >= 0x13e8) && (reg_address <= 0x1407))
{
if((reg_address + data_lenth) > 0x1408) data_lenth = 0x1408 - reg_address;
if(data_lenth > 8) data_lenth = 0x08;
modbus_s_func03(sd+(reg_address-0x13e8),data_lenth);
}
else
{
err_code = 0x02;
}
break;
}
case 0x05:
{
if((reg_address >= 0x00) && (reg_address <= 0x3f))
{
modbus_s_func05(s + (reg_address >> 3),reg_address % 8,data_lenth);
}
//else if((reg_address >= 0x400) && (reg_address <= 0x43f))
// {
// }
else if((reg_address >= 0x500) && (reg_address <= 0x53f))
{
modbus_s_func05(y + ((reg_address-0x500)>>3),(reg_address-0x500) % 8,data_lenth);
}
else if((reg_address >= 0x600) && (reg_address <= 0x61f))
{
if(data_lenth != 0xff00) t_value[reg_address - 0x600] = 0x0;
modbus_s_func05(t_out + ((reg_address-0x600)>>3),(reg_address-0x600) % 8,data_lenth);
}
else if((reg_address >= 0x800) && (reg_address <= 0x8ff))
{
modbus_s_func05(m + ((reg_address-0x800)>>3),(reg_address-0x800) % 8,data_lenth);
}
else if((reg_address >= 0xbe8) && (reg_address <= 0xc67))
{
modbus_s_func05(sm + ((reg_address-0xbe8)>>3),(reg_address-0xbe8) % 8,data_lenth);
}
else if((reg_address >= 0xe00) && (reg_address <= 0xe1f))
{
if(data_lenth != 0xff00) c_value[reg_address - 0xe00] = 0x0;
modbus_s_func05(c_out + ((reg_address-0xe00)>>3),(reg_address-0xe00) % 8,data_lenth);
}
else
{
err_code = 0x02;
}
break;
}
case 0x06:
{
if((reg_address >= 0x600) && (reg_address <= 0x061f))
{
modbus_s_func06(t_value+(reg_address-0x600),data_lenth);
}
else if((reg_address >= 0xe00) && (reg_address <= 0xe1f))
{
modbus_s_func06(c_value+(reg_address-0xe00),data_lenth);
}
else if((reg_address >= 0x1000) && (reg_address <= 0x107f))
{
modbus_s_func06(d+(reg_address-0x1000),data_lenth);
}
else if((reg_address >= 0x13e8) && (reg_address <= 0x1407))
{
modbus_s_func06(sd+(reg_address-0x13e8),data_lenth);
}
else
{
err_code = 0x02;
}
break;
}
case 0x0f:
{
if((reg_address >= 0x00) && (reg_address <= 0x3f))
{
if((reg_address + data_lenth) > 0x40)
{
err_code = 0x03;
}
else
{
modbus_s_func0f(s,reg_address,data_lenth);
}
}
//else if((reg_address >= 0x400) && (reg_address <= 0x43f))
// {
// }
else if((reg_address >= 0x500) && (reg_address <= 0x53f))
{
if((reg_address + data_lenth) > 0x540)
{
err_code = 0x03;
}
else
{
modbus_s_func0f(y,reg_address-0x500,data_lenth);
}
}
else if((reg_address >= 0x600) && (reg_address <= 0x61f))
{
if((reg_address + data_lenth) > 0x620)
{
err_code = 0x03;
}
else
{
modbus_s_func0f(t_out,reg_address-0x600,data_lenth);
}
}
else if((reg_address >= 0x800) && (reg_address <= 0x8ff))
{
if((reg_address + data_lenth) > 0x900)
{
err_code = 0x03;
}
else
{
modbus_s_func0f(m,reg_address-0x800,data_lenth);
}
}
else if((reg_address >= 0xbe8) && (reg_address <= 0xc67))
{
if((reg_address + data_lenth) > 0xc68)
{
err_code = 0x03;
}
else
{
modbus_s_func0f(sm,reg_address-0xbe8,data_lenth);
}
}
else if((reg_address >= 0xe00) && (reg_address <= 0xe1f))
{
if((reg_address + data_lenth) > 0xe20)
{
err_code = 0x03;
}
else
{
modbus_s_func0f(c_out,reg_address-0xe00,data_lenth);
}
}
else
{
err_code = 0x02;
}
break;
}
case 0x10:
{
if((reg_address >= 0x600) && (reg_address <= 0x061f))
{
if((reg_address + data_lenth) > 0x0620)
{
err_code = 0x04;
}
else
{
modbus_s_func10(t_value+(reg_address-0x600),data_lenth);
}
}
else if((reg_address >= 0xe00) && (reg_address <= 0xe1f))
{
if((reg_address + data_lenth) > 0x0e20)
{
err_code = 0x04;
}
else
{
modbus_s_func10(c_value+(reg_address-0xe00),data_lenth);
}
}
else if((reg_address >= 0x1000) && (reg_address <= 0x107f))
{
if((reg_address + data_lenth) > 0x01100)
{
err_code = 0x04;
}
else
{
modbus_s_func10(d+(reg_address-0x1000),data_lenth);
}
}
else if((reg_address >= 0x13e8) && (reg_address <= 0x1407))
{
if((reg_address + data_lenth) > 0x1408)
{
err_code = 0x04;
}
else
{
modbus_s_func10(sd+(reg_address-0x13e8),data_lenth);
}
}
else
{
err_code = 0x02;
}
break;
}
default:
{
err_code = 0x01;
}
}
if(err_code) modbus_s_err0(com_command,err_code);
usart0_txd_initial();
usart0_txd_transmiting0 = 1;
while(!(UCSR0A & DATA_REGISTER_EMPTY));
UDR0 = usart0_com_buffer0[0];
usart0_txd_index0 = 1;
}
else
{
usart0_rxd_complete0 = 0;
usart0_rxd_initial();
}
}
else
{
usart0_rxd_complete0 = 0;
usart0_rxd_initial();
}
}
//以下是控制器通讯部分程序
void main(void)
{
usart0_com_initial();
usart0_rxd_initial();
while(1)
{
//有通讯完成标志,
if((!usart0_txd_transmiting0) && usart0_rxd_complete0)
{
usart0_com_s_rxdcomplete0();
}
};
} |
|