diff --git a/.settings/org.eclipse.core.resources.prefs b/.settings/org.eclipse.core.resources.prefs new file mode 100644 index 0000000..096b822 --- /dev/null +++ b/.settings/org.eclipse.core.resources.prefs @@ -0,0 +1,2 @@ +eclipse.preferences.version=1 +encoding//Core/Src/modbus.c=UTF-8 diff --git a/Core/Src/modbus.c b/Core/Src/modbus.c new file mode 100644 index 0000000..dcfdc05 --- /dev/null +++ b/Core/Src/modbus.c @@ -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 *) ¤tData.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&¤tData.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&¤tData.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; + } + } + } + } +} + + + + diff --git a/Ноги и усиление.xlsx b/Ноги и усиление.xlsx new file mode 100644 index 0000000..d376c5a Binary files /dev/null and b/Ноги и усиление.xlsx differ