/* USER CODE BEGIN Header */ /** ****************************************************************************** * @file : main.c * @brief : Main program body ****************************************************************************** * @attention * * Copyright (c) 2024 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 "dma.h" #include "i2c.h" #include "spi.h" #include "tim.h" #include "usart.h" #include "gpio.h" /* Private includes ----------------------------------------------------------*/ /* USER CODE BEGIN Includes */ #include "wf5803.h" #include "ch395.h" #include "hp303s.h" #include "dac7311.h" #include "eeprom.h" #include "digital.h" #include "cmd_queue.h" /* USER CODE END Includes */ /* Private typedef -----------------------------------------------------------*/ /* USER CODE BEGIN PTD */ /* USER CODE END PTD */ /* 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 -----------------------------------------------*/ void SystemClock_Config(void); /* USER CODE BEGIN PFP */ /* USER CODE END PFP */ /* Private user code ---------------------------------------------------------*/ /* USER CODE BEGIN 0 */ int last_encode_num = 0; int curr_encode_num = 0; uint32_t encode_num = 0; float AO1_data = 0; //AO1输出电流值 float AO2_data = 0; //AO2输出电流值 float ao1_offsets = 0; //电流补偿 float ao2_offsets = 0; //电流补偿 int16_t ao1_k,ao1_b,ao2_k,ao2_b; uint8_t ao_data[8] = {0x27,0x00,0x00,0x36,0x26,0xE8,0x00,0x22}; int16_t current_offsets[4] = {0,0,0,0}; //电流补偿值 int16_t pressure_offsets[4] = {0,0,0,0};//气压补偿值 uint16_t holdreg_data1[10] = {0,0,0,0,0,0,0,0,0,0};//临时保存寄存器数据,用于比较 uint16_t holdreg_data2[10] = {0,0,0,0,0,0,0,0,0,0};//临时保存寄存器数据,用于比较 /* 本地网络信息:IP地址、网关地址、子网掩码和端口号 */ uint8_t ch395_addr[16] = {192,168,114,194,192,168,114,110,255,255,255,0,15,250,19,226}; int size = 0; //串口屏指令长度 int cnt_update = 152; int net_status = 0; long adc_sum[4] = {0}; int adc_cnt = 0; void analog_cal() { //提取保持寄存器数据,比较前后数据是否有变化,有变化就修改校准值 for(int hold_num = 3;hold_num < 13;hold_num ++) { holdreg_data1[hold_num-3] = holdreg_data2[hold_num-3]; holdreg_data2[hold_num-3] = HoldReg[hold_num]; } //电流输出补偿,寄存器内数据为补偿值,直接赋予对应补偿参数 if(holdreg_data1[0] != holdreg_data2[0]) { if(holdreg_data2[0] > 0xF000) ao1_offsets = holdreg_data2[0]-1-0xFFFF; else ao1_offsets = holdreg_data2[0]; } if(holdreg_data1[1] != holdreg_data2[1]) { if(holdreg_data2[1] > 0xF000) ao2_offsets = holdreg_data2[1]-1-0xFFFF; else ao2_offsets = holdreg_data2[1]; } for(int off_num = 2;off_num < 10;off_num++) { if(holdreg_data1[off_num] != holdreg_data2[off_num]) { //获取电流校准值 if(off_num < 6) { if(holdreg_data2[off_num] > 0xF000) current_offsets[off_num - 2] = holdreg_data2[off_num]-1-0xFFFF; else current_offsets[off_num - 2] = holdreg_data2[off_num]; } //获取压力校准值 else { if(holdreg_data2[off_num] > 0xF000) pressure_offsets[off_num - 6] = holdreg_data2[off_num]-1-0xFFFF; else pressure_offsets[off_num - 6] = holdreg_data2[off_num]; } } } } /* 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_DMA_Init(); MX_ADC1_Init(); MX_UART4_Init(); MX_USART1_UART_Init(); MX_USART2_UART_Init(); MX_TIM3_Init(); MX_USART3_UART_Init(); MX_I2C1_Init(); MX_I2C2_Init(); MX_I2C3_Init(); MX_SPI1_Init(); MX_SPI3_Init(); MX_TIM1_Init(); MX_USART6_UART_Init(); MX_TIM6_Init(); MX_TIM7_Init(); MX_TIM10_Init(); MX_TIM2_Init(); /* USER CODE BEGIN 2 */ delay_ms(100); wf5803_setup(); //压力传感器初始化 delay_ms(100); hp303_init(); //气压传感器初始化 dac7311_init(); //初始化DAC7311 adcs_init(); modbus_rtu_init(&huart1,&htim7); //modbus rtu模式初始化 hart_init(); //Hart通信 __HAL_UART_ENABLE_IT(&huart6, UART_IT_RXNE); //开启串口屏接收中断 HAL_TIM_Base_Start_IT(&htim6); //主要定时 HAL_TIM_Encoder_Start(&htim1, TIM_CHANNEL_ALL); //定时器1编码器启动 __HAL_TIM_SetCounter(&htim1, 0x9718); //编码器初始值30000//1亿 HAL_TIM_PWM_Init(&htim3); HAL_TIM_PWM_Start(&htim3,TIM_CHANNEL_2); //460.8kHzPWM波 HAL_TIM_Base_Start_IT(&htim2); HAL_TIM_PWM_Start(&htim2,TIM_CHANNEL_2); __HAL_TIM_SET_COMPARE(&htim2,TIM_CHANNEL_2,30000);//50%占空比 __HAL_TIM_SET_COMPARE(&htim3,TIM_CHANNEL_2,67);//50%占空比 ee_io_init(); //eeprom初始化 ee_read_data(); HoldReg[13] = 6000;//阀杆直径 //网络参数读取 ee_readbytes(ch395_addr,100,16); for(int n = 0;n < 12;n++) { HoldReg[40 + n] = ch395_addr[n]; } HoldReg[52] = ch395_addr[12] << 8 | ch395_addr[13]; HoldReg[53] = ch395_addr[14] << 8 | ch395_addr[15]; //输出电流校准 //ee_writebytes(ao_data,20,8); ee_readbytes(ao_data,20,8); ao1_k = (int16_t)(ao_data[0] << 8 | ao_data[1]); ao1_b = (int16_t)(ao_data[2] << 8 | ao_data[3]); ao2_k = (int16_t)(ao_data[4] << 8 | ao_data[5]); ao1_b = (int16_t)(ao_data[6] << 8 | ao_data[7]); /* USER CODE END 2 */ /* Infinite loop */ /* USER CODE BEGIN WHILE */ while (1) { /* USER CODE END WHILE */ /* USER CODE BEGIN 3 */ if(net_status == 1) { ch395_hardware_init(); //ch395硬件初始化 ch395_init(); //以太网初始化 net_status = 2; } if(net_status == 2) { ch395q_handler(); //网络通讯 if(HoldReg[54]) { for(int n = 0;n < 12;n++) { ch395_addr[n] = HoldReg[40 + n]; } ch395_addr[12] = HoldReg[52] >> 8; ch395_addr[13] = HoldReg[52] & 0xFF; ch395_addr[14] = HoldReg[53] >> 8; ch395_addr[15] = HoldReg[53] & 0xFF; ee_writebytes(ch395_addr,100,16); HoldReg[54] = 0; set_ipv4(); } } //串口屏任务处理 size = queue_find_cmd(cmd_buffer,CMD_MAX_SIZE); //从缓冲区中获取一条指令 if(size>0 && cmd_buffer[1]!=0x07) //接收到指令 ,及判断是否为开机提示 { ProcessMessage((PCTRL_MSG)cmd_buffer, size); //指令处理 } if(it_100ms_flag) { UpdateUI(); //UI界面更新 hp303_read(); //环境气压数据采集 it_100ms_flag = 0; } wf5803_loop(); //A口B口气源压力数据采集 analog_cal(); //校准值更新 di_do_ctrl(); //数字量输入输出 adcs_data_processing(); //4-20mA电流输出控制 if(!(AO1_data == (float)(HoldReg[0] + ao1_offsets) / 1000)) { AO1_data = (float)(HoldReg[0] + ao1_offsets) / 1000; if(AO1_data > 25) AO1_data = 25; ao1_set((ao1_k * AO1_data + ao1_b) / 10000.0f); //ao1_set(AO1_data); } if(!(AO2_data == (float)(HoldReg[1] + ao2_offsets) / 1000)) { AO2_data = (float)(HoldReg[1] + ao2_offsets) / 1000; if(AO2_data > 25) AO2_data = 25; ao2_set((ao2_k * AO2_data + ao2_b) / 10000.0f); //ao2_set(AO2_data); } //编码器 last_encode_num = curr_encode_num; //保存前次编码器数值 curr_encode_num = __HAL_TIM_GET_COUNTER(&htim1); //获取当前编码器数值 //判断编码器计数向上溢出还是向下溢出 if((curr_encode_num - last_encode_num) < -50000) cnt_update++; else if((curr_encode_num - last_encode_num) > 50000) cnt_update--; encode_num = curr_encode_num + cnt_update * 0xFFFF; //编码器,返回计数脉冲值 InputReg[10] = (encode_num >> 16) & 0xffff; InputReg[11] = encode_num & 0xffff; InputReg[12]= (((float)adcs_data[0] * 3300 / 4096) / 0.082f) * 1.01 - 69 + current_offsets[0]; InputReg[0]= adcs_data[1] * 3300 / 4096; InputReg[1]= (((float)adcs_data[2] * 3300 / 4096) / 0.082f) + 450; InputReg[2]= (((float)adcs_data[3] * 3300 / 4096) / 0.082f); if(it_1000ms_flag) { ee_write_data(); HAL_GPIO_TogglePin(LED_GPIO_Port,LED_Pin); it_1000ms_flag = 0; } } /* USER CODE END 3 */ } /** * @brief System Clock Configuration * @retval None */ void SystemClock_Config(void) { RCC_OscInitTypeDef RCC_OscInitStruct = {0}; RCC_ClkInitTypeDef RCC_ClkInitStruct = {0}; /** Configure the main internal regulator output voltage */ __HAL_RCC_PWR_CLK_ENABLE(); __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1); /** 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.PLL.PLLState = RCC_PLL_ON; RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE; RCC_OscInitStruct.PLL.PLLM = 8; RCC_OscInitStruct.PLL.PLLN = 90; RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2; RCC_OscInitStruct.PLL.PLLQ = 4; 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(); } } /* USER CODE BEGIN 4 */ #define CPU_FREQUENCY_MHZ 62 // STM32时钟主频,实际主频为62.208MHz,这里取整,us延时会偏大 void delay_us(__IO uint32_t delay) { int last, curr, val; int temp; while (delay != 0) { temp = delay > 900 ? 900 : delay; last = SysTick->VAL; curr = last - CPU_FREQUENCY_MHZ * temp; if (curr >= 0) { do { val = SysTick->VAL; } while ((val < last) && (val >= curr)); } else { curr += CPU_FREQUENCY_MHZ * 1000; do { val = SysTick->VAL; } while ((val <= last) || (val > curr)); } delay -= temp; } } void delay_ms(__IO uint32_t delay) { HAL_Delay(delay); } void delay_tick(uint32_t ticks) { while (ticks--) { __NOP(); } } /* USER CODE END 4 */ /** * @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 */