基于树莓派4B与STM32的UART串口通信实验(代码开源)_树莓派4b串口波特率(1)

(1)、UART,(2)、SPI,(3)、I2C(该项目使用Serial)

1.2 树莓派4B安装Serial与使用

引脚连接:

根据上图树莓派4B的 Pin 引脚图中 GPIO14(TXD) 和 GPIO15(RXD) 的两个引脚分别与 STM32F103C8T6 的 PA10(RXD) 和 PA10(RXD) 的引脚相连(交叉连接

1.2.1 安装serial

在终端输入:sudo apt-get install serial

1.2.2 打开树莓派4B串口

在终端输入:sudo raspi-config 打开界面设置

Interfacing Options→serial→否→是

在终端输入:ls -al /dev/查看设备

1.2.3 修改串口映射关系

在终端输入:sudo nano /boot/config.txt

末行添加 dtoverlay=pi3-miniuart-bit

重启树莓派4B,之后终端输入:ls -la /dev/查看设备

1.2.4 修改配置文件

在终端输入:sudo nano /boot/cmdline.txt

修改cmdline.txt文件的内容,内容如下:

dwc_otg.lpm_enable=0 console=tty1 root=/dev/mmcblk0p2 rootfstype=ext4 elevator=deadline rootwait

二、安装minicom与树莓派4B测试

2.1  minicom安装

minicom 是 Linux/树莓派4B 平台串口调试工具,相当于 windows 上的串口调试助手,此时需要先安装 minicom

sudo apt-get install minicom

在终端输入:minicom -D /dev/ttyAMA0

如果要退出这个minicom软件的话,先按CTRL+A再按Z就会弹出菜单,按下0回车就退出了,然后就能直接关闭了。

2.2 树莓派4B通信测试

我们使用 XCOM 串口调试助手来测试树莓派4B能否正常进行 UART 通信!

使用USB-TTL模块交叉连接树莓派4B的 UART 的引脚;

**★特殊说明:**USB-TTL 模块的 VCC 和 GND 一定都要与树莓派4B的相应 Pin 相连,不然可能因为电流的不平衡导致端口疯狂输出乱码!

我们在下图 minicom 红框区域输入 **Hi IKUN!**字样之后,可以在 XCOM 的端口处看到字符串成功发送到了 PC 端;

同理,在 XCOM 端口发送 Hi My Brother 字样之后,可以在树莓派4B的  minicom 红框区域成功接收到该信息!

当成功完成上述的操作之后,说明我们已经成功的配置好树莓派4B的UART功能!之后就可以尝试与 STM32 进行通信了(发送数据给XCOM不仅可以通过 minicom,也可以通过python等代码)!

三、树莓派4B与STM32通信

STM32 的代码其实就是简单的UART串口通讯代码,但实质上是有很多坑!!!作者发现大部分博主并没有说明出坑所在,这部分作者将会为读者朋友把可能出现的坑给解决掉!

3.1 树莓派4B代码

我们利用 Python 代码写一个循环发送数字的代码程序,具体代码如下:

import serial  
import time  
  
ser = serial.Serial('/dev/ttyAMA0',115200) # 串口初始化,根据实际情况修改串口号和波特率  

# 定义要输出的数字  
num =  196 

while True:  
                
    ser.write(str(int(num)).encode()) # 发送数字到串口   
    num += 1  
    if num > 205:  
        num = 196
     
    time.sleep(0.2) # 等待1秒钟  

可以看出代码是非常简单的,但是这里读者朋友需要注意的是树莓派4B的端口发送至STM32的其实都是字符串流!在STM32端我们对发送过来的字符串流进行解码(很多博主其实都没有说明该点,导致很多朋友解码失败)!

3.2 CubeMX配置

1、RCC配置外部高速晶振(精度更高)——HSE;

2、SYS配置:Debug设置成Serial Wire否则可能导致芯片自锁);

3、I2C配置:

4、USART1配置:设置UART1串口;波特率:115200;开启UART串口中断;

5、时钟树配置

6、工程配置

3.3 STM32代码

3.3.1 OLED代码

OLED模块主要是方便显示树莓派4B发送给STM32的数据信息!考虑到实际情况,我们一般需要根据树莓派4B发送过来的数字信息,所以,我们这里利用OLED进行数字显示!

小数显示API函数:

