STM32F103C8T6 Configuration Using CubeMX + HAL Library
Open STM32CubeMX and select STM32F103C8T6.
Enable two UART interfaces:
USART1
- PA9 → USART1_TX
- PA10 → USART1_RX
USART2
- PA2 → USART2_TX
- PA3 → USART2_RX
Select Asynchronous mode and enable UART interrupts.
Baud rate settings:
- USART1: 256000 bps
- USART2: 115200 bps
Note: Ensure the baud rate settings match the radar and voice module requirements.
UART Data Processing Rd-03D UART Data
The Rd-03D module communicates with external devices via UART (TTL level).
- Default baud rate: 256000 bps
- Data format: 1 stop bit, no parity
The radar outputs detected target information, including:
- X coordinate
- Y coordinate
- Target velocity
By default, the radar operates in single-target detection mode and must be switched to multi-target detection mode for this application.
Data Frame Format
Example data frame:
AA FF 03 00 0E 03 B1 86 10 00 68 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 55 CC
AA FF 03 00 0E 03 B1 86 10 00 68 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 55 CC
- Red section: Target 1 information
- Blue section: Target 2 information
- Green section: Target 3 information
In this demo, only presence detection is required, so it is sufficient to check whether valid target data exists in the corresponding frame.
6. VC-02 UART Data The VC-02 UART protocol is user-defined. Development resources and documentation can be found on the VC series official website:
https://docs.ai-thinker.com/voice_module
Below is a custom-defined UART protocol and voice command table. All UART outputs are in hexadecimal format.
7. STM32 Data Processing Logic
This implementation uses flag-based logic to process data, preventing repeated voice announcements when radar data is updated too frequently.
uint8_t RX_BUF[64] = {0}; // Receive buffer
uint8_t RX_count = 0; // Buffer counter
uint8_t RX_temp; // Temporary received byte
uint8_t Radar_1 = 0; // Target 1 flag
uint8_t Radar_2 = 0; // Target 2 flag
uint8_t Radar_3 = 0; // Target 3 flag
uint8_t Speaker_1 = 0; // Voice announcement flag for target 1
uint8_t Speaker_2 = 0; // Voice announcement flag for target 2
uint8_t Speaker_3 = 0; // Voice announcement flag for target 3
uint8_t Single_Target_Detection_CMD[] = {
0xFD,0xFC,0xFB,0xFA,0x02,0x00,0x80,0x00,0x04,0x03,0x02,0x01
}; // Single-target detection mode command (detects only one target)
uint8_t Multi_Target_Detection_CMD[] = {
0xFD,0xFC,0xFB,0xFA,0x02,0x00,0x90,0x00,0x04,0x03,0x02,0x01
}; // Multi-target detection mode command (detects multiple targets)
uint8_t SpeakerCMD_0[5] = {0x5A,0x00,0x00,0x00,0x00}; // No-target voice announcement command
uint8_t SpeakerCMD_1[5] = {0x5A,0x00,0x00,0x00,0x01}; // One-target voice announcement command
uint8_t SpeakerCMD_2[5] = {0x5A,0x00,0x00,0x00,0x02}; // Two-target voice announcement command
uint8_t SpeakerCMD_3[5] = {0x5A,0x00,0x00,0x00,0x03}; // Three-target voice announcement command
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart) // Callback function, called when one frame of data is received
{
if (huart == &huart2) { // UART2 interrupt triggered
RX_BUF[RX_count++] = RX_temp; // Store received byte into buffer
// Receive VC UART command to query current number of people
if ((RX_BUF[RX_count - 1] == 0x00) && (RX_BUF[RX_count - 2] == 0xFF)) {
if ((Radar_3 == 0) && (Radar_2 == 0) && (Radar_1 == 0)) {
HAL_UART_Transmit(&huart2, (uint8_t *)&SpeakerCMD_0, sizeof(SpeakerCMD_0), 0xFFFF); // Trigger no-target voice announcement
}
else if (Radar_3 == 1) {
HAL_UART_Transmit(&huart2, (uint8_t *)&SpeakerCMD_3, sizeof(SpeakerCMD_3), 0xFFFF); // Trigger three-target voice announcement
}
else if (Radar_2 == 1) {
HAL_UART_Transmit(&huart2, (uint8_t *)&SpeakerCMD_2, sizeof(SpeakerCMD_2), 0xFFFF); // Trigger two-target voice announcement
}
else if (Radar_1 == 1) {
HAL_UART_Transmit(&huart2, (uint8_t *)&SpeakerCMD_1, sizeof(SpeakerCMD_1), 0xFFFF); // Trigger one-target voice announcement
}
while (HAL_UART_GetState(&huart2) == HAL_UART_STATE_BUSY_TX); // Wait until transmission is complete
memset(RX_BUF, 0x00, sizeof(RX_temp)); // Clear receive buffer
RX_count = 0; // Reset buffer counter
}
HAL_UART_Receive_IT(&huart2, &RX_temp, 1); // Continue receiving data on UART2
}
if (huart == &huart1) { // UART1 interrupt triggered
RX_BUF[RX_count++] = RX_temp; // Store received byte into buffer
if ((RX_BUF[RX_count - 1] == 0xCC) && (RX_BUF[RX_count - 2] == 0x55)) {
// Logic check: trigger voice announcement for target 1
if ((Radar_1 == 1) && (Speaker_1 == 0)) {
HAL_UART_Transmit(&huart2, (uint8_t *)&SpeakerCMD_1, sizeof(SpeakerCMD_1), 0xFFFF);
Speaker_1 = 1;
}
// Logic check: trigger voice announcement for target 2
else if ((Radar_2 == 1) && (Speaker_2 == 0)) {
HAL_UART_Transmit(&huart2, (uint8_t *)&SpeakerCMD_2, sizeof(SpeakerCMD_2), 0xFFFF);
Speaker_2 = 1;
}
// Logic check: trigger voice announcement for target 3
else if ((Radar_3 == 1) && (Speaker_3 == 0)) {
HAL_UART_Transmit(&huart2, (uint8_t *)&SpeakerCMD_3, sizeof(SpeakerCMD_3), 0xFFFF);
Speaker_3 = 1;
}
// Data comparison: no target detected
else if ((RX_BUF[5] == 0x00) && (RX_BUF[14] == 0x00) && (RX_BUF[22] == 0x00)) {
Radar_1 = 0;
Radar_2 = 0;
Radar_3 = 0;
Speaker_1 = 0;
Speaker_2 = 0;
Speaker_3 = 0;
}
// Data comparison: one target detected
else if ((RX_BUF[5] != 0x00) && (RX_BUF[14] == 0x00) && (RX_BUF[22] == 0x00)) {
Radar_1 = 1;
Radar_2 = 0;
Radar_3 = 0;
Speaker_2 = 0;
Speaker_3 = 0;
}
// Data comparison: two targets detected
else if ((RX_BUF[5] != 0x00) && (RX_BUF[14] != 0x00) && (RX_BUF[22] == 0x00)) {
Radar_1 = 0;
Radar_2 = 1;
Radar_3 = 0;
Speaker_1 = 0;
Speaker_3 = 0;
}
// Data comparison: three targets detected
else if ((RX_BUF[5] != 0x00) && (RX_BUF[14] != 0x00) && (RX_BUF[22] != 0x00)) {
Radar_1 = 0;
Radar_2 = 0;
Radar_3 = 1;
Speaker_1 = 0;
Speaker_2 = 0;
}
// HAL_UART_Transmit(&huart1, (uint8_t *)&RX_BUF, RX_count, 0xFFFF); // Send buffer data via UART (optional debug)
while (HAL_UART_GetState(&huart2) == HAL_UART_STATE_BUSY_TX); // Wait until transmission is complete
memset(RX_BUF, 0x00, sizeof(RX_temp)); // Clear receive buffer
RX_count = 0; // Reset buffer counter
}
HAL_UART_Receive_IT(&huart1, &RX_temp, 1); // Continue receiving data on UART1
}
}
8. Source Code & Firmware
Source code repository:
Ai-Thinker