Jetson nano和STM32通信

本文详细介绍了如何使用Jetson Nano通过串口与STM32进行通信,包括Jetson Nano的串口配置、数据包的三种发送方式以及STM32的数据处理。文中提供了Python代码示例,涉及struct库的使用,以及数据帧头和校验位的处理。STM32端的数据接收通过中断完成,要求前两个帧头和校验位正确。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Jetson nano系列之串口使用



前言

据上次博主写OpenMV与STM32通信的博客已经过去两个月了,今天在写下Jetson nano 与 STM32 的通信问题。
我先把上次文章的地址贴过来:
Openmv与STM32通信
还有相关的程序,我也已经打包好上传到了优快云上,我在把它贴出来:
基于STM32C8T6的OLED+USART+OpenMV
之所以要提到OpenMV的通信问题,是因为Jetson nano的串口通信过程和OpenMV相差不大,二者可以做一个对比。


一、Jetson nano串口配置

  这里的串口配置,优快云上许多博主都有说到,而且也都挺详细的,所以我就不大做文章,我就一笔带过就好了。
   配置串口的时,记得给予Jetson nano串口权限,在终端控制区输入
`sudo chmod 777 /dev/ttyTHS1` 

这个指令,打开串口权限,这个权限每次重新开机后都需要重新设置。

import serial

com = serial.Serial("/dev/ttyTHS1",115200)


   这就是打开串口所需要的代码,由于和OpenMv一样,也是基于python,所以也是一样的简洁和实用。

   主要操作就是,调用serial库,然后使用其中的函数,打开和配置串口,像我在代码中所写的,打开串口,配置其波特率为115200。

二、通信过程


   在我之前的OpenMV与STM32通信的博客中,我提及到的OpenMV和STM32数据传输通信中所使用的方法,而现在改用Jetson nano来实现与STM32数据传输通信,基本上在OpenMV与STM32上传输数据能成功的方法也可以适用于Jetson nano上。

   Jetson nano写串口的函数和OpenMV写串口的函数一样,都是 .write( ) 的函数来写入,这就对写入的数据有所要求。

1.使用数据包的形式发送数据

代码如下:

impor struct

def pack_Data(a,b):
    temp = struct.pack("<BBbb",0x2C,0x12,int(a),int(b))
    print(temp)

    com.write(temp)


   首先这里需要引入struct库,然后调用struct中的 .pack 函数,使用该函数来对所需要发送的数据进行打包。

   对于struct.pack() 的函数分析, 可以参考博主之前写的OpenMV的数据传输通信部分,也可以优快云上搜索 struct.pack() 这个噶不是这里不在重复介绍解释,这里的主要操作是,我声明我所发送的几个数据的格式,并将其打包完成后,再一并发送。

   对于0x2C、0x12这两个所对应的是**BB**,而B所对应的是有符号的char类型,但在这影响不大,0x2C、0x12都位于[-128,127]的区间中,毫无疑问,这里出现的这两个数据,便是起到数据帧头的作用。本来按理说,应该在数据串的末端再增加一个校验和来作为数据是否完全传输的判断来确保数据的准确性的,但在这就先不重复说明,大家应该都知道怎么操作。

   而后面的两个数据——数据a、数据b,对应的是bb这两个类型格式,而b所对应的是无符号的char类型,区间位于[0,255],这个后面数据传输时候是需要稍加注意的。于此之外,还有在这个数据接收的过程应该格外注意下,不同的数据类型所占的数组大小不同,很多情况下数据为0,可能是因为你读取数组存放位置出现了问题,而不是数据没有送达到位。

   最后再通过com. write( temp)将数据发送出去。

2.另外一种数据包形式发送数据

代码如下:

BUF = bytearray(5)

def packData( a , b, ):
    print(BUF)
    struct.pack_into('<2B2b', BUF, 0, 0x2C, 0x12,  a, b, )
    checksum = 0
    for i in BUF[:-1]:
        checksum += i
        checksum = (checksum & 0xff)
    struct.pack_into('<B', BUF, 4, checksum)

    com.write(BUF)


   这个方法是使用 struct 库中另外的函数, struct.pack_into() 函数

 struct.pack_into(fmt, buffer, offset, v1, v2, ...)该函数的用法:
   按照指定的格式fmt,将v1,v2...打包到buffer中,其中偏移位置为offset。 也就说在这个函数中的作用就是将0x2C、0x12、数据a、数据b 都加入到数组BUF中,并在最后为这个数组添加一个校验位。而数据格式类型的选择与之前的 .pack( )函数中的相同,只是此处BBbb变成了2B2b而已。

3.使用list直接发送数据

代码如下:

