Creating a CANopen Protocol
I'm creating a CANopen protocol, but I'm having a problem with the code. I used two while loops, and as far as I understand, this is preventing me from seeing the data I'm getting from the sensor in the 'live expression' section. Do you have any suggestions?
/* 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"
/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include <math.h>
/* USER CODE END Includes */
/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */
/* USER CODE END PTD */
/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
#define KEY_PRESSED GPIO_PIN_RESET
#define KEY_NOT_PRESSED GPIO_PIN_SET
/* USER CODE END PD */
/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */
/* USER CODE END PM */
/* Private variables ---------------------------------------------------------*/
ADC_HandleTypeDef hadc1;
DMA_HandleTypeDef hdma_adc1;
FDCAN_HandleTypeDef hfdcan1;
TIM_HandleTypeDef htim16;
/* USER CODE BEGIN PV */
FDCAN_TxHeaderTypeDef TxTransmitter; // TxTransmitter Structure'ı
FDCAN_RxHeaderTypeDef rxHeader; // Ortak RX okuma başlığı
uint32_t verici_bilgileri[5];
// LIVE EXPRESSIONS İÇİN VOLATILE EKLENDİ
volatile uint32_t ADC[3];
volatile uint8_t temp1, temp2, temp3;
volatile uint8_t istenilen_sicaklik[8];
volatile uint8_t sayac = 0;
volatile uint8_t start = 0;
uint8_t tx_buffer[8];
uint8_t heartbeat[2];
uint8_t NodeID = 1;
uint8_t rxData[8]; // Gelen mesajları tutacağımız ortak buffer
/* USER CODE END PV */
/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_DMA_Init(void);
static void MX_ADC1_Init(void);
static void MX_FDCAN1_Init(void);
static void MX_TIM16_Init(void);
/* USER CODE BEGIN PFP */
void systemReset(void);
double Thermistor(int analogValue);
/* USER CODE END PFP */
/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
if (htim == &htim16)
{
while (HAL_FDCAN_GetRxFifoFillLevel(&hfdcan1, FDCAN_RX_FIFO0) > 0)
{
// Mesajı kuyruktan bir kez okuyoruz
if (HAL_FDCAN_GetRxMessage(&hfdcan1, FDCAN_RX_FIFO0, &rxHeader, rxData) == HAL_OK)
{
/* --- NMT MESAJI KONTROLÜ (ID: 0x00) --- */
if (rxHeader.Identifier == 0x00 && rxHeader.DataLength == FDCAN_DLC_BYTES_2)
{
switch (rxData[0])
{
case 0x01: // Start
HAL_ADC_Start_DMA(&hadc1, (uint32_t*)ADC, 3); // &ADC hatası düzeltildi
start = 1;
break;
case 0x02: // Stop
HAL_ADC_Stop_DMA(&hadc1);
start = 0;
break;
case 0x81: // Reset Node
systemReset();
break;
}
}
/* Sistem Start edildiyse diğer komutları dinle */
if (start == 1)
{
/* --- RPDO KONTROLÜ (Örn ID: 0x201) --- */
if (rxHeader.Identifier == 0x201)
{
// RPDO ile gelen ilk byte istenilen sıcaklık
istenilen_sicaklik[0] = rxData[0];
if (temp1 >= istenilen_sicaklik[0] || temp2 >= istenilen_sicaklik[0] || temp3 >= istenilen_sicaklik[0])
{
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5, SET);
}
else
{
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5, RESET);
}
}
/* --- SDO KONTROLÜ (Örn ID: 0x601) --- */
else if (rxHeader.Identifier == 0x601)
{
// 1. OKUMA İSTEĞİ (0x20 ---> SENSÖR VERİLERİ)
if (rxData[3] == 0x04 && rxData[4] == 0x20)
{
TxTransmitter.Identifier = 0x581;
TxTransmitter.IdType = FDCAN_STANDARD_ID;
TxTransmitter.TxFrameType = FDCAN_DATA_FRAME;
TxTransmitter.DataLength = FDCAN_DLC_BYTES_8;
TxTransmitter.ErrorStateIndicator = FDCAN_ESI_ACTIVE;
TxTransmitter.BitRateSwitch = FDCAN_BRS_OFF;
TxTransmitter.FDFormat = FDCAN_CLASSIC_CAN;
TxTransmitter.TxEventFifoControl = FDCAN_NO_TX_EVENTS;
TxTransmitter.MessageMarker = 0;
tx_buffer[0] = temp1;
tx_buffer[1] = temp2;
tx_buffer[2] = temp3;
tx_buffer[3] = 0;
tx_buffer[4] = 0;
tx_buffer[5] = 0;
tx_buffer[6] = 0;
tx_buffer[7] = 0;
HAL_FDCAN_AddMessageToTxFifoQ(&hfdcan1, &TxTransmitter, tx_buffer);
}
// 2. DİĞER OKUMA İSTEĞİ (0x21 ---> İSTENİLEN SICAKLIK DEĞERİ VERİSİ)
else if (rxData[3] == 0x04 && rxData[4] == 0x21)
{
TxTransmitter.Identifier = 0x581;
TxTransmitter.IdType = FDCAN_STANDARD_ID;
TxTransmitter.TxFrameType = FDCAN_DATA_FRAME;
TxTransmitter.DataLength = FDCAN_DLC_BYTES_8;
TxTransmitter.ErrorStateIndicator = FDCAN_ESI_ACTIVE;
TxTransmitter.BitRateSwitch = FDCAN_BRS_OFF;
TxTransmitter.FDFormat = FDCAN_CLASSIC_CAN;
TxTransmitter.TxEventFifoControl = FDCAN_NO_TX_EVENTS;
TxTransmitter.MessageMarker = 0;
tx_buffer[0] = istenilen_sicaklik[0];
tx_buffer[1] = 0;
tx_buffer[2] = 0;
tx_buffer[3] = 0;
tx_buffer[4] = 0;
tx_buffer[5] = 0;
tx_buffer[6] = 0;
tx_buffer[7] = 0;
HAL_FDCAN_AddMessageToTxFifoQ(&hfdcan1, &TxTransmitter, tx_buffer);
}
// 3. YAZMA/DEĞİŞTİRME İSTEĞİ (0x22)
else if (rxData[3] == 0x04 && rxData[4] == 0x22)
{
istenilen_sicaklik[0] = rxData[5];
// Veriyi başarıyla aldım ve güncelledim (ACK)
TxTransmitter.Identifier = 0x601;
TxTransmitter.IdType = FDCAN_STANDARD_ID;
TxTransmitter.TxFrameType = FDCAN_DATA_FRAME;
TxTransmitter.DataLength = FDCAN_DLC_BYTES_8;
TxTransmitter.ErrorStateIndicator = FDCAN_ESI_ACTIVE;
TxTransmitter.BitRateSwitch = FDCAN_BRS_OFF;
TxTransmitter.FDFormat = FDCAN_CLASSIC_CAN;
TxTransmitter.TxEventFifoControl = FDCAN_NO_TX_EVENTS;
TxTransmitter.MessageMarker = 0;
tx_buffer[0] = 0x60; // CANopen SDO Success
tx_buffer[1] = 0;
tx_buffer[2] = 0;
tx_buffer[3] = 0;
tx_buffer[4] = 0;
tx_buffer[5] = 0;
tx_buffer[6] = 0;
tx_buffer[7] = 0;
HAL_FDCAN_AddMessageToTxFifoQ(&hfdcan1, &TxTransmitter, tx_buffer);
}
}
}
}
} // RX okuma bloğu bitti
sayac++;
if (sayac >= 10) // sayac==10 yerine güvenli olması için >= yapıldı
{
if (start == 1)
{
/*------HeartBeat-------*/
TxTransmitter.Identifier = 0x701;
TxTransmitter.IdType = FDCAN_STANDARD_ID;
TxTransmitter.TxFrameType = FDCAN_DATA_FRAME;
TxTransmitter.DataLength = FDCAN_DLC_BYTES_2;
TxTransmitter.ErrorStateIndicator = FDCAN_ESI_ACTIVE;
TxTransmitter.BitRateSwitch = FDCAN_BRS_OFF;
TxTransmitter.FDFormat = FDCAN_CLASSIC_CAN;
TxTransmitter.TxEventFifoControl = FDCAN_NO_TX_EVENTS;
TxTransmitter.MessageMarker = 0;
heartbeat[0] = 0x5F;
heartbeat[1] = 0x7F;
HAL_FDCAN_AddMessageToTxFifoQ(&hfdcan1, &TxTransmitter, heartbeat);
/*------TPDO-------*/
TxTransmitter.Identifier = 0x181;
TxTransmitter.IdType = FDCAN_STANDARD_ID;
TxTransmitter.TxFrameType = FDCAN_DATA_FRAME;
TxTransmitter.DataLength = FDCAN_DLC_BYTES_8;
TxTransmitter.ErrorStateIndicator = FDCAN_ESI_ACTIVE;
TxTransmitter.BitRateSwitch = FDCAN_BRS_OFF;
TxTransmitter.FDFormat = FDCAN_CLASSIC_CAN;
TxTransmitter.TxEventFifoControl = FDCAN_NO_TX_EVENTS;
TxTransmitter.MessageMarker = 0;
tx_buffer[0] = temp1;
tx_buffer[1] = temp2;
tx_buffer[2] = temp3;
tx_buffer[3] = 0;
tx_buffer[4] = 0;
tx_buffer[5] = 0;
tx_buffer[6] = 0;
tx_buffer[7] = 0;
HAL_FDCAN_AddMessageToTxFifoQ(&hfdcan1, &TxTransmitter, tx_buffer);
}
sayac = 0;
}
}
}
void systemReset(void)
{
NVIC_SystemReset();
}
double Thermistor(int analogValue)
{
// Cihaz kısa devre veya kopuksa (0 veya çok yüksek değerler) formüle sokma
if (analogValue > 0 && analogValue < 4095)
{
double temperature;
temperature = log(((40950000.0 / analogValue) - 10000.0)); // Matematiksel hassasiyet düzeltildi (.0)
temperature = 1.0 / (0.001129148 + (0.000234125 + (0.0000000876741 * temperature * temperature)) * temperature);
temperature = temperature - 273.15;
return temperature;
}
return 0.0; // Güvenli varsayılan değer
}
/* 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_FDCAN1_Init();
MX_TIM16_Init();
/* USER CODE BEGIN 2 */
// ÇOK ÖNEMLİ: ADC Kalibrasyonu olmadan DMA doğru okuma yapmaz.
HAL_ADCEx_Calibration_Start(&hadc1, ADC_SINGLE_ENDED);
HAL_FDCAN_Start(&hfdcan1);
HAL_TIM_Base_Start_IT(&htim16);
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
/*---------NTC VERİLERİNİN CELCİUS'A DÖNÜŞÜMÜ---------*/
temp1 = (uint8_t)Thermistor(ADC[0]);
temp2 = (uint8_t)Thermistor(ADC[1]);
temp3 = (uint8_t)Thermistor(ADC[2]);
/* 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_PWREx_ControlVoltageScaling(PWR_REGULATOR_VOLTAGE_SCALE1_BOOST);
/** Initializes the RCC Oscillators according to the specified parameters
* in the RCC_OscInitTypeDef structure.
*/
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
RCC_OscInitStruct.HSIState = RCC_HSI_ON;
RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI;
RCC_OscInitStruct.PLL.PLLM = RCC_PLLM_DIV4;
RCC_OscInitStruct.PLL.PLLN = 85;
RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
RCC_OscInitStruct.PLL.PLLQ = RCC_PLLQ_DIV2;
RCC_OscInitStruct.PLL.PLLR = RCC_PLLR_DIV2;
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_DIV1;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_4) != HAL_OK)
{
Error_Handler();
}
}
/**
* @brief ADC1 Initialization Function
* None
* @retval None
*/
static void MX_ADC1_Init(void)
{
ADC_MultiModeTypeDef multimode = {0};
ADC_ChannelConfTypeDef sConfig = {0};
hadc1.Instance = ADC1;
hadc1.Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV4;
hadc1.Init.Resolution = ADC_RESOLUTION_12B;
hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT;
hadc1.Init.GainCompensation = 0;
hadc1.Init.ScanConvMode = ADC_SCAN_ENABLE;
hadc1.Init.EOCSelection = ADC_EOC_SINGLE_CONV;
hadc1.Init.LowPowerAutoWait = DISABLE;
hadc1.Init.ContinuousConvMode = ENABLE;
hadc1.Init.NbrOfConversion = 3;
hadc1.Init.DiscontinuousConvMode = DISABLE;
hadc1.Init.ExternalTrigConv = ADC_SOFTWARE_START;
hadc1.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;
hadc1.Init.DMAContinuousRequests = ENABLE;
hadc1.Init.Overrun = ADC_OVR_DATA_PRESERVED;
hadc1.Init.OversamplingMode = DISABLE;
if (HAL_ADC_Init(&hadc1) != HAL_OK)
{
Error_Handler();
}
multimode.Mode = ADC_MODE_INDEPENDENT;
if (HAL_ADCEx_MultiModeConfigChannel(&hadc1, &multimode) != HAL_OK)
{
Error_Handler();
}
sConfig.Channel = ADC_CHANNEL_1;
sConfig.Rank = ADC_REGULAR_RANK_1;
sConfig.SamplingTime = ADC_SAMPLETIME_92CYCLES_5;
sConfig.SingleDiff = ADC_SINGLE_ENDED;
sConfig.OffsetNumber = ADC_OFFSET_NONE;
sConfig.Offset = 0;
if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
{
Error_Handler();
}
sConfig.Channel = ADC_CHANNEL_2;
sConfig.Rank = ADC_REGULAR_RANK_2;
if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
{
Error_Handler();
}
sConfig.Channel = ADC_CHANNEL_9;
sConfig.Rank = ADC_REGULAR_RANK_3;
if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
{
Error_Handler();
}
}
/**
* @brief FDCAN1 Initialization Function
* None
* @retval None
*/
static void MX_FDCAN1_Init(void)
{
hfdcan1.Instance = FDCAN1;
hfdcan1.Init.ClockDivider = FDCAN_CLOCK_DIV1;
hfdcan1.Init.FrameFormat = FDCAN_FRAME_CLASSIC;
hfdcan1.Init.Mode = FDCAN_MODE_NORMAL;
hfdcan1.Init.AutoRetransmission = DISABLE;
hfdcan1.Init.TransmitPause = DISABLE;
hfdcan1.Init.ProtocolException = DISABLE;
hfdcan1.Init.NominalPrescaler = 40;
hfdcan1.Init.NominalSyncJumpWidth = 1;
hfdcan1.Init.NominalTimeSeg1 = 14;
hfdcan1.Init.NominalTimeSeg2 = 2;
hfdcan1.Init.DataPrescaler = 1;
hfdcan1.Init.DataSyncJumpWidth = 1;
hfdcan1.Init.DataTimeSeg1 = 1;
hfdcan1.Init.DataTimeSeg2 = 1;
hfdcan1.Init.StdFiltersNbr = 0;
hfdcan1.Init.ExtFiltersNbr = 0;
hfdcan1.Init.TxFifoQueueMode = FDCAN_TX_FIFO_OPERATION;
if (HAL_FDCAN_Init(&hfdcan1) != HAL_OK)
{
Error_Handler();
}
FDCAN_FilterTypeDef fdcan_filtre_yapi;
fdcan_filtre_yapi.IdType = FDCAN_STANDARD_ID;
fdcan_filtre_yapi.FilterIndex = 0;
fdcan_filtre_yapi.FilterType = FDCAN_FILTER_MASK;
fdcan_filtre_yapi.FilterConfig = FDCAN_FILTER_TO_RXFIFO0;
fdcan_filtre_yapi.FilterID1 = 0x000;
fdcan_filtre_yapi.FilterID2 = 0x000;
HAL_FDCAN_ConfigFilter(&hfdcan1, &fdcan_filtre_yapi);
}
/**
* @brief TIM16 Initialization Function
* None
* @retval None
*/
static void MX_TIM16_Init(void)
{
htim16.Instance = TIM16;
htim16.Init.Prescaler = 1001;
htim16.Init.CounterMode = TIM_COUNTERMODE_UP;
htim16.Init.Period = 17001;
htim16.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
htim16.Init.RepetitionCounter = 0;
htim16.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
if (HAL_TIM_Base_Init(&htim16) != HAL_OK)
{
Error_Handler();
}
}
/**
* Enable DMA controller clock
*/
static void MX_DMA_Init(void)
{
__HAL_RCC_DMAMUX1_CLK_ENABLE();
__HAL_RCC_DMA1_CLK_ENABLE();
HAL_NVIC_SetPriority(DMA1_Channel1_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(DMA1_Channel1_IRQn);
}
/**
* @brief GPIO Initialization Function
* None
* @retval None
*/
static void MX_GPIO_Init(void)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
__HAL_RCC_GPIOC_CLK_ENABLE();
__HAL_RCC_GPIOF_CLK_ENABLE();
__HAL_RCC_GPIOA_CLK_ENABLE();
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5, GPIO_PIN_RESET);
GPIO_InitStruct.Pin = GPIO_PIN_13;
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
GPIO_InitStruct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
GPIO_InitStruct.Pin = GPIO_PIN_2|GPIO_PIN_3;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
GPIO_InitStruct.Alternate = GPIO_AF12_LPUART1;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
GPIO_InitStruct.Pin = GPIO_PIN_5;
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);
}
void Error_Handler(void)
{
__disable_irq();
while (1)
{
}
}
#ifdef USE_FULL_ASSERT
void assert_failed(uint8_t *file, uint32_t line)
{
}
#endif /* USE_FULL_ASSERT */
