电赛备赛日记(一):K210与STM32串口通信

这篇具有很好参考价值的文章主要介绍了电赛备赛日记(一):K210与STM32串口通信。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

   拖更了n久的备赛日记终于来啦,最近实现了关于K210图像识别并将所需数据(即目标类别,目标在图像中的加权坐标)其中,加权坐标指K210识别到的目标并框出的框的宽和高与框左上顶点的坐标加权,希望以此来判断目标所处的位置并方便后续进行诸如寻迹,目标跟随等任务。其中涉及包括YOLO网络的训练,上位机K210进行目标检测并利用串口对数据进行发出。下位机STM32则要接收到K210传出的数据,对数据进行解码,存入对应数组便于后续引用,在此次实验中再利用串口二将接收数据传给PC端利用串口助手进行数据显示。

   我们一步一步来,从K210的YOLO网络训练开始讲起,K210中常用的YOLO网络训练包括利用spieed公司的线上训练平台,本地训练中除了深度学习大佬依旧可以利用之前常用的训练方法进行训练外,身为初学者,没有那么多的经历也没有能力完成深度学习环境的搭建与代码的编写,可以选择大佬开发好的MX-YOLO进行训练。本次实验就是采用MX-YOLO进行本地训练(跑例程的mask检测),开发的模型,在本次日记中不做过多赘述,后续会和相关训练方法同期更新出。在模型运行中遇到了诸如内存不足的问题(感觉是运行内存不足),在重刷了spieed的最小固件后得以解决。也建议大家在使用K210跑深度学习模型的时候刷最小固件来执行程序,这样能容纳稍微大一点的模型。一般能支持2兆到3兆左右(模型存至sd卡)。

   模型导入进行目标识别后,我们需要启动K210的串口将数据发出,要注意K210的串口不能单独发出数字,所以此处选择定义了一个一个元组参数来统一发送数据。为了让STM32更好的接收数据,我们定义了一个简单的通信协议。长这样

帧头1:0xfe
帧头2: 0xfd
数据1:classid
数据2:cx
数据3:cy
帧尾:0xff

其中之所以选择0xfe 0xfd 0xff作为帧头,是因为我们的捕捉的图像大小为224*224,皆小于0xfd,不会出现加权后数据大于0xff从而影响通信的情况。

下面就是我们K210端的全部代码啦,烧即用,只需要修改对应模型以及对应的anchor文件和lable文件即可。(注意我选用的spieed的固件包,选用canmv或者其它固件包大概率会无法使用喔)

#此代码中0为未带口罩,1为戴口罩
import sensor
import image
import lcd
import KPU as kpu
from machine import UART
from fpioa_manager import fm
import ustruct
lcd.init()
sensor.reset()
sensor.set_pixformat(sensor.RGB565)
sensor.set_framesize(sensor.QVGA)
sensor.set_windowing((224, 224))
sensor.set_vflip(1)#设置摄像头后置即所见即所得
sensor.run(1)
#初始化串口,pin6为串口1RX口,pin7为串口1TX口
fm.register(6,fm.fpioa.UART1_RX)
fm.register(7,fm.fpioa.UART1_TX)
def sending_data(cc,cx,cy):
    global uart;
    data = ustruct.pack("<bbhhhb",              #格式为俩个字符俩个短整型(2字节)
                   0xfe,#帧头1
                   0xfd,#帧头2
                   int(cc), #数据1为传入类型 #四字节
                   int(cx), #数据2为框与顶点坐标的加权的长#四字节
                   int(cy), #数据3为框与顶点坐标的加权的高#四字节
                   0xff)
    uart = UART(UART.UART1, 115200, 8, 0, 0, timeout=1000, read_buf_len=4096)
    uart.write(data);   #必须要传入一个字节数组
task = kpu.load("/sd/mask.kmodel")
info_list = kpu.netinfo(task)
f=open("mask.anchors.txt","r")
anchor_txt=f.read()
L=[]
for i in anchor_txt.split(","):
    L.append(float(i))
