Compare commits
7 Commits
Author | SHA1 | Date | |
---|---|---|---|
53db135840 | |||
6315234d40 | |||
3e56a4b910 | |||
afb28ad70b | |||
8fcf65ba66 | |||
7819975461 | |||
baa98357c1 |
31
README.md
31
README.md
@ -1,31 +0,0 @@
|
|||||||
# Modbus устройство на AVR
|
|
||||||
# Задание
|
|
||||||
Устройство поключено к питанию всегда. Взаимодействие по интерфейсу UART (RS-485) и протоколу Modbus.
|
|
||||||
- Discrete Inputs - 4 штуки
|
|
||||||
- Coils - 4 штуки
|
|
||||||
- Input registers - 2 канала АЦП
|
|
||||||
- Holding Registers - 1 штука: адрес на шине Modbus.
|
|
||||||
Адрес по умолчанию 0х32. Адрес хранить в ПЗУ чипа.
|
|
||||||
Адреса данных определить самостоятельно.
|
|
||||||
# Участники
|
|
||||||
Южакова Лада
|
|
||||||
Салангина Анастасия
|
|
||||||
Макуц Ольга
|
|
||||||
# Задачи
|
|
||||||
Южакова Лада:
|
|
||||||
- Изучить, как переопределять адрес по умолчанию в ПЗУ
|
|
||||||
- Изучить ПЗУ
|
|
||||||
- Изучить АЦП
|
|
||||||
- Изучить, как определять адреса данных в ПЗУ
|
|
||||||
- Понять, в какой последовательности будет работать программа
|
|
||||||
- Изучить, что такое верхняя архитектура
|
|
||||||
|
|
||||||
Салангина Анастасия:
|
|
||||||
- Изучить Modbus
|
|
||||||
- Определить, как происходит передача по протоколу
|
|
||||||
|
|
||||||
Макуц Ольга:
|
|
||||||
- Изучить UART
|
|
||||||
- Разобрать назначение и способы использования регистров и вхоов-выходов
|
|
||||||
- Изучить, как использовать RX/TX
|
|
||||||
- Изучить кольцевой буфер
|
|
37
device_adc.c
Normal file
37
device_adc.c
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
#include "device_adc.h"
|
||||||
|
|
||||||
|
uint16_t value = 0;
|
||||||
|
char high_adc = 0, low_adc = 0;
|
||||||
|
|
||||||
|
ISR(ADC_vect)
|
||||||
|
{
|
||||||
|
low_adc = ADCL;
|
||||||
|
high_adc = ADCH;
|
||||||
|
value = (high_adc << 8) | low_adc;
|
||||||
|
}
|
||||||
|
|
||||||
|
void adc_init(void)
|
||||||
|
{
|
||||||
|
// Опорное напряжение на входе AREF
|
||||||
|
ADMUX &= ~REFS0_MASK;
|
||||||
|
// Выравнивание результата вправо
|
||||||
|
ADMUX &= ~ADLAR_MASK;
|
||||||
|
// Коммутация выбранного входа с АЦП (ADC0)
|
||||||
|
ADMUX &= ~(MUX3_MASK | MUX2_MASK | MUX1_MASK | MUX0_MASK);
|
||||||
|
// Разерешение работы АЦП
|
||||||
|
ADCSRA |= ADEN_MASK;
|
||||||
|
// Запуск работы АЦП
|
||||||
|
ADCSRA |= ADSC_MASK;
|
||||||
|
// Предделитель частоты (128)
|
||||||
|
ADCSRA |= ADPS2_MASK | ADPS1_MASK | ADPS0_MASK;
|
||||||
|
// Разрешение прерывания от АЦП
|
||||||
|
ADCSRA |= ADIE_MASK;
|
||||||
|
// Непрерывный режим работы АЦП
|
||||||
|
ADCSRA |= ADATE_MASK;
|
||||||
|
sei();
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t get_adc_value(void)
|
||||||
|
{
|
||||||
|
return value;
|
||||||
|
}
|
43
device_adc.h
Normal file
43
device_adc.h
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
#ifndef DEVICE_ADC_H
|
||||||
|
#define DEVICE_ADC_H
|
||||||
|
|
||||||
|
#include <avr/interrupt.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <avr/io.h>
|
||||||
|
#define F_CPU 16000000
|
||||||
|
|
||||||
|
#define REFS1_BIT (7)
|
||||||
|
#define REFS1_MASK (1<<REFS1_BIT)
|
||||||
|
#define REFS0_BIT (6)
|
||||||
|
#define REFS0_MASK (1<<REFS0_BIT)
|
||||||
|
#define ADLAR_BIT (5)
|
||||||
|
#define ADLAR_MASK (1<<ADLAR_BIT)
|
||||||
|
#define MUX3_BIT (3)
|
||||||
|
#define MUX3_MASK (1<<MUX3_BIT)
|
||||||
|
#define MUX2_BIT (2)
|
||||||
|
#define MUX2_MASK (1<<MUX2_BIT)
|
||||||
|
#define MUX1_BIT (1)
|
||||||
|
#define MUX1_MASK (1<<MUX1_BIT)
|
||||||
|
#define MUX0_BIT (0)
|
||||||
|
#define MUX0_MASK (1<<MUX0_BIT)
|
||||||
|
#define ADEN_BIT (7)
|
||||||
|
#define ADEN_MASK (1<<ADEN_BIT)
|
||||||
|
#define ADPS2_BIT (2)
|
||||||
|
#define ADPS2_MASK (1<<ADPS2_BIT)
|
||||||
|
#define ADPS1_BIT (1)
|
||||||
|
#define ADPS1_MASK (1<<ADPS1_BIT)
|
||||||
|
#define ADPS0_BIT (0)
|
||||||
|
#define ADPS0_MASK (1<<ADPS0_BIT)
|
||||||
|
#define ADSC_BIT (6)
|
||||||
|
#define ADSC_MASK (1<<ADSC_BIT)
|
||||||
|
#define ADIF_BIT (4)
|
||||||
|
#define ADIF_MASK (1<<ADIF_BIT)
|
||||||
|
#define ADIE_BIT (3)
|
||||||
|
#define ADIE_MASK (1<<ADIE_BIT)
|
||||||
|
#define ADATE_BIT (5)
|
||||||
|
#define ADATE_MASK (1<<ADATE_BIT)
|
||||||
|
|
||||||
|
void adc_init(void);
|
||||||
|
uint16_t get_adc_value(void);
|
||||||
|
|
||||||
|
#endif /*DEVICE_C_H*/
|
39
main.c
39
main.c
@ -1,39 +0,0 @@
|
|||||||
/*
|
|
||||||
* main.c
|
|
||||||
*
|
|
||||||
* Created: 18.06.2023 19:53:46
|
|
||||||
* Author: Lada Yuzhakova
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "UART.h"
|
|
||||||
#include "modbus.h"
|
|
||||||
#include "timer.h"
|
|
||||||
#include "device_adc.h"
|
|
||||||
#include "device_ring_buffer.h"
|
|
||||||
#include "gpio.h"
|
|
||||||
#include <avr/io.h>
|
|
||||||
|
|
||||||
int main(void)
|
|
||||||
{
|
|
||||||
// Èíèöèàëèçàöèè
|
|
||||||
adc_init();
|
|
||||||
uart_initialize();
|
|
||||||
modbus_init();
|
|
||||||
gpio_init();
|
|
||||||
rb_initialize(get_rb_receive());
|
|
||||||
rb_initialize(get_rb_transmit());
|
|
||||||
// Çàïóñêàåì òàéìåð
|
|
||||||
setup_timer();
|
|
||||||
|
|
||||||
while(1)
|
|
||||||
{
|
|
||||||
// Ôóíêöèÿ ïðèåìà ìîäáàñ-çàïðîñà
|
|
||||||
modbus_rtu();
|
|
||||||
// Ôóíêöèÿ ôîðìèðîâàíèÿ ìîäáàñ-îòâåòà
|
|
||||||
modbus_answer();
|
|
||||||
// Îòïðàâëÿòü îòâåò ïî óàðò
|
|
||||||
UART_Transmit(get_rb_transmit());
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
360
modbus.c
360
modbus.c
@ -1,360 +0,0 @@
|
|||||||
|
|
||||||
#define On 1
|
|
||||||
#define Off 0
|
|
||||||
#define Change_output 10
|
|
||||||
#define discrete_output_reading 11
|
|
||||||
|
|
||||||
|
|
||||||
volatile unsigned char Data_Rx_ModbasRtu[30];//массив принятых данных
|
|
||||||
volatile unsigned char quantity_Data_ModbasRtu; //количество принятых данных
|
|
||||||
//Volatile — ключевое слово языков C/C++, которое информирует компилятор о том, что значение переменной может меняться извне и что компилятор не будет оптимизировать эту переменную
|
|
||||||
volatile unsigned int Data_ModbasRtu_analog_input[1]; //данные на аналоговом входе [1 - НОМЕР АНАЛОГОВОГО ВХОДА]
|
|
||||||
volatile unsigned int Data_ModbasRtu_analog_Output[1]; //данные на аналоговом выходе [1 - НОМЕР АНАЛОГОВОГО ВЫХОДА]
|
|
||||||
volatile unsigned char Data_ModbasRtu_Binary_input[(1/8)+1]; //данные на дискретном входе [1 - НОМЕР ДИСКРЕТНОГО ВХОДА]
|
|
||||||
volatile unsigned char Data_ModbasRtu_Binary_Output[(1/8)+1]; //данные на дискретном выходе [1 - НОМЕР ДИСКРЕТНОГО ВЫХОДА]
|
|
||||||
|
|
||||||
|
|
||||||
//ПРИНЯТЬ ДАННЫЕ С КОЛЬЦЕВОГО БУФЕРА(Data_Rx_ModbasRtu)
|
|
||||||
//выглядит как int rb_get(struct rb* _rb, char *element)
|
|
||||||
Data_Rx_ModbasRtu = rb_get(&, 1);
|
|
||||||
|
|
||||||
|
|
||||||
//КОНТРОЛЬНАЯ СУММА(+)
|
|
||||||
int crc_chk(unsigned char* data, unsigned char length)
|
|
||||||
{
|
|
||||||
register int j; // register - спецификатор, который предполагает, что доступ к объекту будет быстрым
|
|
||||||
register unsigned int reg_crc = 0xFFFF; //объявление 16-битного регистра
|
|
||||||
while (length--)
|
|
||||||
{
|
|
||||||
reg_crc ^= *data++; //каждый байт-исключение складывается по исключающему ИЛИ с текущим значением регистра контр суммы. После последнего 8 сдвига следующий байт складывается с текущей величиной регистра контр суммы и процесс сдвига повторяется повторно 8 раз
|
|
||||||
for (j = 0; j < 8; j++)
|
|
||||||
{
|
|
||||||
if (reg_crc & 0x01) //проверка младшего бита
|
|
||||||
{
|
|
||||||
reg_crc = (reg_crc >> 1) ^ 0xA001; //проверочный код на основе полинома. Результат всегда сдвигается в сторону младшего бита с заполнением нулем старшего бита. Если младший бит = 1, то производится искл ИЛИ содержимого регистра контр суммы и полиномиального числа
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
reg_crc = reg_crc >> 1; //если младший бит = 0, искл ИЛИ не делается
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return reg_crc; //регистр хранения конечного результата контр суммы
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//ОБЪЕДИНЕНИЕ ДВУХ БАЙТ(старшего и младшего)
|
|
||||||
int ModbasRtu_Register_address(unsigned char Li)
|
|
||||||
//Hi - старший байт
|
|
||||||
//Li - младший
|
|
||||||
{
|
|
||||||
register char Hi = Li - 1;
|
|
||||||
return Data_Rx_ModbasRtu[Hi] * 256 + Data_Rx_ModbasRtu[Li]; //считываем адрес старшего и младшего байта
|
|
||||||
}
|
|
||||||
|
|
||||||
//АДРЕС
|
|
||||||
int Modbus_addr()
|
|
||||||
{
|
|
||||||
volatile unsigned int adres;
|
|
||||||
adres = ModbasRtu_Register_address(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
//ПРОВЕРКА КОНТРОЛЬНОЙ СУММЫ В ПОЛУЧЕННОЙ ПОСЫЛКЕ ДАННЫХ
|
|
||||||
char Data_integrity()
|
|
||||||
{
|
|
||||||
register unsigned int Temp_2;
|
|
||||||
register unsigned char Temp_3;
|
|
||||||
quantity_Data_ModbasRtu = quantity_Data_ModbasRtu - 2; //убираем контрольную сумму от адресов
|
|
||||||
Temp_2 = crc_chk(Data_Rx_ModbasRtu, quantity_Data_ModbasRtu); //вычисляем контрольную сумму
|
|
||||||
Temp_3 = Temp_2; //выделяем старший байт с контрольной суммы
|
|
||||||
if (Data_Rx_ModbasRtu[quantity_Data_ModbasRtu] == Temp_3) //сравнимаем с таблицы старший байт с контрольной суммой
|
|
||||||
{
|
|
||||||
quantity_Data_ModbasRtu++; //объем данных увеличается
|
|
||||||
Temp_3 = (Temp_2 >> 8); //сдвиг на 8 бит
|
|
||||||
if (Data_Rx_ModbasRtu[quantity_Data_ModbasRtu] == Temp_3) //старший
|
|
||||||
{
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//РАБОТА С ДИСКРЕТНЫМИ ВХОДАМИ И ВЫВОДАМИ
|
|
||||||
char _Bin_input_Output(register unsigned char NUMBER, register unsigned char state, volatile unsigned char* Masiv, volatile unsigned char Sd)
|
|
||||||
{
|
|
||||||
volatile unsigned char Temp = 0, Temp_1 = 0;
|
|
||||||
while (NUMBER >= 8)
|
|
||||||
{
|
|
||||||
NUMBER = NUMBER - 8;
|
|
||||||
Temp++; //определяем, в каком регистре нужно изменить либо считывать бит
|
|
||||||
}
|
|
||||||
Temp_1 = Masiv[Temp];
|
|
||||||
if (Sd == 10) //выполняется, если нужно изменить бит
|
|
||||||
{
|
|
||||||
if (state == On)
|
|
||||||
Temp_1 |= (1 << NUMBER);
|
|
||||||
else
|
|
||||||
Temp_1 &= ~(1 << NUMBER);
|
|
||||||
Masiv[Temp] = Temp_1;
|
|
||||||
}
|
|
||||||
else //выполняется, если нужно прочитать состояние бита
|
|
||||||
{
|
|
||||||
if (Temp_1 & (1 << NUMBER))
|
|
||||||
NUMBER = 1;
|
|
||||||
else
|
|
||||||
NUMBER = 0;
|
|
||||||
}
|
|
||||||
return NUMBER; //возвращает состояние прочитанного бита
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//КОДЫ ФУНКЦИИ :
|
|
||||||
|
|
||||||
//Чтение значений нескольких регистров флагов 0x01, Чтение значений нескольких дискретных входов 0x02
|
|
||||||
void Reading_Discrete_Output(unsigned char* Massiv, register unsigned char Number_)
|
|
||||||
{
|
|
||||||
volatile unsigned int adres, Number_bits;
|
|
||||||
register unsigned char Temp = 0, Data, Temp2 = 0, adres2 = 0, Temp3 = 2;
|
|
||||||
adres = ModbasRtu_Register_address(3); //адрес регистра, к которому обращается мастер
|
|
||||||
if (adres > Number_) //проверка, что адрес не превышает допустимый
|
|
||||||
{
|
|
||||||
Error_modbasRtu(0x02); //недопустимый адрес
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Number_bits = ModbasRtu_Register_address(5); //количество бит, которые нужно передать
|
|
||||||
while (adres >= 8) //узнаем номер ячейки массива, с которой начнем считывать данные
|
|
||||||
{
|
|
||||||
adres = adres - 8; //по завершению преобразования хранится бит, с которого нужно начинать считывание
|
|
||||||
Temp++; //номер байта в массиве к которому изначально происходит обращение
|
|
||||||
}
|
|
||||||
Data = Massiv[Temp]; //считываем данные
|
|
||||||
//считываем побитно и формируем данные для отправки
|
|
||||||
while (Number_bits > 0) //проверка, что все биты запроса переданы
|
|
||||||
{
|
|
||||||
Number_bits--;
|
|
||||||
if (Data & (1 << adres))
|
|
||||||
{
|
|
||||||
Temp2 |= (1 << adres2);
|
|
||||||
}
|
|
||||||
adres2++;
|
|
||||||
adres++;
|
|
||||||
if (adres2 == 8)
|
|
||||||
{
|
|
||||||
adres2 = 0;
|
|
||||||
Temp3++;
|
|
||||||
Data_Rx_ModbasRtu[Temp3] = Temp2;
|
|
||||||
Temp2 = 0;
|
|
||||||
}
|
|
||||||
if (adres == 8)
|
|
||||||
{
|
|
||||||
adres = 0;
|
|
||||||
Temp++;
|
|
||||||
Data = Massiv[Temp]; //считываем данные
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (adres2 > 0)
|
|
||||||
{
|
|
||||||
Temp3++;
|
|
||||||
Data_Rx_ModbasRtu[Temp3] = Temp2;
|
|
||||||
}
|
|
||||||
Data_Rx_ModbasRtu[2] = Temp3 - 2; //количество переданных байт (без учета адреса и кода команды)
|
|
||||||
Temp3++;
|
|
||||||
check_sum(Temp3); //подсчитаем контрольную сумму для передачи данных
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//Чтение значений нескольких регистров хранения 0x03, Чтение значений нескольких регистров ввода 0x04
|
|
||||||
void Read_analog_input(unsigned char* Massiv, register unsigned char Number_, unsigned char Vt)
|
|
||||||
//Vt - ввод или вывод
|
|
||||||
{
|
|
||||||
volatile unsigned int address, Number_bits, Data;
|
|
||||||
volatile unsigned char Adress = 4;
|
|
||||||
address = ModbasRtu_Register_address(3); //адрес регистра, к которому обращается мастер
|
|
||||||
if (address > Number_) //проверка, что адрес не превышает допустимый
|
|
||||||
{
|
|
||||||
Error_modbasRtu(0x02); //указанный в запросе адрес не существует
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Number_bits = ModbasRtu_Register_address(5); //количество байт, которые нужно передать (старший и младший)
|
|
||||||
Data_Rx_ModbasRtu[2] = Number_bits * 2; //количество байт информащии, которые будут переданы
|
|
||||||
Adress = 3;
|
|
||||||
while (Number_bits > 0)
|
|
||||||
{
|
|
||||||
if (Vt == 1) //определение, что считывать - вход или выход
|
|
||||||
{
|
|
||||||
Data = Data_ModbasRtu_analog_input[address];
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Data = Data_ModbasRtu_analog_Output[address];
|
|
||||||
}
|
|
||||||
address++;
|
|
||||||
Massiv = &Data;
|
|
||||||
Data_Rx_ModbasRtu[Adress++] = Massiv[1]; //считываем старший байт
|
|
||||||
Data_Rx_ModbasRtu[Adress++] = Massiv[0]; //считываем младший байт
|
|
||||||
Number_bits = Number_bits - 1;
|
|
||||||
}
|
|
||||||
check_sum(Adress); //подсчитаем контрольную сумму для передачи данных
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//Запись одного регистра флагов 0x05
|
|
||||||
void Changing_Discrete_Output(void)
|
|
||||||
{
|
|
||||||
register unsigned int address;
|
|
||||||
address = ModbasRtu_Register_address(3); //адрес регистра, к которому обращается мастер
|
|
||||||
if (address > 11) //проверка, что адрес не превышает допустимый [11 - НОМЕР ДИСКРЕТНОГО ВЫХОДА]
|
|
||||||
{
|
|
||||||
Error_modbasRtu(0x02);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (Data_Rx_ModbasRtu[4] == 255)
|
|
||||||
_Bin_input_Output(address, On, Data_ModbasRtu_Binary_Output, Change_output);
|
|
||||||
else
|
|
||||||
_Bin_input_Output(address, Off, Data_ModbasRtu_Binary_Output, Change_output);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//Запись одного регистра хранения 0x06
|
|
||||||
void analog_output_recording(void)
|
|
||||||
{
|
|
||||||
register int address;
|
|
||||||
address = ModbasRtu_Register_address(3);
|
|
||||||
if (address > 11) //[11 - НОМЕР АНАЛОГОВОГО ВЫХОДА]
|
|
||||||
{
|
|
||||||
Error_modbasRtu(0x02);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Data_ModbasRtu_analog_Output[address] = ModbasRtu_Register_address(5); //данные, которые нужно записать
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//ОШИБКА
|
|
||||||
void Error_modbasRtu(volatile unsigned char Temp_Error)
|
|
||||||
{
|
|
||||||
Data_Rx_ModbasRtu[1] |= (1 << 7);
|
|
||||||
Data_Rx_ModbasRtu[2] = Temp_Error; //код ошибки
|
|
||||||
check_sum(3); //подсчитаем контрольную сумму для передачи данных
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//ОТВЕТ КОНТРОЛЬНОЙ СУММЫ
|
|
||||||
void check_sum(register unsigned char Adress)
|
|
||||||
{
|
|
||||||
register unsigned int RC;
|
|
||||||
RC = crc_chk(Data_Rx_ModbasRtu, Adress); //вычисляем контрольную сумму
|
|
||||||
Data_Rx_ModbasRtu[Adress] = RC; //младший байт контрольной суммы
|
|
||||||
Adress++;
|
|
||||||
Data_Rx_ModbasRtu[Adress] = RC >> 8; //старший байт контрольной суммы
|
|
||||||
quantity_Data_ModbasRtu = Adress;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//ФОРМИРУЕМ ДЕЙСТВИЕ И ОТВЕТ НА ПРИНЯТЫЕ КОМАНДЫ ИЛИ ФОРМИРУЕМ ОТВЕТ ОБ ОШИБКАХ
|
|
||||||
void modbasRtu_Answer()
|
|
||||||
{
|
|
||||||
switch (Data_Rx_ModbasRtu[1])
|
|
||||||
{
|
|
||||||
case 1:
|
|
||||||
//Modbus RTU чтение дискретного выхода 0x01
|
|
||||||
Reading_Discrete_Output(Data_ModbasRtu_Binary_Output, 11); //[11 - НОМЕР ДИСКРЕТНОГО ВЫХОДА]
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
//Modbus RTU чтение дискретного входа 0x02
|
|
||||||
Reading_Discrete_Output(Data_ModbasRtu_Binary_input, 11); //[11 - НОМЕР ДИСКРЕТНОГО ВХОДА]
|
|
||||||
break;
|
|
||||||
case 3:
|
|
||||||
|
|
||||||
Read_analog_input(Data_ModbasRtu_analog_Output, 11, 0); //Modbus RTU на чтение аналогового выхода 0x03 [11 - НОМЕР АНАЛОГОВОГО ВЫХОДА]
|
|
||||||
break;
|
|
||||||
case 4:
|
|
||||||
|
|
||||||
Read_analog_input(Data_ModbasRtu_analog_input, 11, 1); //Modbus RTU на чтение аналогового входа 0x04 [11 - НОМЕР АНАЛОГОВОГО ВХОДА]
|
|
||||||
break;
|
|
||||||
case 5:
|
|
||||||
//Modbus RTU на запись дискретного вывода 0x05
|
|
||||||
Changing_Discrete_Output();
|
|
||||||
break;
|
|
||||||
case 6:
|
|
||||||
//Modbus RTU на запись аналогового выхода 0x06
|
|
||||||
analog_output_recording();
|
|
||||||
break;
|
|
||||||
case 15:
|
|
||||||
//Modbus RTU на запись нескольких дискретных выводов 0x0F
|
|
||||||
asm("nop"); //команда протокола, которая предписывает ничего не делать
|
|
||||||
//break;
|
|
||||||
case 16:
|
|
||||||
//Modbus RTU на запись нескольких аналоговых выводов 0x10
|
|
||||||
asm("nop");
|
|
||||||
//break;
|
|
||||||
default:
|
|
||||||
//команды не подерживаются
|
|
||||||
Error_modbasRtu(0x01); //принятый код функции не может быть обработан
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//ПОДПРОГРАММЫ ДЛЯ ОБРАБОТКИ ЗНАЧЕНИЙ
|
|
||||||
|
|
||||||
//прочитать бит входов
|
|
||||||
char read_digital_inputs(volatile unsigned char Temp1)
|
|
||||||
{
|
|
||||||
return _Bin_input_Output(Temp1, On, Data_ModbasRtu_Binary_input, discrete_output_reading); //считать состояние выхода из буферного массива
|
|
||||||
}
|
|
||||||
|
|
||||||
//изменить бит входов
|
|
||||||
void change_digital_inputs(volatile unsigned char Temp1, volatile unsigned char Temp2)
|
|
||||||
{
|
|
||||||
_Bin_input_Output(Temp1, Temp2, Data_ModbasRtu_Binary_input, Change_output);
|
|
||||||
}
|
|
||||||
|
|
||||||
//прочитать бит выходов
|
|
||||||
char read_digital_Output(volatile unsigned char Temp1)
|
|
||||||
{
|
|
||||||
return _Bin_input_Output(Temp1, On, Data_ModbasRtu_Binary_Output, discrete_output_reading); //считать состояние выхода из буферного массива
|
|
||||||
}
|
|
||||||
|
|
||||||
//изменить бит выходов
|
|
||||||
void change_digital_Output(volatile unsigned char Temp1, volatile unsigned char Temp2)
|
|
||||||
{
|
|
||||||
_Bin_input_Output(Temp1, Temp2, Data_ModbasRtu_Binary_Output, Change_output);
|
|
||||||
}
|
|
||||||
|
|
||||||
//записать значение аналоговых выходов
|
|
||||||
void change_analogue_Output(volatile unsigned char nomer, int Data)
|
|
||||||
{
|
|
||||||
Data_ModbasRtu_analog_Output[nomer] = Data;
|
|
||||||
}
|
|
||||||
|
|
||||||
//записать значение аналоговых входов
|
|
||||||
void change_analogue_input(volatile unsigned char nomer, int Data)
|
|
||||||
{
|
|
||||||
Data_ModbasRtu_analog_input[nomer] = Data;
|
|
||||||
}
|
|
||||||
|
|
||||||
//считать значение аналоговых выходов
|
|
||||||
int read_analogue_Output(volatile unsigned char nomer)
|
|
||||||
{
|
|
||||||
return Data_ModbasRtu_analog_Output[nomer];
|
|
||||||
}
|
|
||||||
|
|
||||||
//считать значение аналоговых выходов
|
|
||||||
int read_analogue_input(volatile unsigned char nomer)
|
|
||||||
{
|
|
||||||
return Data_ModbasRtu_analog_input[nomer];
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//(отправить по rb_put в кольцевой буфер ответ)
|
|
||||||
//выглядит как int rb_put(struct rb* _rb, char element)
|
|
||||||
void Data_Modbus_answer()
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
25
modbus.h
25
modbus.h
@ -1,25 +0,0 @@
|
|||||||
|
|
||||||
#ifndef MODBUS_H
|
|
||||||
#define MODBUS_H
|
|
||||||
|
|
||||||
int crc_chk(unsigned char* data, unsigned char length);
|
|
||||||
int ModbasRtu_Register_address(unsigned char Li);
|
|
||||||
char Data_integrity();
|
|
||||||
char _Bin_input_Output(register unsigned char NUMBER, register unsigned char state, volatile unsigned char* Masiv, volatile unsigned char Sd);
|
|
||||||
void Reading_Discrete_Output(unsigned char* Massiv, register unsigned char Number_);
|
|
||||||
void Read_analog_input(unsigned char* Massiv, register unsigned char Number_, unsigned char Vt);
|
|
||||||
void Changing_Discrete_Output(void);
|
|
||||||
void analog_output_recording(void);
|
|
||||||
void Error_modbasRtu(volatile unsigned char Temp_Error);
|
|
||||||
void check_sum(register unsigned char Adress);
|
|
||||||
void modbasRtu_Answer();
|
|
||||||
char read_digital_inputs(volatile unsigned char Temp1);
|
|
||||||
void change_digital_inputs(volatile unsigned char Temp1, volatile unsigned char Temp2);
|
|
||||||
char read_digital_Output(volatile unsigned char Temp1);
|
|
||||||
void change_digital_Output(volatile unsigned char Temp1, volatile unsigned char Temp2);
|
|
||||||
void change_analogue_Output(volatile unsigned char nomer, int Data);
|
|
||||||
void change_analogue_input(volatile unsigned char nomer, int Data);
|
|
||||||
int read_analogue_Output(volatile unsigned char nomer);
|
|
||||||
int read_analogue_input(volatile unsigned char nomer);
|
|
||||||
|
|
||||||
#endif /*MODBUS_H*/
|
|
Loading…
Reference in New Issue
Block a user