controller-pcba/Core/Src/freertos.c

549 lines
16 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 Name : freertos.c
* Description : Code for freertos applications
******************************************************************************
* @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.
* @file freertos.c
*
******************************************************************************
*/
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "FreeRTOS.h"
#include "task.h"
#include "main.h"
#include "cmsis_os.h"
/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "dac161s997.h"
#include "ad7124.h"
#include "usart.h"
#include "communication_protocol.h"
#include "tim.h"
#include "gpio.h"
#include "tcpserverc.h"
#include "lwip.h"
#include "lwip/tcp.h" // 添加TCP相关定义
#include "uart_lcd.h"
#include "user_gpio.h"
#include "linear_encoder.h"
#include "lan8742.h"
#include "ad7124_test.h"
#include <string.h> // 添加string.h用于字符串操作
#include "ht1200m.h"
// 声明外部变量
extern ad7124_analog_t ad7124_analog[AD7124_CHANNEL_EN_MAX];
/* 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 Variables */
osThreadId lwip_taskHandle;
osThreadId led_taskHandle;
osThreadId dac_taskHandle;
osThreadId adc_taskHandle;
osThreadId gpio_di_do_taskHandle;
osThreadId ec11_taskHandle;
osThreadId ad7124_test_taskHandle;
osThreadId usart6_test_taskHandle; // 添加USART6测试任务句柄
// 添加调试变量
static volatile uint32_t uart6_dr_raw = 0; // UART数据寄存器的原始值
static volatile uint8_t uart6_data_bits = 0; // 数据位8位
static volatile uint8_t uart6_parity_bit = 0; // 校验位
static volatile uint8_t uart6_stop_bits = 0; // 停止位
static volatile uint8_t uart6_error_flags = 0; // 错误标志
// 添加RTS引脚监控变量
volatile GPIO_PinState rts_pin_state = GPIO_PIN_RESET; // RTS引脚当前状态
volatile GPIO_PinState rst_pin_state = GPIO_PIN_RESET; // RTS引脚当前状态
volatile uint32_t rts_pin_pull = 0; // RTS引脚上下拉配置
volatile uint32_t rts_pin_mode = 0; // RTS引脚模式
volatile uint32_t rts_pin_speed = 0; // RTS引脚速度
volatile uint32_t rts_pin_alternate = 0; // RTS引脚复用功能
/* USER CODE END Variables */
/* Private function prototypes -----------------------------------------------*/
/* USER CODE BEGIN FunctionPrototypes */
extern float current_buff[2];
extern struct netif gnetif;
extern ETH_HandleTypeDef heth;
extern struct tcp_pcb *server_pcb_hart1;
extern struct tcp_pcb *server_pcb_hart2;
extern struct tcp_pcb *server_pcb_ble1;
extern struct tcp_pcb *server_pcb_ble2;
extern struct tcp_pcb *server_pcb_control;
extern void tcp_abort(struct tcp_pcb *pcb);
void start_usart6_test_task(void const *argument); // 添加USART6测试任务函数声明
/* USER CODE END FunctionPrototypes */
void start_tcp_task(void const *argument);
void start_led_toggle_task(void const *argument);
void start_dac_task(void const *argument);
void start_adc_task(void const *argument);
void start_gpio_di_do_task(void const *argument);
void start_ec11_task(void const *argument);
void start_ad7124_test_task(void const *argument);
void ad7124_multi_channel_init(uint8_t sample_rate);
void start_adc_task(void const *argument);
void test_cs_pin(void);
extern void MX_LWIP_Init(void);
void MX_FREERTOS_Init(void); /* (MISRA C 2004 rule 8.1) */
/* GetIdleTaskMemory prototype (linked to static allocation support) */
void vApplicationGetIdleTaskMemory(StaticTask_t **ppxIdleTaskTCBBuffer, StackType_t **ppxIdleTaskStackBuffer, uint32_t *pulIdleTaskStackSize);
/* USER CODE BEGIN GET_IDLE_TASK_MEMORY */
static StaticTask_t xIdleTaskTCBBuffer;
static StackType_t xIdleStack[configMINIMAL_STACK_SIZE];
void vApplicationGetIdleTaskMemory(StaticTask_t **ppxIdleTaskTCBBuffer, StackType_t **ppxIdleTaskStackBuffer, uint32_t *pulIdleTaskStackSize)
{
*ppxIdleTaskTCBBuffer = &xIdleTaskTCBBuffer;
*ppxIdleTaskStackBuffer = &xIdleStack[0];
*pulIdleTaskStackSize = configMINIMAL_STACK_SIZE;
/* place for user code */
}
/* USER CODE END GET_IDLE_TASK_MEMORY */
/**
* @brief FreeRTOS initialization
* @param None
* @retval None
*/
void MX_FREERTOS_Init(void)
{
/* USER CODE BEGIN Init */
/* USER CODE END Init */
/* USER CODE BEGIN RTOS_MUTEX */
/* add mutexes, ... */
/* USER CODE END RTOS_MUTEX */
/* USER CODE BEGIN RTOS_SEMAPHORES */
/* add semaphores, ... */
/* USER CODE END RTOS_SEMAPHORES */
/* USER CODE BEGIN RTOS_TIMERS */
/* start timers, add new ones, ... */
/* USER CODE END RTOS_TIMERS */
/* USER CODE BEGIN RTOS_QUEUES */
/* add queues, ... */
/* USER CODE END RTOS_QUEUES */
/* Create the thread(s) */
/* definition and creation of lwip_task */
osThreadDef(lwip_task, start_tcp_task, osPriorityHigh, 0, 512);
lwip_taskHandle = osThreadCreate(osThread(lwip_task), NULL);
/* definition and creation of led_task */
// osThreadDef(led_task, start_led_toggle_task, osPriorityLow, 0, 128);
// led_taskHandle = osThreadCreate(osThread(led_task), NULL);
/* definition and creation of dac_task */
// osThreadDef(dac_task, start_dac_task, osPriorityNormal, 0, 512);
// dac_taskHandle = osThreadCreate(osThread(dac_task), NULL);
osThreadDef(adc_task, start_adc_task, osPriorityBelowNormal, 0, 128);
adc_taskHandle = osThreadCreate(osThread(adc_task), NULL);
/* definition and creation of adc_task */
// osThreadDef(adc_task, start_adc_task, osPriorityBelowNormal, 0, 128);
// adc_taskHandle = osThreadCreate(osThread(adc_task), NULL);
/* definition and creation of gpio_di_do_task */
//osThreadDef(gpio_di_do_task, start_gpio_di_do_task, osPriorityNormal, 0, 128);
//gpio_di_do_taskHandle = osThreadCreate(osThread(gpio_di_do_task), NULL);
/* definition and creation of ec11_task */
// osThreadDef(ec11_task, start_ec11_task, osPriorityNormal, 0, 512);
// ec11_taskHandle = osThreadCreate(osThread(ec11_task), NULL);
/* definition and creation of ad7124_test_task */
// osThreadDef(ad7124_test_task, start_ad7124_test_task, osPriorityNormal, 0, 512);
// ad7124_test_taskHandle = osThreadCreate(osThread(ad7124_test_task), NULL);
/* HART测试任务 */
osThreadDef(usart6_test_task, start_usart6_test_task, osPriorityNormal, 0, 128);
usart6_test_taskHandle = osThreadCreate(osThread(usart6_test_task), NULL);
/* USER CODE BEGIN RTOS_THREADS */
/* add threads, ... */
/* USER CODE END RTOS_THREADS */
}
/* USER CODE BEGIN Header_start_tcp_task */
/**
* @brief Function implementing the lwip_task thread.
* @param argument: Not used
* @retval None
*/
/* USER CODE END Header_start_tcp_task */
void start_tcp_task(void const *argument)
{
/* init code for LWIP */
MX_LWIP_Init();
/* USER CODE BEGIN start_tcp_task */
tcp_echo_init();
uart_lcd_draw_ipaddr(); // 初始化显示IP地址信息
/* Infinite loop */
for (;;)
{
uint32_t phyreg = 0;
HAL_ETH_ReadPHYRegister(&heth, 0x00, PHY_BSR, &phyreg);
if (((phyreg >> 2) & 0x1) != 0x1)
{
/* When the netif link is down this function must be called */
netif_set_link_down(&gnetif);
netif_set_down(&gnetif); // 热插拔下线时调用
if (tcp_echo_flags_hart1 == 1)
{
tcp_abort(server_pcb_hart1); // 热插拔下线时调用
tcp_echo_flags_hart1 = 0;
}
if (tcp_echo_flags_hart2 == 1)
{
tcp_abort(server_pcb_hart2); // 热插拔下线时调用
tcp_echo_flags_hart2 = 0;
}
#if (BLE2_USART6 == 1)
if (tcp_echo_flags_ble1 == 1)
{
tcp_abort(server_pcb_ble1); // 热插拔下线时调用
tcp_echo_flags_ble1 = 0;
}
#endif
if (tcp_echo_flags_ble2 == 1)
{
tcp_abort(server_pcb_ble2); // 热插拔下线时调用
tcp_echo_flags_ble2 = 0;
}
if (tcp_echo_flags_control == 1)
{
tcp_abort(server_pcb_control); // 热插拔下线时调用
tcp_echo_flags_control = 0;
}
}
else
{
/* When the netif is fully configured this function must be called */
netif_set_link_up(&gnetif);
netif_set_up(&gnetif); // 热插拔上线时调用
// if (tcp_echo_flags_ble1 == 2)
// {
// tcp_echo_init(); // 热插拔上线时调用
// // uart_lcd_draw_ipaddr(); // 初始化显示IP地址信息
// tcp_echo_flags_ble1 = 0;
// }
}
vTaskDelay(1000);
// osThreadTerminate(NULL);
}
/* USER CODE END start_tcp_task */
}
/* USER CODE BEGIN Header_start_led_toggle_task */
/**
* @brief Function implementing the led_task thread.
* @param argument: Not used
* @retval None
*/
/* USER CODE END Header_start_led_toggle_task */
void start_led_toggle_task(void const *argument)
{
/* USER CODE BEGIN start_led_toggle_task */
/* Infinite loop */
for (;;)
{
HAL_GPIO_TogglePin(LED3_G_GPIO_Port, LED3_G_Pin);
uart_lcd_ecll_control_current_out();
vTaskDelay(500);
}
/* USER CODE END start_led_toggle_task */
}
/* USER CODE BEGIN Header_start_dac_task */
/**
* @brief Function implementing the dac_task thread.
* @param argument: Not used
* @retval None
*/
/* USER CODE END Header_start_dac_task */
void start_dac_task(void const *argument)
{
/* USER CODE BEGIN start_dac_task */
dac161s997_init();
/* Infinite loop */
for (;;)
{
osThreadSuspend(adc_taskHandle); // 暂停ADC任务防止DAC采集时产生干????????,因为ADC和DAC采用的是同一路SPI但是时序不????????
dac161s997_output(DAC161S997_1, current_buff[0]);
dac161s997_output(DAC161S997_2, current_buff[1]);
osThreadResume(adc_taskHandle);
vTaskDelay(100);
}
/* USER CODE END start_dac_task */
}
/* USER CODE BEGIN Header_start_adc_task */
/**
* @brief ADC任务函数实现
* @param argument: 未使用
* @retval None
*/
/* USER CODE END Header_start_adc_task */
void start_adc_task(void const *argument)
{
/* USER CODE BEGIN start_adc_task */
ad7124_setup();
/* Infinite loop */
for (;;)
{
uint8_t ch = 0;
for (ch = AD7124_AIN0; ch < AD7124_CHANNEL_EN_MAX; ch++)
{
ad7124_get_analog(ch);
}
vTaskDelay(10);
}
/* USER CODE END start_adc_task */
}
/* USER CODE BEGIN Header_start_gpio_di_do_task */
/**
* @brief Function implementing the gpio_di_do_task thread.
* @param argument: Not used
* @retval None
*/
/* USER CODE END Header_start_gpio_di_do_task */
void start_gpio_di_do_task(void const *argument)
{
/* USER CODE BEGIN start_gpio_di_do_task */
/* Infinite loop */
for (;;)
{
user_gpio_trigger();
vTaskDelay(100);
}
/* USER CODE END start_gpio_di_do_task */
}
/* USER CODE BEGIN Header_start_ec11_task */
/**
* @brief Function implementing the ec11_task thread.
* @param argument: Not used
* @retval None
*/
/* USER CODE END Header_start_ec11_task */
void start_ec11_task(void const *argument)
{
/* USER CODE BEGIN start_ec11_task */
/* Infinite loop */
for (;;)
{
linear_encoder_get_data();
uart_lcd_ec11_control_current();
uart_forwarding_tcp();
vTaskDelay(10);
}
/* USER CODE END start_ec11_task */
}
/**
* @brief Initialize AD7124 with multiple channels
* @param sample_rate: Sample rate selection (2Hz to 1kHz)
* @retval None
*/
/* USER CODE END Application */
/**
* @brief 测试CS引脚的功能
*
* 这个函数将不断地尝试拉低和拉高CS引脚并读取其状态。
* 它主要用于测试硬件连接和引脚操作的正确性。
*
* @return 无返回值
*/
void test_cs_pin(void)
{
while (1) {
ad7124_cs_on(); // 尝试拉低
GPIO_PinState state = HAL_GPIO_ReadPin(SPI2_CS_GPIO_Port, SPI2_CS_Pin);
// 打印或观察state值应该是GPIO_PIN_RESET
HAL_Delay(100);
ad7124_cs_off(); // 尝试拉高
state = HAL_GPIO_ReadPin(SPI2_CS_GPIO_Port, SPI2_CS_Pin);
// 打印或观察state值应该是GPIO_PIN_SET
HAL_Delay(100);
}
}
/* USER CODE BEGIN Header_start_usart6_test_task */
/**
* @brief Function implementing the usart6_test_task thread.
* @param argument: Not used
* @retval None
*/
/* USER CODE END Header_start_usart6_test_task */
// 添加UART接收回调函数声明
static void UART6_RxCpltCallback(void);
// 添加接收缓冲区
static uint8_t uart6_rx_buffer[1];
static volatile uint8_t uart6_rx_data = 0;
static volatile uint8_t uart6_rx_flag = 0;
// UART接收完成回调函数
static void UART6_RxCpltCallback(void)
{
uart6_rx_data = uart6_rx_buffer[0];
uart6_rx_flag = 1;
// 重新启动接收
HAL_UART_Receive_IT(&huart6, uart6_rx_buffer, 1);
}
void start_usart6_test_task(void const *argument)
{
/* USER CODE BEGIN start_usart6_test_task */
uint8_t rx_buffer[1]; // 接收缓冲区
err_t err;
// 确保UART6已正确初始化
if (huart6.Instance == NULL) {
Error_Handler();
}
// 重新初始化UART6
HAL_UART_DeInit(&huart6);
huart6.Init.BaudRate = 1200;
huart6.Init.WordLength = UART_WORDLENGTH_8B;
huart6.Init.StopBits = UART_STOPBITS_1;
huart6.Init.Parity = UART_PARITY_NONE;
huart6.Init.Mode = UART_MODE_TX_RX;
huart6.Init.HwFlowCtl = UART_HWCONTROL_NONE;
huart6.Init.OverSampling = UART_OVERSAMPLING_16;
// 清除所有标志位
__HAL_UART_CLEAR_FLAG(&huart6, UART_FLAG_RXNE);
__HAL_UART_CLEAR_FLAG(&huart6, UART_FLAG_PE);
__HAL_UART_CLEAR_FLAG(&huart6, UART_FLAG_FE);
__HAL_UART_CLEAR_FLAG(&huart6, UART_FLAG_ORE);
if (HAL_UART_Init(&huart6) != HAL_OK) {
Error_Handler();
}
/* Infinite loop */
for(;;)
{
// 直接检查接收标志
if (__HAL_UART_GET_FLAG(&huart6, UART_FLAG_RXNE))
{
// 读取数据寄存器的原始值
uart6_dr_raw = huart6.Instance->DR;
// 解析数据寄存器的各个位
uart6_data_bits = (uint8_t)(uart6_dr_raw & 0xFF); // 低8位是数据位
uart6_parity_bit = (uint8_t)((uart6_dr_raw >> 8) & 0x1); // 第9位是校验位
uart6_stop_bits = (uint8_t)((uart6_dr_raw >> 9) & 0x3); // 第10-11位是停止位
// 存储错误标志
uart6_error_flags = 0;
if (__HAL_UART_GET_FLAG(&huart6, UART_FLAG_PE)) uart6_error_flags |= 0x01;
if (__HAL_UART_GET_FLAG(&huart6, UART_FLAG_FE)) uart6_error_flags |= 0x02;
if (__HAL_UART_GET_FLAG(&huart6, UART_FLAG_ORE)) uart6_error_flags |= 0x04;
// 使用数据位作为接收数据
rx_buffer[0] = uart6_data_bits;
// 检查是否有接收错误
if (uart6_error_flags == 0)
{
// 检查TCP连接状态
if (server_pcb_control != NULL && tcp_echo_flags_control == 1)
{
// 尝试发送数据
err = tcp_write(server_pcb_control, rx_buffer, 1, 1);
if (err == ERR_OK)
{
err = tcp_output(server_pcb_control);
if (err != ERR_OK)
{
// TCP输出失败可能需要重新建立连接
tcp_abort(server_pcb_control);
server_pcb_control = NULL;
tcp_echo_flags_control = 0;
}
}
else if (err == ERR_MEM)
{
// 内存不足,等待一段时间后重试
vTaskDelay(10);
}
else
{
// 其他错误,关闭连接
tcp_abort(server_pcb_control);
server_pcb_control = NULL;
tcp_echo_flags_control = 0;
}
}
}
else
{
// 清除错误标志
__HAL_UART_CLEAR_FLAG(&huart6, UART_FLAG_PE);
__HAL_UART_CLEAR_FLAG(&huart6, UART_FLAG_FE);
__HAL_UART_CLEAR_FLAG(&huart6, UART_FLAG_ORE);
}
}
vTaskDelay(1); // 给其他任务执行的机会
}
/* USER CODE END start_usart6_test_task */
}
void start_usart6_dma_test_task(void const *argument)
{
}