Files
ds18b20-MODBUS/john103C6T6NewVer/Core/Src/main.c

685 lines
20 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/* 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 "i2c.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 "modbus.h"
#include "eeprom_emul.h"
#include "stdio.h"
#include "flash_ring.h"
#include "string.h"
/* USER CODE END Includes */
/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */
#include "linkBlink.h"
/* USER CODE END PTD */
/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
uint16_t iter, cnt = 5;
uint8_t init_retries = 5;
uint8_t ralay_5v_on_var = 0;
/* USER CODE END PD */
/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */
float temperature;
uint8_t roms[MAX_DEVICES][8];
Flags_TypeDef flag;
//extern uint8_t devices_found ;
uint8_t _debug_init = 0;
TEMP_TypeDef 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];
int init_sens = 0;
FlashRecord_t* record;
uint8_t flash_buff[RECORD_SIZE - 4];
RS_HandleTypeDef hmodbus_master;
RS_HandleTypeDef hmodbus_slave;
RS_MsgTypeDef master_msg;
RS_MsgTypeDef slave_msg;
uint8_t master_modbus_uart_buff[MSG_SIZE_MAX];
uint8_t slave_modbus_uart_buff[MSG_SIZE_MAX];
uint32_t last_modbus_request_tick = 0;
/* USER CODE END PM */
/* Private variables ---------------------------------------------------------*/
/* USER CODE BEGIN PV */
int last_page_addr = LAST_PAGE_ADDR;
/* USER CODE END PV */
/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
/* USER CODE BEGIN PFP */
BufferState_t buffer_state = {0};
/* 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_I2C1_Init();
MX_USART2_UART_Init();
/* USER CODE BEGIN 2 */
// #ifdef USART1_PA6_PA7
// HAL_UART_DeInit(&huart1);
// GPIO_InitTypeDef GPIO_InitStruct = {0};
//
// /* 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
// PA9 ------> USART1_TX
// PA10 ------> 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);
// /* USART1 interrupt Init */
// HAL_NVIC_SetPriority(USART1_IRQn, 0, 0);
// HAL_NVIC_EnableIRQ(USART1_IRQn);
//
//
//
// if (HAL_UART_Init(&huart1) != HAL_OK)
// {
// Error_Handler();
// }
// #endif
LED_BlinkRx_Config_t led_rx =
{
.port = GPIOC,
.pin = GPIO_PIN_13,
.blink_period = 10, // 100 РјСЃ
.blink_count = 2 // 3 мигания
};
LED_BlinkRx_Init(&led_rx);
BufferState_t buffer_init();
led_blink(GPIOC, 13, rest_iter, reset_blink_delay);
MODBUS_FirstInit(&hmodbus_master, &huart2, &htim2);
hmodbus_master.pBufferPtr = master_modbus_uart_buff;
MODBUS_Config(&hmodbus_master, MODBUS_DEVICE_ID, MODBUS_TIMEOUT, MODBUS_MODE_MASTER);
MODBUS_FirstInit(&hmodbus_slave, &huart1, NULL);
hmodbus_slave.pBufferPtr = slave_modbus_uart_buff;
MODBUS_Config(&hmodbus_slave, MODBUS_DEVICE_ID, MODBUS_TIMEOUT, MODBUS_MODE_SLAVE);
MODBUS_SlaveStart(&hmodbus_slave, &slave_msg);
// Запуск приема Modbus
master_msg = MB_REQUEST_READ_HOLDING_REGS(1, 0, 1);
uint8_t uart_byte = 0;
Dallas_BusFirstInit(&htim1);
// пїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅ пїЅпїЅ пїЅпїЅпїЅпїЅпїЅпїЅпїЅ пїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅ пїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅ
// пїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅ пїЅпїЅ пїЅпїЅпїЅпїЅпїЅпїЅпїЅ (пїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅ пїЅпїЅпїЅпїЅпїЅпїЅ пїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅ пїЅпїЅпїЅпїЅпїЅпїЅпїЅ)
reinit_t_sens();
init_setpoint_all_T_sense(temp_sense, hdallas.onewire->RomCnt);
MB_DATA.InRegs.num_Tsens = hdallas.onewire->RomCnt;
// BufferState_t buffer_state = buffer_init();
for(int i=0;i<RECORD_SIZE;i++)
{
flash_buff[i]=i;
}
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
if ((HAL_GetTick() - last_modbus_request_tick) >= 1000U)
{
if (MODBUS_MasterRequest(&hmodbus_master, &master_msg, NULL) == HAL_OK)
{
last_modbus_request_tick = HAL_GetTick();
}
}
if (MB_DATA.Coils.reserve3[3]==1)
{
MB_DATA.Coils.reserve3[3]=0;
LED_BlinkRx_Init(&led_rx);
}
//////блинкер по приему RS
if ((hmodbus_master.f.blink == 1) || (hmodbus_slave.f.blink == 1))
{
hmodbus_master.f.blink = 0;
hmodbus_slave.f.blink = 0;
LED_BlinkRx_OnRx();
}
LED_BlinkRx_Process();
//////
////// запись во флэш
if (MB_DATA.Coils.reserve3[0]==1)
{
MB_DATA.Coils.reserve3[0] = 0;
BufferState_t state = buffer_init();
uint32_t idx = (state.write_index ) % RECORDS_PER_PAGE;
FlashRecord_t* record = buffer_read_record(idx);
}
if (MB_DATA.Coils.reserve3[1]==1)
{
MB_DATA.Coils.reserve3[1] = 0;
FlashRecord_t new_record;
new_record.timestamp = HAL_GetTick();
memcpy(new_record.data, flash_buff, sizeof(new_record.data));
HAL_StatusTypeDef status = buffer_write_record(&new_record, &buffer_state);
if (status == HAL_OK)
{
// printf("Record written successfully\n");
GPIOC->ODR |= 1 << 13;
}
}
temp_sense[0].t_close = 1;
Field_modbus(&MB_DATA, &flag);
Check_Tconnect(&MB_DATA, &flag, &hdallas, 0);
value_control();
init_setpoint_all_T_sense(temp_sense, hdallas.onewire->RomCnt);
// handle_valves(temp_sense[]);
init_cycle_counter();
static uint16_t dataBE[2];
static uint16_t dataLE[2];
uint32_t start_dwt = get_cycle_count();
uint32_t start = HAL_GetTick();
Dallas_StartConvertTAll(&hdallas, DALLAS_WAIT_DELAY, 200);
uint32_t end_dwt = get_cycle_count();
uint32_t end = HAL_GetTick();
uint32_t time_DWT=end_dwt-start_dwt;
uint32_t time_hal=end-start;
U32_TO_MODBUS(time_DWT, dataBE, MODBUS_REG_ORDER_BE);
U32_TO_MODBUS(time_DWT, dataLE, MODBUS_REG_ORDER_LE);
for(int i = 0; i < hdallas.onewire->RomCnt; i++)
{
if(sens[i].isLost)
{
sens[i].lost_cnt ++;
}
Dallas_ReadTemperature(&sens[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);
}
}
/* 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_HSE;
RCC_OscInitStruct.HSEState = RCC_HSE_ON;
RCC_OscInitStruct.HSEPredivValue = RCC_HSE_PREDIV_DIV1;
RCC_OscInitStruct.HSIState = RCC_HSI_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_ADC;
PeriphClkInit.AdcClockSelection = RCC_ADCPCLK2_DIV6;
if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK)
{
Error_Handler();
}
}
/* USER CODE BEGIN 4 */
uint32_t get_cycle_count(void) {
return DWT->CYCCNT;
}
void init_cycle_counter(void) {
CoreDebug->DEMCR |= CoreDebug_DEMCR_TRCENA_Msk;
DWT->CYCCNT = 0;
DWT->CTRL |= DWT_CTRL_CYCCNTENA_Msk;
}
// Замер времени в тактах процессора
uint32_t measure_execution_time_cycles(void (*func)(void)) {
uint32_t start = get_cycle_count();
func();
uint32_t end = get_cycle_count();
return end - start;
}
uint16_t* U32_TO_MODBUS (uint32_t value, uint16_t reg_array[2], int order)
{
if (order == MODBUS_REG_ORDER_BE)
{
(reg_array)[0] = (uint16_t)((value) >> 16);
(reg_array)[1] = (uint16_t)(value);
} else
{
(reg_array)[0] = (uint16_t)(value);
(reg_array)[1] = (uint16_t)((value) >> 16);
}
return reg_array;
}
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 Check_Tconnect(MB_DataStructureTypeDef* MB_DATA, Flags_TypeDef* flag, DALLAS_HandleTypeDef* hdallas, int a[0])
{
for(int i = 0; i < hdallas->onewire->RomCnt; i++)
{
if(sens[i].isLost)
{
//init_sens=1;
}
}
if (init_sens || flag->init_tsens)
{
init_sens = 0;
flag->init_tsens = 0;
//Dallas_BusFirstInit(&htim1);
DS18B20_Search(&DS, &OW) ;
reinit_t_sens();
MB_DATA->InRegs.num_Tsens = hdallas->onewire->RomCnt;
}
}
void reinit_t_sens(void)
{
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]);
}
}
FuncStat packStruct(MB_DataStructureTypeDef* MB_DATA, int sizeARR)
{
for(int i = 0; i < sizeARR; i++)
{
for(int sens_num = 0; sens_num < hdallas.onewire->RomCnt; sens_num++)
{
switch(sens_num)
{
case 0:
MB_DATA->Coils.status_tSens[i].state_val_bit.Temp1_isConnected = sens[i * 16 + sens_num ].isConnected;
break;
case 1:
MB_DATA->Coils.status_tSens[i].state_val_bit.Temp2_isConnected = sens[i * 16 + sens_num ].isConnected;
break;
case 2:
MB_DATA->Coils.status_tSens[i].state_val_bit.Temp3_isConnected = sens[i * 16 + sens_num ].isConnected;
break;
case 3:
MB_DATA->Coils.status_tSens[i].state_val_bit.Temp4_isConnected = sens[i * 16 + sens_num ].isConnected;
break;
case 4:
MB_DATA->Coils.status_tSens[i].state_val_bit.Temp5_isConnected = sens[i * 16 + sens_num ].isConnected;
break;
case 5:
MB_DATA->Coils.status_tSens[i].state_val_bit.Temp6_isConnected = sens[i * 16 + sens_num ].isConnected;
break;
case 6:
MB_DATA->Coils.status_tSens[i].state_val_bit.Temp7_isConnected = sens[i * 16 + sens_num ].isConnected;
break;
case 7:
MB_DATA->Coils.status_tSens[i].state_val_bit.Temp8_isConnected = sens[i * 16 + sens_num ].isConnected;
break;
case 8:
MB_DATA->Coils.status_tSens[i].state_val_bit.Temp9_isConnected = sens[i * 16 + sens_num ].isConnected;
break;
case 9:
MB_DATA->Coils.status_tSens[i].state_val_bit.Temp10_isConnected = sens[i * 16 + sens_num ].isConnected;
break;
case 10:
MB_DATA->Coils.status_tSens[i].state_val_bit.Temp11_isConnected = sens[i * 16 + sens_num ].isConnected;
break;
case 11:
MB_DATA->Coils.status_tSens[i].state_val_bit.Temp12_isConnected = sens[i * 16 + sens_num ].isConnected;
break;
case 12:
MB_DATA->Coils.status_tSens[i].state_val_bit.Temp13_isConnected = sens[i * 16 + sens_num ].isConnected;
break;
case 13:
MB_DATA->Coils.status_tSens[i].state_val_bit.Temp14_isConnected = sens[i * 16 + sens_num ].isConnected;
break;
case 14:
MB_DATA->Coils.status_tSens[i].state_val_bit.Temp15_isConnected = sens[i * 16 + sens_num ].isConnected;
break;
case 15:
MB_DATA->Coils.status_tSens[i].state_val_bit.Temp16_isConnected = sens[i * 16 + sens_num ].isConnected;
break;
}
}
}
return FuncOK;
}
FuncStat Field_modbus(MB_DataStructureTypeDef* MB_DATA, Flags_TypeDef* flag)
{
//MB_DATA->InRegs.reserve1 sin_table_phase_a
MB_DATA->InRegs.ID = *hdallas.ds_devices;
flag->init_tsens = MB_DATA->Coils.init_Tsens;
packStruct(MB_DATA, MAX_SENSE / 16);
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];
}
}
return FuncOK;
};
FuncStat value_control(void )
{
for(int i = 0; i < hdallas.onewire->RomCnt; i++)
{
if (sens[i].isLost==0)
{
sens[i].lost_cnt=0;
if (sens[i].temperature < sens[i].set_temp - sens[i].hyst)
{
MB_DATA.Coils.relay_struct_off.all |= 1 << i;
MB_DATA.Coils.relay_struct_on.all &= ~(1 << i);
}
else
if (sens[i].temperature > sens[i].set_temp + sens[i].hyst)
{
MB_DATA.Coils.relay_struct_off.all &= ~(1 << i);
MB_DATA.Coils.relay_struct_on.all |= 1 << i;
}
else
if (sens[i].temperature == sens[i].set_temp )
{
MB_DATA.Coils.relay_struct_on.all &= ~(1 << i);
MB_DATA.Coils.relay_struct_off.all &= ~(1 << i);
}
}
else
{
if(sens[i].lost_cnt>10)
{
MB_DATA.Coils.relay_struct_on.all &= ~(1 << i);
MB_DATA.Coils.relay_struct_off.all &= ~(1 << i);
}
}
}
return FuncOK;
}
uint16_t handle_valves(TEMP_TypeDef* temp_sense[MAX_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_setpoint_all_T_sense(TEMP_TypeDef* temp_sense, int size_array)
{
//ds_search_devices();
for(int i = 0; i < size_array ; 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 */