2025-12-06 12:49 PM - last edited on 2025-12-08 10:44 AM by Andrew Neil
Code is given below in the files:
/* USER CODE BEGIN Header */
/**
******************************************************************************
* @file : main.c
* @brief : Main program body
******************************************************************************
*/
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "main.h"
/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include <string.h>
/* USER CODE END Includes */
/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */
/* USER CODE END PTD */
/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
#define RING_BUF_SIZE 32
#define PACKET_SIZE 8
#define CAN_CMD_ID 0x100
/* USER CODE END PD */
/* Private variables ---------------------------------------------------------*/
CAN_HandleTypeDef hcan;
UART_HandleTypeDef huart1;
DMA_HandleTypeDef hdma_usart1_rx;
/* USER CODE BEGIN PV */
uint8_t r_buffer[RING_BUF_SIZE];
volatile uint16_t head_index = 0;
volatile uint16_t tail_index = 0;
static uint8_t packet[PACKET_SIZE];
static uint8_t pkt_index = 0;
CAN_TxHeaderTypeDef TxHeader;
uint32_t TxMailbox;
/* 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_CAN_Init(void);
static void MX_USART1_UART_Init(void);
/* USER CODE BEGIN PFP */
static void CAN_AppInit(void);
static void uart_can(uint8_t b);
static void send_can_packet(uint8_t *data);
/* USER CODE END PFP */
/* USER CODE BEGIN 0 */
static void CAN_AppInit(void)
{
TxHeader.StdId = CAN_CMD_ID;
TxHeader.IDE = CAN_ID_STD;
TxHeader.RTR = CAN_RTR_DATA;
TxHeader.DLC = 8;
TxHeader.TransmitGlobalTime = DISABLE;
if (HAL_CAN_Start(&hcan) != HAL_OK)
Error_Handler();
}
static void send_can_packet(uint8_t *data)
{
if (HAL_CAN_AddTxMessage(&hcan, &TxHeader, data, &TxMailbox) != HAL_OK)
{
// CAN TX error handling if needed
}
}
static void uart_can(uint8_t b)
{
packet[pkt_index++] = b;
if (pkt_index == PACKET_SIZE)
{
send_can_packet(packet);
pkt_index = 0;
}
}
/* USER CODE END 0 */
/**
* @brief The application entry point.
* @retval int
*/
int main(void)
{
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
MX_DMA_Init();
MX_CAN_Init();
MX_USART1_UART_Init();
CAN_AppInit();
// Start DMA ring buffer reception
HAL_UART_Receive_DMA(&huart1, r_buffer, RING_BUF_SIZE);
while (1)
{
head_index = (RING_BUF_SIZE - __HAL_DMA_GET_COUNTER(huart1.hdmarx)) % RING_BUF_SIZE;
while (tail_index != head_index)
{
uint8_t b = r_buffer[tail_index];
tail_index = (tail_index + 1) % RING_BUF_SIZE;
uart_can(b);
}
}
}
/* ---------------- SYSTEM & PERIPHERAL CONFIG BELOW ---------------- */
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.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();
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();
}
static void MX_CAN_Init(void)
{
hcan.Instance = CAN1;
// 36 MHz / (18 * 16) ≈ 125 kbps (your desired bitrate)
hcan.Init.Prescaler = 18;
hcan.Init.Mode = CAN_MODE_NORMAL;
hcan.Init.SyncJumpWidth = CAN_SJW_1TQ;
hcan.Init.TimeSeg1 = CAN_BS1_13TQ;
hcan.Init.TimeSeg2 = CAN_BS2_2TQ;
hcan.Init.TimeTriggeredMode = DISABLE;
hcan.Init.AutoBusOff = ENABLE;
hcan.Init.AutoWakeUp = DISABLE;
hcan.Init.AutoRetransmission = ENABLE;
hcan.Init.ReceiveFifoLocked = DISABLE;
hcan.Init.TransmitFifoPriority = DISABLE;
if (HAL_CAN_Init(&hcan) != HAL_OK) Error_Handler();
}
static void MX_USART1_UART_Init(void)
{
huart1.Instance = USART1;
huart1.Init.BaudRate = 115200;
huart1.Init.WordLength = UART_WORDLENGTH_8B;
huart1.Init.StopBits = UART_STOPBITS_1;
huart1.Init.Parity = UART_PARITY_NONE;
huart1.Init.Mode = UART_MODE_TX_RX;
huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;
huart1.Init.OverSampling = UART_OVERSAMPLING_16;
if (HAL_UART_Init(&huart1) != HAL_OK) Error_Handler();
}
static void MX_DMA_Init(void)
{
__HAL_RCC_DMA1_CLK_ENABLE();
HAL_NVIC_SetPriority(DMA1_Channel5_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(DMA1_Channel5_IRQn);
}
static void MX_GPIO_Init(void)
{
__HAL_RCC_GPIOD_CLK_ENABLE();
__HAL_RCC_GPIOA_CLK_ENABLE();
}
void Error_Handler(void)
{
__disable_irq();
while (1) {}
}
#ifdef USE_FULL_ASSERT
void assert_failed(uint8_t *file, uint32_t line)
{ }
#endif(TRANSMITTER CODE ABOVE)
/* 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.
*
******************************************************************************
*/
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "main.h"
/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include <stdbool.h>
#include <string.h>
/* USER CODE END Includes */
/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */
/* USER CODE END PTD */
/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
#define CAN_CMD_ID 0x100
/* USER CODE END PD */
/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */
/* USER CODE END PM */
/* Private variables ---------------------------------------------------------*/
CAN_HandleTypeDef hcan;
UART_HandleTypeDef huart1;
/* USER CODE BEGIN PV */
CAN_RxHeaderTypeDef RxHeader;
uint8_t RxData[8];
volatile bool rx_ready_flag = false;
uint8_t buff[8];
/* USER CODE END PV */
/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_CAN_Init(void);
static void MX_USART1_UART_Init(void);
/* USER CODE BEGIN PFP */
static void CAN_AppInit(void);
/* USER CODE END PFP */
/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
static void CAN_AppInit(void)
{
CAN_FilterTypeDef sFilterConfig = {0};
// Accept only StdId = CAN_CMD_ID (0x100) into FIFO0
sFilterConfig.FilterBank = 0;
sFilterConfig.FilterMode = CAN_FILTERMODE_IDMASK;
sFilterConfig.FilterScale = CAN_FILTERSCALE_32BIT;
sFilterConfig.FilterFIFOAssignment = CAN_FILTER_FIFO0;
sFilterConfig.FilterActivation = ENABLE;
// 11-bit ID goes in bits [10:0] → stored at [15:5] in FilterIdHigh
sFilterConfig.FilterIdHigh = (CAN_CMD_ID << 5);
sFilterConfig.FilterIdLow = 0x0000;
sFilterConfig.FilterMaskIdHigh = (0x7FF << 5); // match all 11 bits
sFilterConfig.FilterMaskIdLow = 0x0000;
if (HAL_CAN_ConfigFilter(&hcan, &sFilterConfig) != HAL_OK)
{
Error_Handler();
}
if (HAL_CAN_Start(&hcan) != HAL_OK)
{
Error_Handler();
}
// Enable RX FIFO0 pending interrupt
if (HAL_CAN_ActivateNotification(&hcan, CAN_IT_RX_FIFO0_MSG_PENDING) != HAL_OK)
{
Error_Handler();
}
}
void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef *hcan_rx)
{
if (hcan_rx->Instance == CAN1)
{
if (HAL_CAN_GetRxMessage(hcan_rx, CAN_RX_FIFO0, &RxHeader, RxData) != HAL_OK)
{
// Error while reading, ignore
return;
}
if ((RxHeader.IDE == CAN_ID_STD) &&
(RxHeader.StdId == CAN_CMD_ID) &&
(RxHeader.DLC == 8))
{
memcpy(buff, RxData, 8); // dst = buff, src=RxData
}
}
}
/* USER CODE END 0 */
/**
* @brief The application entry point.
* @retval int
*/
int main(void)
{
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */
/* MCU Configuration--------------------------------------------------------*/
HAL_Init();
/* USER CODE BEGIN Init */
/* USER CODE END Init */
SystemClock_Config();
/* USER CODE BEGIN SysInit */
/* USER CODE END SysInit */
MX_GPIO_Init();
MX_CAN_Init();
MX_USART1_UART_Init();
/* USER CODE BEGIN 2 */
CAN_AppInit();
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
if (rx_ready_flag == true)
{
HAL_UART_Transmit(&huart1, buff, 8, HAL_MAX_DELAY);
// optional: newline so each frame is on its own line
uint8_t nl[2] = {'\r', '\n'};
HAL_UART_Transmit(&huart1, nl, 2, HAL_MAX_DELAY);
rx_ready_flag = false;
}
}
/* 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; // <-- FIXED
RCC_OscInitStruct.HSEPredivValue = RCC_HSE_PREDIV_DIV1;
RCC_OscInitStruct.HSIState = RCC_HSI_ON; // <-- FIXED
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON; // <-- FIXED
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; // APB1 = 36 MHz
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1; // APB2 = 72 MHz
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK)
{
Error_Handler();
}
}
/**
* @brief CAN Initialization Function
* None
* @retval None
*/
static void MX_CAN_Init(void)
{
hcan.Instance = CAN1;
hcan.Init.Prescaler = 18; // 36MHz / (18 * 16) ≈ 125 kbit/s
hcan.Init.Mode = CAN_MODE_NORMAL;
hcan.Init.SyncJumpWidth = CAN_SJW_1TQ;
hcan.Init.TimeSeg1 = CAN_BS1_13TQ;
hcan.Init.TimeSeg2 = CAN_BS2_2TQ;
hcan.Init.TimeTriggeredMode = DISABLE;
hcan.Init.AutoBusOff = ENABLE;
hcan.Init.AutoWakeUp = DISABLE;
hcan.Init.AutoRetransmission = ENABLE;
hcan.Init.ReceiveFifoLocked = DISABLE;
hcan.Init.TransmitFifoPriority= DISABLE;
if (HAL_CAN_Init(&hcan) != HAL_OK)
{
Error_Handler();
}
}
/**
* @brief USART1 Initialization Function
* None
* @retval None
*/
static void MX_USART1_UART_Init(void)
{
huart1.Instance = USART1;
huart1.Init.BaudRate = 115200;
huart1.Init.WordLength = UART_WORDLENGTH_8B;
huart1.Init.StopBits = UART_STOPBITS_1;
huart1.Init.Parity = UART_PARITY_NONE;
huart1.Init.Mode = UART_MODE_TX_RX;
huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;
huart1.Init.OverSampling = UART_OVERSAMPLING_16;
if (HAL_UART_Init(&huart1) != HAL_OK)
{
Error_Handler();
}
}
/**
* @brief GPIO Initialization Function
* None
* @retval None
*/
static void MX_GPIO_Init(void)
{
__HAL_RCC_GPIOD_CLK_ENABLE();
__HAL_RCC_GPIOA_CLK_ENABLE();
}
/**
* @brief This function is executed in case of error occurrence.
* @retval None
*/
void Error_Handler(void)
{
__disable_irq();
while (1)
{
}
}
#ifdef USE_FULL_ASSERT
void assert_failed(uint8_t *file, uint32_t line)
{
(void)file;
(void)line;
}
#endif /* USE_FULL_ASSERT */(RECIEVER CODE)
import serial
import time
# --------- Configure your COM port here ---------
PORT = "COM12" # change if needed
BAUD = 115200
# timeout > 0 → blocking read with this max wait time (in seconds)
ser = serial.Serial(PORT, BAUD, timeout=0.05) # 50 ms timeout is plenty
def format_frame(val: int) -> bytes:
"""
Convert integer val (0–256) into exactly 8 bytes:
"+XYZ+XYZ" where XYZ is a zero-padded 3-digit number.
"""
return f"+{val:03d}+{val:03d}".encode("ascii")
print("Starting PWM sweep over UART...\n")
try:
while True:
# -------- INCREASE: 0 → 256 --------
for pwm in range(0, 257):
frame = format_frame(pwm)
ser.write(frame)
# Print what we sent
print(f"TX: {frame.decode('ascii')}")
# Optional: try to read back 8 bytes (if STM echoes)
resp = ser.read(8)
if resp:
print(f"RX: {resp.decode(errors='ignore')}")
time.sleep(0.01) # 10 ms between frames
# -------- DECREASE: 256 → 0 --------
for pwm in range(256, -1, -1):
frame = format_frame(pwm)
ser.write(frame)
print(f"TX: {frame.decode('ascii')}")
resp = ser.read(8)
if resp:
print(f"RX: {resp.decode(errors='ignore')}")
time.sleep(0.01)
except KeyboardInterrupt:
print("\nStopped by user.")
ser.close()(PYSERIAL CODE)
THE
THE FIRST COMMAND KEEPS REPEATING ON THE CAN REICIEVER END...... IS THERE ANY LOGICAL ERROR OR CODE ERROR, PLEASE POINT IT OUT
2025-12-06 3:49 PM - edited 2025-12-06 3:53 PM
You'll have to debug your code to understand which points specifically are failing.
Perhaps use a debugger, and determine if your USART or CAN is actually functional. Just saying the PYSERIAL doesn't do what you want at the end, is a bit abstract, illustrate expectations and confirm each step can work.
I don't see rx_ready_flag ever being set.
2025-12-08 10:31 AM
After debugging my code I see that the ring buffer is working perfectly fine and the packets are gettings updated periodically in the live expressions........ on the reciever end the RxData and buff variable are staying the same +000+000...... so the RxData buffer is not being overwritten ......... or the CAN is not sending properly..... i dont have a logic analyzer or can analyzer is ther a way to debug this
2025-12-08 12:46 PM
As @Tesla DeLorean mentions, you don't set rx_ready_flag in the callback.
In your main while loop, the code will never send any UART packets because rx_ready_flag is never set.
In your Python script you're not receiving any data but timing out. You're also not testing for a good packet.
At least we know that the first character is a '+'
Try...
resp = None
while resp == None: # will eventually timeout after 50ms
resp= ser.read(8)
substr = resp[0:1].decode() # test for '+' character
if substr == '+':
print(f"RX: {resp.decode(errors='ignore')}")
else:
print("***** No reply, timeout. *****\r\n")