一、硬件概述
1、开发板(FTHR-G0001)

MM32G0001微控制器搭载 Arm® Cortex®-M0 内核,最高工作频率可达 48MHz。
内置16KB 高速存储器, 并集成了丰富的 I/O 端口和外设模块。
包含 1 个 12 位的 ADC、1 个 16 位高级定时器、 1 个 16 位通用定时器和 1 个 16 位基本定时器, 还包含标准的通信接口: 2 个 USART 接口、 1 个 SPI 接口和 1 个 I2C 接口等。
(开发板使用指南)
2、雷达模块(CEM5826-M11)

CEM5826-M11是一款高灵敏度 24GHz 毫米波人体微动存在检测雷达模块。
区别于传统雷达通过检测人体移动的大幅度动作或肢体动作来判断人体存在,本模块主要特点是在传统人 体感应雷达的功能基础上,同时具备检测积累人体微动幅度的运动,来判断人体的存在的功能。
因此相比传统多普勒雷达来说,具备一定范围内的存在检测,准确率更高。不易漏报。
1.模块相关特性
本系统利用电磁波多普勒效应对运动目标进行探测。
通过发射天线发射出 24GHz 电磁波信号,该电磁波信号遇到运动物体时会反射回带有频偏的 24GHz 电磁波信号,此频偏即为多普勒频偏,反射回的信号被接收天线接收,通过对多普勒频偏及中频 IQ 相位的采集计算分析可以较为灵敏地探测出附近的运动物体以及运动物体是靠近还是远离。
当探测到有运动物体靠近时 VO 输出高电平,无运动物体靠近时 VO 输出低电平。
模块性能:
| 参数 | 典型值 |
|---|---|
| 频率 | 24G-24.25GHz |
| 调制方式 | CW |
| 范围 | 挂高 3m,微动人体检测半径 3m, 移动检测半径 5-6m |
| 供电 | 3.3-5V |
| 电流 | 70mA |
| 输出串口电平 | 3V |
| 检测周期 | 实时 |
| 数据格式 | 串口 ASCII 输出/或高低电平 |
二、雷达参数配置
可以通过串口助手在电脑上调试测试 CEM5826-M11。
使用任意串口调试工具。波特率 115200,8位数据位,1位停止位,校验位和流控为 None, 接收设置选 ASCII,发送设置选 ASCII。
配置指令:
th=: 检测阈值,默认值为 200。
vmin=:设置最小检测速度,单位为 km/h,默认值为 0。
vmax=:设置最大检测速度,单位为 km/h,默认值为 100。
led_on_100ms=: 设置 led 电平维持时间,时间为 xx*0.1s,默认值为 10。
led_iflag=xx: 设置 led 指示模式, led_iflag 默认值为 0。当 led_iflag=0 时,高电平指示检测到目标,低电平指示未检测到目标。当 led_iflag=1 时,高电平指示未检测到目标,低电平指示检测到目标。
save:将当前参数存储到 flash 中,确保参数掉电不丢失。
get_all: 获取当前参数值。
VER:获取软件版本号。
所有指令带回车换行发送有效。
雷达输出:
当采用串口输出模式时,雷达检测到运动时, 则输出 v=, str= 。(V 代表目标速度大小, str 代表信号强度)
例:
(v=1.0 km/h, str=1121) [ASCII]
(76 3D 31 2E 30 20 6B 6D 2F 68 2C 20 73 74 72 3D 31 31 32 31 0D 0A 0D) [Hex]
当雷达检测不到目标时,串口停止输出。 当采用 OUT 输出高电平时,则无人后 OUT 经过延时 led_on_100ms 后从高电平恢复为低电平。
三、硬件连接
开发板(引脚复用)与雷达模块相关引脚连接:
PA3(USART1_RX) -> TX (接收雷达数据)
PA12(USART1_TX) 发送数据到上位机上
PA11 -> OUT(选择性配置)
(DAPLINK虚拟串口默认连接到 PA12、PA3的引脚上)
(注:不要使用 PA13 / PA14 作为复用功能,已被用作 SWDIO、SWCLK,用于下载程序)
四、代码编写
1、串口代码编写
创建usart.c://串口部分: //1、定义接收数据的数组#define RX_BUFFER_SIZE 50char rxBuffer[RX_BUFFER_SIZE];uint8_t rxIndex = 0;uint8_t Rx_Flag = 0;//2、编写串口1相关函数,并配置 PA11 为 IO口(可选择)void USART_Configure(uint32_t Baudrate){ GPIO_InitTypeDef GPIO_InitStruct; NVIC_InitTypeDef NVIC_InitStruct; USART_InitTypeDef USART_InitStruct; //配置中断优先级 NVIC_InitStruct.NVIC_IRQChannel = USART1_IRQn; NVIC_InitStruct.NVIC_IRQChannelPriority = 0x01; NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStruct); RCC_AHBPeriphClockCmd(RCC_AHBENR_GPIOA, ENABLE); // PA3、PA12 复用AF1 GPIO_PinAFConfig(GPIOA, GPIO_PinSource3, GPIO_AF_1); //RX GPIO_PinAFConfig(GPIOA, GPIO_PinSource12, GPIO_AF_1); //TX GPIO_StructInit(&GPIO_InitStruct); GPIO_InitStruct.GPIO_Pin = GPIO_Pin_3; GPIO_InitStruct.GPIO_Speed = GPIO_Speed_High; GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IPU; GPIO_Init(GPIOA, &GPIO_InitStruct); GPIO_StructInit(&GPIO_InitStruct); GPIO_InitStruct.GPIO_Pin = GPIO_Pin_12; GPIO_InitStruct.GPIO_Speed = GPIO_Speed_High; GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_Init(GPIOA, &GPIO_InitStruct); // PA11 配置 为IO口 (可选择是否开启) GPIO_StructInit(&GPIO_InitStruct); GPIO_InitStruct.GPIO_Pin = GPIO_Pin_11; GPIO_InitStruct.GPIO_Speed = GPIO_Speed_High; GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_Init(GPIOA, &GPIO_InitStruct); RCC_APB1PeriphClockCmd(RCC_APB1ENR_USART1, ENABLE); USART_StructInit(&USART_InitStruct); USART_InitStruct.USART_BaudRate = Baudrate; USART_InitStruct.USART_WordLength = USART_WordLength_8b; USART_InitStruct.USART_StopBits = USART_StopBits_1; USART_InitStruct.USART_Parity = USART_Parity_No; USART_InitStruct.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; USART_Init(USART1, &USART_InitStruct); // 开启RX接收中断 USART_ITConfig(USART1, USART_IT_RXNE, ENABLE); USART_Cmd(USART1, ENABLE);}//2、数组(雷达数据)发送 函数void SendString(USART_TypeDef* USARTx, uint8_t *str) { while (*str) { USART_SendData(USARTx, *str++); // 等待发送完成 while (USART_GetFlagStatus(USARTx, USART_FLAG_TXE) == RESET); } }//3、对雷达数据输出void USART_Interrupt(void){ USART_Configure(115200); //根据判断 数据接收完成标志位,然后进行后续数据发送 while(1){ if(Rx_Flag){ SendString(USART1, rxBuffer); Rx_Flag = 0; } }}2、中断代码编写
在mm32g0001.it.c中编写中断处理函数: extern char rxBuffer[RX_BUFFER_SIZE];extern uint8_t rxIndex;extern uint8_t Rx_Flag;void USART1_IRQHandler(void) { if (USART_GetITStatus(USART1, USART_IT_RXNE) != RESET) { // 读取接收到的字符 char receivedChar = (char)USART_ReceiveData(USART1); // 添加字符到接收数组缓冲区 if (rxIndex < RX_BUFFER_SIZE - 1) { //接收完一组数据 if (receivedChar == 'v') { Rx_Flag = 1; //接收完成标志位 rxBuffer[rxIndex] = '\0'; // 添加字符串结束符 rxIndex = 0; // 重置索引,准备接收下一组数据 } rxBuffer[rxIndex++] = receivedChar; } // 清除中断标志位 USART_ClearITPendingBit(USART1, USART_IT_RXNE); }} 3、数据处理部分
// 对接收到的雷达数据进行相关处理#include <stdlib.h>float K = 27.778; //转换系数//输出结果如下://v=1.0 km/h, str=1319//当前检测到的速度 = 27.778 cm/s void USART_Interrupt(void) { USART_Configure(115200); //根据判断 数据接收完成标志位,然后进行后续数据发送 while(1){ if(Rx_Flag){ SendString(USART1, (char*)rxBuffer); //雷达源数据 //处理后的数据 printf("当前检测到的速度 = %.3lf cm/s \r\n",strtod(&rxBuffer[2],NULL) * K); } Rx_Flag = 0; } }strtod()函数:将字符串转换为浮点数。(详细用法见此)
同样,若想要获取str强度相关信息,也可以按此进行相关处理。
4、主函数
main.c int main(void){ USART_Interrupt(); while (1) { }}
