Merhaba üstadlar,
Modbus RTU üzerine çalışmalar yapmaktayım.Program üzerinde deneme yanılma üzerine ilerliyorum. Elimde Delta VFD-USB01 RS485 çevirici var. Şu an devre board üzerine kurulu olduğu için şema paylaşamıyorum. Öncelikle kod üzerinde bariz hatalarım var ise ya da şu şekilde ilerle diyebileceğiniz noktalar var ise oradan adım adım düzenleyip ilerlemek istiyorum. Kodlarım şu şekilde;
//--------------------------40 pin MCU PIN_diagram
// _____________
//MCLR/VPP----------------|1 40|-------RB7/PGD
//RA0/AN0-----------------|2 39|-------RB6/PGC
//RA1/AN1-----------------|3 38|-------RB5
//RA2/AN2/VREF-/CVREF-----|4 37|-------RB4
//RA3/AN3/VREF+-----------|5 36|-------RB3/PGM
//RA4/T0CKI/C1OUT---------|6 35|-------RB2
//RA5/AN4/SS/C2OUT--------|7 34|-------RB1
//RE0/RD/AN5--------------|8 33|-------RB0/INT
//RE1/WR/AN6--------------|9 32|-------VDD
//RE2/CS/AN7--------------|10 31|-------VSS
//VDD---------------------|11 30|-------RD7/PSP7
//VSS---------------------|12 29|-------RD6/PSP6
//OSC1/CLKI---------------|13 28|-------RD5/PSP5
//OSC2/CLKO---------------|14 27|-------RD4/PSP4
//RC0/T1OSO/T1CKI---------|15 26|-------RC7/RX/DT
//RC1/T1OSI/CCP2----------|16 25|-------RC6/TX/CK
//RC2/CCP1----------------|17 24|-------RC5/SDO
//RC3/SCK/SCL-------------|18 23|-------RC4/SDI/SDA
//RD0/PSP0----------------|19 22|-------RD3/PSP3
//RD1/PSP1----------------|20 21|-------RD2/PSP2
// |____________|
#include <main.h>
#define MODBUS_BUS SERIAL
#define MODBUS_TYPE MODBUS_TYPE_SLAVE
#define MODBUS_SERIAL_TYPE MODBUS_RTU
#define MODBUS_SERIAL_INT_SOURCE MODBUS_INT_RDA
#define MODBUS_SERIAL_ENABLE_PIN PIN_C5
#define MODBUS_SERIAL_RX_ENABLE PIN_C4
#define MODBUS_SERIAL_BAUD 9600
#define MODBUS_OUR_ADDRESS 10
#include "modbus.c"
//#use fast_io(a)
//#use fast_io(b)
//#use fast_io(c)
//#use fast_io(d)
//#use fast_io(e)
#define LCD_ENABLE_PIN PIN_D1
#define LCD_RS_PIN PIN_D2
#define LCD_RW_PIN PIN_D3
#define LCD_DATA4 PIN_D4
#define LCD_DATA5 PIN_D5
#define LCD_DATA6 PIN_D6
#define LCD_DATA7 PIN_D7
#include "lcd.c"
#define MODBUS_ADDRESS 0x05
#define OUT1 PIN_C0
#define OUT2 PIN_C1
#define OUT3 PIN_C2
#define OUT4 PIN_C3
int8 coils = 0b00000101;
int8 inputs = 0b00001001;
int16 hold_regs[] = {0x8800,0x7700,0x6600,0x5500,0x4400,0x3300,0x2200,0x1100};
int16 input_regs[] = {0x1100,0x2200,0x3300,0x4400,0x5500,0x6600,0x7700,0x8800};
int16 event_count = 0;
int8 swap_bits(int8 c)
{
return ((c&1)?128:0)|((c&2)?64:0)|((c&4)?32:0)|((c&8)?16:0)|((c&16)?8:0)
|((c&32)?4:0)|((c&64)?2:0)|((c&128)?1:0);
}
void main()
{
//set_tris_a(0xFF);
//set_tris_e(0b111);
//set_tris_b(0x00);
//set_tris_c(0b10000000);
//set_tris_d(0x00);
modbus_init();
lcd_init();
delay_ms(1000);
lcd_gotoxy(1,1);
delay_ms(100);
lcd_putc("GOKHAN");
delay_ms(100);
while(TRUE)
{
output_toggle(OUT1);
delay_ms(500);
if (bit_test(coils,0) == 1)
OUTPUT_HIGH(OUT1);
else
OUTPUT_LOW(OUT1);
if (bit_test(coils,1) == 1)
OUTPUT_HIGH(OUT2);
else
OUTPUT_LOW(OUT2);
if (bit_test(coils,2) == 1)
OUTPUT_HIGH(OUT3);
else
OUTPUT_LOW(OUT3);
if (bit_test(coils,3) == 1)
OUTPUT_HIGH(OUT4);
else
OUTPUT_LOW(OUT4);
while(!modbus_kbhit());
delay_us(50);
//check address against our address, 0 is broadcast
if((modbus_rx.address == MODBUS_ADDRESS) || modbus_rx.address == 0)
{
switch(modbus_rx.func)
{
case FUNC_READ_COILS: //read coils
case FUNC_READ_DISCRETE_INPUT: //read inputs
if(modbus_rx.data[0] || modbus_rx.data[2] ||
modbus_rx.data[1] >= 8 || modbus_rx.data[3]+modbus_rx.data[1] > 8)
modbus_exception_rsp(MODBUS_ADDRESS,modbus_rx.func,ILLEGAL_DATA_ADDRESS);
else
{
int8 data;
if(modbus_rx.func == FUNC_READ_COILS)
data = coils>>(modbus_rx.data[1]); //move to the starting coil
else
data = inputs>>(modbus_rx.data[1]); //move to the starting input
data = data & (0xFF>>(8-modbus_rx.data[3])); //0 out values after quantity
if(modbus_rx.func == FUNC_READ_COILS)
modbus_read_coils_rsp(MODBUS_ADDRESS, 0x01, &data);
else
modbus_read_discrete_input_rsp(MODBUS_ADDRESS, 0x01, &data);
event_count++;
}
break;
case FUNC_READ_HOLDING_REGISTERS:
case FUNC_READ_INPUT_REGISTERS:
if(modbus_rx.data[0] || modbus_rx.data[2] ||
modbus_rx.data[1] >= 8 || modbus_rx.data[3]+modbus_rx.data[1] > 8)
modbus_exception_rsp(MODBUS_ADDRESS,modbus_rx.func,ILLEGAL_DATA_ADDRESS);
else
{
if(modbus_rx.func == FUNC_READ_HOLDING_REGISTERS)
modbus_read_holding_registers_rsp(MODBUS_ADDRESS,(modbus_rx.data[3]*2),hold_regs+modbus_rx.data[1]);
else
modbus_read_input_registers_rsp(MODBUS_ADDRESS,(modbus_rx.data[3]*2),input_regs+modbus_rx.data[1]);
event_count++;
}
break;
case FUNC_WRITE_SINGLE_COIL: //write coil
if(modbus_rx.data[0] || modbus_rx.data[3] || modbus_rx.data[1] > 8)
modbus_exception_rsp(MODBUS_ADDRESS,modbus_rx.func,ILLEGAL_DATA_ADDRESS);
else if(modbus_rx.data[2] != 0xFF && modbus_rx.data[2] != 0x00)
modbus_exception_rsp(MODBUS_ADDRESS,modbus_rx.func,ILLEGAL_DATA_VALUE);
else
{
if(modbus_rx.data[2] == 0xFF)
bit_set(coils,modbus_rx.data[1]);
else
bit_clear(coils,modbus_rx.data[1]);
modbus_write_single_coil_rsp(MODBUS_ADDRESS,modbus_rx.data[1],((int16)(modbus_rx.data[2]))<<8);
event_count++;
}
break;
case FUNC_WRITE_SINGLE_REGISTER:
if(modbus_rx.data[0] || modbus_rx.data[1] >= 8)
modbus_exception_rsp(MODBUS_ADDRESS,modbus_rx.func,ILLEGAL_DATA_ADDRESS);
else
{
hold_regs[modbus_rx.data[1]] = make16(modbus_rx.data[2],modbus_rx.data[3]);
modbus_write_single_register_rsp(MODBUS_ADDRESS,
make16(modbus_rx.data[0],modbus_rx.data[1]),
make16(modbus_rx.data[2],modbus_rx.data[3]));
}
break;
case FUNC_WRITE_MULTIPLE_COILS:
if(modbus_rx.data[0] || modbus_rx.data[2] ||
modbus_rx.data[1] >= 8 || modbus_rx.data[3]+modbus_rx.data[1] > 8)
modbus_exception_rsp(MODBUS_ADDRESS,modbus_rx.func,ILLEGAL_DATA_ADDRESS);
else
{
int i,j;
modbus_rx.data[5] = swap_bits(modbus_rx.data[5]);
for(i=modbus_rx.data[1],j=0; i < modbus_rx.data[1]+modbus_rx.data[3]; ++i,++j)
{
if(bit_test(modbus_rx.data[5],j))
bit_set(coils,7-i);
else
bit_clear(coils,7-i);
}
modbus_write_multiple_coils_rsp(MODBUS_ADDRESS,
make16(modbus_rx.data[0],modbus_rx.data[1]),
make16(modbus_rx.data[2],modbus_rx.data[3]));
event_count++;
}
break;
case FUNC_WRITE_MULTIPLE_REGISTERS:
if(modbus_rx.data[0] || modbus_rx.data[2] ||
modbus_rx.data[1] >= 8 || modbus_rx.data[3]+modbus_rx.data[1] > 8)
modbus_exception_rsp(MODBUS_ADDRESS,modbus_rx.func,ILLEGAL_DATA_ADDRESS);
else
{
int i,j;
for(i=0,j=5; i < modbus_rx.data[4]/2; ++i,j+=2)
hold_regs[i] = make16(modbus_rx.data[j],modbus_rx.data[j+1]);
modbus_write_multiple_registers_rsp(MODBUS_ADDRESS,
make16(modbus_rx.data[0],modbus_rx.data[1]),
make16(modbus_rx.data[2],modbus_rx.data[3]));
event_count++;
}
break;
default: //We don't support the function, so return exception
modbus_exception_rsp(MODBUS_ADDRESS,modbus_rx.func,ILLEGAL_FUNCTION);
}
}
}
}
Başlangıçta lcd ekranı ve modbus kütüphanesini init edip ekrana GOKHAN yazdırıyorum. Sonrasında modbus işliyor diye düşünüyorum. Bağlantılarım ise şu şekilde;
16F877A SN75176
RX>>>>>>>>>>>>4 nolu pin
TX>>>>>>>>>>>>1 nolu pin
PIN_C5>>>>>>>>>3 nolu pin
PIN_C4>>>>>>>>>2 nolu pin
A-B uçları direkt olarak 75176'ya bağlı arada herhangi bir direnç vs yok.
Belki bir arkadaşa faydası dokunur. Şu anda program 2x16 lcd ekranın 2. satırına Modbus RTU'dan gelen yazma isteği üzerine yazılan değişkeni göstermektedir. Slave ID 5'dir. İstenildiği taktirde program içerisinden müdahale edilebilir. CCS'nin default kütüphane kodudur. İnclude dosyalarını kendi klasöründen rahatlıkla bulabilirsiniz. Program default olarak 16bit 8 adet değişken adresi, 8 adet output,8 adet input barındırmaktadır. Programda tanımlandığı gibi outputları istediğiniz pinlere yönlendirebilirsiniz. Örnekte 0. adresteki output pini PIN_C0 şeklindedir.
//--------------------------40 pin MCU PIN_diagram
// _____________
//MCLR/VPP----------------|1 40|-------RB7/PGD
//RA0/AN0-----------------|2 39|-------RB6/PGC
//RA1/AN1-----------------|3 38|-------RB5
//RA2/AN2/VREF-/CVREF-----|4 37|-------RB4
//RA3/AN3/VREF+-----------|5 36|-------RB3/PGM
//RA4/T0CKI/C1OUT---------|6 35|-------RB2
//RA5/AN4/SS/C2OUT--------|7 34|-------RB1
//RE0/RD/AN5--------------|8 33|-------RB0/INT
//RE1/WR/AN6--------------|9 32|-------VDD
//RE2/CS/AN7--------------|10 31|-------VSS
//VDD---------------------|11 30|-------RD7/PSP7
//VSS---------------------|12 29|-------RD6/PSP6
//OSC1/CLKI---------------|13 28|-------RD5/PSP5
//OSC2/CLKO---------------|14 27|-------RD4/PSP4
//RC0/T1OSO/T1CKI---------|15 26|-------RC7/RX/DT
//RC1/T1OSI/CCP2----------|16 25|-------RC6/TX/CK
//RC2/CCP1----------------|17 24|-------RC5/SDO
//RC3/SCK/SCL-------------|18 23|-------RC4/SDI/SDA
//RD0/PSP0----------------|19 22|-------RD3/PSP3
//RD1/PSP1----------------|20 21|-------RD2/PSP2
// |____________|
#include <main.h>
#define MODBUS_BUS SERIAL
#define MODBUS_TYPE MODBUS_TYPE_SLAVE
#define MODBUS_SERIAL_TYPE MODBUS_RTU
#define MODBUS_SERIAL_INT_SOURCE MODBUS_INT_RDA
#define MODBUS_SERIAL_ENABLE_PIN PIN_C5
#define MODBUS_SERIAL_RX_ENABLE PIN_C4
#define MODBUS_SERIAL_BAUD 9600
#define MODBUS_OUR_ADDRESS 10
#include "modbus.c"
//#use fast_io(a)
//#use fast_io(b)
//#use fast_io(c)
//#use fast_io(d)
//#use fast_io(e)
#define LCD_ENABLE_PIN PIN_D1
#define LCD_RS_PIN PIN_D2
#define LCD_RW_PIN PIN_D3
#define LCD_DATA4 PIN_D4
#define LCD_DATA5 PIN_D5
#define LCD_DATA6 PIN_D6
#define LCD_DATA7 PIN_D7
#include "lcd.c"
#define MODBUS_ADDRESS 0x05
#define OUT1 PIN_C0
#define OUT2 PIN_C1
#define OUT3 PIN_C2
#define OUT4 PIN_C3
int8 coils = 0b00000000;
int8 inputs = 0b00000000;
int16 hold_regs[] = {0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000};
int16 input_regs[] = {0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000};
int16 event_count = 0;
int8 swap_bits(int8 c)
{
return ((c&1)?128:0)|((c&2)?64:0)|((c&4)?32:0)|((c&8)?16:0)|((c&16)?8:0)
|((c&32)?4:0)|((c&64)?2:0)|((c&128)?1:0);
}
#zero_ram
void main()
{
//set_tris_a(0xFF);
//set_tris_e(0b111);
//set_tris_b(0x00);
//set_tris_c(0b10000000);
//set_tris_d(0x00);
modbus_init();
lcd_init();
delay_ms(1000);
lcd_gotoxy(1,1);
delay_ms(100);
lcd_putc("GOKHAN");
delay_ms(100);
while(TRUE)
{
if (bit_test(coils,0) == 1)
OUTPUT_HIGH(OUT1);
else
OUTPUT_LOW(OUT1);
if (bit_test(coils,1) == 1)
OUTPUT_HIGH(OUT2);
else
OUTPUT_LOW(OUT2);
if (bit_test(coils,2) == 1)
OUTPUT_HIGH(OUT3);
else
OUTPUT_LOW(OUT3);
if (bit_test(coils,3) == 1)
OUTPUT_HIGH(OUT4);
else
OUTPUT_LOW(OUT4);
lcd_gotoxy(1,2);
printf(lcd_putc,"%4LX",hold_regs[0]);
while(!modbus_kbhit());
delay_us(50);
//check address against our address, 0 is broadcast
if((modbus_rx.address == MODBUS_ADDRESS) || modbus_rx.address == 0)
{
switch(modbus_rx.func)
{
case FUNC_READ_COILS: //read coils
case FUNC_READ_DISCRETE_INPUT: //read inputs
if(modbus_rx.data[0] || modbus_rx.data[2] ||
modbus_rx.data[1] >= 8 || modbus_rx.data[3]+modbus_rx.data[1] > 8)
modbus_exception_rsp(MODBUS_ADDRESS,modbus_rx.func,ILLEGAL_DATA_ADDRESS);
else
{
int8 data;
if(modbus_rx.func == FUNC_READ_COILS)
data = coils>>(modbus_rx.data[1]); //move to the starting coil
else
data = inputs>>(modbus_rx.data[1]); //move to the starting input
data = data & (0xFF>>(8-modbus_rx.data[3])); //0 out values after quantity
if(modbus_rx.func == FUNC_READ_COILS)
modbus_read_coils_rsp(MODBUS_ADDRESS, 0x01, &data);
else
modbus_read_discrete_input_rsp(MODBUS_ADDRESS, 0x01, &data);
event_count++;
}
break;
case FUNC_READ_HOLDING_REGISTERS:
case FUNC_READ_INPUT_REGISTERS:
if(modbus_rx.data[0] || modbus_rx.data[2] ||
modbus_rx.data[1] >= 8 || modbus_rx.data[3]+modbus_rx.data[1] > 8)
modbus_exception_rsp(MODBUS_ADDRESS,modbus_rx.func,ILLEGAL_DATA_ADDRESS);
else
{
if(modbus_rx.func == FUNC_READ_HOLDING_REGISTERS)
modbus_read_holding_registers_rsp(MODBUS_ADDRESS,(modbus_rx.data[3]*2),hold_regs+modbus_rx.data[1]);
else
modbus_read_input_registers_rsp(MODBUS_ADDRESS,(modbus_rx.data[3]*2),input_regs+modbus_rx.data[1]);
event_count++;
}
break;
case FUNC_WRITE_SINGLE_COIL: //write coil
if(modbus_rx.data[0] || modbus_rx.data[3] || modbus_rx.data[1] > 8)
modbus_exception_rsp(MODBUS_ADDRESS,modbus_rx.func,ILLEGAL_DATA_ADDRESS);
else if(modbus_rx.data[2] != 0xFF && modbus_rx.data[2] != 0x00)
modbus_exception_rsp(MODBUS_ADDRESS,modbus_rx.func,ILLEGAL_DATA_VALUE);
else
{
if(modbus_rx.data[2] == 0xFF)
bit_set(coils,modbus_rx.data[1]);
else
bit_clear(coils,modbus_rx.data[1]);
modbus_write_single_coil_rsp(MODBUS_ADDRESS,modbus_rx.data[1],((int16)(modbus_rx.data[2]))<<8);
event_count++;
}
break;
case FUNC_WRITE_SINGLE_REGISTER:
if(modbus_rx.data[0] || modbus_rx.data[1] >= 8)
modbus_exception_rsp(MODBUS_ADDRESS,modbus_rx.func,ILLEGAL_DATA_ADDRESS);
else
{
hold_regs[modbus_rx.data[1]] = make16(modbus_rx.data[2],modbus_rx.data[3]);
modbus_write_single_register_rsp(MODBUS_ADDRESS,
make16(modbus_rx.data[0],modbus_rx.data[1]),
make16(modbus_rx.data[2],modbus_rx.data[3]));
}
break;
case FUNC_WRITE_MULTIPLE_COILS:
if(modbus_rx.data[0] || modbus_rx.data[2] ||
modbus_rx.data[1] >= 8 || modbus_rx.data[3]+modbus_rx.data[1] > 8)
modbus_exception_rsp(MODBUS_ADDRESS,modbus_rx.func,ILLEGAL_DATA_ADDRESS);
else
{
int i,j;
modbus_rx.data[5] = swap_bits(modbus_rx.data[5]);
for(i=modbus_rx.data[1],j=0; i < modbus_rx.data[1]+modbus_rx.data[3]; ++i,++j)
{
if(bit_test(modbus_rx.data[5],j))
bit_set(coils,7-i);
else
bit_clear(coils,7-i);
}
modbus_write_multiple_coils_rsp(MODBUS_ADDRESS,
make16(modbus_rx.data[0],modbus_rx.data[1]),
make16(modbus_rx.data[2],modbus_rx.data[3]));
event_count++;
}
break;
case FUNC_WRITE_MULTIPLE_REGISTERS:
if(modbus_rx.data[0] || modbus_rx.data[2] ||
modbus_rx.data[1] >= 8 || modbus_rx.data[3]+modbus_rx.data[1] > 8)
modbus_exception_rsp(MODBUS_ADDRESS,modbus_rx.func,ILLEGAL_DATA_ADDRESS);
else
{
int i,j;
for(i=0,j=5; i < modbus_rx.data[4]/2; ++i,j+=2)
hold_regs[i] = make16(modbus_rx.data[j],modbus_rx.data[j+1]);
modbus_write_multiple_registers_rsp(MODBUS_ADDRESS,
make16(modbus_rx.data[0],modbus_rx.data[1]),
make16(modbus_rx.data[2],modbus_rx.data[3]));
event_count++;
}
break;
default: //We don't support the function, so return exception
modbus_exception_rsp(MODBUS_ADDRESS,modbus_rx.func,ILLEGAL_FUNCTION);
}
}
}
}
Bağlantılar ise şöyle;
Default olarak programdan RX ve TX pini seçmediğinizde (Wizard ile Modbus RTU kodu oluştururken) hardware USART pinlerini kullanılıyor. 75176 kullandım konvertör olarak.
1. Pin-> işlemci RX pinine,
2. Pin-> Programdaki tanımlanan RX enable pini,
3. Pin-> Programdaki tanımlanan Serial enable pini,
4. Pin-> İşlemci TX pinine,
5. Pin-> GND,
6. Pin-> Modbus hattı,
7. Pin-> Modbus hattı,
8. Pin-> +5V,
LCD bağlantıları zaten programda belirlenebiliyor. İşlemci beslemesi ve reset osc pinleri standart işlemciye göre bağlantı yapılır. Cümleten iyi günler dilerim.
http://www.modbus.pl/Modbus%20Tester_MODBUS.PL.html
Bu programı firmware'ini test edebilirsin.
Başlangıçta direk rs232 ile iletişim kurmanı tavsiye ederim. rx,tx,gnd pinleri ve herhangi bir usb seri çevirici yeterli olur.
Teşekkür ederim hocam, Modbus Pool ile testlerimi yaptım gayet güzel çalışıyor ama demo olmasından dolayı 10 dk'da kapatmamı istiyor 30 gün gibide süresi var bitmek üzere verdiğiniz programı deneyeceğim.
Alıntı yapılan: gokhangokcen - 12 Eylül 2017, 11:12:16Teşekkür ederim hocam, Modbus Pool ile testlerimi yaptım gayet güzel çalışıyor ama demo olmasından dolayı 10 dk'da kapatmamı istiyor 30 gün gibide süresi var bitmek üzere verdiğiniz programı deneyeceğim.
Hocam selamün aleyküm, hemşeriymişiz.
Bana da tam senin projen ihtiyaçtı. Kodlarını kullanmak istedim. Söylediklerinin aynısını yapıyorum yalnız nedense transmitter enable pini bir türlü aktif olmuyor. Hem transmitteri hem de LCD yi arduino platformunda kullandım bir problem yoktu.
Yardımcı olursan çok sevinirim, benim için bu çok büyük dert oldu.
Kullandığım kod
#include <16F877A.h>
#device ADC=10
#fuses HS,NOWDT,NOPROTECT,NOBROWNOUT,NOLVP,NOPUT,NOWRT,NODEBUG,NOCPD
#use delay(crystal=20MHz)
//--------------------------40 pin MCU PIN_diagram
// _____________
//MCLR/VPP----------------|1 40|-------RB7/PGD
//RA0/AN0-----------------|2 39|-------RB6/PGC
//RA1/AN1-----------------|3 38|-------RB5
//RA2/AN2/VREF-/CVREF-----|4 37|-------RB4
//RA3/AN3/VREF+-----------|5 36|-------RB3/PGM
//RA4/T0CKI/C1OUT---------|6 35|-------RB2
//RA5/AN4/SS/C2OUT--------|7 34|-------RB1
//RE0/RD/AN5--------------|8 33|-------RB0/INT
//RE1/WR/AN6--------------|9 32|-------VDD
//RE2/CS/AN7--------------|10 31|-------VSS
//VDD---------------------|11 30|-------RD7/PSP7
//VSS---------------------|12 29|-------RD6/PSP6
//OSC1/CLKI---------------|13 28|-------RD5/PSP5
//OSC2/CLKO---------------|14 27|-------RD4/PSP4
//RC0/T1OSO/T1CKI---------|15 26|-------RC7/RX/DT
//RC1/T1OSI/CCP2----------|16 25|-------RC6/TX/CK
//RC2/CCP1----------------|17 24|-------RC5/SDO
//RC3/SCK/SCL-------------|18 23|-------RC4/SDI/SDA
//RD0/PSP0----------------|19 22|-------RD3/PSP3
//RD1/PSP1----------------|20 21|-------RD2/PSP2
// |____________|
#define MODBUS_BUS SERIAL
#define MODBUS_TYPE MODBUS_TYPE_SLAVE
#define MODBUS_SERIAL_TYPE MODBUS_RTU
#define MODBUS_SERIAL_INT_SOURCE MODBUS_INT_RDA
#define MODBUS_SERIAL_ENABLE_PIN PIN_C5
#define MODBUS_SERIAL_RX_ENABLE PIN_C5
#define MODBUS_SERIAL_BAUD 9600
#define MODBUS_OUR_ADDRESS 10
#include "modbus.c"
//#use fast_io(a)
//#use fast_io(b)
//#use fast_io(c)
//#use fast_io(d)
//#use fast_io(e)
#define LCD_ENABLE_PIN PIN_D1
#define LCD_RS_PIN PIN_D2
#define LCD_RW_PIN PIN_D3
#define LCD_DATA4 PIN_D4
#define LCD_DATA5 PIN_D5
#define LCD_DATA6 PIN_D6
#define LCD_DATA7 PIN_D7
#include "lcd.c"
#define MODBUS_ADDRESS 0x05
#define OUT1 PIN_C0
#define OUT2 PIN_C1
#define OUT3 PIN_C2
#define OUT4 PIN_C3
int8 coils = 0b00000000;
int8 inputs = 0b00000000;
int16 hold_regs[] = {0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000};
int16 input_regs[] = {0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000};
int16 event_count = 0;
int8 swap_bits(int8 c)
{
return ((c&1)?128:0)|((c&2)?64:0)|((c&4)?32:0)|((c&8)?16:0)|((c&16)?8:0)
|((c&32)?4:0)|((c&64)?2:0)|((c&128)?1:0);
}
#zero_ram
void main()
{
//set_tris_a(0xFF);
//set_tris_e(0b111);
//set_tris_b(0x00);
//set_tris_c(0b10000000);
//set_tris_d(0x00);
modbus_init();
lcd_init();
delay_ms(1000);
lcd_gotoxy(1,1);
delay_ms(100);
lcd_putc("GOKHAN");
delay_ms(100);
while(TRUE)
{
if (bit_test(coils,0) == 1)
OUTPUT_HIGH(OUT1);
else
OUTPUT_LOW(OUT1);
if (bit_test(coils,1) == 1)
OUTPUT_HIGH(OUT2);
else
OUTPUT_LOW(OUT2);
if (bit_test(coils,2) == 1)
OUTPUT_HIGH(OUT3);
else
OUTPUT_LOW(OUT3);
if (bit_test(coils,3) == 1)
OUTPUT_HIGH(OUT4);
else
OUTPUT_LOW(OUT4);
lcd_gotoxy(1,2);
printf(lcd_putc,"%4LX",hold_regs[0]);
while(!modbus_kbhit());
delay_us(50);
//check address against our address, 0 is broadcast
if((modbus_rx.address == MODBUS_ADDRESS) || modbus_rx.address == 0)
{
switch(modbus_rx.func)
{
case FUNC_READ_COILS: //read coils
case FUNC_READ_DISCRETE_INPUT: //read inputs
if(modbus_rx.data[0] || modbus_rx.data[2] ||
modbus_rx.data[1] >= 8 || modbus_rx.data[3]+modbus_rx.data[1] > 8)
modbus_exception_rsp(MODBUS_ADDRESS,modbus_rx.func,ILLEGAL_DATA_ADDRESS);
else
{
int8 data;
if(modbus_rx.func == FUNC_READ_COILS)
data = coils>>(modbus_rx.data[1]); //move to the starting coil
else
data = inputs>>(modbus_rx.data[1]); //move to the starting input
data = data & (0xFF>>(8-modbus_rx.data[3])); //0 out values after quantity
if(modbus_rx.func == FUNC_READ_COILS)
modbus_read_coils_rsp(MODBUS_ADDRESS, 0x01, &data);
else
modbus_read_discrete_input_rsp(MODBUS_ADDRESS, 0x01, &data);
event_count++;
}
break;
case FUNC_READ_HOLDING_REGISTERS:
case FUNC_READ_INPUT_REGISTERS:
if(modbus_rx.data[0] || modbus_rx.data[2] ||
modbus_rx.data[1] >= 8 || modbus_rx.data[3]+modbus_rx.data[1] > 8)
modbus_exception_rsp(MODBUS_ADDRESS,modbus_rx.func,ILLEGAL_DATA_ADDRESS);
else
{
if(modbus_rx.func == FUNC_READ_HOLDING_REGISTERS)
modbus_read_holding_registers_rsp(MODBUS_ADDRESS,(modbus_rx.data[3]*2),hold_regs+modbus_rx.data[1]);
else
modbus_read_input_registers_rsp(MODBUS_ADDRESS,(modbus_rx.data[3]*2),input_regs+modbus_rx.data[1]);
event_count++;
}
break;
case FUNC_WRITE_SINGLE_COIL: //write coil
if(modbus_rx.data[0] || modbus_rx.data[3] || modbus_rx.data[1] > 8)
modbus_exception_rsp(MODBUS_ADDRESS,modbus_rx.func,ILLEGAL_DATA_ADDRESS);
else if(modbus_rx.data[2] != 0xFF && modbus_rx.data[2] != 0x00)
modbus_exception_rsp(MODBUS_ADDRESS,modbus_rx.func,ILLEGAL_DATA_VALUE);
else
{
if(modbus_rx.data[2] == 0xFF)
bit_set(coils,modbus_rx.data[1]);
else
bit_clear(coils,modbus_rx.data[1]);
modbus_write_single_coil_rsp(MODBUS_ADDRESS,modbus_rx.data[1],((int16)(modbus_rx.data[2]))<<8);
event_count++;
}
break;
case FUNC_WRITE_SINGLE_REGISTER:
if(modbus_rx.data[0] || modbus_rx.data[1] >= 8)
modbus_exception_rsp(MODBUS_ADDRESS,modbus_rx.func,ILLEGAL_DATA_ADDRESS);
else
{
hold_regs[modbus_rx.data[1]] = make16(modbus_rx.data[2],modbus_rx.data[3]);
modbus_write_single_register_rsp(MODBUS_ADDRESS,
make16(modbus_rx.data[0],modbus_rx.data[1]),
make16(modbus_rx.data[2],modbus_rx.data[3]));
}
break;
case FUNC_WRITE_MULTIPLE_COILS:
if(modbus_rx.data[0] || modbus_rx.data[2] ||
modbus_rx.data[1] >= 8 || modbus_rx.data[3]+modbus_rx.data[1] > 8)
modbus_exception_rsp(MODBUS_ADDRESS,modbus_rx.func,ILLEGAL_DATA_ADDRESS);
else
{
int i,j;
modbus_rx.data[5] = swap_bits(modbus_rx.data[5]);
for(i=modbus_rx.data[1],j=0; i < modbus_rx.data[1]+modbus_rx.data[3]; ++i,++j)
{
if(bit_test(modbus_rx.data[5],j))
bit_set(coils,7-i);
else
bit_clear(coils,7-i);
}
modbus_write_multiple_coils_rsp(MODBUS_ADDRESS,
make16(modbus_rx.data[0],modbus_rx.data[1]),
make16(modbus_rx.data[2],modbus_rx.data[3]));
event_count++;
}
break;
case FUNC_WRITE_MULTIPLE_REGISTERS:
if(modbus_rx.data[0] || modbus_rx.data[2] ||
modbus_rx.data[1] >= 8 || modbus_rx.data[3]+modbus_rx.data[1] > 8)
modbus_exception_rsp(MODBUS_ADDRESS,modbus_rx.func,ILLEGAL_DATA_ADDRESS);
else
{
int i,j;
for(i=0,j=5; i < modbus_rx.data[4]/2; ++i,j+=2)
hold_regs[i] = make16(modbus_rx.data[j],modbus_rx.data[j+1]);
modbus_write_multiple_registers_rsp(MODBUS_ADDRESS,
make16(modbus_rx.data[0],modbus_rx.data[1]),
make16(modbus_rx.data[2],modbus_rx.data[3]));
event_count++;
}
break;
default: //We don't support the function, so return exception
modbus_exception_rsp(MODBUS_ADDRESS,modbus_rx.func,ILLEGAL_FUNCTION);
}
}
}
}
Kodta bir yerlerde yanlış yapıyorum sanıyorum. Halbuki pic tanımlamaları dışında her şey seninkinin aynısı.
Yardımcı olursan çok sevinirim.
İyi akşamlar.
@rattlesnake mesajını yeni gördüm rx_enable ile tx_enable pinlerinin ikisinide PIN_C5 olarak tanımlamışsın bu pinler birbirinin değili olduğu için son fonksiyonda pini low yapıyordur o yüzden aktif olmaz. Olması gereken ya tek bir tane pin kullanacaksın 485 entegresinde rx_tx-enable pinlerini kısa devre yapacaksın ya da iki farklı pin tanımlayıp bağlayacaksın.
gökhan kardeşim merhaba.
modbus poll da test yaptığımda timeout error hatası alıyorum. Bu konuda bir bilgin var mı? iyi çalışmalar.
@omerglal1 üstad devreni görmeden yorum yapmam zor. herşey olabilir. slave id hatalı olabilir, devren çalışmıyor olabilir, bozuk malzeme olabilir, a-b uçları ters olabilir.. vb. şeyleri çoğaltmak mümkün.
tamamdır çözdüm problemi. enable pinlerini ters bağlamışım. cevabın için teşekkürler.
İyi günler , projenin şemasını paylaşabilme şansınız var mı acaba?
@umutaymn projenin şemasını paylaşacak bir durum yok zaten kodda bütün pinlerin nereye bağlı olduğu yazıyor.