【K230 CanMV】UART K210与STM32串口通信 发送接收数据包 附源码

引言:随着嵌入式系统的发展,串口通信(UART)成为了不同硬件平台之间进行数据传输和控制的重要手段。在嵌入式系统中,串口通信的应用十分广泛,尤其是在处理器与外设、微控制器之间的数据交换中,串口通信的稳定性和高效性至关重要。本文将重点介绍 K230 系列处理器的 UART 外设及其在实际开发中的应用,结合具体的代码示例,深入探讨如何利用串口进行数据的发送、接收及串口回环测试等常见操作。

通过本篇文章,读者将能够全面了解 K230 的 UART 外设功能,掌握如何通过 CanMV IDE 环境开发串口通信程序,并通过具体案例学习如何在 K230 与其他硬件设备(如 STM32)之间实现数据交换。

目录

一、什么是串口?串口的本质

二、K230的UART外设

三、CanMV IDE UART 使用方法

四、实际案例-K230发送数据

发送基本数据

发送字节数组

五、实际案例-K230接收数据

接收数据代码

接受换行符结尾的文本

六、实际案例-串口回环测试

七、STM32与K230串口通信 数据包的形式接收发送


一、什么是串口?串口的本质

对于协议类的问题,我们应该系统性的学习,在之前笔者有对于各种协议的汇总,包含uart、IIC、SPI、CAN、232、485、等等基础协议以及变种协议modbus等,如果想系统性学习可以回到之前看看文章,接下来就是先认识串口通信了,在使用相关API的时候,很少会理解该协议的本质,如下笔者开始阐述,带你搞懂UART协议。

UART(Universal Asynchronous Receiver-Transmitter,通用异步收发传输器)是嵌入式系统和电子设备中常用的一种串行通信协议。UART的广泛应用主要集中在微控制器、嵌入式系统模块、传感器以及调试接口等方面。甚至以前的电脑都是自带串口的老式的DB9接口,不过随着科技发展在个人PC上被逐渐淘汰了,被USB等更现代化的接口替代了。

其是一种异步串行通信协议,发送端和接收端的数据传输不需要时钟信号同步,也就是说不需要额外的时钟线。UART主要通过以下两条线来进行数据传输:

  • TXD(Transmit Data):数据发送端,将数据从发送设备发送到接收设备。
  • RXD(Receive Data):数据接收端,用于接收从发送设备发来的数据。

通信时,UART会将并行数据(如8位数据)用移位寄存器转换成串行格式逐位按照比特顺序发送发送;接收端会将将比特(bit)数据组装为字节,供系统进一步处理。

UART数据帧格式,UART的本质(重要)

  • 空闲位

    • 处于高电平(逻辑 1)。
  • 起始位

    • 1 位,发送 0(逻辑低电平)。
    • 用于标识数据传输的开始。
  • 数据位

    • 一般为 8 位,数据以二进制 0 或 1 的形式传输。
    • 在 5 至 8 位的数据中,低位先发送(从右至左)。
  • 校验位

    • 可选的 1 位,用于检验数据的准确性。
    • 常见的校验方式有奇偶校验(可以是奇校验或偶校验)。
  • 停止位

    • 停止位用来结束数据传输,通常为 1 位,发送 1(高电平)。
    • 可以选择 1 位、1.5 位或 2 位的停止位。

  • 发送端:先发送起始位,将TX线拉低,然后依次发送数据位,接着发送可选的奇偶校验位,最后发送停止位。
  • 接收端:检测起始位的到来,然后按顺序接收数据位,校验位(如果有),并通过停止位判断传输结束。

串口可以工作在单工【一根数据线】、半双工【一根数据线】和全双工【两根数据线】模式下。

  • 单工:在通信的任意时刻,信息只能由 A 传到 B。
  • 半双工:在通信的任意时刻,信息即可由 A 传到 B,又能由 B 传到 A,但同时只能有一个方向上的传输存在。同一条数据线。
  • 全双工:在通信的任意时刻,通信线路上存在 A 到 B 和 B 到 A 的双向信号传输。

