十六进制、ASCII码、文本模式、十六进制之间的关系

#引入串口
from machine import UART,Timer
from fpioa_manager import fm

#映射串口引脚
fm.register(6, fm.fpioa.UART1_RX, force=True)
fm.register(7, fm.fpioa.UART1_TX, force=True)

#串口初始化
uart = UART(UART.UART1, 115200, timeout=1000 , read_buf_len=4096)

#引入KPU和摄像头
import sensor,image,lcd,time
import KPU as kpu

#LCD初始化
lcd.init(freq=15000000)

#摄像头初始化
sensor.reset()
sensor.set_pixformat(sensor.RGB565)
sensor.set_framesize(sensor.QVGA)    #设置帧大小
sensor.set_vflip(1)                  #摄像头后置方式
sensor.run(1)                        #图像捕抓控制
sensor.set_windowing((224, 224))     #设置LCD显示屏大小
sensor.set_hmirror(1)
#标签
classes = ['1', '2', '3', '4', '5', '6', '7', '8']

task = kpu.load("/sd/m.kmodel") #模型SD卡上,kpu.load()调用模型的方法,并赋值给对象

#网络参数
anchor = [1.40625, 1.8125000000000002, 5.09375, 5.28125, 3.46875, 3.8124999999999996, 2.0, 2.3125, 2.71875, 2.90625]


a = kpu.init_yolo2(task, 0.68, 0.3, 5, anchor) #KPU.init_yolo2(kpu_net, threshold, nms_value, anchor_num, anchor)
#参数解析:
#kpu_net:模型加载的对象,一般是KPU.load()的返回值;threshold:概率阈值,大于这个值才会输出结果;nms_value:两个框重合的比率大于这个值,就取概率大的值。换言之,这个值越小越好。
#anchor_num:锚点数,len(anchor)//2;anchor:锚点参数与模型参数一致,同一个模型这个参数是固定的,和模型绑定的(训练模型时即确定了), 不能改成其它值。

header = bytearray([0xFF])  #包头
Left_Direction = bytearray([0x3A])  #左转
Right_Direction = bytearray([0x3B]) #右转
footer = bytearray([0xFE])  #包尾



while(True):

    img = sensor.snapshot()
    code = kpu.run_yolo2(task, img) #kpu.run_yolo2(kpu_net,image_t)kpu_net: kpu_load 返回的 kpu_net 对象;image_t:从 sensor 采集到的图像;返回值:kpu_yolo2_find 的列表
    #运行yolo2网络。kpu.run_yolo2()返回一个二维列表,每个子列表代表一个识别到的目标物体,目标物体信息列表包含以下6个数据:x, y, w, h:代表目标框的左上角x,y坐标,以及框的宽w高h.class: 类别序号.prob : 概率值,范围:[0, 1]

    if code:
        for i in code:
            a=img.draw_rectangle(i.rect()) #i.rect()这个方法调用返回一个代表检测到的对象边界框的元组。这个元组通常包含四个元素(x,y,w,h)
            a = lcd.display(img) #识别到后,立马画矩形框
            #kpu.run_yolo2(task, img) 的返回值是一个列表,列表中的元素为字典。每个字典表示检测到的一个对象的相关信息,
            #包括矩形框左上角的元素位置(x、y)、矩形的宽度和高度(w、h)、该对象的概率值(value)、类别 ID(classid)、索引(index)以及对象的数量(objnum)等。

            x1,y1,x2,y2 = i.rect() #解包,将其赋值给x1,y1,x2,y2
            x_center = (x1 + x2) // 2

            if x_center < 80:
               lcd.draw_string(100, 20, "left", lcd.RED, lcd.WHITE)
               uart.write(header+classes[i.classid()]+Left_Direction++footer)
               #uart.write(header+classes[i.classid()]+footer)
               print(classes[i.classid()])
            else:
               lcd.draw_string(200, 20, "right", lcd.RED, lcd.WHITE)
               uart.write(header+classes[i.classid()]+Right_Direction++footer)
               #uart.write(header+classes[i.classid()]+footer)
               print(classes[i.classid()])
            for i in code:
               lcd.draw_string(i.x(), i.y(), classes[i.classid()], lcd.BLUE, lcd.WHITE)
               lcd.draw_string(i.x(), i.y()+12, '%f'%i.value(), lcd.BLUE, lcd.WHITE)
               #uart.write('0xb3'+'0xb3'+classes[i.classid()]+classes[i.classid()]+classes[i.classid()]+'0x5b')

    else:
        a = lcd.display(img)

#uart_A.deinit()
#del uart_A
#a = kpu.deinit(task)

上面的代码是k210识别标签后给stm32发送标签数字'1', '2', '3', '4', '5', '6', '7', '8'。但是在主控里的usart使用的是下面这行代码,依旧能接收。不仅如此,而且是字符S ,A等,其他字符均可接收。

uint16_t Serial_RxPacket[4];
当发送的字符为A时,代码如下
import sensor, image, lcd, time
from machine import UART
from fpioa_manager import fm

