Files
Balsam_167/Source/Internal/message.c

304 lines
9.2 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/* Параметры и обработчики 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);
}