二、K230的UART外设

针对于K230我们还是可以用之前的办法来查询相关外设,也就是如下的方法:

from machine import FPIOA
# 实例化FPIOA
fpioa = FPIOA()
# 打印所有引脚配置
fpioa.help()

我们也可以根据下述表格来找到相关引脚。

排针引脚号芯片引脚号串口功能号备注
03GPIO 49UART4_RXD同时连入摄像头2(CSI2)用作IIC通讯,板子内部有4.7K的电阻上拉至3.3V
05GPIO 48UART4_TXD同时连入摄像头2(CSI2)用作IIC通讯,板子内部有4.7K的电阻上拉至3.3V
08GPIO 03UART1_TXDNa
10GPIO 04UART1_RXDNa
11GPIO 05UART2_TXDNa
13GPIO 06UART2_RXDNa
27GPIO 41UART1_RXD同时连入摄像头1(CSI1)用作IIC通讯,板子内部有4.7K的电阻上拉至3.3V
28GPIO 40UART1_TXD同时连入摄像头1(CSI1)用作IIC通讯,板子内部有4.7K的电阻上拉至3.3V
29GPIO 36UART4_TXDNa
31GPIO 37UART4_RXDNa
37GPIO 32UART3_TXDNa
40GPIO 33UART3_RXDNa

本身是有五个串口可以使用的,但是有些串口会被占用以及与上位机通讯调试之类的作用,因此我们需要结合自身的开发板找到合适的串口才行,我们需要根据原理图以及相关固件程序来明确。

这里笔者使用串口2,如下所示:

丝印简称芯片引脚号串口功能号备注
VNaNa5V输入输出口
RGPIO 11UART2_RXDNa
TGPIO 12UART2_TXDNa
GNaNaGND,接地点

需要注意的是 K230 芯片内部集成了 5 个 UART 硬件模块,其中 UART0 被小核(sh)占用,UART3 被大核(sh)占用,剩余的 UART1、UART2 和 UART4 供用户使用。用户在使用时,可通过 IOMUX 模块进行 UART 引脚的配置。

三、CanMV IDE UART 使用方法

K230 内部集成了五个 UART(通用异步收发传输器)硬件模块,串口3(当前固件没被占用,但如果使用的是Linux+RT-Smart SDK就会被小核占用,如果用最新的CanMV固件则用户可以使用);串口0(被RT-Smart占用,最新的CanMV K230固件中只在大核中运行了RT-Smart),剩下的串口1,2,3,4均可被用户正常调用。

使用 machine 模块来配置 UART 串口的引脚,并使用 FPIOA 来设置引脚的功能。

from machine import UART

from machine import FPIOA

fpioa = FPIOA()

# 将指定引脚配置为 UART 功能
fpioa.set_function(11, FPIOA.UART2_TXD)
fpioa.set_function(12, FPIOA.UART2_RXD)

1.构造函数

uart = UART(id, baudrate=115200, bits=UART.EIGHTBITS, parity=UART.PARITY_NONE, stop=UART.STOPBITS_ONE)
参数类型有效值默认值描述
id常量UART.UART1UART.UART2UART.UART3UART.UART4无(必须指定)UART 模块编号,选择对应的 UART 模块(如 UART1UART2 等)。
baudrate整数任意正整数(如 9600、115200、460800、921600 等)115200波特率,表示串口通信的传输速率,单位为比特每秒(bps)。
bits常量UART.FIVEBITSUART.SIXBITSUART.SEVENBITSUART.EIGHTBITSUART.EIGHTBITS数据位数,表示每个字符的位数。常见的为 8 位。
parity常量UART.PARITY_NONEUART.PARITY_ODDUART.PARITY_EVENUART.PARITY_NONE校验位,用于检查数据传输中的错误。可选择无校验、奇校验或偶校验。
stop常量UART.STOPBITS_ONEUART.STOPBITS_TWOUART.STOPBITS_ONE停止位数,标识数据帧结束时使用的停止位数。常见的为 1 位或 2 位停止位。