def Data(a,b):
    data = [0x2C,0x12,int(a),int(b),0xAA]
    data = bytearray(data)

    print(data)
    com.write(data)

   相较于以数据包的形式发送数据,本人比较喜欢这样发送数据的方法,比较简单,但是数据区间是[0,255]。此方法减少了数据处理的工作量。

   该方法最重要的一点就是对数据进行 bytearray() 的处理,只用这样处理后的数据才可以发送打印到串口上。需要注意。

   最后的0xAA便是校验位。

三、STM32数据处理


   STM32数据接收部分其实和OpenMv的那篇文章相同,同样也是打开串口1,改变波特率为115200。

   开启接收中断,然后在中断进行数据处理。首先需要前两个帧头正确了,最后是最后一位的校验位正确了,这段数据才算有效。

   我大概的代码如下(偷懒了一下,我并没有检查最后一位的校验位):
void USART1_IRQHandler(void)
{

		static u8 Rebuf[20]={0};
		static u8 i = 0;

		if( USART_GetITStatus(USART1,USART_IT_RXNE)!=RESET )
	{
		Rebuf[i++] = USART_ReceiveData(USART1);
		if(Rebuf[0] != 0x2c)
				i = 0;
		if((i==2)&&Rebuf[1] != 0x12)
			  i = 0;

			if(i>=10)
			{
				memcpy(OpenMV_Rx_BUF,Rebuf,i);
				i = 0;
			}
			USART_ClearITPendingBit(USART1,USART_IT_RXNE);//清除中断标志

	}
}

总结

   因为之前有配置OpenMV和STM32数据传输通信的问题频出,所谓吃一堑长一智,这次Jetson nano的数据传输串口通信上,并没有那么多的问题。所以我在本文开头才说先看完我的OpenMV串口通信的博客再来看我这篇文章,这样才会比较容易读懂。
### Jetson Nano STM32 之间的串口通信实现程序开关 为了实现在 Jetson Nano 上通过 Python 脚本发送命令给 STM32 来控制程序的开启或关闭,下面提供了一个完整的解决方案。 #### 在 Jetson Nano 上编写 Python 发送端代码 ```python import serial from time import sleep def send_command(command): try: with serial.Serial('/dev/ttyTHS1', baudrate=115200, timeout=1) as ser: message = f"{command}\r\n" encoded_message = message.encode('utf-8') ser.write(encoded_message) response = ser.readline().decode('utf-8').strip() print(f"Received from STM32: {response}") except Exception as e: print(e) if __name__ == "__main__": while True: user_input = input("Enter 'on' to start or 'off' to stop the program on STM32 ('q' to quit): ") if user_input.lower() == "on": send_command("START") # 启动指令 elif user_input.lower() == "off": send_command("STOP") # 停止指令 elif user_input.lower() == "q": break # 结束循环退出程序 else: print("Invalid command.") ``` 这段代码定义了一个 `send_command` 函数用于向 STM32 发送启动(`START`) 或停止 (`STOP`) 的字符串消息,并读取来自 STM32 的反馈信息[^4]。 主函数部分则创建了一个简单的交互界面让用户输入想要执行的操作。 #### 在 STM32 上编写的接收并响应命令的 C/C++ 代码片段 假设已经配置好了 UART 接收中断服务例程,在该 ISR 中对接收到的数据进行解析: ```c++ #include <string.h> char buffer[64]; volatile bool isProgramRunning = false; void USART1_IRQHandler(void){ /* Check whether an RXNE flag is set */ if (__HAL_UART_GET_FLAG(&huart1,UART_FLAG_RXNE)){ uint8_t ch; HAL_UART_Receive_IT(&huart1,&ch,1); strncat(buffer,(const char*)&ch,strlen((const char*)&ch)); // 当遇到回车符时处理整个命令 if(ch=='\n'){ stripNewline(buffer); // 移除可能存在的换行字符 if(strcmp(buffer,"START")==0 && !isProgramRunning){ StartProgram(); // 执行实际的任务初始化逻辑 strcpy(buffer,"Started"); isProgramRunning=true; }else if(strcmp(buffer,"STOP")==0 && isProgramRunning){ StopProgram(); // 清理资源等操作 strcpy(buffer,"Stopped"); isProgramRunning=false; } SendResponse(); memset(buffer,'\0',sizeof(buffer)); // 清空缓冲区准备下一次接收 } } } // 辅助函数:移除最后可能出现的新行字符 static void stripNewline(char *str){ size_t length=strlen(str)-1; if(length>0&&str[length]=='\r') str[length]='\0'; } ``` 此段嵌入式C代码展示了如何设置一个基本的状态机来监听特定的关键字(即 `"START"` `"STOP"`)。当检测到这些关键字之一时,则调用相应的功能函数去改变系统的运行状态,并返回确认信息给 Jetson Nano[^3]。
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值