new file: .settings/org.eclipse.core.resources.prefs

new file:   Core/Src/modbus.c
	new file:   "\320\235\320\276\320\263\320\270 \320\270 \321\203\321\201\320\270\320\273\320\265\320\275\320\270\320\265.xlsx"
main
dplimin 2023-11-24 14:45:18 +03:00
parent d9f76c68ee
commit 01b5d0a6c8
3 changed files with 553 additions and 0 deletions

View File

@ -0,0 +1,2 @@
eclipse.preferences.version=1
encoding//Core/Src/modbus.c=UTF-8

551
Core/Src/modbus.c 100644
View File

@ -0,0 +1,551 @@
/*
* modbus.c
*
* Created on: 28 пїЅпїЅпїЅ 2018 пїЅ.
* Author: Shukov
*/
// Includes --------------------------------------------------------------------
#include "modbus.h"
#include "my.h"
#include "usart.h"
#include "main.h"
// External function -----------------------------------------------------------
// External variables ----------------------------------------------------------
extern __IO UserData_TypeDef currentData;
#define LO(x) ((uint8_t) ((x) & 0xff))
#define HI(x) ((uint8_t) (((x) >> 8) & 0xff))
//extern __IO uint32_t STATUS;
// Global variables ------------------------------------------------------------
uint8_t iobuf[256];
uint8_t tx[256];
uint8_t timeout;
uint16_t lastbyte; //последний байт в сообщении
uint16_t lastbyteToSend; //последний байт на отправку
uint16_t iolen = 0; // счетчик для буфера
uint8_t ioa; //ваще не шарю нахуя
bool sendreq = false; //влаг готовности к отправке
bool setbaud = false; //при смене скорости условие для переинициализации уарта
extern char pString[16]; // палки шишки - без этого не копирует floatToAscII
extern uint8_t buff[16];
extern int reload_flag; //флаг перегрузки
bool send = true;
__IO uint16_t delayREDE;
__IO bool needSave = false;
__IO bool needParam = false;
__IO bool needReset = false;
__IO bool POVERKA = false;
__IO bool needPoverka = false;
__IO bool needFactory = false;
const int8_t inversely[] = {3, 1, -1,-3};
void StartTransfer(void) //todo жесько отключаю прерывания это неправильно
{
int a = delayREDE;
while(a)
{
a--; a++; a--; a++; a--;
}
HAL_GPIO_WritePin(USART1_RE_GPIO_Port, USART1_RE_Pin, GPIO_PIN_SET); //todo это нужно только п//это ужасная вещь - но обеспечивает постоянный прием
//HAL_UART_Transmit_IT(&huart1, tx, lastbyte);
__disable_irq();
HAL_UART_Transmit(&huart1, tx, lastbyteToSend,100);// возможно не отправит из за того что приемник в прерывании
memset(tx,0,sizeof(tx));
__enable_irq();
HAL_GPIO_WritePin(USART1_RE_GPIO_Port, USART1_RE_Pin, GPIO_PIN_RESET);
Transfer_Complete();
}
void strtOut(uint16_t n)
{
uint16_t crc;
if(tx[0]) // если на отправку что то есть то
{
lastbyteToSend = n + 2; // добавляем 2 байта под CRC
crc = Crc16_TX(n);
tx[n] = LO(crc);
tx[n + 1] = HI(crc); //todo: Внимание костыль & 0xFF!!!! // Добавляем контрольную сумму
sendreq = true; //Устанавливаем флаг требования отправки
}
iolen = 0; // сбрасываем длинну сообщения
}
uint16_t Crc16(uint16_t len)
{
uint16_t i;
uint16_t crc = 0xFFFF;
for(i = 0; i < len; i++) {
crc = (crc >> 8) ^ Crc16Table[(crc & 0xFF) ^ iobuf[i]];
}
return crc;
}
uint16_t Crc16_TX(uint16_t len)
{
uint16_t i;
uint16_t crc = 0xFFFF;
for(i = 0; i < len; i++) {
crc = (crc >> 8) ^ Crc16Table[(crc & 0xFF) ^ tx[i]];
}
return crc;
}
//-----------------------------------------
// пїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅ пїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅ пїЅпїЅпїЅпїЅпїЅ-пїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅ
//-----------------------------------------
void SetBaudRate(){ //todo: сделать установку скорости
timeout = time35[currentData.BAUD];
delayREDE = sendtime[currentData.BAUD];
MX_USART1_UART_DeInit();
MX_USART1_UART_Init();
}
//float32_t tmpf;
uint16_t hp16;
void Transfer_Complete(void)
{
__IO uint16_t a;
a = delayREDE;
while(a)
{
a--; a++; a--; a++; a--; // какая то задержка пусть будет
}
if(setbaud) // наверное нужно для применения новых настроек скорости
{
setbaud = 0;
needSave = true;
SetBaudRate();
}
//__HAL_UART_CLEAR_FLAG(&huart1, UART_FLAG_TC);
HAL_GPIO_WritePin(USART1_RE_GPIO_Port, USART1_RE_Pin, GPIO_PIN_RESET);
}
void Receive_Complete(void){ //я сейчас попробую раскоментировать тебя
// не забывай что команды подаются little endian формате.
/// перенес в надежде на чудо
uint16_t j;
uint8_t *pch;
usshort crc, addr, regs;
usfloat f;
uint8_t tmp, tmp1;
///
timeout = time35[currentData.BAUD]; // какие то мутные таймауты от скорости всегда двойки(((
iobuf[iolen++] = buff[0];
//iobuf[iolen++] = (uint8_t) (USART1->DR & 0xff); // прибывший байт принимаем в из регистра в буфер
if((iobuf[0] == currentData.OWN) || (!iobuf[0])) //если нулевая посылка совпадает с адресом устройства или не равен себе
{
if(iolen > 1)
{
if(iolen == 2) // если длинна сообщения 2
{
switch(iobuf[1]) // смотрим на команды
{
case 0x03: //команда на чтение
lastbyte = 7; //последний байт в сообщении будет 7
break;
case 0x10:
lastbyte = 6; // если на запись то 6
break;
default:
lastbyte = 3; // если не то не то то 3
tx[0] = iobuf[0]; //в отправку заряжаем принятый адрес
tx[1] = (iobuf[1] | 0x80); //берем прешедшую команду и обвосьмериваем - помечаем как ошибку
tx[2] = 0x01; // принятый код функции не может быть обработан
strtOut(3); // на отправку
break;
}
}
if(iolen > lastbyte) //если длинна принятой строки больше чем последний байт
{
switch(iobuf[1]) //смотрим на командц
{
case 0x03: // если команда на чтение
iolen = 0; // ставим счетчик буфера на 0
crc.ch[0] = iobuf[6]; // берем из буфера CRC
crc.ch[1] = iobuf[7];
if(Crc16(6) == crc.sh) // Проверяем её
{
addr.ch[1] = iobuf[2]; //адрес первого регистра hi
addr.ch[0] = iobuf[3]; //lo
regs.ch[1] = iobuf[4]; //колличество регистров hi
regs.ch[0] = iobuf[5]; //колличесво регистров lo
switch(addr.sh) // здесь union
{
case 5001: // 5001 //тип заряда ACP=
case 5002: // 5002 //фильтр верхних частот
case 5003: // 5003 //нижних
case 5004: //IKU 5004 //Коэф усиления
case 5005: //IKE 5005 // Legacy a141
case 5006: //IKD 5006 // Legacy a141
case 5007: //IKS 5007 // Legacy a141
case 5008: //IPZ 5008 // признак плав земли
case 5009: //OPZ 5009 // Legacy a141
case 5010: //UNIT 5010 // Значения
case 5011: //OVERLOAD 5011 // Использую для передачи перегрузки
if(regs.ch[0] > (5012 - addr.sh))
{
tx[0] = iobuf[0];
tx[1] = (iobuf[1] | 0x80);
tx[2] = 0x03;
strtOut(3);
}
else
{
tx[0] = iobuf[0];
tx[1] = iobuf[1];
tx[2] = regs.ch[0] << 1;
pch = (uint8_t *) &currentData.IIN + ((addr.sh - 5001) << 1);
for(j = 0; j < tx[2]; j++)
tx[j + 3] = *(pch + (j ^ 1));
strtOut(3 + tx[2]);
}
break;
case 7004: // Sens
case 7502:
tmp = 2;
tx[0] = iobuf[0];
tx[1] = iobuf[1];
tx[2] = regs.ch[0] << 2;
if(addr.sh == 7004)
{
tmp <<= 1;
tx[2] >>= 1;
}
if(regs.ch[0] > tmp)
{
tx[0] = iobuf[0];
tx[1] = (iobuf[1] | 0x80);
tx[2] = 0x03;
strtOut(3);
}
else
{
f.fl = currentData.SENS;
tx[3] = f.ch[3];
tx[4] = f.ch[2];
tx[5] = f.ch[1];
tx[6] = f.ch[0];
strtOut(3 + tx[2]);
}
break;
default:
tx[0] = iobuf[0];
tx[1] = (iobuf[1] | 0x80);
tx[2] = 0x02;
strtOut(3);
break;
}
}
break;
case 0x10: // //запрос на запись
addr.ch[1] = iobuf[2];
addr.ch[0] = iobuf[3];
regs.ch[1] = iobuf[4];
regs.ch[0] = iobuf[5];
switch(addr.sh) // Запись pardata
{
case 4001: // 4001 //тип заряда ACP=
case 4002: // 4002 //фильтр верхних частот
case 4003: // 4003 //нижних
{
if((regs.ch[0] > (4004 - addr.sh)) || (iobuf[6] != (regs.ch[0] << 1)))
{
tx[0] = iobuf[0];
tx[1] = (iobuf[1] | 0x80);
tx[2] = 0x03;
strtOut(3);
}
else
{
j = 8 + iobuf[6];
if(iolen > j)
{
iolen = 0;
crc.ch[0] = iobuf[j - 1];
crc.ch[1] = iobuf[j];
if(crc.sh == Crc16(j - 1))
{
UserData_TypeDef recivedData =currentData;
pch = (uint8_t *) &recivedData.OWN + ((addr.sh - 4001) << 1);
for(j = 0; j < iobuf[6]; j++)
*(pch + (j ^ 1)) = iobuf[j + 7];
if((recivedData.OWN > 247) || (recivedData.BAUD > 9) || (recivedData.INFB > 2))
{
tx[0] = iobuf[0];
tx[1] = (iobuf[1] | 0x80);
tx[2] = 0x03;
strtOut(3);
}
else //если значения корректны
{
currentData=recivedData; //Пишем значения в рабочую структуру
if(!iobuf[0]) //если широковешательная то не отвечаем
{
setbaud = false; // снимаем флаг следующей смены
needSave = true; // ставим флаг надобности сохранения
SetBaudRate(); // устанавливаем свойства связи
}
else
{
setbaud = true; // по колбеку ТХ переинициализируем УАРТ
for(j = 0; j < 6; j++) {
tx[j] = iobuf[j];
}
strtOut(6);
}
}
}
}
}
}
break;
case 5001: // 5001 //тип заряда ACP=
case 5002: // 5002 //фильтр верхних частот
case 5003: // 5003 //нижних
case 5004: //IKU 5004 //Коэф усиления
case 5005: //IKE 5005 // Legacy a141
case 5006: //IKD 5006 // Legacy a141
case 5007: //IKS 5007 // Legacy a141
case 5008: //IPZ 5008 // признак плав земли
case 5009: //OPZ 5009 // Legacy a141
case 5010: //UNIT 5010 // Значения
if((regs.ch[0] > (5011 - addr.sh)) || (iobuf[6] != (regs.ch[0] << 1)))
{
tx[0] = iobuf[0];
tx[1] = (iobuf[1] | 0x80);
tx[2] = 0x03;
strtOut(3);
}
else
{
j = 8 + iobuf[6];
if(iolen > j)
{
iolen = 0;
crc.ch[0] = iobuf[j - 1];
crc.ch[1] = iobuf[j];
if(crc.sh == Crc16(j - 1))
{
UserData_TypeDef recivedData =currentData; // должно работать как копирование
pch = (uint8_t *) &recivedData.IIN + ((addr.sh - 5001) << 1);
for(j = 0; j < iobuf[6]; j++)
*(pch + (j ^ 1)) = iobuf[j + 7];
if((recivedData.IIN > 0) || (recivedData.IKU > Ku1000) || (recivedData.IFV > Hp10)
|| (recivedData.IFN > Lp100000) || (recivedData.UNIT > H) || (recivedData.IPZ > 1)|| (recivedData.OVERLOAD > 1))
{
tx[0] = iobuf[0];
tx[1] = (iobuf[1] | 0x80);
tx[2] = 0x03;
strtOut(3);
}
else
{
currentData=recivedData; // значения правильные копируем в рабочую структуру
needSave = true;
if(iobuf[0]) //если адрес не широковещательный отвечаем
{
for(j = 0; j < 6; j++) {
tx[j] = iobuf[j];
}
strtOut(6);
}
}
}
}
}
break;
case 7004: // Запись Sens
case 7502:
tmp = 2;
tmp1 = 2;
if(addr.sh == 7004)
{
tmp <<= 1;
tmp1 = 1;
}
if((regs.ch[0] > tmp) || (iobuf[6] != (regs.ch[0] << tmp1)))
{
tx[0] = iobuf[0];
tx[1] |= 0x80; //модификация кода функции на ошибку
tx[2] = 0x03; //Адрес данных указанный в запросе не доступен
strtOut(3);
}
else
{
j = 8 + iobuf[6];
if(iolen > j)
{
crc.ch[0] = iobuf[j - 1];
crc.ch[1] = iobuf[j];
if(crc.sh == Crc16(j - 1))
{
if(iobuf[6] == 4)
{
for(j = 0; j < 4; j++)
f.ch[3 - j] = iobuf[7 + j];
//ввести проверку и прочую чепуху
currentData.SENS = f.fl;
if(currentData.SENS==1000) {
currentData.IK0=1;
currentData.IK1=0;
currentData.IK2=0;
currentData.IK3=0;
currentData.IK4='~';
currentData.IK5=0;
}
else if(currentData.SENS<1000&&currentData.SENS>=100) {
char str[20] = {0};
strcpy(str, FloatToASCII(currentData.SENS, -2));
currentData.IK0=str[0]-48;
currentData.IK1=str[1]-48;
currentData.IK2=str[2]-48;
currentData.IK3='~';//str[3];
currentData.IK4=str[4]-48;
currentData.IK5=str[5]-48;
}
else if(currentData.SENS<100&&currentData.SENS>=10)
{
char str[20] = {0};
strcpy(str, FloatToASCII(currentData.SENS, -3));
currentData.IK0=str[0]-48;
currentData.IK1=str[1]-48;
currentData.IK2=str[2];
currentData.IK3=str[3]-48;
currentData.IK4=str[4]-48;
currentData.IK5=str[5]-48;
}
else //if(currentData.SENS<10);
{
char str[20] = {0};
strcpy(str, FloatToASCII(currentData.SENS, -4));
currentData.IK0=str[0]-48;
currentData.IK1=str[1];
currentData.IK2=str[2]-48;
currentData.IK3=str[3]-48;
currentData.IK4=str[4]-48;
currentData.IK5=str[5]-48;
}
needSave = true;
strtOut(6);
}
else
if(iobuf[6] == 8)
{
/*for(j = 0; j < 4; j++)
f.ch[3 - j] = iobuf[3 + j];
pardata.SENS = f.fl;*/
//Если сюда попали то что то идет не так
for(j = 0; j < 4; j++)
f.ch[3 - j] = iobuf[7 + j];
currentData.ACCEL = f.fl;
needSave = true;
strtOut(6);
}
else
{
tx[0] = iobuf[0];
tx[1] |= 0x80; //модификация кода функции на ошибку
tx[2] = 0x03; //Адрес данных указанный в запросе не доступен
strtOut(3);
}
}
}
}
break;
default://Команда неопознана
tx[0] = iobuf[0];
tx[1] |= 0x80; //модификация кода функции на ошибку
tx[2] = 0x02; //Адрес данных указанный в запросе не доступен
strtOut(3);
break;
}
break;
}
}
}
}
}

Binary file not shown.