案例:

uart = UART(UART.UART1, baudrate=9600, bits=UART.SEVENBITS, parity=UART.PARITY_EVEN, stop=UART.STOPBITS_ONE)

 创建了一个 UART1 模块,波特率为 9600,比特位为 7 位,使用偶校验位,停止位为 1 位。

2.串口初始化

uart.init(baudrate=115200, bits=UART.EIGHTBITS, parity=UART.PARITY_NONE, stop=UART.STOPBITS_ONE)

3.串口read函数

uart.read([nbytes])

4.串口readline函数

uart.readline()

5.串口readinto函数

uart.readinto(buf[, nbytes])

6.串口write函数

uart.write(buf)

7.串口deinit函数

uart.deinit()

四、实际案例-K230发送数据

发送基本数据

K230 UART发送基本数据

from machine import UART
from machine import FPIOA

# 配置引脚
fpioa = FPIOA()
fpioa.set_function(11, FPIOA.UART2_TXD)
fpioa.set_function(12, FPIOA.UART2_RXD)

# 初始化UART2,波特率115200,8位数据位,无校验,1位停止位
uart = UART(UART.UART2, baudrate=115200, bits=UART.EIGHTBITS, parity=UART.PARITY_NONE, stop=UART.STOPBITS_ONE)

# 要发送的字符串
message = "Hello,LuShan-Pi!\n"

# 通过UART发送数据
uart.write(message)

# 释放UART资源
uart.deinit()

使用 UART2 串口进行数据通信。首先,使用 FPIOA 类来配置物理引脚,将引脚 11 设置为 UART2 的发送数据引脚(TXD),将引脚 12 设置为 UART2 的接收数据引脚(RXD)。接下来,初始化 UART2 串口,设置波特率为 115200,数据位为 8 位,无奇偶校验,停止位为 1 位。然后,定义了一个字符串 message = "Hello,LuShan-Pi!\n" 作为要发送的内容,并通过 uart.write(message) 通过 UART2 发送该字符串。最后,通过 uart.deinit() 释放了 UART2 资源,关闭了串口通信。

发送字节数组

如下方式即可,非常简单,相信大家都可以看懂。

from machine import UART
from machine import FPIOA

# 配置引脚
fpioa = FPIOA()
fpioa.set_function(11, FPIOA.UART2_TXD)
fpioa.set_function(12, FPIOA.UART2_RXD)

# 初始化UART2,波特率115200,8位数据位,无校验,1位停止位
uart = UART(UART.UART2, baudrate=115200, bits=UART.EIGHTBITS, parity=UART.PARITY_NONE, stop=UART.STOPBITS_ONE)

# 发送字节数组
data = bytes([0x01, 0x02, 0x03, 0x04])
uart.write(data)

# 释放UART资源
uart.deinit()

五、实际案例-K230接收数据

接收数据代码

K230 UART的接收数据代码如下所示:

from machine import UART
from machine import FPIOA

# 配置引脚
fpioa = FPIOA()
fpioa.set_function(11, FPIOA.UART2_TXD)
fpioa.set_function(12, FPIOA.UART2_RXD)

# 初始化UART2,波特率115200,8位数据位,无校验,1位停止位
uart = UART(UART.UART2, baudrate=115200, bits=UART.EIGHTBITS, parity=UART.PARITY_NONE, stop=UART.STOPBITS_ONE)

data = b''

#如果接收不到数据就一直尝试读取
while data == b'':
    # 读取数据
    data = uart.read()  # 尝试读取数据

#通过CanMV IDE K230中的串行终端控制台打印出来
print("Received:", data)

#通过串口2发送接收到的数据
uart.write("UART2 Received:{}\n".format(data))

