摘要: 想给单片机装上“眼睛”和“大脑”,实现低功耗、高响应、离线运行的人脸识别控制。本文手把手带你实战K210与STM32的联动。非常荣幸本篇博客被九章云极"普惠算力"社区录用,感谢社区的支持!

一.项目架构与核心思想

1.1K210(视觉处理单元)

  • 运行轻量化的人脸识别模型(如Mobilenet-SSD或自定义卷积神经网络),实时处理摄像头输入数据。
  • 输出结构化识别结果:识别成功时发送人员ID及置信度,未识别时发送特定错误码。
  • 通过UART串口以固定协议(如JSON或自定义二进制协议)向STM32传输数据,波特率需双方匹配(如115200bps)。

1.2STM32(控制执行单元)

  • 配置UART接收中断服务程序,实时解析K210发送的指令数据包。
  • 实现状态机逻辑:根据指令内容触发对应动作(如ID匹配成功点亮绿色LED,未识别触发蜂鸣器报警)。
  • 直接操作GPIO驱动外设:LED采用推挽输出模式,蜂鸣器需PWM调制频率,必要时增加三极管驱动电路。

二、K210端的“灵魂”代码(MaixPy)

核心是模型转换和串口通信。这里坑最多:

2.1 模型转换:

训练完成的模型需转换为K210支持的.kmodel格式。使用官方工具nncase或在线转换平台完成转换,确保模型输入输出尺寸与硬件匹配。转换后模型需存放在SD卡指定路径。

2.2路径配置:

SD卡中模型存储路径必须与代码中load_kmodel()指定的路径完全一致。建议使用简洁路径如/sd/KPU/model_name.kmodel,避免因路径错误导致加载失败。

分享一个k210初学者的指南:k210配置与学习

2.3串口通信核心代码

import sensor, image, time, lcd
from maix import KPU
from modules import ybserial
import binascii

serial = ybserial()

def str_int(data_str):
    bb = binascii.hexlify(data_str)
    bb = str(bb)[2:-1]
    hex_1 = int(bb[0])*16
    hex_2 = int(bb[1],16)
    return hex_1+hex_2

def send_data(x,y,w,h,msg):
    start = 0x24
    end = 0x23
    data = []
    # 小端模式处理坐标数据
    if x!=0 or y!=0 or w!=0 or h!=0:
        for val in [x, y, w, h]:
            data.append(val & 0xFF)
            data.append(0x2C)
            data.append(val >> 8 & 0xFF)
            data.append(0x2C)
    # 消息处理
    if msg:
        for char in msg:
            data.append(str_int(char))
            data.append(0x2C)
    
    crc = sum([len(data)+5, 0x06, 0xBB, len(data)] + data) % 256
    send_buf = [start, len(data)+5, 0x06, 0xBB, len(data)] + data + [crc, end]
    return send_buf

三、STM32端的“大脑”解析(标准库)

STM32端的关键在于稳定地接收和解析数据。我们使用的是STM32F103来进行控制,在里面我们采用了简单的帧结构 "ID:xxx\n"。

3.1硬件初始化部分

GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);  // 使能GPIOB时钟
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;       // 配置为推挽输出模式
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12;             // 选择PB12引脚
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;     // 设置IO口速度为50MHz
GPIO_Init(GPIOB, &GPIO_InitStructure);                // 初始化GPIOB
GPIO_SetBits(GPIOB,GPIO_Pin_12);                      // 初始置高电平(关闭蜂鸣器)

3.2外设初始化部分

OLED_Init();           // OLED显示屏初始化
SystemInit();          // 系统时钟初始化
delay_init();          // 延时函数初始化
led_int();             // LED灯初始化
USART2_init(115200);   // 串口2初始化,波特率115200
LED = 0;               // 初始关闭LED

3.3主循环逻辑

while(1)
{
    if (k210_msg.class_n != 0)  // 检测是否收到K210发送的有效数据
    {
        if(k210_msg.class_n == 8)  // 检查数据类别是否为8(特定指令)
        {
            // 格式化输出坐标信息到串口
            sprintf(buff_com,"x=%d,y=%d,w=%d,h=%d\r\n",k210_msg.x,k210_msg.y,k210_msg.w,k210_msg.h);
            USART2_Send_ArrayU8((uint8_t*)buff_com,strlen(buff_com));

3.4身份验证处理

            if(k210_msg.id == 'Y' || k210_msg.id == 'y')  // 验证成功分支
            {
                sprintf(buff_com,"Yes\r\n");
                USART2_Send_ArrayU8(...);
                LED=1;                          // 点亮LED
                OLED_ShowString(2,1,"identity yes");  // OLED显示验证成功
            }
            else  // 验证失败分支
            {
                sprintf(buff_com,"NO\r\n");
                USART2_Send_ArrayU8(...);
                
                // LED闪烁三次
                for(i=0;i<3;i++) {
                    LED=1; delay_ms(100);
                    LED=0; delay_ms(100);
                }
                
                // 蜂鸣器报警(PB12控制)
                GPIO_ResetBits(GPIOB, GPIO_Pin_12);  // 蜂鸣器响
                delay_ms(100);
                GPIO_SetBits(GPIOB, GPIO_Pin_12);    // 蜂鸣器停
                delay_ms(100);
                
                OLED_ShowString(2,1,"identity no ");  // OLED显示验证失败
            }
            k210_msg.class_n = 0;  // 清除接收标志位
        }
    }
}

四.STM32进行命令下发控制

在main函数里面,我们已经接受到了k210的数据,能够判断人脸id是不是正确的,要实现led显示人员身份正确或者错误可以直接在id判断那里修改即可,如果id正确则控制led显示"identify yes",如果错误则控制led显示"identify no",这样即可实现k210识别的数据来控制led的显示,让结果直接呈现在LED上面。

4.1定义LED显示模式

  • 身份正确时:LED常亮(LED=1),OLED显示"identity yes"
  • 身份错误时:LED闪烁3次(现有逻辑),OLED显示"identity no"
if(k210_msg.id == 'Y' || k210_msg.id == 'y') 
{
    sprintf(buff_com,"Yes\r\n");
    USART2_Send_ArrayU8((uint8_t*)buff_com,strlen(buff_com));
    LED=1;  // 常亮模式
    OLED_ShowString(2,1,"identity yes");
}
else
{
    sprintf(buff_com,"NO\r\n");
    USART2_Send_ArrayU8((uint8_t*)buff_com,strlen(buff_com));
    
    // 闪烁逻辑保持不变
    for(i=0;i<3;i++){
        LED=1;
        delay_ms(100);
        LED=0;
        delay_ms(100);
    }
    OLED_ShowString(2,1,"identity no");
}

4.2硬件连接验证

  • 确保LED引脚(如GPIO_Pin_12)已正确连接到物理LED模块
  • 检查OLED的I2C/SPI接口连接是否正常
  • 蜂鸣器控制引脚(PB12)应独立于LED控制

4.3调试建议

  • 使用逻辑分析仪或示波器观察LED引脚的电平变化
  • 在串口调试助手查看buff_com发送的调试信息
  • 若LED不亮,检查:
    • GPIO初始化配置(输出模式、时钟使能)
    • 硬件限流电阻是否合适
    • LED正负极连接方向

4.4扩展功能(可选)

  • 添加声音提示:在身份错误时触发蜂鸣器(现有代码已实现)
  • 增加RGB LED支持:用不同颜色表示不同状态
  • 设置延时复位:身份验证后延迟5秒清除OLED显示

至此完成了从k210端进行识别,并且和STM32通信,同时根据k210的识别数据控制指示灯的开关和LED屏的显示。

 

 

更多推荐