anchor=tuple(L)
f.close()
a = kpu.init_yolo2(task, 0.6, 0.3, 5, anchor)
f=open("mask.lable.txt","r")
labels_txt=f.read()
labels = labels_txt.split(",")
f.close()
while(True):
    img = sensor.snapshot()
    code = kpu.run_yolo2(task, img)
    if code:#识别到对应目标
        for i in code:
            #print(i.w())
            obj_x=(i.x()+i.w())/2
            obj_y=(i.y()+i.h())/2#数据加权平均计算x,y
            sending_data(i.classid(),obj_x,obj_y)#发送数据
            if i.classid():#检测目标为mask,仅适用于二分类问题运用此行
               a=img.draw_rectangle(i.rect(),(0,255,0),2)
               a = lcd.display(img)
               for i in code:
                 lcd.draw_string(i.x()+45, i.y()-20, labels[i.classid()]+" "+'%.2f'%i.value(), lcd.WHITE,lcd.GREEN)
            else:#检测目标为un_mask
               a=img.draw_rectangle(i.rect(),(255,0,0),2)
               a = lcd.display(img)
               for i in code:
                 lcd.draw_string(i.x()+45, i.y()-20, labels[i.classid()]+" "+'%.2f'%i.value(), lcd.WHITE,lcd.RED)
    else:#没有要检测的目标出现
        a = lcd.display(img)
a = kpu.deinit(task)

  K210的数据会按ASCII形式发出(其实无所谓,对应都有十六进制形式),这里要留意,一个整形是四字节,也就是比如我classid为01,但实际发出的数据是 00 01

   然后就是stm32的部分了,为了方便移植和开发,本程序中选用hal库开发,对于较底层的解读后续更新。

   目前用到的所有初始化都是最基础的cubemx初始化串口的步骤,并无特殊操作,要注意需要使能串口一的中断用于接收中断。同时将串口模式设置为asynchronous(异步)。下面简单介绍一下具体配置过程。

    电赛备赛日记(一):K210与STM32串口通信