# 释放UART资源
uart.deinit()

通过 FPIOA 配置了 UART2 的传输和接收引脚,随后初始化了 UART2 串口,设置了波特率为 115200,数据位为 8 位,无校验位,停止位为 1 位。接下来,代码在一个 while 循环中持续尝试读取通过 UART2 接收到的数据,如果没有数据接收,则会继续读取。一旦接收到数据,它会打印该数据到控制台,并将接收到的数据通过串口回传。最后,代码通过 uart.deinit() 释放了 UART2 资源,关闭了串口通信。这段代码适用于串口通信的基本数据接收与回传操作。

接受换行符结尾的文本

如果接收的数据是以换行符结尾的文本,可以使用 uart.readline() 方法读取一整行数据。

from machine import UART
from machine import FPIOA

# 配置引脚
fpioa = FPIOA()
fpioa.set_function(11, FPIOA.UART2_TXD)
fpioa.set_function(12, FPIOA.UART2_RXD)

# 初始化UART2,波特率115200,8位数据位,无校验,1位停止位
uart = UART(UART.UART2, baudrate=115200, bits=UART.EIGHTBITS, parity=UART.PARITY_NONE, stop=UART.STOPBITS_ONE)

line = b''

#如果接收不到数据就一直尝试读取
while line == b'':
    # 读取数据
    line = uart.read()  # 尝试读取数据

#通过CanMV IDE K230中的串行终端控制台打印出来
print("Received:", line)

#通过串口2发送接收到的数据
uart.write("UART2 Received:{}\n".format(line))

# 释放UART资源
uart.deinit()

通过 UART2 串口接收数据,并通过串口将接收到的数据回传。首先,使用 FPIOA 配置了引脚 11 和 12,分别作为 UART2 的发送(TXD)和接收(RXD)引脚。接着,初始化了 UART2,设置波特率为 115200,数据位为 8 位,无校验位,停止位为 1 位。在进入一个 while 循环后,代码持续尝试读取串口接收到的数据(通过 uart.read()),直到接收到数据为止。当数据被成功接收后,打印接收到的数据到控制台。接着,通过 UART2 将接收到的数据回传并格式化显示。最后,使用 uart.deinit() 释放 UART2 资源,关闭串口通信。这个过程展示了如何通过 UART 接收数据并将其回传的基本操作。

六、实际案例-串口回环测试

import time
from machine import UART
from machine import FPIOA

# 配置引脚
fpioa = FPIOA()
fpioa.set_function(11, FPIOA.UART2_TXD)
fpioa.set_function(12, FPIOA.UART2_RXD)

# 初始化UART2,波特率115200,8位数据位,无校验,1位停止位
uart = UART(UART.UART2, baudrate=115200, bits=UART.EIGHTBITS, parity=UART.PARITY_NONE, stop=UART.STOPBITS_ONE)

# 要测试的消息
test_message = b'UART Loopback Test!'

# 发送数据
uart.write(test_message)

# 等待数据发送和接收(根据波特率和数据长度,调整延时)
time.sleep(0.1)

# 如果接收不到数据就一直尝试读取
received_data = b''

received_data = uart.read()

if received_data:
    received_message = received_data
    print("Received:", received_message)
    if received_message == test_message:
        print("Loopback Test Passed!")
    else:
        print("Loopback Test Failed: Data Mismatch")
else:
    print("Loopback Test Failed: No Data Received")

print("test_message is {}".format(test_message))
print("received_message is {}".format(received_message))

# 释放UART资源
uart.deinit()

UART 环回测试。首先,使用 FPIOA 配置了引脚 11 和 12,分别作为 UART2 的发送(TXD)和接收(RXD)引脚。接着,初始化了 UART2,设置了波特率为 115200,数据位为 8 位,无校验位,停止位为 1 位。然后定义了一个要测试的消息 test_message,并通过 uart.write() 发送这个消息。

