ToB企服应用市场:ToB评测及商务社交产业平台
标题:
通信搬运工(开源)
[打印本页]
作者:
盛世宏图
时间:
2024-11-3 10:03
标题:
通信搬运工(开源)
目录
1. stm32与openmv通信
2. stm32与stm32通信
2.1 stm32 USART通信
2.1.1 stm32蓝牙与串口上位机
2.1.2 stm32与匿名上位机
2.2 stm32 SPI通信
2.2.1 stm32 2.4G
通过百度网盘分享的文件:开源文件.zip
链接:https://pan.baidu.com/s/1emgW2Q42Jg8jGXW6uKtZKA?pwd=1111
提取码:1111
媒介
哈喽,各位小同伴们各人好。我们在学习单片机大概其他外设的时候,我们都盼望可以查看他们的状态大概与电脑取得联系,来帮助我们更加的了解他们。其着实许多网站上面都有许多学习资料了,我也是这样学习过来的,哈哈。其实我也是一枚忠实的搬运工,下面我给各人总结和开源了我自己用过的一些通信方法与经验,各人可以挑自己喜欢的部分看哦,假如可以帮助到各人,那就收藏起来用吧,有时间可以看看。假如我讲的不对,还盼望大佬们引导引导,谢谢啦。
百度网盘链接:
1. stm32与 openmv通信
stm32与通过串口与openmv进行通信,串口通信还是很轻易上手的,只要我们把重要的一些参数设置规定好,像波特率、克制位啥的,引脚也连接精确就可以通信了。
(树莓派跟openmv串口通信方法都是差不多的)
openmv的实物引脚图:
接线(交叉相接):
openmv P4(TX)--stm32(RX)
openmv P5(RX)--stm32(TX)
openmv端
其实openmv端串口的利用就是直接调用他自带的库函数就行了,非常方便。不外就是发送的数据格式大概不是自己想要的。比如我做了一个主动捡球小车的体系,我想及时发送小球的坐标,但是直接调用库函数只能发送字节序列大概发送字符串,不可以直接发送int型数据。那咋办呢,那这时候我们就大概想到可以把int型数据转换成字节序列和字符型数据就可以发送了,没错我也是这样做的。下面我先容一下我的两种写法,我也会在百度链接内里标明,供各人参考。
1. 转字符型再发送
步骤:
1.打开对应串口外设并设置对应参数
uart=UART(3,115200) #初始化串口3
#uart.init(9600,bits=8,parity=None,stop=1) #设置串口3,波特率115200,数据位8,无校验位,克制位1位
固然对应的库也要导入
from machine import UART
from pyb import UART
import pyb
2.接下来把要发送的int型数据转换为字符型数据(我这里准备把x,y点的坐标都设置为三位数),并发送:
if 9<c.x()<100:
my_x='0'+str(c.x())
if 0<c.x()<10:
my_x='00'+str(c.x())
if 99<c.x():
my_x=str(c.x())
if 9<c.y()<100:
my_y='0'+str(c.y())
if 0<c.y()<10:
my_y='00'+str(c.y())
if 99<c.y():
my_y=str(c.y())
temp=my_x+my_y#拼接成字符串发送
#可以加入自己的帧头帧尾,我这里没加
temp=int(temp)
print(temp)
uart.write("@%d \r\n" % temp)#发送
复制代码
2. 转字节序列后再发送
步骤:
1.跟“转字符型再发送”步骤1一样。
2.接下来把要发送的int型数据转换为字节序列数据(由于x,y坐标在这最大值为3位,以是我把转换后的字节序列设置为8位的。假如你们必要传递的int数据超过8位的,你们只要改变转换格式就行了。8位是B,16位的是H,32位是I。
我举个例子以便大家理解(32位的):
import struct
# 假设我要传输一个整数变量
int_value = 12345
# 使用struct.pack将整数转换为字节序列
byte_array = struct.pack('<I', int_value ) #改这个I就行了
#byte_array的打印结构为b'\x39\x03\x00\x00'
复制代码
开始我们的传输代码:
# 使用struct.pack将整数转换为字节序列
byte_array1 = struct.pack('<B', c.x() )
byte_array2 = struct.pack('<B', c.y() )
UART_TXDATA=bytearray([0XFF,byte_array1,byte_array2,0XFE])
#自己设置帧头帧尾,加校验位,数据位都是没问题的,我这里帧头是0XFF,帧尾是0XFE。
#自己的数据帧需要stm32端有对应的解码就行
uart.write(UART_TXDATA)
复制代码
2. stm32与stm32通信
2.1 stm32 USART通信
stm32之间串口通信就不多说了,还是很轻易上手的。我们直接将步骤和上代码部分吧(代码部分我就用吸收openmv的代码):
留意点:
波特率两端参数设置一致,连线要RX、TX交叉相连就行。
引脚图:
接线(交叉相接):
openmv P4(TX)--stm32 PA10(RX)
openmv P5(RX)--stm32 PA9(TX)
代码部分:
//配置部分我删除了,不然会有点多
uint8_t Serial_TxPacket[2]; //FF 01 02 FE
uint8_t Serial_RxPacket[2];
uint8_t Serial_RxFlag;
void Serial_SendPacket(void)
{
Serial_SendByte(0xFF);
Serial_SendArray(Serial_TxPacket, 2);
Serial_SendByte(0xFE);
}
//接收字节序列部分
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 >= 2)
{
RxState = 2;
}
}
else if (RxState == 2)
{
if (RxData == 0xFE)
{
RxState = 0;
Serial_RxFlag = 1;
}
}
USART_ClearITPendingBit(USART1, USART_IT_RXNE);
}
}
复制代码
下面是解码部分:
// 解码就是把字节序列转换成一开始我们的坐标原始数据int型
uint8_t x_data,x_data;
x_data = (int)Serial_RxPacket[0];
y_data = (int)Serial_RxPacket[1];
/*
//假如解码16位字节序列
uint8_t x_data,x_data;
x_data = ((int)Serial_RxPacket[1] << 8) |
(int)Serial_RxPacket[0];
y_data = ((int)Serial_RxPacket[3] << 8) |
(int)Serial_RxPacket[2];
//32位就再移,依次类推
*/
复制代码
外加 stm32int转字节序列代码:
//这个是我问AI的,有兴趣可以看看
// 假设你有以下数据
int data = 123456; // 你想要发送的int数据
// 准备一个字节缓冲区
uint8_t dataBytes[4]; // 假设int为32位
// 将int数据转换为字节序列
memcpy(dataBytes, &data, 4); // 假设字节对齐正确
// 如果需要处理字节顺序,可以调整这里
// 例如,对于大端模式,可能需要反转字节顺序
// 发送数据
HAL_UART_Transmit(&huart1, dataBytes, 4, HAL_MAX_DELAY);
复制代码
2.1.1 stm32蓝牙与串口上位机通信
他们都是通过串口传输数据的,那他们详细是什么一个工作流程呢?疑惑?
有没有小同伴跟我一样,刚开始接触蓝牙的时候,疑惑过他们是怎么传输数据的呢?没事奥,现在带各人以我的视角重新浅浅认识一下,哈哈。其实我们只必要把他们两个模块当作是一条断开的线,当我利用魔法给他接上时,他就是一条电线。
(固然奥,这个是我叠起来的效果,不是真的可以接上奥,哈哈)
接线部分:
蓝牙 USB转TTL
VCC- 5V
GND-GND
RX-TX
TX-RX
下面开始展示我的魔法,哈哈。不美意思奥,我是戏精。
在此之前我先给各人分享文字上的教程(也是我自己的条记,我的字太丑了就不拍照了,我给你们打出来吧):
(在让他们相连之前必要下载一个串口助手,我用的是,其他的串口助手也是可以的)
给蓝牙模块进行AT指令我们必要,按住模块上的按键不动,然后把USB_TTL模块插入电脑。此过程不松手,当蓝牙指示灯开始慢闪,约莫2秒闪1次,就可以松手了。俩个蓝牙模块都这样上电。
有指令在旁边的,也可以自己更改再发送
随便选一个蓝牙作为从机(从机部分):
1.AT 进入指令模式(返回OK表示进入AT指令乐成)
2.AT+ORGL 先恢复出厂设置,并拔出来,再重新上电
3.AT 再次进入指令模式
4.AT+NAME 修改蓝牙名称 //修改格式为AT+NAME="名称"
5.AT+PSWD修改蓝牙配对密码 //“AT+ROLE="密码"(主从的密码要一致)
6.AT+CMODE=0 设置从模式
7.AT+ADDR ?获取蓝牙地点并记下
另外一个蓝牙作为主机(从机部分):
1.AT 进入指令模式(返回OK表示进入AT指令乐成)
2.AT+ORGL 先恢复出厂设置,并拔出来,再重新上电
3.AT 再次进入指令模式
4.AT+NAME 修改蓝牙名称 //修改格式为AT+NAME="名称"
5.AT+PSWD修改蓝牙配对密码 //“AT+ROLE="密码"(主从的密码要一致)
6.AT+CMODE=1 设置主模式
7.AT+CMODE=0 设置为指定蓝牙地点连接模式。
8.AT+BIND=xxx,xxx,xxx 绑定蓝牙地点,中间用逗号隔开。
2.1.2 stm32与匿名上位机
学会了蓝牙,我们现在用蓝牙把姿态信息传到匿名上位机上面进行显示。我就用官网的资料给各人展示吧。
其实我们要想把自己小车大概飞控的姿态信息,在匿名上面进行展示的话,只必要按照匿名给的通信协议来写,然后把他发送到上位机,他就会自己姿态跟随了。(还黑白常方便的)
这个是V7版的通信协议。
要想完成姿态跟随我们只必要按照官网的要求写对应的数据包就可以了。下面我们就以传输欧拉角格式数据帧讲解。
协议已经给出了明白的,
帧头:0XAA
目标地点: 0XFF
功能码:0X03
数据长度:0X07
数据内容: 一共有7位,2位ROL,2位PIT,2位YAW,1位姿态融合姿态
要求姿态角度精确到0.01(*100),两位。
数据内容的格式如下图:
和校验:就是从帧头开始,对每一字节进行求和,直到DATA区结束的一个值。
附加校验:每一字节的求和操纵,进行一次累加。假如和校验和附加校验相等,代表数据包校验通过。
可以看一下官方的资料:
了解完这些我们就可以来编写我们自己的数据包了:
在此之前,我先展示一下这整个数据包的格式,和内容:
这个数据包,一共13个字节。
展示代码:
#大家也可以写自己的数据帧,只要符合通信协议就可以
void nmswj_Reveal(float roL,float pit,float yaw)
{
u8 i;
unsigned int data_temp;
u8 sumcheck = 0;
u8 addcheck = 0;
u8 buf[13]={0};
buf[0]=0xAA;//帧头
buf[1]=0xFF;//目标地址
buf[2]=0x03;//功能码
buf[3]=0x07;//数据长度
//2字节横滚角
data_temp= (int)(Roll * 100);
buf[4]=(u8)data_temp;
buf[5]=(u8)(data_temp>>8);
//2字节俯仰角
data_temp=-(int)(pit* 100);
buf[6]=(u8)data_temp;
buf[7]=(u8)(data_temp>>8);
//2字节航向角
data_temp= (int)(yaw* 100);
buf[8]=(u8)data_temp;
buf[9]=(u8)(data_temp>>8);
//1字节融合状态
buf[10]=0x00;
for(i=0; i < 11; i++)
{
sumcheck += buf[i]; //从帧头开始,对每一字节进行求和,直到DATA区结束
addcheck += sumcheck; //每一字节的求和操作,进行一次sumcheck的累加
}
buf[11]=sumcheck;
buf[12]=addcheck;
if(sumcheck == buf[11] && addcheck == buf[12]) //数据帧校验判断
{Serial_SendArray(buf,13);}
}
复制代码
其实另有许多上位机,他们都有对应数据帧,必要我们按照官方给的资料进行编写也是可以利用他们的。而且上位机的功能不止于姿态的显示,各人可以多多试试,都是有规律的(我看过一些视频感觉的,哈哈)。
2.2 stm32 SPI通信
2.2.1 stm32 2.4G
通信方式千万种,2.4G也是其中一种(顺口溜,哈哈)。关于2.4G许多网站上面都有资料,还挺多的。各人就去网上直接拿资料就行了,我就不多说了,由于我也是在网上学习的。不外我还是可以展示一下我自己从零开始学习的条记和2.4G寄存器地点,盼望可以帮助到一些自己设置过IIc传感器的外设、并且学习过SPI协议的各位小同伴。
发送端初始化过程:
1.写发送端地点 TX_ADDR
2.写吸收端地点 RX_ADDR_P0
3.使能AutoACK EN_AA
4.使能PIPE0 EN_RXADDR
5.设置主动重发数 SETUP_RETR
6.选择通信频率 RF_CH
7.设置发送参数(低噪声放大器增益、发射功率、无线速率) RF_SETUP
8.选择通道0有用数据宽度 RX_PW_P0
9.设置24l01的根本参数以及工作模式 CONFIG
吸收端初始化过程:
1.写节点RX的地点 RX_ADDR_P0
2.使能AutoACK EN_AA
3.使能PIPE0 EN_RXADDR
4.选择通信频率 RF_CH
5.选择通道0有用数据宽度 RX_PW_P0
6.设置发送参数(低噪声放大器增益、发射功率、无线速率) RF_SETUP
7.设置24l01的根本参数以及工作模式 CONFIG
通信条件(必要条件):
1.频道雷同(设置频道寄存器RF_CH)
2.地点雷同(设置TX_ADDR和RX_ADDR_P0雷同)
3.每次发送吸收的字节数雷同(假如设置了通道的有用数据宽度为n,那么每次发送的字节数也必须为n,n<=32)
(在写入寄存器之前,肯定要进入待机模式)
//NRF24L01寄存器操作命令
#define nRF_READ_REG 0x00
#define nRF_WRITE_REG 0x20
#define RD_RX_PLOAD 0x61
#define WR_TX_PLOAD 0xA0
#define FLUSH_TX 0xE1
#define FLUSH_RX 0xE2
#define REUSE_TX_PL 0xE3
#define NOP 0xFF
//NRF24L01寄存器地址
#define CONFIG 0x00
#define EN_AA 0x01
#define EN_RXADDR 0x02
#define SETUP_AW 0x03
#define SETUP_RETR 0x04
#define RF_CH 0x05
#define RF_SETUP 0x06
#define STATUS 0x07
#define OBSERVE_TX 0x08
#define CD 0x09
#define RX_ADDR_P0 0x0A
#define RX_ADDR_P1 0x0B
#define RX_ADDR_P2 0x0C
#define RX_ADDR_P3 0x0D
#define RX_ADDR_P4 0x0E
#define RX_ADDR_P5 0x0F
#define TX_ADDR 0x10
#define RX_PW_P0 0x11
#define RX_PW_P1 0x12
#define RX_PW_P2 0x13
#define RX_PW_P3 0x14
#define RX_PW_P4 0x15
#define RX_PW_P5 0x16
#define FIFO_STATUS 0x17
//STATUS寄存器bit位定义
#define MAX_TX 0x10 //达到最大发送次数中断
#define TX_OK 0x20 //TX发送完成中断
#define RX_OK 0x40 //接收到数据中断
复制代码
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
欢迎光临 ToB企服应用市场:ToB评测及商务社交产业平台 (https://dis.qidao123.com/)
Powered by Discuz! X3.4