//z_len为整数显示位数,f_len为小数显示位数,size2为字体大小
void OLED_Showdecimal(u8 x,u8 y,float num,u8 z_len,u8 f_len,u8 size2)
{         	
	u8 t,temp;
	u8 enshow;
	int z_temp,f_temp;      
	z_temp=(int)num;
	//整数部分
	for(t=0;t<z_len;t++)
	{
		temp=(z_temp/oled_pow(10,z_len-t-1))%10;
		if(enshow==0 && t<(z_len-1))
		{
			if(temp==0)
			{
				OLED_ShowChar(x+(size2/2)*t,y,' ',size2);
				continue;
			}
			else
			enshow=1;
		}
		OLED_ShowChar(x+(size2/2)*t,y,temp+'0',size2); 
	}
	//小数点
	OLED_ShowChar(x+(size2/2)*(z_len),y,'.',size2); 
	
	f_temp=(int)((num-z_temp)*(oled_pow(10,f_len)));
  //小数部分
	for(t=0;t<f_len;t++)
	{
		temp=(f_temp/oled_pow(10,f_len-t-1))%10;
		OLED_ShowChar(x+(size2/2)*(t+z_len)+5,y,temp+'0',size2); 
	}
}

篇幅有限,OLED参考博客:http://t.csdn.cn/kydg4

3.3.2 UART代码

这部分代码是比较核心的,上述博客作者已经说明了,其实树莓派4B发送给STM32的数据都是以字符串流的格式发送来得。所以,即使发送过来的是数字数据也会变成字符,这就需要我们进行解码!

uart.h:

#ifndef __UART_H
#define __UART_H

#include "stm32f1xx_hal.h" 

extern UART_HandleTypeDef huart1;

#define USART1_REC_LEN  600

extern int  USART1_RX_BUF[USART1_REC_LEN];
extern uint16_t USART1_RX_STA;
extern int USART1_NewData;

void  HAL_UART_RxCpltCallback(UART_HandleTypeDef  *huart);

#endif

uart.c:

#include "uart.h"
#include "oled.h"

int USART1_RX_BUF[USART1_REC_LEN];		//目标数据
uint16_t USART1_RX_STA=2;
int USART1_NewData;

extern int num;		//百位
extern int num2;    //十位
extern int num3;    //个位


void  HAL_UART_RxCpltCallback(UART_HandleTypeDef  *huart)
{
    if(huart ==&huart1)
    { 
			
      USART1_RX_BUF[USART1_RX_STA&0X7FFF]=USART1_NewData; 					
      USART1_RX_STA++;  
			
						
      if(USART1_RX_STA>(USART1_REC_LEN-1))USART1_RX_STA=0;

			//num = USART1_RX_BUF[USART1_RX_STA];
			
			HAL_UART_Receive_IT(&huart1,(uint8_t *)&USART1_NewData,1);
			
			num = USART1_RX_BUF[USART1_RX_STA-1];			
			num2 = USART1_RX_BUF[USART1_RX_STA-2];
			num3 = USART1_RX_BUF[USART1_RX_STA-3];			
    }		
}

上述UART代码,利用 UART 中断函数进行读取 USART1_NewData 的数值,因为我们最大传输的数字为3位数,所以我们分别读取缓存数组中最近的 3 个字节数据(树莓派4B发送过来的是字符串,也就是被转换成了对应数字的ASCII数值,例如:发送过来100,则STM32端接收到的为49 49 48 这3个字节)。

3.3.3 数据解码代码

control.c:

#include "control.h"
#include "uart.h"
#include "tim.h"
#include "oled.h"

int num;
int num2;
int num3;
int value;
int flag;
int last;


void TargetTracking()
{
	flag = USART1_RX_STA - last;
				
	last = USART1_RX_STA;
	
	value = (num3-48) * 100 + (num2-48) * 10 + (num-48) * 1;
	
	OLED_ShowStr(10,2,"Object Center",2);
	OLED_Showdecimal(45,4,value,3,1,16);
	
	if(flag == 2)
	{
		value = (num2-48) * 10 + (num-48) * 1;
		OLED_Showdecimal(40,4,value,3,1,16);
	}
	
}

这里默认都是 3 位数,所以之间按照 UART 数据传输高低位的数据将数据-48变为实际的数字,在×对应的比例即可得到实际值!flag 则是通过 USART1_RX_STA 变量的变化值判断一次传输过来几个字节的数据,可以判断是几位数!

读者朋友可以根据自己实际情况更改上述代码为己所用!

代码运行之后:

四、高级应用

智能小车的目标追踪

树莓派4B通常会出现在基于视觉技术进行规定目标的追踪,这个时候往往需要树莓派4B读取到目标框数据,然后发送给STM32下位机,之后STM32根据这些目标框信息来进行逻辑上的控制。

作者这里以上一篇博客的网络模型检测结果为例,代码如下:

import cv2
import numpy as np
import onnxruntime as ort
import serial
import time

**自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。**

**深知大多数嵌入式工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!**

**因此收集整理了一份《2024年嵌入式&物联网开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。**