在发送数据之后,代码通过 time.sleep(0.1) 让程序暂停 0.1 秒,等待数据发送和接收。接下来,通过 uart.read() 尝试读取接收到的数据。如果成功接收到数据,程序会判断接收到的数据是否与发送的测试消息一致。如果一致,则打印 "Loopback Test Passed!",否则打印 "Loopback Test Failed: Data Mismatch"。如果没有接收到任何数据,则会打印 "Loopback Test Failed: No Data Received"。

最后,代码通过 print() 显示了发送的消息和接收到的消息,并使用 uart.deinit() 释放 UART 资源,关闭串口通信。这段代码的目的是验证 UART 串口的环回功能,确保发送的数据能够被正确接收。

七、STM32与K230串口通信 数据包的形式接收发送

K230与STM32串口连接(接线TX对RX即可),如下就是K230发送一个含有包头包尾的数据包格式,然后呈现在oled屏幕上。

直接附上所有代码,首先是K230的,如下所示:
 

import time
import os
import gc
import sys
import math
from media.sensor import *
from media.display import *
from media.media import *
from machine import UART
from machine import FPIOA

DETECT_WIDTH = 640
DETECT_HEIGHT = 480

# 只跟踪红色物体的阈值 (L Min, L Max, A Min, A Max, B Min, B Max)
# 红色的阈值
red_thresholds = [(30, 68, 9, 127, -12, 73)]  # 通用红色阈值 -> 索引为 0,所以代码 == (1 << 0)

sensor = None

# 配置引脚
fpioa = FPIOA()
fpioa.set_function(11, FPIOA.UART2_TXD)
fpioa.set_function(12, FPIOA.UART2_RXD)

# 初始化UART2,波特率115200,8位数据位,无校验,1位停止位
uart = UART(UART.UART2, baudrate=115200, bits=UART.EIGHTBITS, parity=UART.PARITY_NONE, stop=UART.STOPBITS_ONE)

try:
    # 使用默认配置构造一个Sensor对象
    sensor = Sensor(width=DETECT_WIDTH, height=DETECT_HEIGHT)
    # sensor复位
    sensor.reset()
    # 设置通道 0 输出大小
    sensor.set_framesize(width=DETECT_WIDTH, height=DETECT_HEIGHT)
    # 设置通道 0 输出格式
    sensor.set_pixformat(Sensor.RGB565)

    # 设置显示
    Display.init(Display.VIRT, width=DETECT_WIDTH, height=DETECT_HEIGHT, fps=100)

    # 初始化媒体管理器
    MediaManager.init()
    # sensor开始运行
    sensor.run()

    fps = time.clock()

    while True:
        fps.tick()

        # 检查是否应该退出
        os.exitpoint()
        img = sensor.snapshot()

        # 只检测符合红色阈值的斑点
        for blob in img.find_blobs(red_thresholds, pixels_threshold=100, area_threshold=100, merge=True):
            if blob.code() == 1:  # 代码为 1 表示仅红色
                # 绘制矩形框
                img.draw_rectangle([v for v in blob.rect()])
                # 绘制十字准星
                img.draw_cross(blob.cx(), blob.cy())
                # 绘制旋转角度
                img.draw_keypoints([(blob.cx(), blob.cy(), int(math.degrees(blob.rotation())))], size=20)

                # 获取色块在屏幕上的位置
                x, y, w, h = blob.rect()
                print(f"Blob position: (x: {x}, y: {y}, w: {w}, h: {h})")

# 发送 x 和 y 坐标到串口
                data = bytes([0xFF, x & 0xFF, (x >> 8) & 0xFF,
                y & 0xFF, (y >> 8) & 0xFF, 0xFE])
                uart.write(data)

        # 将结果绘制到屏幕上
        Display.show_image(img)
        gc.collect()

        print(fps.fps())

except KeyboardInterrupt as e:
    print(f"user stop")
