Files
Balsam_167/Source/Internal/message.c
T

304 lines
9.2 KiB
C

/* Параметры и обработчики Modbus после проверки CRC. Массив modbus
* содержит обычные адреса 0..127, область 0x1000 обслуживает логгер.
* EEPROM хранит параметры, но не является источником START/STOP:
* при загрузке сохраняется последняя живая команда нагрузки.
* Функции вызываются из main; EEPROM блокирует этот контекст.
*/
#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"
#include "log_to_mem.h"
#include "DAC.h"
int modbus[ANSWER_LEN+1];
unsigned int param[ANSWER_LEN+1];
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++)
{
/* Команда нагрузки не является параметром по умолчанию. */
if (Desk != dsk_LOAD || i != 127) Modbus[i].all = 0;
}
UMP_reset_parameter_commands();
LastMode = Mode;
if(Desk == dsk_EPLT)
{
Cancount[m_FAST] = 10; // Задаёт для пульта быстрый CAN-пакет раз в 10 базовых интервалов CANPOWSE по 20 мс, то есть примерно 200 мс; это значение по умолчанию, которое могут заменить параметры EEPROM.
for(i=0;i<6;i++) Bright[i] = bright[i];
}
else
{
Cancount[m_FAST] = 10; // пауза между посылками CAN
Brightness = 8;
}
Cancount[m_SLOW] = 101; // пауза между посылками CAN
if(Kalibro)
{
def = Mode-3;
if(Mode==adr_SHKF) def=4;
for(i=0;i<8;i++) Caliber[i] = def_cal[def][i];
}
if(Desk == dsk_COMM)
{
for(i=0;i<TPL_POW*2;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();
}
/* CRC и Mode проверяются до применения EEPROM. Слово 127
* нагрузки не копируется даже временно: ISR не должен увидеть
* старый START из EEPROM либо потерять текущую CAN-команду.
*/
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]))
{
/* Не восстанавливать START/STOP из EEPROM даже на один тик ISR. */
for(i=0;i<ANSWER_LEN;i++)
if (Desk != dsk_LOAD || i != 127) modbus[i] = param[i];
UMP_reset_parameter_commands();
}
else
{
Default_params();
UMP_reset_parameter_commands();
Save_params();
if(Desk == dsk_COMM)
{
cTermoCal = 1;
Caliber_time = 0xFFFF;
} } }
/* ISR продолжает менять измерения во время сбора param. CRC
* относится к собранному массиву, а не атомарному снимку всей платы.
* Не вызывать сохранение из критического пути дискретов.
*/
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
Чтение ачеек данных */
/***************************************************************/
/***************************************************************/
static void modbus_exception(RS_DATA *rs_arr, unsigned int function, unsigned int error)
{
unsigned int crc;
rs_arr->buffer[0] = CNTRL_ADDR;
rs_arr->buffer[1] = function | 0x80;
rs_arr->buffer[2] = error;
crc = get_crc_16(0xFFFF, rs_arr->buffer, 3);
rs_arr->buffer[3] = LOBYTE(crc); rs_arr->buffer[4] = HIBYTE(crc);
rs_arr->flag_TIMEOUT_to_Send = true;
RS_Send(rs_arr, rs_arr->buffer, 5);
}
void ReceiveCommandModbus3(RS_DATA *rs_arr)
{
unsigned int crc, Address_MB, Length_MB, i, value, saved = 0;
// получили начальный адрес чтениа
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];
if (!Length_MB || Length_MB > 125 ||
!((Address_MB < ANSWER_LEN && Length_MB <= ANSWER_LEN-Address_MB) ||
(Address_MB >= UMP_LOG_BASE && Address_MB <= UMP_LOG_BASE+15 &&
Length_MB <= UMP_LOG_BASE+16-Address_MB) ||
(Address_MB >= UMP_LOG_DATA && Address_MB < UMP_LOG_DATA+120 &&
Length_MB <= UMP_LOG_DATA+120-Address_MB) ||
(Address_MB == UMP_LOG_LIVE && Length_MB == 124))) {
modbus_exception(rs_arr, CMD_MODBUS_3, 2); return;
}
/////////////////////////////////////////////////
// Отсылка
/* Посчитали контрольную сумму перед самой посылкой */
rs_arr->buffer[0] = CNTRL_ADDR;
rs_arr->buffer[1] = CMD_MODBUS_3;
rs_arr->buffer[2] = Length_MB*2;
/* Защищаем целостность одного снимка/блока; передача UART идёт уже
* с разрешёнными прерываниями и не задерживает измерение/управление. */
if (Address_MB >= UMP_LOG_BASE) saved = __disable_interrupts();
for (i=0;i<Length_MB;i++)
{
value = Address_MB >= UMP_LOG_BASE ? ump_log_read(Address_MB+i) : modbus[Address_MB+i];
rs_arr->buffer[3+i*2] = (value >> 8) & 0xFF;
rs_arr->buffer[3+i*2+1] = value & 0xFF;
}
if (Address_MB >= UMP_LOG_BASE) __restore_interrupts(saved);
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;
/* Расширение логгера отвечает точным кадром Modbus без хвостовых
* нулей: они иначе попали бы в начало ответа следующего блока GUI.
* Исторический формат технологических регистров оставлен прежним. */
RS_Send(rs_arr, rs_arr->buffer, Length_MB*2+(Address_MB >= UMP_LOG_BASE ? 5 : 8));
return;
}
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];
if (Address_MB >= UMP_LOG_BASE) {
if (!ump_log_write(Address_MB, Data_MB)) {
modbus_exception(rs_arr, CMD_MODBUS_6, 3); return;
}
} else if (Address_MB < ANSWER_LEN) {
/* RS и CAN используют одну историю фронтов. Чередование каналов
* не создаёт двух независимых повторных запусков. */
if (Address_MB == 127) {
UMP_commands_write(Data_MB);
ump_log_rs();
} else Modbus[Address_MB].all = Data_MB;
} else { modbus_exception(rs_arr, CMD_MODBUS_6, 2); return; }
rs_arr->flag_TIMEOUT_to_Send=true;
RS_Send(rs_arr, rs_arr->buffer, Address_MB >= UMP_LOG_BASE ? 8 : 10);
}