test/freetest/Core/Src/main.c

922 lines
26 KiB
C
Raw Permalink 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) 2026 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 "cmsis_os.h"
/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "hw_can.h"
#include "app_uds.h"
#include "app_iap.h"
#include "app_flash.h"
#include "stdio.h"
#include "string.h"
#if 1
#pragma import(__use_no_semihosting)
struct __FILE
{
int handle;
};
FILE __stdout;
void _sys_exit(int x)
{
x = x;
}
int fputc(int ch, FILE *f)
{
while((USART2->SR&0X40)==0);
USART2->DR = (unsigned char) ch;
return ch;
}
#endif
/* 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 ---------------------------------------------------------*/
CAN_HandleTypeDef hcan;
UART_HandleTypeDef huart2;
/* Definitions for defaultTask */
osThreadId_t defaultTaskHandle;
const osThreadAttr_t defaultTask_attributes = {
.name = "defaultTask",
.stack_size = 128 * 4,
.priority = (osPriority_t) osPriorityNormal,
};
/* Definitions for myTask02 */
osThreadId_t myTask02Handle;
const osThreadAttr_t myTask02_attributes = {
.name = "myTask02",
.stack_size = 128 * 4,
.priority = (osPriority_t) osPriorityLow,
};
/* Definitions for myTask03 */
osThreadId_t myTask03Handle;
const osThreadAttr_t myTask03_attributes = {
.name = "myTask03",
.stack_size = 128 * 4,
.priority = (osPriority_t) osPriorityLow,
};
/* Definitions for myTask04 */
osThreadId_t myTask04Handle;
const osThreadAttr_t myTask04_attributes = {
.name = "myTask04",
.stack_size = 128 * 4,
.priority = (osPriority_t) osPriorityLow,
};
/* Definitions for myTask05 */
osThreadId_t myTask05Handle;
const osThreadAttr_t myTask05_attributes = {
.name = "myTask05",
.stack_size = 128 * 4,
.priority = (osPriority_t) osPriorityLow,
};
/* Definitions for myTask06 */
osThreadId_t myTask06Handle;
const osThreadAttr_t myTask06_attributes = {
.name = "myTask06",
.stack_size = 128 * 4,
.priority = (osPriority_t) osPriorityLow,
};
/* Definitions for myTimer01 */
osTimerId_t myTimer01Handle;
const osTimerAttr_t myTimer01_attributes = {
.name = "myTimer01"
};
/* Definitions for myTimer02 */
osTimerId_t myTimer02Handle;
const osTimerAttr_t myTimer02_attributes = {
.name = "myTimer02"
};
/* Definitions for myMutex01 */
osMutexId_t myMutex01Handle;
const osMutexAttr_t myMutex01_attributes = {
.name = "myMutex01"
};
/* Definitions for myRecursiveMutex01 */
osMutexId_t myRecursiveMutex01Handle;
const osMutexAttr_t myRecursiveMutex01_attributes = {
.name = "myRecursiveMutex01",
.attr_bits = osMutexRecursive,
};
/* Definitions for myBinarySem01 */
osSemaphoreId_t myBinarySem01Handle;
const osSemaphoreAttr_t myBinarySem01_attributes = {
.name = "myBinarySem01"
};
/* Definitions for myBinarySem02 */
osSemaphoreId_t myBinarySem02Handle;
const osSemaphoreAttr_t myBinarySem02_attributes = {
.name = "myBinarySem02"
};
/* Definitions for myCountingSem01 */
osSemaphoreId_t myCountingSem01Handle;
const osSemaphoreAttr_t myCountingSem01_attributes = {
.name = "myCountingSem01"
};
/* Definitions for myCountingSem02 */
osSemaphoreId_t myCountingSem02Handle;
const osSemaphoreAttr_t myCountingSem02_attributes = {
.name = "myCountingSem02"
};
/* Definitions for myEvent01 */
osEventFlagsId_t myEvent01Handle;
const osEventFlagsAttr_t myEvent01_attributes = {
.name = "myEvent01"
};
/* Definitions for myEvent02 */
osEventFlagsId_t myEvent02Handle;
const osEventFlagsAttr_t myEvent02_attributes = {
.name = "myEvent02"
};
/* USER CODE BEGIN PV */
/* USER CODE END PV */
/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_USART2_UART_Init(void);
static void MX_CAN_Init(void);
void StartDefaultTask(void *argument);
void SampleTask(void *argument);
void Commtask(void *argument);
void CalcTask(void *argument);
void ProtectTask(void *argument);
void Can_Task(void *argument);
void Callback01(void *argument);
void Callback02(void *argument);
/* USER CODE BEGIN PFP */
/* USER CODE END PFP */
/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
/* 简化的 CAN 帧结构 */
//typedef struct {
// uint32_t id;
// uint32_t seq;
// uint8_t data[8];
// uint8_t dlc;
// uint32_t tick;
//} CanFrame_t;
/* 帧缓冲:环形缓冲区,模拟收到的帧 */
#define FRAME_BUF_SIZE 200
static CanFrame_t frame_buf[FRAME_BUF_SIZE];
static volatile uint8_t frame_write_idx = 0;
static uint8_t frame_read_idx = 0;
static volatile uint32_t frame_seq = 0; /* 帧序号,方便观察丢没丢 */
/* 模拟处理一帧 CAN 数据(耗时约 50ms */
void parse_can_frame(CanFrame_t *frame)
{
// printf("[处理] seq=%lu id=0x%lX tick=%lu ...处理中\r\n",
// frame->seq, frame->id, frame->tick);
// printf("[完成] seq=%lu 处理完毕\r\n", frame->seq);
// osDelay(5);
}
typedef struct{
uint16_t cell_voltage;
uint16_t cell_temp;
}Cell_Data;
Cell_Data cell_data;
/* USER CODE END 0 */
/**
* @brief The application entry point.
* @retval int
*/
int main(void)
{
/* USER CODE BEGIN 1 */
/* Bootloader 启动检查: 在 HAL_Init 之前调用, 此时环境最干净
* flag=UPGRADING → 停留 Bootloader 处理 IAP
* flag=COMPLETE/NONE → 跳转 App */
uds_bootloader_check();
/* USER CODE END 1 */
/* MCU Configuration--------------------------------------------------------*/
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* USER CODE BEGIN Init */
/* 如果是APP编程请求进入的Bootloader, 清除编程请求标志
* (擦除参数页, Flash只能1→0无法直接写0xFFFFFFFF) */
// if (iap_check_prog_request())
// iap_clear_prog_request();
/* 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_USART2_UART_Init();
MX_CAN_Init();
__disable_irq(); // 关中断
// iap_clear_prog_request();
uint8_t ret = flash_erase_page(IAP_PARAM_ADDR); // 擦除(~30ms)
__enable_irq();
/* USER CODE BEGIN 2 */
#if 0
__HAL_RCC_GPIOB_CLK_DISABLE(); // PB3 SWO 调试用,量产关闭
/* 2. 关闭未用 GPIO 的漏电流 */
/* STM32F103 未用引脚默认浮空输入,会漏电 */
/* 设为模拟输入可消除漏电流 */
GPIO_InitTypeDef GPIO_InitStruct = {0};
GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
GPIO_InitStruct.Pull = GPIO_NOPULL;
/* GPIOB 所有引脚(已关时钟,但先配置再关更安全) */
GPIO_InitStruct.Pin = GPIO_PIN_All;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
/* GPIOC 整个端口没用到,关时钟 + 模拟输入 */
__HAL_RCC_GPIOC_CLK_ENABLE();
GPIO_InitStruct.Pin = GPIO_PIN_All;
HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
__HAL_RCC_GPIOC_CLK_DISABLE();
#endif
/* USER CODE END 2 */
/* Init scheduler */
osKernelInitialize();
/* Create the mutex(es) */
/* creation of myMutex01 */
myMutex01Handle = osMutexNew(&myMutex01_attributes);
/* Create the recursive mutex(es) */
/* creation of myRecursiveMutex01 */
myRecursiveMutex01Handle = osMutexNew(&myRecursiveMutex01_attributes);
/* USER CODE BEGIN RTOS_MUTEX */
/* add mutexes, ... */
/* USER CODE END RTOS_MUTEX */
/* Create the semaphores(s) */
/* creation of myBinarySem01 */
myBinarySem01Handle = osSemaphoreNew(1, 1, &myBinarySem01_attributes);
/* creation of myBinarySem02 */
myBinarySem02Handle = osSemaphoreNew(1, 1, &myBinarySem02_attributes);
/* creation of myCountingSem01 */
myCountingSem01Handle = osSemaphoreNew(200, 0, &myCountingSem01_attributes);
/* creation of myCountingSem02 */
myCountingSem02Handle = osSemaphoreNew(2, 0, &myCountingSem02_attributes);
/* USER CODE BEGIN RTOS_SEMAPHORES */
/* add semaphores, ... */
/* USER CODE END RTOS_SEMAPHORES */
/* Create the timer(s) */
/* creation of myTimer01 */
myTimer01Handle = osTimerNew(Callback01, osTimerPeriodic, NULL, &myTimer01_attributes);
/* creation of myTimer02 */
myTimer02Handle = osTimerNew(Callback02, osTimerPeriodic, NULL, &myTimer02_attributes);
/* USER CODE BEGIN RTOS_TIMERS */
/* start timers, add new ones, ... */
// osTimerStart(myTimer01Handle, 10); // 50ms 一帧,和生产匹配
osTimerStart(myTimer02Handle, 500); // 50ms 一帧,和生产匹配
/* USER CODE END RTOS_TIMERS */
/* USER CODE BEGIN RTOS_QUEUES */
/* add queues, ... */
/* USER CODE END RTOS_QUEUES */
/* Create the thread(s) */
/* creation of defaultTask */
defaultTaskHandle = osThreadNew(StartDefaultTask, NULL, &defaultTask_attributes);
/* creation of myTask02 */
myTask02Handle = osThreadNew(SampleTask, NULL, &myTask02_attributes);
/* creation of myTask03 */
myTask03Handle = osThreadNew(Commtask, NULL, &myTask03_attributes);
/* creation of myTask04 */
myTask04Handle = osThreadNew(CalcTask, NULL, &myTask04_attributes);
/* creation of myTask05 */
myTask05Handle = osThreadNew(ProtectTask, NULL, &myTask05_attributes);
/* creation of myTask06 */
myTask06Handle = osThreadNew(Can_Task, NULL, &myTask06_attributes);
/* USER CODE BEGIN RTOS_THREADS */
/* add threads, ... */
/* USER CODE END RTOS_THREADS */
/* creation of myEvent01 */
myEvent01Handle = osEventFlagsNew(&myEvent01_attributes);
/* creation of myEvent02 */
myEvent02Handle = osEventFlagsNew(&myEvent02_attributes);
/* USER CODE BEGIN RTOS_EVENTS */
/* add events, ... */
/* USER CODE END RTOS_EVENTS */
/* Start scheduler */
osKernelStart();
/* We should never get here as control is now taken by the scheduler */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
}
/**
* @brief System Clock Configuration
* @retval None
*/
void SystemClock_Config(void)
{
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
RCC_ClkInitTypeDef RCC_ClkInitStruct = {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();
}
}
/**
* @brief CAN Initialization Function
* @param None
* @retval None
*/
static void MX_CAN_Init(void)
{
/* USER CODE BEGIN CAN_Init 0 */
/* USER CODE END CAN_Init 0 */
/* USER CODE BEGIN CAN_Init 1 */
/* USER CODE END CAN_Init 1 */
hcan.Instance = CAN1;
hcan.Init.Prescaler = 9;
hcan.Init.Mode = CAN_MODE_NORMAL;
hcan.Init.SyncJumpWidth = CAN_SJW_1TQ;
hcan.Init.TimeSeg1 = CAN_BS1_6TQ;
hcan.Init.TimeSeg2 = CAN_BS2_1TQ;
hcan.Init.TimeTriggeredMode = DISABLE;
hcan.Init.AutoBusOff = ENABLE;
hcan.Init.AutoWakeUp = ENABLE;
hcan.Init.AutoRetransmission = DISABLE;
hcan.Init.ReceiveFifoLocked = DISABLE;
hcan.Init.TransmitFifoPriority = DISABLE;
if (HAL_CAN_Init(&hcan) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN CAN_Init 2 */
hwCanInit();
/* USER CODE END CAN_Init 2 */
}
/**
* @brief USART2 Initialization Function
* @param None
* @retval None
*/
static void MX_USART2_UART_Init(void)
{
/* USER CODE BEGIN USART2_Init 0 */
/* USER CODE END USART2_Init 0 */
/* USER CODE BEGIN USART2_Init 1 */
/* USER CODE END USART2_Init 1 */
huart2.Instance = USART2;
huart2.Init.BaudRate = 115200;
huart2.Init.WordLength = UART_WORDLENGTH_8B;
huart2.Init.StopBits = UART_STOPBITS_1;
huart2.Init.Parity = UART_PARITY_NONE;
huart2.Init.Mode = UART_MODE_TX_RX;
huart2.Init.HwFlowCtl = UART_HWCONTROL_NONE;
huart2.Init.OverSampling = UART_OVERSAMPLING_16;
if (HAL_UART_Init(&huart2) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN USART2_Init 2 */
/* USER CODE END USART2_Init 2 */
}
/**
* @brief GPIO Initialization Function
* @param None
* @retval None
*/
static void MX_GPIO_Init(void)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
/* USER CODE BEGIN MX_GPIO_Init_1 */
/* USER CODE END MX_GPIO_Init_1 */
/* GPIO Ports Clock 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_15, GPIO_PIN_RESET);
/*Configure GPIO pin : PA15 */
GPIO_InitStruct.Pin = 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(GPIOA, &GPIO_InitStruct);
/* USER CODE BEGIN MX_GPIO_Init_2 */
/* USER CODE END MX_GPIO_Init_2 */
}
volatile uint32_t rx_total_cnt = 0; /* 接收成功计数 */
volatile uint32_t rx_fail_cnt = 0; /* 接收失败计数(HAL_LOCK冲突) */
volatile uint32_t tx_fail_cnt = 0; /* 发送失败计数 */
/* USER CODE BEGIN 4 */
/* CAN 接收中断回调:把收到的帧存入环形缓冲并通知处理任务 */
static void can_rx_store(uint8_t fifo)
{
#if 1
CAN_RxHeaderTypeDef rx_hdr;
CanFrame_t *f = &frame_buf[frame_write_idx % FRAME_BUF_SIZE];
/* 从 FIFO 取出一帧(中断里必须立即取走,否则会溢出) */
if (HAL_CAN_GetRxMessage(&hcan, fifo, &rx_hdr, f->data) != HAL_OK){
rx_fail_cnt++;
return;
}
else {
rx_total_cnt++;
}
f->id = rx_hdr.StdId;
f->dlc = rx_hdr.DLC;
f->seq = frame_seq++;
f->tick = HAL_GetTick();
frame_write_idx++;
/* 通知处理任务CMSIS-RTOS2 自动识别中断上下文,内部走 FromISR */
/* 判空防抖:信号量可能尚未创建(启动瞬间) */
if (myCountingSem01Handle != NULL)
osSemaphoreRelease(myCountingSem01Handle);
#else
CAN_RxHeaderTypeDef rx_hdr;
CanFrame_t *f = &frame_buf[frame_write_idx % FRAME_BUF_SIZE];
/* 直接读FIFO寄存器,绕过HAL_LOCK */
uint8_t fifo_offset = (fifo == CAN_RX_FIFO0) ? 0 : 3;
/* 检查FIFO非空 */
if ((hcan.Instance->RF0R & CAN_RF0R_FMP0) == 0 && fifo == CAN_RX_FIFO0)
{
rx_fail_cnt++;
return;
}
if ((hcan.Instance->RF1R & CAN_RF1R_FMP1) == 0 && fifo == CAN_RX_FIFO1)
{
rx_fail_cnt++;
return;
}
/* 读标准帧ID */
if (fifo == CAN_RX_FIFO0)
{
rx_hdr.StdId = (hcan.Instance->sFIFOMailBox[0].RIR >> 21) & 0x7FF;
rx_hdr.DLC = hcan.Instance->sFIFOMailBox[0].RDTR & 0x0F;
((uint32_t*)f->data)[0] = hcan.Instance->sFIFOMailBox[0].RDLR;
((uint32_t*)f->data)[1] = hcan.Instance->sFIFOMailBox[0].RDHR;
/* 释放FIFO0 */
hcan.Instance->RF0R |= CAN_RF0R_RFOM0;
}
else
{
rx_hdr.StdId = (hcan.Instance->sFIFOMailBox[1].RIR >> 21) & 0x7FF;
rx_hdr.DLC = hcan.Instance->sFIFOMailBox[1].RDTR & 0x0F;
((uint32_t*)f->data)[0] = hcan.Instance->sFIFOMailBox[1].RDLR;
((uint32_t*)f->data)[1] = hcan.Instance->sFIFOMailBox[1].RDHR;
/* 释放FIFO1 */
hcan.Instance->RF1R |= CAN_RF1R_RFOM1;
}
rx_total_cnt++;
f->id = rx_hdr.StdId;
f->dlc = rx_hdr.DLC;
f->seq = frame_seq++;
f->tick = HAL_GetTick();
frame_write_idx++;
if (myCountingSem01Handle != NULL)
osSemaphoreRelease(myCountingSem01Handle);
#endif
}
void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef *hcan_def)
{
(void)hcan_def;
if(hcan_def == &hcan){
can_rx_store(CAN_RX_FIFO0);
}
}
void HAL_CAN_RxFifo1MsgPendingCallback(CAN_HandleTypeDef *hcan_def)
{
(void)hcan_def;
if(hcan_def == &hcan){
can_rx_store(CAN_RX_FIFO1);
}
}
volatile uint32_t tx_complete_cnt_mail00 = 0;
volatile uint32_t tx_complete_cnt_mail01 = 0;
volatile uint32_t tx_complete_cnt_mail02 = 0;
void HAL_CAN_TxMailbox0CompleteCallback(CAN_HandleTypeDef *hcan)
{
tx_complete_cnt_mail00++;
}
void HAL_CAN_TxMailbox1CompleteCallback(CAN_HandleTypeDef *hcan)
{
tx_complete_cnt_mail01++;
}
void HAL_CAN_TxMailbox2CompleteCallback(CAN_HandleTypeDef *hcan)
{
tx_complete_cnt_mail02++;
}
void test_uds(void)
{
}
/* USER CODE END 4 */
uint32_t frame_seq_task = 0;
/* USER CODE BEGIN Header_StartDefaultTask */
/**
* @brief Function implementing the defaultTask thread.
* @param argument: Not used
* @retval None
*/
/* USER CODE END Header_StartDefaultTask */
void StartDefaultTask(void *argument)
{
/* USER CODE BEGIN 5 */
uint32_t can_test_id = 0x0000;
/* Infinite loop */
for(;;)
{
// ① Binary Sem等 Timer release 后通过
// if (osSemaphoreAcquire(myBinarySem01Handle, osWaitForever) == osOK)
// {
// printf("Binary Sem acquired, tick=%lu\r\n", HAL_GetTick());
// }
// ② Counting Sem等 Timer release 后通过
// if (osSemaphoreAcquire(myCountingSem01Handle, osWaitForever) == osOK)
// {
// printf("Counting Sem acquired, tick=%lu\r\n", HAL_GetTick());
// }
/* 阻塞等待 Counting Sem有帧可处理才往下走 */
if (osSemaphoreAcquire(myCountingSem01Handle, osWaitForever) == osOK)
{
CanFrame_t *f = &frame_buf[frame_read_idx % FRAME_BUF_SIZE];
frame_read_idx++;
/* 打印当前积压数max=2超过2的会被丢弃 */
// printf(">>> 取出 seq=%lu, 当前积压=%d\r\n",
// f->seq, osSemaphoreGetCount(myCountingSem01Handle));
// can_test_id = frame_read_idx;
// uds_frame_handle(f);
// parse_can_frame(f);
// test_uds();
// if (hwCanSend(can_test_id, f->data, f->dlc))
// {
// // printf("[发送] ID=0x180 成功\r\n");
// frame_seq_task++;
// }
// else{
// printf("[发送] ID=0x181 失败\r\n");
// }
iap_process_frame(f->id,f->data,f->dlc);
}
// if(osSemaphoreAcquire(myBinarySem02Handle,osWaitForever) == osOK){
// // printf("this is BinarySem02\r\n");
// HAL_GPIO_TogglePin(GPIOA, GPIO_PIN_15);
// }
}
/* USER CODE END 5 */
}
/* USER CODE BEGIN Header_SampleTask */
/**
* @brief Function implementing the myTask02 thread.
* @param argument: Not used
* @retval None
*/
/* USER CODE END Header_SampleTask */
void SampleTask(void *argument)
{
/* USER CODE BEGIN SampleTask */
/* Infinite loop */
for(;;)
{
// iap_clear_prog_request();
osDelay(500);
}
/* USER CODE END SampleTask */
}
/* USER CODE BEGIN Header_Commtask */
/**
* @brief Function implementing the myTask03 thread.
* @param argument: Not used
* @retval None
*/
/* USER CODE END Header_Commtask */
void Commtask(void *argument)
{
/* USER CODE BEGIN Commtask */
/* Infinite loop */
for(;;)
{
// osMutexAcquire(myMutex01Handle, osWaitForever);
// // printf("cell_data.cellvoltage:%d ",cell_data.cell_voltage);
// // printf("cell_data.cell_temp:%d \r\n",cell_data.cell_temp);
// osMutexRelease(myMutex01Handle);
// osDelay(100);
}
/* USER CODE END Commtask */
}
/* USER CODE BEGIN Header_CalcTask */
/**
* @brief Function implementing the myTask04 thread.
* @param argument: Not used
* @retval None
*/
/* USER CODE END Header_CalcTask */
void CalcTask(void *argument)
{
/* USER CODE BEGIN CalcTask */
/* Infinite loop */
for(;;)
{
// /* 等 bit0 和 bit1 都置位才唤醒 */
// osEventFlagsWait(myEvent01Handle,
// EVT_VOLTAGE_READY | EVT_TEMP_READY,
// osFlagsWaitAll, /* AND 逻辑 */
// osWaitForever);
// osMutexAcquire(myMutex01Handle, osWaitForever);
// uint16_t v = cell_data.cell_voltage;
// uint16_t t = cell_data.cell_temp;
// osMutexRelease(myMutex01Handle);
// printf("[计算] V=%d T=%d\r\n", v, t);
}
/* USER CODE END CalcTask */
}
/* USER CODE BEGIN Header_ProtectTask */
/**
* @brief Function implementing the myTask05 thread.
* @param argument: Not used
* @retval None
*/
/* USER CODE END Header_ProtectTask */
void ProtectTask(void *argument)
{
/* USER CODE BEGIN ProtectTask */
/* Infinite loop */
for(;;)
{
/* 等 bit2/bit3/bit4 任一个置位就唤醒 */
// uint32_t flags = osEventFlagsWait(myEvent01Handle,
// EVT_OVER_VOLTAGE | EVT_OVER_TEMP | EVT_COMM_TIMEOUT,
// osFlagsWaitAny, /* OR 逻辑 */
// osWaitForever);
// if (flags & EVT_OVER_VOLTAGE)
// printf("[报警] 过压! V=%d\r\n", cell_data.cell_voltage);
// if (flags & EVT_OVER_TEMP)
// printf("[报警] 过温! T=%d\r\n", cell_data.cell_temp);
// if (flags & EVT_COMM_TIMEOUT)
// printf("[报警] 通信超时!\r\n");
}
/* USER CODE END ProtectTask */
}
/* USER CODE BEGIN Header_Can_Task */
/**
* @brief Function implementing the myTask06 thread.
* @param argument: Not used
* @retval None
*/
/* USER CODE END Header_Can_Task */
void Can_Task(void *argument)
{
/* USER CODE BEGIN Can_Task */
uint8_t tx_data[8] = {0};
uint32_t counter = 0;
for(;;)
{
/* 周期发送 BMS 电压/温度上报帧 0x180 */
// tx_data[0] = counter++;
// tx_data[1] = cell_data.cell_voltage >> 8; /* 电压高字节 */
// tx_data[2] = cell_data.cell_voltage & 0xFF; /* 电压低字节 */
// tx_data[3] = cell_data.cell_temp >> 8; /* 温度高字节 */
// tx_data[4] = cell_data.cell_temp & 0xFF; /* 温度低字节 */
// if (hwCanSend(0x180, tx_data, 8))
// {
// // printf("[发送] ID=0x180 成功\r\n");
// }
// else
// {
// printf("[发送] ID=0x180 失败(邮箱忙)\r\n");
// }
osDelay(100); /* 100ms 发送一帧 */
}
/* USER CODE END Can_Task */
}
/* Callback01 function */
void Callback01(void *argument)
{
/* USER CODE BEGIN Callback01 */
/* 模拟收到一帧 CAN 数据 */
// CanFrame_t *f = &frame_buf[frame_write_idx % FRAME_BUF_SIZE];
// f->id = 0x180 + (frame_seq % 8); /* 模拟不同 ID */
// f->dlc = 8;
// f->seq = frame_seq;
// f->tick = HAL_GetTick();
// memset(f->data, frame_seq, 8);
// frame_write_idx++;
// frame_seq++;
// // 周期触发,给 Counting Sem 释放一次(计数 +1
// osSemaphoreRelease(myCountingSem01Handle); // 给 Counting Sem
// osSemaphoreRelease(myBinarySem01Handle); // 给 Binary Sem
/* USER CODE END Callback01 */
}
/* Callback02 function */
void Callback02(void *argument)
{
/* USER CODE BEGIN Callback02 */
osSemaphoreRelease(myBinarySem02Handle); // 给 Counting Sem
osEventFlagsSet(myEvent01Handle, EVT_COMM_TIMEOUT);
/* USER CODE END Callback02 */
}
/**
* @brief Period elapsed callback in non blocking mode
* @note This function is called when TIM1 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 == TIM1)
{
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 */