except BaseException as e:
    print(f"Exception '{e}'")
finally:
    # sensor停止运行
    if isinstance(sensor, Sensor):
        sensor.stop()
    # 销毁display
    Display.deinit()

    os.exitpoint(os.EXITPOINT_ENABLE_SLEEP)
    time.sleep_ms(100)

    # 释放媒体缓冲区
    MediaManager.deinit()

    # 释放UART资源
    uart.deinit()

上述代码就是一个根据色度追踪图片呈现在画面屏幕的位置,然后发送到STM32。

其次是STM32的代码,如下所示:

#include "stm32f10x.h"                  // Device header
#include "Delay.h"
#include "OLED.h"
#include "Serial.h"
#include "Key.h"

int main(void)
{
	OLED_Init();
	Serial_Init();
	
	OLED_ShowString(1, 1, "RxPacket");
	
	while (1)
	{
		if (Serial_GetRxFlag() == 1)
		{
			OLED_ShowHexNum(2, 1, Serial_RxPacket[0], 2);
			OLED_ShowHexNum(2, 4, Serial_RxPacket[1], 2);
			OLED_ShowHexNum(2, 7, Serial_RxPacket[2], 2);
			OLED_ShowHexNum(2, 10, Serial_RxPacket[3], 2);
		}
	}
}
#include "stm32f10x.h"                  // Device header
#include <stdio.h>
#include <stdarg.h>

uint8_t Serial_TxPacket[4];				//FF 01 02 03 04 FE
uint8_t Serial_RxPacket[4];
uint8_t Serial_RxFlag;

void Serial_Init(void)
{
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
	
	GPIO_InitTypeDef GPIO_InitStructure;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOA, &GPIO_InitStructure);
	
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOA, &GPIO_InitStructure);
	
	USART_InitTypeDef USART_InitStructure;
	USART_InitStructure.USART_BaudRate = 115200;
	USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
	USART_InitStructure.USART_Mode = USART_Mode_Tx | USART_Mode_Rx;
	USART_InitStructure.USART_Parity = USART_Parity_No;
	USART_InitStructure.USART_StopBits = USART_StopBits_1;
	USART_InitStructure.USART_WordLength = USART_WordLength_8b;
	USART_Init(USART1, &USART_InitStructure);
	
	USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);
	
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
	
	NVIC_InitTypeDef NVIC_InitStructure;
	NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
	NVIC_Init(&NVIC_InitStructure);
	
	USART_Cmd(USART1, ENABLE);
}

void Serial_SendByte(uint8_t Byte)
{
	USART_SendData(USART1, Byte);
	while (USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);
}

void Serial_SendArray(uint8_t *Array, uint16_t Length)
{
	uint16_t i;
	for (i = 0; i < Length; i ++)
	{
		Serial_SendByte(Array[i]);
	}
}

void Serial_SendString(char *String)
{
	uint8_t i;
	for (i = 0; String[i] != '\0'; i ++)
	{
		Serial_SendByte(String[i]);
	}
}

uint32_t Serial_Pow(uint32_t X, uint32_t Y)
{
	uint32_t Result = 1;
	while (Y --)
	{
		Result *= X;
	}
	return Result;
}

void Serial_SendNumber(uint32_t Number, uint8_t Length)
{
	uint8_t i;
	for (i = 0; i < Length; i ++)
	{
		Serial_SendByte(Number / Serial_Pow(10, Length - i - 1) % 10 + '0');
	}
}

int fputc(int ch, FILE *f)
{
	Serial_SendByte(ch);
	return ch;
}

void Serial_Printf(char *format, ...)
{
	char String[100];
	va_list arg;
	va_start(arg, format);
	vsprintf(String, format, arg);
	va_end(arg);
	Serial_SendString(String);
}


void Serial_SendPacket(void)
{
	Serial_SendByte(0xFF);
	Serial_SendArray(Serial_TxPacket, 4);
	Serial_SendByte(0xFE);
}

