> 技术文档 > stm32和树莓派进行串口通信(无需安装micro-ROS版)_树莓派与stm32串口通信源码

stm32和树莓派进行串口通信(无需安装micro-ROS版)_树莓派与stm32串口通信源码


零、预设:

        本次实验是为了给ROS2模块小车的通信打基础,我们选择stm32f407和树莓派4B进行电机控制和数据处理,二者之间需要进行串口通信,找到一个比较方便的方法(无需安装micro-ROS)

一、基本思路:

        和普通的串口通信其实都差不多,只是stm32发送的数据要用树莓派的ros系统上来接收,我们这次只是为了验证能否正常通信,于是树莓派的ros系统上我们就用cutecom串口收发助手来进行接收

二、具体操作:

1、接线:

        我们使用TTL转串口来进行,注意stm32引出的串口RX、TX要和TTL转串口的TX、RX交错连接,引脚电平3v3,别忘了GND。        

2、stm32端的代码编写:

        我们使用串口1来进行收发数据

(1)串口1初始化(一般我们需要初始化串口的TX RX引脚、串口的波特率、数据的格式)

void uart1_init(u32 bound){ GPIO_InitTypeDef GPIO_InitStructure;USART_InitTypeDef USART_InitStructure;NVIC_InitTypeDef NVIC_InitStructure;RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE); //Enable the gpio clock //使能GPIO时钟RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE); //Enable the Usart clock //使能USART时钟GPIO_PinAFConfig(GPIOA,GPIO_PinSource9,GPIO_AF_USART1);GPIO_PinAFConfig(GPIOA,GPIO_PinSource10 ,GPIO_AF_USART1); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9|GPIO_Pin_10;//USART_Mode_Rx | USART_Mode_TxGPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF; //输出模式GPIO_InitStructure.GPIO_OType=GPIO_OType_PP; //推挽输出GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz; //高速50MHZGPIO_InitStructure.GPIO_PuPd=GPIO_PuPd_UP; //上拉GPIO_Init(GPIOA, &GPIO_InitStructure); //初始化 //UsartNVIC configuration //UsartNVIC配置NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;//Preempt priority //抢占优先级NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=1 ;//Subpriority //子优先级NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;//Enable the IRQ channel //IRQ通道使能NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //Initialize the VIC register with the specified parameters //根据指定的参数初始化VIC寄存器NVIC_Init(&NVIC_InitStructure); //USART Initialization Settings 初始化设置USART_InitStructure.USART_BaudRate = bound; //Port rate //串口波特率USART_InitStructure.USART_WordLength = USART_WordLength_8b; //The word length is 8 bit data format //字长为8位数据格式USART_InitStructure.USART_StopBits = USART_StopBits_1; //A stop bit //一个停止位USART_InitStructure.USART_Parity = USART_Parity_No; //Prosaic parity bits //无奇偶校验位USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None; //No hardware data flow control //无硬件数据流控制USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;//Sending and receiving mode //收发模式USART_Init(USART1, &USART_InitStructure); //Initialize serial port 1 //初始化串口1USART_ITConfig(USART1, USART_IT_RXNE, ENABLE); //Open the serial port to accept interrupts //开启串口接受中断USART_Cmd(USART1, ENABLE);  //Enable serial port 1 //使能串口1}

        通过上面的初始化,我们将PA9、PA10分别设为我们的RX、TX引脚,并配置了下面的数据格式,格式的参数在树莓派接收数据时会使用到 。

  • 波特率:通过函数参数bound动态设置波特率。

  • 数据位长度:设置为8位(USART_WordLength_8b)。

  • 停止位:设置为1个停止位(USART_StopBits_1)。

  • 校验位:无校验位(USART_Parity_No

(2)串口1接收中断

        在这里我们开启了串口接收的中断回调函数,如果你原来的 usartx.c 文件中就已经有同名的回调函数了,可以在原回调函数里头写或者把原回调函数给注释掉。

        在这里我们使用 data_smp来接收数据,flag_smp来做为状态机的标志位,状态机说得简单一点就是我们在中断函数中判断接收到了信息,通过对标志位flag_smp的标志后,再到主函数里头来收发数据(这里是选择了直接在串口中断回调函数中进行接收),因为我们要尽量少在中断函数中进行大量的函数使用。

//别忘了在 usartx.c 的最前端定义两个用于串口收发的变量uint8_t data_smp = 0;uint8_t flag_smp = 0; //标志位int USART1_IRQHandler(void){ if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET) {data_smp = USART_ReceiveData(USART1);flag_smp = 1;USART_ClearITPendingBit(USART1, USART_IT_RXNE); } return 0; }

(3)串口1发送

        我们为了测试方便,因此我们的串口发送就直接使用printf函数来进行,要查看你的printf函数定向输出到的是哪个串口,如果原来是输出到其他串口则需要调整fputc函数中的串口,如图所示,我们把串口全改为 USART1,那在使用printf函数返回接收到的数据时就会直接通过串口1来发送数据了。

        在 main.c 中,我们需要使用刚刚写的初始化函数来进行初始化,这里波特率设为115200,并写上返回数据的逻辑。

//别忘了引用刚刚定义的两个变量extern uint8_t data_smp;extern uint8_t flag_smp;int main(void){ //初始化串口1,用于发送数据给上位机uart1_init(115200);while(1){if(flag_smp !=0){flag_smp=0; //将标志位置为代表未接收的数值printf(\"%d\\r\\n\",data_smp); //将收到的data_smp 数据返回}}

(4)将代码烧录进stm32f407中 

3、树莓派4B端的代码编写:

        我们使用cutecom来进行串口数据的接收

(1)下载cutecom

        打开终端,输入

sudo apt updatesudo apt install cutecom

(2)配置cutecom

        首先我们要确认我们和树莓派进行连接的端口是哪个?

        使用

ls /dev/tty*

        串口设备通常显示为 /dev/ttyUSB0 或 /dev/ttyS0 等

        我们继续使用指令 打开cutecom

sudo cutecom

        点击右上角的setting进入配置界面

                1 配置好波特率(要和stm32代码中一致)

                2 选择我们刚刚指令找到的端口

                3 点击Open,即可在最下方查看到从stm32发送而来的数据

                4 在此处输入数据回车来发送给stm32,由于我们的代码写了stm32的收到数据后返回的功能,因此可以看到刚刚发送的数据

        最后我们就可以看到,A区是我们发送的信息,B区是我们接收到的stm32返回的数据。 

 

三、升级的思路

        由于我们这次代码只是为了验证stm32和树莓派串口通信的可行性,所以stm32发送数据用的只是prinf函数来进行,真正的收发数据就需要我们把想要发送的数据进行一定的“打包”,后续的“打包”教程我会继续更新,欢迎大家关注我接收最新的更新~