343 lines
9.8 KiB
C
343 lines
9.8 KiB
C
/**
|
||
* @file message.c
|
||
* @brief Параметры устройства и прикладные сообщения протокола Modbus.
|
||
*
|
||
* Инициализирует значения по умолчанию, загружает и сохраняет параметры в
|
||
* EEPROM, принимает команды функций 3/6 и формирует ответы функции 4.
|
||
* Индексы param/Modbus согласованы с внешней картой регистров; менять порядок,
|
||
* ANSWER_LEN или представление слов можно только вместе с ведущей системой.
|
||
*/
|
||
#include "DSP2833x_Device.h" // DSP2833x Headerfile Include File
|
||
#include "package.h"
|
||
#include "RS485.h"
|
||
#include "crc16.h"
|
||
#include "cntrl_adr.h"
|
||
#include "bios_dsp.h"
|
||
#include "message.h"
|
||
#include "filter_bat2.h"
|
||
#include "measure.h"
|
||
|
||
|
||
#include "ADC.h"
|
||
#include "peripher.h"
|
||
|
||
#include "ecan.h"
|
||
#include "pulto.h"
|
||
#include "spise2p.h"
|
||
|
||
#include "caliber.h"
|
||
|
||
/** @brief Рабочий образ регистров Modbus, передаваемый внешнему мастеру. */
|
||
int modbus[ANSWER_LEN+1];
|
||
/** @brief Сохраняемые параметры, индексно согласованные с картой регистров. */
|
||
unsigned int param[ANSWER_LEN+1];
|
||
|
||
/**
|
||
* @brief Создаёт полный набор безопасных параметров для текущего варианта платы.
|
||
* @post Modbus/param, режимы, пороги, яркость и калибровки имеют штатные значения.
|
||
* @details Начальная очистка предотвращает сохранение мусора в зарезервированных
|
||
* регистрах; далее значения выбираются по Desk и compile-time конфигурации.
|
||
*/
|
||
void Default_params()
|
||
{
|
||
unsigned int i,def;
|
||
|
||
int shkf_lo_edge[] = {300, // 380
|
||
300, // 38O
|
||
0, // 0
|
||
0, // 0
|
||
15, // 31
|
||
22, // 27
|
||
20, // 24
|
||
10, // 15
|
||
60}; // AD
|
||
|
||
int bright[] = {10,8,6,8,6,8};
|
||
|
||
for(i=0;i<ANSWER_LEN;i++)
|
||
{
|
||
Modbus[i].all = 0;
|
||
}
|
||
|
||
LastMode = Mode;
|
||
|
||
if(Desk == dsk_EPLT)
|
||
{
|
||
Cancount[m_FAST] = 2; // пауза между посылками CAN
|
||
|
||
for(i=0;i<6;i++) Bright[i] = bright[i];
|
||
}
|
||
else
|
||
{
|
||
Cancount[m_FAST] = 10; // пауза между посылками CAN
|
||
Brightness = 8;
|
||
}
|
||
|
||
Cancount[m_SLOW] = 101; // пауза между посылками CAN
|
||
|
||
if(Owen) Owncount = 20; // пауза между опросами OWEN
|
||
|
||
if(Kalibro)
|
||
{
|
||
#ifdef CALIB_RS
|
||
def = Mode-1;
|
||
if(Mode>adr_PULT) def--;
|
||
#else
|
||
def = Mode-3;
|
||
if(Mode==adr_SHKF) def=4;
|
||
#endif
|
||
for(i=0;i<8;i++) Caliber[i] = def_cal[def][i];
|
||
}
|
||
|
||
if(Desk == dsk_COMM)
|
||
{
|
||
for(i=0;i<TPL_POW*2+Owen;i++)
|
||
{
|
||
sens_hi_edge[i] = 70;
|
||
sens_lo_edge[i] = 60;
|
||
} }
|
||
|
||
if(Desk==dsk_BKSD)
|
||
{
|
||
for(i=0;i<6;i++)
|
||
{
|
||
sens_hi_edge[i] = 170;
|
||
sens_lo_edge[i] = 150;
|
||
}
|
||
for(i=6;i<8;i++)
|
||
{
|
||
sens_hi_edge[i] = 115;
|
||
sens_lo_edge[i] = 105;
|
||
} }
|
||
|
||
if(Desk==dsk_BKST)
|
||
for(i=0;i<TPL_TRN*2;i++)
|
||
{
|
||
sens_hi_edge[i] = 70;
|
||
sens_lo_edge[i] = 60;
|
||
}
|
||
|
||
if(Mode==adr_SHKF)
|
||
{
|
||
for(i=0;i<15;i++) sens_lo_edge[i] = shkf_lo_edge[sens_type[i]];
|
||
|
||
sens_hi_edge[13] = 70;
|
||
sens_hi_edge[14] = 70;
|
||
}
|
||
|
||
if(Desk==dsk_LOAD)
|
||
{
|
||
sens_hi_edge[0] = 420;
|
||
sens_hi_edge[1] = 420;
|
||
sens_hi_edge[2] = 900;
|
||
sens_hi_edge[3] = 900;
|
||
sens_lo_edge[0] = 300;
|
||
sens_lo_edge[1] = 300;
|
||
sens_lo_edge[2] = 800;
|
||
sens_lo_edge[3] = 800;
|
||
|
||
DAC_20 = Caliber[6];
|
||
DAC_04 = Caliber[7];
|
||
|
||
/* Не врема!
|
||
DAC_go = 6; // начало зарада
|
||
DAC_stop= 15; // конец зарада
|
||
*/
|
||
}
|
||
|
||
if(Kurrent)
|
||
for(i=0;i<4;i++)
|
||
Zero_lev[i] = 0x800;
|
||
|
||
Init_sensors_more();
|
||
}
|
||
|
||
/**
|
||
* @brief Загружает параметрический блок из EEPROM и проверяет его целостность.
|
||
* @details При несовпадении сигнатуры/CRC вызывается Default_params(); после
|
||
* успешной загрузки значения переносятся в рабочие глобальные настройки.
|
||
*/
|
||
void Load_params()
|
||
{
|
||
unsigned int i,crc;
|
||
|
||
Seeprom_read(0x3FFF-(ANSWER_LEN+1), param, (ANSWER_LEN+1)*2);
|
||
crc = get_crc16(param,ANSWER_LEN);
|
||
if( (crc==param[ANSWER_LEN]) &&
|
||
(crc !=0xFFFF) &&
|
||
(Mode == param[126]) )
|
||
{
|
||
for(i=0;i<ANSWER_LEN;i++) modbus[i] = param[i];
|
||
Commands=0;
|
||
}
|
||
else
|
||
{
|
||
Default_params();
|
||
Commands=0;
|
||
Save_params();
|
||
if(TermoSW)
|
||
{
|
||
cTermoCal =1;
|
||
Caliber_time = 0xFFFF;
|
||
} } }
|
||
|
||
/**
|
||
* @brief Формирует параметрический блок с CRC и записывает его в EEPROM.
|
||
* @warning Запись следует запускать только при свободном драйвере EEPROM;
|
||
* питание должно сохраняться до физического завершения транзакции.
|
||
*/
|
||
void Save_params()
|
||
{
|
||
unsigned int i,dif=0;
|
||
|
||
for(i=0;i<ANSWER_LEN;i++)
|
||
if(param[i] != modbus[i])
|
||
{
|
||
param[i] = modbus[i];
|
||
dif=1;
|
||
}
|
||
if(dif)
|
||
{
|
||
param[ANSWER_LEN] = get_crc16(param,ANSWER_LEN);
|
||
Seeprom_write(0x3FFF-(ANSWER_LEN+1),param,(ANSWER_LEN+1)*2);
|
||
} }
|
||
|
||
/***************************************************************/
|
||
/***************************************************************/
|
||
/* Передача данных по протоколу ModBus - команда 3
|
||
Чтение ачеек данных */
|
||
/***************************************************************/
|
||
/***************************************************************/
|
||
|
||
/**
|
||
* @brief Обрабатывает запрос Modbus чтения диапазона регистров.
|
||
* @param rs_arr Порт с проверенным входным кадром и буфером ответа.
|
||
* @details Проверяет начальный адрес и длину, копирует слова из modbus и
|
||
* формирует CRC непосредственно перед отправкой.
|
||
*/
|
||
void ReceiveCommandModbus3(RS_DATA *rs_arr)
|
||
{
|
||
unsigned int crc, Address_MB, Length_MB, i;
|
||
|
||
// получили начальный адрес чтениа
|
||
Address_MB =/*(rs_arr->RS_Header[2] << 8) |*/ rs_arr->RS_Header[3];
|
||
|
||
// получили количество слов данных
|
||
Length_MB = (rs_arr->RS_Header[4] << 8) | rs_arr->RS_Header[5];
|
||
|
||
/////////////////////////////////////////////////
|
||
// Отсылка
|
||
/* Посчитали контрольную сумму перед самой посылкой */
|
||
|
||
rs_arr->buffer[0] = CNTRL_ADDR;
|
||
rs_arr->buffer[1] = CMD_MODBUS_3;
|
||
rs_arr->buffer[2] = Length_MB*2;
|
||
|
||
for (i=0;i<Length_MB;i++)
|
||
{
|
||
rs_arr->buffer[3+i*2 ]=(Modbus[Address_MB+i].byt.byte_hi);
|
||
rs_arr->buffer[3+i*2+1]=(Modbus[Address_MB+i].byt.byte_lo);
|
||
}
|
||
|
||
crc = 0xffff;
|
||
crc = get_crc_16(crc, rs_arr->buffer, Length_MB*2+3);
|
||
|
||
rs_arr->buffer[Length_MB*2+3] = LOBYTE(crc);
|
||
rs_arr->buffer[Length_MB*2+4] = HIBYTE(crc);
|
||
|
||
rs_arr->buffer[Length_MB*2+5] = 0;
|
||
rs_arr->buffer[Length_MB*2+6] = 0;
|
||
rs_arr->buffer[Length_MB*2+7] = 0;
|
||
rs_arr->buffer[Length_MB*2+8] = 0;
|
||
|
||
rs_arr->flag_TIMEOUT_to_Send=true;
|
||
RS_Send(rs_arr, rs_arr->buffer, Length_MB*2+8);
|
||
|
||
return;
|
||
}
|
||
|
||
/**
|
||
* @brief Применяет команду записи одного параметра Modbus.
|
||
* @details После проверки адреса обновляет разрешённое значение, выставляет
|
||
* события перенастройки/сохранения и возвращает эхо принятой команды.
|
||
*/
|
||
void ReceiveCommandModbus6(RS_DATA *rs_arr)
|
||
{
|
||
unsigned int Address_MB, Data_MB, i;
|
||
|
||
/////////////////////////////////////////////////
|
||
// Отсылка
|
||
/* Отправлаем назад то же самое */
|
||
|
||
for (i=0;i<8;i++)
|
||
rs_arr->buffer[i] = rs_arr->RS_Header[i];
|
||
|
||
|
||
// получили начальный адрес записи
|
||
Address_MB = (/*(rs_arr->RS_Header[2] << 8) | */rs_arr->RS_Header[3]);
|
||
|
||
// получили слово данных
|
||
Data_MB = (rs_arr->RS_Header[4] << 8) | rs_arr->RS_Header[5];
|
||
|
||
Modbus[Address_MB].all = Data_MB;
|
||
|
||
rs_arr->flag_TIMEOUT_to_Send=true;
|
||
RS_Send(rs_arr, rs_arr->buffer, 10);
|
||
}
|
||
|
||
/**
|
||
* @brief Формирует периодический запрос/ответ функции 4 для внешнего устройства.
|
||
* @details Адрес, полезная нагрузка и CRC помещаются в буфер выбранного RS-порта,
|
||
* после чего передача запускается неблокирующим RS_Send().
|
||
*/
|
||
void SendCommandModbus4(RS_DATA *rs_arr)
|
||
{
|
||
unsigned int crc;
|
||
|
||
/////////////////////////////////////////////////
|
||
// Отсылка
|
||
|
||
rs_arr->buffer[0] = 16;
|
||
rs_arr->buffer[1] = 4;
|
||
rs_arr->buffer[2] = 0;
|
||
rs_arr->buffer[3] = 0;
|
||
rs_arr->buffer[4] = 0;
|
||
rs_arr->buffer[5] = 48;
|
||
|
||
crc = 0xffff;
|
||
crc = get_crc_16(crc, rs_arr->buffer, 6);
|
||
|
||
rs_arr->buffer[6] = LOBYTE(crc);
|
||
rs_arr->buffer[7] = HIBYTE(crc);
|
||
|
||
//rs_arr->buffer[8] = 0;
|
||
//rs_arr->buffer[9] = 0;
|
||
//rs_arr->buffer[10] = 0;
|
||
|
||
rs_arr->flag_TIMEOUT_to_Send=true;
|
||
RS_Send(rs_arr, rs_arr->buffer, 8);
|
||
}
|
||
|
||
/**
|
||
* @brief Разбирает ответ внешнего измерителя на функцию Modbus 4.
|
||
* @details Проверяет формат и переносит температуры/диагностики в ext_temp и
|
||
* ext_diag; некорректный ответ не должен заменять последний пригодный снимок.
|
||
*/
|
||
void ReceiveAnswerModbus4(RS_DATA *rs_arr)
|
||
{
|
||
unsigned int i;
|
||
|
||
/////////////////////////////////////////////////
|
||
// Отсылка
|
||
|
||
for (i=0;i<8;i++)
|
||
{
|
||
ext_temp[i] = ( rs_arr->RS_Header[5+i*12] << 8) +
|
||
rs_arr->RS_Header[6+i*12];
|
||
|
||
ext_diag[i] = ( rs_arr->RS_Header[7+i*12] |
|
||
rs_arr->RS_Header[8+i*12] ) != 0;
|
||
} }
|
||
|
||
|