uint8_t Serial_GetRxFlag(void)
{
	if (Serial_RxFlag == 1)
	{
		Serial_RxFlag = 0;
		return 1;
	}
	return 0;
}

void USART1_IRQHandler(void)
{
	static uint8_t RxState = 0;
	static uint8_t pRxPacket = 0;
	if (USART_GetITStatus(USART1, USART_IT_RXNE) == SET)
	{
		uint8_t RxData = USART_ReceiveData(USART1);
		
		if (RxState == 0)
		{
			if (RxData == 0xFF)
			{
				RxState = 1;
				pRxPacket = 0;
			}
		}
		else if (RxState == 1)
		{
			Serial_RxPacket[pRxPacket] = RxData;
			pRxPacket ++;
			if (pRxPacket >= 4)
			{
				RxState = 2;
			}
		}
		else if (RxState == 2)
		{
			if (RxData == 0xFE)
			{
				RxState = 0;
				Serial_RxFlag = 1;
			}
		}
		
		USART_ClearITPendingBit(USART1, USART_IT_RXNE);
	}
}

 上述涉及到十进制转十六进制,如果不会转的读者可以看下述例子,

表达式 x = (0x01 << 8) | 0x5F 可以分解为两步:

  1. 0x01 << 8:将 0x01(十六进制的1)左移8位,得到 0x0100(十六进制的256)。

  2. 0x0100 | 0x5F:按位或运算,将 0x0100(十六进制的256)和 0x5F(十六进制的95)进行按位或。计算如下:

    • 0x0100 = 00000001 00000000
    • 0x5F = 00000000 01011111 按位或的结果是:0x015F(十六进制的351)。

所以,最终结果 x = 0x015F,十进制值为 351

### 庐山派 K230 设备串口通信教程及问题解决 #### 串行通信接口 (UART) 的基本概念 串行通信接口(UART) 是嵌入式系统中常见的通信协议之一,用于实现设备间的异步串行数据传输。对于庐山派K230开发板而言,其提供了多个UART接口来满足不同的应用场景需求[^2]。 #### UART 接口配置初始化 为了使能和配置K230上的UART接口,在编程时通常需要设置波特率、停止位、校验模式以及字长等参数。具体操作可以通过调用相应的API函数完成。下面是一个简单的Python代码示例展示如何初始化UART: ```python import canmv.uart as uart def init_uart(port, baudrate=115200): config = { 'baudrate': baudrate, 'parity': None, 'stopbits': 1, 'bytesize': 8 } u = uart.UART(port) u.init(config) return u ``` 此段代码展示了如何创建一个`uart.UART()`对象,并通过传递端口号和其他必要的配置项来进行初始化工作。 #### 数据发送接收 一旦完成了UART的初始化过程之后就可以开始收发数据了。这里给出一段用来发送字符串消息给指定目标地址的例子: ```python def send_message(uart_instance, message="Hello World"): try: sent_bytes_count = uart_instance.write(message.encode()) print(f"{sent_bytes_count} bytes were successfully transmitted.") except Exception as e: print(e) # 使用之前定义过的init_uart方法获取实例化后的uart对象 u = init_uart('/dev/ttyUSB0') send_message(u) ``` 同样地,也可以编写类似的逻辑去读取来自其他设备的数据流并将其解码成人类可读的形式显示出来或者进一步处理。 #### 常见错误排查指南 当遇到无法正常工作的UART连接情况时可以从以下几个方面入手解决问题: - **检查硬件连线**:确保所有物理接线都牢固可靠; - **验证电源状态**:确认供电电压稳定且充足; - **调整波特率匹配度**:保证双方设定一致; - **查阅文档手册**:参照官方提供的技术参考资料寻找可能存在的特殊注意事项或限制条件; 以上就是针对庐山派K230设备上实施串口通讯的一些指导说明和技术要点介绍。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

7yewh

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值