# 针对 Maix 系列开发板的引脚映射
fm.register(7, fm.fpioa.UART1_TX, force=True)
fm.register(6, fm.fpioa.UART1_RX, force=True)

uart = UART(UART.UART1, 9600, 8, 0, 1, timeout=1000, read_buf_len=4096)

header = bytearray([0xFF])
footer = bytearray([0xFE])
label = 'A'
#label = 'S'


while True:
    a=uart.write(header + label.encode() + footer)
    print(a)

A
串口助手在
十六进制下为: FF 41 FE 
文本模式下为:?A?A?A?A?A?A?

S
串口助手在
十六进制下为: FF 53 FE 
文本模式下为:S?S?S?S?

那么为什么明明是字符,主控用无符号整形也能接受呢?

分情况讨论:

接收在十六进制下,包头包尾本身就是十六进制。所以在十六进制的模式下,直接显示FF和FE。那么字符S和A呢?他们又不是十六进制,为什么可以被接收?那就得讲讲ASCII码了

ASCII(美国标准信息交换码,American Standard Code for Information Interchange)是一种字符编码标准,用于表示文本数据。每个字符都被映射到一个唯一的整数值,范围从 0127。这使得计算机可以用整数来表示和处理字符。

  • 控制字符0x000x1F(如换行符、回车符)
  • 可打印字符0x200x7E(如字母、数字、标点符号)
  • 删除符0x7F
  • ASCII 范围:ASCII 字符集仅包含从 0x000x7F 的字符。

https://blog.csdn.net/u010033786/article/details/126275465

在这个链接里,你可以明白为什么是范围从 0127,为什么0x000x7F ,且两者是映射的。

为什么字符能在 STM32 的整形数组中被接收?

在 STM32 这样的嵌入式系统中,接收字符数据并将其存储在整形数组中是因为:

  1. 字符是整数:在计算机中,字符实际上是整数。每个字符都有一个对应的整数值(即 ASCII 码)。例如,字符 'S' 的 ASCII 码是 83(十六进制 0x53),在整形数组中就是 83

  2. 整形数组存储字节:在 STM32 中,整形数组可以存储字节(uint8_t)、半字(uint16_t)、字(uint32_t)等。字符数据(即其 ASCII 码)可以直接存储在这些数组中。因为每个字符的 ASCII 码都是一个 8 位的值(即一个字节),可以用 uint8_t(无符号 8 位整数)来存储。

  3. 数据传输:串口通信等数据传输方式通常以字节为单位传输数据。在 STM32 中,通过 UART 接收数据时,接收到的字节数据可以存储在整形数组中。接收到的数据可以是字符(ASCII 码)、数字或其他二进制数据。处理数据时,可以将这些字节解释为对应的字符或其他数据类型。

是的,你可以这样理解。让我们详细分解一下这个过程:

1. 转换字符为 ASCII 码

当你传输字符 'S' 时,它首先被转换为其 ASCII 码。对于 'S',其 ASCII 码是 83(十进制),十六进制表示为 0x53,二进制表示为 01010011

2. 传输数据

在传输过程中,字符 'S' 实际上被转化为其 ASCII 码 0x53 的字节数据。传输的是字节数据,而不是字符本身。

3. 主控接收数据

主控(如 STM32)接收到的实际上是一个字节(0x53),它能够理解和处理这个字节。主控不关心这个字节代表什么字符,只是按照字节流的方式接收数据。

4. 显示数据

  • 十进制模式:在十进制模式下,字节值 0x53 会显示为 83
  • 十六进制模式:在十六进制模式下,字节值 0x53 会显示为 53
  • 文本模式:在文本模式下,字节 0x53 会显示为字符 'S'

ASCII码是人与计算机之间的桥梁,十六进制是一种表现方式(也可以说是HEX模式),

文本模式也是一种模式,只不过这种 模式主要是为人类服务的,是给人看的。但是只能看到0x20到0x7E的字符,其他的则是乱码。

为什么不能转化为两个 ASCII 字符

0xFF0xFE 是单个字节的数据,超出了标准 ASCII 字符集的范围:

  1. 单字节表示

    • 0xFF0xFE 都是 8 位数据(即一个字节)。在 ASCII 编码中,一个字符始终由一个字节表示。如果一个字符的 ASCII 码超出了 ASCII 编码范围(0x000x7F),它不能被直接解释为标准的 ASCII 字符。即使在扩展 ASCII 中,这些值也可能不对应于可打印字符。
  2. 不能拆分为两个 ASCII 字符

    • ASCII 编码是基于 7 位或 8 位的单字节表示,每个字符都是独立的一个字节。0xFF0xFE 本身是两个单独的字节,它们并不代表两个 ASCII 字符,而是一个单独的值。
    • 如果你将 0xFF0xFE 拆分成两个 4 位的半字节(nibbles),你得到的值(0xF0xF0xF0xE)不能直接映射到标准 ASCII 字符集,因为 ASCII 字符集不是以这种方式设计的。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值