/* 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"
/* Private variables ---------------------------------------------------------*/
CAN_HandleTypeDef hcan;
CAN_TxHeaderTypeDef TxHeader;
CAN_RxHeaderTypeDef RxHeader;
uint8_t TxData[8];
uint8_t RxData[8];
uint32_t TxMailbox;
/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_CAN_Init(void);
static void CAN_ConfigFilter(void);
static void CAN_SendOBD2Data(uint8_t pid, uint8_t value);
/* USER CODE BEGIN 0 */
/* USER CODE END 0 */
/**
* @brief The application entry point.
* @retval int
*/
int main(void)
{
/* MCU Configuration--------------------------------------------------------*/
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
MX_CAN_Init();
CAN_ConfigFilter();
/* Start CAN */
HAL_CAN_Start(&hcan);
/* Activate CAN RX interrupt */
HAL_CAN_ActivateNotification(&hcan, CAN_IT_RX_FIFO0_MSG_PENDING);
/* USER CODE BEGIN WHILE */
int x=0;
while (1)
{
/* Giả lập tốc độ động cơ 1500 RPM (OBD-II PID: 0x0D) */
CAN_SendOBD2Data(0x0D, (60+x)); // 60 km/h
x++;
HAL_Delay(200);
if(x==1000) x=0;
}
/* USER CODE END WHILE */
}
/**
* @brief Cấu hình bộ lọc CAN
*/
static void CAN_ConfigFilter(void)
{
CAN_FilterTypeDef canFilter;
canFilter.FilterBank = 0;
canFilter.FilterMode = CAN_FILTERMODE_IDMASK;
canFilter.FilterScale = CAN_FILTERSCALE_32BIT;
canFilter.FilterIdHigh = 0x7DF << 5; // ID của máy chẩn đoán gửi đến ECU
canFilter.FilterIdLow = 0;
canFilter.FilterMaskIdHigh = 0x7FF << 5;
canFilter.FilterMaskIdLow = 0;
canFilter.FilterFIFOAssignment = CAN_RX_FIFO0;
canFilter.FilterActivation = ENABLE;
HAL_CAN_ConfigFilter(&hcan, &canFilter);
}
/**
* @brief Hàm gửi dữ liệu OBD-II qua CAN
* @param pid: Mã PID OBD-II
* @param value: Giá trị của PID
*/
static void CAN_SendOBD2Data(uint8_t pid, uint8_t value)
{
TxHeader.StdId = 0x7E8; // ECU phản hồi (ID tiêu chuẩn)
TxHeader.ExtId = 0;
TxHeader.RTR = CAN_RTR_DATA;
TxHeader.IDE = CAN_ID_STD;
TxHeader.DLC = 4;
TxData[0] = 0x03; // Số byte dữ liệu (2 byte)
TxData[1] = 0x41; // Phản hồi OBD-II (41 = phản hồi của 01 - yêu cầu)
TxData[2] = pid; // PID phản hồi
TxData[3] = value; // Giá trị của PID (ví dụ tốc độ xe km/h)
HAL_CAN_AddTxMessage(&hcan, &TxHeader, TxData, &TxMailbox);
}
/**
* @brief Callback khi nhận được dữ liệu CAN
*/
/* void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef *hcan)
{
HAL_CAN_GetRxMessage(hcan, CAN_RX_FIFO0, &RxHeader, RxData);
if (RxHeader.StdId == 0x7DF) // Máy chẩn đoán gửi yêu cầu
{
if (RxData[1] == 0x10) // Yêu cầu dữ liệu OBD-II
{
uint8_t requested_pid = RxData[2];
if (requested_pid == 0x0D) // Yêu cầu tốc độ xe
{
CAN_SendOBD2Data(0x0D, 3C); // Phản hồi tốc độ 60 km/h
}
}
}
} */
// Phản hồi tốc độ 60 km/h
void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef *hcan)
{
HAL_CAN_GetRxMessage(hcan, CAN_RX_FIFO0, &RxHeader, RxData);
CAN_SendOBD2Data(0x0D, 60); }// Phản hồi tốc độ 60 km/h
/*if (RxHeader.StdId == 0x7DF) // Máy chẩn đoán gửi yêu cầu
{
CAN_SendOBD2Data(0x0D, 60); // Phản hồi tốc độ 60 km/h
}
}*/
/**
* @brief CAN Initialization Function
*/
static void MX_CAN_Init(void)
{
hcan.Instance = CAN1;
hcan.Init.Prescaler = 18;
hcan.Init.Mode = CAN_MODE_NORMAL;
hcan.Init.SyncJumpWidth = CAN_SJW_1TQ;
hcan.Init.TimeSeg1 = CAN_BS1_2TQ;
hcan.Init.TimeSeg2 = CAN_BS2_1TQ;
hcan.Init.TimeTriggeredMode = DISABLE;
hcan.Init.AutoBusOff = DISABLE;
hcan.Init.AutoWakeUp = DISABLE;
hcan.Init.AutoRetransmission = DISABLE;
hcan.Init.ReceiveFifoLocked = DISABLE;
hcan.Init.TransmitFifoPriority = DISABLE;
if (HAL_CAN_Init(&hcan) != HAL_OK)
{
Error_Handler();
}
}
/**
* @brief GPIO Initialization Function
*/
static void MX_GPIO_Init(void)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
__HAL_RCC_GPIOC_CLK_ENABLE();
__HAL_RCC_GPIOA_CLK_ENABLE();
/*Configure GPIO pin Output Level */
HAL_GPIO_WritePin(GPIOC, GPIO_PIN_13, GPIO_PIN_RESET);
/*Configure GPIO pin : PC13 */
GPIO_InitStruct.Pin = GPIO_PIN_13;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
}
/**
* @brief System Clock Configuration
*/
void SystemClock_Config(void)
{
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
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.PLLMUL = RCC_PLL_MUL9;
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
{
Error_Handler();
}
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 Error Handler
*/
void Error_Handler(void)
{
__disable_irq();
while (1)
{
}
}