![img](https://img-blog.csdnimg.cn/img_convert/bd856997621be46847c823f0304bacea.png)

![img](https://img-blog.csdnimg.cn/img_convert/45f01136a9c19da99e9e91bf9c9151ef.jpeg)

![img](https://img-blog.csdnimg.cn/img_convert/e6cb7cd319951b48cca4306aebcc553d.png)

 **既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上嵌入式&物联网开发知识点,真正体系化!**

![img](https://img-blog.csdnimg.cn/img_convert/01823f76fd039d072447c3d27a90fc7c.png)

![img](https://img-blog.csdnimg.cn/img_convert/19b49fc93c43f287886d311e1482aa0b.png)

 

**由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新**

**如果你觉得这些内容对你有帮助,可以+V:Vip1104z获取!!! (备注:嵌入式)**

<img src="https://img-community.csdnimg.cn/images/73bb5de17851459088c6af944156ee24.jpg" alt="img" style="zoom: 67%;" />



# 最后

**资料整理不易,觉得有帮助的朋友可以帮忙点赞分享支持一下小编~**

**你的支持,我的动力;祝各位前程似锦,offer不断,步步高升!!!**

-3Or2P3Vm-1712386366021)]

 **既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上嵌入式&物联网开发知识点,真正体系化!**

[外链图片转存中...(img-zzMIeXFs-1712386366022)]

[外链图片转存中...(img-2shUIufk-1712386366023)]

 

**由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新**

**如果你觉得这些内容对你有帮助,可以+V:Vip1104z获取!!! (备注:嵌入式)**

<img src="https://img-community.csdnimg.cn/images/73bb5de17851459088c6af944156ee24.jpg" alt="img" style="zoom: 67%;" />



# 最后

**资料整理不易,觉得有帮助的朋友可以帮忙点赞分享支持一下小编~**

**你的支持,我的动力;祝各位前程似锦,offer不断,步步高升!!!**

**[更多资料点击此处获qu!!](https://bbs.csdn.net/topics/618376385)**
  • 23
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Sure, here is an example code for STM32 to receive information from Raspberry Pi 4 over UART (serial communication): ```c #include "stm32f4xx.h" #include <stdio.h> #define BUFFER_SIZE 100 char rx_buffer[BUFFER_SIZE]; uint8_t rx_index = 0; uint8_t rx_data_available = 0; void USART2_IRQHandler(void) { if (USART_GetITStatus(USART2, USART_IT_RXNE) != RESET) { rx_buffer[rx_index] = USART_ReceiveData(USART2); rx_index++; if (rx_index >= BUFFER_SIZE) { rx_index = 0; // Reset buffer index if it exceeds the buffer size } rx_data_available = 1; } } void USART2_Init(void) { GPIO_InitTypeDef GPIO_InitStruct; USART_InitTypeDef USART_InitStruct; NVIC_InitTypeDef NVIC_InitStruct; // Enable clock for USART2 and GPIOA RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE); RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE); // Configure pins for USART2 GPIO_InitStruct.GPIO_Pin = GPIO_Pin_2 | GPIO_Pin_3; GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF; GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStruct.GPIO_OType = GPIO_OType_PP; GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_UP; GPIO_Init(GPIOA, &GPIO_InitStruct); // Connect USART2 pins to AF7 GPIO_PinAFConfig(GPIOA, GPIO_PinSource2, GPIO_AF_USART2); // USART2_TX GPIO_PinAFConfig(GPIOA, GPIO_PinSource3, GPIO_AF_USART2); // USART2_RX // Configure USART2 USART_InitStruct.USART_BaudRate = 9600; USART_InitStruct.USART_WordLength = USART_WordLength_8b; USART_InitStruct.USART_StopBits = USART_StopBits_1; USART_InitStruct.USART_Parity = USART_Parity_No; USART_InitStruct.USART_HardwareFlowControl = USART_HardwareFlowControl_None; USART_InitStruct.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; USART_Init(USART2, &USART_InitStruct); // Enable USART2 interrupt NVIC_InitStruct.NVIC_IRQChannel = USART2_IRQn; NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 0; NVIC_InitStruct.NVIC_IRQChannelSubPriority = 0; NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStruct); // Enable USART2 and receive interrupt USART_Cmd(USART2, ENABLE); USART_ITConfig(USART2, USART_IT_RXNE, ENABLE); } int main(void) { // Initialize USART2 USART2_Init(); while (1) { if (rx_data_available) { // Process received data printf("Received: %s", rx_buffer); // Reset buffer and data available flag rx_index = 0; rx_data_available = 0; } } } ``` Make sure to configure the Raspberry Pi 4 to transmit data over the UART interface correctly as well.

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值