首先我们需要配置系统的RCC,将高速时钟配置成Crystal/Ceramic Resonator:外部无源晶振(陶瓷晶振

  编辑时钟树  配置对应串口

电赛备赛日记(一):K210与STM32串口通信

这里只展示了配置串口1,串口2同串口1一致,注意串口1要打开中断,即NVIC那块enable

电赛备赛日记(一):K210与STM32串口通信

中断优先级可以不动,让系统自动按中断号跑就行。

电赛备赛日记(一):K210与STM32串口通信

初始化就是这样,我们就可以生成代码啦。

将我们这里需要的一些定义代码写在此处,注意一定一定要把代码写在user code里,这样重新配置文件的时候不会被覆盖掉。这里有如此多的hello world主要是为了测试程序是否正常执行。可以进行删除。

/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "stdio.h"
/* USER CODE END Includes */

/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */
uint8_t aRxBuffer;			//接收中断缓冲
uint8_t Uart1_RxBuffer[9] = {0};		//接收缓冲
uint8_t Uart1_Rx_Cnt = 0;		//接收缓冲计数
uint8_t Uart1_RxFlag = 0;
uint8_t hello[]={"hello,world\r\n"};
uint8_t hello1[]={"hello1,world\r\n"};
uint8_t hello2[]={"hello2,world\r\n"};
uint8_t hello3[]={"hello3,world\r\n"};
uint8_t hello4[]={"hello4,world\r\n"};
uint8_t hello5[]={"hello5,world\r\n"};
uint8_t hello6[]={"hello6,world\r\n"};
uint8_t error3[]={"please check the end of the frame\r\n"};
uint8_t error2[]={"please check the end of the header1\r\n"};
uint8_t error1[]={"please check the end of the header1\r\n"};
uint8_t classid;
uint8_t obj_x;
uint8_t obj_y;
uint8_t jieguo[3]={0};
/* USER CODE END PTD */

下面是main函数中的部分,要记得在main函数中除了生成的初始化函数,我们还要开启对应的接收中断。

  HAL_UART_Transmit(&huart2, hello,sizeof(hello) , 1000);
  HAL_UART_Receive_IT(&huart1,Uart1_RxBuffer, 9);

这里将串口1接收的数据直接存储进数组Uart1_RxBuffer中要注意这里其实需要的是一个地址,但是我们知道数组的第一位可以代表他整个数组的地址,所以这里只需要这么写,9代表接收数据的长度为9个字节(参考上述的通信协议,总共是九个字节)

串口接收满9个字节的数据后会引起中断,本程序目前while循环中无任何代码,如果有需要也可以将数据解析任务放置在main函数的while循环中。

引起串口中断后会执行串口中断服务函数,在服务函数中调用串口中断回调函数

此处串口中断回调函数代码如下:

void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
  /* Prevent unused argument(s) compilation warning */
  /* NOTE: This function Should not be modified, when the callback is needed,
           the HAL_UART_TxCpltCallback could be implemented in the user file
   */

	//HAL_UART_Transmit(&huart2, hello, sizeof(hello),0xFFFF);
		HAL_UART_Transmit(&huart2, hello1, sizeof(hello1),0xFFFF);
		if(Uart1_RxBuffer[0]==0XFE)//判断帧头1
		 {
			 HAL_UART_Transmit(&huart2, hello2, sizeof(hello2),0xFFFF);
			 if(Uart1_RxBuffer[1]==0XFD)//判断帧头2
			 {
				HAL_UART_Transmit(&huart2, hello3, sizeof(hello2),0xFFFF);
				 jieguo[0]=Uart1_RxBuffer[3];
				 jieguo[1]=Uart1_RxBuffer[5];
				 jieguo[2]=Uart1_RxBuffer[7];
				 if(Uart1_RxBuffer[8]==0xFF) //判断帧尾
					{
						HAL_UART_Transmit(&huart2, hello4, sizeof(hello4),0xFFFF);
					}
				 else
				 {
						HAL_UART_Transmit(&huart2, error3, sizeof(error3), 1000);
				 }
			 }
			 else
			  {
				 HAL_UART_Transmit(&huart2, error2, sizeof(error2), 1000);
			  }
		 }
	    else
	     {
	       HAL_UART_Transmit(&huart2, error1, sizeof(error1), 1000);
		 }
    HAL_UART_Transmit(&huart2, jieguo, sizeof(jieguo), 1000);
    memset(jieguo,0x00,sizeof(jieguo)); //清空数组
	memset(Uart1_RxBuffer,0x00,sizeof(Uart1_RxBuffer)); //清空数组
    HAL_UART_Transmit(&huart2, Uart1_RxBuffer, sizeof(Uart1_RxBuffer), 1000);
	HAL_UART_Receive_IT(&huart1,Uart1_RxBuffer, 9);   //再开启接收中断
	HAL_UART_Transmit(&huart2, hello5, sizeof(hello5), 1000);
}

此处要注意必须用memset清除数组,如果不用memset清除数组,则串口接收数据无法更新(我也不懂,明明进中断了但是不会覆盖第一次的数据结果。有懂的大佬麻烦给我讲一下),同时一定要在中断回调函数中再次使能接收中断。

进行完上述所有,就可正常接收K210传输的数据并将接收数据通过串口2利用USB转TTL传输回PC机串口助手显示。

项目原工程参考gitee链接cointreau/cointreau - 码云 - 开源中国 (gitee.com)文章来源地址https://www.toymoban.com/news/detail-444662.html

