Atmega Bascom odczyt rejestru po RS485 Modbus RTU
: 28 maja 2026, 21:47
Szukałem jakichś przykładów w Internecie ale nic nie znalazłem, AI też nie jest chętna do pomocy bo każda poprawka to coraz więcej błędów w kompilatorze. Chciałbym prosić o pomoc w napisaniu programu. Chciałem odczytać za pomocą Atmegi 8-ki 1 rejestr dwukierunkowego licznika energii DTSU666 , wpisać tą wartość do jakiejś zmiennej i wyświetlić ją na wyświetlaczu LCD. Konkretnie chodzi o rejestr 2012H , wg. rozpiski opis rejestru Data type : float , data lenght : Word 2. Licznik ma komunikację RS485 Modbus RTU. Ustawienia parametrów licznika : Szybkość transmisji : 9600bps / Adres urządzenia : 1 / Protokół komunikacyjny : brak parzystości , 1 bit stopu , n.1. Wartość odczytana z rejestru będzie na pewno miała wartość ujemną lub dodatnią bo jest to moc czynna oddawana/pobierana z sieci. Będzie to wartość 32-bitowa. Docelowo mnie głównie będzie interesować wartość ujemna, ( poniżej zera ) którą chciałem wpisać do PWM i docelowo atmega ma za pomocą wypełnienia PWM przedstawiać wartość mocy oddawanej do sieci a to sobie dalej będzie sterować resztą.
Coś tam w Bascomie programowałem ale jeżeli chodzi o modbus to niestety jestem zielony. Jeżeli mogę to bardzo proszę o pomoc, oczywiście wcale nie chcę za darmo bo wiem że wiedza kosztuje i ktoś na to musi poświęcić swój czas. Jesteśmy tylko ludźmi i zawsze możemy się dogadać. Schemat podłączenia Amegi z układem MAX485 i wyświetlaczem w załączniku. W załączniku są także instrukcja do licznika i opis jego rejestrów. Poniżej kod który wygenerowała AI, ale kompilator pokazuje błędy z którymi ani AI ani ja nie potrafimy sobie poradzić
Coś tam w Bascomie programowałem ale jeżeli chodzi o modbus to niestety jestem zielony. Jeżeli mogę to bardzo proszę o pomoc, oczywiście wcale nie chcę za darmo bo wiem że wiedza kosztuje i ktoś na to musi poświęcić swój czas. Jesteśmy tylko ludźmi i zawsze możemy się dogadać. Schemat podłączenia Amegi z układem MAX485 i wyświetlaczem w załączniku. W załączniku są także instrukcja do licznika i opis jego rejestrów. Poniżej kod który wygenerowała AI, ale kompilator pokazuje błędy z którymi ani AI ani ja nie potrafimy sobie poradzić
Code: [Zaznacz cały] [Rozwiń/Zwiń]
- $regfile = "m8def.dat"
- $crystal = 16000000
- $baud = 9600
- '========================
- ' LCD 2x16 konfiguracja
- '========================
- Config Lcd = 16 * 2
- Config Lcdpin = Pin , Rs = Portd.4 , E = Portc.5 , Db4 = Portc.4 , Db5 = Portc.3 , Db6 = Portc.2 , Db7 = Portc.1
- Cursor Off
- Cls
- '========================
- ' RS485 kierunek transmisji
- ' PD2 -> RE/ + DE MAX485
- ' 0 = odbiór
- ' 1 = nadawanie
- '========================
- Config Portd.2 = Output
- Portd.2 = 0
- '========================
- ' UART
- ' PD0 = RXD
- ' PD1 = TXD
- '========================
- Open "COMD.0:9600,8,N,1" For Binary As #1
- '========================
- ' Zmienne
- '========================
- Dim Tx(8) As Byte
- Dim Rx(9) As Byte
- Dim I As Byte
- Dim Crc As Word
- Dim Crc_lo As Byte
- Dim Crc_hi As Byte
- Dim Reg_hi As Word
- Dim Reg_lo As Word
- Dim P As Long
- Dim Slave_id As Byte
- Slave_id = 1
- '========================
- ' Deklaracje
- '========================
- Declare Function Modbus_crc(byval Crcdata() As Byte , Byval N As Byte) As Word
- Declare Sub Send_modbus_request()
- Declare Function Read_power() As Byte
- '========================
- ' Start
- '========================
- Cls
- Locate 1 , 1
- Lcd "DTSU666 Modbus"
- Locate 2 , 1
- Lcd "Start..."
- Wait 2
- Do
- If Read_power() = 1 Then
- Cls
- Locate 1 , 1
- Lcd "Moc P:"
- Locate 2 , 1
- Lcd P
- Else
- Cls
- Locate 1 , 1
- Lcd "Blad odczytu"
- End If
- Wait 1
- Loop
- End
- '====================================================
- ' Funkcja odczytu rejestru 2012H (2 rejestry = 32 bity)
- ' Zwraca 1 gdy OK, 0 gdy blad
- '====================================================
- Function Read_power() As Byte
- Local Timeout As Word
- Local Bytecount As Byte
- Local Calc_crc As Word
- Local Rec_crc As Word
- '------------------------------------------
- ' Ramka zapytania Modbus RTU:
- ' [ID][03][20][12][00][02][CRCL][CRCH]
- '------------------------------------------
- Tx(1) = Slave_id
- Tx(2) = &H03
- Tx(3) = &H20
- Tx(4) = &H12
- Tx(5) = &H00
- Tx(6) = &H02
- Crc = Modbus_crc(tx() , 6) 'Crc = Modbus_crc(tx , 6)
- Tx(7) = Low(crc)
- Tx(8) = High(crc)
- '------------------------------------------
- ' Wysylanie
- '------------------------------------------
- Portd.2 = 1
- Waitms 2
- For I = 1 To 8
- Put #1 , Tx(i)
- Next I
- Waitms 10
- Portd.2 = 0
- '------------------------------------------
- ' Odbior odpowiedzi:
- ' [ID][03][04][D1][D2][D3][D4][CRCL][CRCH]
- '------------------------------------------
- Timeout = 0
- For I = 1 To 9
- Do
- If Ischarwaiting(#1) <> 0 Then Exit Do
- Waitms 1
- Incr Timeout
- If Timeout > 500 Then
- Read_power = 0
- Exit Function
- End If
- Loop
- Get #1 , Rx(i)
- Next I
- ' Sprawdzenie podstawowe
- If Rx(1) <> Slave_id Then
- Read_power = 0
- Exit Function
- End If
- If Rx(2) <> &H03 Then
- Read_power = 0
- Exit Function
- End If
- Bytecount = Rx(3)
- If Bytecount <> 4 Then
- Read_power = 0
- Exit Function
- End If
- ' CRC odpowiedzi
- Calc_crc = Modbus_crc(rx() , 7)
- Rec_crc = Makeint(rx(8) , Rx(9))
- If Calc_crc <> Rec_crc Then
- Read_power = 0
- Exit Function
- End If
- ' Skladanie 32-bitowej wartosci:
- ' Rx(4)=MSB high word
- ' Rx(5)=LSB high word
- ' Rx(6)=MSB low word
- ' Rx(7)=LSB low word
- Reg_hi = Makeint(rx(5) , Rx(4))
- Reg_lo = Makeint(rx(7) , Rx(6))
- P = Reg_hi
- Shift P , Left , 16
- P = P + Reg_lo
- Read_power = 1
- End Function
- '====================================================
- ' CRC16 Modbus
- '====================================================
- Function Modbus_crc(byval Crcdata() As Byte , Byval N As Byte) As Word
- Local J As Byte
- Local K As Byte
- Local C As Word
- C = &HFFFF
- For J = 1 To N
- C = C Xor Crcdata(j)
- For K = 1 To 8
- If C.0 = 1 Then
- Shift C , Right , 1
- C = C Xor &HA001
- Else
- Shift C , Right , 1
- End If
- Next K
- Next J
- Modbus_crc = C
- End Function