22 Commits

Author SHA1 Message Date
5cbffd3674 Добавлены служебные файлы и второй бэкап john103C8T6 2026-06-26 15:24:44 +03:00
0692b21d9b Добавлены драйверы и периферийные библиотеки 2026-06-26 15:24:29 +03:00
ce169b9cb9 Добавлен ядро прошивки john103C6T6_F4 2026-06-26 15:24:23 +03:00
60d4d4d257 Добавлен модбас-модуль для john103C6T6_F4 2026-06-26 15:23:56 +03:00
0db33b3837 Добавлен лог ошибок сборки сервера 2026-06-26 15:23:33 +03:00
41a50a1d1e добавил gui 2026-06-25 17:25:41 +03:00
cdd8fc3f71 сделал новую версию рабаем с 0 2026-06-25 11:21:08 +03:00
f695867969 настройка 2 uart одни на слейв другой на мастер 2026-06-25 11:08:10 +03:00
132055b177 не помню все как в тумане 2026-06-25 09:20:18 +03:00
c7aedab9cd up 2026-05-28 17:53:50 +03:00
d65a758c31 add 2026-02-27 15:38:07 +03:00
97a7bfeb07 add 2026-02-27 08:47:44 +03:00
b36ffe294c labview 2026-02-21 18:32:02 +03:00
8552d8ee90 добавил второй проект для C8T6 2026-02-14 18:13:02 +03:00
69ae4f8cf2 notjob 2025-11-15 16:10:18 +03:00
e1bb35e6b6 up 2025-11-07 16:43:19 +03:00
46068a5ffe up 2025-11-07 16:30:14 +03:00
81d95635f9 comit_job ver new modbus 2025-11-07 16:22:00 +03:00
461a206fe7 commit 2025-11-05 09:26:36 +03:00
345ab9df8b add iddle irq 2025-10-27 16:49:16 +03:00
694a8ab793 добавил распиновку разъема 2025-10-27 16:47:50 +03:00
1a519ebf02 добавил setup file для настроек 2025-10-27 16:46:43 +03:00
3661 changed files with 2147714 additions and 11221 deletions

48
.gitignore vendored
View File

@@ -1,48 +0,0 @@
# ---> uVision
# git ignore file for Keil µVision Project
# µVision 5 and µVision 4 Project screen layout file
*.uvguix.*
*.uvgui.*
# Listing Files
*.i
*.lst
*.m51
*.m66
*.map
# Object Files
*.axf
*.b[0-2][0-9]
*.b3[0-1]
*.bak
*.build_log.htm
*.crf
*.d
*.dep
*.elf
*.htm
*.iex
*.lnp
*.o
*.obj
*.sbr
# Firmware Files
*.bin
*.h86
*.hex
# Build Files
.bat
# Debugger Files
.ini
# JLink Files
JLinkLog.txt
# Other Files
/john103C6T6/MDK-ARM/john103C6T6.uvoptx

7
.gitmodules vendored
View File

@@ -1,7 +0,0 @@
[submodule "external_flash_eeprom"]
path = external_flash_eeprom
url = https://git.arktika.cyou/set506/external_flash_eeprom.git
[submodule "labview_proj"]
path = labview_proj
url = https://git.arktika.cyou/Andrey/labview_proj.git
branch = master

View File

@@ -1,2 +0,0 @@
# ds18b20-MODBUS

File diff suppressed because one or more lines are too long

View File

@@ -1,102 +0,0 @@
/**
******************************************************************************
* @file ds18b20_driver.h
* @brief This file contains all the constants parameters for the DS18B20
* 1-Wire Digital Thermometer
******************************************************************************
* @attention
* Usage:
* Uncomment LL Driver for HAL driver
*
******************************************************************************
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef DS18B20_H
#define DS18B20_H
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ------------------------------------------------------------------*/
#include "onewire.h"
/* Data Structure ------------------------------------------------------------*/
#define DS18B20_DEVICE_AMOUNT 30
/* Register ------------------------------------------------------------------*/
#define DS18B20_CMD_CONVERT 0x44
#define DS18B20_CMD_ALARM_SEARCH 0xEC
#define DS18B20_CMD_READSCRATCHPAD 0xBE
#define DS18B20_CMD_WRITESCRATCHPAD 0x4E
#define DS18B20_CMD_COPYSCRATCHPAD 0x48
/* Data Structure ------------------------------------------------------------*/
#define DS18B20_FAMILY_CODE 0x28
#define DS18B20_SERIAL_NUMBER_LEN_BYTES 6
#define DS18B20_SERIAL_NUMBER_OFFSET_BYTES 1
#define DS18B20_SCRATCHPAD_T_LSB_BYTE_IDX 0
#define DS18B20_SCRATCHPAD_T_MSB_BYTE_IDX 1
#define DS18B20_SCRATCHPAD_T_LIMIT_H_BYTE_IDX 2
#define DS18B20_SCRATCHPAD_T_LIMIT_L_BYTE_IDX 3
#define DS18B20_SCRATCHPAD_CONFIG_BYTE_IDX 4
#define DS18B20_SCRATCHPAD_USER_BYTE_3_IDX 6
#define DS18B20_SCRATCHPAD_USER_BYTE_4_IDX 7
#define DS18B20_SCRATCHPAD_CRC_IDX 8
/* Bits locations for resolution */
#define DS18B20_RESOLUTION_R1 6
#define DS18B20_RESOLUTION_R0 5
#define DS18B20_DECIMAL_STEP_12BIT 0.0625
#define DS18B20_DECIMAL_STEP_11BIT 0.125
#define DS18B20_DECIMAL_STEP_10BIT 0.25
#define DS18B20_DECIMAL_STEP_9BIT 0.5
#define DS18B20_DELAY_MS_9_BITS 94
#define DS18B20_DELAY_MS_10_BITS 188
#define DS18B20_DELAY_MS_11_BITS 375
#define DS18B20_DELAY_MS_12_BITS 750
#define DS18B20_DELAY_MS_MAX DS18B20_DELAY_MS_12_BITS
/* DS18B20 Resolutions */
typedef enum {
DS18B20_RESOLUTION_9BITS = 0x1F,
DS18B20_RESOLUTION_10BITS = 0x3F,
DS18B20_RESOLUTION_11BITS = 0x5F,
DS18B20_RESOLUTION_12BITS = 0x7F
} DS18B20_Res_t;
typedef struct
{
uint8_t DevAddr[DS18B20_DEVICE_AMOUNT][8];
} DS18B20_Drv_t;
extern DS18B20_Drv_t DS;;
extern OneWire_t OW;
/* External Function ---------------------------------------------------------*/
HAL_StatusTypeDef DS18B20_Search(DS18B20_Drv_t *DS, OneWire_t *OW);
HAL_StatusTypeDef DS18B20_StartConvT(OneWire_t* OW, uint8_t *ROM);
HAL_StatusTypeDef DS18B20_StartConvTAll(OneWire_t* OW);
HAL_StatusTypeDef DS18B20_CalcTemperature(OneWire_t* OW, uint8_t *ROM, uint8_t *Scratchpad, float *destination);
HAL_StatusTypeDef DS18B20_ReadScratchpad(OneWire_t* OW, uint8_t *ROM, uint8_t *Scratchpad);
HAL_StatusTypeDef DS18B20_WaitForEndConvertion(OneWire_t* OW);
HAL_StatusTypeDef DS18B20_WaitForEndConvertion_NonBlocking(OneWire_t* OW);
HAL_StatusTypeDef DS18B20_SetTempAlarm(OneWire_t* OW, uint8_t *ROM, int8_t Low,
int8_t High);
HAL_StatusTypeDef DS18B20_WriteUserBytes(OneWire_t* OW, uint8_t *ROM, int16_t UserBytes12,
int16_t UserBytes34, uint8_t UserBytesMask);
uint8_t DS18B20_AlarmSearch(DS18B20_Drv_t *DS, OneWire_t* OW);
HAL_StatusTypeDef DS18B20_SetResolution(OneWire_t* OW, uint8_t *ROM,
DS18B20_Res_t Resolution);
HAL_StatusTypeDef DS18B20_IsValidAddress(uint8_t *ROM);
#ifdef __cplusplus
}
#endif
#endif /* DS18B20_H */

View File

@@ -1,110 +0,0 @@
/* USER CODE BEGIN Header */
/**
******************************************************************************
* @file : main.h
* @brief : Header for main.c file.
* This file contains the common defines of the application.
******************************************************************************
* @attention
*
* Copyright (c) 2025 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
/* USER CODE END Header */
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __MAIN_H
#define __MAIN_H
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ------------------------------------------------------------------*/
#include "stm32f1xx_hal.h"
/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
typedef enum {
STATE_OPEN_VALVE = 0, // open
STATE_CLOSE_VALVE= 1 // close
} ValveState;
typedef struct
{
uint32_t id[2];
float temp;
uint16_t location;
uint8_t t_open;
float t_set;
uint8_t t_close;
uint8_t status_T_sense:1 ;
ValveState state;
uint16_t count;
}TEMP;
/* USER CODE END Includes */
/* Exported types ------------------------------------------------------------*/
/* USER CODE BEGIN ET */
#define reset_blink_delay 50
#define rest_iter 10
#define GPIOB11_valve MB_DATA.Coils.coils[0].state_val_bit.state_val_01
#define ralay_5v_on GPIOA->ODR&(1<<10);
extern void handle_command(char* cmd);
typedef void (*FunctionPointer)(void);
uint16_t handle_valves(TEMP* tmp_sense);
void init_all_T_sense(void);
void iwdg_refresh(void);
void led_blink(GPIO_TypeDef *GPIOx,uint16_t GPIO_Pin,uint8_t iter,uint16_t delay);
/* USER CODE END ET */
/* Exported constants --------------------------------------------------------*/
/* USER CODE BEGIN EC */
/* USER CODE END EC */
/* Exported macro ------------------------------------------------------------*/
/* USER CODE BEGIN EM */
/* USER CODE END EM */
/* Exported functions prototypes ---------------------------------------------*/
void Error_Handler(void);
/* USER CODE BEGIN EFP */
/* USER CODE END EFP */
/* Private defines -----------------------------------------------------------*/
#define One_wire_Pin GPIO_PIN_15
#define One_wire_GPIO_Port GPIOA
/* USER CODE BEGIN Private defines */
/* USER CODE END Private defines */
#ifdef __cplusplus
}
#endif
#endif /* __MAIN_H */

View File

@@ -1,52 +0,0 @@
/* USER CODE BEGIN Header */
/**
******************************************************************************
* @file rtc.h
* @brief This file contains all the function prototypes for
* the rtc.c file
******************************************************************************
* @attention
*
* Copyright (c) 2025 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
/* USER CODE END Header */
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __RTC_H__
#define __RTC_H__
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ------------------------------------------------------------------*/
#include "main.h"
/* USER CODE BEGIN Includes */
/* USER CODE END Includes */
extern RTC_HandleTypeDef hrtc;
/* USER CODE BEGIN Private defines */
/* USER CODE END Private defines */
void MX_RTC_Init(void);
/* USER CODE BEGIN Prototypes */
/* USER CODE END Prototypes */
#ifdef __cplusplus
}
#endif
#endif /* __RTC_H__ */

View File

@@ -1,74 +0,0 @@
/* USER CODE BEGIN Header */
/**
******************************************************************************
* @file stm32f1xx_it.h
* @brief This file contains the headers of the interrupt handlers.
******************************************************************************
* @attention
*
* Copyright (c) 2025 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
/* USER CODE END Header */
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __STM32F1xx_IT_H
#define __STM32F1xx_IT_H
#ifdef __cplusplus
extern "C" {
#endif
/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
/* USER CODE END Includes */
/* Exported types ------------------------------------------------------------*/
/* USER CODE BEGIN ET */
/* USER CODE END ET */
/* Exported constants --------------------------------------------------------*/
/* USER CODE BEGIN EC */
/* USER CODE END EC */
/* Exported macro ------------------------------------------------------------*/
/* USER CODE BEGIN EM */
/* USER CODE END EM */
/* Exported functions prototypes ---------------------------------------------*/
void NMI_Handler(void);
void HardFault_Handler(void);
void MemManage_Handler(void);
void BusFault_Handler(void);
void UsageFault_Handler(void);
void SVC_Handler(void);
void DebugMon_Handler(void);
void PendSV_Handler(void);
void SysTick_Handler(void);
void RTC_IRQHandler(void);
void TIM1_BRK_IRQHandler(void);
void TIM1_UP_IRQHandler(void);
void TIM1_TRG_COM_IRQHandler(void);
void TIM1_CC_IRQHandler(void);
void TIM2_IRQHandler(void);
void TIM3_IRQHandler(void);
void USART1_IRQHandler(void);
/* USER CODE BEGIN EFP */
/* USER CODE END EFP */
#ifdef __cplusplus
}
#endif
#endif /* __STM32F1xx_IT_H */

View File

@@ -1,55 +0,0 @@
/* USER CODE BEGIN Header */
/**
******************************************************************************
* @file tim.h
* @brief This file contains all the function prototypes for
* the tim.c file
******************************************************************************
* @attention
*
* Copyright (c) 2025 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
/* USER CODE END Header */
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __TIM_H__
#define __TIM_H__
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ------------------------------------------------------------------*/
#include "main.h"
/* USER CODE BEGIN Includes */
/* USER CODE END Includes */
extern TIM_HandleTypeDef htim1;
extern TIM_HandleTypeDef htim2;
/* USER CODE BEGIN Private defines */
/* USER CODE END Private defines */
void MX_TIM1_Init(void);
void MX_TIM2_Init(void);
/* USER CODE BEGIN Prototypes */
/* USER CODE END Prototypes */
#ifdef __cplusplus
}
#endif
#endif /* __TIM_H__ */

View File

@@ -1,52 +0,0 @@
/* USER CODE BEGIN Header */
/**
******************************************************************************
* @file usart.h
* @brief This file contains all the function prototypes for
* the usart.c file
******************************************************************************
* @attention
*
* Copyright (c) 2025 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
/* USER CODE END Header */
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __USART_H__
#define __USART_H__
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ------------------------------------------------------------------*/
#include "main.h"
/* USER CODE BEGIN Includes */
/* USER CODE END Includes */
extern UART_HandleTypeDef huart1;
/* USER CODE BEGIN Private defines */
/* USER CODE END Private defines */
void MX_USART1_UART_Init(void);
/* USER CODE BEGIN Prototypes */
/* USER CODE END Prototypes */
#ifdef __cplusplus
}
#endif
#endif /* __USART_H__ */

View File

@@ -1,129 +0,0 @@
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include "main.h"
#include "def.h"
//extern uint8_t devices_found ;
extern uint8_t roms[MAX_DEVICES][8];
extern char rx_buffer[64];
extern TEMP temp_sense[30];
extern uint8_t init;
int test_var=0;
//void handle_command(char* cmd)
//
//{
// if (strncmp(cmd, "list", 4) == 0)
// {
// printf("find %d devices:\r\n", devices_found);
// for (int i = 0; i < devices_found; i++)
// {
// printf("Device #%d: ", i);
// for (int j = 0; j < 8; j++)
// printf("%02X ", roms[i][j]);
// printf("\r\n");
// }
// }
// else if (strncmp(cmd, "temp all", 8) == 0)
// {
// for (int i = 0; i < devices_found; i++)
// {
// ds_reset();
// ds_write_byte(0x55);
// for (int j = 0; j < 8; j++)
// ds_write_byte(roms[i][j]);
// ds_write_byte(0x44);
// }
// HAL_Delay(750);
// for (int i = 0; i < devices_found; i++)
// {
// ds_reset();
// ds_write_byte(0x55);
// for (int j = 0; j < 8; j++)
// ds_write_byte(roms[i][j]);
// ds_write_byte(0xBE);
// uint8_t tl = ds_read_byte();
// uint8_t th = ds_read_byte();
// int16_t t = (th << 8) | tl;
// float temp = t / 16.0;
// printf("T[%d] = %.2f C\r\n", i, temp);
// }
// }
// else if (strncmp(cmd, "temp ", 5) == 0)
// {
// int id = atoi(&cmd[5]);
// if (id < 0 || id >= devices_found)
// {
// printf("unknown ID\r\n");
// return;
// }
// ds_reset();
// ds_write_byte(0x55);
// for (int j = 0; j < 8; j++)
// ds_write_byte(roms[id][j]);
// ds_write_byte(0x44);
// HAL_Delay(750);
// ds_reset();
// ds_write_byte(0x55);
// for (int j = 0; j < 8; j++)
// ds_write_byte(roms[id][j]);
// ds_write_byte(0xBE);
// uint8_t tl = ds_read_byte();
// uint8_t th = ds_read_byte();
// int16_t t = (th << 8) | tl;
// float temp = t / 16.0;
// printf("T[%d] = %.2f C\r\n", id, temp);
// }
// else if (strncmp(cmd, "ts_1_open_minus",15 ) == 0)
// {
// temp_sense[0].t_open-=1;
//
// }
// else if (strncmp(cmd, "ts_1_open_plus",14 ) == 0)
// {
// temp_sense[0].t_open+=1;
//
// }
// else if (strncmp(cmd, "ts_1_close_minus",16 ) == 0)
// {
// temp_sense[0].t_close-=1;
//
// }
// else if (strncmp(cmd, "ts_1_close_plus",15 ) == 0)
// {
//
// temp_sense[0].t_close+=1;
// }
// else if (strncmp(cmd, "init",4 ) == 0)
// {
// init=1;
// printf("init %s\r\n", "OK");
// }
// else if
// (strncmp(cmd, "set_temp ", 9) == 0)
// {
// uint8_t sense_num = (atoi(&cmd[9])&0x7c0)>>10;
// int parse_uart=atoi(&cmd[10]);
//
// temp_sense[sense_num].t_set=(float)parse_uart/10.;
// printf("temp_sense %i %s\r\n",sense_num, "OK");
//
//
// }
// else if (strncmp(cmd, "temp ", 5) == 0)
// {
//
//
// }
// else
// {
// printf("unknown CMD: %s\r\n", cmd);
// for (int i=0;i<63;i++)
// rx_buffer[i]=0;
//
// }
//}

View File

@@ -1,95 +0,0 @@
/* USER CODE BEGIN Header */
/**
******************************************************************************
* @file gpio.c
* @brief This file provides code for the configuration
* of all used GPIO pins.
******************************************************************************
* @attention
*
* Copyright (c) 2025 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "gpio.h"
/* USER CODE BEGIN 0 */
/* USER CODE END 0 */
/*----------------------------------------------------------------------------*/
/* Configure GPIO */
/*----------------------------------------------------------------------------*/
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */
/** Configure pins as
* Analog
* Input
* Output
* EVENT_OUT
* EXTI
*/
void MX_GPIO_Init(void)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
/* GPIO Ports Clock Enable */
__HAL_RCC_GPIOC_CLK_ENABLE();
__HAL_RCC_GPIOD_CLK_ENABLE();
__HAL_RCC_GPIOA_CLK_ENABLE();
__HAL_RCC_GPIOB_CLK_ENABLE();
/*Configure GPIO pin Output Level */
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3|GPIO_PIN_4
|GPIO_PIN_5|GPIO_PIN_6|GPIO_PIN_7|GPIO_PIN_8
|GPIO_PIN_9|GPIO_PIN_10|One_wire_Pin, GPIO_PIN_SET);
/*Configure GPIO pin Output Level */
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_10
|GPIO_PIN_11|GPIO_PIN_12|GPIO_PIN_13|GPIO_PIN_14
|GPIO_PIN_15, GPIO_PIN_SET);
/*Configure GPIO pin : PA0 */
GPIO_InitStruct.Pin = GPIO_PIN_0;
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
GPIO_InitStruct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
/*Configure GPIO pins : PA1 PA2 PA3 PA4
PA5 PA6 PA7 PA8
PA9 PA10 PAPin */
GPIO_InitStruct.Pin = GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3|GPIO_PIN_4
|GPIO_PIN_5|GPIO_PIN_6|GPIO_PIN_7|GPIO_PIN_8
|GPIO_PIN_9|GPIO_PIN_10|One_wire_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
/*Configure GPIO pins : PB0 PB1 PB2 PB10
PB11 PB12 PB13 PB14
PB15 */
GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_10
|GPIO_PIN_11|GPIO_PIN_12|GPIO_PIN_13|GPIO_PIN_14
|GPIO_PIN_15;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
}
/* USER CODE BEGIN 2 */
/* USER CODE END 2 */

View File

@@ -1,423 +0,0 @@
/* USER CODE BEGIN Header */
/**
******************************************************************************
* @file : main.c
* @brief : Main program body
******************************************************************************
* @attention
*
* Copyright (c) 2025 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "adc.h"
#include "can.h"
#include "i2c.h"
#include "rtc.h"
#include "spi.h"
#include "tim.h"
#include "usart.h"
#include "gpio.h"
/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "dallas_tools.h"
#include "def.h"
#include <stdio.h>
#include "rs_message.h"
/* USER CODE END Includes */
/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */
int fputc(int ch, FILE *f)
{
HAL_UART_Transmit(&huart1, (uint8_t *)&ch, 1, HAL_MAX_DELAY);
return ch;
}
/* USER CODE END PTD */
/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
uint16_t iter,cnt=5;
uint8_t ralay_5v_on_var=0;
/* USER CODE END PD */
/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */
float temperature;
extern uint8_t roms[MAX_DEVICES][8];
//extern uint8_t devices_found ;
uint8_t _debug_init=0;
//TEMP temp_sense[30];
float set_temp_old[30];
char rx_buffer[64];
uint8_t rx_index = 0;
char command_ready = 0;
uint8_t uart_byte = 0;
uint8_t first_in=1;
DALLAS_SensorHandleTypeDef sens[30];
/* USER CODE END PM */
/* Private variables ---------------------------------------------------------*/
/* USER CODE BEGIN PV */
/* USER CODE END PV */
/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
/* USER CODE BEGIN PFP */
/* USER CODE END PFP */
/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
/* USER CODE END 0 */
/**
* @brief The application entry point.
* @retval int
*/
int main(void)
{
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */
/* MCU Configuration--------------------------------------------------------*/
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* USER CODE BEGIN Init */
/* USER CODE END Init */
/* Configure the system clock */
SystemClock_Config();
/* USER CODE BEGIN SysInit */
/* USER CODE END SysInit */
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_TIM1_Init();
MX_USART1_UART_Init();
MX_TIM2_Init();
MX_ADC1_Init();
MX_CAN_Init();
MX_I2C1_Init();
MX_RTC_Init();
MX_SPI1_Init();
/* USER CODE BEGIN 2 */
led_blink(GPIOC,13,rest_iter,reset_blink_delay);
MODBUS_FirstInit();
uint8_t uart_byte = 0;
RS_Receive_IT(&hmodbus1, &MODBUS_MSG);
Dallas_BusFirstInit(&htim1);
// èíèöèàëèçàöèÿ ïî ïîðÿäêó íàéäåííûõ äàò÷èêîâ
// Èíèöèàëèçàöèÿ ïî èíäåêñó (ïîðÿäêîâîìó íîìåðó íàéäåííîãî äàò÷èêà)
for ( int i=0; i<hdallas.onewire->RomCnt;i++)
{
// Èíèöèàëèçàöèÿ ïî ROM-àäðåñó
//sens[i].Init.init_func = &Dallas_SensorInitByROM;
// sens[i].Init.InitParam.ROM = rom_address;
sens[i].Init.InitParam.Ind = i;
sens[i].Init.init_func = &Dallas_SensorInitByInd;
sens[i].Init.Resolution = DALLAS_CONFIG_9_BITS;
MB_DATA.HoldRegs.set_Temp[i] =sens[i].set_temp =20.;
MB_DATA.HoldRegs.set_hyst[i]=sens[i].hyst =1;
Dallas_AddNewSensors(&hdallas, &sens[i]);
}
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
if (_debug_init||MB_DATA.Coils.init_param)
{
_debug_init=0;
MB_DATA.Coils.init_param=0;
for(int i=0;i<hdallas.onewire->RomCnt;i++)
{
sens[i].set_temp=MB_DATA.HoldRegs.set_Temp[i];
sens[i].hyst=MB_DATA.HoldRegs.set_hyst[i];
}
}
Dallas_StartConvertTAll(&hdallas,DALLAS_WAIT_BUS,0);
for(int i=0;i<hdallas.onewire->RomCnt;i++)
{
if(sens[i].isLost)
{
sens[i].lost_cnt ++;
}
Dallas_ReadTemperature(&sens[i]);
sens[i].set_temp = MB_DATA.HoldRegs.set_Temp[i];
MB_DATA.InRegs.sens_Temp[i]=sens[i].temperature*10;
ralay_5v_on_var=MB_DATA.Coils.coils[1].state_val_bit.state_val_05;
if (ralay_5v_on_var)
{
GPIOA->ODR|=1<<10;
}
else
{
GPIOA->ODR&=~(1<<10);
}
//// if (sens[i].temperature<sens[i].set_temp-sens[i].hyst)
////
//// {
////
//// MB_DATA.Coils.coils[0].all|=1<<i;
////
//// }
////
//// else
////
//// if (sens[i].temperature>sens[i].set_temp+sens[i].hyst)
//// {
////
//// MB_DATA.Coils.coils[0].all&=~(1<<i);
////
//// }
//// if(GPIOB11_valve)
//// {
//// GPIOB->ODR|=1<<11;
//// }
//// else
//// {
//// GPIOB->ODR&=~(1<<11);
////
//// }
}
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
//iwdg_refresh();
//HAL_Delay(200);
}
/* USER CODE END 3 */
}
/**
* @brief System Clock Configuration
* @retval None
*/
void SystemClock_Config(void)
{
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
RCC_PeriphCLKInitTypeDef PeriphClkInit = {0};
/** Initializes the RCC Oscillators according to the specified parameters
* in the RCC_OscInitTypeDef structure.
*/
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_LSI|RCC_OSCILLATORTYPE_HSE;
RCC_OscInitStruct.HSEState = RCC_HSE_ON;
RCC_OscInitStruct.HSEPredivValue = RCC_HSE_PREDIV_DIV1;
RCC_OscInitStruct.HSIState = RCC_HSI_ON;
RCC_OscInitStruct.LSIState = RCC_LSI_ON;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL9;
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
{
Error_Handler();
}
/** Initializes the CPU, AHB and APB buses clocks
*/
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
|RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK)
{
Error_Handler();
}
PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_RTC|RCC_PERIPHCLK_ADC;
PeriphClkInit.RTCClockSelection = RCC_RTCCLKSOURCE_LSI;
PeriphClkInit.AdcClockSelection = RCC_ADCPCLK2_DIV6;
if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK)
{
Error_Handler();
}
}
/* USER CODE BEGIN 4 */
void iwdg_refresh(void)
{
IWDG->KR = 0xAAAA; // Ñáðîñèòü òàéìåð
}
void led_blink(GPIO_TypeDef *GPIOx,uint16_t GPIO_Pin,uint8_t iter,uint16_t delay)
{
for(int i=0;i<iter;i++)
{
GPIOx->ODR^=(1<<GPIO_Pin);
HAL_Delay(delay);
}
}
//void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
//{
// if (huart->Instance == USART1)
// {
// if(first_in)
// {
// first_in=0;
// rx_index = 0;
//
// }
//
//
//
// static uint8_t ch;
// HAL_UART_Receive_IT(&huart1, &ch, 1);
// if (ch == '\r' || ch == '\n')
// {
// rx_buffer[rx_index] = 0;
// command_ready = 1;
// rx_index = 0;
// first_in=1;
//
// }
// else
// {
// if (rx_index < sizeof(rx_buffer) - 1)
// {
// rx_buffer[rx_index++] = ch;
// }
// }
// }
//}
//uint16_t handle_valves(TEMP* tmp_sense )
//{
//
// if (temp_sense[0].state==STATE_OPEN_VALVE)
// {
// GPIOC->ODR|=1<<14;
// }
// else
// if (temp_sense[0].state==STATE_CLOSE_VALVE)
// {
// GPIOC->ODR&=~(1<<14);
// }
//
// return 1;
//
//}
//void init_all_T_sense(void)
//{
// //ds_search_devices();
// for(int i=0;i<hdallas.onewire->RomCnt;i++)
//{
// temp_sense[i].id[0]=roms[i][0]<<0|roms[i][1]<<8|roms[i][2]<<16|roms[i][3]<<24;
// temp_sense[i].id[1]=roms[i][4]<<0|roms[i][5]<<8|roms[i][6]<<16|roms[i][7]<<24;
// temp_sense[i].count =i+1;
// temp_sense[i].location=1;
// temp_sense[i].t_open=22;
// temp_sense[i].t_close=18;
// temp_sense[i].status_T_sense=1;
//}
//}
/* USER CODE END 4 */
/**
* @brief Period elapsed callback in non blocking mode
* @note This function is called when TIM3 interrupt took place, inside
* HAL_TIM_IRQHandler(). It makes a direct call to HAL_IncTick() to increment
* a global variable "uwTick" used as application time base.
* @param htim : TIM handle
* @retval None
*/
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
/* USER CODE BEGIN Callback 0 */
/* USER CODE END Callback 0 */
if (htim->Instance == TIM3) {
HAL_IncTick();
}
/* USER CODE BEGIN Callback 1 */
/* USER CODE END Callback 1 */
}
/**
* @brief This function is executed in case of error occurrence.
* @retval None
*/
void Error_Handler(void)
{
/* USER CODE BEGIN Error_Handler_Debug */
/* User can add his own implementation to report the HAL error return state */
__disable_irq();
while (1)
{
}
/* USER CODE END Error_Handler_Debug */
}
#ifdef USE_FULL_ASSERT
/**
* @brief Reports the name of the source file and the source line number
* where the assert_param error has occurred.
* @param file: pointer to the source file name
* @param line: assert_param error line source number
* @retval None
*/
void assert_failed(uint8_t *file, uint32_t line)
{
/* USER CODE BEGIN 6 */
/* User can add his own implementation to report the file name and line number,
ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
/* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT */

View File

@@ -1,122 +0,0 @@
/**
******************************************************************************
* @file ow_port.c
* @brief This file includes the driver for port for OneWire purposes
******************************************************************************
*/
#include "ow_port.h"
#include "onewire.h"
#include "tim.h"
uint32_t pin_pos = (OW_Pin_Numb < 8) ? (OW_Pin_Numb * 4) : ((OW_Pin_Numb - 8) * 4);
/**
* @brief The internal function is used as gpio pin mode
* @param OW OneWire HandleTypedef
* @param Mode Input or Output
*/
void OneWire_Pin_Mode(OneWire_t* OW, PinMode Mode)
{
#ifdef CMSIS_Driver
volatile uint32_t *config_reg = (OW_Pin_Numb < 8) ? &(OW->DataPort->CRL) : &(OW->DataPort->CRH);
// —брос текущих 4 бит (CNF + MODE)
*config_reg &= ~(0xF << pin_pos);
if (Mode == Input)
{
// ¬ход с подт¤жкой или без Ц например, CNF = 0b01, MODE = 0b00
// «десь устанавливаем вход с подт¤жкой:
*config_reg |= (0x8 << pin_pos); // CNF=10, MODE=00 (вход с подт¤жкой)
OW->DataPort->ODR |= (1 << OW_Pin_Numb); // ¬ключить подт¤жку вверх
}
else
{
// ¬ыход push-pull, 2 ћ√ц Ц MODE = 0b10, CNF = 0b00
*config_reg |= (0x2 << pin_pos);
}
#else
#ifdef LL_Driver
if(Mode == Input)
{
LL_GPIO_SetPinMode(OW->DataPort, OW->DataPin, LL_GPIO_MODE_INPUT);
}else{
LL_GPIO_SetPinMode(OW->DataPort, OW->DataPin, LL_GPIO_MODE_OUTPUT);
}
#else
GPIO_InitTypeDef GPIO_InitStruct = {0};
GPIO_InitStruct.Pin = OW->DataPin;
if(Mode == Input)
{
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
}else{
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
}
HAL_GPIO_Init(OW->DataPort, &GPIO_InitStruct);
#endif
#endif
}
/**
* @brief The internal function is used as gpio pin level
* @param OW OneWire HandleTypedef
* @param Mode Level: Set/High = 1, Reset/Low = 0
*/
void OneWire_Pin_Level(OneWire_t* OW, uint8_t Level)
{
#ifdef CMSIS_Driver
if (Level != GPIO_PIN_RESET)
{
OW->DataPort->BSRR = OW->DataPin;
}
else
{
OW->DataPort->BSRR = (uint32_t)OW->DataPin << 16u;
}
#else
#ifdef LL_Driver
if(Level == 1)
{
LL_GPIO_SetOutputPin(OW->DataPort, OW->DataPin);
}else{
LL_GPIO_ResetOutputPin(OW->DataPort, OW->DataPin);
}
#else
HAL_GPIO_WritePin(OW->DataPort, OW->DataPin, Level);
#endif
#endif
}
/**
* @brief The internal function is used to read data pin
* @retval Pin level status
* @param OW OneWire HandleTypedef
*/
uint8_t OneWire_Pin_Read(OneWire_t* OW)
{
#ifdef CMSIS_Driver
return ((OW->DataPort->IDR & OW->DataPin) != 0x00U) ? 1 : 0;
#else
#ifdef LL_Driver
return ((OW->DataPort->IDR & OW->DataPin) != 0x00U) ? 1 : 0;
#else6
return HAL_GPIO_ReadPin(OW->DataPort, OW->DataPin);
#endif
#endif
}
uint32_t tim_1us_period = OW_TIM_1US_PERIOD;
void OneWire_Delay_us(uint32_t us)
{
uint32_t ticks = us * tim_1us_period;
uint16_t start = OW_TIM->CNT;
uint32_t elapsed = 0;
uint16_t prev = start;
while (elapsed < ticks)
{
uint16_t curr = OW_TIM->CNT;
uint16_t delta = (uint16_t)(curr - prev); // учЄт переполнени¤
elapsed += delta;
prev = curr;
}
}

View File

@@ -1,128 +0,0 @@
/* USER CODE BEGIN Header */
/**
******************************************************************************
* @file rtc.c
* @brief This file provides code for the configuration
* of the RTC instances.
******************************************************************************
* @attention
*
* Copyright (c) 2025 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "rtc.h"
/* USER CODE BEGIN 0 */
/* USER CODE END 0 */
RTC_HandleTypeDef hrtc;
/* RTC init function */
void MX_RTC_Init(void)
{
/* USER CODE BEGIN RTC_Init 0 */
/* USER CODE END RTC_Init 0 */
RTC_TimeTypeDef sTime = {0};
RTC_DateTypeDef DateToUpdate = {0};
/* USER CODE BEGIN RTC_Init 1 */
/* USER CODE END RTC_Init 1 */
/** Initialize RTC Only
*/
hrtc.Instance = RTC;
hrtc.Init.AsynchPrediv = RTC_AUTO_1_SECOND;
hrtc.Init.OutPut = RTC_OUTPUTSOURCE_SECOND;
if (HAL_RTC_Init(&hrtc) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN Check_RTC_BKUP */
/* USER CODE END Check_RTC_BKUP */
/** Initialize RTC and set the Time and Date
*/
// sTime.Hours = 0x0;
// sTime.Minutes = 0x0;
// sTime.Seconds = 0x0;
// // if (HAL_RTC_SetTime(&hrtc, &sTime, RTC_FORMAT_BCD) != HAL_OK)
// {
// Error_Handler();
// }
// DateToUpdate.WeekDay = RTC_WEEKDAY_MONDAY;
// DateToUpdate.Month = RTC_MONTH_JANUARY;
// DateToUpdate.Date = 0x1;
// DateToUpdate.Year = 0x0;
// if (HAL_RTC_SetDate(&hrtc, &DateToUpdate, RTC_FORMAT_BCD) != HAL_OK)
// {
// Error_Handler();
// }
/* USER CODE BEGIN RTC_Init 2 */
/* USER CODE END RTC_Init 2 */
}
void HAL_RTC_MspInit(RTC_HandleTypeDef* rtcHandle)
{
if(rtcHandle->Instance==RTC)
{
/* USER CODE BEGIN RTC_MspInit 0 */
/* USER CODE END RTC_MspInit 0 */
HAL_PWR_EnableBkUpAccess();
/* Enable BKP CLK enable for backup registers */
__HAL_RCC_BKP_CLK_ENABLE();
/* RTC clock enable */
__HAL_RCC_RTC_ENABLE();
/* RTC interrupt Init */
HAL_NVIC_SetPriority(RTC_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(RTC_IRQn);
/* USER CODE BEGIN RTC_MspInit 1 */
/* USER CODE END RTC_MspInit 1 */
}
}
void HAL_RTC_MspDeInit(RTC_HandleTypeDef* rtcHandle)
{
if(rtcHandle->Instance==RTC)
{
/* USER CODE BEGIN RTC_MspDeInit 0 */
/* USER CODE END RTC_MspDeInit 0 */
/* Peripheral clock disable */
__HAL_RCC_RTC_DISABLE();
/* RTC interrupt Deinit */
HAL_NVIC_DisableIRQ(RTC_IRQn);
/* USER CODE BEGIN RTC_MspDeInit 1 */
/* USER CODE END RTC_MspDeInit 1 */
}
}
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */

View File

@@ -1,124 +0,0 @@
/* USER CODE BEGIN Header */
/**
******************************************************************************
* @file spi.c
* @brief This file provides code for the configuration
* of the SPI instances.
******************************************************************************
* @attention
*
* Copyright (c) 2025 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "spi.h"
/* USER CODE BEGIN 0 */
/* USER CODE END 0 */
SPI_HandleTypeDef hspi1;
/* SPI1 init function */
void MX_SPI1_Init(void)
{
/* USER CODE BEGIN SPI1_Init 0 */
/* USER CODE END SPI1_Init 0 */
/* USER CODE BEGIN SPI1_Init 1 */
/* USER CODE END SPI1_Init 1 */
hspi1.Instance = SPI1;
hspi1.Init.Mode = SPI_MODE_MASTER;
hspi1.Init.Direction = SPI_DIRECTION_2LINES;
hspi1.Init.DataSize = SPI_DATASIZE_8BIT;
hspi1.Init.CLKPolarity = SPI_POLARITY_LOW;
hspi1.Init.CLKPhase = SPI_PHASE_1EDGE;
hspi1.Init.NSS = SPI_NSS_SOFT;
hspi1.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_2;
hspi1.Init.FirstBit = SPI_FIRSTBIT_MSB;
hspi1.Init.TIMode = SPI_TIMODE_DISABLE;
hspi1.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
hspi1.Init.CRCPolynomial = 10;
if (HAL_SPI_Init(&hspi1) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN SPI1_Init 2 */
/* USER CODE END SPI1_Init 2 */
}
void HAL_SPI_MspInit(SPI_HandleTypeDef* spiHandle)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
if(spiHandle->Instance==SPI1)
{
/* USER CODE BEGIN SPI1_MspInit 0 */
/* USER CODE END SPI1_MspInit 0 */
/* SPI1 clock enable */
__HAL_RCC_SPI1_CLK_ENABLE();
__HAL_RCC_GPIOB_CLK_ENABLE();
/**SPI1 GPIO Configuration
PB3 ------> SPI1_SCK
PB4 ------> SPI1_MISO
PB5 ------> SPI1_MOSI
*/
GPIO_InitStruct.Pin = GPIO_PIN_3|GPIO_PIN_5;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
GPIO_InitStruct.Pin = GPIO_PIN_4;
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
GPIO_InitStruct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
__HAL_AFIO_REMAP_SPI1_ENABLE();
/* USER CODE BEGIN SPI1_MspInit 1 */
/* USER CODE END SPI1_MspInit 1 */
}
}
void HAL_SPI_MspDeInit(SPI_HandleTypeDef* spiHandle)
{
if(spiHandle->Instance==SPI1)
{
/* USER CODE BEGIN SPI1_MspDeInit 0 */
/* USER CODE END SPI1_MspDeInit 0 */
/* Peripheral clock disable */
__HAL_RCC_SPI1_CLK_DISABLE();
/**SPI1 GPIO Configuration
PB3 ------> SPI1_SCK
PB4 ------> SPI1_MISO
PB5 ------> SPI1_MOSI
*/
HAL_GPIO_DeInit(GPIOB, GPIO_PIN_3|GPIO_PIN_4|GPIO_PIN_5);
/* USER CODE BEGIN SPI1_MspDeInit 1 */
/* USER CODE END SPI1_MspDeInit 1 */
}
}
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */

View File

@@ -1,87 +0,0 @@
/* USER CODE BEGIN Header */
/**
******************************************************************************
* @file stm32f1xx_hal_msp.c
* @brief This file provides code for the MSP Initialization
* and de-Initialization codes.
******************************************************************************
* @attention
*
* Copyright (c) 2025 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "main.h"
/* USER CODE BEGIN Includes */
/* USER CODE END Includes */
/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN TD */
/* USER CODE END TD */
/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN Define */
/* USER CODE END Define */
/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN Macro */
/* USER CODE END Macro */
/* Private variables ---------------------------------------------------------*/
/* USER CODE BEGIN PV */
/* USER CODE END PV */
/* Private function prototypes -----------------------------------------------*/
/* USER CODE BEGIN PFP */
/* USER CODE END PFP */
/* External functions --------------------------------------------------------*/
/* USER CODE BEGIN ExternalFunctions */
/* USER CODE END ExternalFunctions */
/* USER CODE BEGIN 0 */
/* USER CODE END 0 */
/**
* Initializes the Global MSP.
*/
void HAL_MspInit(void)
{
/* USER CODE BEGIN MspInit 0 */
/* USER CODE END MspInit 0 */
__HAL_RCC_AFIO_CLK_ENABLE();
__HAL_RCC_PWR_CLK_ENABLE();
/* System interrupt init*/
/** NOJTAG: JTAG-DP Disabled and SW-DP Enabled
*/
__HAL_AFIO_REMAP_SWJ_NOJTAG();
/* USER CODE BEGIN MspInit 1 */
/* USER CODE END MspInit 1 */
}
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */

View File

@@ -1,136 +0,0 @@
/* USER CODE BEGIN Header */
/**
******************************************************************************
* @file stm32f1xx_hal_timebase_tim.c
* @brief HAL time base based on the hardware TIM.
******************************************************************************
* @attention
*
* Copyright (c) 2025 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "stm32f1xx_hal.h"
#include "stm32f1xx_hal_tim.h"
/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
TIM_HandleTypeDef htim3;
/* Private function prototypes -----------------------------------------------*/
void TIM3_IRQHandler(void);
/* Private functions ---------------------------------------------------------*/
/**
* @brief This function configures the TIM3 as a time base source.
* The time source is configured to have 1ms time base with a dedicated
* Tick interrupt priority.
* @note This function is called automatically at the beginning of program after
* reset by HAL_Init() or at any time when clock is configured, by HAL_RCC_ClockConfig().
* @param TickPriority: Tick interrupt priority.
* @retval HAL status
*/
HAL_StatusTypeDef HAL_InitTick(uint32_t TickPriority)
{
RCC_ClkInitTypeDef clkconfig;
uint32_t uwTimclock, uwAPB1Prescaler = 0U;
uint32_t uwPrescalerValue = 0U;
uint32_t pFLatency;
HAL_StatusTypeDef status = HAL_OK;
/* Enable TIM3 clock */
__HAL_RCC_TIM3_CLK_ENABLE();
/* Get clock configuration */
HAL_RCC_GetClockConfig(&clkconfig, &pFLatency);
/* Get APB1 prescaler */
uwAPB1Prescaler = clkconfig.APB1CLKDivider;
/* Compute TIM3 clock */
if (uwAPB1Prescaler == RCC_HCLK_DIV1)
{
uwTimclock = HAL_RCC_GetPCLK1Freq();
}
else
{
uwTimclock = 2UL * HAL_RCC_GetPCLK1Freq();
}
/* Compute the prescaler value to have TIM3 counter clock equal to 1MHz */
uwPrescalerValue = (uint32_t) ((uwTimclock / 1000000U) - 1U);
/* Initialize TIM3 */
htim3.Instance = TIM3;
/* Initialize TIMx peripheral as follow:
+ Period = [(TIM3CLK/1000) - 1]. to have a (1/1000) s time base.
+ Prescaler = (uwTimclock/1000000 - 1) to have a 1MHz counter clock.
+ ClockDivision = 0
+ Counter direction = Up
*/
htim3.Init.Period = (1000000U / 1000U) - 1U;
htim3.Init.Prescaler = uwPrescalerValue;
htim3.Init.ClockDivision = 0;
htim3.Init.CounterMode = TIM_COUNTERMODE_UP;
htim3.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
status = HAL_TIM_Base_Init(&htim3);
if (status == HAL_OK)
{
/* Start the TIM time Base generation in interrupt mode */
status = HAL_TIM_Base_Start_IT(&htim3);
if (status == HAL_OK)
{
/* Enable the TIM3 global Interrupt */
HAL_NVIC_EnableIRQ(TIM3_IRQn);
/* Configure the SysTick IRQ priority */
if (TickPriority < (1UL << __NVIC_PRIO_BITS))
{
/* Configure the TIM IRQ priority */
HAL_NVIC_SetPriority(TIM3_IRQn, TickPriority, 0U);
uwTickPrio = TickPriority;
}
else
{
status = HAL_ERROR;
}
}
}
/* Return function status */
return status;
}
/**
* @brief Suspend Tick increment.
* @note Disable the tick increment by disabling TIM3 update interrupt.
* @param None
* @retval None
*/
void HAL_SuspendTick(void)
{
/* Disable TIM3 update Interrupt */
__HAL_TIM_DISABLE_IT(&htim3, TIM_IT_UPDATE);
}
/**
* @brief Resume Tick increment.
* @note Enable the tick increment by Enabling TIM3 update interrupt.
* @param None
* @retval None
*/
void HAL_ResumeTick(void)
{
/* Enable TIM3 Update interrupt */
__HAL_TIM_ENABLE_IT(&htim3, TIM_IT_UPDATE);
}

View File

@@ -1,328 +0,0 @@
/* USER CODE BEGIN Header */
/**
******************************************************************************
* @file stm32f1xx_it.c
* @brief Interrupt Service Routines.
******************************************************************************
* @attention
*
* Copyright (c) 2025 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "stm32f1xx_it.h"
/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "rs_message.h"
/* USER CODE END Includes */
/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN TD */
/* USER CODE END TD */
/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
/* USER CODE END PD */
/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */
/* USER CODE END PM */
/* Private variables ---------------------------------------------------------*/
/* USER CODE BEGIN PV */
/* USER CODE END PV */
/* Private function prototypes -----------------------------------------------*/
/* USER CODE BEGIN PFP */
/* USER CODE END PFP */
/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
/* USER CODE END 0 */
/* External variables --------------------------------------------------------*/
extern RTC_HandleTypeDef hrtc;
extern TIM_HandleTypeDef htim1;
extern TIM_HandleTypeDef htim2;
extern UART_HandleTypeDef huart1;
extern TIM_HandleTypeDef htim3;
/* USER CODE BEGIN EV */
/* USER CODE END EV */
/******************************************************************************/
/* Cortex-M3 Processor Interruption and Exception Handlers */
/******************************************************************************/
/**
* @brief This function handles Non maskable interrupt.
*/
void NMI_Handler(void)
{
/* USER CODE BEGIN NonMaskableInt_IRQn 0 */
/* USER CODE END NonMaskableInt_IRQn 0 */
/* USER CODE BEGIN NonMaskableInt_IRQn 1 */
while (1)
{
}
/* USER CODE END NonMaskableInt_IRQn 1 */
}
/**
* @brief This function handles Hard fault interrupt.
*/
void HardFault_Handler(void)
{
/* USER CODE BEGIN HardFault_IRQn 0 */
/* USER CODE END HardFault_IRQn 0 */
while (1)
{
/* USER CODE BEGIN W1_HardFault_IRQn 0 */
/* USER CODE END W1_HardFault_IRQn 0 */
}
}
/**
* @brief This function handles Memory management fault.
*/
void MemManage_Handler(void)
{
/* USER CODE BEGIN MemoryManagement_IRQn 0 */
/* USER CODE END MemoryManagement_IRQn 0 */
while (1)
{
/* USER CODE BEGIN W1_MemoryManagement_IRQn 0 */
/* USER CODE END W1_MemoryManagement_IRQn 0 */
}
}
/**
* @brief This function handles Prefetch fault, memory access fault.
*/
void BusFault_Handler(void)
{
/* USER CODE BEGIN BusFault_IRQn 0 */
/* USER CODE END BusFault_IRQn 0 */
while (1)
{
/* USER CODE BEGIN W1_BusFault_IRQn 0 */
/* USER CODE END W1_BusFault_IRQn 0 */
}
}
/**
* @brief This function handles Undefined instruction or illegal state.
*/
void UsageFault_Handler(void)
{
/* USER CODE BEGIN UsageFault_IRQn 0 */
/* USER CODE END UsageFault_IRQn 0 */
while (1)
{
/* USER CODE BEGIN W1_UsageFault_IRQn 0 */
/* USER CODE END W1_UsageFault_IRQn 0 */
}
}
/**
* @brief This function handles System service call via SWI instruction.
*/
void SVC_Handler(void)
{
/* USER CODE BEGIN SVCall_IRQn 0 */
/* USER CODE END SVCall_IRQn 0 */
/* USER CODE BEGIN SVCall_IRQn 1 */
/* USER CODE END SVCall_IRQn 1 */
}
/**
* @brief This function handles Debug monitor.
*/
void DebugMon_Handler(void)
{
/* USER CODE BEGIN DebugMonitor_IRQn 0 */
/* USER CODE END DebugMonitor_IRQn 0 */
/* USER CODE BEGIN DebugMonitor_IRQn 1 */
/* USER CODE END DebugMonitor_IRQn 1 */
}
/**
* @brief This function handles Pendable request for system service.
*/
void PendSV_Handler(void)
{
/* USER CODE BEGIN PendSV_IRQn 0 */
/* USER CODE END PendSV_IRQn 0 */
/* USER CODE BEGIN PendSV_IRQn 1 */
/* USER CODE END PendSV_IRQn 1 */
}
/**
* @brief This function handles System tick timer.
*/
void SysTick_Handler(void)
{
/* USER CODE BEGIN SysTick_IRQn 0 */
/* USER CODE END SysTick_IRQn 0 */
/* USER CODE BEGIN SysTick_IRQn 1 */
/* USER CODE END SysTick_IRQn 1 */
}
/******************************************************************************/
/* STM32F1xx Peripheral Interrupt Handlers */
/* Add here the Interrupt Handlers for the used peripherals. */
/* For the available peripheral interrupt handler names, */
/* please refer to the startup file (startup_stm32f1xx.s). */
/******************************************************************************/
/**
* @brief This function handles RTC global interrupt.
*/
void RTC_IRQHandler(void)
{
/* USER CODE BEGIN RTC_IRQn 0 */
/* USER CODE END RTC_IRQn 0 */
HAL_RTCEx_RTCIRQHandler(&hrtc);
/* USER CODE BEGIN RTC_IRQn 1 */
/* USER CODE END RTC_IRQn 1 */
}
/**
* @brief This function handles TIM1 break interrupt.
*/
void TIM1_BRK_IRQHandler(void)
{
/* USER CODE BEGIN TIM1_BRK_IRQn 0 */
/* USER CODE END TIM1_BRK_IRQn 0 */
HAL_TIM_IRQHandler(&htim1);
/* USER CODE BEGIN TIM1_BRK_IRQn 1 */
/* USER CODE END TIM1_BRK_IRQn 1 */
}
/**
* @brief This function handles TIM1 update interrupt.
*/
void TIM1_UP_IRQHandler(void)
{
/* USER CODE BEGIN TIM1_UP_IRQn 0 */
/* USER CODE END TIM1_UP_IRQn 0 */
HAL_TIM_IRQHandler(&htim1);
/* USER CODE BEGIN TIM1_UP_IRQn 1 */
//GPIOC->ODR^=(1<<13);
/* USER CODE END TIM1_UP_IRQn 1 */
}
/**
* @brief This function handles TIM1 trigger and commutation interrupts.
*/
void TIM1_TRG_COM_IRQHandler(void)
{
/* USER CODE BEGIN TIM1_TRG_COM_IRQn 0 */
/* USER CODE END TIM1_TRG_COM_IRQn 0 */
HAL_TIM_IRQHandler(&htim1);
/* USER CODE BEGIN TIM1_TRG_COM_IRQn 1 */
/* USER CODE END TIM1_TRG_COM_IRQn 1 */
}
/**
* @brief This function handles TIM1 capture compare interrupt.
*/
void TIM1_CC_IRQHandler(void)
{
/* USER CODE BEGIN TIM1_CC_IRQn 0 */
/* USER CODE END TIM1_CC_IRQn 0 */
HAL_TIM_IRQHandler(&htim1);
/* USER CODE BEGIN TIM1_CC_IRQn 1 */
/* USER CODE END TIM1_CC_IRQn 1 */
}
/**
* @brief This function handles TIM2 global interrupt.
*/
void TIM2_IRQHandler(void)
{
/* USER CODE BEGIN TIM2_IRQn 0 */
/* USER CODE END TIM2_IRQn 0 */
HAL_TIM_IRQHandler(&htim2);
/* USER CODE BEGIN TIM2_IRQn 1 */
RS_TIM_Handler(&hmodbus1);
/* USER CODE END TIM2_IRQn 1 */
}
/**
* @brief This function handles TIM3 global interrupt.
*/
void TIM3_IRQHandler(void)
{
/* USER CODE BEGIN TIM3_IRQn 0 */
static uint8_t first_in=1;
/* USER CODE END TIM3_IRQn 0 */
HAL_TIM_IRQHandler(&htim3);
/* USER CODE BEGIN TIM3_IRQn 1 */
if (first_in)
{
first_in=0;
}
/* USER CODE END TIM3_IRQn 1 */
}
/**
* @brief This function handles USART1 global interrupt.
*/
void USART1_IRQHandler(void)
{
/* USER CODE BEGIN USART1_IRQn 0 */
/* USER CODE END USART1_IRQn 0 */
HAL_UART_IRQHandler(&huart1);
/* USER CODE BEGIN USART1_IRQn 1 */
RS_UART_Handler(&hmodbus1);
/* USER CODE END USART1_IRQn 1 */
}
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */

View File

@@ -1,191 +0,0 @@
/* USER CODE BEGIN Header */
/**
******************************************************************************
* @file tim.c
* @brief This file provides code for the configuration
* of the TIM instances.
******************************************************************************
* @attention
*
* Copyright (c) 2025 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "tim.h"
/* USER CODE BEGIN 0 */
/* USER CODE END 0 */
TIM_HandleTypeDef htim1;
TIM_HandleTypeDef htim2;
/* TIM1 init function */
void MX_TIM1_Init(void)
{
/* USER CODE BEGIN TIM1_Init 0 */
/* USER CODE END TIM1_Init 0 */
TIM_ClockConfigTypeDef sClockSourceConfig = {0};
TIM_MasterConfigTypeDef sMasterConfig = {0};
/* USER CODE BEGIN TIM1_Init 1 */
/* USER CODE END TIM1_Init 1 */
htim1.Instance = TIM1;
htim1.Init.Prescaler = 0;
htim1.Init.CounterMode = TIM_COUNTERMODE_UP;
htim1.Init.Period = 65535;
htim1.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
htim1.Init.RepetitionCounter = 0;
htim1.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
if (HAL_TIM_Base_Init(&htim1) != HAL_OK)
{
Error_Handler();
}
sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;
if (HAL_TIM_ConfigClockSource(&htim1, &sClockSourceConfig) != HAL_OK)
{
Error_Handler();
}
sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
if (HAL_TIMEx_MasterConfigSynchronization(&htim1, &sMasterConfig) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN TIM1_Init 2 */
/* USER CODE END TIM1_Init 2 */
}
/* TIM2 init function */
void MX_TIM2_Init(void)
{
/* USER CODE BEGIN TIM2_Init 0 */
/* USER CODE END TIM2_Init 0 */
TIM_ClockConfigTypeDef sClockSourceConfig = {0};
TIM_MasterConfigTypeDef sMasterConfig = {0};
/* USER CODE BEGIN TIM2_Init 1 */
/* USER CODE END TIM2_Init 1 */
htim2.Instance = TIM2;
htim2.Init.Prescaler = 7199;
htim2.Init.CounterMode = TIM_COUNTERMODE_UP;
htim2.Init.Period = 65535;
htim2.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
htim2.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
if (HAL_TIM_Base_Init(&htim2) != HAL_OK)
{
Error_Handler();
}
sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;
if (HAL_TIM_ConfigClockSource(&htim2, &sClockSourceConfig) != HAL_OK)
{
Error_Handler();
}
sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
if (HAL_TIMEx_MasterConfigSynchronization(&htim2, &sMasterConfig) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN TIM2_Init 2 */
/* USER CODE END TIM2_Init 2 */
}
void HAL_TIM_Base_MspInit(TIM_HandleTypeDef* tim_baseHandle)
{
if(tim_baseHandle->Instance==TIM1)
{
/* USER CODE BEGIN TIM1_MspInit 0 */
/* USER CODE END TIM1_MspInit 0 */
/* TIM1 clock enable */
__HAL_RCC_TIM1_CLK_ENABLE();
/* TIM1 interrupt Init */
HAL_NVIC_SetPriority(TIM1_BRK_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(TIM1_BRK_IRQn);
HAL_NVIC_SetPriority(TIM1_UP_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(TIM1_UP_IRQn);
HAL_NVIC_SetPriority(TIM1_TRG_COM_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(TIM1_TRG_COM_IRQn);
HAL_NVIC_SetPriority(TIM1_CC_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(TIM1_CC_IRQn);
/* USER CODE BEGIN TIM1_MspInit 1 */
/* USER CODE END TIM1_MspInit 1 */
}
else if(tim_baseHandle->Instance==TIM2)
{
/* USER CODE BEGIN TIM2_MspInit 0 */
/* USER CODE END TIM2_MspInit 0 */
/* TIM2 clock enable */
__HAL_RCC_TIM2_CLK_ENABLE();
/* TIM2 interrupt Init */
HAL_NVIC_SetPriority(TIM2_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(TIM2_IRQn);
/* USER CODE BEGIN TIM2_MspInit 1 */
/* USER CODE END TIM2_MspInit 1 */
}
}
void HAL_TIM_Base_MspDeInit(TIM_HandleTypeDef* tim_baseHandle)
{
if(tim_baseHandle->Instance==TIM1)
{
/* USER CODE BEGIN TIM1_MspDeInit 0 */
/* USER CODE END TIM1_MspDeInit 0 */
/* Peripheral clock disable */
__HAL_RCC_TIM1_CLK_DISABLE();
/* TIM1 interrupt Deinit */
HAL_NVIC_DisableIRQ(TIM1_BRK_IRQn);
HAL_NVIC_DisableIRQ(TIM1_UP_IRQn);
HAL_NVIC_DisableIRQ(TIM1_TRG_COM_IRQn);
HAL_NVIC_DisableIRQ(TIM1_CC_IRQn);
/* USER CODE BEGIN TIM1_MspDeInit 1 */
/* USER CODE END TIM1_MspDeInit 1 */
}
else if(tim_baseHandle->Instance==TIM2)
{
/* USER CODE BEGIN TIM2_MspDeInit 0 */
/* USER CODE END TIM2_MspDeInit 0 */
/* Peripheral clock disable */
__HAL_RCC_TIM2_CLK_DISABLE();
/* TIM2 interrupt Deinit */
HAL_NVIC_DisableIRQ(TIM2_IRQn);
/* USER CODE BEGIN TIM2_MspDeInit 1 */
/* USER CODE END TIM2_MspDeInit 1 */
}
}
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */

View File

@@ -1,124 +0,0 @@
/* USER CODE BEGIN Header */
/**
******************************************************************************
* @file usart.c
* @brief This file provides code for the configuration
* of the USART instances.
******************************************************************************
* @attention
*
* Copyright (c) 2025 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "usart.h"
/* USER CODE BEGIN 0 */
/* USER CODE END 0 */
UART_HandleTypeDef huart1;
/* USART1 init function */
void MX_USART1_UART_Init(void)
{
/* USER CODE BEGIN USART1_Init 0 */
/* USER CODE END USART1_Init 0 */
/* USER CODE BEGIN USART1_Init 1 */
/* USER CODE END USART1_Init 1 */
huart1.Instance = USART1;
huart1.Init.BaudRate = 115200;
huart1.Init.WordLength = UART_WORDLENGTH_8B;
huart1.Init.StopBits = UART_STOPBITS_1;
huart1.Init.Parity = UART_PARITY_NONE;
huart1.Init.Mode = UART_MODE_TX_RX;
huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;
huart1.Init.OverSampling = UART_OVERSAMPLING_16;
if (HAL_UART_Init(&huart1) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN USART1_Init 2 */
/* USER CODE END USART1_Init 2 */
}
void HAL_UART_MspInit(UART_HandleTypeDef* uartHandle)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
if(uartHandle->Instance==USART1)
{
/* USER CODE BEGIN USART1_MspInit 0 */
/* USER CODE END USART1_MspInit 0 */
/* USART1 clock enable */
__HAL_RCC_USART1_CLK_ENABLE();
__HAL_RCC_GPIOB_CLK_ENABLE();
/**USART1 GPIO Configuration
PB6 ------> USART1_TX
PB7 ------> USART1_RX
*/
GPIO_InitStruct.Pin = GPIO_PIN_6;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
GPIO_InitStruct.Pin = GPIO_PIN_7;
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
GPIO_InitStruct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
__HAL_AFIO_REMAP_USART1_ENABLE();
/* USART1 interrupt Init */
HAL_NVIC_SetPriority(USART1_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(USART1_IRQn);
/* USER CODE BEGIN USART1_MspInit 1 */
/* USER CODE END USART1_MspInit 1 */
}
}
void HAL_UART_MspDeInit(UART_HandleTypeDef* uartHandle)
{
if(uartHandle->Instance==USART1)
{
/* USER CODE BEGIN USART1_MspDeInit 0 */
/* USER CODE END USART1_MspDeInit 0 */
/* Peripheral clock disable */
__HAL_RCC_USART1_CLK_DISABLE();
/**USART1 GPIO Configuration
PB6 ------> USART1_TX
PB7 ------> USART1_RX
*/
HAL_GPIO_DeInit(GPIOB, GPIO_PIN_6|GPIO_PIN_7);
/* USART1 interrupt Deinit */
HAL_NVIC_DisableIRQ(USART1_IRQn);
/* USER CODE BEGIN USART1_MspDeInit 1 */
/* USER CODE END USART1_MspDeInit 1 */
}
}
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */

View File

@@ -1,3772 +0,0 @@
/**
******************************************************************************
* @file stm32f1xx_hal_uart.c
* @author MCD Application Team
* @brief UART HAL module driver.
* This file provides firmware functions to manage the following
* functionalities of the Universal Asynchronous Receiver Transmitter Peripheral (UART).
* + Initialization and de-initialization functions
* + IO operation functions
* + Peripheral Control functions
* + Peripheral State and Errors functions
*
******************************************************************************
* @attention
*
* Copyright (c) 2016 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
@verbatim
==============================================================================
##### How to use this driver #####
==============================================================================
[..]
The UART HAL driver can be used as follows:
(#) Declare a UART_HandleTypeDef handle structure (eg. UART_HandleTypeDef huart).
(#) Initialize the UART low level resources by implementing the HAL_UART_MspInit() API:
(##) Enable the USARTx interface clock.
(##) UART pins configuration:
(+++) Enable the clock for the UART GPIOs.
(+++) Configure the UART TX/RX pins as alternate function pull-up.
(##) NVIC configuration if you need to use interrupt process (HAL_UART_Transmit_IT()
and HAL_UART_Receive_IT() APIs):
(+++) Configure the USARTx interrupt priority.
(+++) Enable the NVIC USART IRQ handle.
(##) DMA Configuration if you need to use DMA process (HAL_UART_Transmit_DMA()
and HAL_UART_Receive_DMA() APIs):
(+++) Declare a DMA handle structure for the Tx/Rx channel.
(+++) Enable the DMAx interface clock.
(+++) Configure the declared DMA handle structure with the required
Tx/Rx parameters.
(+++) Configure the DMA Tx/Rx channel.
(+++) Associate the initialized DMA handle to the UART DMA Tx/Rx handle.
(+++) Configure the priority and enable the NVIC for the transfer complete
interrupt on the DMA Tx/Rx channel.
(+++) Configure the USARTx interrupt priority and enable the NVIC USART IRQ handle
(used for last byte sending completion detection in DMA non circular mode)
(#) Program the Baud Rate, Word Length, Stop Bit, Parity, Hardware
flow control and Mode(Receiver/Transmitter) in the huart Init structure.
(#) For the UART asynchronous mode, initialize the UART registers by calling
the HAL_UART_Init() API.
(#) For the UART Half duplex mode, initialize the UART registers by calling
the HAL_HalfDuplex_Init() API.
(#) For the LIN mode, initialize the UART registers by calling the HAL_LIN_Init() API.
(#) For the Multi-Processor mode, initialize the UART registers by calling
the HAL_MultiProcessor_Init() API.
[..]
(@) The specific UART interrupts (Transmission complete interrupt,
RXNE interrupt and Error Interrupts) will be managed using the macros
__HAL_UART_ENABLE_IT() and __HAL_UART_DISABLE_IT() inside the transmit
and receive process.
[..]
(@) These APIs (HAL_UART_Init() and HAL_HalfDuplex_Init()) configure also the
low level Hardware GPIO, CLOCK, CORTEX...etc) by calling the customized
HAL_UART_MspInit() API.
##### Callback registration #####
==================================
[..]
The compilation define USE_HAL_UART_REGISTER_CALLBACKS when set to 1
allows the user to configure dynamically the driver callbacks.
[..]
Use Function HAL_UART_RegisterCallback() to register a user callback.
Function HAL_UART_RegisterCallback() allows to register following callbacks:
(+) TxHalfCpltCallback : Tx Half Complete Callback.
(+) TxCpltCallback : Tx Complete Callback.
(+) RxHalfCpltCallback : Rx Half Complete Callback.
(+) RxCpltCallback : Rx Complete Callback.
(+) ErrorCallback : Error Callback.
(+) AbortCpltCallback : Abort Complete Callback.
(+) AbortTransmitCpltCallback : Abort Transmit Complete Callback.
(+) AbortReceiveCpltCallback : Abort Receive Complete Callback.
(+) MspInitCallback : UART MspInit.
(+) MspDeInitCallback : UART MspDeInit.
This function takes as parameters the HAL peripheral handle, the Callback ID
and a pointer to the user callback function.
[..]
Use function HAL_UART_UnRegisterCallback() to reset a callback to the default
weak (surcharged) function.
HAL_UART_UnRegisterCallback() takes as parameters the HAL peripheral handle,
and the Callback ID.
This function allows to reset following callbacks:
(+) TxHalfCpltCallback : Tx Half Complete Callback.
(+) TxCpltCallback : Tx Complete Callback.
(+) RxHalfCpltCallback : Rx Half Complete Callback.
(+) RxCpltCallback : Rx Complete Callback.
(+) ErrorCallback : Error Callback.
(+) AbortCpltCallback : Abort Complete Callback.
(+) AbortTransmitCpltCallback : Abort Transmit Complete Callback.
(+) AbortReceiveCpltCallback : Abort Receive Complete Callback.
(+) MspInitCallback : UART MspInit.
(+) MspDeInitCallback : UART MspDeInit.
[..]
For specific callback RxEventCallback, use dedicated registration/reset functions:
respectively HAL_UART_RegisterRxEventCallback() , HAL_UART_UnRegisterRxEventCallback().
[..]
By default, after the HAL_UART_Init() and when the state is HAL_UART_STATE_RESET
all callbacks are set to the corresponding weak (surcharged) functions:
examples HAL_UART_TxCpltCallback(), HAL_UART_RxHalfCpltCallback().
Exception done for MspInit and MspDeInit functions that are respectively
reset to the legacy weak (surcharged) functions in the HAL_UART_Init()
and HAL_UART_DeInit() only when these callbacks are null (not registered beforehand).
If not, MspInit or MspDeInit are not null, the HAL_UART_Init() and HAL_UART_DeInit()
keep and use the user MspInit/MspDeInit callbacks (registered beforehand).
[..]
Callbacks can be registered/unregistered in HAL_UART_STATE_READY state only.
Exception done MspInit/MspDeInit that can be registered/unregistered
in HAL_UART_STATE_READY or HAL_UART_STATE_RESET state, thus registered (user)
MspInit/DeInit callbacks can be used during the Init/DeInit.
In that case first register the MspInit/MspDeInit user callbacks
using HAL_UART_RegisterCallback() before calling HAL_UART_DeInit()
or HAL_UART_Init() function.
[..]
When The compilation define USE_HAL_UART_REGISTER_CALLBACKS is set to 0 or
not defined, the callback registration feature is not available
and weak (surcharged) callbacks are used.
[..]
Three operation modes are available within this driver :
*** Polling mode IO operation ***
=================================
[..]
(+) Send an amount of data in blocking mode using HAL_UART_Transmit()
(+) Receive an amount of data in blocking mode using HAL_UART_Receive()
*** Interrupt mode IO operation ***
===================================
[..]
(+) Send an amount of data in non blocking mode using HAL_UART_Transmit_IT()
(+) At transmission end of transfer HAL_UART_TxCpltCallback is executed and user can
add his own code by customization of function pointer HAL_UART_TxCpltCallback
(+) Receive an amount of data in non blocking mode using HAL_UART_Receive_IT()
(+) At reception end of transfer HAL_UART_RxCpltCallback is executed and user can
add his own code by customization of function pointer HAL_UART_RxCpltCallback
(+) In case of transfer Error, HAL_UART_ErrorCallback() function is executed and user can
add his own code by customization of function pointer HAL_UART_ErrorCallback
*** DMA mode IO operation ***
==============================
[..]
(+) Send an amount of data in non blocking mode (DMA) using HAL_UART_Transmit_DMA()
(+) At transmission end of half transfer HAL_UART_TxHalfCpltCallback is executed and user can
add his own code by customization of function pointer HAL_UART_TxHalfCpltCallback
(+) At transmission end of transfer HAL_UART_TxCpltCallback is executed and user can
add his own code by customization of function pointer HAL_UART_TxCpltCallback
(+) Receive an amount of data in non blocking mode (DMA) using HAL_UART_Receive_DMA()
(+) At reception end of half transfer HAL_UART_RxHalfCpltCallback is executed and user can
add his own code by customization of function pointer HAL_UART_RxHalfCpltCallback
(+) At reception end of transfer HAL_UART_RxCpltCallback is executed and user can
add his own code by customization of function pointer HAL_UART_RxCpltCallback
(+) In case of transfer Error, HAL_UART_ErrorCallback() function is executed and user can
add his own code by customization of function pointer HAL_UART_ErrorCallback
(+) Pause the DMA Transfer using HAL_UART_DMAPause()
(+) Resume the DMA Transfer using HAL_UART_DMAResume()
(+) Stop the DMA Transfer using HAL_UART_DMAStop()
[..] This subsection also provides a set of additional functions providing enhanced reception
services to user. (For example, these functions allow application to handle use cases
where number of data to be received is unknown).
(#) Compared to standard reception services which only consider number of received
data elements as reception completion criteria, these functions also consider additional events
as triggers for updating reception status to caller :
(+) Detection of inactivity period (RX line has not been active for a given period).
(++) RX inactivity detected by IDLE event, i.e. RX line has been in idle state (normally high state)
for 1 frame time, after last received byte.
(#) There are two mode of transfer:
(+) Blocking mode: The reception is performed in polling mode, until either expected number of data is received,
or till IDLE event occurs. Reception is handled only during function execution.
When function exits, no data reception could occur. HAL status and number of actually received data elements,
are returned by function after finishing transfer.
(+) Non-Blocking mode: The reception is performed using Interrupts or DMA.
These API's return the HAL status.
The end of the data processing will be indicated through the
dedicated UART IRQ when using Interrupt mode or the DMA IRQ when using DMA mode.
The HAL_UARTEx_RxEventCallback() user callback will be executed during Receive process
The HAL_UART_ErrorCallback()user callback will be executed when a reception error is detected.
(#) Blocking mode API:
(+) HAL_UARTEx_ReceiveToIdle()
(#) Non-Blocking mode API with Interrupt:
(+) HAL_UARTEx_ReceiveToIdle_IT()
(#) Non-Blocking mode API with DMA:
(+) HAL_UARTEx_ReceiveToIdle_DMA()
*** UART HAL driver macros list ***
=============================================
[..]
Below the list of most used macros in UART HAL driver.
(+) __HAL_UART_ENABLE: Enable the UART peripheral
(+) __HAL_UART_DISABLE: Disable the UART peripheral
(+) __HAL_UART_GET_FLAG : Check whether the specified UART flag is set or not
(+) __HAL_UART_CLEAR_FLAG : Clear the specified UART pending flag
(+) __HAL_UART_ENABLE_IT: Enable the specified UART interrupt
(+) __HAL_UART_DISABLE_IT: Disable the specified UART interrupt
(+) __HAL_UART_GET_IT_SOURCE: Check whether the specified UART interrupt has occurred or not
[..]
(@) You can refer to the UART HAL driver header file for more useful macros
@endverbatim
[..]
(@) Additional remark: If the parity is enabled, then the MSB bit of the data written
in the data register is transmitted but is changed by the parity bit.
Depending on the frame length defined by the M bit (8-bits or 9-bits),
the possible UART frame formats are as listed in the following table:
+-------------------------------------------------------------+
| M bit | PCE bit | UART frame |
|---------------------|---------------------------------------|
| 0 | 0 | | SB | 8 bit data | STB | |
|---------|-----------|---------------------------------------|
| 0 | 1 | | SB | 7 bit data | PB | STB | |
|---------|-----------|---------------------------------------|
| 1 | 0 | | SB | 9 bit data | STB | |
|---------|-----------|---------------------------------------|
| 1 | 1 | | SB | 8 bit data | PB | STB | |
+-------------------------------------------------------------+
******************************************************************************
*/
/* Includes ------------------------------------------------------------------*/
#include "stm32f1xx_hal.h"
/** @addtogroup STM32F1xx_HAL_Driver
* @{
*/
/** @defgroup UART UART
* @brief HAL UART module driver
* @{
*/
#ifdef HAL_UART_MODULE_ENABLED
/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
/** @addtogroup UART_Private_Constants
* @{
*/
/**
* @}
*/
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
/* Private function prototypes -----------------------------------------------*/
/** @addtogroup UART_Private_Functions UART Private Functions
* @{
*/
#if (USE_HAL_UART_REGISTER_CALLBACKS == 1)
void UART_InitCallbacksToDefault(UART_HandleTypeDef *huart);
#endif /* USE_HAL_UART_REGISTER_CALLBACKS */
static void UART_EndTxTransfer(UART_HandleTypeDef *huart);
static void UART_EndRxTransfer(UART_HandleTypeDef *huart);
static void UART_DMATransmitCplt(DMA_HandleTypeDef *hdma);
static void UART_DMAReceiveCplt(DMA_HandleTypeDef *hdma);
static void UART_DMATxHalfCplt(DMA_HandleTypeDef *hdma);
static void UART_DMARxHalfCplt(DMA_HandleTypeDef *hdma);
static void UART_DMAError(DMA_HandleTypeDef *hdma);
static void UART_DMAAbortOnError(DMA_HandleTypeDef *hdma);
static void UART_DMATxAbortCallback(DMA_HandleTypeDef *hdma);
static void UART_DMARxAbortCallback(DMA_HandleTypeDef *hdma);
static void UART_DMATxOnlyAbortCallback(DMA_HandleTypeDef *hdma);
static void UART_DMARxOnlyAbortCallback(DMA_HandleTypeDef *hdma);
static HAL_StatusTypeDef UART_Transmit_IT(UART_HandleTypeDef *huart);
static HAL_StatusTypeDef UART_EndTransmit_IT(UART_HandleTypeDef *huart);
static HAL_StatusTypeDef UART_Receive_IT(UART_HandleTypeDef *huart);
static HAL_StatusTypeDef UART_WaitOnFlagUntilTimeout(UART_HandleTypeDef *huart, uint32_t Flag, FlagStatus Status,
uint32_t Tickstart, uint32_t Timeout);
static void UART_SetConfig(UART_HandleTypeDef *huart);
/**
* @}
*/
/* Exported functions ---------------------------------------------------------*/
/** @defgroup UART_Exported_Functions UART Exported Functions
* @{
*/
/** @defgroup UART_Exported_Functions_Group1 Initialization and de-initialization functions
* @brief Initialization and Configuration functions
*
@verbatim
===============================================================================
##### Initialization and Configuration functions #####
===============================================================================
[..]
This subsection provides a set of functions allowing to initialize the USARTx or the UARTy
in asynchronous mode.
(+) For the asynchronous mode only these parameters can be configured:
(++) Baud Rate
(++) Word Length
(++) Stop Bit
(++) Parity: If the parity is enabled, then the MSB bit of the data written
in the data register is transmitted but is changed by the parity bit.
Depending on the frame length defined by the M bit (8-bits or 9-bits),
please refer to Reference manual for possible UART frame formats.
(++) Hardware flow control
(++) Receiver/transmitter modes
(++) Over Sampling Method
[..]
The HAL_UART_Init(), HAL_HalfDuplex_Init(), HAL_LIN_Init() and HAL_MultiProcessor_Init() APIs
follow respectively the UART asynchronous, UART Half duplex, LIN and Multi-Processor configuration
procedures (details for the procedures are available in reference manuals
(RM0008 for STM32F10Xxx MCUs and RM0041 for STM32F100xx MCUs)).
@endverbatim
* @{
*/
/**
* @brief Initializes the UART mode according to the specified parameters in
* the UART_InitTypeDef and create the associated handle.
* @param huart Pointer to a UART_HandleTypeDef structure that contains
* the configuration information for the specified UART module.
* @retval HAL status
*/
HAL_StatusTypeDef HAL_UART_Init(UART_HandleTypeDef *huart)
{
/* Check the UART handle allocation */
if (huart == NULL)
{
return HAL_ERROR;
}
/* Check the parameters */
if (huart->Init.HwFlowCtl != UART_HWCONTROL_NONE)
{
/* The hardware flow control is available only for USART1, USART2 and USART3 */
assert_param(IS_UART_HWFLOW_INSTANCE(huart->Instance));
assert_param(IS_UART_HARDWARE_FLOW_CONTROL(huart->Init.HwFlowCtl));
}
else
{
assert_param(IS_UART_INSTANCE(huart->Instance));
}
assert_param(IS_UART_WORD_LENGTH(huart->Init.WordLength));
#if defined(USART_CR1_OVER8)
assert_param(IS_UART_OVERSAMPLING(huart->Init.OverSampling));
#endif /* USART_CR1_OVER8 */
if (huart->gState == HAL_UART_STATE_RESET)
{
/* Allocate lock resource and initialize it */
huart->Lock = HAL_UNLOCKED;
#if (USE_HAL_UART_REGISTER_CALLBACKS == 1)
UART_InitCallbacksToDefault(huart);
if (huart->MspInitCallback == NULL)
{
huart->MspInitCallback = HAL_UART_MspInit;
}
/* Init the low level hardware */
huart->MspInitCallback(huart);
#else
/* Init the low level hardware : GPIO, CLOCK */
HAL_UART_MspInit(huart);
#endif /* (USE_HAL_UART_REGISTER_CALLBACKS) */
}
huart->gState = HAL_UART_STATE_BUSY;
/* Disable the peripheral */
__HAL_UART_DISABLE(huart);
/* Set the UART Communication parameters */
UART_SetConfig(huart);
/* In asynchronous mode, the following bits must be kept cleared:
- LINEN and CLKEN bits in the USART_CR2 register,
- SCEN, HDSEL and IREN bits in the USART_CR3 register.*/
CLEAR_BIT(huart->Instance->CR2, (USART_CR2_LINEN | USART_CR2_CLKEN));
CLEAR_BIT(huart->Instance->CR3, (USART_CR3_SCEN | USART_CR3_HDSEL | USART_CR3_IREN));
/* Enable the peripheral */
__HAL_UART_ENABLE(huart);
/* Initialize the UART state */
huart->ErrorCode = HAL_UART_ERROR_NONE;
huart->gState = HAL_UART_STATE_READY;
huart->RxState = HAL_UART_STATE_READY;
huart->RxEventType = HAL_UART_RXEVENT_TC;
return HAL_OK;
}
/**
* @brief Initializes the half-duplex mode according to the specified
* parameters in the UART_InitTypeDef and create the associated handle.
* @param huart Pointer to a UART_HandleTypeDef structure that contains
* the configuration information for the specified UART module.
* @retval HAL status
*/
HAL_StatusTypeDef HAL_HalfDuplex_Init(UART_HandleTypeDef *huart)
{
/* Check the UART handle allocation */
if (huart == NULL)
{
return HAL_ERROR;
}
/* Check the parameters */
assert_param(IS_UART_HALFDUPLEX_INSTANCE(huart->Instance));
assert_param(IS_UART_WORD_LENGTH(huart->Init.WordLength));
#if defined(USART_CR1_OVER8)
assert_param(IS_UART_OVERSAMPLING(huart->Init.OverSampling));
#endif /* USART_CR1_OVER8 */
if (huart->gState == HAL_UART_STATE_RESET)
{
/* Allocate lock resource and initialize it */
huart->Lock = HAL_UNLOCKED;
#if (USE_HAL_UART_REGISTER_CALLBACKS == 1)
UART_InitCallbacksToDefault(huart);
if (huart->MspInitCallback == NULL)
{
huart->MspInitCallback = HAL_UART_MspInit;
}
/* Init the low level hardware */
huart->MspInitCallback(huart);
#else
/* Init the low level hardware : GPIO, CLOCK */
HAL_UART_MspInit(huart);
#endif /* (USE_HAL_UART_REGISTER_CALLBACKS) */
}
huart->gState = HAL_UART_STATE_BUSY;
/* Disable the peripheral */
__HAL_UART_DISABLE(huart);
/* Set the UART Communication parameters */
UART_SetConfig(huart);
/* In half-duplex mode, the following bits must be kept cleared:
- LINEN and CLKEN bits in the USART_CR2 register,
- SCEN and IREN bits in the USART_CR3 register.*/
CLEAR_BIT(huart->Instance->CR2, (USART_CR2_LINEN | USART_CR2_CLKEN));
CLEAR_BIT(huart->Instance->CR3, (USART_CR3_IREN | USART_CR3_SCEN));
/* Enable the Half-Duplex mode by setting the HDSEL bit in the CR3 register */
SET_BIT(huart->Instance->CR3, USART_CR3_HDSEL);
/* Enable the peripheral */
__HAL_UART_ENABLE(huart);
/* Initialize the UART state*/
huart->ErrorCode = HAL_UART_ERROR_NONE;
huart->gState = HAL_UART_STATE_READY;
huart->RxState = HAL_UART_STATE_READY;
huart->RxEventType = HAL_UART_RXEVENT_TC;
return HAL_OK;
}
/**
* @brief Initializes the LIN mode according to the specified
* parameters in the UART_InitTypeDef and create the associated handle.
* @param huart Pointer to a UART_HandleTypeDef structure that contains
* the configuration information for the specified UART module.
* @param BreakDetectLength Specifies the LIN break detection length.
* This parameter can be one of the following values:
* @arg UART_LINBREAKDETECTLENGTH_10B: 10-bit break detection
* @arg UART_LINBREAKDETECTLENGTH_11B: 11-bit break detection
* @retval HAL status
*/
HAL_StatusTypeDef HAL_LIN_Init(UART_HandleTypeDef *huart, uint32_t BreakDetectLength)
{
/* Check the UART handle allocation */
if (huart == NULL)
{
return HAL_ERROR;
}
/* Check the LIN UART instance */
assert_param(IS_UART_LIN_INSTANCE(huart->Instance));
/* Check the Break detection length parameter */
assert_param(IS_UART_LIN_BREAK_DETECT_LENGTH(BreakDetectLength));
assert_param(IS_UART_LIN_WORD_LENGTH(huart->Init.WordLength));
#if defined(USART_CR1_OVER8)
assert_param(IS_UART_LIN_OVERSAMPLING(huart->Init.OverSampling));
#endif /* USART_CR1_OVER8 */
if (huart->gState == HAL_UART_STATE_RESET)
{
/* Allocate lock resource and initialize it */
huart->Lock = HAL_UNLOCKED;
#if (USE_HAL_UART_REGISTER_CALLBACKS == 1)
UART_InitCallbacksToDefault(huart);
if (huart->MspInitCallback == NULL)
{
huart->MspInitCallback = HAL_UART_MspInit;
}
/* Init the low level hardware */
huart->MspInitCallback(huart);
#else
/* Init the low level hardware : GPIO, CLOCK */
HAL_UART_MspInit(huart);
#endif /* (USE_HAL_UART_REGISTER_CALLBACKS) */
}
huart->gState = HAL_UART_STATE_BUSY;
/* Disable the peripheral */
__HAL_UART_DISABLE(huart);
/* Set the UART Communication parameters */
UART_SetConfig(huart);
/* In LIN mode, the following bits must be kept cleared:
- CLKEN bits in the USART_CR2 register,
- SCEN, HDSEL and IREN bits in the USART_CR3 register.*/
CLEAR_BIT(huart->Instance->CR2, (USART_CR2_CLKEN));
CLEAR_BIT(huart->Instance->CR3, (USART_CR3_HDSEL | USART_CR3_IREN | USART_CR3_SCEN));
/* Enable the LIN mode by setting the LINEN bit in the CR2 register */
SET_BIT(huart->Instance->CR2, USART_CR2_LINEN);
/* Set the USART LIN Break detection length. */
CLEAR_BIT(huart->Instance->CR2, USART_CR2_LBDL);
SET_BIT(huart->Instance->CR2, BreakDetectLength);
/* Enable the peripheral */
__HAL_UART_ENABLE(huart);
/* Initialize the UART state*/
huart->ErrorCode = HAL_UART_ERROR_NONE;
huart->gState = HAL_UART_STATE_READY;
huart->RxState = HAL_UART_STATE_READY;
huart->RxEventType = HAL_UART_RXEVENT_TC;
return HAL_OK;
}
/**
* @brief Initializes the Multi-Processor mode according to the specified
* parameters in the UART_InitTypeDef and create the associated handle.
* @param huart Pointer to a UART_HandleTypeDef structure that contains
* the configuration information for the specified UART module.
* @param Address USART address
* @param WakeUpMethod specifies the USART wake-up method.
* This parameter can be one of the following values:
* @arg UART_WAKEUPMETHOD_IDLELINE: Wake-up by an idle line detection
* @arg UART_WAKEUPMETHOD_ADDRESSMARK: Wake-up by an address mark
* @retval HAL status
*/
HAL_StatusTypeDef HAL_MultiProcessor_Init(UART_HandleTypeDef *huart, uint8_t Address, uint32_t WakeUpMethod)
{
/* Check the UART handle allocation */
if (huart == NULL)
{
return HAL_ERROR;
}
/* Check the parameters */
assert_param(IS_UART_INSTANCE(huart->Instance));
/* Check the Address & wake up method parameters */
assert_param(IS_UART_WAKEUPMETHOD(WakeUpMethod));
assert_param(IS_UART_ADDRESS(Address));
assert_param(IS_UART_WORD_LENGTH(huart->Init.WordLength));
#if defined(USART_CR1_OVER8)
assert_param(IS_UART_OVERSAMPLING(huart->Init.OverSampling));
#endif /* USART_CR1_OVER8 */
if (huart->gState == HAL_UART_STATE_RESET)
{
/* Allocate lock resource and initialize it */
huart->Lock = HAL_UNLOCKED;
#if (USE_HAL_UART_REGISTER_CALLBACKS == 1)
UART_InitCallbacksToDefault(huart);
if (huart->MspInitCallback == NULL)
{
huart->MspInitCallback = HAL_UART_MspInit;
}
/* Init the low level hardware */
huart->MspInitCallback(huart);
#else
/* Init the low level hardware : GPIO, CLOCK */
HAL_UART_MspInit(huart);
#endif /* (USE_HAL_UART_REGISTER_CALLBACKS) */
}
huart->gState = HAL_UART_STATE_BUSY;
/* Disable the peripheral */
__HAL_UART_DISABLE(huart);
/* Set the UART Communication parameters */
UART_SetConfig(huart);
/* In Multi-Processor mode, the following bits must be kept cleared:
- LINEN and CLKEN bits in the USART_CR2 register,
- SCEN, HDSEL and IREN bits in the USART_CR3 register */
CLEAR_BIT(huart->Instance->CR2, (USART_CR2_LINEN | USART_CR2_CLKEN));
CLEAR_BIT(huart->Instance->CR3, (USART_CR3_SCEN | USART_CR3_HDSEL | USART_CR3_IREN));
/* Set the USART address node */
CLEAR_BIT(huart->Instance->CR2, USART_CR2_ADD);
SET_BIT(huart->Instance->CR2, Address);
/* Set the wake up method by setting the WAKE bit in the CR1 register */
CLEAR_BIT(huart->Instance->CR1, USART_CR1_WAKE);
SET_BIT(huart->Instance->CR1, WakeUpMethod);
/* Enable the peripheral */
__HAL_UART_ENABLE(huart);
/* Initialize the UART state */
huart->ErrorCode = HAL_UART_ERROR_NONE;
huart->gState = HAL_UART_STATE_READY;
huart->RxState = HAL_UART_STATE_READY;
huart->RxEventType = HAL_UART_RXEVENT_TC;
return HAL_OK;
}
/**
* @brief DeInitializes the UART peripheral.
* @param huart Pointer to a UART_HandleTypeDef structure that contains
* the configuration information for the specified UART module.
* @retval HAL status
*/
HAL_StatusTypeDef HAL_UART_DeInit(UART_HandleTypeDef *huart)
{
/* Check the UART handle allocation */
if (huart == NULL)
{
return HAL_ERROR;
}
/* Check the parameters */
assert_param(IS_UART_INSTANCE(huart->Instance));
huart->gState = HAL_UART_STATE_BUSY;
/* Disable the Peripheral */
__HAL_UART_DISABLE(huart);
#if (USE_HAL_UART_REGISTER_CALLBACKS == 1)
if (huart->MspDeInitCallback == NULL)
{
huart->MspDeInitCallback = HAL_UART_MspDeInit;
}
/* DeInit the low level hardware */
huart->MspDeInitCallback(huart);
#else
/* DeInit the low level hardware */
HAL_UART_MspDeInit(huart);
#endif /* (USE_HAL_UART_REGISTER_CALLBACKS) */
huart->ErrorCode = HAL_UART_ERROR_NONE;
huart->gState = HAL_UART_STATE_RESET;
huart->RxState = HAL_UART_STATE_RESET;
huart->ReceptionType = HAL_UART_RECEPTION_STANDARD;
huart->RxEventType = HAL_UART_RXEVENT_TC;
/* Process Unlock */
__HAL_UNLOCK(huart);
return HAL_OK;
}
/**
* @brief UART MSP Init.
* @param huart Pointer to a UART_HandleTypeDef structure that contains
* the configuration information for the specified UART module.
* @retval None
*/
__weak void HAL_UART_MspInit(UART_HandleTypeDef *huart)
{
/* Prevent unused argument(s) compilation warning */
UNUSED(huart);
/* NOTE: This function should not be modified, when the callback is needed,
the HAL_UART_MspInit could be implemented in the user file
*/
}
/**
* @brief UART MSP DeInit.
* @param huart Pointer to a UART_HandleTypeDef structure that contains
* the configuration information for the specified UART module.
* @retval None
*/
__weak void HAL_UART_MspDeInit(UART_HandleTypeDef *huart)
{
/* Prevent unused argument(s) compilation warning */
UNUSED(huart);
/* NOTE: This function should not be modified, when the callback is needed,
the HAL_UART_MspDeInit could be implemented in the user file
*/
}
#if (USE_HAL_UART_REGISTER_CALLBACKS == 1)
/**
* @brief Register a User UART Callback
* To be used instead of the weak predefined callback
* @note The HAL_UART_RegisterCallback() may be called before HAL_UART_Init(), HAL_HalfDuplex_Init(), HAL_LIN_Init(),
* HAL_MultiProcessor_Init() to register callbacks for HAL_UART_MSPINIT_CB_ID and HAL_UART_MSPDEINIT_CB_ID
* @param huart uart handle
* @param CallbackID ID of the callback to be registered
* This parameter can be one of the following values:
* @arg @ref HAL_UART_TX_HALFCOMPLETE_CB_ID Tx Half Complete Callback ID
* @arg @ref HAL_UART_TX_COMPLETE_CB_ID Tx Complete Callback ID
* @arg @ref HAL_UART_RX_HALFCOMPLETE_CB_ID Rx Half Complete Callback ID
* @arg @ref HAL_UART_RX_COMPLETE_CB_ID Rx Complete Callback ID
* @arg @ref HAL_UART_ERROR_CB_ID Error Callback ID
* @arg @ref HAL_UART_ABORT_COMPLETE_CB_ID Abort Complete Callback ID
* @arg @ref HAL_UART_ABORT_TRANSMIT_COMPLETE_CB_ID Abort Transmit Complete Callback ID
* @arg @ref HAL_UART_ABORT_RECEIVE_COMPLETE_CB_ID Abort Receive Complete Callback ID
* @arg @ref HAL_UART_MSPINIT_CB_ID MspInit Callback ID
* @arg @ref HAL_UART_MSPDEINIT_CB_ID MspDeInit Callback ID
* @param pCallback pointer to the Callback function
* @retval HAL status
*/
HAL_StatusTypeDef HAL_UART_RegisterCallback(UART_HandleTypeDef *huart, HAL_UART_CallbackIDTypeDef CallbackID,
pUART_CallbackTypeDef pCallback)
{
HAL_StatusTypeDef status = HAL_OK;
if (pCallback == NULL)
{
/* Update the error code */
huart->ErrorCode |= HAL_UART_ERROR_INVALID_CALLBACK;
return HAL_ERROR;
}
if (huart->gState == HAL_UART_STATE_READY)
{
switch (CallbackID)
{
case HAL_UART_TX_HALFCOMPLETE_CB_ID :
huart->TxHalfCpltCallback = pCallback;
break;
case HAL_UART_TX_COMPLETE_CB_ID :
huart->TxCpltCallback = pCallback;
break;
case HAL_UART_RX_HALFCOMPLETE_CB_ID :
huart->RxHalfCpltCallback = pCallback;
break;
case HAL_UART_RX_COMPLETE_CB_ID :
huart->RxCpltCallback = pCallback;
break;
case HAL_UART_ERROR_CB_ID :
huart->ErrorCallback = pCallback;
break;
case HAL_UART_ABORT_COMPLETE_CB_ID :
huart->AbortCpltCallback = pCallback;
break;
case HAL_UART_ABORT_TRANSMIT_COMPLETE_CB_ID :
huart->AbortTransmitCpltCallback = pCallback;
break;
case HAL_UART_ABORT_RECEIVE_COMPLETE_CB_ID :
huart->AbortReceiveCpltCallback = pCallback;
break;
case HAL_UART_MSPINIT_CB_ID :
huart->MspInitCallback = pCallback;
break;
case HAL_UART_MSPDEINIT_CB_ID :
huart->MspDeInitCallback = pCallback;
break;
default :
/* Update the error code */
huart->ErrorCode |= HAL_UART_ERROR_INVALID_CALLBACK;
/* Return error status */
status = HAL_ERROR;
break;
}
}
else if (huart->gState == HAL_UART_STATE_RESET)
{
switch (CallbackID)
{
case HAL_UART_MSPINIT_CB_ID :
huart->MspInitCallback = pCallback;
break;
case HAL_UART_MSPDEINIT_CB_ID :
huart->MspDeInitCallback = pCallback;
break;
default :
/* Update the error code */
huart->ErrorCode |= HAL_UART_ERROR_INVALID_CALLBACK;
/* Return error status */
status = HAL_ERROR;
break;
}
}
else
{
/* Update the error code */
huart->ErrorCode |= HAL_UART_ERROR_INVALID_CALLBACK;
/* Return error status */
status = HAL_ERROR;
}
return status;
}
/**
* @brief Unregister an UART Callback
* UART callaback is redirected to the weak predefined callback
* @note The HAL_UART_UnRegisterCallback() may be called before HAL_UART_Init(), HAL_HalfDuplex_Init(),
* HAL_LIN_Init(), HAL_MultiProcessor_Init() to un-register callbacks for HAL_UART_MSPINIT_CB_ID
* and HAL_UART_MSPDEINIT_CB_ID
* @param huart uart handle
* @param CallbackID ID of the callback to be unregistered
* This parameter can be one of the following values:
* @arg @ref HAL_UART_TX_HALFCOMPLETE_CB_ID Tx Half Complete Callback ID
* @arg @ref HAL_UART_TX_COMPLETE_CB_ID Tx Complete Callback ID
* @arg @ref HAL_UART_RX_HALFCOMPLETE_CB_ID Rx Half Complete Callback ID
* @arg @ref HAL_UART_RX_COMPLETE_CB_ID Rx Complete Callback ID
* @arg @ref HAL_UART_ERROR_CB_ID Error Callback ID
* @arg @ref HAL_UART_ABORT_COMPLETE_CB_ID Abort Complete Callback ID
* @arg @ref HAL_UART_ABORT_TRANSMIT_COMPLETE_CB_ID Abort Transmit Complete Callback ID
* @arg @ref HAL_UART_ABORT_RECEIVE_COMPLETE_CB_ID Abort Receive Complete Callback ID
* @arg @ref HAL_UART_MSPINIT_CB_ID MspInit Callback ID
* @arg @ref HAL_UART_MSPDEINIT_CB_ID MspDeInit Callback ID
* @retval HAL status
*/
HAL_StatusTypeDef HAL_UART_UnRegisterCallback(UART_HandleTypeDef *huart, HAL_UART_CallbackIDTypeDef CallbackID)
{
HAL_StatusTypeDef status = HAL_OK;
if (HAL_UART_STATE_READY == huart->gState)
{
switch (CallbackID)
{
case HAL_UART_TX_HALFCOMPLETE_CB_ID :
huart->TxHalfCpltCallback = HAL_UART_TxHalfCpltCallback; /* Legacy weak TxHalfCpltCallback */
break;
case HAL_UART_TX_COMPLETE_CB_ID :
huart->TxCpltCallback = HAL_UART_TxCpltCallback; /* Legacy weak TxCpltCallback */
break;
case HAL_UART_RX_HALFCOMPLETE_CB_ID :
huart->RxHalfCpltCallback = HAL_UART_RxHalfCpltCallback; /* Legacy weak RxHalfCpltCallback */
break;
case HAL_UART_RX_COMPLETE_CB_ID :
huart->RxCpltCallback = HAL_UART_RxCpltCallback; /* Legacy weak RxCpltCallback */
break;
case HAL_UART_ERROR_CB_ID :
huart->ErrorCallback = HAL_UART_ErrorCallback; /* Legacy weak ErrorCallback */
break;
case HAL_UART_ABORT_COMPLETE_CB_ID :
huart->AbortCpltCallback = HAL_UART_AbortCpltCallback; /* Legacy weak AbortCpltCallback */
break;
case HAL_UART_ABORT_TRANSMIT_COMPLETE_CB_ID :
huart->AbortTransmitCpltCallback = HAL_UART_AbortTransmitCpltCallback; /* Legacy weak AbortTransmitCpltCallback */
break;
case HAL_UART_ABORT_RECEIVE_COMPLETE_CB_ID :
huart->AbortReceiveCpltCallback = HAL_UART_AbortReceiveCpltCallback; /* Legacy weak AbortReceiveCpltCallback */
break;
case HAL_UART_MSPINIT_CB_ID :
huart->MspInitCallback = HAL_UART_MspInit; /* Legacy weak MspInitCallback */
break;
case HAL_UART_MSPDEINIT_CB_ID :
huart->MspDeInitCallback = HAL_UART_MspDeInit; /* Legacy weak MspDeInitCallback */
break;
default :
/* Update the error code */
huart->ErrorCode |= HAL_UART_ERROR_INVALID_CALLBACK;
/* Return error status */
status = HAL_ERROR;
break;
}
}
else if (HAL_UART_STATE_RESET == huart->gState)
{
switch (CallbackID)
{
case HAL_UART_MSPINIT_CB_ID :
huart->MspInitCallback = HAL_UART_MspInit;
break;
case HAL_UART_MSPDEINIT_CB_ID :
huart->MspDeInitCallback = HAL_UART_MspDeInit;
break;
default :
/* Update the error code */
huart->ErrorCode |= HAL_UART_ERROR_INVALID_CALLBACK;
/* Return error status */
status = HAL_ERROR;
break;
}
}
else
{
/* Update the error code */
huart->ErrorCode |= HAL_UART_ERROR_INVALID_CALLBACK;
/* Return error status */
status = HAL_ERROR;
}
return status;
}
/**
* @brief Register a User UART Rx Event Callback
* To be used instead of the weak predefined callback
* @param huart Uart handle
* @param pCallback Pointer to the Rx Event Callback function
* @retval HAL status
*/
HAL_StatusTypeDef HAL_UART_RegisterRxEventCallback(UART_HandleTypeDef *huart, pUART_RxEventCallbackTypeDef pCallback)
{
HAL_StatusTypeDef status = HAL_OK;
if (pCallback == NULL)
{
huart->ErrorCode |= HAL_UART_ERROR_INVALID_CALLBACK;
return HAL_ERROR;
}
/* Process locked */
__HAL_LOCK(huart);
if (huart->gState == HAL_UART_STATE_READY)
{
huart->RxEventCallback = pCallback;
}
else
{
huart->ErrorCode |= HAL_UART_ERROR_INVALID_CALLBACK;
status = HAL_ERROR;
}
/* Release Lock */
__HAL_UNLOCK(huart);
return status;
}
/**
* @brief UnRegister the UART Rx Event Callback
* UART Rx Event Callback is redirected to the weak HAL_UARTEx_RxEventCallback() predefined callback
* @param huart Uart handle
* @retval HAL status
*/
HAL_StatusTypeDef HAL_UART_UnRegisterRxEventCallback(UART_HandleTypeDef *huart)
{
HAL_StatusTypeDef status = HAL_OK;
/* Process locked */
__HAL_LOCK(huart);
if (huart->gState == HAL_UART_STATE_READY)
{
huart->RxEventCallback = HAL_UARTEx_RxEventCallback; /* Legacy weak UART Rx Event Callback */
}
else
{
huart->ErrorCode |= HAL_UART_ERROR_INVALID_CALLBACK;
status = HAL_ERROR;
}
/* Release Lock */
__HAL_UNLOCK(huart);
return status;
}
#endif /* USE_HAL_UART_REGISTER_CALLBACKS */
/**
* @}
*/
/** @defgroup UART_Exported_Functions_Group2 IO operation functions
* @brief UART Transmit and Receive functions
*
@verbatim
===============================================================================
##### IO operation functions #####
===============================================================================
This subsection provides a set of functions allowing to manage the UART asynchronous
and Half duplex data transfers.
(#) There are two modes of transfer:
(+) Blocking mode: The communication is performed in polling mode.
The HAL status of all data processing is returned by the same function
after finishing transfer.
(+) Non-Blocking mode: The communication is performed using Interrupts
or DMA, these API's return the HAL status.
The end of the data processing will be indicated through the
dedicated UART IRQ when using Interrupt mode or the DMA IRQ when
using DMA mode.
The HAL_UART_TxCpltCallback(), HAL_UART_RxCpltCallback() user callbacks
will be executed respectively at the end of the transmit or receive process
The HAL_UART_ErrorCallback()user callback will be executed when a communication error is detected.
(#) Blocking mode API's are :
(+) HAL_UART_Transmit()
(+) HAL_UART_Receive()
(#) Non-Blocking mode API's with Interrupt are :
(+) HAL_UART_Transmit_IT()
(+) HAL_UART_Receive_IT()
(+) HAL_UART_IRQHandler()
(#) Non-Blocking mode API's with DMA are :
(+) HAL_UART_Transmit_DMA()
(+) HAL_UART_Receive_DMA()
(+) HAL_UART_DMAPause()
(+) HAL_UART_DMAResume()
(+) HAL_UART_DMAStop()
(#) A set of Transfer Complete Callbacks are provided in Non_Blocking mode:
(+) HAL_UART_TxHalfCpltCallback()
(+) HAL_UART_TxCpltCallback()
(+) HAL_UART_RxHalfCpltCallback()
(+) HAL_UART_RxCpltCallback()
(+) HAL_UART_ErrorCallback()
(#) Non-Blocking mode transfers could be aborted using Abort API's :
(+) HAL_UART_Abort()
(+) HAL_UART_AbortTransmit()
(+) HAL_UART_AbortReceive()
(+) HAL_UART_Abort_IT()
(+) HAL_UART_AbortTransmit_IT()
(+) HAL_UART_AbortReceive_IT()
(#) For Abort services based on interrupts (HAL_UART_Abortxxx_IT), a set of Abort Complete Callbacks are provided:
(+) HAL_UART_AbortCpltCallback()
(+) HAL_UART_AbortTransmitCpltCallback()
(+) HAL_UART_AbortReceiveCpltCallback()
(#) A Rx Event Reception Callback (Rx event notification) is available for Non_Blocking modes of enhanced reception services:
(+) HAL_UARTEx_RxEventCallback()
(#) In Non-Blocking mode transfers, possible errors are split into 2 categories.
Errors are handled as follows :
(+) Error is considered as Recoverable and non blocking : Transfer could go till end, but error severity is
to be evaluated by user : this concerns Frame Error, Parity Error or Noise Error in Interrupt mode reception .
Received character is then retrieved and stored in Rx buffer, Error code is set to allow user to identify error type,
and HAL_UART_ErrorCallback() user callback is executed. Transfer is kept ongoing on UART side.
If user wants to abort it, Abort services should be called by user.
(+) Error is considered as Blocking : Transfer could not be completed properly and is aborted.
This concerns Overrun Error In Interrupt mode reception and all errors in DMA mode.
Error code is set to allow user to identify error type, and HAL_UART_ErrorCallback() user callback is executed.
-@- In the Half duplex communication, it is forbidden to run the transmit
and receive process in parallel, the UART state HAL_UART_STATE_BUSY_TX_RX can't be useful.
@endverbatim
* @{
*/
/**
* @brief Sends an amount of data in blocking mode.
* @note When UART parity is not enabled (PCE = 0), and Word Length is configured to 9 bits (M1-M0 = 01),
* the sent data is handled as a set of u16. In this case, Size must indicate the number
* of u16 provided through pData.
* @param huart Pointer to a UART_HandleTypeDef structure that contains
* the configuration information for the specified UART module.
* @param pData Pointer to data buffer (u8 or u16 data elements).
* @param Size Amount of data elements (u8 or u16) to be sent
* @param Timeout Timeout duration
* @retval HAL status
*/
HAL_StatusTypeDef HAL_UART_Transmit(UART_HandleTypeDef *huart, const uint8_t *pData, uint16_t Size, uint32_t Timeout)
{
const uint8_t *pdata8bits;
const uint16_t *pdata16bits;
uint32_t tickstart = 0U;
/* Check that a Tx process is not already ongoing */
if (huart->gState == HAL_UART_STATE_READY)
{
if ((pData == NULL) || (Size == 0U))
{
return HAL_ERROR;
}
huart->ErrorCode = HAL_UART_ERROR_NONE;
huart->gState = HAL_UART_STATE_BUSY_TX;
/* Init tickstart for timeout management */
tickstart = HAL_GetTick();
huart->TxXferSize = Size;
huart->TxXferCount = Size;
/* In case of 9bits/No Parity transfer, pData needs to be handled as a uint16_t pointer */
if ((huart->Init.WordLength == UART_WORDLENGTH_9B) && (huart->Init.Parity == UART_PARITY_NONE))
{
pdata8bits = NULL;
pdata16bits = (const uint16_t *) pData;
}
else
{
pdata8bits = pData;
pdata16bits = NULL;
}
while (huart->TxXferCount > 0U)
{
if (UART_WaitOnFlagUntilTimeout(huart, UART_FLAG_TXE, RESET, tickstart, Timeout) != HAL_OK)
{
huart->gState = HAL_UART_STATE_READY;
return HAL_TIMEOUT;
}
if (pdata8bits == NULL)
{
huart->Instance->DR = (uint16_t)(*pdata16bits & 0x01FFU);
pdata16bits++;
}
else
{
huart->Instance->DR = (uint8_t)(*pdata8bits & 0xFFU);
pdata8bits++;
}
huart->TxXferCount--;
}
if (UART_WaitOnFlagUntilTimeout(huart, UART_FLAG_TC, RESET, tickstart, Timeout) != HAL_OK)
{
huart->gState = HAL_UART_STATE_READY;
return HAL_TIMEOUT;
}
/* At end of Tx process, restore huart->gState to Ready */
huart->gState = HAL_UART_STATE_READY;
return HAL_OK;
}
else
{
return HAL_BUSY;
}
}
/**
* @brief Receives an amount of data in blocking mode.
* @note When UART parity is not enabled (PCE = 0), and Word Length is configured to 9 bits (M1-M0 = 01),
* the received data is handled as a set of u16. In this case, Size must indicate the number
* of u16 available through pData.
* @param huart Pointer to a UART_HandleTypeDef structure that contains
* the configuration information for the specified UART module.
* @param pData Pointer to data buffer (u8 or u16 data elements).
* @param Size Amount of data elements (u8 or u16) to be received.
* @param Timeout Timeout duration
* @retval HAL status
*/
HAL_StatusTypeDef HAL_UART_Receive(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size, uint32_t Timeout)
{
uint8_t *pdata8bits;
uint16_t *pdata16bits;
uint32_t tickstart = 0U;
/* Check that a Rx process is not already ongoing */
if (huart->RxState == HAL_UART_STATE_READY)
{
if ((pData == NULL) || (Size == 0U))
{
return HAL_ERROR;
}
huart->ErrorCode = HAL_UART_ERROR_NONE;
huart->RxState = HAL_UART_STATE_BUSY_RX;
huart->ReceptionType = HAL_UART_RECEPTION_STANDARD;
/* Init tickstart for timeout management */
tickstart = HAL_GetTick();
huart->RxXferSize = Size;
huart->RxXferCount = Size;
/* In case of 9bits/No Parity transfer, pRxData needs to be handled as a uint16_t pointer */
if ((huart->Init.WordLength == UART_WORDLENGTH_9B) && (huart->Init.Parity == UART_PARITY_NONE))
{
pdata8bits = NULL;
pdata16bits = (uint16_t *) pData;
}
else
{
pdata8bits = pData;
pdata16bits = NULL;
}
/* Check the remain data to be received */
while (huart->RxXferCount > 0U)
{
if (UART_WaitOnFlagUntilTimeout(huart, UART_FLAG_RXNE, RESET, tickstart, Timeout) != HAL_OK)
{
huart->RxState = HAL_UART_STATE_READY;
return HAL_TIMEOUT;
}
if (pdata8bits == NULL)
{
*pdata16bits = (uint16_t)(huart->Instance->DR & 0x01FF);
pdata16bits++;
}
else
{
if ((huart->Init.WordLength == UART_WORDLENGTH_9B) || ((huart->Init.WordLength == UART_WORDLENGTH_8B) && (huart->Init.Parity == UART_PARITY_NONE)))
{
*pdata8bits = (uint8_t)(huart->Instance->DR & (uint8_t)0x00FF);
}
else
{
*pdata8bits = (uint8_t)(huart->Instance->DR & (uint8_t)0x007F);
}
pdata8bits++;
}
huart->RxXferCount--;
}
/* At end of Rx process, restore huart->RxState to Ready */
huart->RxState = HAL_UART_STATE_READY;
return HAL_OK;
}
else
{
return HAL_BUSY;
}
}
/**
* @brief Sends an amount of data in non blocking mode.
* @note When UART parity is not enabled (PCE = 0), and Word Length is configured to 9 bits (M1-M0 = 01),
* the sent data is handled as a set of u16. In this case, Size must indicate the number
* of u16 provided through pData.
* @param huart Pointer to a UART_HandleTypeDef structure that contains
* the configuration information for the specified UART module.
* @param pData Pointer to data buffer (u8 or u16 data elements).
* @param Size Amount of data elements (u8 or u16) to be sent
* @retval HAL status
*/
HAL_StatusTypeDef HAL_UART_Transmit_IT(UART_HandleTypeDef *huart, const uint8_t *pData, uint16_t Size)
{
/* Check that a Tx process is not already ongoing */
if (huart->gState == HAL_UART_STATE_READY)
{
if ((pData == NULL) || (Size == 0U))
{
return HAL_ERROR;
}
huart->pTxBuffPtr = pData;
huart->TxXferSize = Size;
huart->TxXferCount = Size;
huart->ErrorCode = HAL_UART_ERROR_NONE;
huart->gState = HAL_UART_STATE_BUSY_TX;
/* Enable the UART Transmit data register empty Interrupt */
__HAL_UART_ENABLE_IT(huart, UART_IT_TXE);
return HAL_OK;
}
else
{
return HAL_BUSY;
}
}
/**
* @brief Receives an amount of data in non blocking mode.
* @note When UART parity is not enabled (PCE = 0), and Word Length is configured to 9 bits (M1-M0 = 01),
* the received data is handled as a set of u16. In this case, Size must indicate the number
* of u16 available through pData.
* @param huart Pointer to a UART_HandleTypeDef structure that contains
* the configuration information for the specified UART module.
* @param pData Pointer to data buffer (u8 or u16 data elements).
* @param Size Amount of data elements (u8 or u16) to be received.
* @retval HAL status
*/
HAL_StatusTypeDef HAL_UART_Receive_IT(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size)
{
/* Check that a Rx process is not already ongoing */
if (huart->RxState == HAL_UART_STATE_READY)
{
if ((pData == NULL) || (Size == 0U))
{
return HAL_ERROR;
}
/* Set Reception type to Standard reception */
huart->ReceptionType = HAL_UART_RECEPTION_STANDARD;
return (UART_Start_Receive_IT(huart, pData, Size));
}
else
{
return HAL_BUSY;
}
}
/**
* @brief Sends an amount of data in DMA mode.
* @note When UART parity is not enabled (PCE = 0), and Word Length is configured to 9 bits (M1-M0 = 01),
* the sent data is handled as a set of u16. In this case, Size must indicate the number
* of u16 provided through pData.
* @param huart Pointer to a UART_HandleTypeDef structure that contains
* the configuration information for the specified UART module.
* @param pData Pointer to data buffer (u8 or u16 data elements).
* @param Size Amount of data elements (u8 or u16) to be sent
* @retval HAL status
*/
HAL_StatusTypeDef HAL_UART_Transmit_DMA(UART_HandleTypeDef *huart, const uint8_t *pData, uint16_t Size)
{
const uint32_t *tmp;
/* Check that a Tx process is not already ongoing */
if (huart->gState == HAL_UART_STATE_READY)
{
if ((pData == NULL) || (Size == 0U))
{
return HAL_ERROR;
}
huart->pTxBuffPtr = pData;
huart->TxXferSize = Size;
huart->TxXferCount = Size;
huart->ErrorCode = HAL_UART_ERROR_NONE;
huart->gState = HAL_UART_STATE_BUSY_TX;
/* Set the UART DMA transfer complete callback */
huart->hdmatx->XferCpltCallback = UART_DMATransmitCplt;
/* Set the UART DMA Half transfer complete callback */
huart->hdmatx->XferHalfCpltCallback = UART_DMATxHalfCplt;
/* Set the DMA error callback */
huart->hdmatx->XferErrorCallback = UART_DMAError;
/* Set the DMA abort callback */
huart->hdmatx->XferAbortCallback = NULL;
/* Enable the UART transmit DMA channel */
tmp = (const uint32_t *)&pData;
HAL_DMA_Start_IT(huart->hdmatx, *(const uint32_t *)tmp, (uint32_t)&huart->Instance->DR, Size);
/* Clear the TC flag in the SR register by writing 0 to it */
__HAL_UART_CLEAR_FLAG(huart, UART_FLAG_TC);
/* Enable the DMA transfer for transmit request by setting the DMAT bit
in the UART CR3 register */
ATOMIC_SET_BIT(huart->Instance->CR3, USART_CR3_DMAT);
return HAL_OK;
}
else
{
return HAL_BUSY;
}
}
/**
* @brief Receives an amount of data in DMA mode.
* @note When UART parity is not enabled (PCE = 0), and Word Length is configured to 9 bits (M1-M0 = 01),
* the received data is handled as a set of u16. In this case, Size must indicate the number
* of u16 available through pData.
* @param huart Pointer to a UART_HandleTypeDef structure that contains
* the configuration information for the specified UART module.
* @param pData Pointer to data buffer (u8 or u16 data elements).
* @param Size Amount of data elements (u8 or u16) to be received.
* @note When the UART parity is enabled (PCE = 1) the received data contains the parity bit.
* @retval HAL status
*/
HAL_StatusTypeDef HAL_UART_Receive_DMA(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size)
{
/* Check that a Rx process is not already ongoing */
if (huart->RxState == HAL_UART_STATE_READY)
{
if ((pData == NULL) || (Size == 0U))
{
return HAL_ERROR;
}
/* Set Reception type to Standard reception */
huart->ReceptionType = HAL_UART_RECEPTION_STANDARD;
return (UART_Start_Receive_DMA(huart, pData, Size));
}
else
{
return HAL_BUSY;
}
}
/**
* @brief Pauses the DMA Transfer.
* @param huart Pointer to a UART_HandleTypeDef structure that contains
* the configuration information for the specified UART module.
* @retval HAL status
*/
HAL_StatusTypeDef HAL_UART_DMAPause(UART_HandleTypeDef *huart)
{
uint32_t dmarequest = 0x00U;
dmarequest = HAL_IS_BIT_SET(huart->Instance->CR3, USART_CR3_DMAT);
if ((huart->gState == HAL_UART_STATE_BUSY_TX) && dmarequest)
{
/* Disable the UART DMA Tx request */
ATOMIC_CLEAR_BIT(huart->Instance->CR3, USART_CR3_DMAT);
}
dmarequest = HAL_IS_BIT_SET(huart->Instance->CR3, USART_CR3_DMAR);
if ((huart->RxState == HAL_UART_STATE_BUSY_RX) && dmarequest)
{
/* Disable RXNE, PE and ERR (Frame error, noise error, overrun error) interrupts */
ATOMIC_CLEAR_BIT(huart->Instance->CR1, USART_CR1_PEIE);
ATOMIC_CLEAR_BIT(huart->Instance->CR3, USART_CR3_EIE);
/* Disable the UART DMA Rx request */
ATOMIC_CLEAR_BIT(huart->Instance->CR3, USART_CR3_DMAR);
}
return HAL_OK;
}
/**
* @brief Resumes the DMA Transfer.
* @param huart Pointer to a UART_HandleTypeDef structure that contains
* the configuration information for the specified UART module.
* @retval HAL status
*/
HAL_StatusTypeDef HAL_UART_DMAResume(UART_HandleTypeDef *huart)
{
if (huart->gState == HAL_UART_STATE_BUSY_TX)
{
/* Enable the UART DMA Tx request */
ATOMIC_SET_BIT(huart->Instance->CR3, USART_CR3_DMAT);
}
if (huart->RxState == HAL_UART_STATE_BUSY_RX)
{
/* Clear the Overrun flag before resuming the Rx transfer*/
__HAL_UART_CLEAR_OREFLAG(huart);
/* Re-enable PE and ERR (Frame error, noise error, overrun error) interrupts */
if (huart->Init.Parity != UART_PARITY_NONE)
{
ATOMIC_SET_BIT(huart->Instance->CR1, USART_CR1_PEIE);
}
ATOMIC_SET_BIT(huart->Instance->CR3, USART_CR3_EIE);
/* Enable the UART DMA Rx request */
ATOMIC_SET_BIT(huart->Instance->CR3, USART_CR3_DMAR);
}
return HAL_OK;
}
/**
* @brief Stops the DMA Transfer.
* @param huart Pointer to a UART_HandleTypeDef structure that contains
* the configuration information for the specified UART module.
* @retval HAL status
*/
HAL_StatusTypeDef HAL_UART_DMAStop(UART_HandleTypeDef *huart)
{
uint32_t dmarequest = 0x00U;
/* The Lock is not implemented on this API to allow the user application
to call the HAL UART API under callbacks HAL_UART_TxCpltCallback() / HAL_UART_RxCpltCallback():
when calling HAL_DMA_Abort() API the DMA TX/RX Transfer complete interrupt is generated
and the correspond call back is executed HAL_UART_TxCpltCallback() / HAL_UART_RxCpltCallback()
*/
/* Stop UART DMA Tx request if ongoing */
dmarequest = HAL_IS_BIT_SET(huart->Instance->CR3, USART_CR3_DMAT);
if ((huart->gState == HAL_UART_STATE_BUSY_TX) && dmarequest)
{
ATOMIC_CLEAR_BIT(huart->Instance->CR3, USART_CR3_DMAT);
/* Abort the UART DMA Tx channel */
if (huart->hdmatx != NULL)
{
HAL_DMA_Abort(huart->hdmatx);
}
UART_EndTxTransfer(huart);
}
/* Stop UART DMA Rx request if ongoing */
dmarequest = HAL_IS_BIT_SET(huart->Instance->CR3, USART_CR3_DMAR);
if ((huart->RxState == HAL_UART_STATE_BUSY_RX) && dmarequest)
{
ATOMIC_CLEAR_BIT(huart->Instance->CR3, USART_CR3_DMAR);
/* Abort the UART DMA Rx channel */
if (huart->hdmarx != NULL)
{
HAL_DMA_Abort(huart->hdmarx);
}
UART_EndRxTransfer(huart);
}
return HAL_OK;
}
/**
* @brief Receive an amount of data in blocking mode till either the expected number of data is received or an IDLE event occurs.
* @note HAL_OK is returned if reception is completed (expected number of data has been received)
* or if reception is stopped after IDLE event (less than the expected number of data has been received)
* In this case, RxLen output parameter indicates number of data available in reception buffer.
* @note When UART parity is not enabled (PCE = 0), and Word Length is configured to 9 bits (M = 01),
* the received data is handled as a set of uint16_t. In this case, Size must indicate the number
* of uint16_t available through pData.
* @param huart UART handle.
* @param pData Pointer to data buffer (uint8_t or uint16_t data elements).
* @param Size Amount of data elements (uint8_t or uint16_t) to be received.
* @param RxLen Number of data elements finally received (could be lower than Size, in case reception ends on IDLE event)
* @param Timeout Timeout duration expressed in ms (covers the whole reception sequence).
* @retval HAL status
*/
HAL_StatusTypeDef HAL_UARTEx_ReceiveToIdle(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size, uint16_t *RxLen,
uint32_t Timeout)
{
uint8_t *pdata8bits;
uint16_t *pdata16bits;
uint32_t tickstart;
/* Check that a Rx process is not already ongoing */
if (huart->RxState == HAL_UART_STATE_READY)
{
if ((pData == NULL) || (Size == 0U))
{
return HAL_ERROR;
}
huart->ErrorCode = HAL_UART_ERROR_NONE;
huart->RxState = HAL_UART_STATE_BUSY_RX;
huart->ReceptionType = HAL_UART_RECEPTION_TOIDLE;
huart->RxEventType = HAL_UART_RXEVENT_TC;
/* Init tickstart for timeout management */
tickstart = HAL_GetTick();
huart->RxXferSize = Size;
huart->RxXferCount = Size;
/* In case of 9bits/No Parity transfer, pRxData needs to be handled as a uint16_t pointer */
if ((huart->Init.WordLength == UART_WORDLENGTH_9B) && (huart->Init.Parity == UART_PARITY_NONE))
{
pdata8bits = NULL;
pdata16bits = (uint16_t *) pData;
}
else
{
pdata8bits = pData;
pdata16bits = NULL;
}
/* Initialize output number of received elements */
*RxLen = 0U;
/* as long as data have to be received */
while (huart->RxXferCount > 0U)
{
/* Check if IDLE flag is set */
if (__HAL_UART_GET_FLAG(huart, UART_FLAG_IDLE))
{
/* Clear IDLE flag in ISR */
__HAL_UART_CLEAR_IDLEFLAG(huart);
/* If Set, but no data ever received, clear flag without exiting loop */
/* If Set, and data has already been received, this means Idle Event is valid : End reception */
if (*RxLen > 0U)
{
huart->RxEventType = HAL_UART_RXEVENT_IDLE;
huart->RxState = HAL_UART_STATE_READY;
return HAL_OK;
}
}
/* Check if RXNE flag is set */
if (__HAL_UART_GET_FLAG(huart, UART_FLAG_RXNE))
{
if (pdata8bits == NULL)
{
*pdata16bits = (uint16_t)(huart->Instance->DR & (uint16_t)0x01FF);
pdata16bits++;
}
else
{
if ((huart->Init.WordLength == UART_WORDLENGTH_9B) || ((huart->Init.WordLength == UART_WORDLENGTH_8B) && (huart->Init.Parity == UART_PARITY_NONE)))
{
*pdata8bits = (uint8_t)(huart->Instance->DR & (uint8_t)0x00FF);
}
else
{
*pdata8bits = (uint8_t)(huart->Instance->DR & (uint8_t)0x007F);
}
pdata8bits++;
}
/* Increment number of received elements */
*RxLen += 1U;
huart->RxXferCount--;
}
/* Check for the Timeout */
if (Timeout != HAL_MAX_DELAY)
{
if (((HAL_GetTick() - tickstart) > Timeout) || (Timeout == 0U))
{
huart->RxState = HAL_UART_STATE_READY;
return HAL_TIMEOUT;
}
}
}
/* Set number of received elements in output parameter : RxLen */
*RxLen = huart->RxXferSize - huart->RxXferCount;
/* At end of Rx process, restore huart->RxState to Ready */
huart->RxState = HAL_UART_STATE_READY;
return HAL_OK;
}
else
{
return HAL_BUSY;
}
}
/**
* @brief Receive an amount of data in interrupt mode till either the expected number of data is received or an IDLE event occurs.
* @note Reception is initiated by this function call. Further progress of reception is achieved thanks
* to UART interrupts raised by RXNE and IDLE events. Callback is called at end of reception indicating
* number of received data elements.
* @note When UART parity is not enabled (PCE = 0), and Word Length is configured to 9 bits (M = 01),
* the received data is handled as a set of uint16_t. In this case, Size must indicate the number
* of uint16_t available through pData.
* @param huart UART handle.
* @param pData Pointer to data buffer (uint8_t or uint16_t data elements).
* @param Size Amount of data elements (uint8_t or uint16_t) to be received.
* @retval HAL status
*/
HAL_StatusTypeDef HAL_UARTEx_ReceiveToIdle_IT(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size)
{
HAL_StatusTypeDef status;
/* Check that a Rx process is not already ongoing */
if (huart->RxState == HAL_UART_STATE_READY)
{
if ((pData == NULL) || (Size == 0U))
{
return HAL_ERROR;
}
/* Set Reception type to reception till IDLE Event*/
huart->ReceptionType = HAL_UART_RECEPTION_TOIDLE;
huart->RxEventType = HAL_UART_RXEVENT_TC;
status = UART_Start_Receive_IT(huart, pData, Size);
/* Check Rx process has been successfully started */
if (status == HAL_OK)
{
if (huart->ReceptionType == HAL_UART_RECEPTION_TOIDLE)
{
__HAL_UART_CLEAR_IDLEFLAG(huart);
ATOMIC_SET_BIT(huart->Instance->CR1, USART_CR1_IDLEIE);
}
else
{
/* In case of errors already pending when reception is started,
Interrupts may have already been raised and lead to reception abortion.
(Overrun error for instance).
In such case Reception Type has been reset to HAL_UART_RECEPTION_STANDARD. */
status = HAL_ERROR;
}
}
return status;
}
else
{
return HAL_BUSY;
}
}
/**
* @brief Receive an amount of data in DMA mode till either the expected number of data is received or an IDLE event occurs.
* @note Reception is initiated by this function call. Further progress of reception is achieved thanks
* to DMA services, transferring automatically received data elements in user reception buffer and
* calling registered callbacks at half/end of reception. UART IDLE events are also used to consider
* reception phase as ended. In all cases, callback execution will indicate number of received data elements.
* @note When the UART parity is enabled (PCE = 1), the received data contain
* the parity bit (MSB position).
* @note When UART parity is not enabled (PCE = 0), and Word Length is configured to 9 bits (M = 01),
* the received data is handled as a set of uint16_t. In this case, Size must indicate the number
* of uint16_t available through pData.
* @param huart UART handle.
* @param pData Pointer to data buffer (uint8_t or uint16_t data elements).
* @param Size Amount of data elements (uint8_t or uint16_t) to be received.
* @retval HAL status
*/
HAL_StatusTypeDef HAL_UARTEx_ReceiveToIdle_DMA(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size)
{
HAL_StatusTypeDef status;
/* Check that a Rx process is not already ongoing */
if (huart->RxState == HAL_UART_STATE_READY)
{
if ((pData == NULL) || (Size == 0U))
{
return HAL_ERROR;
}
/* Set Reception type to reception till IDLE Event*/
huart->ReceptionType = HAL_UART_RECEPTION_TOIDLE;
huart->RxEventType = HAL_UART_RXEVENT_TC;
status = UART_Start_Receive_DMA(huart, pData, Size);
/* Check Rx process has been successfully started */
if (huart->ReceptionType == HAL_UART_RECEPTION_TOIDLE)
{
__HAL_UART_CLEAR_IDLEFLAG(huart);
ATOMIC_SET_BIT(huart->Instance->CR1, USART_CR1_IDLEIE);
}
else
{
/* In case of errors already pending when reception is started,
Interrupts may have already been raised and lead to reception abortion.
(Overrun error for instance).
In such case Reception Type has been reset to HAL_UART_RECEPTION_STANDARD. */
status = HAL_ERROR;
}
return status;
}
else
{
return HAL_BUSY;
}
}
/**
* @brief Provide Rx Event type that has lead to RxEvent callback execution.
* @note When HAL_UARTEx_ReceiveToIdle_IT() or HAL_UARTEx_ReceiveToIdle_DMA() API are called, progress
* of reception process is provided to application through calls of Rx Event callback (either default one
* HAL_UARTEx_RxEventCallback() or user registered one). As several types of events could occur (IDLE event,
* Half Transfer, or Transfer Complete), this function allows to retrieve the Rx Event type that has lead
* to Rx Event callback execution.
* @note This function is expected to be called within the user implementation of Rx Event Callback,
* in order to provide the accurate value :
* In Interrupt Mode :
* - HAL_UART_RXEVENT_TC : when Reception has been completed (expected nb of data has been received)
* - HAL_UART_RXEVENT_IDLE : when Idle event occurred prior reception has been completed (nb of
* received data is lower than expected one)
* In DMA Mode :
* - HAL_UART_RXEVENT_TC : when Reception has been completed (expected nb of data has been received)
* - HAL_UART_RXEVENT_HT : when half of expected nb of data has been received
* - HAL_UART_RXEVENT_IDLE : when Idle event occurred prior reception has been completed (nb of
* received data is lower than expected one).
* In DMA mode, RxEvent callback could be called several times;
* When DMA is configured in Normal Mode, HT event does not stop Reception process;
* When DMA is configured in Circular Mode, HT, TC or IDLE events don't stop Reception process;
* @param huart UART handle.
* @retval Rx Event Type (returned value will be a value of @ref UART_RxEvent_Type_Values)
*/
HAL_UART_RxEventTypeTypeDef HAL_UARTEx_GetRxEventType(UART_HandleTypeDef *huart)
{
/* Return Rx Event type value, as stored in UART handle */
return(huart->RxEventType);
}
/**
* @brief Abort ongoing transfers (blocking mode).
* @param huart UART handle.
* @note This procedure could be used for aborting any ongoing transfer started in Interrupt or DMA mode.
* This procedure performs following operations :
* - Disable UART Interrupts (Tx and Rx)
* - Disable the DMA transfer in the peripheral register (if enabled)
* - Abort DMA transfer by calling HAL_DMA_Abort (in case of transfer in DMA mode)
* - Set handle State to READY
* @note This procedure is executed in blocking mode : when exiting function, Abort is considered as completed.
* @retval HAL status
*/
HAL_StatusTypeDef HAL_UART_Abort(UART_HandleTypeDef *huart)
{
/* Disable TXEIE, TCIE, RXNE, PE and ERR (Frame error, noise error, overrun error) interrupts */
ATOMIC_CLEAR_BIT(huart->Instance->CR1, (USART_CR1_RXNEIE | USART_CR1_PEIE | USART_CR1_TXEIE | USART_CR1_TCIE));
ATOMIC_CLEAR_BIT(huart->Instance->CR3, USART_CR3_EIE);
/* If Reception till IDLE event was ongoing, disable IDLEIE interrupt */
if (huart->ReceptionType == HAL_UART_RECEPTION_TOIDLE)
{
ATOMIC_CLEAR_BIT(huart->Instance->CR1, (USART_CR1_IDLEIE));
}
/* Disable the UART DMA Tx request if enabled */
if (HAL_IS_BIT_SET(huart->Instance->CR3, USART_CR3_DMAT))
{
ATOMIC_CLEAR_BIT(huart->Instance->CR3, USART_CR3_DMAT);
/* Abort the UART DMA Tx channel: use blocking DMA Abort API (no callback) */
if (huart->hdmatx != NULL)
{
/* Set the UART DMA Abort callback to Null.
No call back execution at end of DMA abort procedure */
huart->hdmatx->XferAbortCallback = NULL;
if (HAL_DMA_Abort(huart->hdmatx) != HAL_OK)
{
if (HAL_DMA_GetError(huart->hdmatx) == HAL_DMA_ERROR_TIMEOUT)
{
/* Set error code to DMA */
huart->ErrorCode = HAL_UART_ERROR_DMA;
return HAL_TIMEOUT;
}
}
}
}
/* Disable the UART DMA Rx request if enabled */
if (HAL_IS_BIT_SET(huart->Instance->CR3, USART_CR3_DMAR))
{
ATOMIC_CLEAR_BIT(huart->Instance->CR3, USART_CR3_DMAR);
/* Abort the UART DMA Rx channel: use blocking DMA Abort API (no callback) */
if (huart->hdmarx != NULL)
{
/* Set the UART DMA Abort callback to Null.
No call back execution at end of DMA abort procedure */
huart->hdmarx->XferAbortCallback = NULL;
if (HAL_DMA_Abort(huart->hdmarx) != HAL_OK)
{
if (HAL_DMA_GetError(huart->hdmarx) == HAL_DMA_ERROR_TIMEOUT)
{
/* Set error code to DMA */
huart->ErrorCode = HAL_UART_ERROR_DMA;
return HAL_TIMEOUT;
}
}
}
}
/* Reset Tx and Rx transfer counters */
huart->TxXferCount = 0x00U;
huart->RxXferCount = 0x00U;
/* Reset ErrorCode */
huart->ErrorCode = HAL_UART_ERROR_NONE;
/* Restore huart->RxState and huart->gState to Ready */
huart->RxState = HAL_UART_STATE_READY;
huart->gState = HAL_UART_STATE_READY;
huart->ReceptionType = HAL_UART_RECEPTION_STANDARD;
return HAL_OK;
}
/**
* @brief Abort ongoing Transmit transfer (blocking mode).
* @param huart UART handle.
* @note This procedure could be used for aborting any ongoing Tx transfer started in Interrupt or DMA mode.
* This procedure performs following operations :
* - Disable UART Interrupts (Tx)
* - Disable the DMA transfer in the peripheral register (if enabled)
* - Abort DMA transfer by calling HAL_DMA_Abort (in case of transfer in DMA mode)
* - Set handle State to READY
* @note This procedure is executed in blocking mode : when exiting function, Abort is considered as completed.
* @retval HAL status
*/
HAL_StatusTypeDef HAL_UART_AbortTransmit(UART_HandleTypeDef *huart)
{
/* Disable TXEIE and TCIE interrupts */
ATOMIC_CLEAR_BIT(huart->Instance->CR1, (USART_CR1_TXEIE | USART_CR1_TCIE));
/* Disable the UART DMA Tx request if enabled */
if (HAL_IS_BIT_SET(huart->Instance->CR3, USART_CR3_DMAT))
{
ATOMIC_CLEAR_BIT(huart->Instance->CR3, USART_CR3_DMAT);
/* Abort the UART DMA Tx channel : use blocking DMA Abort API (no callback) */
if (huart->hdmatx != NULL)
{
/* Set the UART DMA Abort callback to Null.
No call back execution at end of DMA abort procedure */
huart->hdmatx->XferAbortCallback = NULL;
if (HAL_DMA_Abort(huart->hdmatx) != HAL_OK)
{
if (HAL_DMA_GetError(huart->hdmatx) == HAL_DMA_ERROR_TIMEOUT)
{
/* Set error code to DMA */
huart->ErrorCode = HAL_UART_ERROR_DMA;
return HAL_TIMEOUT;
}
}
}
}
/* Reset Tx transfer counter */
huart->TxXferCount = 0x00U;
/* Restore huart->gState to Ready */
huart->gState = HAL_UART_STATE_READY;
return HAL_OK;
}
/**
* @brief Abort ongoing Receive transfer (blocking mode).
* @param huart UART handle.
* @note This procedure could be used for aborting any ongoing Rx transfer started in Interrupt or DMA mode.
* This procedure performs following operations :
* - Disable UART Interrupts (Rx)
* - Disable the DMA transfer in the peripheral register (if enabled)
* - Abort DMA transfer by calling HAL_DMA_Abort (in case of transfer in DMA mode)
* - Set handle State to READY
* @note This procedure is executed in blocking mode : when exiting function, Abort is considered as completed.
* @retval HAL status
*/
HAL_StatusTypeDef HAL_UART_AbortReceive(UART_HandleTypeDef *huart)
{
/* Disable RXNE, PE and ERR (Frame error, noise error, overrun error) interrupts */
ATOMIC_CLEAR_BIT(huart->Instance->CR1, (USART_CR1_RXNEIE | USART_CR1_PEIE));
ATOMIC_CLEAR_BIT(huart->Instance->CR3, USART_CR3_EIE);
/* If Reception till IDLE event was ongoing, disable IDLEIE interrupt */
if (huart->ReceptionType == HAL_UART_RECEPTION_TOIDLE)
{
ATOMIC_CLEAR_BIT(huart->Instance->CR1, (USART_CR1_IDLEIE));
}
/* Disable the UART DMA Rx request if enabled */
if (HAL_IS_BIT_SET(huart->Instance->CR3, USART_CR3_DMAR))
{
ATOMIC_CLEAR_BIT(huart->Instance->CR3, USART_CR3_DMAR);
/* Abort the UART DMA Rx channel : use blocking DMA Abort API (no callback) */
if (huart->hdmarx != NULL)
{
/* Set the UART DMA Abort callback to Null.
No call back execution at end of DMA abort procedure */
huart->hdmarx->XferAbortCallback = NULL;
if (HAL_DMA_Abort(huart->hdmarx) != HAL_OK)
{
if (HAL_DMA_GetError(huart->hdmarx) == HAL_DMA_ERROR_TIMEOUT)
{
/* Set error code to DMA */
huart->ErrorCode = HAL_UART_ERROR_DMA;
return HAL_TIMEOUT;
}
}
}
}
/* Reset Rx transfer counter */
huart->RxXferCount = 0x00U;
/* Restore huart->RxState to Ready */
huart->RxState = HAL_UART_STATE_READY;
huart->ReceptionType = HAL_UART_RECEPTION_STANDARD;
return HAL_OK;
}
/**
* @brief Abort ongoing transfers (Interrupt mode).
* @param huart UART handle.
* @note This procedure could be used for aborting any ongoing transfer started in Interrupt or DMA mode.
* This procedure performs following operations :
* - Disable UART Interrupts (Tx and Rx)
* - Disable the DMA transfer in the peripheral register (if enabled)
* - Abort DMA transfer by calling HAL_DMA_Abort_IT (in case of transfer in DMA mode)
* - Set handle State to READY
* - At abort completion, call user abort complete callback
* @note This procedure is executed in Interrupt mode, meaning that abort procedure could be
* considered as completed only when user abort complete callback is executed (not when exiting function).
* @retval HAL status
*/
HAL_StatusTypeDef HAL_UART_Abort_IT(UART_HandleTypeDef *huart)
{
uint32_t AbortCplt = 0x01U;
/* Disable TXEIE, TCIE, RXNE, PE and ERR (Frame error, noise error, overrun error) interrupts */
ATOMIC_CLEAR_BIT(huart->Instance->CR1, (USART_CR1_RXNEIE | USART_CR1_PEIE | USART_CR1_TXEIE | USART_CR1_TCIE));
ATOMIC_CLEAR_BIT(huart->Instance->CR3, USART_CR3_EIE);
/* If Reception till IDLE event was ongoing, disable IDLEIE interrupt */
if (huart->ReceptionType == HAL_UART_RECEPTION_TOIDLE)
{
ATOMIC_CLEAR_BIT(huart->Instance->CR1, (USART_CR1_IDLEIE));
}
/* If DMA Tx and/or DMA Rx Handles are associated to UART Handle, DMA Abort complete callbacks should be initialised
before any call to DMA Abort functions */
/* DMA Tx Handle is valid */
if (huart->hdmatx != NULL)
{
/* Set DMA Abort Complete callback if UART DMA Tx request if enabled.
Otherwise, set it to NULL */
if (HAL_IS_BIT_SET(huart->Instance->CR3, USART_CR3_DMAT))
{
huart->hdmatx->XferAbortCallback = UART_DMATxAbortCallback;
}
else
{
huart->hdmatx->XferAbortCallback = NULL;
}
}
/* DMA Rx Handle is valid */
if (huart->hdmarx != NULL)
{
/* Set DMA Abort Complete callback if UART DMA Rx request if enabled.
Otherwise, set it to NULL */
if (HAL_IS_BIT_SET(huart->Instance->CR3, USART_CR3_DMAR))
{
huart->hdmarx->XferAbortCallback = UART_DMARxAbortCallback;
}
else
{
huart->hdmarx->XferAbortCallback = NULL;
}
}
/* Disable the UART DMA Tx request if enabled */
if (HAL_IS_BIT_SET(huart->Instance->CR3, USART_CR3_DMAT))
{
/* Disable DMA Tx at UART level */
ATOMIC_CLEAR_BIT(huart->Instance->CR3, USART_CR3_DMAT);
/* Abort the UART DMA Tx channel : use non blocking DMA Abort API (callback) */
if (huart->hdmatx != NULL)
{
/* UART Tx DMA Abort callback has already been initialised :
will lead to call HAL_UART_AbortCpltCallback() at end of DMA abort procedure */
/* Abort DMA TX */
if (HAL_DMA_Abort_IT(huart->hdmatx) != HAL_OK)
{
huart->hdmatx->XferAbortCallback = NULL;
}
else
{
AbortCplt = 0x00U;
}
}
}
/* Disable the UART DMA Rx request if enabled */
if (HAL_IS_BIT_SET(huart->Instance->CR3, USART_CR3_DMAR))
{
ATOMIC_CLEAR_BIT(huart->Instance->CR3, USART_CR3_DMAR);
/* Abort the UART DMA Rx channel : use non blocking DMA Abort API (callback) */
if (huart->hdmarx != NULL)
{
/* UART Rx DMA Abort callback has already been initialised :
will lead to call HAL_UART_AbortCpltCallback() at end of DMA abort procedure */
/* Abort DMA RX */
if (HAL_DMA_Abort_IT(huart->hdmarx) != HAL_OK)
{
huart->hdmarx->XferAbortCallback = NULL;
AbortCplt = 0x01U;
}
else
{
AbortCplt = 0x00U;
}
}
}
/* if no DMA abort complete callback execution is required => call user Abort Complete callback */
if (AbortCplt == 0x01U)
{
/* Reset Tx and Rx transfer counters */
huart->TxXferCount = 0x00U;
huart->RxXferCount = 0x00U;
/* Reset ErrorCode */
huart->ErrorCode = HAL_UART_ERROR_NONE;
/* Restore huart->gState and huart->RxState to Ready */
huart->gState = HAL_UART_STATE_READY;
huart->RxState = HAL_UART_STATE_READY;
huart->ReceptionType = HAL_UART_RECEPTION_STANDARD;
/* As no DMA to be aborted, call directly user Abort complete callback */
#if (USE_HAL_UART_REGISTER_CALLBACKS == 1)
/* Call registered Abort complete callback */
huart->AbortCpltCallback(huart);
#else
/* Call legacy weak Abort complete callback */
HAL_UART_AbortCpltCallback(huart);
#endif /* USE_HAL_UART_REGISTER_CALLBACKS */
}
return HAL_OK;
}
/**
* @brief Abort ongoing Transmit transfer (Interrupt mode).
* @param huart UART handle.
* @note This procedure could be used for aborting any ongoing Tx transfer started in Interrupt or DMA mode.
* This procedure performs following operations :
* - Disable UART Interrupts (Tx)
* - Disable the DMA transfer in the peripheral register (if enabled)
* - Abort DMA transfer by calling HAL_DMA_Abort_IT (in case of transfer in DMA mode)
* - Set handle State to READY
* - At abort completion, call user abort complete callback
* @note This procedure is executed in Interrupt mode, meaning that abort procedure could be
* considered as completed only when user abort complete callback is executed (not when exiting function).
* @retval HAL status
*/
HAL_StatusTypeDef HAL_UART_AbortTransmit_IT(UART_HandleTypeDef *huart)
{
/* Disable TXEIE and TCIE interrupts */
ATOMIC_CLEAR_BIT(huart->Instance->CR1, (USART_CR1_TXEIE | USART_CR1_TCIE));
/* Disable the UART DMA Tx request if enabled */
if (HAL_IS_BIT_SET(huart->Instance->CR3, USART_CR3_DMAT))
{
ATOMIC_CLEAR_BIT(huart->Instance->CR3, USART_CR3_DMAT);
/* Abort the UART DMA Tx channel : use blocking DMA Abort API (no callback) */
if (huart->hdmatx != NULL)
{
/* Set the UART DMA Abort callback :
will lead to call HAL_UART_AbortCpltCallback() at end of DMA abort procedure */
huart->hdmatx->XferAbortCallback = UART_DMATxOnlyAbortCallback;
/* Abort DMA TX */
if (HAL_DMA_Abort_IT(huart->hdmatx) != HAL_OK)
{
/* Call Directly huart->hdmatx->XferAbortCallback function in case of error */
huart->hdmatx->XferAbortCallback(huart->hdmatx);
}
}
else
{
/* Reset Tx transfer counter */
huart->TxXferCount = 0x00U;
/* Restore huart->gState to Ready */
huart->gState = HAL_UART_STATE_READY;
/* As no DMA to be aborted, call directly user Abort complete callback */
#if (USE_HAL_UART_REGISTER_CALLBACKS == 1)
/* Call registered Abort Transmit Complete Callback */
huart->AbortTransmitCpltCallback(huart);
#else
/* Call legacy weak Abort Transmit Complete Callback */
HAL_UART_AbortTransmitCpltCallback(huart);
#endif /* USE_HAL_UART_REGISTER_CALLBACKS */
}
}
else
{
/* Reset Tx transfer counter */
huart->TxXferCount = 0x00U;
/* Restore huart->gState to Ready */
huart->gState = HAL_UART_STATE_READY;
/* As no DMA to be aborted, call directly user Abort complete callback */
#if (USE_HAL_UART_REGISTER_CALLBACKS == 1)
/* Call registered Abort Transmit Complete Callback */
huart->AbortTransmitCpltCallback(huart);
#else
/* Call legacy weak Abort Transmit Complete Callback */
HAL_UART_AbortTransmitCpltCallback(huart);
#endif /* USE_HAL_UART_REGISTER_CALLBACKS */
}
return HAL_OK;
}
/**
* @brief Abort ongoing Receive transfer (Interrupt mode).
* @param huart UART handle.
* @note This procedure could be used for aborting any ongoing Rx transfer started in Interrupt or DMA mode.
* This procedure performs following operations :
* - Disable UART Interrupts (Rx)
* - Disable the DMA transfer in the peripheral register (if enabled)
* - Abort DMA transfer by calling HAL_DMA_Abort_IT (in case of transfer in DMA mode)
* - Set handle State to READY
* - At abort completion, call user abort complete callback
* @note This procedure is executed in Interrupt mode, meaning that abort procedure could be
* considered as completed only when user abort complete callback is executed (not when exiting function).
* @retval HAL status
*/
HAL_StatusTypeDef HAL_UART_AbortReceive_IT(UART_HandleTypeDef *huart)
{
/* Disable RXNE, PE and ERR (Frame error, noise error, overrun error) interrupts */
ATOMIC_CLEAR_BIT(huart->Instance->CR1, (USART_CR1_RXNEIE | USART_CR1_PEIE));
ATOMIC_CLEAR_BIT(huart->Instance->CR3, USART_CR3_EIE);
/* If Reception till IDLE event was ongoing, disable IDLEIE interrupt */
if (huart->ReceptionType == HAL_UART_RECEPTION_TOIDLE)
{
ATOMIC_CLEAR_BIT(huart->Instance->CR1, (USART_CR1_IDLEIE));
}
/* Disable the UART DMA Rx request if enabled */
if (HAL_IS_BIT_SET(huart->Instance->CR3, USART_CR3_DMAR))
{
ATOMIC_CLEAR_BIT(huart->Instance->CR3, USART_CR3_DMAR);
/* Abort the UART DMA Rx channel : use blocking DMA Abort API (no callback) */
if (huart->hdmarx != NULL)
{
/* Set the UART DMA Abort callback :
will lead to call HAL_UART_AbortCpltCallback() at end of DMA abort procedure */
huart->hdmarx->XferAbortCallback = UART_DMARxOnlyAbortCallback;
/* Abort DMA RX */
if (HAL_DMA_Abort_IT(huart->hdmarx) != HAL_OK)
{
/* Call Directly huart->hdmarx->XferAbortCallback function in case of error */
huart->hdmarx->XferAbortCallback(huart->hdmarx);
}
}
else
{
/* Reset Rx transfer counter */
huart->RxXferCount = 0x00U;
/* Restore huart->RxState to Ready */
huart->RxState = HAL_UART_STATE_READY;
huart->ReceptionType = HAL_UART_RECEPTION_STANDARD;
/* As no DMA to be aborted, call directly user Abort complete callback */
#if (USE_HAL_UART_REGISTER_CALLBACKS == 1)
/* Call registered Abort Receive Complete Callback */
huart->AbortReceiveCpltCallback(huart);
#else
/* Call legacy weak Abort Receive Complete Callback */
HAL_UART_AbortReceiveCpltCallback(huart);
#endif /* USE_HAL_UART_REGISTER_CALLBACKS */
}
}
else
{
/* Reset Rx transfer counter */
huart->RxXferCount = 0x00U;
/* Restore huart->RxState to Ready */
huart->RxState = HAL_UART_STATE_READY;
huart->ReceptionType = HAL_UART_RECEPTION_STANDARD;
/* As no DMA to be aborted, call directly user Abort complete callback */
#if (USE_HAL_UART_REGISTER_CALLBACKS == 1)
/* Call registered Abort Receive Complete Callback */
huart->AbortReceiveCpltCallback(huart);
#else
/* Call legacy weak Abort Receive Complete Callback */
HAL_UART_AbortReceiveCpltCallback(huart);
#endif /* USE_HAL_UART_REGISTER_CALLBACKS */
}
return HAL_OK;
}
/**
* @brief This function handles UART interrupt request.
* @param huart Pointer to a UART_HandleTypeDef structure that contains
* the configuration information for the specified UART module.
* @retval None
*/
void HAL_UART_IRQHandler(UART_HandleTypeDef *huart)
{
uint32_t isrflags = READ_REG(huart->Instance->SR);
uint32_t cr1its = READ_REG(huart->Instance->CR1);
uint32_t cr3its = READ_REG(huart->Instance->CR3);
uint32_t errorflags = 0x00U;
uint32_t dmarequest = 0x00U;
/* If no error occurs */
errorflags = (isrflags & (uint32_t)(USART_SR_PE | USART_SR_FE | USART_SR_ORE | USART_SR_NE));
if (errorflags == RESET)
{
/* UART in mode Receiver -------------------------------------------------*/
if (((isrflags & USART_SR_RXNE) != RESET) && ((cr1its & USART_CR1_RXNEIE) != RESET))
{
UART_Receive_IT(huart);
return;
}
}
/* If some errors occur */
if ((errorflags != RESET) && (((cr3its & USART_CR3_EIE) != RESET)
|| ((cr1its & (USART_CR1_RXNEIE | USART_CR1_PEIE)) != RESET)))
{
/* UART parity error interrupt occurred ----------------------------------*/
if (((isrflags & USART_SR_PE) != RESET) && ((cr1its & USART_CR1_PEIE) != RESET))
{
huart->ErrorCode |= HAL_UART_ERROR_PE;
}
/* UART noise error interrupt occurred -----------------------------------*/
if (((isrflags & USART_SR_NE) != RESET) && ((cr3its & USART_CR3_EIE) != RESET))
{
huart->ErrorCode |= HAL_UART_ERROR_NE;
}
/* UART frame error interrupt occurred -----------------------------------*/
if (((isrflags & USART_SR_FE) != RESET) && ((cr3its & USART_CR3_EIE) != RESET))
{
huart->ErrorCode |= HAL_UART_ERROR_FE;
}
/* UART Over-Run interrupt occurred --------------------------------------*/
if (((isrflags & USART_SR_ORE) != RESET) && (((cr1its & USART_CR1_RXNEIE) != RESET)
|| ((cr3its & USART_CR3_EIE) != RESET)))
{
huart->ErrorCode |= HAL_UART_ERROR_ORE;
}
/* Call UART Error Call back function if need be --------------------------*/
if (huart->ErrorCode != HAL_UART_ERROR_NONE)
{
/* UART in mode Receiver -----------------------------------------------*/
if (((isrflags & USART_SR_RXNE) != RESET) && ((cr1its & USART_CR1_RXNEIE) != RESET))
{
UART_Receive_IT(huart);
}
/* If Overrun error occurs, or if any error occurs in DMA mode reception,
consider error as blocking */
dmarequest = HAL_IS_BIT_SET(huart->Instance->CR3, USART_CR3_DMAR);
if (((huart->ErrorCode & HAL_UART_ERROR_ORE) != RESET) || dmarequest)
{
/* Blocking error : transfer is aborted
Set the UART state ready to be able to start again the process,
Disable Rx Interrupts, and disable Rx DMA request, if ongoing */
UART_EndRxTransfer(huart);
/* Disable the UART DMA Rx request if enabled */
if (HAL_IS_BIT_SET(huart->Instance->CR3, USART_CR3_DMAR))
{
ATOMIC_CLEAR_BIT(huart->Instance->CR3, USART_CR3_DMAR);
/* Abort the UART DMA Rx channel */
if (huart->hdmarx != NULL)
{
/* Set the UART DMA Abort callback :
will lead to call HAL_UART_ErrorCallback() at end of DMA abort procedure */
huart->hdmarx->XferAbortCallback = UART_DMAAbortOnError;
if (HAL_DMA_Abort_IT(huart->hdmarx) != HAL_OK)
{
/* Call Directly XferAbortCallback function in case of error */
huart->hdmarx->XferAbortCallback(huart->hdmarx);
}
}
else
{
/* Call user error callback */
#if (USE_HAL_UART_REGISTER_CALLBACKS == 1)
/*Call registered error callback*/
huart->ErrorCallback(huart);
#else
/*Call legacy weak error callback*/
HAL_UART_ErrorCallback(huart);
#endif /* USE_HAL_UART_REGISTER_CALLBACKS */
}
}
else
{
/* Call user error callback */
#if (USE_HAL_UART_REGISTER_CALLBACKS == 1)
/*Call registered error callback*/
huart->ErrorCallback(huart);
#else
/*Call legacy weak error callback*/
HAL_UART_ErrorCallback(huart);
#endif /* USE_HAL_UART_REGISTER_CALLBACKS */
}
}
else
{
/* Non Blocking error : transfer could go on.
Error is notified to user through user error callback */
#if (USE_HAL_UART_REGISTER_CALLBACKS == 1)
/*Call registered error callback*/
huart->ErrorCallback(huart);
#else
/*Call legacy weak error callback*/
HAL_UART_ErrorCallback(huart);
#endif /* USE_HAL_UART_REGISTER_CALLBACKS */
huart->ErrorCode = HAL_UART_ERROR_NONE;
}
}
return;
} /* End if some error occurs */
/* Check current reception Mode :
If Reception till IDLE event has been selected : */
if ((huart->ReceptionType == HAL_UART_RECEPTION_TOIDLE)
&& ((isrflags & USART_SR_IDLE) != 0U)
&& ((cr1its & USART_SR_IDLE) != 0U))
{
__HAL_UART_CLEAR_IDLEFLAG(huart);
/* Check if DMA mode is enabled in UART */
if (HAL_IS_BIT_SET(huart->Instance->CR3, USART_CR3_DMAR))
{
/* DMA mode enabled */
/* Check received length : If all expected data are received, do nothing,
(DMA cplt callback will be called).
Otherwise, if at least one data has already been received, IDLE event is to be notified to user */
uint16_t nb_remaining_rx_data = (uint16_t) __HAL_DMA_GET_COUNTER(huart->hdmarx);
if ((nb_remaining_rx_data > 0U)
&& (nb_remaining_rx_data < huart->RxXferSize))
{
/* Reception is not complete */
huart->RxXferCount = nb_remaining_rx_data;
/* In Normal mode, end DMA xfer and HAL UART Rx process*/
if (huart->hdmarx->Init.Mode != DMA_CIRCULAR)
{
/* Disable PE and ERR (Frame error, noise error, overrun error) interrupts */
ATOMIC_CLEAR_BIT(huart->Instance->CR1, USART_CR1_PEIE);
ATOMIC_CLEAR_BIT(huart->Instance->CR3, USART_CR3_EIE);
/* Disable the DMA transfer for the receiver request by resetting the DMAR bit
in the UART CR3 register */
ATOMIC_CLEAR_BIT(huart->Instance->CR3, USART_CR3_DMAR);
/* At end of Rx process, restore huart->RxState to Ready */
huart->RxState = HAL_UART_STATE_READY;
huart->ReceptionType = HAL_UART_RECEPTION_STANDARD;
ATOMIC_CLEAR_BIT(huart->Instance->CR1, USART_CR1_IDLEIE);
/* Last bytes received, so no need as the abort is immediate */
(void)HAL_DMA_Abort(huart->hdmarx);
}
/* Initialize type of RxEvent that correspond to RxEvent callback execution;
In this case, Rx Event type is Idle Event */
huart->RxEventType = HAL_UART_RXEVENT_IDLE;
#if (USE_HAL_UART_REGISTER_CALLBACKS == 1)
/*Call registered Rx Event callback*/
huart->RxEventCallback(huart, (huart->RxXferSize - huart->RxXferCount));
#else
/*Call legacy weak Rx Event callback*/
HAL_UARTEx_RxEventCallback(huart, (huart->RxXferSize - huart->RxXferCount));
#endif /* USE_HAL_UART_REGISTER_CALLBACKS */
}
return;
}
else
{
/* DMA mode not enabled */
/* Check received length : If all expected data are received, do nothing.
Otherwise, if at least one data has already been received, IDLE event is to be notified to user */
uint16_t nb_rx_data = huart->RxXferSize - huart->RxXferCount;
if ((huart->RxXferCount > 0U)
&& (nb_rx_data > 0U))
{
/* Disable the UART Parity Error Interrupt and RXNE interrupts */
ATOMIC_CLEAR_BIT(huart->Instance->CR1, (USART_CR1_RXNEIE | USART_CR1_PEIE));
/* Disable the UART Error Interrupt: (Frame error, noise error, overrun error) */
ATOMIC_CLEAR_BIT(huart->Instance->CR3, USART_CR3_EIE);
/* Rx process is completed, restore huart->RxState to Ready */
huart->RxState = HAL_UART_STATE_READY;
huart->ReceptionType = HAL_UART_RECEPTION_STANDARD;
ATOMIC_CLEAR_BIT(huart->Instance->CR1, USART_CR1_IDLEIE);
/* Initialize type of RxEvent that correspond to RxEvent callback execution;
In this case, Rx Event type is Idle Event */
huart->RxEventType = HAL_UART_RXEVENT_IDLE;
#if (USE_HAL_UART_REGISTER_CALLBACKS == 1)
/*Call registered Rx complete callback*/
huart->RxEventCallback(huart, nb_rx_data);
#else
/*Call legacy weak Rx Event callback*/
HAL_UARTEx_RxEventCallback(huart, nb_rx_data);
#endif /* USE_HAL_UART_REGISTER_CALLBACKS */
}
return;
}
}
/* UART in mode Transmitter ------------------------------------------------*/
if (((isrflags & USART_SR_TXE) != RESET) && ((cr1its & USART_CR1_TXEIE) != RESET))
{
UART_Transmit_IT(huart);
return;
}
/* UART in mode Transmitter end --------------------------------------------*/
if (((isrflags & USART_SR_TC) != RESET) && ((cr1its & USART_CR1_TCIE) != RESET))
{
UART_EndTransmit_IT(huart);
return;
}
}
/**
* @brief Tx Transfer completed callbacks.
* @param huart Pointer to a UART_HandleTypeDef structure that contains
* the configuration information for the specified UART module.
* @retval None
*/
__weak void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart)
{
/* Prevent unused argument(s) compilation warning */
UNUSED(huart);
/* NOTE: This function should not be modified, when the callback is needed,
the HAL_UART_TxCpltCallback could be implemented in the user file
*/
}
/**
* @brief Tx Half Transfer completed callbacks.
* @param huart Pointer to a UART_HandleTypeDef structure that contains
* the configuration information for the specified UART module.
* @retval None
*/
__weak void HAL_UART_TxHalfCpltCallback(UART_HandleTypeDef *huart)
{
/* Prevent unused argument(s) compilation warning */
UNUSED(huart);
/* NOTE: This function should not be modified, when the callback is needed,
the HAL_UART_TxHalfCpltCallback could be implemented in the user file
*/
}
/**
* @brief Rx Transfer completed callbacks.
* @param huart Pointer to a UART_HandleTypeDef structure that contains
* the configuration information for the specified UART module.
* @retval None
*/
__weak void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
/* Prevent unused argument(s) compilation warning */
UNUSED(huart);
/* NOTE: This function should not be modified, when the callback is needed,
the HAL_UART_RxCpltCallback could be implemented in the user file
*/
}
/**
* @brief Rx Half Transfer completed callbacks.
* @param huart Pointer to a UART_HandleTypeDef structure that contains
* the configuration information for the specified UART module.
* @retval None
*/
__weak void HAL_UART_RxHalfCpltCallback(UART_HandleTypeDef *huart)
{
/* Prevent unused argument(s) compilation warning */
UNUSED(huart);
/* NOTE: This function should not be modified, when the callback is needed,
the HAL_UART_RxHalfCpltCallback could be implemented in the user file
*/
}
/**
* @brief UART error callbacks.
* @param huart Pointer to a UART_HandleTypeDef structure that contains
* the configuration information for the specified UART module.
* @retval None
*/
__weak void HAL_UART_ErrorCallback(UART_HandleTypeDef *huart)
{
/* Prevent unused argument(s) compilation warning */
UNUSED(huart);
/* NOTE: This function should not be modified, when the callback is needed,
the HAL_UART_ErrorCallback could be implemented in the user file
*/
}
/**
* @brief UART Abort Complete callback.
* @param huart UART handle.
* @retval None
*/
__weak void HAL_UART_AbortCpltCallback(UART_HandleTypeDef *huart)
{
/* Prevent unused argument(s) compilation warning */
UNUSED(huart);
/* NOTE : This function should not be modified, when the callback is needed,
the HAL_UART_AbortCpltCallback can be implemented in the user file.
*/
}
/**
* @brief UART Abort Complete callback.
* @param huart UART handle.
* @retval None
*/
__weak void HAL_UART_AbortTransmitCpltCallback(UART_HandleTypeDef *huart)
{
/* Prevent unused argument(s) compilation warning */
UNUSED(huart);
/* NOTE : This function should not be modified, when the callback is needed,
the HAL_UART_AbortTransmitCpltCallback can be implemented in the user file.
*/
}
/**
* @brief UART Abort Receive Complete callback.
* @param huart UART handle.
* @retval None
*/
__weak void HAL_UART_AbortReceiveCpltCallback(UART_HandleTypeDef *huart)
{
/* Prevent unused argument(s) compilation warning */
UNUSED(huart);
/* NOTE : This function should not be modified, when the callback is needed,
the HAL_UART_AbortReceiveCpltCallback can be implemented in the user file.
*/
}
/**
* @brief Reception Event Callback (Rx event notification called after use of advanced reception service).
* @param huart UART handle
* @param Size Number of data available in application reception buffer (indicates a position in
* reception buffer until which, data are available)
* @retval None
*/
__weak void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *huart, uint16_t Size)
{
/* Prevent unused argument(s) compilation warning */
UNUSED(huart);
UNUSED(Size);
/* NOTE : This function should not be modified, when the callback is needed,
the HAL_UARTEx_RxEventCallback can be implemented in the user file.
*/
}
/**
* @}
*/
/** @defgroup UART_Exported_Functions_Group3 Peripheral Control functions
* @brief UART control functions
*
@verbatim
==============================================================================
##### Peripheral Control functions #####
==============================================================================
[..]
This subsection provides a set of functions allowing to control the UART:
(+) HAL_LIN_SendBreak() API can be helpful to transmit the break character.
(+) HAL_MultiProcessor_EnterMuteMode() API can be helpful to enter the UART in mute mode.
(+) HAL_MultiProcessor_ExitMuteMode() API can be helpful to exit the UART mute mode by software.
(+) HAL_HalfDuplex_EnableTransmitter() API to enable the UART transmitter and disables the UART receiver in Half Duplex mode
(+) HAL_HalfDuplex_EnableReceiver() API to enable the UART receiver and disables the UART transmitter in Half Duplex mode
@endverbatim
* @{
*/
/**
* @brief Transmits break characters.
* @param huart Pointer to a UART_HandleTypeDef structure that contains
* the configuration information for the specified UART module.
* @retval HAL status
*/
HAL_StatusTypeDef HAL_LIN_SendBreak(UART_HandleTypeDef *huart)
{
/* Check the parameters */
assert_param(IS_UART_INSTANCE(huart->Instance));
/* Process Locked */
__HAL_LOCK(huart);
huart->gState = HAL_UART_STATE_BUSY;
/* Send break characters */
ATOMIC_SET_BIT(huart->Instance->CR1, USART_CR1_SBK);
huart->gState = HAL_UART_STATE_READY;
/* Process Unlocked */
__HAL_UNLOCK(huart);
return HAL_OK;
}
/**
* @brief Enters the UART in mute mode.
* @param huart Pointer to a UART_HandleTypeDef structure that contains
* the configuration information for the specified UART module.
* @retval HAL status
*/
HAL_StatusTypeDef HAL_MultiProcessor_EnterMuteMode(UART_HandleTypeDef *huart)
{
/* Check the parameters */
assert_param(IS_UART_INSTANCE(huart->Instance));
/* Process Locked */
__HAL_LOCK(huart);
huart->gState = HAL_UART_STATE_BUSY;
/* Enable the USART mute mode by setting the RWU bit in the CR1 register */
ATOMIC_SET_BIT(huart->Instance->CR1, USART_CR1_RWU);
huart->gState = HAL_UART_STATE_READY;
huart->RxEventType = HAL_UART_RXEVENT_TC;
/* Process Unlocked */
__HAL_UNLOCK(huart);
return HAL_OK;
}
/**
* @brief Exits the UART mute mode: wake up software.
* @param huart Pointer to a UART_HandleTypeDef structure that contains
* the configuration information for the specified UART module.
* @retval HAL status
*/
HAL_StatusTypeDef HAL_MultiProcessor_ExitMuteMode(UART_HandleTypeDef *huart)
{
/* Check the parameters */
assert_param(IS_UART_INSTANCE(huart->Instance));
/* Process Locked */
__HAL_LOCK(huart);
huart->gState = HAL_UART_STATE_BUSY;
/* Disable the USART mute mode by clearing the RWU bit in the CR1 register */
ATOMIC_CLEAR_BIT(huart->Instance->CR1, USART_CR1_RWU);
huart->gState = HAL_UART_STATE_READY;
huart->RxEventType = HAL_UART_RXEVENT_TC;
/* Process Unlocked */
__HAL_UNLOCK(huart);
return HAL_OK;
}
/**
* @brief Enables the UART transmitter and disables the UART receiver.
* @param huart Pointer to a UART_HandleTypeDef structure that contains
* the configuration information for the specified UART module.
* @retval HAL status
*/
HAL_StatusTypeDef HAL_HalfDuplex_EnableTransmitter(UART_HandleTypeDef *huart)
{
uint32_t tmpreg = 0x00U;
/* Process Locked */
__HAL_LOCK(huart);
huart->gState = HAL_UART_STATE_BUSY;
/*-------------------------- USART CR1 Configuration -----------------------*/
tmpreg = huart->Instance->CR1;
/* Clear TE and RE bits */
tmpreg &= (uint32_t)~((uint32_t)(USART_CR1_TE | USART_CR1_RE));
/* Enable the USART's transmit interface by setting the TE bit in the USART CR1 register */
tmpreg |= (uint32_t)USART_CR1_TE;
/* Write to USART CR1 */
WRITE_REG(huart->Instance->CR1, (uint32_t)tmpreg);
huart->gState = HAL_UART_STATE_READY;
/* Process Unlocked */
__HAL_UNLOCK(huart);
return HAL_OK;
}
/**
* @brief Enables the UART receiver and disables the UART transmitter.
* @param huart Pointer to a UART_HandleTypeDef structure that contains
* the configuration information for the specified UART module.
* @retval HAL status
*/
HAL_StatusTypeDef HAL_HalfDuplex_EnableReceiver(UART_HandleTypeDef *huart)
{
uint32_t tmpreg = 0x00U;
/* Process Locked */
__HAL_LOCK(huart);
huart->gState = HAL_UART_STATE_BUSY;
/*-------------------------- USART CR1 Configuration -----------------------*/
tmpreg = huart->Instance->CR1;
/* Clear TE and RE bits */
tmpreg &= (uint32_t)~((uint32_t)(USART_CR1_TE | USART_CR1_RE));
/* Enable the USART's receive interface by setting the RE bit in the USART CR1 register */
tmpreg |= (uint32_t)USART_CR1_RE;
/* Write to USART CR1 */
WRITE_REG(huart->Instance->CR1, (uint32_t)tmpreg);
huart->gState = HAL_UART_STATE_READY;
/* Process Unlocked */
__HAL_UNLOCK(huart);
return HAL_OK;
}
/**
* @}
*/
/** @defgroup UART_Exported_Functions_Group4 Peripheral State and Errors functions
* @brief UART State and Errors functions
*
@verbatim
==============================================================================
##### Peripheral State and Errors functions #####
==============================================================================
[..]
This subsection provides a set of functions allowing to return the State of
UART communication process, return Peripheral Errors occurred during communication
process
(+) HAL_UART_GetState() API can be helpful to check in run-time the state of the UART peripheral.
(+) HAL_UART_GetError() check in run-time errors that could be occurred during communication.
@endverbatim
* @{
*/
/**
* @brief Returns the UART state.
* @param huart Pointer to a UART_HandleTypeDef structure that contains
* the configuration information for the specified UART module.
* @retval HAL state
*/
HAL_UART_StateTypeDef HAL_UART_GetState(const UART_HandleTypeDef *huart)
{
uint32_t temp1 = 0x00U, temp2 = 0x00U;
temp1 = huart->gState;
temp2 = huart->RxState;
return (HAL_UART_StateTypeDef)(temp1 | temp2);
}
/**
* @brief Return the UART error code
* @param huart Pointer to a UART_HandleTypeDef structure that contains
* the configuration information for the specified UART.
* @retval UART Error Code
*/
uint32_t HAL_UART_GetError(const UART_HandleTypeDef *huart)
{
return huart->ErrorCode;
}
/**
* @}
*/
/**
* @}
*/
/** @defgroup UART_Private_Functions UART Private Functions
* @{
*/
/**
* @brief Initialize the callbacks to their default values.
* @param huart UART handle.
* @retval none
*/
#if (USE_HAL_UART_REGISTER_CALLBACKS == 1)
void UART_InitCallbacksToDefault(UART_HandleTypeDef *huart)
{
/* Init the UART Callback settings */
huart->TxHalfCpltCallback = HAL_UART_TxHalfCpltCallback; /* Legacy weak TxHalfCpltCallback */
huart->TxCpltCallback = HAL_UART_TxCpltCallback; /* Legacy weak TxCpltCallback */
huart->RxHalfCpltCallback = HAL_UART_RxHalfCpltCallback; /* Legacy weak RxHalfCpltCallback */
huart->RxCpltCallback = HAL_UART_RxCpltCallback; /* Legacy weak RxCpltCallback */
huart->ErrorCallback = HAL_UART_ErrorCallback; /* Legacy weak ErrorCallback */
huart->AbortCpltCallback = HAL_UART_AbortCpltCallback; /* Legacy weak AbortCpltCallback */
huart->AbortTransmitCpltCallback = HAL_UART_AbortTransmitCpltCallback; /* Legacy weak AbortTransmitCpltCallback */
huart->AbortReceiveCpltCallback = HAL_UART_AbortReceiveCpltCallback; /* Legacy weak AbortReceiveCpltCallback */
huart->RxEventCallback = HAL_UARTEx_RxEventCallback; /* Legacy weak RxEventCallback */
}
#endif /* USE_HAL_UART_REGISTER_CALLBACKS */
/**
* @brief DMA UART transmit process complete callback.
* @param hdma Pointer to a DMA_HandleTypeDef structure that contains
* the configuration information for the specified DMA module.
* @retval None
*/
static void UART_DMATransmitCplt(DMA_HandleTypeDef *hdma)
{
UART_HandleTypeDef *huart = (UART_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent;
/* DMA Normal mode*/
if ((hdma->Instance->CCR & DMA_CCR_CIRC) == 0U)
{
huart->TxXferCount = 0x00U;
/* Disable the DMA transfer for transmit request by setting the DMAT bit
in the UART CR3 register */
ATOMIC_CLEAR_BIT(huart->Instance->CR3, USART_CR3_DMAT);
/* Enable the UART Transmit Complete Interrupt */
ATOMIC_SET_BIT(huart->Instance->CR1, USART_CR1_TCIE);
}
/* DMA Circular mode */
else
{
#if (USE_HAL_UART_REGISTER_CALLBACKS == 1)
/*Call registered Tx complete callback*/
huart->TxCpltCallback(huart);
#else
/*Call legacy weak Tx complete callback*/
HAL_UART_TxCpltCallback(huart);
#endif /* USE_HAL_UART_REGISTER_CALLBACKS */
}
}
/**
* @brief DMA UART transmit process half complete callback
* @param hdma Pointer to a DMA_HandleTypeDef structure that contains
* the configuration information for the specified DMA module.
* @retval None
*/
static void UART_DMATxHalfCplt(DMA_HandleTypeDef *hdma)
{
UART_HandleTypeDef *huart = (UART_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent;
#if (USE_HAL_UART_REGISTER_CALLBACKS == 1)
/*Call registered Tx complete callback*/
huart->TxHalfCpltCallback(huart);
#else
/*Call legacy weak Tx complete callback*/
HAL_UART_TxHalfCpltCallback(huart);
#endif /* USE_HAL_UART_REGISTER_CALLBACKS */
}
/**
* @brief DMA UART receive process complete callback.
* @param hdma Pointer to a DMA_HandleTypeDef structure that contains
* the configuration information for the specified DMA module.
* @retval None
*/
static void UART_DMAReceiveCplt(DMA_HandleTypeDef *hdma)
{
UART_HandleTypeDef *huart = (UART_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent;
/* DMA Normal mode*/
if ((hdma->Instance->CCR & DMA_CCR_CIRC) == 0U)
{
huart->RxXferCount = 0U;
/* Disable RXNE, PE and ERR (Frame error, noise error, overrun error) interrupts */
ATOMIC_CLEAR_BIT(huart->Instance->CR1, USART_CR1_PEIE);
ATOMIC_CLEAR_BIT(huart->Instance->CR3, USART_CR3_EIE);
/* Disable the DMA transfer for the receiver request by setting the DMAR bit
in the UART CR3 register */
ATOMIC_CLEAR_BIT(huart->Instance->CR3, USART_CR3_DMAR);
/* At end of Rx process, restore huart->RxState to Ready */
huart->RxState = HAL_UART_STATE_READY;
/* If Reception till IDLE event has been selected, Disable IDLE Interrupt */
if (huart->ReceptionType == HAL_UART_RECEPTION_TOIDLE)
{
ATOMIC_CLEAR_BIT(huart->Instance->CR1, USART_CR1_IDLEIE);
}
}
/* Initialize type of RxEvent that correspond to RxEvent callback execution;
In this case, Rx Event type is Transfer Complete */
huart->RxEventType = HAL_UART_RXEVENT_TC;
/* Check current reception Mode :
If Reception till IDLE event has been selected : use Rx Event callback */
if (huart->ReceptionType == HAL_UART_RECEPTION_TOIDLE)
{
#if (USE_HAL_UART_REGISTER_CALLBACKS == 1)
/*Call registered Rx Event callback*/
huart->RxEventCallback(huart, huart->RxXferSize);
#else
/*Call legacy weak Rx Event callback*/
HAL_UARTEx_RxEventCallback(huart, huart->RxXferSize);
#endif /* USE_HAL_UART_REGISTER_CALLBACKS */
}
else
{
/* In other cases : use Rx Complete callback */
#if (USE_HAL_UART_REGISTER_CALLBACKS == 1)
/*Call registered Rx complete callback*/
huart->RxCpltCallback(huart);
#else
/*Call legacy weak Rx complete callback*/
HAL_UART_RxCpltCallback(huart);
#endif /* USE_HAL_UART_REGISTER_CALLBACKS */
}
}
/**
* @brief DMA UART receive process half complete callback
* @param hdma Pointer to a DMA_HandleTypeDef structure that contains
* the configuration information for the specified DMA module.
* @retval None
*/
static void UART_DMARxHalfCplt(DMA_HandleTypeDef *hdma)
{
UART_HandleTypeDef *huart = (UART_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent;
/* Initialize type of RxEvent that correspond to RxEvent callback execution;
In this case, Rx Event type is Half Transfer */
huart->RxEventType = HAL_UART_RXEVENT_HT;
/* Check current reception Mode :
If Reception till IDLE event has been selected : use Rx Event callback */
if (huart->ReceptionType == HAL_UART_RECEPTION_TOIDLE)
{
#if (USE_HAL_UART_REGISTER_CALLBACKS == 1)
/*Call registered Rx Event callback*/
huart->RxEventCallback(huart, huart->RxXferSize / 2U);
#else
/*Call legacy weak Rx Event callback*/
HAL_UARTEx_RxEventCallback(huart, huart->RxXferSize / 2U);
#endif /* USE_HAL_UART_REGISTER_CALLBACKS */
}
else
{
/* In other cases : use Rx Half Complete callback */
#if (USE_HAL_UART_REGISTER_CALLBACKS == 1)
/*Call registered Rx Half complete callback*/
huart->RxHalfCpltCallback(huart);
#else
/*Call legacy weak Rx Half complete callback*/
HAL_UART_RxHalfCpltCallback(huart);
#endif /* USE_HAL_UART_REGISTER_CALLBACKS */
}
}
/**
* @brief DMA UART communication error callback.
* @param hdma Pointer to a DMA_HandleTypeDef structure that contains
* the configuration information for the specified DMA module.
* @retval None
*/
static void UART_DMAError(DMA_HandleTypeDef *hdma)
{
uint32_t dmarequest = 0x00U;
UART_HandleTypeDef *huart = (UART_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent;
/* Stop UART DMA Tx request if ongoing */
dmarequest = HAL_IS_BIT_SET(huart->Instance->CR3, USART_CR3_DMAT);
if ((huart->gState == HAL_UART_STATE_BUSY_TX) && dmarequest)
{
huart->TxXferCount = 0x00U;
UART_EndTxTransfer(huart);
}
/* Stop UART DMA Rx request if ongoing */
dmarequest = HAL_IS_BIT_SET(huart->Instance->CR3, USART_CR3_DMAR);
if ((huart->RxState == HAL_UART_STATE_BUSY_RX) && dmarequest)
{
huart->RxXferCount = 0x00U;
UART_EndRxTransfer(huart);
}
huart->ErrorCode |= HAL_UART_ERROR_DMA;
#if (USE_HAL_UART_REGISTER_CALLBACKS == 1)
/*Call registered error callback*/
huart->ErrorCallback(huart);
#else
/*Call legacy weak error callback*/
HAL_UART_ErrorCallback(huart);
#endif /* USE_HAL_UART_REGISTER_CALLBACKS */
}
/**
* @brief This function handles UART Communication Timeout. It waits
* until a flag is no longer in the specified status.
* @param huart Pointer to a UART_HandleTypeDef structure that contains
* the configuration information for the specified UART module.
* @param Flag specifies the UART flag to check.
* @param Status The actual Flag status (SET or RESET).
* @param Tickstart Tick start value
* @param Timeout Timeout duration
* @retval HAL status
*/
static HAL_StatusTypeDef UART_WaitOnFlagUntilTimeout(UART_HandleTypeDef *huart, uint32_t Flag, FlagStatus Status,
uint32_t Tickstart, uint32_t Timeout)
{
/* Wait until flag is set */
while ((__HAL_UART_GET_FLAG(huart, Flag) ? SET : RESET) == Status)
{
/* Check for the Timeout */
if (Timeout != HAL_MAX_DELAY)
{
if (((HAL_GetTick() - Tickstart) > Timeout) || (Timeout == 0U))
{
return HAL_TIMEOUT;
}
if ((READ_BIT(huart->Instance->CR1, USART_CR1_RE) != 0U) && (Flag != UART_FLAG_TXE) && (Flag != UART_FLAG_TC))
{
if (__HAL_UART_GET_FLAG(huart, UART_FLAG_ORE) == SET)
{
/* Clear Overrun Error flag*/
__HAL_UART_CLEAR_OREFLAG(huart);
/* Blocking error : transfer is aborted
Set the UART state ready to be able to start again the process,
Disable Rx Interrupts if ongoing */
UART_EndRxTransfer(huart);
huart->ErrorCode = HAL_UART_ERROR_ORE;
/* Process Unlocked */
__HAL_UNLOCK(huart);
return HAL_ERROR;
}
}
}
}
return HAL_OK;
}
/**
* @brief Start Receive operation in interrupt mode.
* @note This function could be called by all HAL UART API providing reception in Interrupt mode.
* @note When calling this function, parameters validity is considered as already checked,
* i.e. Rx State, buffer address, ...
* UART Handle is assumed as Locked.
* @param huart UART handle.
* @param pData Pointer to data buffer (u8 or u16 data elements).
* @param Size Amount of data elements (u8 or u16) to be received.
* @retval HAL status
*/
HAL_StatusTypeDef UART_Start_Receive_IT(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size)
{
huart->pRxBuffPtr = pData;
huart->RxXferSize = Size;
huart->RxXferCount = Size;
huart->ErrorCode = HAL_UART_ERROR_NONE;
huart->RxState = HAL_UART_STATE_BUSY_RX;
if (huart->Init.Parity != UART_PARITY_NONE)
{
/* Enable the UART Parity Error Interrupt */
__HAL_UART_ENABLE_IT(huart, UART_IT_PE);
}
/* Enable the UART Error Interrupt: (Frame error, noise error, overrun error) */
__HAL_UART_ENABLE_IT(huart, UART_IT_ERR);
/* Enable the UART Data Register not empty Interrupt */
__HAL_UART_ENABLE_IT(huart, UART_IT_RXNE);
return HAL_OK;
}
/**
* @brief Start Receive operation in DMA mode.
* @note This function could be called by all HAL UART API providing reception in DMA mode.
* @note When calling this function, parameters validity is considered as already checked,
* i.e. Rx State, buffer address, ...
* UART Handle is assumed as Locked.
* @param huart UART handle.
* @param pData Pointer to data buffer (u8 or u16 data elements).
* @param Size Amount of data elements (u8 or u16) to be received.
* @retval HAL status
*/
HAL_StatusTypeDef UART_Start_Receive_DMA(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size)
{
uint32_t *tmp;
huart->pRxBuffPtr = pData;
huart->RxXferSize = Size;
huart->ErrorCode = HAL_UART_ERROR_NONE;
huart->RxState = HAL_UART_STATE_BUSY_RX;
/* Set the UART DMA transfer complete callback */
huart->hdmarx->XferCpltCallback = UART_DMAReceiveCplt;
/* Set the UART DMA Half transfer complete callback */
huart->hdmarx->XferHalfCpltCallback = UART_DMARxHalfCplt;
/* Set the DMA error callback */
huart->hdmarx->XferErrorCallback = UART_DMAError;
/* Set the DMA abort callback */
huart->hdmarx->XferAbortCallback = NULL;
/* Enable the DMA stream */
tmp = (uint32_t *)&pData;
HAL_DMA_Start_IT(huart->hdmarx, (uint32_t)&huart->Instance->DR, *(uint32_t *)tmp, Size);
/* Clear the Overrun flag just before enabling the DMA Rx request: can be mandatory for the second transfer */
__HAL_UART_CLEAR_OREFLAG(huart);
if (huart->Init.Parity != UART_PARITY_NONE)
{
/* Enable the UART Parity Error Interrupt */
ATOMIC_SET_BIT(huart->Instance->CR1, USART_CR1_PEIE);
}
/* Enable the UART Error Interrupt: (Frame error, noise error, overrun error) */
ATOMIC_SET_BIT(huart->Instance->CR3, USART_CR3_EIE);
/* Enable the DMA transfer for the receiver request by setting the DMAR bit
in the UART CR3 register */
ATOMIC_SET_BIT(huart->Instance->CR3, USART_CR3_DMAR);
return HAL_OK;
}
/**
* @brief End ongoing Tx transfer on UART peripheral (following error detection or Transmit completion).
* @param huart UART handle.
* @retval None
*/
static void UART_EndTxTransfer(UART_HandleTypeDef *huart)
{
/* Disable TXEIE and TCIE interrupts */
ATOMIC_CLEAR_BIT(huart->Instance->CR1, (USART_CR1_TXEIE | USART_CR1_TCIE));
/* At end of Tx process, restore huart->gState to Ready */
huart->gState = HAL_UART_STATE_READY;
}
/**
* @brief End ongoing Rx transfer on UART peripheral (following error detection or Reception completion).
* @param huart UART handle.
* @retval None
*/
static void UART_EndRxTransfer(UART_HandleTypeDef *huart)
{
/* Disable RXNE, PE and ERR (Frame error, noise error, overrun error) interrupts */
ATOMIC_CLEAR_BIT(huart->Instance->CR1, (USART_CR1_RXNEIE | USART_CR1_PEIE));
ATOMIC_CLEAR_BIT(huart->Instance->CR3, USART_CR3_EIE);
/* In case of reception waiting for IDLE event, disable also the IDLE IE interrupt source */
if (huart->ReceptionType == HAL_UART_RECEPTION_TOIDLE)
{
ATOMIC_CLEAR_BIT(huart->Instance->CR1, USART_CR1_IDLEIE);
}
/* At end of Rx process, restore huart->RxState to Ready */
huart->RxState = HAL_UART_STATE_READY;
huart->ReceptionType = HAL_UART_RECEPTION_STANDARD;
}
/**
* @brief DMA UART communication abort callback, when initiated by HAL services on Error
* (To be called at end of DMA Abort procedure following error occurrence).
* @param hdma Pointer to a DMA_HandleTypeDef structure that contains
* the configuration information for the specified DMA module.
* @retval None
*/
static void UART_DMAAbortOnError(DMA_HandleTypeDef *hdma)
{
UART_HandleTypeDef *huart = (UART_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent;
huart->RxXferCount = 0x00U;
huart->TxXferCount = 0x00U;
#if (USE_HAL_UART_REGISTER_CALLBACKS == 1)
/*Call registered error callback*/
huart->ErrorCallback(huart);
#else
/*Call legacy weak error callback*/
HAL_UART_ErrorCallback(huart);
#endif /* USE_HAL_UART_REGISTER_CALLBACKS */
}
/**
* @brief DMA UART Tx communication abort callback, when initiated by user
* (To be called at end of DMA Tx Abort procedure following user abort request).
* @note When this callback is executed, User Abort complete call back is called only if no
* Abort still ongoing for Rx DMA Handle.
* @param hdma Pointer to a DMA_HandleTypeDef structure that contains
* the configuration information for the specified DMA module.
* @retval None
*/
static void UART_DMATxAbortCallback(DMA_HandleTypeDef *hdma)
{
UART_HandleTypeDef *huart = (UART_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent;
huart->hdmatx->XferAbortCallback = NULL;
/* Check if an Abort process is still ongoing */
if (huart->hdmarx != NULL)
{
if (huart->hdmarx->XferAbortCallback != NULL)
{
return;
}
}
/* No Abort process still ongoing : All DMA channels are aborted, call user Abort Complete callback */
huart->TxXferCount = 0x00U;
huart->RxXferCount = 0x00U;
/* Reset ErrorCode */
huart->ErrorCode = HAL_UART_ERROR_NONE;
/* Restore huart->gState and huart->RxState to Ready */
huart->gState = HAL_UART_STATE_READY;
huart->RxState = HAL_UART_STATE_READY;
huart->ReceptionType = HAL_UART_RECEPTION_STANDARD;
/* Call user Abort complete callback */
#if (USE_HAL_UART_REGISTER_CALLBACKS == 1)
/* Call registered Abort complete callback */
huart->AbortCpltCallback(huart);
#else
/* Call legacy weak Abort complete callback */
HAL_UART_AbortCpltCallback(huart);
#endif /* USE_HAL_UART_REGISTER_CALLBACKS */
}
/**
* @brief DMA UART Rx communication abort callback, when initiated by user
* (To be called at end of DMA Rx Abort procedure following user abort request).
* @note When this callback is executed, User Abort complete call back is called only if no
* Abort still ongoing for Tx DMA Handle.
* @param hdma Pointer to a DMA_HandleTypeDef structure that contains
* the configuration information for the specified DMA module.
* @retval None
*/
static void UART_DMARxAbortCallback(DMA_HandleTypeDef *hdma)
{
UART_HandleTypeDef *huart = (UART_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent;
huart->hdmarx->XferAbortCallback = NULL;
/* Check if an Abort process is still ongoing */
if (huart->hdmatx != NULL)
{
if (huart->hdmatx->XferAbortCallback != NULL)
{
return;
}
}
/* No Abort process still ongoing : All DMA channels are aborted, call user Abort Complete callback */
huart->TxXferCount = 0x00U;
huart->RxXferCount = 0x00U;
/* Reset ErrorCode */
huart->ErrorCode = HAL_UART_ERROR_NONE;
/* Restore huart->gState and huart->RxState to Ready */
huart->gState = HAL_UART_STATE_READY;
huart->RxState = HAL_UART_STATE_READY;
huart->ReceptionType = HAL_UART_RECEPTION_STANDARD;
/* Call user Abort complete callback */
#if (USE_HAL_UART_REGISTER_CALLBACKS == 1)
/* Call registered Abort complete callback */
huart->AbortCpltCallback(huart);
#else
/* Call legacy weak Abort complete callback */
HAL_UART_AbortCpltCallback(huart);
#endif /* USE_HAL_UART_REGISTER_CALLBACKS */
}
/**
* @brief DMA UART Tx communication abort callback, when initiated by user by a call to
* HAL_UART_AbortTransmit_IT API (Abort only Tx transfer)
* (This callback is executed at end of DMA Tx Abort procedure following user abort request,
* and leads to user Tx Abort Complete callback execution).
* @param hdma Pointer to a DMA_HandleTypeDef structure that contains
* the configuration information for the specified DMA module.
* @retval None
*/
static void UART_DMATxOnlyAbortCallback(DMA_HandleTypeDef *hdma)
{
UART_HandleTypeDef *huart = (UART_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent;
huart->TxXferCount = 0x00U;
/* Restore huart->gState to Ready */
huart->gState = HAL_UART_STATE_READY;
/* Call user Abort complete callback */
#if (USE_HAL_UART_REGISTER_CALLBACKS == 1)
/* Call registered Abort Transmit Complete Callback */
huart->AbortTransmitCpltCallback(huart);
#else
/* Call legacy weak Abort Transmit Complete Callback */
HAL_UART_AbortTransmitCpltCallback(huart);
#endif /* USE_HAL_UART_REGISTER_CALLBACKS */
}
/**
* @brief DMA UART Rx communication abort callback, when initiated by user by a call to
* HAL_UART_AbortReceive_IT API (Abort only Rx transfer)
* (This callback is executed at end of DMA Rx Abort procedure following user abort request,
* and leads to user Rx Abort Complete callback execution).
* @param hdma Pointer to a DMA_HandleTypeDef structure that contains
* the configuration information for the specified DMA module.
* @retval None
*/
static void UART_DMARxOnlyAbortCallback(DMA_HandleTypeDef *hdma)
{
UART_HandleTypeDef *huart = (UART_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent;
huart->RxXferCount = 0x00U;
/* Restore huart->RxState to Ready */
huart->RxState = HAL_UART_STATE_READY;
huart->ReceptionType = HAL_UART_RECEPTION_STANDARD;
/* Call user Abort complete callback */
#if (USE_HAL_UART_REGISTER_CALLBACKS == 1)
/* Call registered Abort Receive Complete Callback */
huart->AbortReceiveCpltCallback(huart);
#else
/* Call legacy weak Abort Receive Complete Callback */
HAL_UART_AbortReceiveCpltCallback(huart);
#endif /* USE_HAL_UART_REGISTER_CALLBACKS */
}
/**
* @brief Sends an amount of data in non blocking mode.
* @param huart Pointer to a UART_HandleTypeDef structure that contains
* the configuration information for the specified UART module.
* @retval HAL status
*/
static HAL_StatusTypeDef UART_Transmit_IT(UART_HandleTypeDef *huart)
{
const uint16_t *tmp;
/* Check that a Tx process is ongoing */
if (huart->gState == HAL_UART_STATE_BUSY_TX)
{
if ((huart->Init.WordLength == UART_WORDLENGTH_9B) && (huart->Init.Parity == UART_PARITY_NONE))
{
tmp = (const uint16_t *) huart->pTxBuffPtr;
huart->Instance->DR = (uint16_t)(*tmp & (uint16_t)0x01FF);
huart->pTxBuffPtr += 2U;
}
else
{
huart->Instance->DR = (uint8_t)(*huart->pTxBuffPtr++ & (uint8_t)0x00FF);
}
if (--huart->TxXferCount == 0U)
{
/* Disable the UART Transmit Data Register Empty Interrupt */
__HAL_UART_DISABLE_IT(huart, UART_IT_TXE);
/* Enable the UART Transmit Complete Interrupt */
__HAL_UART_ENABLE_IT(huart, UART_IT_TC);
}
return HAL_OK;
}
else
{
return HAL_BUSY;
}
}
/**
* @brief Wraps up transmission in non blocking mode.
* @param huart Pointer to a UART_HandleTypeDef structure that contains
* the configuration information for the specified UART module.
* @retval HAL status
*/
static HAL_StatusTypeDef UART_EndTransmit_IT(UART_HandleTypeDef *huart)
{
/* Disable the UART Transmit Complete Interrupt */
__HAL_UART_DISABLE_IT(huart, UART_IT_TC);
/* Tx process is ended, restore huart->gState to Ready */
huart->gState = HAL_UART_STATE_READY;
#if (USE_HAL_UART_REGISTER_CALLBACKS == 1)
/*Call registered Tx complete callback*/
huart->TxCpltCallback(huart);
#else
/*Call legacy weak Tx complete callback*/
HAL_UART_TxCpltCallback(huart);
#endif /* USE_HAL_UART_REGISTER_CALLBACKS */
return HAL_OK;
}
/**
* @brief Receives an amount of data in non blocking mode
* @param huart Pointer to a UART_HandleTypeDef structure that contains
* the configuration information for the specified UART module.
* @retval HAL status
*/
static HAL_StatusTypeDef UART_Receive_IT(UART_HandleTypeDef *huart)
{
uint8_t *pdata8bits;
uint16_t *pdata16bits;
/* Check that a Rx process is ongoing */
if (huart->RxState == HAL_UART_STATE_BUSY_RX)
{
if ((huart->Init.WordLength == UART_WORDLENGTH_9B) && (huart->Init.Parity == UART_PARITY_NONE))
{
pdata8bits = NULL;
pdata16bits = (uint16_t *) huart->pRxBuffPtr;
*pdata16bits = (uint16_t)(huart->Instance->DR & (uint16_t)0x01FF);
huart->pRxBuffPtr += 2U;
}
else
{
pdata8bits = (uint8_t *) huart->pRxBuffPtr;
pdata16bits = NULL;
if ((huart->Init.WordLength == UART_WORDLENGTH_9B) || ((huart->Init.WordLength == UART_WORDLENGTH_8B) && (huart->Init.Parity == UART_PARITY_NONE)))
{
*pdata8bits = (uint8_t)(huart->Instance->DR & (uint8_t)0x00FF);
}
else
{
*pdata8bits = (uint8_t)(huart->Instance->DR & (uint8_t)0x007F);
}
huart->pRxBuffPtr += 1U;
}
if (--huart->RxXferCount == 0U)
{
/* Disable the UART Data Register not empty Interrupt */
__HAL_UART_DISABLE_IT(huart, UART_IT_RXNE);
/* Disable the UART Parity Error Interrupt */
__HAL_UART_DISABLE_IT(huart, UART_IT_PE);
/* Disable the UART Error Interrupt: (Frame error, noise error, overrun error) */
__HAL_UART_DISABLE_IT(huart, UART_IT_ERR);
/* Rx process is completed, restore huart->RxState to Ready */
huart->RxState = HAL_UART_STATE_READY;
/* Initialize type of RxEvent to Transfer Complete */
huart->RxEventType = HAL_UART_RXEVENT_TC;
/* Check current reception Mode :
If Reception till IDLE event has been selected : */
if (huart->ReceptionType == HAL_UART_RECEPTION_TOIDLE)
{
/* Set reception type to Standard */
huart->ReceptionType = HAL_UART_RECEPTION_STANDARD;
/* Disable IDLE interrupt */
ATOMIC_CLEAR_BIT(huart->Instance->CR1, USART_CR1_IDLEIE);
/* Check if IDLE flag is set */
if (__HAL_UART_GET_FLAG(huart, UART_FLAG_IDLE))
{
/* Clear IDLE flag in ISR */
__HAL_UART_CLEAR_IDLEFLAG(huart);
}
#if (USE_HAL_UART_REGISTER_CALLBACKS == 1)
/*Call registered Rx Event callback*/
huart->RxEventCallback(huart, huart->RxXferSize);
#else
/*Call legacy weak Rx Event callback*/
HAL_UARTEx_RxEventCallback(huart, huart->RxXferSize);
#endif /* USE_HAL_UART_REGISTER_CALLBACKS */
}
else
{
/* Standard reception API called */
#if (USE_HAL_UART_REGISTER_CALLBACKS == 1)
/*Call registered Rx complete callback*/
huart->RxCpltCallback(huart);
#else
/*Call legacy weak Rx complete callback*/
HAL_UART_RxCpltCallback(huart);
#endif /* USE_HAL_UART_REGISTER_CALLBACKS */
}
return HAL_OK;
}
return HAL_OK;
}
else
{
return HAL_BUSY;
}
}
/**
* @brief Configures the UART peripheral.
* @param huart Pointer to a UART_HandleTypeDef structure that contains
* the configuration information for the specified UART module.
* @retval None
*/
static void UART_SetConfig(UART_HandleTypeDef *huart)
{
uint32_t tmpreg;
uint32_t pclk;
/* Check the parameters */
assert_param(IS_UART_BAUDRATE(huart->Init.BaudRate));
assert_param(IS_UART_STOPBITS(huart->Init.StopBits));
assert_param(IS_UART_PARITY(huart->Init.Parity));
assert_param(IS_UART_MODE(huart->Init.Mode));
/*-------------------------- USART CR2 Configuration -----------------------*/
/* Configure the UART Stop Bits: Set STOP[13:12] bits
according to huart->Init.StopBits value */
MODIFY_REG(huart->Instance->CR2, USART_CR2_STOP, huart->Init.StopBits);
/*-------------------------- USART CR1 Configuration -----------------------*/
/* Configure the UART Word Length, Parity and mode:
Set the M bits according to huart->Init.WordLength value
Set PCE and PS bits according to huart->Init.Parity value
Set TE and RE bits according to huart->Init.Mode value
Set OVER8 bit according to huart->Init.OverSampling value */
#if defined(USART_CR1_OVER8)
tmpreg = (uint32_t)huart->Init.WordLength | huart->Init.Parity | huart->Init.Mode | huart->Init.OverSampling;
MODIFY_REG(huart->Instance->CR1,
(uint32_t)(USART_CR1_M | USART_CR1_PCE | USART_CR1_PS | USART_CR1_TE | USART_CR1_RE | USART_CR1_OVER8),
tmpreg);
#else
tmpreg = (uint32_t)huart->Init.WordLength | huart->Init.Parity | huart->Init.Mode;
MODIFY_REG(huart->Instance->CR1,
(uint32_t)(USART_CR1_M | USART_CR1_PCE | USART_CR1_PS | USART_CR1_TE | USART_CR1_RE),
tmpreg);
#endif /* USART_CR1_OVER8 */
/*-------------------------- USART CR3 Configuration -----------------------*/
/* Configure the UART HFC: Set CTSE and RTSE bits according to huart->Init.HwFlowCtl value */
MODIFY_REG(huart->Instance->CR3, (USART_CR3_RTSE | USART_CR3_CTSE), huart->Init.HwFlowCtl);
if(huart->Instance == USART1)
{
pclk = HAL_RCC_GetPCLK2Freq();
}
else
{
pclk = HAL_RCC_GetPCLK1Freq();
}
/*-------------------------- USART BRR Configuration ---------------------*/
#if defined(USART_CR1_OVER8)
if (huart->Init.OverSampling == UART_OVERSAMPLING_8)
{
huart->Instance->BRR = UART_BRR_SAMPLING8(pclk, huart->Init.BaudRate);
}
else
{
huart->Instance->BRR = UART_BRR_SAMPLING16(pclk, huart->Init.BaudRate);
}
#else
huart->Instance->BRR = UART_BRR_SAMPLING16(pclk, huart->Init.BaudRate);
#endif /* USART_CR1_OVER8 */
}
/**
* @}
*/
#endif /* HAL_UART_MODULE_ENABLED */
/**
* @}
*/
/**
* @}
*/

View File

@@ -1,24 +0,0 @@
/*
* Auto generated Run-Time-Environment Configuration File
* *** Do not modify ! ***
*
* Project: 'john103C6T6'
* Target: 'john103C6T6'
*/
#ifndef RTE_COMPONENTS_H
#define RTE_COMPONENTS_H
/*
* Define the Device Header File:
*/
#define CMSIS_device_header "stm32f10x.h"
/* Keil.ARM Compiler::Compiler:I/O:STDOUT:Breakpoint:1.2.0 */
#define RTE_Compiler_IO_STDOUT /* Compiler I/O: STDOUT */
#define RTE_Compiler_IO_STDOUT_BKPT /* Compiler I/O: STDOUT Breakpoint */
#endif /* RTE_COMPONENTS_H */

View File

@@ -1,938 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no" ?>
<ProjectOpt xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="project_optx.xsd">
<SchemaVersion>1.0</SchemaVersion>
<Header>### uVision Project, (C) Keil Software</Header>
<Extensions>
<cExt>*.c</cExt>
<aExt>*.s*; *.src; *.a*</aExt>
<oExt>*.obj; *.o</oExt>
<lExt>*.lib</lExt>
<tExt>*.txt; *.h; *.inc; *.md</tExt>
<pExt>*.plm</pExt>
<CppX>*.cpp</CppX>
<nMigrate>0</nMigrate>
</Extensions>
<DaveTm>
<dwLowDateTime>0</dwLowDateTime>
<dwHighDateTime>0</dwHighDateTime>
</DaveTm>
<Target>
<TargetName>john103C6T6</TargetName>
<ToolsetNumber>0x4</ToolsetNumber>
<ToolsetName>ARM-ADS</ToolsetName>
<TargetOption>
<CLKADS>8000000</CLKADS>
<OPTTT>
<gFlags>1</gFlags>
<BeepAtEnd>1</BeepAtEnd>
<RunSim>0</RunSim>
<RunTarget>1</RunTarget>
<RunAbUc>0</RunAbUc>
</OPTTT>
<OPTHX>
<HexSelection>1</HexSelection>
<FlashByte>65535</FlashByte>
<HexRangeLowAddress>0</HexRangeLowAddress>
<HexRangeHighAddress>0</HexRangeHighAddress>
<HexOffset>0</HexOffset>
</OPTHX>
<OPTLEX>
<PageWidth>79</PageWidth>
<PageLength>66</PageLength>
<TabStop>8</TabStop>
<ListingPath>C:\Users\z\Documents\</ListingPath>
</OPTLEX>
<ListingPage>
<CreateCListing>1</CreateCListing>
<CreateAListing>1</CreateAListing>
<CreateLListing>1</CreateLListing>
<CreateIListing>0</CreateIListing>
<AsmCond>1</AsmCond>
<AsmSymb>1</AsmSymb>
<AsmXref>0</AsmXref>
<CCond>1</CCond>
<CCode>0</CCode>
<CListInc>0</CListInc>
<CSymb>0</CSymb>
<LinkerCodeListing>0</LinkerCodeListing>
</ListingPage>
<OPTXL>
<LMap>1</LMap>
<LComments>1</LComments>
<LGenerateSymbols>1</LGenerateSymbols>
<LLibSym>1</LLibSym>
<LLines>1</LLines>
<LLocSym>1</LLocSym>
<LPubSym>1</LPubSym>
<LXref>0</LXref>
<LExpSel>0</LExpSel>
</OPTXL>
<OPTFL>
<tvExp>1</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
<IsCurrentTarget>1</IsCurrentTarget>
</OPTFL>
<CpuCode>18</CpuCode>
<DebugOpt>
<uSim>0</uSim>
<uTrg>1</uTrg>
<sLdApp>1</sLdApp>
<sGomain>1</sGomain>
<sRbreak>1</sRbreak>
<sRwatch>1</sRwatch>
<sRmem>1</sRmem>
<sRfunc>1</sRfunc>
<sRbox>1</sRbox>
<tLdApp>1</tLdApp>
<tGomain>1</tGomain>
<tRbreak>1</tRbreak>
<tRwatch>1</tRwatch>
<tRmem>1</tRmem>
<tRfunc>1</tRfunc>
<tRbox>1</tRbox>
<tRtrace>1</tRtrace>
<sRSysVw>1</sRSysVw>
<tRSysVw>1</tRSysVw>
<sRunDeb>0</sRunDeb>
<sLrtime>0</sLrtime>
<bEvRecOn>1</bEvRecOn>
<bSchkAxf>0</bSchkAxf>
<bTchkAxf>0</bTchkAxf>
<nTsel>6</nTsel>
<sDll></sDll>
<sDllPa></sDllPa>
<sDlgDll></sDlgDll>
<sDlgPa></sDlgPa>
<sIfile></sIfile>
<tDll></tDll>
<tDllPa></tDllPa>
<tDlgDll></tDlgDll>
<tDlgPa></tDlgPa>
<tIfile></tIfile>
<pMon>STLink\ST-LINKIII-KEIL_SWO.dll</pMon>
</DebugOpt>
<TargetDriverDllRegistry>
<SetRegEntry>
<Number>0</Number>
<Key>ARMRTXEVENTFLAGS</Key>
<Name>-L70 -Z18 -C0 -M0 -T1</Name>
</SetRegEntry>
<SetRegEntry>
<Number>0</Number>
<Key>DLGTARM</Key>
<Name>(1010=-1,-1,-1,-1,0)(1007=-1,-1,-1,-1,0)(1008=-1,-1,-1,-1,0)(1009=-1,-1,-1,-1,0)</Name>
</SetRegEntry>
<SetRegEntry>
<Number>0</Number>
<Key>ARMDBGFLAGS</Key>
<Name></Name>
</SetRegEntry>
<SetRegEntry>
<Number>0</Number>
<Key>DLGUARM</Key>
<Name>(105=-1,-1,-1,-1,0)</Name>
</SetRegEntry>
<SetRegEntry>
<Number>0</Number>
<Key>UL2CM3</Key>
<Name>UL2CM3(-S0 -C0 -P0 -FD20000000 -FC1000 -FN1 -FF0STM32F10x_128 -FS08000000 -FL020000 -FP0($$Device:STM32F103C6$Flash\STM32F10x_128.FLM))</Name>
</SetRegEntry>
<SetRegEntry>
<Number>0</Number>
<Key>ST-LINKIII-KEIL_SWO</Key>
<Name>-U37FF71064E57343625581443 -O2254 -SF10000 -C0 -A0 -I0 -HNlocalhost -HP7184 -P1 -N00("ARM CoreSight SW-DP (ARM Core") -D00(1BA01477) -L00(0) -TO131090 -TC10000000 -TT10000000 -TP21 -TDS8000 -TDT0 -TDC1F -TIEFFFFFFFF -TIP8 -FO15 -FD20000000 -FC800 -FN1 -FF0STM32F10x_128.FLM -FS08000000 -FL08000 -FP0($$Device:STM32F103C6$Flash\STM32F10x_128.FLM) -WA0 -WE0 -WVCE4 -WS2710 -WM0 -WP2</Name>
</SetRegEntry>
</TargetDriverDllRegistry>
<Breakpoint>
<Bp>
<Number>0</Number>
<Type>0</Type>
<LineNumber>302</LineNumber>
<EnabledFlag>1</EnabledFlag>
<Address>0</Address>
<ByteObject>0</ByteObject>
<HtxType>0</HtxType>
<ManyObjects>0</ManyObjects>
<SizeOfObject>0</SizeOfObject>
<BreakByAccess>0</BreakByAccess>
<BreakIfRCount>0</BreakIfRCount>
<Filename>..\Modbus\modbus.c</Filename>
<ExecCommand></ExecCommand>
<Expression></Expression>
</Bp>
</Breakpoint>
<WatchWindow1>
<Ww>
<count>0</count>
<WinNumber>1</WinNumber>
<ItemText>sens,0x0A</ItemText>
</Ww>
<Ww>
<count>1</count>
<WinNumber>1</WinNumber>
<ItemText>hdallas</ItemText>
</Ww>
<Ww>
<count>2</count>
<WinNumber>1</WinNumber>
<ItemText>DS</ItemText>
</Ww>
<Ww>
<count>3</count>
<WinNumber>1</WinNumber>
<ItemText>hmodbus1</ItemText>
</Ww>
<Ww>
<count>4</count>
<WinNumber>1</WinNumber>
<ItemText>hiwdg</ItemText>
</Ww>
<Ww>
<count>5</count>
<WinNumber>1</WinNumber>
<ItemText>OW</ItemText>
</Ww>
<Ww>
<count>6</count>
<WinNumber>1</WinNumber>
<ItemText>_debug_init</ItemText>
</Ww>
<Ww>
<count>7</count>
<WinNumber>1</WinNumber>
<ItemText>htim1,0x0A</ItemText>
</Ww>
<Ww>
<count>8</count>
<WinNumber>1</WinNumber>
<ItemText>DS18B20_DEVICE_AMOUNT</ItemText>
</Ww>
<Ww>
<count>9</count>
<WinNumber>1</WinNumber>
<ItemText>set_temp_old</ItemText>
</Ww>
<Ww>
<count>10</count>
<WinNumber>1</WinNumber>
<ItemText>hrtc.Instance,0x0A</ItemText>
</Ww>
<Ww>
<count>11</count>
<WinNumber>1</WinNumber>
<ItemText>\\john103C6T6\../Modbus/modbus.c\MB_DATA,0x0A</ItemText>
</Ww>
<Ww>
<count>12</count>
<WinNumber>1</WinNumber>
<ItemText>sTime</ItemText>
</Ww>
<Ww>
<count>13</count>
<WinNumber>1</WinNumber>
<ItemText>ralay_5v_on_var</ItemText>
</Ww>
<Ww>
<count>14</count>
<WinNumber>1</WinNumber>
<ItemText>MB_DATA.Coils.coils[1].state_val_bit.state_val_01,0x0A</ItemText>
</Ww>
<Ww>
<count>15</count>
<WinNumber>1</WinNumber>
<ItemText>RS_Buffer</ItemText>
</Ww>
<Ww>
<count>16</count>
<WinNumber>1</WinNumber>
<ItemText>MODBUS_MSG</ItemText>
</Ww>
<Ww>
<count>17</count>
<WinNumber>1</WinNumber>
<ItemText>modbus_uart_buff</ItemText>
</Ww>
</WatchWindow1>
<WatchWindow2>
<Ww>
<count>0</count>
<WinNumber>2</WinNumber>
<ItemText>resolution</ItemText>
</Ww>
</WatchWindow2>
<MemoryWindow1>
<Mm>
<WinNumber>1</WinNumber>
<SubType>0</SubType>
<ItemText>0x2000058c</ItemText>
<AccSizeX>0</AccSizeX>
</Mm>
</MemoryWindow1>
<Tracepoint>
<THDelay>0</THDelay>
</Tracepoint>
<DebugFlag>
<trace>0</trace>
<periodic>1</periodic>
<aLwin>1</aLwin>
<aCover>0</aCover>
<aSer1>0</aSer1>
<aSer2>0</aSer2>
<aPa>0</aPa>
<viewmode>1</viewmode>
<vrSel>0</vrSel>
<aSym>0</aSym>
<aTbox>0</aTbox>
<AscS1>0</AscS1>
<AscS2>0</AscS2>
<AscS3>0</AscS3>
<aSer3>0</aSer3>
<eProf>0</eProf>
<aLa>0</aLa>
<aPa1>0</aPa1>
<AscS4>0</AscS4>
<aSer4>0</aSer4>
<StkLoc>1</StkLoc>
<TrcWin>0</TrcWin>
<newCpu>0</newCpu>
<uProt>0</uProt>
</DebugFlag>
<LintExecutable></LintExecutable>
<LintConfigFile></LintConfigFile>
<bLintAuto>0</bLintAuto>
<bAutoGenD>0</bAutoGenD>
<LntExFlags>0</LntExFlags>
<pMisraName></pMisraName>
<pszMrule></pszMrule>
<pSingCmds></pSingCmds>
<pMultCmds></pMultCmds>
<pMisraNamep></pMisraNamep>
<pszMrulep></pszMrulep>
<pSingCmdsp></pSingCmdsp>
<pMultCmdsp></pMultCmdsp>
<SystemViewers>
<Entry>
<Name>System Viewer\BKP</Name>
<WinId>35895</WinId>
</Entry>
<Entry>
<Name>System Viewer\GPIOA</Name>
<WinId>35904</WinId>
</Entry>
<Entry>
<Name>System Viewer\GPIOB</Name>
<WinId>35900</WinId>
</Entry>
<Entry>
<Name>System Viewer\GPIOC</Name>
<WinId>35896</WinId>
</Entry>
<Entry>
<Name>System Viewer\IWDG</Name>
<WinId>35905</WinId>
</Entry>
<Entry>
<Name>System Viewer\PWR</Name>
<WinId>35899</WinId>
</Entry>
<Entry>
<Name>System Viewer\RCC</Name>
<WinId>35898</WinId>
</Entry>
<Entry>
<Name>System Viewer\RTC</Name>
<WinId>35897</WinId>
</Entry>
<Entry>
<Name>System Viewer\TIM1</Name>
<WinId>35903</WinId>
</Entry>
<Entry>
<Name>System Viewer\TIM2</Name>
<WinId>35901</WinId>
</Entry>
<Entry>
<Name>System Viewer\USART1</Name>
<WinId>35902</WinId>
</Entry>
</SystemViewers>
<DebugDescription>
<Enable>1</Enable>
<EnableFlashSeq>0</EnableFlashSeq>
<EnableLog>0</EnableLog>
<Protocol>2</Protocol>
<DbgClock>10000000</DbgClock>
</DebugDescription>
</TargetOption>
</Target>
<Group>
<GroupName>Application/MDK-ARM</GroupName>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
<cbSel>0</cbSel>
<RteFlg>0</RteFlg>
<File>
<GroupNumber>1</GroupNumber>
<FileNumber>1</FileNumber>
<FileType>2</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
<bDave2>0</bDave2>
<PathWithFileName>startup_stm32f103x6.s</PathWithFileName>
<FilenameWithoutPath>startup_stm32f103x6.s</FilenameWithoutPath>
<RteFlg>0</RteFlg>
<bShared>0</bShared>
</File>
</Group>
<Group>
<GroupName>Application/User/Core</GroupName>
<tvExp>1</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
<cbSel>0</cbSel>
<RteFlg>0</RteFlg>
<File>
<GroupNumber>2</GroupNumber>
<FileNumber>2</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
<bDave2>0</bDave2>
<PathWithFileName>..\Core\Src\UART_TERM.c</PathWithFileName>
<FilenameWithoutPath>UART_TERM.c</FilenameWithoutPath>
<RteFlg>0</RteFlg>
<bShared>0</bShared>
</File>
<File>
<GroupNumber>2</GroupNumber>
<FileNumber>3</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
<bDave2>0</bDave2>
<PathWithFileName>..\Core\Src\dallas_tools.c</PathWithFileName>
<FilenameWithoutPath>dallas_tools.c</FilenameWithoutPath>
<RteFlg>0</RteFlg>
<bShared>0</bShared>
</File>
<File>
<GroupNumber>2</GroupNumber>
<FileNumber>4</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
<bDave2>0</bDave2>
<PathWithFileName>..\Core\Src\ds18b20_driver.c</PathWithFileName>
<FilenameWithoutPath>ds18b20_driver.c</FilenameWithoutPath>
<RteFlg>0</RteFlg>
<bShared>0</bShared>
</File>
<File>
<GroupNumber>2</GroupNumber>
<FileNumber>5</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
<bDave2>0</bDave2>
<PathWithFileName>..\Core\Src\onewire.c</PathWithFileName>
<FilenameWithoutPath>onewire.c</FilenameWithoutPath>
<RteFlg>0</RteFlg>
<bShared>0</bShared>
</File>
<File>
<GroupNumber>2</GroupNumber>
<FileNumber>6</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
<bDave2>0</bDave2>
<PathWithFileName>..\Core\Src\ow_port.c</PathWithFileName>
<FilenameWithoutPath>ow_port.c</FilenameWithoutPath>
<RteFlg>0</RteFlg>
<bShared>0</bShared>
</File>
<File>
<GroupNumber>2</GroupNumber>
<FileNumber>7</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
<bDave2>0</bDave2>
<PathWithFileName>..\Modbus\crc_algs.c</PathWithFileName>
<FilenameWithoutPath>crc_algs.c</FilenameWithoutPath>
<RteFlg>0</RteFlg>
<bShared>0</bShared>
</File>
<File>
<GroupNumber>2</GroupNumber>
<FileNumber>8</FileNumber>
<FileType>1</FileType>
<tvExp>1</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
<bDave2>0</bDave2>
<PathWithFileName>..\Modbus\modbus.c</PathWithFileName>
<FilenameWithoutPath>modbus.c</FilenameWithoutPath>
<RteFlg>0</RteFlg>
<bShared>0</bShared>
</File>
<File>
<GroupNumber>2</GroupNumber>
<FileNumber>9</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
<bDave2>0</bDave2>
<PathWithFileName>..\Modbus\rs_message.c</PathWithFileName>
<FilenameWithoutPath>rs_message.c</FilenameWithoutPath>
<RteFlg>0</RteFlg>
<bShared>0</bShared>
</File>
<File>
<GroupNumber>2</GroupNumber>
<FileNumber>10</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
<bDave2>0</bDave2>
<PathWithFileName>../Core/Src/main.c</PathWithFileName>
<FilenameWithoutPath>main.c</FilenameWithoutPath>
<RteFlg>0</RteFlg>
<bShared>0</bShared>
</File>
<File>
<GroupNumber>2</GroupNumber>
<FileNumber>11</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
<bDave2>0</bDave2>
<PathWithFileName>../Core/Src/gpio.c</PathWithFileName>
<FilenameWithoutPath>gpio.c</FilenameWithoutPath>
<RteFlg>0</RteFlg>
<bShared>0</bShared>
</File>
<File>
<GroupNumber>2</GroupNumber>
<FileNumber>12</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
<bDave2>0</bDave2>
<PathWithFileName>../Core/Src/adc.c</PathWithFileName>
<FilenameWithoutPath>adc.c</FilenameWithoutPath>
<RteFlg>0</RteFlg>
<bShared>0</bShared>
</File>
<File>
<GroupNumber>2</GroupNumber>
<FileNumber>13</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
<bDave2>0</bDave2>
<PathWithFileName>../Core/Src/can.c</PathWithFileName>
<FilenameWithoutPath>can.c</FilenameWithoutPath>
<RteFlg>0</RteFlg>
<bShared>0</bShared>
</File>
<File>
<GroupNumber>2</GroupNumber>
<FileNumber>14</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
<bDave2>0</bDave2>
<PathWithFileName>../Core/Src/i2c.c</PathWithFileName>
<FilenameWithoutPath>i2c.c</FilenameWithoutPath>
<RteFlg>0</RteFlg>
<bShared>0</bShared>
</File>
<File>
<GroupNumber>2</GroupNumber>
<FileNumber>15</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
<bDave2>0</bDave2>
<PathWithFileName>../Core/Src/rtc.c</PathWithFileName>
<FilenameWithoutPath>rtc.c</FilenameWithoutPath>
<RteFlg>0</RteFlg>
<bShared>0</bShared>
</File>
<File>
<GroupNumber>2</GroupNumber>
<FileNumber>16</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
<bDave2>0</bDave2>
<PathWithFileName>../Core/Src/spi.c</PathWithFileName>
<FilenameWithoutPath>spi.c</FilenameWithoutPath>
<RteFlg>0</RteFlg>
<bShared>0</bShared>
</File>
<File>
<GroupNumber>2</GroupNumber>
<FileNumber>17</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
<bDave2>0</bDave2>
<PathWithFileName>../Core/Src/tim.c</PathWithFileName>
<FilenameWithoutPath>tim.c</FilenameWithoutPath>
<RteFlg>0</RteFlg>
<bShared>0</bShared>
</File>
<File>
<GroupNumber>2</GroupNumber>
<FileNumber>18</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
<bDave2>0</bDave2>
<PathWithFileName>../Core/Src/usart.c</PathWithFileName>
<FilenameWithoutPath>usart.c</FilenameWithoutPath>
<RteFlg>0</RteFlg>
<bShared>0</bShared>
</File>
<File>
<GroupNumber>2</GroupNumber>
<FileNumber>19</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
<bDave2>0</bDave2>
<PathWithFileName>../Core/Src/stm32f1xx_it.c</PathWithFileName>
<FilenameWithoutPath>stm32f1xx_it.c</FilenameWithoutPath>
<RteFlg>0</RteFlg>
<bShared>0</bShared>
</File>
<File>
<GroupNumber>2</GroupNumber>
<FileNumber>20</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
<bDave2>0</bDave2>
<PathWithFileName>../Core/Src/stm32f1xx_hal_msp.c</PathWithFileName>
<FilenameWithoutPath>stm32f1xx_hal_msp.c</FilenameWithoutPath>
<RteFlg>0</RteFlg>
<bShared>0</bShared>
</File>
<File>
<GroupNumber>2</GroupNumber>
<FileNumber>21</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
<bDave2>0</bDave2>
<PathWithFileName>../Core/Src/stm32f1xx_hal_timebase_tim.c</PathWithFileName>
<FilenameWithoutPath>stm32f1xx_hal_timebase_tim.c</FilenameWithoutPath>
<RteFlg>0</RteFlg>
<bShared>0</bShared>
</File>
</Group>
<Group>
<GroupName>Drivers/STM32F1xx_HAL_Driver</GroupName>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
<cbSel>0</cbSel>
<RteFlg>0</RteFlg>
<File>
<GroupNumber>3</GroupNumber>
<FileNumber>22</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
<bDave2>0</bDave2>
<PathWithFileName>../Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_gpio_ex.c</PathWithFileName>
<FilenameWithoutPath>stm32f1xx_hal_gpio_ex.c</FilenameWithoutPath>
<RteFlg>0</RteFlg>
<bShared>0</bShared>
</File>
<File>
<GroupNumber>3</GroupNumber>
<FileNumber>23</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
<bDave2>0</bDave2>
<PathWithFileName>../Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_adc.c</PathWithFileName>
<FilenameWithoutPath>stm32f1xx_hal_adc.c</FilenameWithoutPath>
<RteFlg>0</RteFlg>
<bShared>0</bShared>
</File>
<File>
<GroupNumber>3</GroupNumber>
<FileNumber>24</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
<bDave2>0</bDave2>
<PathWithFileName>../Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_adc_ex.c</PathWithFileName>
<FilenameWithoutPath>stm32f1xx_hal_adc_ex.c</FilenameWithoutPath>
<RteFlg>0</RteFlg>
<bShared>0</bShared>
</File>
<File>
<GroupNumber>3</GroupNumber>
<FileNumber>25</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
<bDave2>0</bDave2>
<PathWithFileName>../Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal.c</PathWithFileName>
<FilenameWithoutPath>stm32f1xx_hal.c</FilenameWithoutPath>
<RteFlg>0</RteFlg>
<bShared>0</bShared>
</File>
<File>
<GroupNumber>3</GroupNumber>
<FileNumber>26</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
<bDave2>0</bDave2>
<PathWithFileName>../Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_rcc.c</PathWithFileName>
<FilenameWithoutPath>stm32f1xx_hal_rcc.c</FilenameWithoutPath>
<RteFlg>0</RteFlg>
<bShared>0</bShared>
</File>
<File>
<GroupNumber>3</GroupNumber>
<FileNumber>27</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
<bDave2>0</bDave2>
<PathWithFileName>../Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_rcc_ex.c</PathWithFileName>
<FilenameWithoutPath>stm32f1xx_hal_rcc_ex.c</FilenameWithoutPath>
<RteFlg>0</RteFlg>
<bShared>0</bShared>
</File>
<File>
<GroupNumber>3</GroupNumber>
<FileNumber>28</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
<bDave2>0</bDave2>
<PathWithFileName>../Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_gpio.c</PathWithFileName>
<FilenameWithoutPath>stm32f1xx_hal_gpio.c</FilenameWithoutPath>
<RteFlg>0</RteFlg>
<bShared>0</bShared>
</File>
<File>
<GroupNumber>3</GroupNumber>
<FileNumber>29</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
<bDave2>0</bDave2>
<PathWithFileName>../Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_dma.c</PathWithFileName>
<FilenameWithoutPath>stm32f1xx_hal_dma.c</FilenameWithoutPath>
<RteFlg>0</RteFlg>
<bShared>0</bShared>
</File>
<File>
<GroupNumber>3</GroupNumber>
<FileNumber>30</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
<bDave2>0</bDave2>
<PathWithFileName>../Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_cortex.c</PathWithFileName>
<FilenameWithoutPath>stm32f1xx_hal_cortex.c</FilenameWithoutPath>
<RteFlg>0</RteFlg>
<bShared>0</bShared>
</File>
<File>
<GroupNumber>3</GroupNumber>
<FileNumber>31</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
<bDave2>0</bDave2>
<PathWithFileName>../Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_pwr.c</PathWithFileName>
<FilenameWithoutPath>stm32f1xx_hal_pwr.c</FilenameWithoutPath>
<RteFlg>0</RteFlg>
<bShared>0</bShared>
</File>
<File>
<GroupNumber>3</GroupNumber>
<FileNumber>32</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
<bDave2>0</bDave2>
<PathWithFileName>../Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_flash.c</PathWithFileName>
<FilenameWithoutPath>stm32f1xx_hal_flash.c</FilenameWithoutPath>
<RteFlg>0</RteFlg>
<bShared>0</bShared>
</File>
<File>
<GroupNumber>3</GroupNumber>
<FileNumber>33</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
<bDave2>0</bDave2>
<PathWithFileName>../Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_flash_ex.c</PathWithFileName>
<FilenameWithoutPath>stm32f1xx_hal_flash_ex.c</FilenameWithoutPath>
<RteFlg>0</RteFlg>
<bShared>0</bShared>
</File>
<File>
<GroupNumber>3</GroupNumber>
<FileNumber>34</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
<bDave2>0</bDave2>
<PathWithFileName>../Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_exti.c</PathWithFileName>
<FilenameWithoutPath>stm32f1xx_hal_exti.c</FilenameWithoutPath>
<RteFlg>0</RteFlg>
<bShared>0</bShared>
</File>
<File>
<GroupNumber>3</GroupNumber>
<FileNumber>35</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
<bDave2>0</bDave2>
<PathWithFileName>../Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_can.c</PathWithFileName>
<FilenameWithoutPath>stm32f1xx_hal_can.c</FilenameWithoutPath>
<RteFlg>0</RteFlg>
<bShared>0</bShared>
</File>
<File>
<GroupNumber>3</GroupNumber>
<FileNumber>36</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
<bDave2>0</bDave2>
<PathWithFileName>../Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_i2c.c</PathWithFileName>
<FilenameWithoutPath>stm32f1xx_hal_i2c.c</FilenameWithoutPath>
<RteFlg>0</RteFlg>
<bShared>0</bShared>
</File>
<File>
<GroupNumber>3</GroupNumber>
<FileNumber>37</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
<bDave2>0</bDave2>
<PathWithFileName>../Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_rtc.c</PathWithFileName>
<FilenameWithoutPath>stm32f1xx_hal_rtc.c</FilenameWithoutPath>
<RteFlg>0</RteFlg>
<bShared>0</bShared>
</File>
<File>
<GroupNumber>3</GroupNumber>
<FileNumber>38</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
<bDave2>0</bDave2>
<PathWithFileName>../Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_rtc_ex.c</PathWithFileName>
<FilenameWithoutPath>stm32f1xx_hal_rtc_ex.c</FilenameWithoutPath>
<RteFlg>0</RteFlg>
<bShared>0</bShared>
</File>
<File>
<GroupNumber>3</GroupNumber>
<FileNumber>39</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
<bDave2>0</bDave2>
<PathWithFileName>../Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_spi.c</PathWithFileName>
<FilenameWithoutPath>stm32f1xx_hal_spi.c</FilenameWithoutPath>
<RteFlg>0</RteFlg>
<bShared>0</bShared>
</File>
<File>
<GroupNumber>3</GroupNumber>
<FileNumber>40</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
<bDave2>0</bDave2>
<PathWithFileName>../Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_tim.c</PathWithFileName>
<FilenameWithoutPath>stm32f1xx_hal_tim.c</FilenameWithoutPath>
<RteFlg>0</RteFlg>
<bShared>0</bShared>
</File>
<File>
<GroupNumber>3</GroupNumber>
<FileNumber>41</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
<bDave2>0</bDave2>
<PathWithFileName>../Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_tim_ex.c</PathWithFileName>
<FilenameWithoutPath>stm32f1xx_hal_tim_ex.c</FilenameWithoutPath>
<RteFlg>0</RteFlg>
<bShared>0</bShared>
</File>
<File>
<GroupNumber>3</GroupNumber>
<FileNumber>42</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
<bDave2>0</bDave2>
<PathWithFileName>../Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_uart.c</PathWithFileName>
<FilenameWithoutPath>stm32f1xx_hal_uart.c</FilenameWithoutPath>
<RteFlg>0</RteFlg>
<bShared>0</bShared>
</File>
</Group>
<Group>
<GroupName>Drivers/CMSIS</GroupName>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
<cbSel>0</cbSel>
<RteFlg>0</RteFlg>
<File>
<GroupNumber>4</GroupNumber>
<FileNumber>43</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
<bDave2>0</bDave2>
<PathWithFileName>../Core/Src/system_stm32f1xx.c</PathWithFileName>
<FilenameWithoutPath>system_stm32f1xx.c</FilenameWithoutPath>
<RteFlg>0</RteFlg>
<bShared>0</bShared>
</File>
</Group>
<Group>
<GroupName>::CMSIS</GroupName>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
<cbSel>0</cbSel>
<RteFlg>1</RteFlg>
</Group>
<Group>
<GroupName>::Compiler</GroupName>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
<cbSel>0</cbSel>
<RteFlg>1</RteFlg>
</Group>
</ProjectOpt>

View File

@@ -1,1270 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no" ?>
<Project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="project_projx.xsd">
<SchemaVersion>2.1</SchemaVersion>
<Header>### uVision Project, (C) Keil Software</Header>
<Targets>
<Target>
<TargetName>john103C6T6</TargetName>
<ToolsetNumber>0x4</ToolsetNumber>
<ToolsetName>ARM-ADS</ToolsetName>
<pArmCC>6190000::V6.19::ARMCLANG</pArmCC>
<pCCUsed>6190000::V6.19::ARMCLANG</pCCUsed>
<uAC6>1</uAC6>
<TargetOption>
<TargetCommonOption>
<Device>STM32F103C6</Device>
<Vendor>STMicroelectronics</Vendor>
<PackID>Keil.STM32F1xx_DFP.2.4.1</PackID>
<PackURL>https://www.keil.com/pack/</PackURL>
<Cpu>IRAM(0x20000000-0x200027FF) IROM(0x8000000-0x8007FFF) CLOCK(8000000) CPUTYPE("Cortex-M3") TZ</Cpu>
<FlashUtilSpec></FlashUtilSpec>
<StartupFile></StartupFile>
<FlashDriverDll></FlashDriverDll>
<DeviceId>0</DeviceId>
<RegisterFile></RegisterFile>
<MemoryEnv></MemoryEnv>
<Cmp></Cmp>
<Asm></Asm>
<Linker></Linker>
<OHString></OHString>
<InfinionOptionDll></InfinionOptionDll>
<SLE66CMisc></SLE66CMisc>
<SLE66AMisc></SLE66AMisc>
<SLE66LinkerMisc></SLE66LinkerMisc>
<SFDFile>$$Device:STM32F103C6$SVD\STM32F103xx.svd</SFDFile>
<bCustSvd>0</bCustSvd>
<UseEnv>0</UseEnv>
<BinPath></BinPath>
<IncludePath></IncludePath>
<LibPath></LibPath>
<RegisterFilePath></RegisterFilePath>
<DBRegisterFilePath></DBRegisterFilePath>
<TargetStatus>
<Error>0</Error>
<ExitCodeStop>0</ExitCodeStop>
<ButtonStop>0</ButtonStop>
<NotGenerated>0</NotGenerated>
<InvalidFlash>1</InvalidFlash>
</TargetStatus>
<OutputDirectory>john103C6T6\</OutputDirectory>
<OutputName>john103C6T6</OutputName>
<CreateExecutable>1</CreateExecutable>
<CreateLib>0</CreateLib>
<CreateHexFile>1</CreateHexFile>
<DebugInformation>1</DebugInformation>
<BrowseInformation>1</BrowseInformation>
<ListingPath>C:\Users\z\Documents\</ListingPath>
<HexFormatSelection>1</HexFormatSelection>
<Merge32K>0</Merge32K>
<CreateBatchFile>0</CreateBatchFile>
<BeforeCompile>
<RunUserProg1>0</RunUserProg1>
<RunUserProg2>0</RunUserProg2>
<UserProg1Name></UserProg1Name>
<UserProg2Name></UserProg2Name>
<UserProg1Dos16Mode>0</UserProg1Dos16Mode>
<UserProg2Dos16Mode>0</UserProg2Dos16Mode>
<nStopU1X>0</nStopU1X>
<nStopU2X>0</nStopU2X>
</BeforeCompile>
<BeforeMake>
<RunUserProg1>0</RunUserProg1>
<RunUserProg2>0</RunUserProg2>
<UserProg1Name></UserProg1Name>
<UserProg2Name></UserProg2Name>
<UserProg1Dos16Mode>0</UserProg1Dos16Mode>
<UserProg2Dos16Mode>0</UserProg2Dos16Mode>
<nStopB1X>0</nStopB1X>
<nStopB2X>0</nStopB2X>
</BeforeMake>
<AfterMake>
<RunUserProg1>0</RunUserProg1>
<RunUserProg2>1</RunUserProg2>
<UserProg1Name></UserProg1Name>
<UserProg2Name></UserProg2Name>
<UserProg1Dos16Mode>0</UserProg1Dos16Mode>
<UserProg2Dos16Mode>0</UserProg2Dos16Mode>
<nStopA1X>0</nStopA1X>
<nStopA2X>0</nStopA2X>
</AfterMake>
<SelectedForBatchBuild>1</SelectedForBatchBuild>
<SVCSIdString></SVCSIdString>
</TargetCommonOption>
<CommonProperty>
<UseCPPCompiler>0</UseCPPCompiler>
<RVCTCodeConst>0</RVCTCodeConst>
<RVCTZI>0</RVCTZI>
<RVCTOtherData>0</RVCTOtherData>
<ModuleSelection>0</ModuleSelection>
<IncludeInBuild>1</IncludeInBuild>
<AlwaysBuild>0</AlwaysBuild>
<GenerateAssemblyFile>0</GenerateAssemblyFile>
<AssembleAssemblyFile>0</AssembleAssemblyFile>
<PublicsOnly>0</PublicsOnly>
<StopOnExitCode>3</StopOnExitCode>
<CustomArgument></CustomArgument>
<IncludeLibraryModules></IncludeLibraryModules>
<ComprImg>0</ComprImg>
</CommonProperty>
<DllOption>
<SimDllName>SARMCM3.DLL</SimDllName>
<SimDllArguments>-REMAP</SimDllArguments>
<SimDlgDll>DCM.DLL</SimDlgDll>
<SimDlgDllArguments>-pCM3</SimDlgDllArguments>
<TargetDllName>SARMCM3.DLL</TargetDllName>
<TargetDllArguments></TargetDllArguments>
<TargetDlgDll>TCM.DLL</TargetDlgDll>
<TargetDlgDllArguments>-pCM3</TargetDlgDllArguments>
</DllOption>
<DebugOption>
<OPTHX>
<HexSelection>1</HexSelection>
<HexRangeLowAddress>0</HexRangeLowAddress>
<HexRangeHighAddress>0</HexRangeHighAddress>
<HexOffset>0</HexOffset>
<Oh166RecLen>16</Oh166RecLen>
</OPTHX>
</DebugOption>
<Utilities>
<Flash1>
<UseTargetDll>1</UseTargetDll>
<UseExternalTool>0</UseExternalTool>
<RunIndependent>0</RunIndependent>
<UpdateFlashBeforeDebugging>0</UpdateFlashBeforeDebugging>
<Capability>1</Capability>
<DriverSelection>4101</DriverSelection>
</Flash1>
<bUseTDR>1</bUseTDR>
<Flash2>STLink\ST-LINKIII-KEIL_SWO.dll</Flash2>
<Flash3>"" ()</Flash3>
<Flash4></Flash4>
<pFcarmOut></pFcarmOut>
<pFcarmGrp></pFcarmGrp>
<pFcArmRoot></pFcArmRoot>
<FcArmLst>0</FcArmLst>
</Utilities>
<TargetArmAds>
<ArmAdsMisc>
<GenerateListings>0</GenerateListings>
<asHll>1</asHll>
<asAsm>1</asAsm>
<asMacX>1</asMacX>
<asSyms>1</asSyms>
<asFals>1</asFals>
<asDbgD>1</asDbgD>
<asForm>1</asForm>
<ldLst>0</ldLst>
<ldmm>1</ldmm>
<ldXref>1</ldXref>
<BigEnd>0</BigEnd>
<AdsALst>1</AdsALst>
<AdsACrf>1</AdsACrf>
<AdsANop>0</AdsANop>
<AdsANot>0</AdsANot>
<AdsLLst>1</AdsLLst>
<AdsLmap>1</AdsLmap>
<AdsLcgr>1</AdsLcgr>
<AdsLsym>1</AdsLsym>
<AdsLszi>1</AdsLszi>
<AdsLtoi>1</AdsLtoi>
<AdsLsun>1</AdsLsun>
<AdsLven>1</AdsLven>
<AdsLsxf>1</AdsLsxf>
<RvctClst>0</RvctClst>
<GenPPlst>0</GenPPlst>
<AdsCpuType>"Cortex-M3"</AdsCpuType>
<RvctDeviceName></RvctDeviceName>
<mOS>0</mOS>
<uocRom>0</uocRom>
<uocRam>0</uocRam>
<hadIROM>1</hadIROM>
<hadIRAM>1</hadIRAM>
<hadXRAM>0</hadXRAM>
<uocXRam>0</uocXRam>
<RvdsVP>0</RvdsVP>
<RvdsMve>0</RvdsMve>
<RvdsCdeCp>0</RvdsCdeCp>
<nBranchProt>0</nBranchProt>
<hadIRAM2>0</hadIRAM2>
<hadIROM2>0</hadIROM2>
<StupSel>8</StupSel>
<useUlib>0</useUlib>
<EndSel>0</EndSel>
<uLtcg>0</uLtcg>
<nSecure>0</nSecure>
<RoSelD>3</RoSelD>
<RwSelD>4</RwSelD>
<CodeSel>0</CodeSel>
<OptFeed>0</OptFeed>
<NoZi1>0</NoZi1>
<NoZi2>0</NoZi2>
<NoZi3>0</NoZi3>
<NoZi4>0</NoZi4>
<NoZi5>0</NoZi5>
<Ro1Chk>0</Ro1Chk>
<Ro2Chk>0</Ro2Chk>
<Ro3Chk>0</Ro3Chk>
<Ir1Chk>1</Ir1Chk>
<Ir2Chk>0</Ir2Chk>
<Ra1Chk>0</Ra1Chk>
<Ra2Chk>0</Ra2Chk>
<Ra3Chk>0</Ra3Chk>
<Im1Chk>1</Im1Chk>
<Im2Chk>0</Im2Chk>
<OnChipMemories>
<Ocm1>
<Type>0</Type>
<StartAddress>0x0</StartAddress>
<Size>0x0</Size>
</Ocm1>
<Ocm2>
<Type>0</Type>
<StartAddress>0x0</StartAddress>
<Size>0x0</Size>
</Ocm2>
<Ocm3>
<Type>0</Type>
<StartAddress>0x0</StartAddress>
<Size>0x0</Size>
</Ocm3>
<Ocm4>
<Type>0</Type>
<StartAddress>0x0</StartAddress>
<Size>0x0</Size>
</Ocm4>
<Ocm5>
<Type>0</Type>
<StartAddress>0x0</StartAddress>
<Size>0x0</Size>
</Ocm5>
<Ocm6>
<Type>0</Type>
<StartAddress>0x0</StartAddress>
<Size>0x0</Size>
</Ocm6>
<IRAM>
<Type>0</Type>
<StartAddress>0x20000000</StartAddress>
<Size>0x2800</Size>
</IRAM>
<IROM>
<Type>1</Type>
<StartAddress>0x8000000</StartAddress>
<Size>0x8000</Size>
</IROM>
<XRAM>
<Type>0</Type>
<StartAddress>0x0</StartAddress>
<Size>0x0</Size>
</XRAM>
<OCR_RVCT1>
<Type>1</Type>
<StartAddress>0x0</StartAddress>
<Size>0x0</Size>
</OCR_RVCT1>
<OCR_RVCT2>
<Type>1</Type>
<StartAddress>0x0</StartAddress>
<Size>0x0</Size>
</OCR_RVCT2>
<OCR_RVCT3>
<Type>1</Type>
<StartAddress>0x0</StartAddress>
<Size>0x0</Size>
</OCR_RVCT3>
<OCR_RVCT4>
<Type>1</Type>
<StartAddress>0x8000000</StartAddress>
<Size>0x8000</Size>
</OCR_RVCT4>
<OCR_RVCT5>
<Type>1</Type>
<StartAddress>0x8008000</StartAddress>
<Size>0x2000</Size>
</OCR_RVCT5>
<OCR_RVCT6>
<Type>0</Type>
<StartAddress>0x0</StartAddress>
<Size>0x0</Size>
</OCR_RVCT6>
<OCR_RVCT7>
<Type>0</Type>
<StartAddress>0x0</StartAddress>
<Size>0x0</Size>
</OCR_RVCT7>
<OCR_RVCT8>
<Type>0</Type>
<StartAddress>0x0</StartAddress>
<Size>0x0</Size>
</OCR_RVCT8>
<OCR_RVCT9>
<Type>0</Type>
<StartAddress>0x20000000</StartAddress>
<Size>0x2800</Size>
</OCR_RVCT9>
<OCR_RVCT10>
<Type>0</Type>
<StartAddress>0x0</StartAddress>
<Size>0x0</Size>
</OCR_RVCT10>
</OnChipMemories>
<RvctStartVector></RvctStartVector>
</ArmAdsMisc>
<Cads>
<interw>1</interw>
<Optim>1</Optim>
<oTime>0</oTime>
<SplitLS>0</SplitLS>
<OneElfS>1</OneElfS>
<Strict>0</Strict>
<EnumInt>0</EnumInt>
<PlainCh>0</PlainCh>
<Ropi>0</Ropi>
<Rwpi>0</Rwpi>
<wLevel>3</wLevel>
<uThumb>0</uThumb>
<uSurpInc>0</uSurpInc>
<uC99>1</uC99>
<uGnu>0</uGnu>
<useXO>0</useXO>
<v6Lang>5</v6Lang>
<v6LangP>5</v6LangP>
<vShortEn>1</vShortEn>
<vShortWch>1</vShortWch>
<v6Lto>0</v6Lto>
<v6WtE>0</v6WtE>
<v6Rtti>0</v6Rtti>
<VariousControls>
<MiscControls></MiscControls>
<Define>USE_HAL_DRIVER,STM32F103x6</Define>
<Undefine></Undefine>
<IncludePath>../Core/Inc;../Drivers/STM32F1xx_HAL_Driver/Inc;../Drivers/STM32F1xx_HAL_Driver/Inc/Legacy;../Drivers/CMSIS/Device/ST/STM32F1xx/Include;../Drivers/CMSIS/Include;../Modbus</IncludePath>
</VariousControls>
</Cads>
<Aads>
<interw>1</interw>
<Ropi>0</Ropi>
<Rwpi>0</Rwpi>
<thumb>0</thumb>
<SplitLS>0</SplitLS>
<SwStkChk>0</SwStkChk>
<NoWarn>0</NoWarn>
<uSurpInc>0</uSurpInc>
<useXO>0</useXO>
<ClangAsOpt>1</ClangAsOpt>
<VariousControls>
<MiscControls></MiscControls>
<Define></Define>
<Undefine></Undefine>
<IncludePath></IncludePath>
</VariousControls>
</Aads>
<LDads>
<umfTarg>1</umfTarg>
<Ropi>0</Ropi>
<Rwpi>0</Rwpi>
<noStLib>0</noStLib>
<RepFail>1</RepFail>
<useFile>0</useFile>
<TextAddressRange></TextAddressRange>
<DataAddressRange></DataAddressRange>
<pXoBase></pXoBase>
<ScatterFile></ScatterFile>
<IncludeLibs></IncludeLibs>
<IncludeLibsPath></IncludeLibsPath>
<Misc></Misc>
<LinkerInputFile></LinkerInputFile>
<DisabledWarnings></DisabledWarnings>
</LDads>
</TargetArmAds>
</TargetOption>
<Groups>
<Group>
<GroupName>Application/MDK-ARM</GroupName>
<Files>
<File>
<FileName>startup_stm32f103x6.s</FileName>
<FileType>2</FileType>
<FilePath>startup_stm32f103x6.s</FilePath>
</File>
</Files>
</Group>
<Group>
<GroupName>Application/User/Core</GroupName>
<Files>
<File>
<FileName>UART_TERM.c</FileName>
<FileType>1</FileType>
<FilePath>..\Core\Src\UART_TERM.c</FilePath>
</File>
<File>
<FileName>dallas_tools.c</FileName>
<FileType>1</FileType>
<FilePath>..\Core\Src\dallas_tools.c</FilePath>
</File>
<File>
<FileName>ds18b20_driver.c</FileName>
<FileType>1</FileType>
<FilePath>..\Core\Src\ds18b20_driver.c</FilePath>
</File>
<File>
<FileName>onewire.c</FileName>
<FileType>1</FileType>
<FilePath>..\Core\Src\onewire.c</FilePath>
</File>
<File>
<FileName>ow_port.c</FileName>
<FileType>1</FileType>
<FilePath>..\Core\Src\ow_port.c</FilePath>
</File>
<File>
<FileName>crc_algs.c</FileName>
<FileType>1</FileType>
<FilePath>..\Modbus\crc_algs.c</FilePath>
</File>
<File>
<FileName>modbus.c</FileName>
<FileType>1</FileType>
<FilePath>..\Modbus\modbus.c</FilePath>
</File>
<File>
<FileName>rs_message.c</FileName>
<FileType>1</FileType>
<FilePath>..\Modbus\rs_message.c</FilePath>
</File>
<File>
<FileName>main.c</FileName>
<FileType>1</FileType>
<FilePath>../Core/Src/main.c</FilePath>
</File>
<File>
<FileName>gpio.c</FileName>
<FileType>1</FileType>
<FilePath>../Core/Src/gpio.c</FilePath>
</File>
<File>
<FileName>adc.c</FileName>
<FileType>1</FileType>
<FilePath>../Core/Src/adc.c</FilePath>
<FileOption>
<CommonProperty>
<UseCPPCompiler>2</UseCPPCompiler>
<RVCTCodeConst>0</RVCTCodeConst>
<RVCTZI>0</RVCTZI>
<RVCTOtherData>0</RVCTOtherData>
<ModuleSelection>0</ModuleSelection>
<IncludeInBuild>1</IncludeInBuild>
<AlwaysBuild>2</AlwaysBuild>
<GenerateAssemblyFile>2</GenerateAssemblyFile>
<AssembleAssemblyFile>2</AssembleAssemblyFile>
<PublicsOnly>2</PublicsOnly>
<StopOnExitCode>11</StopOnExitCode>
<CustomArgument></CustomArgument>
<IncludeLibraryModules></IncludeLibraryModules>
<ComprImg>1</ComprImg>
</CommonProperty>
<FileArmAds>
<Cads>
<interw>2</interw>
<Optim>0</Optim>
<oTime>2</oTime>
<SplitLS>2</SplitLS>
<OneElfS>2</OneElfS>
<Strict>2</Strict>
<EnumInt>2</EnumInt>
<PlainCh>2</PlainCh>
<Ropi>2</Ropi>
<Rwpi>2</Rwpi>
<wLevel>0</wLevel>
<uThumb>2</uThumb>
<uSurpInc>2</uSurpInc>
<uC99>2</uC99>
<uGnu>2</uGnu>
<useXO>2</useXO>
<v6Lang>0</v6Lang>
<v6LangP>0</v6LangP>
<vShortEn>2</vShortEn>
<vShortWch>2</vShortWch>
<v6Lto>2</v6Lto>
<v6WtE>2</v6WtE>
<v6Rtti>2</v6Rtti>
<VariousControls>
<MiscControls></MiscControls>
<Define></Define>
<Undefine></Undefine>
<IncludePath></IncludePath>
</VariousControls>
</Cads>
</FileArmAds>
</FileOption>
</File>
<File>
<FileName>can.c</FileName>
<FileType>1</FileType>
<FilePath>../Core/Src/can.c</FilePath>
<FileOption>
<CommonProperty>
<UseCPPCompiler>2</UseCPPCompiler>
<RVCTCodeConst>0</RVCTCodeConst>
<RVCTZI>0</RVCTZI>
<RVCTOtherData>0</RVCTOtherData>
<ModuleSelection>0</ModuleSelection>
<IncludeInBuild>1</IncludeInBuild>
<AlwaysBuild>2</AlwaysBuild>
<GenerateAssemblyFile>2</GenerateAssemblyFile>
<AssembleAssemblyFile>2</AssembleAssemblyFile>
<PublicsOnly>2</PublicsOnly>
<StopOnExitCode>11</StopOnExitCode>
<CustomArgument></CustomArgument>
<IncludeLibraryModules></IncludeLibraryModules>
<ComprImg>1</ComprImg>
</CommonProperty>
<FileArmAds>
<Cads>
<interw>2</interw>
<Optim>0</Optim>
<oTime>2</oTime>
<SplitLS>2</SplitLS>
<OneElfS>2</OneElfS>
<Strict>2</Strict>
<EnumInt>2</EnumInt>
<PlainCh>2</PlainCh>
<Ropi>2</Ropi>
<Rwpi>2</Rwpi>
<wLevel>0</wLevel>
<uThumb>2</uThumb>
<uSurpInc>2</uSurpInc>
<uC99>2</uC99>
<uGnu>2</uGnu>
<useXO>2</useXO>
<v6Lang>0</v6Lang>
<v6LangP>0</v6LangP>
<vShortEn>2</vShortEn>
<vShortWch>2</vShortWch>
<v6Lto>2</v6Lto>
<v6WtE>2</v6WtE>
<v6Rtti>2</v6Rtti>
<VariousControls>
<MiscControls></MiscControls>
<Define></Define>
<Undefine></Undefine>
<IncludePath></IncludePath>
</VariousControls>
</Cads>
</FileArmAds>
</FileOption>
</File>
<File>
<FileName>i2c.c</FileName>
<FileType>1</FileType>
<FilePath>../Core/Src/i2c.c</FilePath>
<FileOption>
<CommonProperty>
<UseCPPCompiler>2</UseCPPCompiler>
<RVCTCodeConst>0</RVCTCodeConst>
<RVCTZI>0</RVCTZI>
<RVCTOtherData>0</RVCTOtherData>
<ModuleSelection>0</ModuleSelection>
<IncludeInBuild>1</IncludeInBuild>
<AlwaysBuild>2</AlwaysBuild>
<GenerateAssemblyFile>2</GenerateAssemblyFile>
<AssembleAssemblyFile>2</AssembleAssemblyFile>
<PublicsOnly>2</PublicsOnly>
<StopOnExitCode>11</StopOnExitCode>
<CustomArgument></CustomArgument>
<IncludeLibraryModules></IncludeLibraryModules>
<ComprImg>1</ComprImg>
</CommonProperty>
<FileArmAds>
<Cads>
<interw>2</interw>
<Optim>0</Optim>
<oTime>2</oTime>
<SplitLS>2</SplitLS>
<OneElfS>2</OneElfS>
<Strict>2</Strict>
<EnumInt>2</EnumInt>
<PlainCh>2</PlainCh>
<Ropi>2</Ropi>
<Rwpi>2</Rwpi>
<wLevel>0</wLevel>
<uThumb>2</uThumb>
<uSurpInc>2</uSurpInc>
<uC99>2</uC99>
<uGnu>2</uGnu>
<useXO>2</useXO>
<v6Lang>0</v6Lang>
<v6LangP>0</v6LangP>
<vShortEn>2</vShortEn>
<vShortWch>2</vShortWch>
<v6Lto>2</v6Lto>
<v6WtE>2</v6WtE>
<v6Rtti>2</v6Rtti>
<VariousControls>
<MiscControls></MiscControls>
<Define></Define>
<Undefine></Undefine>
<IncludePath></IncludePath>
</VariousControls>
</Cads>
</FileArmAds>
</FileOption>
</File>
<File>
<FileName>rtc.c</FileName>
<FileType>1</FileType>
<FilePath>../Core/Src/rtc.c</FilePath>
<FileOption>
<CommonProperty>
<UseCPPCompiler>2</UseCPPCompiler>
<RVCTCodeConst>0</RVCTCodeConst>
<RVCTZI>0</RVCTZI>
<RVCTOtherData>0</RVCTOtherData>
<ModuleSelection>0</ModuleSelection>
<IncludeInBuild>1</IncludeInBuild>
<AlwaysBuild>2</AlwaysBuild>
<GenerateAssemblyFile>2</GenerateAssemblyFile>
<AssembleAssemblyFile>2</AssembleAssemblyFile>
<PublicsOnly>2</PublicsOnly>
<StopOnExitCode>11</StopOnExitCode>
<CustomArgument></CustomArgument>
<IncludeLibraryModules></IncludeLibraryModules>
<ComprImg>1</ComprImg>
</CommonProperty>
<FileArmAds>
<Cads>
<interw>2</interw>
<Optim>0</Optim>
<oTime>2</oTime>
<SplitLS>2</SplitLS>
<OneElfS>2</OneElfS>
<Strict>2</Strict>
<EnumInt>2</EnumInt>
<PlainCh>2</PlainCh>
<Ropi>2</Ropi>
<Rwpi>2</Rwpi>
<wLevel>0</wLevel>
<uThumb>2</uThumb>
<uSurpInc>2</uSurpInc>
<uC99>2</uC99>
<uGnu>2</uGnu>
<useXO>2</useXO>
<v6Lang>0</v6Lang>
<v6LangP>0</v6LangP>
<vShortEn>2</vShortEn>
<vShortWch>2</vShortWch>
<v6Lto>2</v6Lto>
<v6WtE>2</v6WtE>
<v6Rtti>2</v6Rtti>
<VariousControls>
<MiscControls></MiscControls>
<Define></Define>
<Undefine></Undefine>
<IncludePath></IncludePath>
</VariousControls>
</Cads>
</FileArmAds>
</FileOption>
</File>
<File>
<FileName>spi.c</FileName>
<FileType>1</FileType>
<FilePath>../Core/Src/spi.c</FilePath>
<FileOption>
<CommonProperty>
<UseCPPCompiler>2</UseCPPCompiler>
<RVCTCodeConst>0</RVCTCodeConst>
<RVCTZI>0</RVCTZI>
<RVCTOtherData>0</RVCTOtherData>
<ModuleSelection>0</ModuleSelection>
<IncludeInBuild>1</IncludeInBuild>
<AlwaysBuild>2</AlwaysBuild>
<GenerateAssemblyFile>2</GenerateAssemblyFile>
<AssembleAssemblyFile>2</AssembleAssemblyFile>
<PublicsOnly>2</PublicsOnly>
<StopOnExitCode>11</StopOnExitCode>
<CustomArgument></CustomArgument>
<IncludeLibraryModules></IncludeLibraryModules>
<ComprImg>1</ComprImg>
</CommonProperty>
<FileArmAds>
<Cads>
<interw>2</interw>
<Optim>0</Optim>
<oTime>2</oTime>
<SplitLS>2</SplitLS>
<OneElfS>2</OneElfS>
<Strict>2</Strict>
<EnumInt>2</EnumInt>
<PlainCh>2</PlainCh>
<Ropi>2</Ropi>
<Rwpi>2</Rwpi>
<wLevel>0</wLevel>
<uThumb>2</uThumb>
<uSurpInc>2</uSurpInc>
<uC99>2</uC99>
<uGnu>2</uGnu>
<useXO>2</useXO>
<v6Lang>0</v6Lang>
<v6LangP>0</v6LangP>
<vShortEn>2</vShortEn>
<vShortWch>2</vShortWch>
<v6Lto>2</v6Lto>
<v6WtE>2</v6WtE>
<v6Rtti>2</v6Rtti>
<VariousControls>
<MiscControls></MiscControls>
<Define></Define>
<Undefine></Undefine>
<IncludePath></IncludePath>
</VariousControls>
</Cads>
</FileArmAds>
</FileOption>
</File>
<File>
<FileName>tim.c</FileName>
<FileType>1</FileType>
<FilePath>../Core/Src/tim.c</FilePath>
</File>
<File>
<FileName>usart.c</FileName>
<FileType>1</FileType>
<FilePath>../Core/Src/usart.c</FilePath>
</File>
<File>
<FileName>stm32f1xx_it.c</FileName>
<FileType>1</FileType>
<FilePath>../Core/Src/stm32f1xx_it.c</FilePath>
</File>
<File>
<FileName>stm32f1xx_hal_msp.c</FileName>
<FileType>1</FileType>
<FilePath>../Core/Src/stm32f1xx_hal_msp.c</FilePath>
</File>
<File>
<FileName>stm32f1xx_hal_timebase_tim.c</FileName>
<FileType>1</FileType>
<FilePath>../Core/Src/stm32f1xx_hal_timebase_tim.c</FilePath>
</File>
</Files>
</Group>
<Group>
<GroupName>Drivers/STM32F1xx_HAL_Driver</GroupName>
<Files>
<File>
<FileName>stm32f1xx_hal_gpio_ex.c</FileName>
<FileType>1</FileType>
<FilePath>../Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_gpio_ex.c</FilePath>
</File>
<File>
<FileName>stm32f1xx_hal_adc.c</FileName>
<FileType>1</FileType>
<FilePath>../Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_adc.c</FilePath>
<FileOption>
<CommonProperty>
<UseCPPCompiler>2</UseCPPCompiler>
<RVCTCodeConst>0</RVCTCodeConst>
<RVCTZI>0</RVCTZI>
<RVCTOtherData>0</RVCTOtherData>
<ModuleSelection>0</ModuleSelection>
<IncludeInBuild>1</IncludeInBuild>
<AlwaysBuild>2</AlwaysBuild>
<GenerateAssemblyFile>2</GenerateAssemblyFile>
<AssembleAssemblyFile>2</AssembleAssemblyFile>
<PublicsOnly>2</PublicsOnly>
<StopOnExitCode>11</StopOnExitCode>
<CustomArgument></CustomArgument>
<IncludeLibraryModules></IncludeLibraryModules>
<ComprImg>1</ComprImg>
</CommonProperty>
<FileArmAds>
<Cads>
<interw>2</interw>
<Optim>0</Optim>
<oTime>2</oTime>
<SplitLS>2</SplitLS>
<OneElfS>2</OneElfS>
<Strict>2</Strict>
<EnumInt>2</EnumInt>
<PlainCh>2</PlainCh>
<Ropi>2</Ropi>
<Rwpi>2</Rwpi>
<wLevel>0</wLevel>
<uThumb>2</uThumb>
<uSurpInc>2</uSurpInc>
<uC99>2</uC99>
<uGnu>2</uGnu>
<useXO>2</useXO>
<v6Lang>0</v6Lang>
<v6LangP>0</v6LangP>
<vShortEn>2</vShortEn>
<vShortWch>2</vShortWch>
<v6Lto>2</v6Lto>
<v6WtE>2</v6WtE>
<v6Rtti>2</v6Rtti>
<VariousControls>
<MiscControls></MiscControls>
<Define></Define>
<Undefine></Undefine>
<IncludePath></IncludePath>
</VariousControls>
</Cads>
</FileArmAds>
</FileOption>
</File>
<File>
<FileName>stm32f1xx_hal_adc_ex.c</FileName>
<FileType>1</FileType>
<FilePath>../Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_adc_ex.c</FilePath>
<FileOption>
<CommonProperty>
<UseCPPCompiler>2</UseCPPCompiler>
<RVCTCodeConst>0</RVCTCodeConst>
<RVCTZI>0</RVCTZI>
<RVCTOtherData>0</RVCTOtherData>
<ModuleSelection>0</ModuleSelection>
<IncludeInBuild>1</IncludeInBuild>
<AlwaysBuild>2</AlwaysBuild>
<GenerateAssemblyFile>2</GenerateAssemblyFile>
<AssembleAssemblyFile>2</AssembleAssemblyFile>
<PublicsOnly>2</PublicsOnly>
<StopOnExitCode>11</StopOnExitCode>
<CustomArgument></CustomArgument>
<IncludeLibraryModules></IncludeLibraryModules>
<ComprImg>1</ComprImg>
</CommonProperty>
<FileArmAds>
<Cads>
<interw>2</interw>
<Optim>0</Optim>
<oTime>2</oTime>
<SplitLS>2</SplitLS>
<OneElfS>2</OneElfS>
<Strict>2</Strict>
<EnumInt>2</EnumInt>
<PlainCh>2</PlainCh>
<Ropi>2</Ropi>
<Rwpi>2</Rwpi>
<wLevel>0</wLevel>
<uThumb>2</uThumb>
<uSurpInc>2</uSurpInc>
<uC99>2</uC99>
<uGnu>2</uGnu>
<useXO>2</useXO>
<v6Lang>0</v6Lang>
<v6LangP>0</v6LangP>
<vShortEn>2</vShortEn>
<vShortWch>2</vShortWch>
<v6Lto>2</v6Lto>
<v6WtE>2</v6WtE>
<v6Rtti>2</v6Rtti>
<VariousControls>
<MiscControls></MiscControls>
<Define></Define>
<Undefine></Undefine>
<IncludePath></IncludePath>
</VariousControls>
</Cads>
</FileArmAds>
</FileOption>
</File>
<File>
<FileName>stm32f1xx_hal.c</FileName>
<FileType>1</FileType>
<FilePath>../Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal.c</FilePath>
</File>
<File>
<FileName>stm32f1xx_hal_rcc.c</FileName>
<FileType>1</FileType>
<FilePath>../Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_rcc.c</FilePath>
</File>
<File>
<FileName>stm32f1xx_hal_rcc_ex.c</FileName>
<FileType>1</FileType>
<FilePath>../Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_rcc_ex.c</FilePath>
</File>
<File>
<FileName>stm32f1xx_hal_gpio.c</FileName>
<FileType>1</FileType>
<FilePath>../Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_gpio.c</FilePath>
</File>
<File>
<FileName>stm32f1xx_hal_dma.c</FileName>
<FileType>1</FileType>
<FilePath>../Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_dma.c</FilePath>
</File>
<File>
<FileName>stm32f1xx_hal_cortex.c</FileName>
<FileType>1</FileType>
<FilePath>../Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_cortex.c</FilePath>
</File>
<File>
<FileName>stm32f1xx_hal_pwr.c</FileName>
<FileType>1</FileType>
<FilePath>../Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_pwr.c</FilePath>
</File>
<File>
<FileName>stm32f1xx_hal_flash.c</FileName>
<FileType>1</FileType>
<FilePath>../Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_flash.c</FilePath>
</File>
<File>
<FileName>stm32f1xx_hal_flash_ex.c</FileName>
<FileType>1</FileType>
<FilePath>../Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_flash_ex.c</FilePath>
</File>
<File>
<FileName>stm32f1xx_hal_exti.c</FileName>
<FileType>1</FileType>
<FilePath>../Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_exti.c</FilePath>
</File>
<File>
<FileName>stm32f1xx_hal_can.c</FileName>
<FileType>1</FileType>
<FilePath>../Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_can.c</FilePath>
<FileOption>
<CommonProperty>
<UseCPPCompiler>2</UseCPPCompiler>
<RVCTCodeConst>0</RVCTCodeConst>
<RVCTZI>0</RVCTZI>
<RVCTOtherData>0</RVCTOtherData>
<ModuleSelection>0</ModuleSelection>
<IncludeInBuild>1</IncludeInBuild>
<AlwaysBuild>2</AlwaysBuild>
<GenerateAssemblyFile>2</GenerateAssemblyFile>
<AssembleAssemblyFile>2</AssembleAssemblyFile>
<PublicsOnly>2</PublicsOnly>
<StopOnExitCode>11</StopOnExitCode>
<CustomArgument></CustomArgument>
<IncludeLibraryModules></IncludeLibraryModules>
<ComprImg>1</ComprImg>
</CommonProperty>
<FileArmAds>
<Cads>
<interw>2</interw>
<Optim>0</Optim>
<oTime>2</oTime>
<SplitLS>2</SplitLS>
<OneElfS>2</OneElfS>
<Strict>2</Strict>
<EnumInt>2</EnumInt>
<PlainCh>2</PlainCh>
<Ropi>2</Ropi>
<Rwpi>2</Rwpi>
<wLevel>0</wLevel>
<uThumb>2</uThumb>
<uSurpInc>2</uSurpInc>
<uC99>2</uC99>
<uGnu>2</uGnu>
<useXO>2</useXO>
<v6Lang>0</v6Lang>
<v6LangP>0</v6LangP>
<vShortEn>2</vShortEn>
<vShortWch>2</vShortWch>
<v6Lto>2</v6Lto>
<v6WtE>2</v6WtE>
<v6Rtti>2</v6Rtti>
<VariousControls>
<MiscControls></MiscControls>
<Define></Define>
<Undefine></Undefine>
<IncludePath></IncludePath>
</VariousControls>
</Cads>
</FileArmAds>
</FileOption>
</File>
<File>
<FileName>stm32f1xx_hal_i2c.c</FileName>
<FileType>1</FileType>
<FilePath>../Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_i2c.c</FilePath>
<FileOption>
<CommonProperty>
<UseCPPCompiler>2</UseCPPCompiler>
<RVCTCodeConst>0</RVCTCodeConst>
<RVCTZI>0</RVCTZI>
<RVCTOtherData>0</RVCTOtherData>
<ModuleSelection>0</ModuleSelection>
<IncludeInBuild>1</IncludeInBuild>
<AlwaysBuild>2</AlwaysBuild>
<GenerateAssemblyFile>2</GenerateAssemblyFile>
<AssembleAssemblyFile>2</AssembleAssemblyFile>
<PublicsOnly>2</PublicsOnly>
<StopOnExitCode>11</StopOnExitCode>
<CustomArgument></CustomArgument>
<IncludeLibraryModules></IncludeLibraryModules>
<ComprImg>1</ComprImg>
</CommonProperty>
<FileArmAds>
<Cads>
<interw>2</interw>
<Optim>0</Optim>
<oTime>2</oTime>
<SplitLS>2</SplitLS>
<OneElfS>2</OneElfS>
<Strict>2</Strict>
<EnumInt>2</EnumInt>
<PlainCh>2</PlainCh>
<Ropi>2</Ropi>
<Rwpi>2</Rwpi>
<wLevel>0</wLevel>
<uThumb>2</uThumb>
<uSurpInc>2</uSurpInc>
<uC99>2</uC99>
<uGnu>2</uGnu>
<useXO>2</useXO>
<v6Lang>0</v6Lang>
<v6LangP>0</v6LangP>
<vShortEn>2</vShortEn>
<vShortWch>2</vShortWch>
<v6Lto>2</v6Lto>
<v6WtE>2</v6WtE>
<v6Rtti>2</v6Rtti>
<VariousControls>
<MiscControls></MiscControls>
<Define></Define>
<Undefine></Undefine>
<IncludePath></IncludePath>
</VariousControls>
</Cads>
</FileArmAds>
</FileOption>
</File>
<File>
<FileName>stm32f1xx_hal_rtc.c</FileName>
<FileType>1</FileType>
<FilePath>../Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_rtc.c</FilePath>
<FileOption>
<CommonProperty>
<UseCPPCompiler>2</UseCPPCompiler>
<RVCTCodeConst>0</RVCTCodeConst>
<RVCTZI>0</RVCTZI>
<RVCTOtherData>0</RVCTOtherData>
<ModuleSelection>0</ModuleSelection>
<IncludeInBuild>1</IncludeInBuild>
<AlwaysBuild>2</AlwaysBuild>
<GenerateAssemblyFile>2</GenerateAssemblyFile>
<AssembleAssemblyFile>2</AssembleAssemblyFile>
<PublicsOnly>2</PublicsOnly>
<StopOnExitCode>11</StopOnExitCode>
<CustomArgument></CustomArgument>
<IncludeLibraryModules></IncludeLibraryModules>
<ComprImg>1</ComprImg>
</CommonProperty>
<FileArmAds>
<Cads>
<interw>2</interw>
<Optim>0</Optim>
<oTime>2</oTime>
<SplitLS>2</SplitLS>
<OneElfS>2</OneElfS>
<Strict>2</Strict>
<EnumInt>2</EnumInt>
<PlainCh>2</PlainCh>
<Ropi>2</Ropi>
<Rwpi>2</Rwpi>
<wLevel>0</wLevel>
<uThumb>2</uThumb>
<uSurpInc>2</uSurpInc>
<uC99>2</uC99>
<uGnu>2</uGnu>
<useXO>2</useXO>
<v6Lang>0</v6Lang>
<v6LangP>0</v6LangP>
<vShortEn>2</vShortEn>
<vShortWch>2</vShortWch>
<v6Lto>2</v6Lto>
<v6WtE>2</v6WtE>
<v6Rtti>2</v6Rtti>
<VariousControls>
<MiscControls></MiscControls>
<Define></Define>
<Undefine></Undefine>
<IncludePath></IncludePath>
</VariousControls>
</Cads>
</FileArmAds>
</FileOption>
</File>
<File>
<FileName>stm32f1xx_hal_rtc_ex.c</FileName>
<FileType>1</FileType>
<FilePath>../Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_rtc_ex.c</FilePath>
<FileOption>
<CommonProperty>
<UseCPPCompiler>2</UseCPPCompiler>
<RVCTCodeConst>0</RVCTCodeConst>
<RVCTZI>0</RVCTZI>
<RVCTOtherData>0</RVCTOtherData>
<ModuleSelection>0</ModuleSelection>
<IncludeInBuild>1</IncludeInBuild>
<AlwaysBuild>2</AlwaysBuild>
<GenerateAssemblyFile>2</GenerateAssemblyFile>
<AssembleAssemblyFile>2</AssembleAssemblyFile>
<PublicsOnly>2</PublicsOnly>
<StopOnExitCode>11</StopOnExitCode>
<CustomArgument></CustomArgument>
<IncludeLibraryModules></IncludeLibraryModules>
<ComprImg>1</ComprImg>
</CommonProperty>
<FileArmAds>
<Cads>
<interw>2</interw>
<Optim>0</Optim>
<oTime>2</oTime>
<SplitLS>2</SplitLS>
<OneElfS>2</OneElfS>
<Strict>2</Strict>
<EnumInt>2</EnumInt>
<PlainCh>2</PlainCh>
<Ropi>2</Ropi>
<Rwpi>2</Rwpi>
<wLevel>0</wLevel>
<uThumb>2</uThumb>
<uSurpInc>2</uSurpInc>
<uC99>2</uC99>
<uGnu>2</uGnu>
<useXO>2</useXO>
<v6Lang>0</v6Lang>
<v6LangP>0</v6LangP>
<vShortEn>2</vShortEn>
<vShortWch>2</vShortWch>
<v6Lto>2</v6Lto>
<v6WtE>2</v6WtE>
<v6Rtti>2</v6Rtti>
<VariousControls>
<MiscControls></MiscControls>
<Define></Define>
<Undefine></Undefine>
<IncludePath></IncludePath>
</VariousControls>
</Cads>
</FileArmAds>
</FileOption>
</File>
<File>
<FileName>stm32f1xx_hal_spi.c</FileName>
<FileType>1</FileType>
<FilePath>../Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_spi.c</FilePath>
<FileOption>
<CommonProperty>
<UseCPPCompiler>2</UseCPPCompiler>
<RVCTCodeConst>0</RVCTCodeConst>
<RVCTZI>0</RVCTZI>
<RVCTOtherData>0</RVCTOtherData>
<ModuleSelection>0</ModuleSelection>
<IncludeInBuild>1</IncludeInBuild>
<AlwaysBuild>2</AlwaysBuild>
<GenerateAssemblyFile>2</GenerateAssemblyFile>
<AssembleAssemblyFile>2</AssembleAssemblyFile>
<PublicsOnly>2</PublicsOnly>
<StopOnExitCode>11</StopOnExitCode>
<CustomArgument></CustomArgument>
<IncludeLibraryModules></IncludeLibraryModules>
<ComprImg>1</ComprImg>
</CommonProperty>
<FileArmAds>
<Cads>
<interw>2</interw>
<Optim>0</Optim>
<oTime>2</oTime>
<SplitLS>2</SplitLS>
<OneElfS>2</OneElfS>
<Strict>2</Strict>
<EnumInt>2</EnumInt>
<PlainCh>2</PlainCh>
<Ropi>2</Ropi>
<Rwpi>2</Rwpi>
<wLevel>0</wLevel>
<uThumb>2</uThumb>
<uSurpInc>2</uSurpInc>
<uC99>2</uC99>
<uGnu>2</uGnu>
<useXO>2</useXO>
<v6Lang>0</v6Lang>
<v6LangP>0</v6LangP>
<vShortEn>2</vShortEn>
<vShortWch>2</vShortWch>
<v6Lto>2</v6Lto>
<v6WtE>2</v6WtE>
<v6Rtti>2</v6Rtti>
<VariousControls>
<MiscControls></MiscControls>
<Define></Define>
<Undefine></Undefine>
<IncludePath></IncludePath>
</VariousControls>
</Cads>
</FileArmAds>
</FileOption>
</File>
<File>
<FileName>stm32f1xx_hal_tim.c</FileName>
<FileType>1</FileType>
<FilePath>../Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_tim.c</FilePath>
</File>
<File>
<FileName>stm32f1xx_hal_tim_ex.c</FileName>
<FileType>1</FileType>
<FilePath>../Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_tim_ex.c</FilePath>
</File>
<File>
<FileName>stm32f1xx_hal_uart.c</FileName>
<FileType>1</FileType>
<FilePath>../Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_uart.c</FilePath>
</File>
</Files>
</Group>
<Group>
<GroupName>Drivers/CMSIS</GroupName>
<Files>
<File>
<FileName>system_stm32f1xx.c</FileName>
<FileType>1</FileType>
<FilePath>../Core/Src/system_stm32f1xx.c</FilePath>
</File>
</Files>
</Group>
<Group>
<GroupName>::CMSIS</GroupName>
</Group>
<Group>
<GroupName>::Compiler</GroupName>
</Group>
</Groups>
</Target>
</Targets>
<RTE>
<apis/>
<components>
<component Cclass="CMSIS" Cgroup="CORE" Cvendor="ARM" Cversion="5.6.0" condition="ARMv6_7_8-M Device">
<package name="CMSIS" schemaVersion="1.7.7" url="http://www.keil.com/pack/" vendor="ARM" version="5.9.0"/>
<targetInfos>
<targetInfo name="john103C6T6"/>
</targetInfos>
</component>
<component Cbundle="ARM Compiler" Cclass="Compiler" Cgroup="I/O" Csub="STDOUT" Cvariant="Breakpoint" Cvendor="Keil" Cversion="1.2.0" condition="ARMCC Cortex-M">
<package name="ARM_Compiler" schemaVersion="1.7.7" url="https://www.keil.com/pack/" vendor="Keil" version="1.7.2"/>
<targetInfos>
<targetInfo name="john103C6T6"/>
</targetInfos>
</component>
</components>
<files/>
</RTE>
<LayerInfo>
<Layers>
<Layer>
<LayName>john103C6T6</LayName>
<LayPrjMark>1</LayPrjMark>
</Layer>
</Layers>
</LayerInfo>
</Project>

View File

@@ -1,116 +0,0 @@
#include "crc_algs.h"
uint32_t CRC_calc;
uint32_t CRC_ref;
//uint16_t CRC_calc;
//uint16_t CRC_ref;
// left this global for debug
uint8_t uchCRCHi = 0xFF;
uint8_t uchCRCLo = 0xFF;
unsigned uIndex;
uint32_t crc32(uint8_t *data, uint32_t data_size)
{
static const unsigned int crc32_table[] =
{
0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419, 0x706AF48F, 0xE963A535, 0x9E6495A3,
0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988, 0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91,
0x1DB71064, 0x6AB020F2, 0xF3B97148, 0x84BE41DE, 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7,
0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC, 0x14015C4F, 0x63066CD9, 0xFA0F3D63, 0x8D080DF5,
0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172, 0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B,
0x35B5A8FA, 0x42B2986C, 0xDBBBC9D6, 0xACBCF940, 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59,
0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116, 0x21B4F4B5, 0x56B3C423, 0xCFBA9599, 0xB8BDA50F,
0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924, 0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D,
0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A, 0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433,
0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818, 0x7F6A0DBB, 0x086D3D2D, 0x91646C97, 0xE6635C01,
0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E, 0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457,
0x65B0D9C6, 0x12B7E950, 0x8BBEB8EA, 0xFCB9887C, 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65,
0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2, 0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB,
0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0, 0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9,
0x5005713C, 0x270241AA, 0xBE0B1010, 0xC90C2086, 0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F,
0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, 0x59B33D17, 0x2EB40D81, 0xB7BD5C3B, 0xC0BA6CAD,
0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A, 0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683,
0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8, 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1,
0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE, 0xF762575D, 0x806567CB, 0x196C3671, 0x6E6B06E7,
0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC, 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5,
0xD6D6A3E8, 0xA1D1937E, 0x38D8C2C4, 0x4FDFF252, 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B,
0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60, 0xDF60EFC3, 0xA867DF55, 0x316E8EEF, 0x4669BE79,
0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236, 0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F,
0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04, 0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D,
0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A, 0x9C0906A9, 0xEB0E363F, 0x72076785, 0x05005713,
0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38, 0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21,
0x86D3D2D4, 0xF1D4E242, 0x68DDB3F8, 0x1FDA836E, 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777,
0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C, 0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45,
0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2, 0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB,
0xAED16A4A, 0xD9D65ADC, 0x40DF0B66, 0x37D83BF0, 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9,
0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6, 0xBAD03605, 0xCDD70693, 0x54DE5729, 0x23D967BF,
0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94, 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D
};
unsigned int crc = 0xFFFFFFFF;
while (data_size--)
{
crc = (crc >> 8) ^ crc32_table[(crc ^ *data) & 255];
data++;
}
return crc^0xFFFFFFFF;
}
uint16_t crc16(uint8_t *data, uint32_t data_size)
{
/*Table of CRC values for high order byte*/
static unsigned char auchCRCHi[]=
{
0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,0x01,0xC0,0x80,0x41,0x00,0xC1,0x81,0x40,
0x01,0xC0,0x80,0x41,0x00,0xC1,0x81,0x40,0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,
0x01,0xC0,0x80,0x41,0x00,0xC1,0x81,0x40,0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,
0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,0x01,0xC0,0x80,0x41,0x00,0xC1,0x81,0x40,
0x01,0xC0,0x80,0x41,0x00,0xC1,0x81,0x40,0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,
0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,0x01,0xC0,0x80,0x41,0x00,0xC1,0x81,0x40,
0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,0x01,0xC0,0x80,0x41,0x00,0xC1,0x81,0x40,
0x01,0xC0,0x80,0x41,0x00,0xC1,0x81,0x40,0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,
0x01,0xC0,0x80,0x41,0x00,0xC1,0x81,0x40,0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,
0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,0x01,0xC0,0x80,0x41,0x00,0xC1,0x81,0x40,
0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,0x01,0xC0,0x80,0x41,0x00,0xC1,0x81,0x40,
0x01,0xC0,0x80,0x41,0x00,0xC1,0x81,0x40,0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,
0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,0x01,0xC0,0x80,0x41,0x00,0xC1,0x81,0x40,
0x01,0xC0,0x80,0x41,0x00,0xC1,0x81,0x40,0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,
0x01,0xC0,0x80,0x41,0x00,0xC1,0x81,0x40,0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,
0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,0x01,0xC0,0x80,0x41,0x00,0xC1,0x81,0x40,
};
/*Table of CRC values for low order byte*/
static char auchCRCLo[] =
{
0x00,0xC0,0xC1,0x01,0xC3,0x03,0x02,0xC2,0xC6,0x06,0x07,0xC7,0x05,0xC5,0xC4,0x04,
0xCC,0x0C,0x0D,0xCD,0x0F,0xCF,0xCE,0x0E,0x0A,0xCA,0xCB,0x0B,0xC9,0x09,0x08,0xC8,
0xD8,0x18,0x19,0xD9,0x1B,0xDB,0xDA,0x1A,0x1E,0xDE,0xDF,0x1F,0xDD,0x1D,0x1C,0xDC,
0x14,0xD4,0xD5,0x15,0xD7,0x17,0x16,0xD6,0xD2,0x12,0x13,0xD3,0x11,0xD1,0xD0,0x10,
0xF0,0x30,0x31,0xF1,0x33,0xF3,0xF2,0x32,0x36,0xF6,0xF7,0x37,0xF5,0x35,0x34,0xF4,
0x3C,0xFC,0xFD,0x3D,0xFF,0x3F,0x3E,0xFE,0xFA,0x3A,0x3B,0xFB,0x39,0xF9,0xF8,0x38,
0x28,0xE8,0xE9,0x29,0xEB,0x2B,0x2A,0xEA,0xEE,0x2E,0x2F,0xEF,0x2D,0xED,0xEC,0x2C,
0xE4,0x24,0x25,0xE5,0x27,0xE7,0xE6,0x26,0x22,0xE2,0xE3,0x23,0xE1,0x21,0x20,0xE0,
0xA0,0x60,0x61,0xA1,0x63,0xA3,0xA2,0x62,0x66,0xA6,0xA7,0x67,0xA5,0x65,0x64,0xA4,
0x6C,0xAC,0xAD,0x6D,0xAF,0x6F,0x6E,0xAE,0xAA,0x6A,0x6B,0xAB,0x69,0xA9,0xA8,0x68,
0x78,0xB8,0xB9,0x79,0xBB,0x7B,0x7A,0xBA,0xBE,0x7E,0x7F,0xBF,0x7D,0xBD,0xBC,0x7C,
0xB4,0x74,0x75,0xB5,0x77,0xB7,0xB6,0x76,0x72,0xB2,0xB3,0x73,0xB1,0x71,0x70,0xB0,
0x50,0x90,0x91,0x51,0x93,0x53,0x52,0x92,0x96,0x56,0x57,0x97,0x55,0x95,0x94,0x54,
0x9C,0x5C,0x5D,0x9D,0x5F,0x9F,0x9E,0x5E,0x5A,0x9A,0x9B,0x5B,0x99,0x59,0x58,0x98,
0x88,0x48,0x49,0x89,0x4B,0x8B,0x8A,0x4A,0x4E,0x8E,0x8F,0x4F,0x8D,0x4D,0x4C,0x8C,
0x44,0x84,0x85,0x45,0x87,0x47,0x46,0x86,0x82,0x42,0x43,0x83,0x41,0x81,0x80,0x40,
};
uchCRCHi = 0xFF;
uchCRCLo = 0xFF;
/* CRC Generation Function */
while( data_size--) /* pass through message buffer */
{
uIndex = uchCRCHi ^ *data++; /* calculate the CRC */
uchCRCHi = uchCRCLo ^ auchCRCHi[uIndex];
uchCRCLo = auchCRCLo[uIndex];
}
return uchCRCHi | uchCRCLo<<8;
}

View File

@@ -1,962 +0,0 @@
/**
**************************************************************************
* @file modbus.c
* @brief Модуль для реализации MODBUS.
**************************************************************************
* @details Файл содержит реализацию функций работы с Modbus, включая:
* - доступ к coils и registers;
* - обработку команд протокола;
* - взаимодействие с RS (UART);
* - инициализацию.
*
* @section Функции и макросы
*
* ### Доступ к coils:
* - MB_Set_Coil_Local() — Установить coil по локальному адресу.
* - MB_Reset_Coil_Local() — Сбросить coil по локальному адресу.
* - MB_Toogle_Coil_Local() — Инвертировать coil по локальному адресу.
* - MB_Read_Coil_Local() — Прочитать coil по локальному адресу.
* - MB_Write_Coil_Global() — Установить/сбросить coil по глобальному адресу.
* - MB_Read_Coil_Global() — Прочитать coil по глобальному адресу.
*
* ### Обработка команд Modbus:
* - MB_DefineRegistersAddress() — Определить начальный адрес регистра.
* - MB_DefineCoilsAddress() — Определить начальный адрес coils.
* - MB_Check_Address_For_Arr() — Проверить, принадлежит ли адрес массиву.
* - Основные команды Modbus:
* - MB_Read_Coils()
* - MB_Read_Hold_Regs()
* - MB_Write_Single_Coil()
* - MB_Write_Miltuple_Coils()
* - MB_Write_Miltuple_Regs()
*
* ### Функции для работы с RS (UART):
* - RS_Parse_Message() / RS_Collect_Message() — Парсинг и сборка сообщения.
* - RS_Response() — Отправка ответа.
* - RS_Define_Size_of_RX_Message() — Определение размера принимаемого сообщения.
* - RS_Init() — Инициализация UART.
*
* ### Инициализация:
* - MODBUS_FirstInit() — Инициализация модуля Modbus.
*
* @section Структура данных Modbus
*
* #### Holding/Input Registers:
* - Регистры — 16-битные слова. Доступ к регистрам осуществляется через указатель.
* Таким образом, сами регистры могут представлять собой как массив так и структуру.
*
* #### Coils:
* - Coils — это биты, упакованные в 16-битные слова. Доступ к коилам осуществляется через указатель.
* Таким образом, сами коилы могут представлять собой как массив так и структуру.
*
* @section Инструкция по подключению
* Для корректной работы надо подключить обработчики RS_UART_Handler(), RS_TIM_Handler(),
* в соответствубщие низкоуровневые прерывания UART_IRQHandler, TIM_IRQHandler. После HAL'овского обработчика
*
* Также необходимо в modbus_config.h настроить дефайны для нужной работы UART
* После для запуска Modbus:
* @verbatim
//----------------Прием модбас----------------//
#include "rs_message.h"
MODBUS_FirstInit();
RS_Receive_IT(&hmodbus1, &MODBUS_MSG);
* @endverbatim
*
******************************************************************************/
#include "rs_message.h"
uint32_t dbg_temp, dbg_temp2, dbg_temp3; // for debug
/* MODBUS HANDLES */
extern UART_HandleTypeDef rs_huart;
extern TIM_HandleTypeDef rs_htim;
RS_HandleTypeDef hmodbus1;
/* DEFINE REGISTERS/COILS */
MB_DeviceIdentificationTypeDef MB_INFO;
MB_DataStructureTypeDef MB_DATA;
RS_MsgTypeDef MODBUS_MSG;
//-------------------------------------------------------------------
//-----------------------------FOR USER------------------------------
/**
* @brief First set up of MODBUS.
* @details Первый инит модбас. Заполняет структуры и инициализирует таймер и юарт для общения по модбас.
* @note This called from main
*/
void MODBUS_FirstInit(void)
{
MB_DevoceInentificationInit();
//-----------SETUP MODBUS-------------
// set up modbus: MB_RX_Size_NotConst and Timeout enable
hmodbus1.ID = MODBUS_DEVICE_ID;
hmodbus1.sRS_Timeout = MODBUS_TIMEOUT;
hmodbus1.sRS_Mode = SLAVE_ALWAYS_WAIT;
hmodbus1.sRS_RX_Size_Mode = RS_RX_Size_NotConst;
// INIT
hmodbus1.RS_STATUS = RS_Init(&hmodbus1, &rs_huart, &rs_htim, 0);
RS_EnableReceive();
}
/**
* @brief Set or Reset Coil at its global address.
* @param Addr - адрес коила.
* @param WriteVal - Что записать в коил: 0 или 1.
* @return ExceptionCode - Код исключения если коила по адресу не существует, и NO_ERRORS если все ок.
*
* @details Позволяет обратиться к любому коилу по его глобальному адрессу.
Вне зависимости от того как коилы размещены в памяти.
*/
MB_ExceptionTypeDef MB_Write_Coil_Global(uint16_t Addr, MB_CoilsOpTypeDef WriteVal)
{
//---------CHECK FOR ERRORS----------
MB_ExceptionTypeDef Exception = NO_ERRORS;
uint16_t *coils;
uint16_t start_shift = 0; // shift in coils register
//------------WRITE COIL-------------
Exception = MB_DefineCoilsAddress(&coils, Addr, 1, &start_shift, 1);
if(Exception == NO_ERRORS)
{
switch(WriteVal)
{
case SET_COIL:
*coils |= (1<<start_shift);
break;
case RESET_COIL:
*coils &= ~(1<<start_shift);
break;
case TOOGLE_COIL:
*coils ^= (1<<start_shift);
break;
}
}
return Exception;
}
/**
* @brief Read Coil at its global address.
* @param Addr - адрес коила.
* @param Exception - Указатель на переменную для кода исключения, в случа неудачи при чтении.
* @return uint16_t - Возвращает весь регистр с маской на запрошенном коиле.
*
* @details Позволяет обратиться к любому коилу по его глобальному адрессу.
Вне зависимости от того как коилы размещены в памяти.
*/
uint16_t MB_Read_Coil_Global(uint16_t Addr, MB_ExceptionTypeDef *Exception)
{
//---------CHECK FOR ERRORS----------
MB_ExceptionTypeDef Exception_tmp;
if(Exception == NULL) // if exception is not given to func fill it
Exception = &Exception_tmp;
uint16_t *coils;
uint16_t start_shift = 0; // shift in coils register
//------------READ COIL--------------
*Exception = MB_DefineCoilsAddress(&coils, Addr, 1, &start_shift, 0);
if(*Exception == NO_ERRORS)
{
return ((*coils)&(1<<start_shift));
}
else
{
return 0;
}
}
//-------------------------------------------------------------------
//----------------FUNCTIONS FOR PROCESSING MESSAGE-------------------
/**
* @brief Check is address valid for certain array.
* @param Addr - начальный адресс.
* @param Qnt - количество запрашиваемых элементов.
* @param R_ARR_ADDR - начальный адресс массива R_ARR.
* @param R_ARR_NUMB - количество элементов в массиве R_ARR.
* @return ExceptionCode - ILLEGAL DATA ADRESS если адресс недействителен, и NO_ERRORS если все ок.
*
* @details Позволяет определить, принадлежит ли адресс Addr массиву R_ARR:
* Если адресс Addr находится в диапазоне адрессов массива R_ARR, то возвращаем NO_ERROR.
* Если адресс Addr находится за пределами адрессов массива R_ARR - ILLEGAL_DATA_ADDRESSю.
*/
MB_ExceptionTypeDef MB_Check_Address_For_Arr(uint16_t Addr, uint16_t Qnt, uint16_t R_ARR_ADDR, uint16_t R_ARR_NUMB)
{
// if address from this array
if(Addr >= R_ARR_ADDR)
{
// if quantity too big return error
if ((Addr - R_ARR_ADDR) + Qnt > R_ARR_NUMB)
{
return ILLEGAL_DATA_ADDRESS; // return exception code
}
// if all ok - return no errors
return NO_ERRORS;
}
// if address isnt from this array return error
else
return ILLEGAL_DATA_ADDRESS; // return exception code
}
/**
* @brief Define Address Origin for Input/Holding Registers
* @param pRegs - указатель на указатель регистров.
* @param Addr - адрес начального регистра.
* @param Qnt - количество запрашиваемых регистров.
* @param WriteFlag - флаг регистр нужны для чтения или записи.
* @return ExceptionCode - Код исключения если есть, и NO_ERRORS если нет.
*
* @details Определение адреса начального регистра.
* @note WriteFlag пока не используется.
*/
MB_ExceptionTypeDef MB_DefineRegistersAddress(uint16_t **pRegs, uint16_t Addr, uint16_t Qnt, uint8_t RegisterType)
{
/* check quantity error */
if (Qnt > 125)
{
return ILLEGAL_DATA_VALUE; // return exception code
}
if(RegisterType == RegisterType_Holding)
{
// Default holding registers
if(MB_Check_Address_For_Arr(Addr, Qnt, R_HOLDING_ADDR, R_HOLDING_QNT) == NO_ERRORS)
{
*pRegs = MB_Set_Register_Ptr(&MB_DATA.HoldRegs, Addr); // указатель на выбранный по Addr регистр
}
// if address doesnt match any array - return illegal data address response
else
{
return ILLEGAL_DATA_ADDRESS;
}
}
else if(RegisterType == RegisterType_Input)
{
// Default input registers
if(MB_Check_Address_For_Arr(Addr, Qnt, R_INPUT_ADDR, R_INPUT_QNT) == NO_ERRORS)
{
*pRegs = MB_Set_Register_Ptr(&MB_DATA.InRegs, Addr); // указатель на выбранный по Addr регистр
}
// if address doesnt match any array - return illegal data address response
else
{
return ILLEGAL_DATA_ADDRESS;
}
}
else
{
return ILLEGAL_FUNCTION;
}
// if found requeried array return no err
return NO_ERRORS; // return no errors
}
/**
* @brief Define Address Origin for coils
* @param pCoils - указатель на указатель коилов.
* @param Addr - адресс начального коила.
* @param Qnt - количество запрашиваемых коилов.
* @param start_shift - указатель на переменную содержащую сдвиг внутри регистра для начального коила.
* @param WriteFlag - флаг коилы нужны для чтения или записи.
* @return ExceptionCode - Код исключения если есть, и NO_ERRORS если нет.
*
* @details Определение адреса начального регистра запрашиваемых коилов.
* @note WriteFlag используется для определния регистров GPIO: ODR или IDR.
*/
MB_ExceptionTypeDef MB_DefineCoilsAddress(uint16_t **pCoils, uint16_t Addr, uint16_t Qnt, uint16_t *start_shift, uint8_t WriteFlag)
{
/* check quantity error */
if (Qnt > 2000)
{
return ILLEGAL_DATA_VALUE; // return exception code
}
// Default coils
if(MB_Check_Address_For_Arr(Addr, Qnt, C_CONTROL_ADDR, C_CONTROL_QNT) == NO_ERRORS)
{
*pCoils = MB_Set_Coil_Reg_Ptr(&MB_DATA.Coils, Addr); // указатель на выбранный по Addr массив коилов
}
// if address doesnt match any array - return illegal data address response
else
{
return ILLEGAL_DATA_ADDRESS;
}
*start_shift = Addr % 16; // set shift to requested coil
// if found requeried array return no err
return NO_ERRORS; // return no errors
}
/**
* @brief Proccess command Read Coils (01 - 0x01).
* @param modbus_msg - указатель на структуру собщения modbus.
* @return fMessageHandled - статус о результате обработки комманды.
* @details Обработка команды Read Coils.
*/
uint8_t MB_Read_Coils(RS_MsgTypeDef *modbus_msg)
{
//---------CHECK FOR ERRORS----------
uint16_t *coils;
uint16_t start_shift = 0; // shift in coils register
modbus_msg->Except_Code = MB_DefineCoilsAddress(&coils, modbus_msg->Addr, modbus_msg->Qnt, &start_shift, 0);
if(modbus_msg->Except_Code != NO_ERRORS)
return 0;
//-----------READING COIL------------
// setup output message data size
modbus_msg->ByteCnt = Divide_Up(modbus_msg->Qnt, 8);
// create mask for coils
uint16_t mask_for_coils = 0; // mask for coils that've been chosen
uint16_t setted_coils = 0; // value of setted coils
uint16_t temp_reg = 0; // temp register for saving coils that hasnt been chosen
uint16_t coil_cnt = 0; // counter for processed coils
// cycle until all registers with requered coils would be processed
int shift = start_shift; // set shift to first coil in first register
int ind = 0; // index for coils registers and data
for(; ind <= Divide_Up(start_shift + modbus_msg->Qnt, 16); ind++)
{
//----SET MASK FOR COILS REGISTER----
mask_for_coils = 0;
for(; shift < 0x10; shift++)
{
mask_for_coils |= 1<<(shift); // choose certain coil
if(++coil_cnt >= modbus_msg->Qnt)
break;
}
shift = 0; // set shift to zero for the next step
//-----------READ COILS--------------
modbus_msg->DATA[ind] = (*(coils+ind)&mask_for_coils) >> start_shift;
if(ind > 0)
modbus_msg->DATA[ind-1] |= ((*(coils+ind)&mask_for_coils) << 16) >> start_shift;
}
// т.к. DATA 16-битная, для 8-битной передачи, надо поменять местами верхний и нижний байты
for(; ind >= 0; --ind)
modbus_msg->DATA[ind] = ByteSwap16(modbus_msg->DATA[ind]);
return 1;
}
/**
* @brief Proccess command Read Holding Registers (03 - 0x03).
* @param modbus_msg - указатель на структуру собщения modbus.
* @return fMessageHandled - статус о результате обработки комманды.
* @details Обработка команды Read Holding Registers.
*/
uint8_t MB_Read_Hold_Regs(RS_MsgTypeDef *modbus_msg)
{
//---------CHECK FOR ERRORS----------
// get origin address for data
uint16_t *pHoldRegs;
modbus_msg->Except_Code = MB_DefineRegistersAddress(&pHoldRegs, modbus_msg->Addr, modbus_msg->Qnt, RegisterType_Holding); // определение адреса регистров
if(modbus_msg->Except_Code != NO_ERRORS)
return 0;
//-----------READING REGS------------
// setup output message data size
modbus_msg->ByteCnt = modbus_msg->Qnt*2; // *2 because we transmit 8 bits, not 16 bits
// read data
int i;
for (i = 0; i<modbus_msg->Qnt; i++)
{
modbus_msg->DATA[i] = *(pHoldRegs++);
}
return 1;
}
/**
* @brief Proccess command Read Input Registers (04 - 0x04).
* @param modbus_msg - указатель на структуру собщения modbus.
* @return fMessageHandled - статус о результате обработки комманды.
* @details Обработка команды Read Input Registers.
*/
uint8_t MB_Read_Input_Regs(RS_MsgTypeDef *modbus_msg)
{
//---------CHECK FOR ERRORS----------
// get origin address for data
uint16_t *pInRegs;
modbus_msg->Except_Code = MB_DefineRegistersAddress(&pInRegs, modbus_msg->Addr, modbus_msg->Qnt, RegisterType_Input); // определение адреса регистров
if(modbus_msg->Except_Code != NO_ERRORS)
return 0;
//-----------READING REGS------------
// setup output message data size
modbus_msg->ByteCnt = modbus_msg->Qnt*2; // *2 because we transmit 8 bits, not 16 bits
// read data
int i;
for (i = 0; i<modbus_msg->Qnt; i++)
{
if(*((int16_t *)pInRegs) > 0)
modbus_msg->DATA[i] = (*pInRegs++);
else
modbus_msg->DATA[i] = (*pInRegs++);
}
return 1;
}
/**
* @brief Proccess command Write Single Coils (05 - 0x05).
* @param modbus_msg - указатель на структуру собщения modbus.
* @return fMessageHandled - статус о результате обработки комманды.
* @details Обработка команды Write Single Coils.
*/
uint8_t MB_Write_Single_Coil(RS_MsgTypeDef *modbus_msg)
{
//---------CHECK FOR ERRORS----------
if ((modbus_msg->Qnt != 0x0000) && (modbus_msg->Qnt != 0xFF00))
{
modbus_msg->Except_Code = ILLEGAL_DATA_VALUE;
return 0;
}
// define position of coil
uint16_t *coils;
uint16_t start_shift = 0; // shift in coils register
modbus_msg->Except_Code = MB_DefineCoilsAddress(&coils, modbus_msg->Addr, 0, &start_shift, 1);
if(modbus_msg->Except_Code != NO_ERRORS)
return 0;
//----------WRITTING COIL------------
if(modbus_msg->Qnt == 0xFF00)
*(coils) |= 1<<start_shift; // write flags corresponding to received data
else
*(coils) &= ~(1<<start_shift); // write flags corresponding to received data
return 1;
}
/**
* @brief Proccess command Write Single Register (06 - 0x06).
* @param modbus_msg - указатель на структуру собщения modbus.
* @return fMessageHandled - статус о результате обработки комманды.
* @details Обработка команды Write Single Register.
*/
uint8_t MB_Write_Single_Reg(RS_MsgTypeDef *modbus_msg)
{
// get origin address for data
uint16_t *pHoldRegs;
modbus_msg->Except_Code = MB_DefineRegistersAddress(&pHoldRegs, modbus_msg->Addr, 1, RegisterType_Holding); // определение адреса регистров
if(modbus_msg->Except_Code != NO_ERRORS)
return 0;
//-----------WRITTING REG------------
*(pHoldRegs) = modbus_msg->Qnt;
return 1;
}
/**
* @brief Proccess command Write Multiple Coils (15 - 0x0F).
* @param modbus_msg - указатель на структуру собщения modbus.
* @return fMessageHandled - статус о результате обработки комманды.
* @details Обработка команды Write Multiple Coils.
*/
uint8_t MB_Write_Miltuple_Coils(RS_MsgTypeDef *modbus_msg)
{
//---------CHECK FOR ERRORS----------
if (modbus_msg->ByteCnt != Divide_Up(modbus_msg->Qnt, 8))
{ // if quantity too large OR if quantity and bytes count arent match
modbus_msg->Except_Code = ILLEGAL_DATA_VALUE;
return 0;
}
// define position of coil
uint16_t *coils; // pointer to coils
uint16_t start_shift = 0; // shift in coils register
modbus_msg->Except_Code = MB_DefineCoilsAddress(&coils, modbus_msg->Addr, modbus_msg->Qnt, &start_shift, 1);
if(modbus_msg->Except_Code != NO_ERRORS)
return 0;
//----------WRITTING COILS-----------
// create mask for coils
uint16_t mask_for_coils = 0; // mask for coils that've been chosen
uint32_t setted_coils = 0; // value of setted coils
uint16_t temp_reg = 0; // temp register for saving coils that hasnt been chosen
uint16_t coil_cnt = 0; // counter for processed coils
// cycle until all registers with requered coils would be processed
int shift = start_shift; // set shift to first coil in first register
for(int ind = 0; ind <= Divide_Up(start_shift + modbus_msg->Qnt, 16); ind++)
{
//----SET MASK FOR COILS REGISTER----
mask_for_coils = 0;
for(; shift < 0x10; shift++)
{
mask_for_coils |= 1<<(shift); // choose certain coil
if(++coil_cnt >= modbus_msg->Qnt)
break;
}
shift = 0; // set shift to zero for the next step
//-----------WRITE COILS-------------
// get current coils
temp_reg = *(coils+ind);
// set coils
setted_coils = ByteSwap16(modbus_msg->DATA[ind]) << start_shift;
if(ind > 0)
{
setted_coils |= ((ByteSwap16(modbus_msg->DATA[ind-1]) << start_shift) >> 16);
}
// write coils
*(coils+ind) = setted_coils & mask_for_coils;
// restore untouched coils
*(coils+ind) |= temp_reg&(~mask_for_coils);
if(coil_cnt >= modbus_msg->Qnt) // if all coils written - break cycle
break; // *kind of unnecessary
}
return 1;
}
/**
* @brief Proccess command Write Multiple Registers (16 - 0x10).
* @param modbus_msg - указатель на структуру собщения modbus.
* @return fMessageHandled - статус о результате обработки комманды.
* @details Обработка команды Write Multiple Registers.
*/
uint8_t MB_Write_Miltuple_Regs(RS_MsgTypeDef *modbus_msg)
{
//---------CHECK FOR ERRORS----------
if (modbus_msg->Qnt*2 != modbus_msg->ByteCnt)
{ // if quantity and bytes count arent match
modbus_msg->Except_Code = 3;
return 0;
}
// get origin address for data
uint16_t *pHoldRegs;
modbus_msg->Except_Code = MB_DefineRegistersAddress(&pHoldRegs, modbus_msg->Addr, modbus_msg->Qnt, RegisterType_Holding); // определение адреса регистров
if(modbus_msg->Except_Code != NO_ERRORS)
return 0;
//-----------WRITTING REGS-----------
for (int i = 0; i<modbus_msg->Qnt; i++)
{
*(pHoldRegs++) = modbus_msg->DATA[i];
}
return 1;
}
void MB_WriteObjectToMessage(char *mbdata, unsigned *ind, MB_DeviceObjectTypeDef *obj)
{
mbdata[(*ind)++] = obj->length;
for (int i = 0; i < obj->length; i++)
{
mbdata[(*ind)++] = obj->name[i];
}
}
/**
* @brief Proccess command Read Device Identification (43/14 - 0x2B/0E).
* @param modbus_msg - указатель на структуру собщения modbus.
* @return fMessageHandled - статус о результате обработки комманды.
* @details Обработка команды Write Single Register.
*/
uint8_t MB_Read_Device_Identification(RS_MsgTypeDef *modbus_msg)
{
char *mbdata = (char *)modbus_msg->DATA;
unsigned ind = 0;
switch(modbus_msg->DevId.ReadDevId)
{
case MB_BASIC_IDENTIFICATION:
mbdata[ind++] = 0x00;
MB_WriteObjectToMessage(mbdata, &ind, &MB_INFO.VendorName);
mbdata[ind++] = 0x01;
MB_WriteObjectToMessage(mbdata, &ind, &MB_INFO.ProductCode);
mbdata[ind++] = 0x02;
MB_WriteObjectToMessage(mbdata, &ind, &MB_INFO.Revision);
modbus_msg->DevId.NumbOfObj = 3;
break;
case MB_REGULAR_IDENTIFICATION:
mbdata[ind++] = 0x03;
MB_WriteObjectToMessage(mbdata, &ind, &MB_INFO.VendorUrl);
mbdata[ind++] = 0x04;
MB_WriteObjectToMessage(mbdata, &ind, &MB_INFO.ProductName);
mbdata[ind++] = 0x05;
MB_WriteObjectToMessage(mbdata, &ind, &MB_INFO.ModelName);
mbdata[ind++] = 0x06;
MB_WriteObjectToMessage(mbdata, &ind, &MB_INFO.UserApplicationName);
modbus_msg->DevId.NumbOfObj = 4;
break;
default:
return 0;
}
modbus_msg->ByteCnt = ind;
return 1;
}
/**
* @brief Respond accord to received message.
* @param hRS - указатель на хендлер RS.
* @param RS_msg - указатель на структуру сообщения.
* @return RS_RES - статус о результате ответа на комманду.
* @details Обработка принятой комманды и ответ на неё.
*/
RS_StatusTypeDef RS_Response(RS_HandleTypeDef *hmodbus, RS_MsgTypeDef *modbus_msg)
{
RS_StatusTypeDef MB_RES = 0;
hmodbus->f.MessageHandled = 0;
hmodbus->f.EchoResponse = 0;
RS_Reset_TX_Flags(hmodbus); // reset flag for correct transmit
if(modbus_msg->Func_Code < ERR_VALUES_START)// if no errors after parsing
{
switch (modbus_msg->Func_Code)
{
// Read Coils
case MB_R_COILS:
hmodbus->f.MessageHandled = MB_Read_Coils(hmodbus->pMessagePtr);
break;
// Read Hodling Registers
case MB_R_HOLD_REGS:
hmodbus->f.MessageHandled = MB_Read_Hold_Regs(hmodbus->pMessagePtr);
break;
case MB_R_IN_REGS:
hmodbus->f.MessageHandled = MB_Read_Input_Regs(hmodbus->pMessagePtr);
break;
// Write Single Coils
case MB_W_COIL:
hmodbus->f.MessageHandled = MB_Write_Single_Coil(hmodbus->pMessagePtr);
if(hmodbus->f.MessageHandled)
{
hmodbus->f.EchoResponse = 1;
hmodbus->RS_Message_Size -= 2; // echo response if write ok (minus 2 cause of two CRC bytes)
}
break;
case MB_W_HOLD_REG:
hmodbus->f.MessageHandled = MB_Write_Single_Reg(hmodbus->pMessagePtr);
if(hmodbus->f.MessageHandled)
{
hmodbus->f.EchoResponse = 1;
hmodbus->RS_Message_Size -= 2; // echo response if write ok (minus 2 cause of two CRC bytes)
}
break;
// Write Multiple Coils
case MB_W_COILS:
hmodbus->f.MessageHandled = MB_Write_Miltuple_Coils(hmodbus->pMessagePtr);
if(hmodbus->f.MessageHandled)
{
hmodbus->f.EchoResponse = 1;
hmodbus->RS_Message_Size = 6; // echo response if write ok (withous data bytes)
}
break;
// Write Multiple Registers
case MB_W_HOLD_REGS:
hmodbus->f.MessageHandled = MB_Write_Miltuple_Regs(hmodbus->pMessagePtr);
if(hmodbus->f.MessageHandled)
{
hmodbus->f.EchoResponse = 1;
hmodbus->RS_Message_Size = 6; // echo response if write ok (withous data bytes)
}
break;
case MB_R_DEVICE_INFO:
hmodbus->f.MessageHandled = MB_Read_Device_Identification(hmodbus->pMessagePtr);
break;
/* unknown func code */
default: modbus_msg->Except_Code = 0x01; /* set exception code: illegal function */
}
if(hmodbus->f.MessageHandled == 0)
{
modbus_msg->Func_Code += ERR_VALUES_START;
}
else
{
}
}
// if we need response - check that transmit isnt busy
if( RS_Is_TX_Busy(hmodbus) )
RS_Abort(hmodbus, ABORT_TX); // if tx busy - set it free
// Transmit right there, or sets (fDeferredResponse) to transmit response in main code
MB_RES = RS_Handle_Transmit_Start(hmodbus, modbus_msg);
hmodbus->RS_STATUS = MB_RES;
return MB_RES;
}
/**
* @brief Collect message in buffer to transmit it.
* @param hRS - указатель на хендлер RS.
* @param RS_msg - указатель на структуру сообщения.
* @param msg_uart_buff - указатель на буффер UART.
* @return RS_RES - статус о результате заполнения буфера.
* @details Заполнение буффера UART из структуры сообщения.
*/
RS_StatusTypeDef RS_Collect_Message(RS_HandleTypeDef *hmodbus, RS_MsgTypeDef *modbus_msg, uint8_t *modbus_uart_buff)
{
int ind = 0; // ind for modbus-uart buffer
if(hmodbus->f.EchoResponse && hmodbus->f.MessageHandled) // if echo response need
ind = hmodbus->RS_Message_Size;
else
{
//------INFO ABOUT DATA/MESSAGE------
//-----------[first bytes]-----------
// set ID of message/user
modbus_uart_buff[ind++] = modbus_msg->MbAddr;
// set dat or err response
modbus_uart_buff[ind++] = modbus_msg->Func_Code;
if (modbus_msg->Func_Code < ERR_VALUES_START) // if no error occur
{
// fill modbus header
if(modbus_msg->Func_Code == MB_R_DEVICE_INFO) // devide identification header
{
modbus_uart_buff[ind++] = modbus_msg->DevId.MEI_Type;
modbus_uart_buff[ind++] = modbus_msg->DevId.ReadDevId;
modbus_uart_buff[ind++] = modbus_msg->DevId.Conformity;
modbus_uart_buff[ind++] = modbus_msg->DevId.MoreFollows;
modbus_uart_buff[ind++] = modbus_msg->DevId.NextObjId;
modbus_uart_buff[ind++] = modbus_msg->DevId.NumbOfObj;
if (modbus_msg->ByteCnt > DATA_SIZE*2) // if ByteCnt less than DATA_SIZE
{
return RS_COLLECT_MSG_ERR;
}
//---------------DATA----------------
//-----------[data bytes]------------
uint8_t *tmp_data_addr = (uint8_t *)modbus_msg->DATA;
for(int i = 0; i < modbus_msg->ByteCnt; i++) // filling buffer with data
{ // set data
modbus_uart_buff[ind++] = *tmp_data_addr;
tmp_data_addr++;
}
}
else // modbus data header
{
// set size of received data
if (modbus_msg->ByteCnt <= DATA_SIZE*2) // if ByteCnt less than DATA_SIZE
modbus_uart_buff[ind++] = modbus_msg->ByteCnt;
else // otherwise return data_size err
{
return RS_COLLECT_MSG_ERR;
}
//---------------DATA----------------
//-----------[data bytes]------------
uint16_t *tmp_data_addr = (uint16_t *)modbus_msg->DATA;
for(int i = 0; i < modbus_msg->ByteCnt; i++) // filling buffer with data
{ // set data
if (i%2 == 0) // HI byte
modbus_uart_buff[ind++] = (*tmp_data_addr)>>8;
else // LO byte
{
modbus_uart_buff[ind++] = *tmp_data_addr;
tmp_data_addr++;
}
}
}
}
else // if some error occur
{ // send expection code
modbus_uart_buff[ind++] = modbus_msg->Except_Code;
}
}
//---------------CRC----------------
//---------[last 16 bytes]----------
// calc crc of received data
uint16_t CRC_VALUE = crc16(modbus_uart_buff, ind);
// write crc to message structure and modbus-uart buffer
modbus_msg->MB_CRC = CRC_VALUE;
modbus_uart_buff[ind++] = CRC_VALUE;
modbus_uart_buff[ind++] = CRC_VALUE >> 8;
hmodbus->RS_Message_Size = ind;
return RS_OK; // returns ok
}
/**
* @brief Parse message from buffer to process it.
* @param hRS - указатель на хендлер RS.
* @param RS_msg - указатель на структуру сообщения.
* @param msg_uart_buff - указатель на буффер UART.
* @return RS_RES - статус о результате заполнения структуры.
* @details Заполнение структуры сообщения из буффера UART.
*/
RS_StatusTypeDef RS_Parse_Message(RS_HandleTypeDef *hmodbus, RS_MsgTypeDef *modbus_msg, uint8_t *modbus_uart_buff)
{
uint32_t check_empty_buff;
int ind = 0; // ind for modbus-uart buffer
//-----INFO ABOUT DATA/MESSAGE-------
#ifdef TCP_ModBus
modbus_msg->ID_Transaction=modbus_uart_buff[ind++]<<8;
modbus_msg->ID_Transaction|=modbus_uart_buff[ind++];
modbus_msg->ID_Prot=modbus_uart_buff[ind++]<<8;
modbus_msg->ID_Prot|=modbus_uart_buff[ind++];
modbus_msg->PDU_Length=modbus_uart_buff[ind++]<<8;
modbus_msg->PDU_Length|=modbus_uart_buff[ind++];
#else
#endif
//-----------[first bits]------------
// get ID of message/user
modbus_msg->MbAddr = modbus_uart_buff[ind++];
if(modbus_msg->MbAddr != hmodbus->ID)
return RS_SKIP;
// get func code
modbus_msg->Func_Code = modbus_uart_buff[ind++];
if(modbus_msg->Func_Code == MB_R_DEVICE_INFO) // if it device identification request
{
modbus_msg->DevId.MEI_Type = modbus_uart_buff[ind++];
modbus_msg->DevId.ReadDevId = modbus_uart_buff[ind++];
modbus_msg->DevId.NextObjId = modbus_uart_buff[ind++];
modbus_msg->ByteCnt = 0;
}
else // if its classic modbus request
{
// get address from CMD
modbus_msg->Addr = modbus_uart_buff[ind++] << 8;
modbus_msg->Addr |= modbus_uart_buff[ind++];
// get address from CMD
modbus_msg->Qnt = modbus_uart_buff[ind++] << 8;
modbus_msg->Qnt |= modbus_uart_buff[ind++];
}
if(hmodbus->f.RX_Half == 0) // if all message received
{
//---------------DATA----------------
// (optional)
if (modbus_msg->ByteCnt != 0)
{
ind++; // increment ind for data_size byte
//check that data size is correct
if (modbus_msg->ByteCnt > DATA_SIZE*2)
{
modbus_msg->Func_Code += ERR_VALUES_START;
return RS_PARSE_MSG_ERR;
}
uint16_t *tmp_data_addr = (uint16_t *)modbus_msg->DATA;
for(int i = 0; i < modbus_msg->ByteCnt; i++) // /2 because we transmit 8 bits, not 16 bits
{ // set data
if (i%2 == 0)
*tmp_data_addr = ((uint16_t)modbus_uart_buff[ind++] << 8);
else
{
*tmp_data_addr |= modbus_uart_buff[ind++];
tmp_data_addr++;
}
}
}
//---------------CRC----------------
//----------[last 16 bits]----------
// calc crc of received data
uint16_t CRC_VALUE = crc16(modbus_uart_buff, ind);
// get crc of received data
modbus_msg->MB_CRC = modbus_uart_buff[ind++];
modbus_msg->MB_CRC |= modbus_uart_buff[ind++] << 8;
// compare crc
if (modbus_msg->MB_CRC != CRC_VALUE)
{
modbus_msg->Func_Code += ERR_VALUES_START;
}
// hmodbus->MB_RESPONSE = MB_CRC_ERR; // set func code - error about wrong crc
// check is buffer empty
check_empty_buff = 0;
for(int i=0; i<ind;i++)
check_empty_buff += modbus_uart_buff[i];
// if(check_empty_buff == 0)
// hmodbus->MB_RESPONSE = MB_EMPTY_MSG; //
}
return RS_OK;
}
/**
* @brief Define size of RX Message that need to be received.
* @param hRS - указатель на хендлер RS.
* @param rx_data_size - указатель на переменную для записи кол-ва байт для принятия.
* @return RS_RES - статус о корректности рассчета кол-ва байт для принятия.
* @details Определение сколько байтов надо принять по протоколу.
*/
RS_StatusTypeDef RS_Define_Size_of_RX_Message(RS_HandleTypeDef *hmodbus, uint32_t *rx_data_size)
{
RS_StatusTypeDef MB_RES = 0;
MB_RES = RS_Parse_Message(hmodbus, hmodbus->pMessagePtr, hmodbus->pBufferPtr);
if(MB_RES == RS_SKIP) // if message not for us
return MB_RES; // return
if ((hmodbus->pMessagePtr->Func_Code & ~ERR_VALUES_START) < 0x0F)
{
hmodbus->pMessagePtr->ByteCnt = 0;
*rx_data_size = 1;
}
else
{
hmodbus->pMessagePtr->ByteCnt = hmodbus->pBufferPtr[RX_FIRST_PART_SIZE-1]; // get numb of data in command
// +1 because that defines is size, not ind.
*rx_data_size = hmodbus->pMessagePtr->ByteCnt + 2;
}
if(hmodbus->pMessagePtr->Func_Code == MB_R_DEVICE_INFO)
{
*rx_data_size = 0;
}
hmodbus->RS_Message_Size = RX_FIRST_PART_SIZE + *rx_data_size; // size of whole message
return RS_OK;
}
//-----------------------------FOR USER------------------------------
//-------------------------------------------------------------------
void MB_DevoceInentificationInit(void)
{
MB_INFO.VendorName.name = MODBUS_VENDOR_NAME;
MB_INFO.ProductCode.name = MODBUS_PRODUCT_CODE;
MB_INFO.Revision.name = MODBUS_REVISION;
MB_INFO.VendorUrl.name = MODBUS_VENDOR_URL;
MB_INFO.ProductName.name = MODBUS_PRODUCT_NAME;
MB_INFO.ModelName.name = MODBUS_MODEL_NAME;
MB_INFO.UserApplicationName.name = MODBUS_USER_APPLICATION_NAME;
MB_INFO.VendorName.length = sizeof(MODBUS_VENDOR_NAME);
MB_INFO.ProductCode.length = sizeof(MODBUS_PRODUCT_CODE);
MB_INFO.Revision.length = sizeof(MODBUS_REVISION);
MB_INFO.VendorUrl.length = sizeof(MODBUS_VENDOR_URL);
MB_INFO.ProductName.length = sizeof(MODBUS_PRODUCT_NAME);
MB_INFO.ModelName.length = sizeof(MODBUS_MODEL_NAME);
MB_INFO.UserApplicationName.length = sizeof(MODBUS_USER_APPLICATION_NAME);
}

View File

@@ -1,383 +0,0 @@
/**
**************************************************************************
* @file modbus.h
* @brief Заголовочный файл модуля MODBUS.
* @details Данный файл необходимо подключить в rs_message.h. После подключать
* rs_message.h к основному проекту.
*
* @defgroup MODBUS
* @brief Modbus stuff
*
*************************************************************************/
#ifndef __MODBUS_H_
#define __MODBUS_H_
#define TCP_ModBus
#include "modbus_config.h"
#include "modbus_data.h"
//#include "settings.h" // for modbus settings
/**
* @addtogroup MODBUS_SETTINGS
* @ingroup MODBUS
* @brief Some defines for modbus
@{
*/
/////////////////////////////////////////////////////////////////////
//////////////////////////---SETTINGS---/////////////////////////////
// USER SETTINGS FOR MODBUS IN interface_config.h
//////////////////////////---SETTINGS---/////////////////////////////
/////////////////////////////////////////////////////////////////////
/////////////////////---USER MESSAGE DEFINES---//////////////////////
//-------------DEFINES FOR STRUCTURE----------------
/* defines for structure of modbus message */
#define ID_Transaction_size 2
#define ID_Prot_size 2
#define DataLength_size 2
#define MbAddr_SIZE 1 ///< size of (MbAddr)
#define Func_Code_SIZE 1 ///< size of (Func_Code)
#define Addr_SIZE 2 ///< size of (Addr)
#define Qnt_SIZE 2 ///< size of (Qnt)
#define ByteCnt_SIZE 1 ///< size of (ByteCnt)
#define DATA_SIZE 125 ///< maximum number of data: DWORD (NOT MESSAGE SIZE)
#define CRC_SIZE 2 ///< size of (MB_CRC) in bytes
/** @brief Size of whole message */
#ifdef TCP_ModBus
#define INFO_SIZE_MAX (ID_Transaction_size+ID_Prot_size+DataLength_size+MbAddr_SIZE+Func_Code_SIZE+Addr_SIZE+Qnt_SIZE)
#else
#define INFO_SIZE_MAX (MbAddr_SIZE+Func_Code_SIZE+Addr_SIZE+Qnt_SIZE+ByteCnt_SIZE)
#endif
/** @brief Size of first part of message that will be received
first receive info part of message, than defines size of rest message*/
#define RX_FIRST_PART_SIZE INFO_SIZE_MAX
/** @brief Size of buffer: max size of whole message */
#define MSG_SIZE_MAX (INFO_SIZE_MAX + DATA_SIZE*2 + CRC_SIZE) // max possible size of message
/** @brief Structure for modbus exception codes */
typedef enum //MB_ExceptionTypeDef
{
// reading
NO_ERRORS = 0x00, ///< no errors
ILLEGAL_FUNCTION = 0x01, ///< Принятый код функции не может быть обработан
ILLEGAL_DATA_ADDRESS = 0x02, ///< Адрес данных, указанный в запросе, недоступен
ILLEGAL_DATA_VALUE = 0x03, ///< Значение, содержащееся в поле данных запроса, является недопустимой величиной
SLAVE_DEVICE_FAILURE = 0x04, ///< Невосстанавливаемая ошибка имела место, пока ведомое устройство пыталось выполнить затребованное действие
// ACKNOWLEDGE = 0x05, ///< idk
// SLAVE_DEVICE_BUSY = 0x06, ///< idk
// MEMORY_PARITY_ERROR = 0x08, ///< idk
}MB_ExceptionTypeDef;
#define ERR_VALUES_START 0x80U ///< from this value starts error func codes
/** @brief Structure for modbus func codes */
typedef enum //MB_FunctonTypeDef
{
/* COMMANDS */
// reading
MB_R_COILS = 0x01, ///< Чтение битовых ячеек
MB_R_DISC_IN = 0x02, ///< Чтение дискретных входов
#ifndef MODBUS_SWITCH_COMMAND_R_IN_REGS_AND_R_HOLD_REGS
MB_R_HOLD_REGS = 0x03, ///< Чтение входных регистров
MB_R_IN_REGS = 0x04, ///< Чтение регистров хранения
#else
MB_R_HOLD_REGS = 0x04, ///< Чтение входных регистров
MB_R_IN_REGS = 0x03, ///< Чтение регистров хранения
#endif
// writting
MB_W_COIL = 0x05, ///< Запись битовой ячейки
MB_W_HOLD_REG = 0x06, ///< Запись одиночного регистра
MB_W_COILS = 0x0F, ///< Запись нескольких битовых ячеек
MB_W_HOLD_REGS = 0x10, ///< Запись нескольких регистров
MB_R_DEVICE_INFO = 0x2B, ///< Чтения информации об устройстве
/* ERRORS */
// error reading
MB_ERR_R_COILS = MB_R_COILS + ERR_VALUES_START, ///< Ошибка чтения битовых ячеек
MB_ERR_R_DISC_IN = MB_R_DISC_IN + ERR_VALUES_START, ///< Ошибка чтения дискретных входов
MB_ERR_R_IN_REGS = MB_R_IN_REGS + ERR_VALUES_START, ///< Ошибка чтения регистров хранения
MB_ERR_R_HOLD_REGS = MB_R_HOLD_REGS + ERR_VALUES_START, ///< Ошибка чтения входных регистров
// error writting
MB_ERR_W_COIL = MB_W_COIL + ERR_VALUES_START, ///< Ошибка записи битовой ячейки
MB_ERR_W_HOLD_REG = MB_W_HOLD_REG + ERR_VALUES_START, ///< Ошибка записи одиночного регистра
MB_ERR_W_COILS = MB_W_COILS + ERR_VALUES_START, ///< Ошибка записи нескольких битовых ячеек
MB_ERR_W_HOLD_REGS = MB_W_HOLD_REGS + ERR_VALUES_START, ///< Ошибка записи нескольких регистров
}MB_FunctonTypeDef;
/** @brief Structure for MEI func codes */
typedef enum //MB_FunctonTypeDef
{
MEI_DEVICE_IDENTIFICATION = 0x0E,
}MB_MEITypeDef;
/** @brief Structure for MEI func codes */
typedef enum //MB_FunctonTypeDef
{
MB_BASIC_IDENTIFICATION = 0x01,
MB_REGULAR_IDENTIFICATION = 0x02,
/* ERRORS */
MB_ERR_BASIC_IDENTIFICATION = MB_BASIC_IDENTIFICATION + ERR_VALUES_START,
MB_ERR_REGULAR_IDENTIFICATION = MB_REGULAR_IDENTIFICATION + ERR_VALUES_START,
}MB_ConformityTypeDef;
/** @brief Structure for decive identification message type */
typedef struct
{
MB_MEITypeDef MEI_Type; ///< MEI Type assigned number for Device Identification Interface
MB_ConformityTypeDef ReadDevId;
MB_ConformityTypeDef Conformity;
uint8_t MoreFollows; ///< in this library always a zero
uint8_t NextObjId;
uint8_t NumbOfObj;
}MB_DevIdMsgTypeDef;
/** @brief Structure for modbus messsage */
typedef struct // RS_MsgTypeDef
{
uint16_t ID_Transaction;
uint16_t ID_Prot;
uint16_t PDU_Length;
uint8_t MbAddr; ///< Modbus Slave Address
MB_FunctonTypeDef Func_Code; ///< Modbus Function Code
MB_DevIdMsgTypeDef DevId; ///< Read Device Identification Header struct
uint16_t Addr; ///< Modbus Address of data
uint16_t Qnt; ///< Quantity of modbus data
uint8_t ByteCnt; ///< Quantity of bytes of data in message to transmit/receive
uint16_t DATA[DATA_SIZE]; ///< Modbus Data
MB_ExceptionTypeDef Except_Code; ///< Exception Code for the command
uint16_t MB_CRC; ///< Modbus CRC
}RS_MsgTypeDef;
//--------------------------------------------------
extern RS_MsgTypeDef MODBUS_MSG;
/////////////////////---MODBUS USER SETTINGS---//////////////////////
/** MODBUS_SETTINGS
* @}
*/
/////////////////////////////////////////////////////////////////////
////////////////////---MODBUS MESSAGE DEFINES---/////////////////////
/**
* @addtogroup MODBUS_MESSAGE_DEFINES
* @ingroup MODBUS
* @brief Some defines for modbus
@{
*/
/** @brief Structure for coils operation */
typedef enum
{
SET_COIL,
RESET_COIL,
TOOGLE_COIL,
}MB_CoilsOpTypeDef;
//--------------------------------------------------
/**
* @brief Macros to set pointer to 16-bit array
* @param _arr_ - массив регистров (16-бит).
*/
#define MB_Set_Arr16_Ptr(_arr_) ((uint16_t*)(&(_arr_)))
/**
* @brief Macros to set pointer to register
* @param _parr_ - массив регистров.
* @param _addr_ - Номер регистра (его индекс) от начала массива _arr_.
*/
#define MB_Set_Register_Ptr(_parr_, _addr_) ((uint16_t *)(_parr_)+(_addr_))
/**
* @brief Macros to set pointer to a certain register that contains certain coil
* @param _parr_ - массив коилов.
* @param _coil_ - Номер коила от начала массива _arr_.
* @note Используется вместе с @ref MB_Set_Coil_Mask
@verbatim Пояснение выражений
(_coil_/16) - get index (address shift) of register that contain certain coil
Visual explanation: 30th coil in coils registers array
xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxCx
|register[0]----| |register[1]----|
|skip this------| |get this-------|
|shift to 14 bit|
@endverbatim
*/
#define MB_Set_Coil_Reg_Ptr(_parr_, _coil_) ((uint16_t *)(_parr_)+((_coil_)/16))
/**
* @brief Macros to set mask to a certain bit in coils register
* @param _coil_ - Номер коила от начала массива _arr_.
* @note Используется вместе с @ref MB_Set_Coil_Reg_Ptr
@verbatim Пояснение выражений
(16*(_coil_/16) - how many coils we need to skip. e.g. (16*30/16) - skip 16 coils from first register
_coil_-(16*(_coil_/16)) - shift to certain coil in certain register
e.g. Coil(30) gets in register[1] (30/16 = 1) coil №14 (30 - (16*30/16) = 30 - 16 = 14)
Visual explanation: 30th coil in coils registers array
xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxCx
|register[0]----| |register[1]----|
|skip this------| |get this-------|
|shift to 14 bit|
@endverbatim
*/
#define MB_Set_Coil_Mask(_coil_) (1 << ( _coil_ - (16*((_coil_)/16)) ))
/**
* @brief Read Coil at its local address.
* @param _parr_ - массив коилов.
* @param _coil_ - Номер коила от начала массива _arr_.
* @return uint16_t - Возвращает запрошенный коил на 0м бите.
*
* @details Позволяет обратиться к коилу по адресу относительно _arr_.
*/
#define MB_Read_Coil_Local(_parr_, _coil_) (( *MB_Set_Coil_Reg_Ptr(_parr_, _coil_) & MB_Set_Coil_Mask(_coil_) ) >> (_coil_))
/**
* @brief Set Coil at its local address.
* @param _parr_ - указатель на массив коилов.
* @param _coil_ - Номер коила от начала массива _arr_.
*
* @details Позволяет обратиться к коилу по адресу относительно _arr_.
*/
#define MB_Set_Coil_Local(_parr_, _coil_) *MB_Set_Coil_Reg_Ptr(_parr_, _coil_) |= MB_Set_Coil_Mask(_coil_)
/**
* @brief Reset Coil at its local address.
* @param _parr_ - указатель на массив коилов.
* @param _coil_ - Номер коила от начала массива _arr_.
*
* @details Позволяет обратиться к коилу по адресу относительно _arr_.
*/
#define MB_Reset_Coil_Local(_parr_, _coil_) *MB_Set_Coil_Reg_Ptr(_parr_, _coil_) &= ~(MB_Set_Coil_Mask(_coil_))
/**
* @brief Set Coil at its local address.
* @param _parr_ - указатель на массив коилов.
* @param _coil_ - Номер коила от начала массива _arr_.
*
* @details Позволяет обратиться к коилу по адресу относительно _arr_.
*/
#define MB_Toogle_Coil_Local(_parr_, _coil_) *MB_Set_Coil_Reg_Ptr(_parr_, _coil_) ^= MB_Set_Coil_Mask(_coil_)
//--------------------------------------------------
//------------------OTHER DEFINES-------------------
#define RegisterType_Holding 0
#define RegisterType_Input 1
#define RegisterType_Discrete 2
// create hadnles and settings for uart, tim, rs with _modbus_ name
//--------------------------------------------------
#ifndef Divide_Up
/**
* @brief Calc dividing including remainder
* @param _val_ - делимое.
* @param _div_ - делитель.
* @details Если результат деления без остатка: он возвращается как есть
Если с остатком - округляется вверх
*/
//#define Divide_Up(_val_, _div_) (((_val_)%(_div_))? (_val_)/(_div_)+1 : (_val_)/_div_) /* через тернарный оператор */
#define Divide_Up(_val_, _div_) ((_val_ - 1) / _div_) + 1 /* через мат выражение */
#endif
#ifndef ByteSwap16
/**
* @brief Swap between Little Endian and Big Endian
* @param v - Переменная для свапа.
* @return v (new) - Свапнутая переменная.
* @details Переключения между двумя типами хранения слова: HI-LO байты и LO-HI байты.
*/
#define ByteSwap16(v) (((v&0xFF00) >> (8)) | ((v&0x00FF) << (8)))
#endif
/** GENERAL_MODBUS_STUFF
* @}
*/
////////////////////---MODBUS MESSAGE DEFINES---/////////////////////
/////////////////////////////////////////////////////////////////////
/////////////////////////---FUNCTIONS---/////////////////////////////
/**
* @addtogroup MODBUS_FUNCTIONS
* @ingroup MODBUS
* @brief Function for controling modbus communication
*/
//----------------FUNCTIONS FOR USER----------------
/**
* @addtogroup MODBUS_DATA_ACCESS_FUNCTIONS
* @ingroup MODBUS_FUNCTIONS
* @brief Function for user use
@{
*/
/* First set up of MODBUS */
void MODBUS_FirstInit(void);
/* Set or Reset Coil at its global address */
MB_ExceptionTypeDef MB_Write_Coil_Global(uint16_t Addr, MB_CoilsOpTypeDef WriteVal);
/* Read Coil at its global address */
uint16_t MB_Read_Coil_Global(uint16_t Addr, MB_ExceptionTypeDef *Exception);
/** MODBUS_DATA_ACCESS_FUNCTIONS
* @}
*/
//---------PROCESS MODBUS COMMAND FUNCTIONS---------
/**
* @addtogroup MODBUS_CMD_PROCESS_FUNCTIONS
* @ingroup MODBUS_FUNCTIONS
* @brief Function process commands
@{
*/
/* Check is address valid for certain array */
MB_ExceptionTypeDef MB_Check_Address_For_Arr(uint16_t Addr, uint16_t Qnt, uint16_t R_ARR_ADDR, uint16_t R_ARR_NUMB);
/* Define Address Origin for Input/Holding Registers */
MB_ExceptionTypeDef MB_DefineRegistersAddress(uint16_t **pRegs, uint16_t Addr, uint16_t Qnt, uint8_t RegisterType);
/* Define Address Origin for coils */
MB_ExceptionTypeDef MB_DefineCoilsAddress(uint16_t **pCoils, uint16_t Addr, uint16_t Qnt, uint16_t *start_shift, uint8_t WriteFlag);
/* Proccess command Read Coils (01 - 0x01) */
uint8_t MB_Read_Coils(RS_MsgTypeDef *modbus_msg);
/* Proccess command Read Holding Registers (03 - 0x03) */
uint8_t MB_Read_Hold_Regs(RS_MsgTypeDef *modbus_msg);
/* Proccess command Read Input Registers (04 - 0x04) */
uint8_t MB_Read_Input_Regs(RS_MsgTypeDef *modbus_msg);
/* Proccess command Write Single Coils (05 - 0x05) */
uint8_t MB_Write_Single_Coil(RS_MsgTypeDef *modbus_msg);
/* Proccess command Write Multiple Coils (15 - 0x0F) */
uint8_t MB_Write_Miltuple_Coils(RS_MsgTypeDef *modbus_msg);
/* Proccess command Write Multiple Register (16 - 0x10) */
uint8_t MB_Write_Miltuple_Regs(RS_MsgTypeDef *modbus_msg);
/** MODBUS_DATA_ACCESS_FUNCTIONS
* @}
*/
/////////////////////////---FUNCTIONS---/////////////////////////////
/////////////////////////////////////////////////////////////////////
/////////////////////////---CALC DEFINES---//////////////////////////
// TRACES DEFINES
#ifndef Trace_MB_UART_Enter
#define Trace_MB_UART_Enter()
#endif //Trace_MB_UART_Enter
#ifndef Trace_MB_UART_Exit
#define Trace_MB_UART_Exit()
#endif //Trace_MB_UART_Exit
#ifndef Trace_MB_TIM_Enter
#define Trace_MB_TIM_Enter()
#endif //Trace_MB_TIM_Enter
#ifndef Trace_MB_TIM_Exit
#define Trace_MB_TIM_Exit()
#endif //Trace_MB_TIM_Exit
#endif //__MODBUS_H_

View File

@@ -1,44 +0,0 @@
/**
**************************************************************************
* @file interface_config.h
* @brief Конфигурация для модбаса
*************************************************************************/
#ifndef _MODBUS_CONFIG_H_
#define _MODBUS_CONFIG_H_
#include "stm32f1xx_hal.h"
// MODBUS PARAMS
#define MODBUS_DEVICE_ID 1 ///< девайс текущего устройства
#define MODBUS_TIMEOUT 2000 ///< максимальнйы тайтаут MB в тиках таймера
// STRING OBJECTS MODBUS
#define MODBUS_VENDOR_NAME "NIO-12"
#define MODBUS_PRODUCT_CODE ""
#define MODBUS_REVISION "Ver. 1.0"
#define MODBUS_VENDOR_URL ""
#define MODBUS_PRODUCT_NAME ""
#define MODBUS_MODEL_NAME "STM32F103"
#define MODBUS_USER_APPLICATION_NAME ""
// PERIPH FUNCTIONS AND HANDLERS
#define RS_UART_Init MX_USART1_UART_Init //инициализация uart
#define RS_UART_DeInit HAL_UART_MspDeInit //деинициализация uart
#define RS_TIM_Init MX_TIM2_Init //инициализация таймера
#define RS_TIM_DeInit HAL_TIM_Base_MspDeInit//деинициализация таймера
#define rs_huart huart1 //используемый uart
#define rs_htim htim2 //используемый таймера
/**
* @brief Поменять комманды 0x03 и 0x04 местами (для LabView терминалки от двигателей)
* @details Терминалка от двигателей использует для чтения регистров комманду R_HOLD_REGS вместо R_IN_REGS
* Поэтому чтобы считывать Input Regs - надо поменять их местами.
*/
//#define MODBUS_SWITCH_COMMAND_R_IN_REGS_AND_R_HOLD_REGS
/////////////////////////////////////////////////////////////////////
/////////////////////////---CALC DEFINES---//////////////////////////
#endif //_MODBUS_CONFIG_H_

View File

@@ -1,201 +0,0 @@
/**
**************************************************************************
* @file modbus_data.h
* @brief Заголовочный файл с описанием даты MODBUS.
* @details Данный файл необходимо подключается в rs_message.h. После rs_message.h
* подключается к основному проекту.
*
* @defgroup MODBUS_DATA
* @ingroup MODBUS
* @brief Modbus data description
*
*************************************************************************/
#ifndef _MODBUS_DATA_H_
#define _MODBUS_DATA_H_
#include "stdint.h"
//--------------DEFINES FOR REGISTERS---------------
// DEFINES FOR ARRAYS
/**
* @addtogroup MODBUS_DATA_RERISTERS_DEFINES
* @ingroup MODBUS_DATA
* @brief Defines for registers
Структура дефайна адресов
@verbatim
Для массивов регистров:
R_<NAME_ARRAY>_ADDR - модбас адресс первого регистра в массиве
R_<NAME_ARRAY>_QNT - количество регистров в массиве
При добавлении новых массивов регистров, необходимо их добавить в функцию MB_DefineRegistersAddress
if(MB_Check_Address_For_Arr(Addr, Qnt, R_<NEW_ARRAY>_ADDR, R_<NEW_ARRAY>_QNT) == NO_ERRORS)
{
*pRegs = MB_Set_Register_Ptr(&<NEW_ARRAY>, Addr); // начало регистров хранения/входных
}
@endverbatim
* @{
*/
/**
* @brief Регистры хранения
*/
#define MAX_SENSE 30
typedef struct //MB_DataInRegsTypeDef
{
uint16_t sens_Temp[MAX_SENSE];
uint16_t UzptPLUS;
uint16_t UzptMINUS;
uint16_t UzptPLUS_MIN;
}MB_DataInRegsTypeDef;
/**
* @brief Входные регистры
*/
typedef struct //MB_DataInRegsTypeDef
{
uint16_t set_Temp[MAX_SENSE];
uint16_t set_hyst[MAX_SENSE];
}MB_DataHoldRegsTypeDef;
// DEFINES FOR INPUT REGISTERS ARRAYS
#define R_INPUT_ADDR 0
#define R_INPUT_QNT 40
// DEFINES FOR HOLDING REGISTERS ARRAYS
#define R_HOLDING_ADDR 0
#define R_HOLDING_QNT 40
/** MODBUS_DATA_RERISTERS_DEFINES
* @}
*/
//----------------DEFINES FOR COILS-----------------
/**
* @addtogroup MODBUS_DATA_COILS_DEFINES
* @ingroup MODBUS_DATA
* @brief Defines for coils
@verbatim
Структура дефайна
Для массивов коилов:
C_<NAME_ARRAY>_ADDR - модбас адресс первого коила в массиве
C_<NAME_ARRAY>_QNT - количество коилов в массиве (минимум 16)
При добавлении новых массивов коилов, необходимо их добавить в функцию MB_DefineCoilsAddress
if(MB_Check_Address_For_Arr(Addr, Qnt, C_<NEW_ARRAY>_ADDR, C_<NEW_ARRAY>_QNT) == NO_ERRORS)
{
*pCoils = MB_Set_Coil_Reg_Ptr(&<NEW_ARRAY>, Addr);
}
@endverbatim
* @{
*/
/**
* @brief Коилы
* @details Желательно с помощью reserved делать стркутуру кратной 16-битам
*/
typedef union
{
struct __packed {
unsigned state_val_01:1;
unsigned state_val_02:1;
unsigned state_val_03:1;
unsigned state_val_04:1;
unsigned state_val_05:1;
unsigned state_val_06:1;
unsigned state_val_07:1;
unsigned state_val_08:1;
unsigned state_val_09:1;
unsigned state_val_10:1;
unsigned state_val_11:1;
unsigned state_val_12:1;
unsigned state_val_13:1;
unsigned state_val_14:1;
unsigned state_val_15:1;
unsigned state_val_16:1;
} state_val_bit;
uint16_t all;
}word;
typedef struct //MB_DataCoilsTypeDef
{
word coils[2];
unsigned init_param:1;
unsigned reserved:15;
}MB_DataCoilsTypeDef;
// DEFINES FOR COIL ARRAYS
#define C_CONTROL_ADDR 0
#define C_CONTROL_QNT 100
/** MODBUS_DATA_COILS_DEFINES
* @}
*/
//-----------MODBUS DEVICE DATA SETTING-------------
// MODBUS DATA STRUCTTURE
/**
* @brief Структура со всеми регистрами и коилами модбас
* @ingroup MODBUS_DATA
*/
typedef struct // tester modbus data
{
MB_DataInRegsTypeDef InRegs; ///< Modbus input registers @ref MB_DataInRegsTypeDef
MB_DataCoilsTypeDef Coils; ///< Modbus coils @ref MB_DataCoilsTypeDef
MB_DataHoldRegsTypeDef HoldRegs; ///< Modbus holding registers @ref MB_DataHoldRegsTypeDef
}MB_DataStructureTypeDef;
extern MB_DataStructureTypeDef MB_DATA;
/**
* @brief Структура для объекта Modbus
* @ingroup MODBUS_DATA
*/
typedef struct
{
unsigned length;
char *name;
}MB_DeviceObjectTypeDef;
/**
* @brief Структура для объектов Modbus
* @ingroup MODBUS_DATA
*/
typedef struct
{
MB_DeviceObjectTypeDef VendorName;
MB_DeviceObjectTypeDef ProductCode;
MB_DeviceObjectTypeDef Revision;
MB_DeviceObjectTypeDef VendorUrl;
MB_DeviceObjectTypeDef ProductName;
MB_DeviceObjectTypeDef ModelName;
MB_DeviceObjectTypeDef UserApplicationName;
}MB_DeviceIdentificationTypeDef;
void MB_DevoceInentificationInit(void);
#endif //_MODBUS_DATA_H_
/////////////////////////////////////////////////////////////
///////////////////////TEMP/OUTDATE/OTHER////////////////////

View File

@@ -1,555 +0,0 @@
/**
**************************************************************************
* @file rs_message.c
* @brief Модуль для реализации протоколов по RS/UART.
**************************************************************************\
* @details
* Данный модуль реализует основные функции для приема и передачи сообщений
* по протоколу RS через UART в режиме прерываний. Реализована обработка
* приема и передачи данных, управление состояниями RS, а также функции для
* инициализации и управления периферией.
*
* Реализованы следующие функции:
* - RS_Receive_IT() — запуск приема данных в прерывании по UART.
* - RS_Transmit_IT() — запуск передачи данных в прерывании по UART.
* - RS_Init() — инициализация структуры RS и привязка периферии.
* - RS_ReInit_UART() — переинициализация UART и перезапуск приема данных.
* - RS_Abort() — остановка работы RS/UART с очисткой флагов и структур.
* - RS_Handle_Receive_Start() — обработка старта приема данных по RS.
*
* В модуле также определен буфер RS_Buffer[] для хранения принимаемых/передаваемых данных.
*
* @note
* Для корректной работы модуля предполагается использование соответствующих
* обработчиков прерываний UART и таймера (RS_UART_Handler(), RS_TIM_Handler()),
* которые надо вызывать с обработчиках используемой периферии
@verbatim
//-------------------Функции-------------------//
Functions: users
- RS_Parse_Message/RS_Collect_Message Заполнение структуры сообщения и буфера
- RS_Response Ответ на сообщение
- RS_Define_Size_of_RX_Message Определение размера принимаемых данных
Functions: general
- RS_Receive_IT Ожидание комманды и ответ на неё
- RS_Transmit_IT Отправление комманды и ожидание ответа
- RS_Init Инициализация переферии и структуры для RS
- RS_ReInit_UART Реинициализация UART для RS
- RS_Abort Отмена приема/передачи по ЮАРТ
- RS_Init Инициализация периферии и modbus handler
Functions: callback/handler
- RS_Handle_Receive_Start Функция для запуска приема или остановки RS
- RS_Handle_Transmit_Start Функция для запуска передачи или остановки RS
- RS_UART_RxCpltCallback Коллбек при окончании приема или передачи
RS_UART_TxCpltCallback
- RS_UART_Handler Обработчик прерывания для UART
- RS_TIM_Handler Обработчик прерывания для TIM
@endverbatim
*************************************************************************/
#include "rs_message.h"
uint8_t RS_Buffer[MSG_SIZE_MAX]; // uart buffer
extern void RS_UART_Init(void);
extern void RS_UART_DeInit(UART_HandleTypeDef *huart);
extern void RS_TIM_Init(void);
extern void RS_TIM_DeInit(TIM_HandleTypeDef *htim);
//-------------------------------------------------------------------
//-------------------------GENERAL FUNCTIONS-------------------------
/**
* @brief Start receive IT.
* @param hRS - указатель на хендлер RS.
* @param RS_msg - указатель на структуру сообщения.
* @return RS_RES - статус о состоянии RS после инициализации приема.
*/
RS_StatusTypeDef RS_Receive_IT(RS_HandleTypeDef *hRS, RS_MsgTypeDef *RS_msg)
{
RS_StatusTypeDef RS_RES = 0;
HAL_StatusTypeDef uart_res = 0;
//-------------CHECK RS LINE----------------
// check that receive isnt busy
if( RS_Is_RX_Busy(hRS) ) // if tx busy - return busy status
return RS_BUSY;
//-----------INITIALIZE RECEIVE-------------
// if all OK: start receiving
RS_EnableReceive();
RS_Set_Busy(hRS); // set RS busy
RS_Set_RX_Flags(hRS); // initialize flags for receive
hRS->pMessagePtr = RS_msg; // set pointer to message structire for filling it from UARTHandler fucntions
// start receiving
uart_res = HAL_UART_Receive_IT(hRS->huart, hRS->pBufferPtr, RX_FIRST_PART_SIZE); // receive until ByteCnt+1 byte,
// then in Callback restart receive for rest bytes
// if receive isnt started - abort RS
if(uart_res != HAL_OK)
{
RS_RES = RS_Abort(hRS, ABORT_RS);
printf_rs_err("\n%d: Error RS: Failed to start RS receiving...", uwTick);
}
else
{
RS_RES = RS_OK;
printf_rs("\n%d: RS: Start Receiving...", uwTick);
}
hRS->RS_STATUS = RS_RES;
return RS_RES; // returns result of receive init
}
/**
* @brief Start transmit IT.
* @param hRS - указатель на хендлер RS.
* @param RS_msg - указатель на структуру сообщения.
* @return RS_RES - статус о состоянии RS после инициализации передачи.
*/
RS_StatusTypeDef RS_Transmit_IT(RS_HandleTypeDef *hRS, RS_MsgTypeDef *RS_msg)
{
RS_StatusTypeDef RS_RES = 0;
HAL_StatusTypeDef uart_res = 0;
//-------------CHECK RS LINE----------------
// check that transmit isnt busy
if( RS_Is_TX_Busy(hRS) ) // if tx busy - return busy status
return RS_BUSY;
// check receive line
//------------COLLECT MESSAGE---------------
RS_RES = RS_Collect_Message(hRS, RS_msg, hRS->pBufferPtr);
if (RS_RES != RS_OK) // if message isnt collect - stop RS and return error in RS_RES
{// need collect message status, so doesnt write abort to RS_RES
RS_Abort(hRS, ABORT_RS);
RS_Handle_Receive_Start(hRS, hRS->pMessagePtr); // restart receive
}
else // if collect successful
{
//----------INITIALIZE TRANSMIT-------------
RS_EnableTransmit();
// for(int i = 0; i < hRS->sRS_Timeout; i++);
RS_Set_Busy(hRS); // set RS busy
RS_Set_TX_Flags(hRS); // initialize flags for transmit IT
hRS->pMessagePtr = RS_msg; // set pointer for filling given structure from UARTHandler fucntion
// if all OK: start transmitting
uart_res = HAL_UART_Transmit_IT(hRS->huart, hRS->pBufferPtr, hRS->RS_Message_Size);
// if transmit isnt started - abort RS
if(uart_res != HAL_OK)
{
RS_RES = RS_Abort(hRS, ABORT_RS);
printf_rs_err("\n%d: Error RS: Failed to start RS transmitting...", uwTick);
}
else
{
RS_RES = RS_OK;
printf_rs("\n%d: RS: Start Transmitting...", uwTick);
}
}
hRS->RS_STATUS = RS_RES;
return RS_RES; // returns result of transmit init
}
/**
* @brief Initialize UART and handle RS stucture.
* @param hRS - указатель на хендлер RS.
* @param suart - указатель на структуру с настройками UART.
* @param stim - указатель на структуру с настройками таймера.
* @param pRS_BufferPtr - указатель на буффер для приема-передачи по UART. Если он NULL, то поставиться библиотечный буфер.
* @return RS_RES - статус о состоянии RS после инициализации.
* @note Инициализация перефирии и структуры для приема-передачи по RS.
*/
RS_StatusTypeDef RS_Init(RS_HandleTypeDef *hRS, UART_HandleTypeDef *huart, TIM_HandleTypeDef *htim, uint8_t *pRS_BufferPtr)
{
// check that hRS is defined
if (hRS == NULL)
return RS_ERR;
// check that huart is defined
if (huart == NULL)
return RS_ERR;
// init uart
// RS_UART_Init();
hRS->huart = huart;
// RS_TIM_Init();
hRS->htim = htim;
if (hRS->sRS_RX_Size_Mode == NULL)
return RS_ERR;
// check that buffer is defined
if (hRS->pBufferPtr == NULL)
{
hRS->pBufferPtr = RS_Buffer; // if no - set default
}
else
hRS->pBufferPtr = pRS_BufferPtr; // if yes - set by user
return RS_OK;
}
/**
* @brief ReInitialize UART and RS receive.
* @param hRS - указатель на хендлер RS.
* @param suart - указатель на структуру с настройками UART.
* @return RS_RES - статус о состоянии RS после инициализации.
* @note Реинициализация UART и приема по RS.
*/
HAL_StatusTypeDef RS_ReInit_UART(RS_HandleTypeDef *hRS, UART_HandleTypeDef *huart)
{
HAL_StatusTypeDef RS_RES;
hRS->f.ReInit_UART = 0;
// // check is settings are valid
// if(Check_UART_Init_Struct(suart) != HAL_OK)
// return HAL_ERROR;
RS_Abort(hRS, ABORT_RS);
RS_UART_DeInit(huart);
RS_UART_Init();
RS_Receive_IT(hRS, hRS->pMessagePtr);
return RS_RES;
}
/**
* @brief Abort RS/UART.
* @param hRS - указатель на хендлер RS.
* @param AbortMode - выбор, что надо отменить.
- ABORT_TX: Отмена передачи по ЮАРТ, с очищением флагов TX,
- ABORT_RX: Отмена приема по ЮАРТ, с очищением флагов RX,
- ABORT_RX_TX: Отмена приема и передачи по ЮАРТ,
- ABORT_RS: Отмена приема-передачи RS, с очищением всей структуры.
* @return RS_RES - статус о состоянии RS после аборта.
* @note Отмена работы UART в целом или отмена приема/передачи RS.
Также очищается хендл hRS.
*/
RS_StatusTypeDef RS_Abort(RS_HandleTypeDef *hRS, RS_AbortTypeDef AbortMode)
{
HAL_StatusTypeDef uart_res = 0;
hRS->htim->Instance->CNT = 0;
__HAL_TIM_CLEAR_IT(hRS->htim, TIM_IT_UPDATE);
if(hRS->sRS_Timeout) // if timeout setted
HAL_TIM_Base_Stop_IT(hRS->htim); // stop timeout
if((AbortMode&ABORT_RS) == 0x00)
{
if((AbortMode&ABORT_RX) == ABORT_RX)
{
uart_res = HAL_UART_AbortReceive(hRS->huart); // abort receive
RS_Reset_RX_Flags(hRS);
}
if((AbortMode&ABORT_TX) == ABORT_TX)
{
uart_res = HAL_UART_AbortTransmit(hRS->huart); // abort transmit
RS_Reset_TX_Flags(hRS);
}
}
else
{
uart_res = HAL_UART_Abort(hRS->huart);
RS_Clear_All(hRS);
}
hRS->RS_STATUS = RS_ABORTED;
return RS_ABORTED;
}
//-------------------------GENERAL FUNCTIONS-------------------------
//-------------------------------------------------------------------
//-------------------------------------------------------------------
//--------------------CALLBACK/HANDLER FUNCTIONS---------------------
/**
* @brief Handle for starting receive.
* @param hRS - указатель на хендлер RS.
* @param RS_msg - указатель на структуру сообщения.
* @return RS_RES - статус о состоянии RS после инициализации приема или окончания общения.
* @note Определяет начинать прием команды/ответа или нет.
*/
RS_StatusTypeDef RS_Handle_Receive_Start(RS_HandleTypeDef *hRS, RS_MsgTypeDef *RS_msg)
{
RS_StatusTypeDef RS_RES = 0;
switch(hRS->sRS_Mode)
{
case SLAVE_ALWAYS_WAIT: // in slave mode with permanent waiting
RS_RES = RS_Receive_IT(hRS, RS_msg); break; // start receiving again
case SLAVE_TIMEOUT_WAIT: // in slave mode with timeout waiting (start receiving cmd by request)
RS_Set_Free(hRS); RS_RES = RS_OK; break; // end RS communication (set RS unbusy)
}
if(RS_RES != RS_OK)
{
}
return RS_RES;
}
/**
* @brief Handle for starting transmit.
* @param hRS - указатель на хендлер RS.
* @param RS_msg - указатель на структуру сообщения.
* @return RS_RES - статус о состоянии RS после инициализации передачи.
* @note Определяет отвечать ли на команду или нет.
*/
RS_StatusTypeDef RS_Handle_Transmit_Start(RS_HandleTypeDef *hRS, RS_MsgTypeDef *RS_msg)
{
RS_StatusTypeDef RS_RES = 0;
switch(hRS->sRS_Mode)
{
case SLAVE_ALWAYS_WAIT: // in slave mode always response
case SLAVE_TIMEOUT_WAIT: // transmit response
RS_RES = RS_Transmit_IT(hRS, RS_msg); break;
}
if(RS_RES != RS_OK)
{
}
return RS_RES;
}
/**
* @brief UART RX Callback: define behaviour after receiving parts of message.
* @param hRS - указатель на хендлер RS.
* @return RS_RES - статус о состоянии RS после обработки приема.
* @note Контролирует прием сообщения: определяет размер принимаемой посылки и обрабатывает его.
*/
RS_StatusTypeDef RS_UART_RxCpltCallback(RS_HandleTypeDef *hRS)
{
RS_StatusTypeDef RS_RES = 0;
HAL_StatusTypeDef uart_res = 0;
// if we had received bytes before ByteCnt
if((hRS->sRS_RX_Size_Mode == RS_RX_Size_NotConst) && (hRS->f.RX_Half == 0)) // if data size isnt constant and its first half, and
{ // First receive part of message, then define size of rest of message, and start receive it
hRS->f.RX_Half = 1;
//---------------FIND DATA SIZE-----------------
uint32_t NuRS_of_Rest_Bytes = 0xFFFF;
RS_RES = RS_Define_Size_of_RX_Message(hRS, &NuRS_of_Rest_Bytes);
// if we need to skip this message - restart receive
if(RS_RES == RS_SKIP || NuRS_of_Rest_Bytes == 0xFFFF)
{
RS_Abort(hRS, ABORT_RX);
RS_RES = RS_Handle_Receive_Start(hRS, hRS->pMessagePtr);
return RS_RES;
}
// if there is no bytes to receive
if(NuRS_of_Rest_Bytes == 0)
{
hRS->f.RX_Half = 0;
//---------PROCESS DATA & ENDING RECEIVING--------
RS_Set_RX_End(hRS);
if(hRS->sRS_Timeout) // if timeout setted
HAL_TIM_Base_Stop_IT(hRS->htim); // stop timeout
// parse received data
RS_RES = RS_Parse_Message(hRS, hRS->pMessagePtr, hRS->pBufferPtr); // parse message
// RESPONSE
RS_RES = RS_Response(hRS, hRS->pMessagePtr);
return RS_RES;
}
//-------------START UART RECEIVE---------------
uart_res = HAL_UART_Receive_IT(hRS->huart, (hRS->pBufferPtr + RX_FIRST_PART_SIZE), NuRS_of_Rest_Bytes);
if(uart_res != HAL_OK)
{// need uart status, so doesnt write abort to RS_RES
RS_RES = RS_Abort(hRS, ABORT_RS);
}
else
RS_RES = RS_OK;
}
else // if we had received whole message
{
hRS->f.RX_Half = 0;
//---------PROCESS DATA & ENDING RECEIVING--------
RS_Set_RX_End(hRS);
if(hRS->sRS_Timeout) // if timeout setted
HAL_TIM_Base_Stop_IT(hRS->htim); // stop timeout
// parse received data
RS_RES = RS_Parse_Message(hRS, hRS->pMessagePtr, hRS->pBufferPtr); // parse message
// RESPONSE
RS_RES = RS_Response(hRS, hRS->pMessagePtr);
}
return RS_RES;
}
/**
* @brief UART TX Callback: define behaviour after transmiting message.
* @param hRS - указатель на хендлер RS.
* @return RS_RES - статус о состоянии RS после обработки приема.
* @note Определяет поведение RS после передачи сообщения.
*/
RS_StatusTypeDef RS_UART_TxCpltCallback(RS_HandleTypeDef *hRS)
{
RS_StatusTypeDef RS_RES = RS_OK;
HAL_StatusTypeDef uart_res = 0;
//--------------ENDING TRANSMITTING-------------
RS_Set_TX_End(hRS);
RS_EnableReceive();
// for(int i = 0; i < hRS->sRS_Timeout; i++);
//-----------START RECEIVING or END RS----------
RS_RES = RS_Handle_Receive_Start(hRS, hRS->pMessagePtr);
return RS_RES;
}
/**
* @brief Handler for UART.
* @param hRS - указатель на хендлер RS.
* @note Обрабатывает ошибки если есть и вызывает RS Коллбеки.
* Добавить вызов этой функции в UARTx_IRQHandler() после HAL_UART_IRQHandler().
*/
void RS_UART_Handler(RS_HandleTypeDef *hRS)
{
//-------------CALL RS CALLBACKS------------
/* IF NO ERROR OCCURS */
if(hRS->huart->ErrorCode == 0)
{
hRS->htim->Instance->CNT = 0; // reset cnt;
/* Start timeout */
if(hRS->sRS_Timeout) // if timeout setted
if((hRS->huart->RxXferCount+1 == hRS->huart->RxXferSize) && RS_Is_RX_Busy(hRS)) // if first byte is received and receive is active
{
hRS->htim->Instance->ARR = hRS->sRS_Timeout; // reset cnt;
HAL_TIM_Base_Start_IT(hRS->htim);
RS_Set_RX_Active_Flags(hRS);
}
/* RX Callback */
if (( hRS->huart->RxXferCount == 0U) && RS_Is_RX_Busy(hRS) && // if all bytes are received and receive is active
hRS->huart->RxState != HAL_UART_STATE_BUSY_RX) // also check that receive "REALLY" isnt busy
RS_UART_RxCpltCallback(hRS);
/* TX Callback */
if (( hRS->huart->TxXferCount == 0U) && RS_Is_TX_Busy(hRS) && // if all bytes are transmited and transmit is active
hRS->huart->gState != HAL_UART_STATE_BUSY_TX) // also check that receive "REALLY" isnt busy
RS_UART_TxCpltCallback(hRS);
}
//----------------ERRORS HANDLER----------------
else
{
if(hRS->f.RX_Busy)
{
/* de-init uart transfer */
RS_Abort(hRS, ABORT_RS);
RS_Handle_Receive_Start(hRS, hRS->pMessagePtr);
// later, maybe, will be added specific handlers for err
}
}
}
/**
* @brief Handler for TIM.
* @param hRS - указатель на хендлер RS.
* @note Попадание сюда = таймаут и перезапуск RS приема
* Добавить вызов этой функции в TIMx_IRQHandler() после HAL_TIM_IRQHandler().
*/
void RS_TIM_Handler(RS_HandleTypeDef *hRS)
{
HAL_TIM_Base_Stop_IT(hRS->htim);
RS_Abort(hRS, ABORT_RS);
RS_Handle_Receive_Start(hRS, hRS->pMessagePtr);
}
//--------------------CALLBACK/HANDLER FUNCTIONS---------------------
//-------------------------------------------------------------------
//-------------------------------------------------------------------
//--------------WEAK PROTOTYPES FOR PROCESSING MESSAGE---------------
/**
* @brief Respond accord to received message.
* @param hRS - указатель на хендлер RS.
* @param RS_msg - указатель на структуру сообщения.
* @return RS_RES - статус о результате ответа на комманду.
* @note Обработка принятой комманды и ответ на неё.
*/
__weak RS_StatusTypeDef RS_Response(RS_HandleTypeDef *hRS, RS_MsgTypeDef *RS_msg)
{
/* Redefine function for user purposes */
return RS_ERR;
}
/**
* @brief Collect message in buffer to transmit it.
* @param hRS - указатель на хендлер RS.
* @param RS_msg - указатель на структуру сообщения.
* @param msg_uart_buff - указатель на буффер UART.
* @return RS_RES - статус о результате заполнения буфера.
* @note Заполнение буффера UART из структуры сообщения.
*/
__weak RS_StatusTypeDef RS_Collect_Message(RS_HandleTypeDef *hRS, RS_MsgTypeDef *RS_msg, uint8_t *msg_uart_buff)
{
/* Redefine function for user purposes */
return RS_ERR;
}
/**
* @brief Parse message from buffer to process it.
* @param hRS - указатель на хендлер RS.
* @param RS_msg - указатель на структуру сообщения.
* @param msg_uart_buff - указатель на буффер UART.
* @return RS_RES - статус о результате заполнения структуры.
* @note Заполнение структуры сообщения из буффера UART.
*/
__weak RS_StatusTypeDef RS_Parse_Message(RS_HandleTypeDef *hRS, RS_MsgTypeDef *RS_msg, uint8_t *msg_uart_buff)
{
/* Redefine function for user purposes */
return RS_ERR;
}
/**
* @brief Define size of RX Message that need to be received.
* @param hRS - указатель на хендлер RS.
* @param rx_data_size - указатель на переменную для записи кол-ва байт для принятия.
* @return RS_RES - статус о корректности рассчета кол-ва байт для принятия.
* @note Определение сколько байтов надо принять по протоколу.
*/
__weak RS_StatusTypeDef RS_Define_Size_of_RX_Message(RS_HandleTypeDef *hRS, uint32_t *rx_data_size)
{
/* Redefine function for user purposes */
return RS_ERR;
}
//--------------WEAK PROTOTYPES FOR PROCESSING MESSAGE---------------
//-------------------------------------------------------------------

View File

@@ -1,259 +0,0 @@
/**
**************************************************************************
* @file rs_message.h
* @brief Заголовочный файл для модуля реализации протоколов по RS/UART.
**************************************************************************
* @defgroup RS_TOOLS
* @brief Всякое для работы по UART/RS
**************************************************************************
@details
**************************************************************************
Для настройки RS/UART под нужный протокол, необходимо:
- Определить структуру сообщения RS_MsgTypeDef и
дефайны RX_FIRST_PART_SIZE и MSG_SIZE_MAX.
- Подключить этот файл в раздел rs_message.h.
- Определить функции для обработки сообщения: RS_Parse_Message(),
RS_Collect_Message(), RS_Response(), RS_Define_Size_of_RX_Message()
- Добавить UART/TIM Handler в Хендлер используемых UART/TIM.
Так же данный модуль использует счетчики
**************************************************************************
@verbatim
Визуальное описание. Форматирование сохраняется как в коде.
@endverbatim
*************************************************************************/
#ifndef __RS_LIB_H_
#define __RS_LIB_H_
#include "modbus.h"
#include "crc_algs.h"
/////////////////////////////////////////////////////////////////////
////////////////////////////---DEFINES---////////////////////////////
/* Check that all defines required by RS are defined */
#ifndef MSG_SIZE_MAX
#error Define MSG_SIZE_MAX (Maximum size of message). This is necessary to create buffer for UART.
#endif
#ifndef RX_FIRST_PART_SIZE
#error Define RX_FIRST_PART_SIZE (Size of first part of message). This is necessary to receive the first part of the message, from which determine the size of the remaining part of the message.
#endif
/* Clear message-uart buffer */
#define RS_Clear_Buff(_buff_) for(int i=0; i<MSG_SIZE_MAX;i++) _buff_[i] = NULL
/* Set/Reset flags */
#define RS_Set_Free(_hRS_) _hRS_->f.RS_Busy = 0
#define RS_Set_Busy(_hRS_) _hRS_->f.RS_Busy = 1
#define RS_Set_RX_Flags(_hRS_) _hRS_->f.RX_Busy = 1; _hRS_->f.RX_Done = 0; _hRS_->f.RX_Half = 0
#define RS_Set_RX_Active_Flags(_hRS_) _hRS_->f.RX_Ongoing = 1
#define RS_Set_TX_Flags(_hRS_) _hRS_->f.TX_Busy = 1; _hRS_->f.TX_Done = 0
#define RS_Reset_RX_Active_Flags(_hRS_) _hRS_->f.RX_Ongoing = 0
#define RS_Reset_RX_Flags(_hRS_) RS_Reset_RX_Active_Flags(_hRS_); _hRS_->f.RX_Busy = 0; _hRS_->f.RX_Done = 0; _hRS_->f.RX_Half = 0
#define RS_Reset_TX_Flags(_hRS_) _hRS_->f.TX_Busy = 0; _hRS_->f.TX_Done = 0
#define RS_Set_RX_End_Flag(_hRS_) _hRS_->f.RX_Done = 1;
#define RS_Set_TX_End_Flag(_hRS_) _hRS_->f.TX_Done = 1
#define RS_Set_RX_End(_hRS_) RS_Reset_RX_Flags(_hRS_); RS_Set_RX_End_Flag(_hRS_)
#define RS_Set_TX_End(_hRS_) RS_Reset_TX_Flags(_hRS_); RS_Set_TX_End_Flag(_hRS_)
/* Clear all RS stuff */
#define RS_Clear_All(_hRS_) RS_Clear_Buff(_hRS_->pBufferPtr); RS_Reset_RX_Flags(_hRS_); RS_Reset_TX_Flags(_hRS_);
//#define MB_Is_RX_Busy(_hRS_) ((_hRS_->huart->gState&HAL_USART_STATE_BUSY_RX) == HAL_USART_STATE_BUSY_RX)
//#define MB_Is_TX_Busy(_hRS_) ((_hRS_->huart->gState&HAL_USART_STATE_BUSY_RX) == HAL_USART_STATE_BUSY_TX)
#define RS_Is_RX_Busy(_hRS_) (_hRS_->f.RX_Busy == 1)
#define RS_Is_TX_Busy(_hRS_) (_hRS_->f.TX_Busy == 1)
#ifndef RS_EnableReceive
#define RS_EnableReceive()
#endif
#ifndef RS_EnableTransmit
#define RS_EnableTransmit()
#endif
////////////////////////////---DEFINES---////////////////////////////
/////////////////////////////////////////////////////////////////////
///////////////////////---STRUCTURES & ENUMS---//////////////////////
//------------------ENUMERATIONS--------------------
/** @brief Enums for respond CMD about RS status */
typedef enum // RS_StatusTypeDef
{
/* IN-CODE STATUS (start from 0x01, and goes up)*/
/*0x01*/ RS_OK = 0x01,
/*0x02*/ RS_ERR,
/*0x03*/ RS_ABORTED,
/*0x04*/ RS_BUSY,
/*0x05*/ RS_SKIP,
/*0x06*/ RS_COLLECT_MSG_ERR,
/*0x07*/ RS_PARSE_MSG_ERR,
// reserved values
// /*0x00*/ RS_UNKNOWN_ERR = 0x00, ///< reserved for case, if no one error founded (nothing changed response from zero)
}RS_StatusTypeDef;
/** @brief Enums for RS Modes */
typedef enum // RS_ModeTypeDef
{
SLAVE_ALWAYS_WAIT = 0x01, ///< Slave mode with infinity waiting
SLAVE_TIMEOUT_WAIT = 0x02, ///< Slave mode with waiting with timeout
// MASTER = 0x03, ///< Master mode
}RS_ModeTypeDef;
/** @brief Enums for RS UART Modes */
typedef enum // RS_ITModeTypeDef
{
BLCK_MODE = 0x00, ///< Blocking mode
IT_MODE = 0x01, ///< Interrupt mode
}RS_ITModeTypeDef;
/** @brief Enums for Abort modes */
typedef enum // RS_AbortTypeDef
{
ABORT_TX = 0x01, ///< Abort transmit
ABORT_RX = 0x02, ///< Abort receive
ABORT_RX_TX = 0x03, ///< Abort receive and transmit
ABORT_RS = 0x04, ///< Abort uart and reset RS structure
}RS_AbortTypeDef;
/** @brief Enums for RX Size modes */
typedef enum // RS_RXSizeTypeDef
{
RS_RX_Size_Const = 0x01, ///< size of receiving message is constant
RS_RX_Size_NotConst = 0x02, ///< size of receiving message isnt constant
}RS_RXSizeTypeDef;
//-----------STRUCTURE FOR HANDLE RS------------
/** @brief Struct for flags RS */
typedef struct
{
unsigned RX_Half:1; ///< flag: 0 - receiving msg before ByteCnt, 0 - receiving msg after ByteCnt
unsigned RS_Busy:1; ///< flag: 1 - RS is busy, 0 - RS isnt busy
unsigned RX_Ongoing:1; ///< flag: 1 - receiving data right now, 0 - waiting for receiving data
unsigned RX_Busy:1; ///< flag: 1 - receiving is active, 0 - receiving isnt active
unsigned TX_Busy:1; ///< flag: 1 - transmiting is active, 0 - transmiting isnt active
unsigned RX_Done:1; ///< flag: 1 - receiving is done, 0 - receiving isnt done
unsigned TX_Done:1; ///< flag: 1 - transmiting is done, 0 - transmiting isnt done
// setted by user
unsigned MessageHandled:1; ///< flag: 1 - RS command is handled, 0 - RS command isnt handled yet
unsigned EchoResponse:1; ///< flag: 1 - response with received msg, 0 - response with own msg
unsigned DeferredResponse:1; ///< flag: 1 - response not in interrupt, 0 - response in interrupt
unsigned ReInit_UART:1; ///< flag: 1 - need to reinitialize uart, 0 - nothing
}RS_FlagsTypeDef;
/**
* @brief Handle for RS communication.
* @note Prefixes: h - handle, s - settings, f - flag
*/
typedef struct // RS_HandleTypeDef
{
/* MESSAGE */
uint8_t ID; ///< ID of RS "channel"
RS_MsgTypeDef *pMessagePtr; ///< pointer to message struct
uint8_t *pBufferPtr; ///< pointer to message buffer
uint32_t RS_Message_Size; ///< size of whole message, not only data
/* HANDLERS and SETTINGS */
UART_HandleTypeDef *huart; ///< handler for used uart
TIM_HandleTypeDef *htim; ///< handler for used tim
RS_ModeTypeDef sRS_Mode; ///< setting: slave or master @ref RS_ModeTypeDef
RS_ITModeTypeDef sRS_IT_Mode; ///< setting: 1 - IT mode, 0 - Blocking mode
uint16_t sRS_Timeout; ///< setting: timeout in ms
RS_RXSizeTypeDef sRS_RX_Size_Mode; ///< setting: 1 - not const, 0 - const
/* FLAGS */
RS_FlagsTypeDef f; ///< These flags for controling receive/transmit
/* RS STATUS */
RS_StatusTypeDef RS_STATUS; ///< RS status
}RS_HandleTypeDef;
extern RS_HandleTypeDef hmodbus1;
///////////////////////---STRUCTURES & ENUMS---//////////////////////
/////////////////////////////////////////////////////////////////////
///////////////////////////---FUNCTIONS---///////////////////////////
//----------------FUNCTIONS FOR PROCESSING MESSAGE-------------------
/*--------------------Defined by users purposes--------------------*/
/* Respond accord to received message */
RS_StatusTypeDef RS_Response(RS_HandleTypeDef *hRS, RS_MsgTypeDef *RS_msg);
/* Collect message in buffer to transmit it */
RS_StatusTypeDef RS_Collect_Message(RS_HandleTypeDef *hRS, RS_MsgTypeDef *RS_msg, uint8_t *msg_uart_buff);
/* Parse message from buffer to process it */
RS_StatusTypeDef RS_Parse_Message(RS_HandleTypeDef *hRS, RS_MsgTypeDef *RS_msg, uint8_t *msg_uart_buff);
/* Define size of RX Message that need to be received */
RS_StatusTypeDef RS_Define_Size_of_RX_Message(RS_HandleTypeDef *hRS, uint32_t *rx_data_size);
//-------------------------GENERAL FUNCTIONS-------------------------
/*-----------------Should be called from main code-----------------*/
/* Start receive IT */
RS_StatusTypeDef RS_Receive_IT(RS_HandleTypeDef *hRS, RS_MsgTypeDef *RS_msg);
/* Start transmit IT */
RS_StatusTypeDef RS_Transmit_IT(RS_HandleTypeDef *hRS, RS_MsgTypeDef *RS_msg);
/* Initialize UART and handle RS stucture */
RS_StatusTypeDef RS_Init(RS_HandleTypeDef *hRS, UART_HandleTypeDef *huart, TIM_HandleTypeDef *htim, uint8_t *pRS_BufferPtr);
/* ReInitialize UART and RS receive */
HAL_StatusTypeDef RS_ReInit_UART(RS_HandleTypeDef *hRS, UART_HandleTypeDef *suart);
/* Abort RS/UART */
RS_StatusTypeDef RS_Abort(RS_HandleTypeDef *hRS, RS_AbortTypeDef AbortMode);
//-------------------------GENERAL FUNCTIONS-------------------------
//-------------------------------------------------------------------
//--------------------CALLBACK/HANDLER FUNCTIONS---------------------
/* Handle for starting receive */
RS_StatusTypeDef RS_Handle_Receive_Start(RS_HandleTypeDef *hRS, RS_MsgTypeDef *RS_msg);
/* Handle for starting transmit */
RS_StatusTypeDef RS_Handle_Transmit_Start(RS_HandleTypeDef *hRS, RS_MsgTypeDef *RS_msg);
/* UART RX Callback: define behaviour after receiving parts of message */
RS_StatusTypeDef RS_UART_RxCpltCallback(RS_HandleTypeDef *hRS);
/* UART TX Callback: define behaviour after transmiting message */
RS_StatusTypeDef RS_UART_TxCpltCallback(RS_HandleTypeDef *hRS);
/* Handler for UART */
void RS_UART_Handler(RS_HandleTypeDef *hRS);
/* Handler for TIM */
void RS_TIM_Handler(RS_HandleTypeDef *hRS);
//--------------------CALLBACK/HANDLER FUNCTIONS---------------------
///////////////////////////---FUNCTIONS---///////////////////////////
#ifndef printf_rs_err
#define printf_rs_err(...)
#endif
#ifndef printf_rs
#define printf_rs(...)
#endif
#endif // __RS_LIB_H_

View File

@@ -1,263 +0,0 @@
#MicroXplorer Configuration settings - do not modify
ADC1.Channel-0\#ChannelRegularConversion=ADC_CHANNEL_VREFINT
ADC1.ContinuousConvMode=ENABLE
ADC1.IPParameters=Rank-0\#ChannelRegularConversion,Channel-0\#ChannelRegularConversion,SamplingTime-0\#ChannelRegularConversion,NbrOfConversionFlag,ContinuousConvMode,master
ADC1.NbrOfConversionFlag=1
ADC1.Rank-0\#ChannelRegularConversion=1
ADC1.SamplingTime-0\#ChannelRegularConversion=ADC_SAMPLETIME_1CYCLE_5
ADC1.master=1
CAD.formats=
CAD.pinconfig=
CAD.provider=
CAN.CalculateBaudRate=749999
CAN.CalculateTimeBit=1333
CAN.CalculateTimeQuantum=444.44444444444446
CAN.IPParameters=CalculateTimeQuantum,CalculateTimeBit,CalculateBaudRate
File.Version=6
GPIO.groupedBy=Group By Peripherals
KeepUserPlacement=false
Mcu.CPN=STM32F103C6T6A
Mcu.Family=STM32F1
Mcu.IP0=ADC1
Mcu.IP1=CAN
Mcu.IP10=USART1
Mcu.IP2=I2C1
Mcu.IP3=NVIC
Mcu.IP4=RCC
Mcu.IP5=RTC
Mcu.IP6=SPI1
Mcu.IP7=SYS
Mcu.IP8=TIM1
Mcu.IP9=TIM2
Mcu.IPNb=11
Mcu.Name=STM32F103C(4-6)Tx
Mcu.Package=LQFP48
Mcu.Pin0=PC13-TAMPER-RTC
Mcu.Pin1=PD0-OSC_IN
Mcu.Pin10=PA7
Mcu.Pin11=PB0
Mcu.Pin12=PB1
Mcu.Pin13=PB2
Mcu.Pin14=PB10
Mcu.Pin15=PB11
Mcu.Pin16=PB12
Mcu.Pin17=PB13
Mcu.Pin18=PB14
Mcu.Pin19=PB15
Mcu.Pin2=PD1-OSC_OUT
Mcu.Pin20=PA8
Mcu.Pin21=PA9
Mcu.Pin22=PA10
Mcu.Pin23=PA11
Mcu.Pin24=PA12
Mcu.Pin25=PA13
Mcu.Pin26=PA14
Mcu.Pin27=PA15
Mcu.Pin28=PB3
Mcu.Pin29=PB4
Mcu.Pin3=PA0-WKUP
Mcu.Pin30=PB5
Mcu.Pin31=PB6
Mcu.Pin32=PB7
Mcu.Pin33=PB8
Mcu.Pin34=PB9
Mcu.Pin35=VP_ADC1_TempSens_Input
Mcu.Pin36=VP_ADC1_Vref_Input
Mcu.Pin37=VP_RTC_VS_RTC_Activate
Mcu.Pin38=VP_RTC_VS_RTC_Calendar
Mcu.Pin39=VP_SYS_VS_tim3
Mcu.Pin4=PA1
Mcu.Pin40=VP_TIM1_VS_ClockSourceINT
Mcu.Pin41=VP_TIM2_VS_ClockSourceINT
Mcu.Pin5=PA2
Mcu.Pin6=PA3
Mcu.Pin7=PA4
Mcu.Pin8=PA5
Mcu.Pin9=PA6
Mcu.PinsNb=42
Mcu.ThirdPartyNb=0
Mcu.UserConstants=
Mcu.UserName=STM32F103C6Tx
MxCube.Version=6.12.0
MxDb.Version=DB.6.0.120
NVIC.BusFault_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:false
NVIC.DebugMonitor_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:false
NVIC.ForceEnableDMAVector=true
NVIC.HardFault_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:false
NVIC.MemoryManagement_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:false
NVIC.NonMaskableInt_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:false
NVIC.PendSV_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:false
NVIC.PriorityGroup=NVIC_PRIORITYGROUP_4
NVIC.RTC_IRQn=true\:0\:0\:false\:false\:true\:true\:true\:true
NVIC.SVCall_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:false
NVIC.SysTick_IRQn=true\:15\:0\:false\:false\:true\:false\:true\:false
NVIC.TIM1_BRK_IRQn=true\:0\:0\:false\:false\:true\:true\:true\:true
NVIC.TIM1_CC_IRQn=true\:0\:0\:false\:false\:true\:true\:true\:true
NVIC.TIM1_TRG_COM_IRQn=true\:0\:0\:false\:false\:true\:true\:true\:true
NVIC.TIM1_UP_IRQn=true\:0\:0\:false\:false\:true\:true\:true\:true
NVIC.TIM2_IRQn=true\:0\:0\:false\:false\:true\:true\:true\:true
NVIC.TIM3_IRQn=true\:15\:0\:false\:false\:true\:false\:true\:true
NVIC.TimeBase=TIM3_IRQn
NVIC.TimeBaseIP=TIM3
NVIC.USART1_IRQn=true\:0\:0\:false\:false\:true\:true\:true\:true
NVIC.UsageFault_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:false
PA0-WKUP.Locked=true
PA0-WKUP.Signal=GPIO_Input
PA1.Locked=true
PA1.Signal=GPIO_Output
PA10.GPIOParameters=GPIO_Label
PA10.GPIO_Label=Relay_dc5v
PA10.Locked=true
PA10.Signal=GPIO_Output
PA11.Mode=CAN_Activate
PA11.Signal=CAN_RX
PA12.Mode=CAN_Activate
PA12.Signal=CAN_TX
PA13.Mode=Serial_Wire
PA13.Signal=SYS_JTMS-SWDIO
PA14.Mode=Serial_Wire
PA14.Signal=SYS_JTCK-SWCLK
PA15.GPIOParameters=GPIO_Label
PA15.GPIO_Label=One_wire
PA15.Locked=true
PA15.Signal=GPIO_Output
PA2.Locked=true
PA2.Signal=GPIO_Output
PA3.Locked=true
PA3.Signal=GPIO_Output
PA4.Locked=true
PA4.Signal=GPIO_Output
PA5.Locked=true
PA5.Signal=GPIO_Output
PA6.Locked=true
PA6.Signal=GPIO_Output
PA7.Locked=true
PA7.Signal=GPIO_Output
PA8.Locked=true
PA8.Signal=GPIO_Output
PA9.Locked=true
PA9.Signal=GPIO_Output
PB0.Locked=true
PB0.Signal=GPIO_Output
PB1.Locked=true
PB1.Signal=GPIO_Output
PB10.Locked=true
PB10.Signal=GPIO_Output
PB11.Locked=true
PB11.Signal=GPIO_Output
PB12.Locked=true
PB12.Signal=GPIO_Output
PB13.Locked=true
PB13.Signal=GPIO_Output
PB14.Locked=true
PB14.Signal=GPIO_Output
PB15.Locked=true
PB15.Signal=GPIO_Output
PB2.Locked=true
PB2.Signal=GPIO_Output
PB3.Mode=Full_Duplex_Master
PB3.Signal=SPI1_SCK
PB4.Mode=Full_Duplex_Master
PB4.Signal=SPI1_MISO
PB5.Mode=Full_Duplex_Master
PB5.Signal=SPI1_MOSI
PB6.Mode=Asynchronous
PB6.Signal=USART1_TX
PB7.Mode=Asynchronous
PB7.Signal=USART1_RX
PB8.Mode=I2C
PB8.Signal=I2C1_SCL
PB9.Mode=I2C
PB9.Signal=I2C1_SDA
PC13-TAMPER-RTC.Mode=RTC OUT
PC13-TAMPER-RTC.Signal=RTC_OUT
PD0-OSC_IN.Mode=HSE-External-Oscillator
PD0-OSC_IN.Signal=RCC_OSC_IN
PD1-OSC_OUT.Mode=HSE-External-Oscillator
PD1-OSC_OUT.Signal=RCC_OSC_OUT
PinOutPanel.RotationAngle=0
ProjectManager.AskForMigrate=true
ProjectManager.BackupPrevious=false
ProjectManager.CompilerOptimize=6
ProjectManager.ComputerToolchain=false
ProjectManager.CoupleFile=true
ProjectManager.CustomerFirmwarePackage=
ProjectManager.DefaultFWLocation=true
ProjectManager.DeletePrevious=true
ProjectManager.DeviceId=STM32F103C6Tx
ProjectManager.FirmwarePackage=STM32Cube FW_F1 V1.8.6
ProjectManager.FreePins=false
ProjectManager.HalAssertFull=false
ProjectManager.HeapSize=0x400
ProjectManager.KeepUserCode=true
ProjectManager.LastFirmware=true
ProjectManager.LibraryCopy=1
ProjectManager.MainLocation=Core/Src
ProjectManager.NoMain=false
ProjectManager.PreviousToolchain=
ProjectManager.ProjectBuild=false
ProjectManager.ProjectFileName=john103C6T6.ioc
ProjectManager.ProjectName=john103C6T6
ProjectManager.ProjectStructure=
ProjectManager.RegisterCallBack=
ProjectManager.StackSize=0x400
ProjectManager.TargetToolchain=MDK-ARM V5.32
ProjectManager.ToolChainLocation=
ProjectManager.UAScriptAfterPath=
ProjectManager.UAScriptBeforePath=
ProjectManager.UnderRoot=false
ProjectManager.functionlistsort=1-SystemClock_Config-RCC-false-HAL-false,2-MX_GPIO_Init-GPIO-false-HAL-true,3-MX_TIM1_Init-TIM1-false-HAL-true,4-MX_USART1_UART_Init-USART1-false-HAL-true,5-MX_TIM2_Init-TIM2-false-HAL-true,6-MX_ADC1_Init-ADC1-false-HAL-true,7-MX_CAN_Init-CAN-false-HAL-true,8-MX_I2C1_Init-I2C1-false-HAL-true,9-MX_RTC_Init-RTC-false-HAL-true,10-MX_SPI1_Init-SPI1-false-HAL-true
RCC.ADCFreqValue=12000000
RCC.ADCPresc=RCC_ADCPCLK2_DIV6
RCC.AHBFreq_Value=72000000
RCC.APB1CLKDivider=RCC_HCLK_DIV2
RCC.APB1Freq_Value=36000000
RCC.APB1TimFreq_Value=72000000
RCC.APB2Freq_Value=72000000
RCC.APB2TimFreq_Value=72000000
RCC.FCLKCortexFreq_Value=72000000
RCC.FamilyName=M
RCC.HCLKFreq_Value=72000000
RCC.IPParameters=ADCFreqValue,ADCPresc,AHBFreq_Value,APB1CLKDivider,APB1Freq_Value,APB1TimFreq_Value,APB2Freq_Value,APB2TimFreq_Value,FCLKCortexFreq_Value,FamilyName,HCLKFreq_Value,MCOFreq_Value,PLLCLKFreq_Value,PLLMCOFreq_Value,PLLMUL,PLLSourceVirtual,SYSCLKFreq_VALUE,SYSCLKSource,TimSysFreq_Value,USBFreq_Value,USBPrescaler,VCOOutput2Freq_Value
RCC.MCOFreq_Value=72000000
RCC.PLLCLKFreq_Value=72000000
RCC.PLLMCOFreq_Value=36000000
RCC.PLLMUL=RCC_PLL_MUL9
RCC.PLLSourceVirtual=RCC_PLLSOURCE_HSE
RCC.SYSCLKFreq_VALUE=72000000
RCC.SYSCLKSource=RCC_SYSCLKSOURCE_PLLCLK
RCC.TimSysFreq_Value=72000000
RCC.USBFreq_Value=48000000
RCC.USBPrescaler=RCC_USBCLKSOURCE_PLL_DIV1_5
RCC.VCOOutput2Freq_Value=8000000
RTC.IPParameters=OutPut
RTC.OutPut=RTC_OUTPUTSOURCE_SECOND
SPI1.BaudRatePrescaler=SPI_BAUDRATEPRESCALER_4
SPI1.CalculateBaudRate=18.0 MBits/s
SPI1.Direction=SPI_DIRECTION_2LINES
SPI1.IPParameters=VirtualType,Mode,Direction,BaudRatePrescaler,CalculateBaudRate
SPI1.Mode=SPI_MODE_MASTER
SPI1.VirtualType=VM_MASTER
TIM1.IPParameters=Prescaler,Period
TIM1.Period=65535
TIM1.Prescaler=0
TIM2.IPParameters=Prescaler,Period
TIM2.Period=65535
TIM2.Prescaler=7199
USART1.IPParameters=VirtualMode
USART1.VirtualMode=VM_ASYNC
VP_ADC1_TempSens_Input.Mode=IN-TempSens
VP_ADC1_TempSens_Input.Signal=ADC1_TempSens_Input
VP_ADC1_Vref_Input.Mode=IN-Vrefint
VP_ADC1_Vref_Input.Signal=ADC1_Vref_Input
VP_RTC_VS_RTC_Activate.Mode=RTC_Enabled
VP_RTC_VS_RTC_Activate.Signal=RTC_VS_RTC_Activate
VP_RTC_VS_RTC_Calendar.Mode=RTC_Calendar
VP_RTC_VS_RTC_Calendar.Signal=RTC_VS_RTC_Calendar
VP_SYS_VS_tim3.Mode=TIM3
VP_SYS_VS_tim3.Signal=SYS_VS_tim3
VP_TIM1_VS_ClockSourceINT.Mode=Internal
VP_TIM1_VS_ClockSourceINT.Signal=TIM1_VS_ClockSourceINT
VP_TIM2_VS_ClockSourceINT.Mode=Internal
VP_TIM2_VS_ClockSourceINT.Signal=TIM2_VS_ClockSourceINT
board=custom

View File

@@ -0,0 +1,78 @@
# Пины МК
Документ составлен по прошивке:
- `..\new rev\john103C8T6\john103C6T6.ioc`
- `..\new rev\john103C8T6\Core\Inc\main.h`
- `..\new rev\john103C8T6\Core\Src\gpio.c`
- `..\new rev\john103C8T6\Core\Src\usart.c`
- `..\new rev\john103C8T6\Core\Src\can.c`
- `..\new rev\john103C8T6\Core\Src\i2c.c`
- `..\new rev\john103C8T6\Core\Src\spi.c`
- `..\new rev\john103C8T6\Core\Inc\ow_port.h`
МК: `STM32F103C8Tx`, корпус `LQFP48`.
## Основные интерфейсы
| Пин МК | Функция | Настройка | Назначение в проекте |
|---|---|---|---|
| `PB6` | `USART1_TX` | AF push-pull, remap USART1 | Modbus RTU slave TX |
| `PB7` | `USART1_RX` | input, no pull, remap USART1 | Modbus RTU slave RX |
| `PA2` | `USART2_TX` | AF push-pull | Modbus RTU master TX |
| `PA3` | `USART2_RX` | input, no pull | Modbus RTU master RX |
| `PA15` | `One_wire` | GPIO, динамически input/output | Шина 1-Wire для DS18B20 |
| `PA10` | `Relay_dc5v` | GPIO output push-pull | Реле 5 В, управляется из Modbus coil `20` |
| `PC13` | GPIO output | push-pull | Светодиод/индикация, используется в `led_blink()` |
| `PA0` | GPIO input | no pull | Вход, назначение в коде не найдено |
| `PA11` | `CAN_RX` | input | CAN RX |
| `PA12` | `CAN_TX` | AF push-pull | CAN TX |
| `PB8` | `I2C1_SCL` | AF open-drain, remap I2C1 | I2C1 SCL |
| `PB9` | `I2C1_SDA` | AF open-drain, remap I2C1 | I2C1 SDA |
| `PB3` | `SPI1_SCK` | AF push-pull, remap SPI1 | SPI1 SCK |
| `PB4` | `SPI1_MISO` | input, no pull, remap SPI1 | SPI1 MISO |
| `PB5` | `SPI1_MOSI` | AF push-pull, remap SPI1 | SPI1 MOSI |
| `PA13` | `SWDIO` | Serial Wire | Отладка |
| `PA14` | `SWCLK` | Serial Wire | Отладка |
| `PD0` | `OSC_IN` | HSE oscillator | Внешний кварц |
| `PD1` | `OSC_OUT` | HSE oscillator | Внешний кварц |
## GPIO output, сконфигурированные в `MX_GPIO_Init`
| Пин МК | Начальное состояние | Комментарий |
|---|---:|---|
| `PC13` | `RESET` | Индикация, мигает при старте через `led_blink(GPIOC, 13, ...)` |
| `PA1` | `RESET` | Выход сконфигурирован, активного использования в коде не найдено |
| `PA4` | `RESET` | Выход сконфигурирован, активного использования в коде не найдено |
| `PA5` | `RESET` | Выход сконфигурирован, активного использования в коде не найдено |
| `PA6` | `RESET` | Выход сконфигурирован, активного использования в коде не найдено |
| `PA7` | `RESET` | Выход сконфигурирован, активного использования в коде не найдено |
| `PA8` | `RESET` | Выход сконфигурирован, активного использования в коде не найдено |
| `PA9` | `RESET` | Выход сконфигурирован, активного использования в коде не найдено |
| `PA10` | `RESET` | `Relay_dc5v`, в цикле main зависит от `MB_DATA.Coils.coils[1].state_val_bit.state_val_05` |
| `PA15` | `RESET` | 1-Wire, затем драйвер меняет режим пина input/output |
| `PB0` | `RESET` | Выход сконфигурирован, активного использования в коде не найдено |
| `PB1` | `RESET` | Выход сконфигурирован, активного использования в коде не найдено |
| `PB2` | `RESET` | Выход сконфигурирован, активного использования в коде не найдено |
| `PB10` | `RESET` | Выход сконфигурирован, активного использования в коде не найдено |
| `PB11` | `RESET` | Есть macro `GPIOB11_valve`, но прямой записи в `PB11` в текущем коде не найдено |
| `PB12` | `RESET` | Выход сконфигурирован, активного использования в коде не найдено |
| `PB13` | `RESET` | Выход сконфигурирован, активного использования в коде не найдено |
| `PB14` | `RESET` | Выход сконфигурирован, активного использования в коде не найдено |
| `PB15` | `RESET` | Выход сконфигурирован, активного использования в коде не найдено |
## Периферия без внешнего пина
| Периферия | Настройка | Назначение |
|---|---|---|
| `TIM1` | internal clock, period `65535`, prescaler `0` | Тайминги 1-Wire, `OW_TIM` |
| `TIM2` | internal clock, period `65535`, prescaler `7199` | Таймер Modbus slave |
| `TIM4` | internal clock, period `65535`, prescaler `7199` | Таймер Modbus master |
| `ADC1` | `ADC_CHANNEL_VREFINT` | Внутренний Vref, внешних ADC-пинов нет |
| `RTC` | LSI | Часы, доступны через Modbus-регистры |
## Замечания
- В `.ioc` пины `PA2/PA3` отмечены как GPIO output, но в актуальном `usart.c` они инициализируются как `USART2_TX/RX`. Для документации использована фактическая инициализация из исходников.
- Функция `handle_valves()` содержит запись в `GPIOC` pin `14`, но `PC14` не инициализирован в `MX_GPIO_Init()` и сама функция в основном цикле закомментирована.
- Для RS-485 direction control (`DE/RE`) отдельный GPIO в `modbus_config.h` не задан: `RS_EnableReceive()` и `RS_EnableTransmit()` закомментированы.

View File

@@ -0,0 +1,201 @@
# Modbus Map
Документ составлен по прошивке:
- `..\new rev\john103C8T6\Modbus\modbus_config.h`
- `..\new rev\john103C8T6\Modbus\modbus_data.h`
- `..\new rev\john103C8T6\Modbus\modbus_data.c`
- `..\new rev\john103C8T6\Core\Src\main.c`
- `..\new rev\john103C8T6\Core\Inc\PROJ_setup.h`
Адреса ниже указаны в 0-based формате, как они используются в прошивке. В некоторых Modbus-терминалах эти же адреса отображаются как `30001`, `40001`, `00001` и т.п. В таком терминале к адресу обычно надо прибавить `1` и выбрать нужный тип таблицы.
## Общие параметры
| Параметр | Значение |
|---|---|
| Протокол | Modbus RTU |
| Slave ID | `3` |
| Slave UART | `USART1`, `PB6 TX`, `PB7 RX` |
| Slave UART настройки | `115200`, `8N1` |
| Slave таймер | `TIM2` |
| Master UART | `USART2`, `PA2 TX`, `PA3 RX` |
| Master UART настройки | `115200`, `8N1` |
| Master таймер | `TIM4` |
| `MAX_SENSE` | `32` |
| Включенные таблицы | Coils, Holding Registers, Input Registers |
## Input Registers, function `0x04`
Базовый массив: `MB_DATA.InRegs`, адресный диапазон прошивки `0..1999`.
| Адрес | Кол-во | Имя | Тип | Описание |
|---:|---:|---|---|---|
| `0` | `32` | `sens_Temp[0..31]` | `uint16_t` | Температура DS18B20, в коде записывается как `temperature * 10`. Рекомендуется читать как `int16_t / 10.0`, если возможны отрицательные температуры |
| `32` | `968` | `reserve` | `uint16_t[]` | Резерв до адреса `999` |
| `1000` | `128` | `ID.DevAddr[32][8]` | raw bytes as registers | ROM-коды DS18B20: 32 датчика по 8 байт. Для датчика `N`: базовый регистр `1000 + N * 4` |
| `1128` | `72` | `reserve1` | `uint16_t[]` | Резерв до адреса `1199` |
| `1200` | `1` | `num_Tsens` | `uint16_t` | Количество найденных датчиков DS18B20 |
| `1201` | `1` | `rtc.hours` | `uint16_t` | Текущие часы RTC |
| `1202` | `1` | `rtc.minutes` | `uint16_t` | Текущие минуты RTC |
| `1203` | `1` | `rtc.seconds` | `uint16_t` | Текущие секунды RTC |
| `1204` | `1` | `rtc.date` | `uint16_t` | День месяца |
| `1205` | `1` | `rtc.month` | `uint16_t` | Месяц |
| `1206` | `1` | `rtc.year` | `uint16_t` | Год в формате RTC проекта |
| `1207` | `1` | `rtc.weekday` | `uint16_t` | День недели |
| `1208` | `1` | `rtc.apply` | `uint16_t` | Для input-регистров обычно `0` |
| `1209` | `1` | `rtc.status` | `uint16_t` | Статус RTC |
| `1210` | `790` | reserved | `uint16_t[]` | Адреса доступны в общем диапазоне, прикладного поля нет |
## Holding Registers, functions `0x03`, `0x06`, `0x10`
Базовый массив: `MB_DATA.HoldRegs`, адресный диапазон прошивки `0..1999`.
| Адрес | Кол-во | Имя | Тип | Описание |
|---:|---:|---|---|---|
| `0` | `32` | `set_Temp[0..31]` | `uint16_t` | Уставки температуры для датчиков. В текущем коде используются как градусы без умножения на 10 |
| `32` | `68` | `reserve` | `uint16_t[]` | Резерв до адреса `99` |
| `100` | `32` | `set_hyst[0..31]` | `uint16_t` | Гистерезис температуры для датчиков. В текущем коде используется как градусы |
| `132` | `68` | `reserve1` | `uint16_t[]` | Резерв до адреса `199` |
| `200` | `1` | `rtc.hours` | `uint16_t` | Часы для установки RTC |
| `201` | `1` | `rtc.minutes` | `uint16_t` | Минуты для установки RTC |
| `202` | `1` | `rtc.seconds` | `uint16_t` | Секунды для установки RTC |
| `203` | `1` | `rtc.date` | `uint16_t` | День месяца |
| `204` | `1` | `rtc.month` | `uint16_t` | Месяц |
| `205` | `1` | `rtc.year` | `uint16_t` | Год в формате RTC проекта |
| `206` | `1` | `rtc.weekday` | `uint16_t` | День недели |
| `207` | `1` | `rtc.apply` | `uint16_t` | Записать `1`, чтобы применить время RTC |
| `208` | `1` | `rtc.status` | `uint16_t` | Статус установки RTC |
| `209` | `1791` | reserved | `uint16_t[]` | Адреса доступны в общем диапазоне, прикладного поля нет |
RTC status:
| Значение | Имя | Описание |
|---:|---|---|
| `0` | `MB_RTC_STATUS_IDLE` | Нет операции |
| `1` | `MB_RTC_STATUS_SET_OK` | Время установлено |
| `2` | `MB_RTC_STATUS_VALUE_ERROR` | Ошибка значения времени/даты |
| `3` | `MB_RTC_STATUS_HAL_ERROR` | Ошибка HAL RTC |
## Coils, functions `0x01`, `0x05`, `0x0F`
Базовый массив: `MB_DATA.Coils`, адресный диапазон прошивки `0..999`.
| Coil address | Кол-во | Имя | Описание |
|---:|---:|---|---|
| `0` | `48` | `coils[0..2]` | Общие управляющие биты `state_val_01..state_val_16` в трех 16-битных словах |
| `20` | `1` | `coils[1].state_val_05` | Управляет `PA10 / Relay_dc5v` в основном цикле |
| `48` | `80` | `reserve_coils` | Резерв до coil `127` |
| `128` | `32` | `status_tSens[0..1]` | Статусы подключения DS18B20: `Temp1_isConnected..Temp32_isConnected` |
| `160` | `96` | `reserve_status_tSens` | Резерв до coil `255` |
| `256` | `16` | `relay_struct_on` | Расчетные биты включения реле по датчикам `Temp1..Temp16` |
| `272` | `16` | `reserve_relay_struct_on` | Резерв |
| `288` | `16` | `relay_struct_off` | Расчетные биты выключения реле по датчикам `Temp1..Temp16` |
| `304` | `80` | reserved | Резерв до coil `383` |
| `384` | `1` | `init_param` | При записи `1` прошивка применяет `set_Temp[]` и `set_hyst[]`, затем сбрасывает бит |
| `385` | `1` | `init_Tsens` | При записи `1` прошивка повторно ищет DS18B20, затем сбрасывает бит |
| `386` | `1` | `Save_Param_to_Flash` | Поле объявлено, активного использования в текущем `main.c` не найдено |
| `387` | `13` | reserved2 | Резервные биты |
| `400` | `600` | reserved | Адреса доступны в общем диапазоне, прикладного поля нет |
## Привязка температур и реле
В `value_control()` прошивка сравнивает `sens[i].temperature` с уставкой и гистерезисом:
- если `temperature < set_temp - hyst`, выставляется `relay_struct_off` для датчика `i`;
- если `temperature > set_temp + hyst`, выставляется `relay_struct_on` для датчика `i`;
- если `temperature == set_temp`, оба бита для датчика сбрасываются.
Эти расчетные биты лежат в coils `256..271` и `288..303`. Прямая аппаратная привязка этих расчетных битов к GPIO-выходам в текущем `main.c` не найдена. Прямое управление GPIO найдено только для `PA10 / Relay_dc5v` через coil `20`.
## GUI binding to the real STM project
Source project checked: `..\new rev\john103C8T6`.
The PC GUI bridge is bound to the actual STM Modbus layout from:
- `Modbus\modbus_config.h`
- `Modbus\modbus_data.h`
- `Core\Src\main.c`
- `Core\Inc\ds18b20_driver.h`
- `Core\Inc\PROJ_setup.h`
Active STM settings:
| Item | Value |
|---|---:|
| Default slave ID | `3` |
| `MAX_SENSE` in STM | `32` |
| GUI channels used | first `16` |
| STM protocol on COM | Modbus RTU |
| Optional GUI network mode | Modbus TCP gateway/device with the same register map |
GUI runtime map:
| GUI value | STM source | Modbus function | 0-based address |
|---|---|---:|---:|
| Current temperature channel `N` | `MB_DATA.InRegs.sens_Temp[N]` | `0x04` | `0 + N` |
| DS18B20 ROM ID channel `N` | `MB_DATA.InRegs.ID.DevAddr[N][8]` | `0x04` | `1000 + N * 4` |
| Sensor connected channel `N` | `MB_DATA.Coils.status_tSens` | `0x01` | `128 + N` |
| Setpoint channel `N` | `MB_DATA.HoldRegs.set_Temp[N]`, value = `degC * 10` | `0x03` / `0x06` | `0 + N` |
| Apply setpoints | `MB_DATA.Coils.init_param` | `0x05` | `384` |
| Open command/state channel `N` | `MB_DATA.Coils.relay_struct_on` | `0x01` / `0x05` | `256 + N` |
| Close command/state channel `N` | `MB_DATA.Coils.relay_struct_off` | `0x01` / `0x05` | `288 + N` |
Notes:
- GUI channel `1` uses index `N = 0`; GUI channel `16` uses index `N = 15`.
- Setpoints are written as tenths of a degree: GUI `28.5°C` -> Modbus holding value `285`; readback `285` -> GUI `28.5°C`.
- DS18B20 IDs are stored by STM as `uint8_t DevAddr[32][8]` and exposed through 16-bit input registers. The bridge restores each register in little-endian byte order to display the ROM ID correctly.
- The current STM project does not expose analog valve position or opening angle registers. GUI position/angle are therefore derived from binary relay state: open = `100% / 90°`, close = `0% / 0°`.
- `value_control()` in `Core\Src\main.c` calculates `relay_struct_on/off` from temperature, setpoint, and hysteresis. Direct manual coil writes from GUI can be overwritten by that firmware logic unless STM firmware adds a manual override register/coil.
## STM room/channel structure added for GUI
Added to Keil STM project `..\new rev\john103C8T6`.
### Input registers: room status block
Base address: `400`. One room/channel uses `18` registers. Channel `N` uses base `400 + N * 18`, where GUI channel 1 is `N = 0`.
| Offset | Field | Scale / meaning |
|---:|---|---|
| 0 | `channel` | 1-based channel number |
| 1 | `location` | numeric location code |
| 2..5 | `ds18b20_id[4]` | 8-byte DS18B20 ROM ID, little-endian bytes per register |
| 6 | `temperature_x10` | current temperature, degC * 10 |
| 7 | `setpoint_x10` | setpoint, degC * 10 |
| 8 | `hysteresis_x10` | hysteresis, degC * 10 |
| 9 | `valve_position_pct` | valve opening percent, 0..100 |
| 10 | `valve_angle_deg` | opening angle in degrees |
| 11 | `valve_angle_max_deg` | max opening angle, default 90 |
| 12 | `is_connected` | DS18B20 connected flag |
| 13 | `valve_open` | open relay/command state |
| 14 | `valve_close` | close relay/command state |
| 15 | `mode` | 0 auto, 1 manual |
| 16 | `command_state` | 0 stop, 1 open, 2 close |
| 17 | `reserved` | reserved |
### Holding registers: room control block
Base address: `300`. One room/channel uses `8` registers. Channel `N` uses base `300 + N * 8`.
| Offset | Field | Scale / meaning |
|---:|---|---|
| 0 | `setpoint_x10` | writable setpoint, degC * 10 |
| 1 | `hysteresis_x10` | writable hysteresis, degC * 10 |
| 2 | `valve_position_pct` | writable manual opening percent, 0..100 |
| 3 | `valve_angle_max_deg` | max opening angle, default 90 |
| 4 | `mode` | 0 auto, 1 manual |
| 5 | `command` | 0 stop, 1 open, 2 close |
| 6 | `location` | numeric location code |
| 7 | `apply` | write 1 to apply room setpoint/hysteresis |
Compatibility:
- Legacy `set_Temp[0..31]` at holding `0..31` is kept.
- Legacy `set_hyst[0..31]` at holding `100..131` is kept.
- Legacy coils `256..271` and `288..303` are kept.
- The Python bridge writes both the legacy map and the new room control block.

105
john103C6T6NewVer/README.md Normal file
View File

@@ -0,0 +1,105 @@
# Web GUI для датчиков температуры и клапанов
Веб-интерфейс для:
- мониторинга температур,
- установки уставок,
- ручного и автоматического управления клапанами,
- управления позицией клапана в `%`.
## Быстрый старт
1. Запустите демо backend:
```bash
python mock_server.py
```
2. Откройте страницу:
- `http://127.0.0.1:8080/index.html`
3. В поле `API endpoint` оставьте пустым для демо или укажите `http://127.0.0.1:8080`.
Если API не указан, интерфейс переходит в офлайн-режим (демо) и хранит состояние в `localStorage`.
## Привязка к вашему проекту
GUI читает и пишет данные через `API_PATHS` в `app.js`:
1. Датчики: `/api/sensors`, `/sensors`, `/api/data`, `/state`
2. Клапаны: `/api/valves`, `/valves`, `/api/data`, `/state`
3. Запись: сначала `PUT /api/*/:id`, затем `PUT /api/*` (без `:id`)
Если ваш контракт другой, правьте:
- массив `API_PATHS` в `app.js`
- функции `normalizeSensor`, `normalizeValve` в `app.js`
## Работа с COM-портом (MCU)
Для чтения с порта COM запущен `serial_bridge.py`:
```bash
python serial_bridge.py --serial-port COM3 --baudrate 115200
```
По умолчанию сервис доступен на `http://127.0.0.1:8080`.
Поддерживаемые входящие форматы с порта:
1) JSON-пакет:
```json
{"sensors":[{"id":"zone_1","value":24.5,"setpoint":28.0}], "valves":[{"id":"valve_1","mode":"auto","position":32,"targetTemp":28}]}
```
2) Текстовый формат:
```text
T1=24.5;T1_SETPOINT=28.0;V1_MODE=auto;V1_POS=32;V1_TGT=28
```
Исходящие команды от GUI (`PUT`) также отправляются в порт как JSON:
```json
{"type":"sensor","id":"zone_1","setpoint":28.0}
{"type":"valve","id":"valve_1","mode":"manual","position":50}
```
Если нужен другой протокол от/к MCU (Modbus/байт-структура), пришлите пример кадров — подгоню парсер в `serial_bridge.py`.
В GUI:
- поле `COM порт` показывает список `/api/serial/ports`;
- кнопка `Обновить порты` — принудительно перечитывает список COM;
- кнопка `Подключить` / `Отключить` — вызывает `/api/serial/connect` и `/api/serial/disconnect` в `serial_bridge.py`.
## Форматы API
### GET
- `GET /api/sensors` → массив:
```json
[
{ "id": "zone_1", "name": "Термопара 1", "value": 24.6, "setpoint": 28, "unit": "°C", "zone": "1" }
]
```
- `GET /api/valves` → массив:
```json
[
{ "id": "valve_1", "name": "Клапан 1", "zone": "1", "mode": "auto", "position": 40, "targetTemp": 28, "isOpen": true }
]
```
### PUT
- `PUT /api/sensors/{id}`:
```json
{ "setpoint": 29.5 }
```
- `PUT /api/valves/{id}`:
- ручной:
```json
{ "mode": "manual", "position": 50 }
```
- авто:
```json
{ "mode": "auto", "targetTemp": 28.0 }
```
- или отдельные поля (`mode`, `position`, `targetTemp`).
## Файлы
- `index.html` — разметка страницы
- `styles.css` — стили
- `app.js` — логика интерфейса
- `mock_server.py` — демонстрационный backend
- `serial_bridge.py` — backend для COM-порта

1640
john103C6T6NewVer/app.js Normal file
View File

@@ -0,0 +1,1640 @@
const SENSOR_COUNT = 16;
const VALVE_COUNT = 32;
const DEFAULT_OPEN_DEGREES_MAX = 90;
const CHANNEL_LOCATIONS = [
"DUO прав",
"DUO лев",
"TRIO",
"SOLO",
"ОСНОВА 7",
"ОСНОВА 6",
"ОСНОВА 5",
"ОСНОВА 4",
"ОСНОВА 3",
"ОСНОВА 2",
"ОСНОВА 1",
];
function defaultChannelLocation(index) {
return CHANNEL_LOCATIONS[index % CHANNEL_LOCATIONS.length];
}
function makeDefaultSensors() {
return Array.from({ length: SENSOR_COUNT }, (_, index) => {
const number = index + 1;
return {
id: `zone_${number}`,
name: `Датчик ${number}`,
value: 0,
setpoint: 28,
unit: "°C",
zone: String(number),
location: defaultChannelLocation(index),
ds18b20Id: `28-00-00-00-00-00-00-${number.toString(16).toUpperCase().padStart(2, "0")}`,
};
});
}
function makeDefaultValves() {
return Array.from({ length: VALVE_COUNT }, (_, index) => {
const number = index + 1;
const zone = (index % SENSOR_COUNT) + 1;
return {
id: `valve_${number}`,
name: `Клапан ${number}`,
zone: String(zone),
mode: "auto",
position: 0,
targetTemp: 28,
isOpen: false,
openDegrees: 0,
openDegreesMax: DEFAULT_OPEN_DEGREES_MAX,
};
});
}
const defaultSensors = makeDefaultSensors();
const defaultValves = makeDefaultValves();
const API_PATHS = {
sensorsRead: ["/api/sensors", "/sensors", "/api/data", "/state"],
valvesRead: ["/api/valves", "/valves", "/api/data", "/state"],
sensorWrite: [
(id) => `/api/sensors/${encodeURIComponent(id)}`,
(id) => `/sensors/${encodeURIComponent(id)}`,
() => "/api/sensors",
() => "/sensors",
],
valveWrite: [
(id) => `/api/valves/${encodeURIComponent(id)}`,
(id) => `/valves/${encodeURIComponent(id)}`,
() => "/api/valves",
() => "/valves",
],
valveCalibrate: [
(id) => `/api/valves/${encodeURIComponent(id)}/calibrate`,
(id) => `/valves/${encodeURIComponent(id)}/calibrate`,
],
valvesCalibrateAll: ["/api/valves/calibrate-all", "/api/calibration/all", "/calibration/all"],
};
const SERIAL_API_PATHS = {
ports: [
"/api/serial/ports",
"/api/ports",
"/ports",
"/serial/ports",
"/status/ports",
],
status: [
"/api/serial/status",
"/api/state",
"/state",
"/serial/status",
],
connect: [
"/api/serial/connect",
"/api/connect",
"/connect",
"/serial/connect",
],
disconnect: [
"/api/serial/disconnect",
"/api/disconnect",
"/disconnect",
"/serial/disconnect",
],
};
const state = {
sensors: [...defaultSensors],
valves: [...defaultValves],
apiBase: "",
timer: null,
};
let serialConnected = false;
let selectedPort = "";
const sensorsEl = document.getElementById("sensors");
const valvesEl = document.getElementById("valves");
const statusEl = document.getElementById("status");
const globalStatus = document.getElementById("globalStatus");
const apiInput = document.getElementById("apiBase");
const refreshBtn = document.getElementById("refreshBtn");
const saveApiBtn = document.getElementById("saveApiBtn");
const refreshPortsBtn = document.getElementById("refreshPortsBtn");
const connectPortBtn = document.getElementById("connectPortBtn");
const comPortSelect = document.getElementById("comPortSelect");
const modbusTransport = document.getElementById("modbusTransport");
const tcpHost = document.getElementById("tcpHost");
const tcpPort = document.getElementById("tcpPort");
const modbusSlaveId = document.getElementById("modbusSlaveId");
const serialStatus = document.getElementById("serialStatus");
const calibrateAllBtn = document.getElementById("calibrateAllBtn");
function clamp(value, min, max) {
return Math.max(min, Math.min(max, value));
}
function parseGuiNumber(value, fallback = 0) {
const parsed = Number(String(value ?? "").replace(",", "."));
return Number.isFinite(parsed) ? parsed : fallback;
}
function storageGet(name, fallback) {
const raw = localStorage.getItem(name);
if (!raw) return fallback;
try {
return JSON.parse(raw);
} catch {
return fallback;
}
}
function storageSet(name, value) {
localStorage.setItem(name, JSON.stringify(value));
}
function getModbusTransport() {
return (modbusTransport?.value || storageGet("modbusTransport", "rtu") || "rtu").toLowerCase();
}
function applyModbusTransportView() {
const transport = getModbusTransport();
const isTcp = transport === "tcp";
document.querySelectorAll(".rtu-field").forEach((element) => {
element.classList.toggle("hidden", isTcp);
});
document.querySelectorAll(".tcp-field").forEach((element) => {
element.classList.toggle("hidden", !isTcp);
});
if (refreshPortsBtn) {
refreshPortsBtn.disabled = isTcp;
}
if (serialStatus && !serialConnected) {
serialStatus.textContent = isTcp ? "Modbus TCP: не подключен" : "COM: не подключен";
}
}
function initModbusTransportControls() {
if (modbusTransport) {
modbusTransport.value = storageGet("modbusTransport", "rtu");
modbusTransport.addEventListener("change", () => {
storageSet("modbusTransport", modbusTransport.value);
applyModbusTransportView();
});
}
if (tcpHost) {
tcpHost.value = storageGet("tcpHost", tcpHost.value || "192.168.0.10");
tcpHost.addEventListener("change", () => storageSet("tcpHost", tcpHost.value.trim()));
}
if (tcpPort) {
tcpPort.value = storageGet("tcpPort", tcpPort.value || "502");
tcpPort.addEventListener("change", () => storageSet("tcpPort", tcpPort.value || "502"));
}
if (modbusSlaveId) {
modbusSlaveId.value = storageGet("modbusSlaveId", modbusSlaveId.value || "3");
modbusSlaveId.addEventListener("change", () => storageSet("modbusSlaveId", modbusSlaveId.value || "3"));
}
applyModbusTransportView();
}
function normalizeApiUrl(value) {
const trimmed = (value || "").trim();
if (trimmed && !/^[a-z][a-z0-9+.-]*:\/\//i.test(trimmed)) {
return normalizeApiUrl(`http://${trimmed}`);
}
if (trimmed.startsWith("http://") || trimmed.startsWith("https://")) {
try {
const parsed = new URL(trimmed);
return `${parsed.protocol}//${parsed.host}`;
} catch {
return trimmed.endsWith("/") ? trimmed.slice(0, -1) : trimmed;
}
}
return trimmed.endsWith("/") ? trimmed.slice(0, -1) : trimmed;
}
function ensureApiBase() {
if (state.apiBase) {
return state.apiBase;
}
if (window.location?.protocol?.startsWith("http") && window.location.host) {
state.apiBase = `${window.location.protocol}//${window.location.host}`;
} else {
state.apiBase = "http://127.0.0.1:8080";
}
if (apiInput) {
apiInput.value = state.apiBase;
}
storageSet("apiBase", state.apiBase);
return state.apiBase;
}
function endpoint(path) {
if (!state.apiBase) {
throw new Error("demo");
}
return `${state.apiBase}${path}`;
}
async function parseResponseBody(response) {
const body = await response.text();
if (!body) {
return {};
}
try {
return JSON.parse(body);
} catch {
return body;
}
}
async function apiGet(path) {
const response = await fetch(endpoint(path), {
method: "GET",
headers: { accept: "application/json" },
});
if (!response.ok) {
const body = await response.text();
throw new Error(`HTTP ${response.status}: ${body}`);
}
return parseResponseBody(response);
}
async function apiPut(path, payload) {
const response = await fetch(endpoint(path), {
method: "PUT",
headers: { "content-type": "application/json", accept: "application/json" },
body: JSON.stringify(payload),
});
if (!response.ok) {
const body = await response.text();
throw new Error(`HTTP ${response.status}: ${body}`);
}
return parseResponseBody(response);
}
async function apiPost(path, payload) {
const response = await fetch(endpoint(path), {
method: "POST",
headers: { "content-type": "application/json", accept: "application/json" },
body: JSON.stringify(payload),
});
if (!response.ok) {
const body = await response.text();
throw new Error(`HTTP ${response.status}: ${body}`);
}
return parseResponseBody(response);
}
function extractPorts(payload) {
if (Array.isArray(payload)) return payload;
if (Array.isArray(payload?.ports)) return payload.ports;
return [];
}
function extractSelectedPort(payload) {
if (typeof payload?.selected === "string") return payload.selected;
if (typeof payload?.port === "string") return payload.port;
return "";
}
async function apiGetFallback(paths) {
let lastError;
for (const path of paths) {
try {
return await apiGet(path);
} catch (error) {
lastError = error;
}
}
throw lastError || new Error("No available endpoint");
}
async function apiPostFallback(paths, payload) {
let lastError;
for (const path of paths) {
try {
return await apiPost(path, payload);
} catch (error) {
lastError = error;
}
}
throw lastError || new Error("No available endpoint");
}
function degreesFromPosition(position, maxDegrees = DEFAULT_OPEN_DEGREES_MAX) {
const maxValue = Number(maxDegrees) > 0 ? Number(maxDegrees) : DEFAULT_OPEN_DEGREES_MAX;
return Math.round(clamp(position, 0, 100) * maxValue / 100);
}
function positionFromDegrees(degrees, maxDegrees = DEFAULT_OPEN_DEGREES_MAX) {
const maxValue = Number(maxDegrees) > 0 ? Number(maxDegrees) : DEFAULT_OPEN_DEGREES_MAX;
return Math.round(clamp(degrees, 0, maxValue) * 100 / maxValue);
}
async function fetchComPorts() {
if (!state.apiBase) {
return { ports: [], selected: "" };
}
const payload = await apiGetFallback(SERIAL_API_PATHS.ports);
return {
ports: extractPorts(payload),
selected: extractSelectedPort(payload),
};
}
function applyPortOptions(ports, preferredPort = "") {
if (!comPortSelect) return;
const current = comPortSelect.value;
comPortSelect.innerHTML = "<option value=\"\">Порт не выбран</option>";
for (const item of ports) {
const entry = typeof item === "string" ? { device: item, description: "" } : item;
const option = document.createElement("option");
const value = entry.device || entry.port || "";
if (!value) continue;
option.value = value;
option.textContent = `${entry.description ? `${entry.description} (${value})` : value}`;
option.dataset.hwid = entry.hwid || "";
comPortSelect.appendChild(option);
}
const targetPort = preferredPort || current;
if (ports.find((item) => (typeof item === "string" ? item : item.device) === targetPort)) {
comPortSelect.value = targetPort;
} else if (current) {
comPortSelect.value = "";
}
}
async function refreshPortsLegacy(silent = false) {
const payload = await fetchComPorts();
const ports = payload?.ports || [];
applyPortOptions(ports, payload?.selected || "");
if (!silent) {
updateStatus(ports.length ? "Доступные порты обновлены" : "Порты не найдены", ports.length ? "ok" : "warn");
}
}
async function connectSelectedPortLegacyOld() {
if (!state.apiBase) {
updateStatus("Укажите API endpoint, чтобы работать с COM-портами", "warn");
return;
}
const value = comPortSelect.value;
if (!value) {
updateStatus("Выберите COM порт", "warn");
return;
}
selectedPort = value;
try {
const payload = { port: value, baud: 115200, baudrate: 115200, parity: "N", stopbits: 1, bytesize: 8, timeout: 0.3 };
await apiPostFallback(SERIAL_API_PATHS.connect, payload);
serialConnected = true;
serialStatus.textContent = `COM: подключён (${value})`;
serialStatus.className = "status status-ok";
updateStatus(`COM ${value} подключён`, "ok");
} catch (error) {
serialConnected = false;
serialStatus.textContent = "COM: ошибка подключения";
serialStatus.className = "status status-error";
updateStatus(`Ошибка подключения COM: ${error.message}`, "error");
}
}
async function disconnectPortLegacy() {
if (!state.apiBase) return;
try {
await apiPostFallback(SERIAL_API_PATHS.disconnect, {});
} catch {
// ignore
} finally {
serialConnected = false;
serialStatus.textContent = "COM: не подключён";
serialStatus.className = "status status-warn";
selectedPort = "";
}
}
function normalizeSensor(raw = {}) {
const rawId = raw.id ?? raw.sensorId ?? raw.key ?? raw.code;
const zone = String(raw.zone ?? raw.channel ?? raw.sensorZone ?? "").trim() || String(rawId ?? "").replace(/\D+/g, "");
const fallbackZone = zone ? `zone_${zone}` : "zone_1";
const id = rawId || fallbackZone;
return {
id: String(id),
name: String(raw.name ?? raw.label ?? `Термопара ${zone || 1}`),
zone: String(zone || "1"),
value: Number(raw.value ?? raw.current ?? raw.temperature ?? raw.temp ?? 0),
setpoint: Number(raw.setpoint ?? raw.target ?? raw.targetTemp ?? raw.tSet ?? 0),
unit: raw.unit ?? raw.units ?? "°C",
};
}
function normalizeValve(raw = {}) {
const rawId = raw.id ?? raw.valveId ?? raw.key ?? raw.code;
const zone = String(raw.zone ?? raw.channel ?? raw.controlZone ?? "").trim() || String(rawId ?? "").replace(/\D+/g, "");
const id = rawId || `valve_${zone || "1"}`;
const mode = String(raw.mode ?? raw.workMode ?? "auto").toLowerCase() === "manual" ? "manual" : "auto";
const maxOpenDegrees = Number(raw.openDegreesMax ?? raw.maxOpenDegrees ?? raw.degMax ?? DEFAULT_OPEN_DEGREES_MAX);
const maxDegrees = Number.isFinite(maxOpenDegrees) && maxOpenDegrees > 0 ? maxOpenDegrees : DEFAULT_OPEN_DEGREES_MAX;
let position = Number(raw.position ?? raw.pos ?? raw.percent ?? raw.value);
let openDegrees = Number(raw.openDegrees ?? raw.degree ?? raw.posDeg ?? raw.opening ?? raw.openAngle ?? raw.angle);
if (Number.isNaN(position)) {
if (Number.isNaN(openDegrees)) {
position = 0;
openDegrees = 0;
} else {
position = positionFromDegrees(openDegrees, maxDegrees);
}
} else if (Number.isNaN(openDegrees)) {
openDegrees = degreesFromPosition(position, maxDegrees);
} else {
position = positionFromDegrees(openDegrees, maxDegrees);
}
return {
id: String(id),
name: String(raw.name ?? raw.label ?? `Клапан ${zone || 1}`),
zone: String(zone || "1"),
mode,
position: clamp(position, 0, 100),
openDegrees: clamp(Math.round(openDegrees), 0, maxDegrees),
openDegreesMax: maxDegrees,
targetTemp: Number(raw.targetTemp ?? raw.targetTemperature ?? raw.setpoint ?? raw.tSet ?? 0),
isOpen: Boolean(raw.isOpen ?? raw.open ?? position > 0),
};
}
function extractCollection(payload, key) {
if (!payload) return null;
if (Array.isArray(payload)) return payload;
if (Array.isArray(payload[key])) return payload[key];
if (Array.isArray(payload.data?.[key])) return payload.data[key];
if (Array.isArray(payload.result?.[key])) return payload.result[key];
if (Array.isArray(payload.state?.[key])) return payload.state[key];
if (Array.isArray(payload.data?.[`temperature_${key}`])) return payload.data[`temperature_${key}`];
return null;
}
async function fetchCollection(paths, key, normalizer) {
let lastError;
for (const path of paths) {
try {
const payload = await apiGet(path);
const collection = extractCollection(payload, key);
if (!collection || !Array.isArray(collection)) continue;
return collection.map(normalizer);
} catch (error) {
lastError = error;
}
}
throw lastError || new Error(`No available endpoint for ${key}`);
}
async function sendWithFallback(paths, id, payload) {
let lastError;
for (const resolvePath of paths) {
try {
const route = typeof resolvePath === "function" ? resolvePath(id) : resolvePath;
return await apiPut(route, payload);
} catch (error) {
lastError = error;
}
}
throw lastError || new Error("No available write endpoint");
}
async function postWithFallback(paths, id, payload) {
let lastError;
for (const resolvePath of paths) {
try {
const route = typeof resolvePath === "function" ? resolvePath(id) : resolvePath;
return await apiPost(route, payload);
} catch (error) {
lastError = error;
}
}
throw lastError || new Error("No available write endpoint");
}
function writePayloadBase(id, type = "sensor") {
const sensor = findSensorById(id);
const valve = findValveById(id);
const entity = type === "valve" ? valve : sensor;
return {
id,
...(entity ? { zone: entity.zone, name: entity.name } : {}),
};
}
function mergeDefaults(stored, defaults, normalizer = (item) => item) {
const source = Array.isArray(stored) ? stored : [];
const byId = new Map(source.map((item) => [String(item.id), normalizer(item)]));
return defaults.map((item) => ({
...item,
...(byId.get(String(item.id)) || {}),
}));
}
function buildDemos() {
state.sensors = mergeDefaults(storageGet("sensorState", []), defaultSensors, normalizeSensor);
state.valves = mergeDefaults(storageGet("valveState", []), defaultValves, normalizeValve);
storageSet("sensorState", state.sensors);
storageSet("valveState", state.valves);
}
function updateStatus(message, type = "ok") {
globalStatus.textContent = message;
globalStatus.className = `status-${type}`;
}
function setConnectButtonText() {
if (!connectPortBtn) {
return;
}
connectPortBtn.textContent = serialConnected ? "Отключить" : "Подключить";
}
function setSerialBusyState(isBusy, message) {
if (refreshPortsBtn) {
refreshPortsBtn.disabled = isBusy;
}
if (connectPortBtn) {
connectPortBtn.disabled = isBusy;
connectPortBtn.textContent = isBusy ? "..." : (serialConnected ? "Отключить" : "Подключить");
}
if (calibrateAllBtn) {
calibrateAllBtn.disabled = isBusy || !serialConnected;
}
if (message) {
serialStatus.textContent = message;
}
}
function applySerialStateFromPayload(payload = {}) {
const connected = Boolean(payload?.connected);
const transport = String(payload?.transport || getModbusTransport()).toLowerCase();
const isTcp = transport === "tcp";
const tcpAddress = payload?.address || (payload?.host || payload?.ip ? `${payload?.host || payload?.ip}:${payload?.tcpPort || payload?.tcp_port || 502}` : "");
const port = isTcp ? (tcpAddress || payload?.port || "") : (payload?.port || payload?.selected || payload?.com || "");
serialConnected = connected;
selectedPort = connected && port ? port : "";
if (comPortSelect && selectedPort) {
comPortSelect.value = selectedPort;
}
if (serialStatus) {
if (connected && selectedPort) {
serialStatus.textContent = isTcp ? `Modbus TCP: connected (${selectedPort})` : `COM: connected (${selectedPort})`;
serialStatus.className = "status status-ok";
} else {
serialStatus.textContent = isTcp ? "Modbus TCP: disconnected" : "COM: disconnected";
serialStatus.className = "status status-warn";
}
}
if (calibrateAllBtn) {
calibrateAllBtn.disabled = !serialConnected;
}
setConnectButtonText();
storageSet("comPort", selectedPort || "");
}
async function loadState() {
if (!state.apiBase) {
buildDemos();
simulateSensorPhysics();
statusEl.textContent = "Режим: демо (без API)";
statusEl.className = "status status-warn";
globalStatus.textContent = "Демо: все изменения сохраняются в браузере";
return;
}
const [sensors, valves] = await Promise.all([
fetchCollection(API_PATHS.sensorsRead, "sensors", normalizeSensor),
fetchCollection(API_PATHS.valvesRead, "valves", normalizeValve),
]);
state.sensors = sensors;
state.valves = valves;
statusEl.textContent = "Подключено к API";
statusEl.className = "status status-ok";
globalStatus.textContent = `API подключен: ${state.apiBase}`;
}
function findSensorByZone(zone) {
return state.sensors.find((s) => String(s.zone) === String(zone));
}
function findValveByZone(zone) {
return state.valves.find((v) => String(v.zone) === String(zone));
}
function findSensorById(id) {
return state.sensors.find((s) => s.id === id);
}
function findValveById(id) {
return state.valves.find((v) => v.id === id);
}
function renderSensors() {
const sensorsRoot = document.getElementById("sensors");
if (!sensorsRoot) return;
sensorsRoot.innerHTML = "";
const sensorPanel = sensorsRoot.closest(".panel");
if (sensorPanel) {
sensorPanel.hidden = false;
const title = sensorPanel.querySelector("h2");
if (title) title.textContent = "Каналы обработки датчиков";
}
}
function renderValves() {
const separateValvesRoot = document.getElementById("valves");
if (separateValvesRoot) {
separateValvesRoot.innerHTML = "";
const separateValvesPanel = separateValvesRoot.closest(".panel");
if (separateValvesPanel) separateValvesPanel.hidden = true;
}
const valvesRoot = document.getElementById("sensors");
if (!valvesRoot) return;
valvesRoot.innerHTML = "";
const valvePanel = valvesRoot.closest(".panel");
if (valvePanel) {
valvePanel.hidden = false;
const title = valvePanel.querySelector("h2");
if (title) title.textContent = "Каналы обработки датчиков";
}
const sensorLocations = storageGet("sensorLocations", {});
state.sensors.forEach((sensor, index) => {
const channelNumber = index + 1;
const openValve = state.valves[index * 2] || {};
const closeValve = state.valves[index * 2 + 1] || {};
const valve = openValve.id ? openValve : closeValve;
const card = document.createElement("article");
card.className = "item compact-item valve-item channel-card full-channel-card";
card.dataset.id = valve.id || `valve_${channelNumber * 2 - 1}`;
const rawTemp = Number(sensor.value);
const temp = Number.isFinite(rawTemp) ? rawTemp : 0;
const tempText = Number.isFinite(rawTemp) ? temp.toFixed(1) : "--";
let setpoint = Number(valve.targetTemp ?? sensor.setpoint ?? 28);
const positionRaw = Number(valve.position ?? 0);
const position = Number.isFinite(positionRaw) ? Math.max(0, Math.min(100, Math.round(positionRaw))) : 0;
const maxDegreesRaw = Number(valve.openDegreesMax ?? DEFAULT_OPEN_DEGREES_MAX);
const maxDegrees = Number.isFinite(maxDegreesRaw) && maxDegreesRaw > 0 ? maxDegreesRaw : DEFAULT_OPEN_DEGREES_MAX;
const angleRaw = Number(valve.openDegrees ?? ((position / 100) * maxDegrees));
const openDegrees = Number.isFinite(angleRaw) ? Math.max(0, Math.min(maxDegrees, Math.round(angleRaw))) : 0;
const openActive = Boolean(openValve.isOpen || position > 0 || openDegrees > 0);
const closeActive = Boolean(closeValve.isOpen || position <= 0);
const connected = Boolean(valve.connected ?? valve.isConnected ?? sensor.connected ?? state.connected);
const tempFill = Math.max(0, Math.min(100, ((temp + 5) / 55) * 100));
const mode = valve.mode === "manual" ? "manual" : "auto";
const modeText = mode === "manual" ? "ручной" : "авто";
const sensorName = sensor.name || `Датчик ${channelNumber}`;
const sensorId = sensor.id || `zone_${channelNumber}`;
const setpointDrafts = storageGet("setpointDrafts", {});
const draftValue = setpointDrafts[sensorId] ?? setpointDrafts[valve.id];
if (draftValue !== undefined) {
setpoint = parseGuiNumber(draftValue, setpoint);
}
const ds18b20Id = sensor.ds18b20Id || sensor.romId || sensor.rom || sensor.address || "--";
const location = sensorLocations[sensorId] || sensor.location || defaultChannelLocation(index);
const locationOptions = CHANNEL_LOCATIONS.map((name) => (
`<option value="${name}" ${name === location ? "selected" : ""}>${name}</option>`
)).join("");
const openValveId = openValve.id || `valve_${channelNumber * 2 - 1}`;
const closeValveId = closeValve.id || `valve_${channelNumber * 2}`;
const openHex = (Number(String(openValveId).replace(/\D/g, "")) || channelNumber * 2 - 1).toString(16).toUpperCase().padStart(2, "0");
const closeHex = (Number(String(closeValveId).replace(/\D/g, "")) || channelNumber * 2).toString(16).toUpperCase().padStart(2, "0");
const setpointText = Number.isFinite(setpoint) ? setpoint.toFixed(1) : "--";
const delta = Number.isFinite(rawTemp) && Number.isFinite(setpoint) ? temp - setpoint : NaN;
const deltaText = Number.isFinite(delta) ? `${delta > 0 ? "+" : ""}${delta.toFixed(1)}°C` : "--";
const deltaClass = !Number.isFinite(delta) || Math.abs(delta) <= 0.5 ? "ok" : delta > 0 ? "hot" : "cold";
const stateText = openActive ? "открытие" : closeActive ? "закрытие" : "стоп";
card.innerHTML = `
<div class="channel-head">
<div class="channel-title">
<strong>Канал ${channelNumber}</strong>
<small>${sensorName} · ${location} · зона ${sensor.zone || channelNumber}</small>
</div>
<span>связь <i class="channel-lamp ${connected ? "on" : "alarm"}"></i></span>
</div>
<div class="channel-id-grid full-channel-id-grid">
<label>уставка
<input class="targetTemp" type="number" step="0.5" value="${setpoint}">
</label>
<label>Расположение
<select class="sensorLocation" data-id="${sensorId}">
${locationOptions}
</select>
</label>
<label>ID DS18B20
<input readonly value="${ds18b20Id}">
</label>
</div>
<div class="channel-body full-channel-body">
<div class="temperature-widget" aria-label="Температура канала ${channelNumber}">
<div class="temp-scale">
<span>50</span><span>40</span><span>30</span><span>20</span><span>10</span><span>0</span><span>-5</span>
</div>
<div class="temp-bar"><b style="height: ${tempFill}%"></b></div>
<div class="temp-now">${tempText}°C</div>
</div>
<div class="channel-workarea">
<div class="top-metrics-row">
<div class="angle-panel">
<span>угол открытия</span>
<strong>${openDegrees}°</strong>
<small>максимум ${Math.round(maxDegrees)}°</small>
</div>
</div>
<div class="channel-data-grid full-channel-data-grid">
<div><span>температура</span><strong>${tempText}°C</strong></div>
<div><span>уставка</span><strong>${setpointText}°C</strong></div>
<div><span>отклонение</span><strong class="delta ${deltaClass}">${deltaText}</strong></div>
<div><span>расположение</span><strong>${location}</strong></div>
<div><span>ID DS18B20</span><strong>${ds18b20Id}</strong></div>
<div><span>режим</span><strong>${modeText}</strong></div>
<div><span>угол/max</span><strong>${openDegrees}° / ${Math.round(maxDegrees)}°</strong></div>
<div><span>команда</span><strong>${stateText}</strong></div>
<div><span>связь</span><strong>${connected ? "есть" : "нет"}</strong></div>
<div><span>канал</span><strong>${channelNumber}</strong></div>
</div>
<label class="range-control channel-position">положение заслонки
<input class="position" type="range" min="0" max="100" value="${position}">
<strong>${position}%</strong>
</label>
<div class="valve-state-row full-state-row">
<span><i class="channel-lamp ${openActive ? "on" : "off"}"></i> клапан откр ${channelNumber}</span>
<span><i class="channel-lamp ${closeActive ? "on" : "off"}"></i> клапан закр ${channelNumber}</span>
</div>
<div class="channel-actions">
<button class="quickPosition" data-position="100" type="button">откр ${channelNumber}</button>
<button class="quickPosition" data-position="0" type="button">закр ${channelNumber}</button>
</div>
<div class="channel-actions channel-mode-line">
<div class="toggle channel-mode">
<button class="modeBtn valveAuto ${mode === "auto" ? "active" : ""}" data-mode="auto" type="button">авто</button>
<button class="modeBtn valveManual ${mode === "manual" ? "active" : ""}" data-mode="manual" type="button">ручное</button>
</div>
<button class="applyTarget mini-btn" type="button">SP</button>
<button class="applyManual mini-btn" type="button">OK</button>
<button class="calibrateValve mini-btn" type="button">CAL</button>
</div>
</div>
</div>
`;
valvesRoot.appendChild(card);
});
}
function render() {
renderSensors();
renderValves();
}
async function applySetpoint(sensorId) {
const sensor = findSensorById(sensorId);
const input = document.querySelector(`.setpoint[data-id="${sensorId}"]`);
const value = Number(input.value);
if (Number.isNaN(value)) {
updateStatus("Некорректное значение уставки", "warn");
return;
}
if (!state.apiBase) {
sensor.setpoint = value;
storageSet("sensorState", state.sensors);
render();
updateStatus(`Демо: уставка ${sensor.name} = ${value.toFixed(1)} °C`, "ok");
return;
}
const payload = {
...writePayloadBase(sensorId, "sensor"),
setpoint: value,
id: sensorId,
};
try {
await sendWithFallback(API_PATHS.sensorWrite, sensorId, payload);
await loadState();
render();
updateStatus(`Уставка ${sensor.name} обновлена`, "ok");
} catch (error) {
updateStatus(`Ошибка уставки ${sensor.name}: ${error.message}`, "error");
}
}
async function applyValveMode(valveId, mode) {
const valve = findValveById(valveId);
if (!valve) return;
valve.mode = mode;
if (!state.apiBase) {
storageSet("valveState", state.valves);
render();
updateStatus(`Демо: ${valve.name} → ${mode}`, "ok");
return;
}
const payload = {
...writePayloadBase(valveId, "valve"),
mode,
id: valveId,
};
try {
await sendWithFallback(API_PATHS.valveWrite, valveId, payload);
await loadState();
render();
updateStatus(`Режим ${valve.name}: ${mode}`, "ok");
} catch (error) {
updateStatus(`Ошибка режима ${valve.name}: ${error.message}`, "error");
await loadState();
render();
}
}
async function applyValveTarget(valveId) {
const valve = findValveById(valveId);
const input = document.querySelector(`.targetTemp[data-id="${valveId}"]`);
const value = Number(input.value);
if (Number.isNaN(value)) {
updateStatus("Некорректная целевая температура", "warn");
return;
}
if (!state.apiBase) {
valve.targetTemp = value;
storageSet("valveState", state.valves);
updateStatus(`Демо: цель ${valve.name} = ${value.toFixed(1)} °C`, "ok");
return;
}
const payload = {
...writePayloadBase(valveId, "valve"),
targetTemp: value,
id: valveId,
};
try {
await sendWithFallback(API_PATHS.valveWrite, valveId, payload);
await loadState();
render();
updateStatus(`Целевая температура ${valve.name} обновлена`, "ok");
} catch (error) {
updateStatus(`Ошибка цели ${valve.name}: ${error.message}`, "error");
}
}
async function applyValvePosition(valveId) {
const valve = findValveById(valveId);
const input = document.querySelector(`.position[data-id="${valveId}"]`);
const value = Number(input.value);
if (Number.isNaN(value)) {
updateStatus("Некорректная позиция клапана", "warn");
return;
}
valve.position = clamp(Math.round(value), 0, 100);
valve.openDegrees = degreesFromPosition(valve.position, valve.openDegreesMax);
valve.isOpen = valve.position > 0;
if (!state.apiBase) {
storageSet("valveState", state.valves);
render();
updateStatus(`Демо: ручная позиция ${valve.name} = ${value}%`, "ok");
return;
}
const payload = {
...writePayloadBase(valveId, "valve"),
mode: "manual",
position: valve.position,
openDegrees: valve.openDegrees,
openDegreesMax: valve.openDegreesMax,
id: valveId,
};
try {
await sendWithFallback(API_PATHS.valveWrite, valveId, payload);
await loadState();
render();
updateStatus(`Позиция ${valve.name} обновлена`, "ok");
} catch (error) {
updateStatus(`Ошибка позиции ${valve.name}: ${error.message}`, "error");
}
}
async function calibrateValve(valveId) {
const valve = findValveById(valveId);
if (!valve) return;
if (!state.apiBase) {
valve.position = 0;
valve.openDegrees = 0;
valve.isOpen = false;
storageSet("valveState", state.valves);
render();
updateStatus(`Демо: калибровка ${valve.name} выполнена`, "ok");
return;
}
try {
const response = await postWithFallback(API_PATHS.valveCalibrate, valveId, {});
const updated = response?.valve || response;
if (updated && updated.id) {
const index = state.valves.findIndex((item) => item.id === valveId);
if (index !== -1) {
state.valves[index] = normalizeValve(updated);
} else {
await loadState();
}
} else {
await loadState();
}
render();
updateStatus(`Калибровка ${valve.name} выполнена`, "ok");
} catch (error) {
updateStatus(`Ошибка калибровки ${valve.name}: ${error.message}`, "error");
}
}
async function calibrateAllValves(silent = false) {
if (!state.apiBase) {
state.valves = state.valves.map((valve) => ({
...valve,
position: 0,
openDegrees: 0,
isOpen: false,
}));
render();
if (!silent) {
updateStatus("Демо: калибровка всех клапанов выполнена", "ok");
}
return;
}
try {
const response = await apiPostFallback(API_PATHS.valvesCalibrateAll, {});
const payload = Array.isArray(response?.valves) ? response.valves : null;
if (payload) {
state.valves = payload.map(normalizeValve);
} else {
await loadState();
}
render();
if (!silent) {
updateStatus("Калибровка всех клапанов выполнена", "ok");
}
} catch (error) {
if (!silent) {
updateStatus(`Ошибка калибровки всех клапанов: ${error.message}`, "error");
}
}
}
function simulateSensorPhysics() {
if (state.timer) clearInterval(state.timer);
state.timer = setInterval(() => {
for (const sensor of state.sensors) {
const valve = findValveByZone(sensor.zone);
const v = valve || {};
let target;
if (v.mode === "manual") {
target = 20 + (clamp(v.position ?? 0, 0, 100) / 100) * 70;
} else {
target = v.targetTemp ?? sensor.setpoint ?? 30;
}
const drift = target - sensor.value;
const noise = (Math.random() - 0.5) * 0.2;
sensor.value = clamp(sensor.value + drift * 0.08 + noise, -40, 150);
sensor.value = Number(sensor.value.toFixed(2));
}
for (const valve of state.valves) {
const maxOpenDegrees = Number(valve.openDegreesMax) > 0 ? Number(valve.openDegreesMax) : DEFAULT_OPEN_DEGREES_MAX;
valve.openDegrees = Math.round(degreesFromPosition(valve.position ?? 0, maxOpenDegrees));
valve.isOpen = (valve.position ?? 0) > 0;
}
storageSet("sensorState", state.sensors);
storageSet("valveState", state.valves);
render();
}, 2500);
}
function attachEvents() {
refreshBtn.addEventListener("click", () => {
const url = normalizeApiUrl(apiInput.value);
state.apiBase = url;
storageSet("apiBase", state.apiBase);
refreshAll(true);
refreshPorts(false);
});
refreshPortsBtn.addEventListener("click", () => {
refreshPorts();
});
connectPortBtn.addEventListener("click", async () => {
if (serialConnected) {
await disconnectPort();
setConnectButtonText();
return;
}
await connectSelectedPort();
setConnectButtonText();
});
if (calibrateAllBtn) {
calibrateAllBtn.addEventListener("click", () => {
calibrateAllValves(false);
});
}
saveApiBtn.addEventListener("click", () => {
const url = normalizeApiUrl(apiInput.value);
state.apiBase = url;
storageSet("apiBase", url);
if (!url) {
updateStatus("API отключён; переход в демо", "warn");
statusEl.textContent = "Режим: демо (без API)";
statusEl.className = "status status-warn";
} else {
updateStatus(`Сохранён API: ${state.apiBase}`, "ok");
statusEl.textContent = "Сохранён адрес API";
statusEl.className = "status status-ok";
}
render();
refreshPorts(false);
if (!url) {
serialStatus.textContent = "COM: не подключён";
serialStatus.className = "status status-warn";
connectPortBtn.textContent = "Подключить";
selectedPort = "";
serialConnected = false;
}
});
sensorsEl.addEventListener("click", (event) => {
const target = event.target;
if (target.classList.contains("applySetpoint")) {
applySetpoint(target.dataset.id);
}
});
valvesEl.addEventListener("click", (event) => {
const target = event.target;
if (target.classList.contains("modeBtn")) {
const button = target.closest(".toggle");
const valveId = button.dataset.id;
const mode = target.dataset.mode;
const card = button.closest(".item");
if (!card) return;
const autoBlock = card.querySelector(".valveAuto");
const manualBlock = card.querySelector(".valveManual");
const applyManualBtn = card.querySelector(".applyManual");
button.querySelectorAll(".modeBtn").forEach((b) => b.classList.remove("active"));
target.classList.add("active");
if (mode === "auto") {
autoBlock.classList.remove("hidden");
manualBlock.classList.add("hidden");
applyManualBtn.classList.add("hidden");
} else {
autoBlock.classList.add("hidden");
manualBlock.classList.remove("hidden");
applyManualBtn.classList.remove("hidden");
}
applyValveMode(valveId, mode);
}
if (target.classList.contains("applyTarget")) {
applyValveTarget(target.dataset.id);
}
if (target.classList.contains("applyManual")) {
applyValvePosition(target.dataset.id);
}
if (target.classList.contains("calibrateValve")) {
calibrateValve(target.dataset.id);
}
});
valvesEl.addEventListener("input", (event) => {
const target = event.target;
if (target.classList.contains("position")) {
const label = target.closest("label");
const span = label ? label.querySelector("strong") : null;
if (span) span.textContent = `${target.value}%`;
}
});
}
async function refreshAll(silent = false) {
try {
await loadState();
render();
if (!silent) updateStatus("Данные обновлены", "ok");
} catch (error) {
if (state.apiBase) {
statusEl.textContent = `Ошибка API: ${error.message}`;
statusEl.className = "status status-error";
globalStatus.textContent = "Не удалось получить данные с API. Откат в демо";
globalStatus.className = "status-warn";
await refreshPorts();
render();
} else {
updateStatus(`Демо инициализирован: ${error.message}`, "warn");
}
}
}
async function connectSelectedPortLegacy() {
if (!state.apiBase) {
updateStatus("Укажите API endpoint для работы с COM-портами", "warn");
return;
}
const value = comPortSelect.value;
if (!value) {
updateStatus("Выберите COM порт", "warn");
return;
}
const payload = { port: value, baud: 115200, baudrate: 115200, parity: "N", stopbits: 1, bytesize: 8, timeout: 0.3 };
try {
await apiPostFallback(SERIAL_API_PATHS.connect, payload);
selectedPort = value;
serialConnected = true;
storageSet("comPort", value);
serialStatus.textContent = `COM: подключен (${value})`;
serialStatus.className = "status status-ok";
connectPortBtn.textContent = "Отключить";
updateStatus(`COM ${value} подключен`, "ok");
} catch (error) {
serialConnected = false;
serialStatus.textContent = "COM: ошибка подключения";
serialStatus.className = "status status-error";
connectPortBtn.textContent = "Подключить";
storageSet("comPort", "");
selectedPort = "";
updateStatus(`Ошибка подключения COM: ${error.message}`, "error");
}
}
async function disconnectPortLegacy() {
if (!state.apiBase) return;
try {
await apiPostFallback(SERIAL_API_PATHS.disconnect, {});
} catch {
// ignore
} finally {
serialConnected = false;
selectedPort = "";
storageSet("comPort", "");
serialStatus.textContent = "COM: не подключен";
serialStatus.className = "status status-warn";
connectPortBtn.textContent = "Подключить";
}
}
async function restoreSerialUiLegacy() {
if (!state.apiBase) return;
try {
const status = await apiGetFallback(SERIAL_API_PATHS.status);
serialConnected = Boolean(status?.connected);
const port = status?.port || status?.selected;
if (serialConnected && port) {
selectedPort = port;
comPortSelect.value = selectedPort;
serialStatus.textContent = `COM: подключен (${selectedPort})`;
serialStatus.className = "status status-ok";
connectPortBtn.textContent = "Отключить";
storageSet("comPort", selectedPort);
} else {
selectedPort = "";
storageSet("comPort", "");
serialStatus.textContent = "COM: не подключен";
serialStatus.className = "status status-warn";
connectPortBtn.textContent = "Подключить";
}
} catch {
// no-op
}
}
async function refreshPorts(silent = false) {
if (!state.apiBase) {
ensureApiBase();
}
if (!state.apiBase) {
if (!silent) {
updateStatus("Set API base URL first", "warn");
}
return;
}
setSerialBusyState(true, "Scanning COM ports...");
try {
const payload = await fetchComPorts();
const ports = Array.isArray(payload?.ports) ? payload.ports : [];
const preferredPort = payload?.selected || selectedPort || storageGet("comPort", "");
applyPortOptions(ports, preferredPort);
if (!silent) {
updateStatus(
ports.length ? `Found COM ports: ${ports.length}` : "No COM ports found",
ports.length ? "ok" : "warn"
);
}
} catch (error) {
applyPortOptions([], "");
updateStatus(`Port scan error: ${error.message}`, "error");
} finally {
setSerialBusyState(false);
}
}
async function connectSelectedPort() {
if (!state.apiBase) {
updateStatus("Set API base URL first", "warn");
return;
}
const requestedPort = comPortSelect.value;
if (!requestedPort) {
updateStatus("Select COM port", "warn");
return;
}
setSerialBusyState(true, `Connecting ${requestedPort}...`);
try {
const payload = {
port: requestedPort,
baud: 115200,
baudrate: 115200,
parity: "N",
stopBits: 1,
stopbits: 1,
byteSize: 8,
bytesize: 8,
timeout: 0.3,
};
const status = await apiPostFallback(SERIAL_API_PATHS.connect, payload);
applySerialStateFromPayload({
connected: true,
port: status?.port || requestedPort,
selected: status?.selected || requestedPort,
});
await calibrateAllValves(true);
updateStatus(`COM ${requestedPort} connected`, "ok");
await refreshPorts(true);
} catch (error) {
applySerialStateFromPayload({ connected: false });
updateStatus(`COM connect error: ${error.message}`, "error");
} finally {
setSerialBusyState(false);
}
}
async function connectRtuPort() {
if (!state.apiBase) {
updateStatus("Укажи API endpoint для Modbus RTU", "warn");
return;
}
const value = comPortSelect?.value || selectedPort;
if (!value) {
updateStatus("Выберите COM порт", "warn");
return;
}
const unitId = Number(modbusSlaveId?.value || 3);
storageSet("modbusTransport", "rtu");
storageSet("comPort", value);
storageSet("modbusSlaveId", String(unitId));
setSerialBusyState(true, `Modbus RTU: подключение ${value}, slave ${unitId}...`);
try {
const status = await apiPostFallback(SERIAL_API_PATHS.connect, {
transport: "rtu",
mode: "rtu",
port: value,
baud: 115200,
baudrate: 115200,
parity: "N",
stopbits: 1,
bytesize: 8,
timeout: 0.8,
unitId,
slaveId: unitId,
});
applySerialStateFromPayload({
...(status || {}),
connected: Boolean(status?.connected ?? status?.ok),
transport: "rtu",
port: value,
});
updateStatus(`Modbus RTU connected: ${value}, slave ${unitId}`, "ok");
} catch (error) {
applySerialStateFromPayload({ connected: false, transport: "rtu" });
updateStatus(`Modbus RTU error: ${error.message}`, "error");
} finally {
setSerialBusyState(false);
applyModbusTransportView();
}
}
async function connectTcpPort() {
if (!state.apiBase) {
updateStatus("Укажи API endpoint для Modbus TCP", "warn");
return;
}
const host = (tcpHost?.value || "").trim();
const port = Number(tcpPort?.value || 502);
const unitId = Number(modbusSlaveId?.value || 3);
if (!host) {
updateStatus("Укажи IP адрес Modbus TCP", "warn");
return;
}
if (!Number.isInteger(port) || port < 1 || port > 65535) {
updateStatus("Некорректный TCP порт", "warn");
return;
}
storageSet("modbusTransport", "tcp");
storageSet("tcpHost", host);
storageSet("tcpPort", String(port));
storageSet("modbusSlaveId", String(unitId));
setSerialBusyState(true, `Modbus TCP: подключение ${host}:${port}, slave ${unitId}...`);
try {
const status = await apiPostFallback(SERIAL_API_PATHS.connect, {
transport: "tcp",
mode: "tcp",
host,
ip: host,
tcpPort: port,
tcp_port: port,
port,
unitId,
slaveId: unitId,
timeout: 0.8,
});
applySerialStateFromPayload({
...(status || {}),
connected: Boolean(status?.connected ?? status?.ok),
transport: "tcp",
host,
tcpPort: port,
address: `${host}:${port}`,
});
updateStatus(`Modbus TCP connected: ${host}:${port}, slave ${unitId}`, "ok");
} catch (error) {
applySerialStateFromPayload({ connected: false, transport: "tcp" });
updateStatus(`Modbus TCP error: ${error.message}`, "error");
} finally {
setSerialBusyState(false);
applyModbusTransportView();
}
}
if (connectPortBtn) {
connectPortBtn.addEventListener("click", async (event) => {
event.preventDefault();
event.stopImmediatePropagation();
if (serialConnected) {
await disconnectPort();
setConnectButtonText();
applyModbusTransportView();
return;
}
if (getModbusTransport() === "tcp") {
await connectTcpPort();
} else {
await connectRtuPort();
}
setConnectButtonText();
}, true);
}
async function disconnectPort() {
if (!state.apiBase) {
applySerialStateFromPayload({ connected: false });
return;
}
setSerialBusyState(true, "Disconnecting...");
try {
const status = await apiPostFallback(SERIAL_API_PATHS.disconnect, {});
applySerialStateFromPayload(status || { connected: false });
} catch {
// ignore
} finally {
applySerialStateFromPayload({ connected: false });
setSerialBusyState(false);
}
}
async function restoreSerialUi() {
if (!state.apiBase) {
return;
}
try {
const status = await apiGetFallback(SERIAL_API_PATHS.status);
applySerialStateFromPayload(status);
if (status?.connected) {
await calibrateAllValves(true);
}
} catch {
applySerialStateFromPayload({ connected: false });
}
}
// Channel location selector
document.addEventListener("change", (event) => {
const select = event.target.closest(".sensorLocation");
if (!select) return;
const sensorId = select.dataset.id;
const sensor = state.sensors.find((item) => item.id === sensorId);
if (sensor) {
sensor.location = select.value;
storageSet("sensorState", state.sensors);
}
const locations = storageGet("sensorLocations", {});
locations[sensorId] = select.value;
storageSet("sensorLocations", locations);
render();
});
// Controls inside sensor processing channel cards
document.addEventListener("input", (event) => {
const targetInput = event.target.closest(".full-channel-card .targetTemp");
if (targetInput) {
const card = targetInput.closest(".full-channel-card");
const valveId = card?.dataset.id;
const targetTemp = parseGuiNumber(targetInput.value, 0);
const valve = state.valves.find((item) => item.id === valveId);
if (valve) {
valve.targetTemp = targetTemp;
}
const valveNumber = Number(String(valveId || "").replace(/\D/g, "")) || 1;
const sensorIndex = Math.max(0, Math.floor((valveNumber - 1) / 2));
const sensor = state.sensors[sensorIndex];
if (sensor) {
sensor.setpoint = targetTemp;
}
const setpointDrafts = storageGet("setpointDrafts", {});
if (sensor?.id) {
setpointDrafts[sensor.id] = targetInput.value;
}
if (valveId) {
setpointDrafts[valveId] = targetInput.value;
}
storageSet("setpointDrafts", setpointDrafts);
storageSet("sensorState", state.sensors);
storageSet("valveState", state.valves);
return;
}
const positionInput = event.target.closest(".full-channel-card .position");
if (!positionInput) return;
const label = positionInput.closest("label");
const value = Number(positionInput.value || 0);
const strong = label?.querySelector("strong");
if (strong) strong.textContent = `${value}%`;
});
document.addEventListener("click", async (event) => {
const button = event.target.closest(".full-channel-card button");
if (!button) return;
const card = button.closest(".full-channel-card");
const valveId = card?.dataset.id;
if (!card || !valveId) return;
if (button.classList.contains("modeBtn")) {
const mode = button.dataset.mode === "manual" ? "manual" : "auto";
card.querySelectorAll(".modeBtn").forEach((item) => item.classList.remove("active"));
button.classList.add("active");
const valve = state.valves.find((item) => item.id === valveId);
if (valve) valve.mode = mode;
storageSet("valveState", state.valves);
await sendWithFallback(API_PATHS.valveWrite, valveId, {
...writePayloadBase(valveId, "valve"),
id: valveId,
mode,
});
return;
}
if (button.classList.contains("applyTarget")) {
const targetInput = card.querySelector(".targetTemp");
const targetTemp = parseGuiNumber(targetInput?.value, 0);
const valve = state.valves.find((item) => item.id === valveId);
if (valve) valve.targetTemp = targetTemp;
const valveNumber = Number(String(valveId || "").replace(/\D/g, "")) || 1;
const sensorIndex = Math.max(0, Math.floor((valveNumber - 1) / 2));
const sensor = state.sensors[sensorIndex];
if (sensor) sensor.setpoint = targetTemp;
const setpointDrafts = storageGet("setpointDrafts", {});
if (sensor?.id) {
setpointDrafts[sensor.id] = targetInput?.value ?? String(targetTemp);
}
setpointDrafts[valveId] = targetInput?.value ?? String(targetTemp);
storageSet("setpointDrafts", setpointDrafts);
storageSet("sensorState", state.sensors);
storageSet("valveState", state.valves);
await sendWithFallback(API_PATHS.valveWrite, valveId, {
...writePayloadBase(valveId, "valve"),
id: valveId,
targetTemp,
});
await loadState();
return;
}
if (button.classList.contains("applyManual")) {
const positionInput = card.querySelector(".position");
const position = Number(positionInput?.value || 0);
const valve = state.valves.find((item) => item.id === valveId);
if (valve) {
valve.position = position;
valve.isOpen = position > 0;
}
storageSet("valveState", state.valves);
await sendWithFallback(API_PATHS.valveWrite, valveId, {
...writePayloadBase(valveId, "valve"),
id: valveId,
position,
});
await loadState();
return;
}
if (button.classList.contains("calibrateValve")) {
await postWithFallback(API_PATHS.valveCalibrate, valveId, {
...writePayloadBase(valveId, "valve"),
id: valveId,
});
await loadState();
}
});
// Quick manual open/close buttons for channel cards
document.addEventListener("click", (event) => {
const quickButton = event.target.closest(".quickPosition");
if (!quickButton) return;
const card = quickButton.closest(".valve-item");
if (!card) return;
const manualButton = card.querySelector(".valveManual");
if (manualButton && !manualButton.classList.contains("active")) {
manualButton.click();
}
const positionInput = card.querySelector(".position");
if (positionInput) {
positionInput.value = quickButton.dataset.position || "0";
positionInput.dispatchEvent(new Event("input", { bubbles: true }));
}
const applyButton = card.querySelector(".applyManual");
if (applyButton) applyButton.click();
});
window.addEventListener("load", async () => {
apiInput.value = storageGet("apiBase", "");
state.apiBase = normalizeApiUrl(apiInput.value);
initModbusTransportControls();
ensureApiBase();
selectedPort = storageGet("comPort", "");
attachEvents();
await refreshAll(true);
if (getModbusTransport() !== "tcp") {
await refreshPorts(true);
}
render();
if (selectedPort) {
comPortSelect.value = selectedPort;
}
await restoreSerialUi();
setInterval(() => {
if (state.apiBase) {
loadState().then(render).catch(() => {});
}
}, 3000);
});

View File

@@ -0,0 +1,72 @@
<!doctype html>
<html lang="ru">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Тепло и клапаны — управление</title>
<link rel="stylesheet" href="styles.css?v=20260625-ds18b20-id-1" />
</head>
<body>
<div class="shell">
<header class="header">
<h1>Панель температуры и клапанов</h1>
<p>Мониторинг датчиков, управление уставками и ручным/авто управлением клапанов.</p>
</header>
<section class="panel">
<label for="apiBase">API endpoint</label>
<div class="api-row">
<input id="apiBase" placeholder="http://127.0.0.1:1923 (пусто = демо)" value="" />
<button id="refreshBtn">Обновить</button>
<button id="saveApiBtn">Сохранить адрес API</button>
<span id="status" class="status">Режим: не подключен</span>
</div>
<p class="hint">Если API не задан, интерфейс работает в автономном демо-режиме с локальным хранением.</p>
<div class="serial-block">
<div class="serial-row">
<label for="modbusTransport">Обмен</label>
<select id="modbusTransport">
<option value="rtu">Modbus RTU / COM</option>
<option value="tcp">Modbus TCP / IP</option>
</select>
<label for="modbusSlaveId">Slave ID</label>
<input id="modbusSlaveId" type="number" min="1" max="247" value="3">
</select>
<label class="rtu-field" for="comPortSelect">COM порт</label>
<select id="comPortSelect" class="rtu-field">
<option value="">Порт не выбран</option>
</select>
<button id="refreshPortsBtn" class="rtu-field">Обновить порты</button>
<label class="tcp-field hidden" for="tcpHost">IP</label>
<input id="tcpHost" class="tcp-field hidden" type="text" value="192.168.0.10" placeholder="192.168.0.10">
<label class="tcp-field hidden" for="tcpPort">TCP порт</label>
<input id="tcpPort" class="tcp-field hidden" type="number" min="1" max="65535" value="502">
<button id="connectPortBtn">Подключить</button>
<button id="calibrateAllBtn">Калибровать все</button>
<span id="serialStatus" class="status status-warn">COM: не подключён</span>
</div>
</div>
</section>
<section class="panel grid">
<article class="card">
<h2>Датчики температуры</h2>
<div id="sensors" class="list"></div>
</article>
<article class="card">
<h2>Клапаны</h2>
<div id="valves" class="list"></div>
</article>
</section>
<footer class="footer">
<span>Статус: </span>
<span id="globalStatus">Ожидание...</span>
</footer>
</div>
<script src="app.js?v=20260625-setpoint-draft-1"></script>
</body>
</html>

View File

@@ -0,0 +1 @@
F:\set\workspace\setcorp\set506\git_project\ds128b20\new rev\john103C8T6\.codex-restored-sessions\codex_sessions_restored_20260609132029

View File

@@ -0,0 +1,16 @@
# Restored Codex sessions
Source archive: `C:\Users\z\Documents\Codex\2026-06-09\c-users-z-codex-sessions\outputs\codex_sessions_restored_20260609132029`
Project CWD: `F:\set\workspace\setcorp\set506\git_project\ds128b20\new rev\john103C8T6`
Generated copy: `2026-06-09T16:29:15.1490867+03:00`
## Dialogues
| Started | Title | Transcript |
|---|---|---|
| 2026-05-28T16:32:05.792Z | собери проект убери ошибки ,если нужны библиотеки подтяни их уровнем выше | [transcript](transcripts/001_14220bef_session.md) |
| 2026-05-28T16:47:52.141Z | настроить RTC с календарем и backup в modbuds сделать регистр времени часы минуты секунды дата | [transcript](transcripts/002_a30c80b2_RTC_backup_modbuds.md) |
## Restored files from patch records
Recovered embedded file contents, if any, are in `files_from_patches/`. Original project files were not overwritten.

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,13 @@
#ifndef __PROJ_SETUP
#define __PROJ_SETUP
//**********BEGIN defines***********
//#define OldVer
#define MAX_SENSE 32 // НЕ ДЕЛАТЬ МЕНЬШЕ 16
//**********END defines***********
#endif

View File

@@ -0,0 +1,53 @@
/* USER CODE BEGIN Header */
/**
******************************************************************************
* @file dma.h
* @brief This file contains all the function prototypes for
* the dma.c file
******************************************************************************
* @attention
*
* Copyright (c) 2025 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
/* USER CODE END Header */
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __DMA_H__
#define __DMA_H__
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ------------------------------------------------------------------*/
#include "main.h"
/* DMA memory to memory transfer handles -------------------------------------*/
extern DMA_HandleTypeDef hdma_memtomem_dma1_channel1;
/* USER CODE BEGIN Includes */
/* USER CODE END Includes */
/* USER CODE BEGIN Private defines */
/* USER CODE END Private defines */
void MX_DMA_Init(void);
/* USER CODE BEGIN Prototypes */
/* USER CODE END Prototypes */
#ifdef __cplusplus
}
#endif
#endif /* __DMA_H__ */

View File

@@ -0,0 +1,104 @@
/**
******************************************************************************
* @file ds18b20_driver.h
* @brief This file contains all the constants parameters for the DS18B20
* 1-Wire Digital Thermometer
******************************************************************************
* @attention
* Usage:
* Uncomment LL Driver for HAL driver
*
******************************************************************************
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef DS18B20_H
#define DS18B20_H
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ------------------------------------------------------------------*/
#include "onewire.h"
#include "PROJ_setup.h"
/* Data Structure ------------------------------------------------------------*/
#define DS18B20_DEVICE_AMOUNT MAX_SENSE
/* Register ------------------------------------------------------------------*/
#define DS18B20_CMD_CONVERT 0x44
#define DS18B20_CMD_ALARM_SEARCH 0xEC
#define DS18B20_CMD_READSCRATCHPAD 0xBE
#define DS18B20_CMD_WRITESCRATCHPAD 0x4E
#define DS18B20_CMD_COPYSCRATCHPAD 0x48
/* Data Structure ------------------------------------------------------------*/
#define DS18B20_FAMILY_CODE 0x28
#define DS18B20_SERIAL_NUMBER_LEN_BYTES 6
#define DS18B20_SERIAL_NUMBER_OFFSET_BYTES 1
#define DS18B20_SCRATCHPAD_T_LSB_BYTE_IDX 0
#define DS18B20_SCRATCHPAD_T_MSB_BYTE_IDX 1
#define DS18B20_SCRATCHPAD_T_LIMIT_H_BYTE_IDX 2
#define DS18B20_SCRATCHPAD_T_LIMIT_L_BYTE_IDX 3
#define DS18B20_SCRATCHPAD_CONFIG_BYTE_IDX 4
#define DS18B20_SCRATCHPAD_USER_BYTE_3_IDX 6
#define DS18B20_SCRATCHPAD_USER_BYTE_4_IDX 7
#define DS18B20_SCRATCHPAD_CRC_IDX 8
/* Bits locations for resolution */
#define DS18B20_RESOLUTION_R1 6
#define DS18B20_RESOLUTION_R0 5
#define DS18B20_DECIMAL_STEP_12BIT 0.0625
#define DS18B20_DECIMAL_STEP_11BIT 0.125
#define DS18B20_DECIMAL_STEP_10BIT 0.25
#define DS18B20_DECIMAL_STEP_9BIT 0.5
#define DS18B20_DELAY_MS_9_BITS 94
#define DS18B20_DELAY_MS_10_BITS 188
#define DS18B20_DELAY_MS_11_BITS 375
#define DS18B20_DELAY_MS_12_BITS 750
#define DS18B20_DELAY_MS_MAX DS18B20_DELAY_MS_12_BITS
/* DS18B20 Resolutions */
typedef enum {
DS18B20_RESOLUTION_9BITS = 0x1F,
DS18B20_RESOLUTION_10BITS = 0x3F,
DS18B20_RESOLUTION_11BITS = 0x5F,
DS18B20_RESOLUTION_12BITS = 0x7F
} DS18B20_Res_t;
typedef struct
{
uint8_t DevAddr[DS18B20_DEVICE_AMOUNT][8];
} DS18B20_Drv_t;
extern DS18B20_Drv_t DS;
extern OneWire_t OW;
/* External Function ---------------------------------------------------------*/
HAL_StatusTypeDef DS18B20_Search(DS18B20_Drv_t *DS, OneWire_t *OW);
HAL_StatusTypeDef DS18B20_StartConvT(OneWire_t* OW, uint8_t *ROM);
HAL_StatusTypeDef DS18B20_StartConvTAll(OneWire_t* OW);
HAL_StatusTypeDef DS18B20_CalcTemperature(OneWire_t* OW, uint8_t *ROM, uint8_t *Scratchpad, float *destination);
HAL_StatusTypeDef DS18B20_ReadScratchpad(OneWire_t* OW, uint8_t *ROM, uint8_t *Scratchpad);
HAL_StatusTypeDef DS18B20_WaitForEndConvertion(OneWire_t* OW);
HAL_StatusTypeDef DS18B20_WaitForEndConvertion_NonBlocking(OneWire_t* OW);
HAL_StatusTypeDef DS18B20_SetTempAlarm(OneWire_t* OW, uint8_t *ROM, int8_t Low,
int8_t High);
HAL_StatusTypeDef DS18B20_WriteUserBytes(OneWire_t* OW, uint8_t *ROM, int16_t UserBytes12,
int16_t UserBytes34, uint8_t UserBytesMask);
uint8_t DS18B20_AlarmSearch(DS18B20_Drv_t *DS, OneWire_t* OW);
HAL_StatusTypeDef DS18B20_SetResolution(OneWire_t* OW, uint8_t *ROM,
DS18B20_Res_t Resolution);
HAL_StatusTypeDef DS18B20_IsValidAddress(uint8_t *ROM);
#ifdef __cplusplus
}
#endif
#endif /* DS18B20_H */

Some files were not shown because too many files have changed in this diff Show More