到了这里,关于电赛备赛日记(一):K210与STM32串口通信的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • K210视觉循迹,STM32之间串口通信 #智能车

    目录 个人感慨与感悟 K210视觉循迹 本人是一名大二的二本学生,本篇文章记录一下我这一年多的学习历程(主要还是针对标题的内 容)。 下面是我的一些经历和感悟,不感兴趣的可以直接跳过 -——————————        高考完之后,在我收到录取通知书之后,父母让

    2024年01月19日
    浏览(40)
  • STM32CubeMx学习与K210串口通信+识别橘色色块——点亮小灯

     K210模块的串口发送代码 识别色块 +数字处理 这里zz是4个数字的数,则需要分成千百位和低二位传输 zz是距离。也映射了距离的算法 整体K210代码 STM32串口接受端函数 判断帧头帧尾 如果数据正常 判断 数据是否合格 若合格则点灯 否则灭灯 不要忘记加入

    2024年02月14日
    浏览(52)
  • 亚博k210视觉模块与stm32双向通信

    【K210模块】使用UART模块发送和接收数据_KevinGuo457的博客-CSDN博客 K210的串口_uart_a.write_飞鸟211的博客-CSDN博客 ①每隔1s终端以及串口助手收到消息并显示 ②通过串口助手发送123,K210收到数据并显示 这里如果想要指定K210接收的数据,判断条件不能直接用==(原因参考上面的链接

    2024年04月23日
    浏览(104)
  • K210追小球程序与STM32最小系统板通信(自主学习)

    本人先通过学习OPENMV,再延申到K210中。(主要是OPENMV我还没买屏幕,但是K210有)在OPENMV官网中,有相关追小球的函数,但是是用OPENMV单片机来进行调试的。在网上找到的相关源码,加载到OPENMV后发现帧数很慢。 学校实训的要求是要做出能追一定物体的平衡小车,我的小车的

    2024年02月16日
    浏览(43)
  • 【K210】K210学习笔记五——串口通信

    本人大四学生,电赛生涯已经走到尽头,一路上踩过不少坑,但运气也不错拿了两年省一,思来想去,决定开始写博客,将电赛经验分享一二,能力有限,高手轻喷。 往期的博客讲述了 K210 的感光元件模块 sensor 的配置,机器视觉模块 image 中部分函数的使用(目前是用 find

    2024年04月28日
    浏览(47)
  • 【2023电赛备赛】msp430f5529学习笔记(一)

    【写在前】 本人目前是大二在读生,第一次参加电赛,准备不充分,结果熬了四天,最后成绩却不如人意。有51和32的基础,然后想立一个flag系统的学习一下主打超低功耗的msp430f5529单片机为比赛做准备(毕竟电赛限制TI的板子)。另一方面也是给电协的后继者留下一些参考的

    2024年02月11日
    浏览(50)
  • k210——maix bit串口通信

    k210 一共有 3个 uart ,每个 uart 可以进行自由的引脚映射。 一、API函数介绍 1.1 register(pin, function, force=True) K210 可以通过映射来改变引脚功能,设置引脚(pin)对应的外设功能(func),默认启用强制绑定参数(force=True) pin: 功能映射引脚 function: 芯片功能 force: 默认为Tru

    2024年02月15日
    浏览(47)
  • STM32通过K210进行PID巡线,使用蓝牙模块与电脑通信从而进行P,I,D参数的调节

    目录 一.前言部分(废话部分) 二.K210色块识别 1.必要知识 2.色块识别 3.单片机的接收代码 三.通过蓝牙连接在电脑上实现PID的调参 我使用的是HAL库,如果你使用的是标准库的话可以根据对应标准库的函数进行更改即可 因为之前使用灰度传感器进行巡线,即使用上PID,最后的效果也

    2024年02月14日
    浏览(47)
  • 备赛电赛学习STM32篇(九):ADC

    目录 一、ADC的简介 二、逐次逼近型ADC 2.1、逐次逼近型ADC框图  2.2、STM32 ADC内部介绍 2.2.1、STM32ADC的通道以及存储数据的寄存器  2.2.2、触发方式 2.2.3、STM32ADC时钟部分 2.2.4  三、ADC基本结构框图 四、另外的细节问题 4.1、输入通道 4.2、转换模式 4.2.1、单次转换、非扫描模式

    2024年02月05日
    浏览(38)
  • 2023 电赛 E 题 K210 方案

    K210芯片是一款基于RISC-V架构的嵌入式人工智能芯片,具备低功耗、高性能的特点。它拥有强大的图像处理和机器学习能力,适用于边缘计算设备和物联网应用。为了方便开发者,K210芯片提供了丰富的外设接口,包括摄像头接口、显示接口、WiFi、蓝牙等,同时支持多种编程语

    2024年02月14日
    浏览(35)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包