STM32与Linux串口双向通信

cnblogs 2024-08-27 11:45:00 阅读 80

STM32 与 linux 双向串口通信实验

本文记录STM32 与 linux 双向串口通信,包含stm32发送、Linux阻塞式接收;Linux发送,STM32阻塞式接收;本实验的目的在于调通数据链路,为之后使用奠定基础。

实验平台为:

STM32方面用的是STM32H723ZGT6为核心的开发板;开发环境为 VSCode + AC5编译器,调试器用的是STLINK-V2;

Linux方面:用的是luckfox的RV1106-G3为核心的开发板;开发环境为window环境下的Clion+交叉编译器,linux为Ubuntu22.04虚拟机,使用ADB将编译后的程序发送到linux开发板;

STM32 向 Linux 串口发送数据

STM32方面代码使用CubuMx生成,串口基本参数为:

1.波特率:115200;

2.数据宽度为8bits;

3.无停止位;

4.无奇偶校验位;

5.一个停止位;

初始化方面代码比较简单,故不放了,放一张CubeMx的配置截图:

发送代码在main的while循环中,代码逻辑为:每隔500ms发送一次数据,发送10次数据后发送"exit",使Linux端退出阻塞式接收,代码如下:

<code> uint8_t TransTemp[] = {"receiveTemp"};

while (1)

{

/* Transmit data code*/

for(int i=0; i<10; i++)

{

HAL_GPIO_TogglePin(GPIOG, GPIO_PIN_7);

HAL_UART_Transmit(&huart2, TransTemp, sizeof(TransTemp), 0xffff);

HAL_Delay(500);

}

HAL_UART_Transmit(&huart2, "exit", 4, 0xffff);

}

Linux方面:如果没有开启串口,需要在设备数中开启串口,开启过程可以见Luckfox的wiki:https://wiki.luckfox.com/zh/Luckfox-Pico/Luckfox-Pico-UART#5修改设备树

Linux方面串口配置和接收逻辑直接由代码配置,代码逻辑为:首先以打开UART3,对其进行基本配置,配置完成后进入阻塞式接收程序,串口一直接收数据并打印,若一段时间未接收到数据则打印Timeout,开始下一轮接收;直到接收到"exit"数据,退出接收,关闭串口。程序如下:

#include <stdio.h>

#include <string.h>

#include <fcntl.h>

#include <termios.h>

#include <unistd.h>

int main() {

int serial_port_num=3;

char serial_port[15];

sprintf(serial_port,"/dev/ttyS%d",serial_port_num);

int serial_fd;

serial_fd = open(serial_port, O_RDWR | O_NOCTTY);

if (serial_fd == -1) {

perror("Failed to open serial port");

return 1;

}

struct termios tty;

memset(&tty, 0, sizeof(tty));

if (tcgetattr(serial_fd, &tty) != 0) {

perror("Error from tcgetattr");

return 1;

}

cfsetospeed(&tty, B115200);

cfsetispeed(&tty, B115200);

tty.c_cflag &= ~PARENB; // NO parity bit

tty.c_cflag &= ~CSTOPB; // 1 stop bit

tty.c_cflag &= ~CSIZE; // clear transimit bit

tty.c_cflag |= CS8; // set data bits to 8 bits

tty.c_cflag |= CREAD | CLOCAL; // Turn on READ & ignore ctrl lines

// Set input mode (non-canonical, no echo,...)

tty.c_lflag &= ~ICANON;

tty.c_lflag &= ~ECHO;

// Set output mode (no post-processing)

tty.c_oflag &= ~OPOST; // no post-processiing means that out row data

// Set timeout to 1 second

tty.c_cc[VTIME] = 1; // inter-character timer unused

tty.c_cc[VMIN] = 1; // wait for up to 1 second for 1 byte

if (tcsetattr(serial_fd, TCSANOW, &tty) != 0) {

perror("Error from tcsetattr");

return 1;

}

/* Receive data in block mode! */

char rx_buffer[16] = {};

int bytes_read;

// 主循环

while (1) {

memset(rx_buffer, 0, sizeof(rx_buffer)); // 清空缓冲区

bytes_read = read(serial_fd, rx_buffer, sizeof(rx_buffer) - 1);

if (bytes_read > 0) {

rx_buffer[bytes_read] = '\0'; // 添加字符串结束符

printf("\rrx_buffer: %s\n", rx_buffer);

} else if (bytes_read == 0) {

printf("No data received.\n");

} else {

if (errno == EAGAIN || errno == EWOULDBLOCK) {

printf("Timeout occurred.\n");

} else {

perror("Error reading from serial port");

}

}

// 检查是否接收到 "exit" 以退出循环

if (strncmp(rx_buffer, "exit", 4) == 0) {

break;

}

}

close(serial_fd);

return 0;

}

实验现象见图,在Linux端可以一直接收到数据,直到STM32端exit数据发送。

可以看到最后一个数据为"exitreceiveTemp"这是为什么呢?

从STM32端的代码可以发现:

这两个发送间距很快,因此接收端认为其是一次发送;

Linux 向 STM32 串口发送数据

发送完成后,接收就大同小异,STM32方面代码较为简单,逻辑为:阻塞式接收,通过判断接收首位是否为0及字符'\0',判断是否接收到数据,若接收到数据则printf出来,代码如下:

<code> uint8_t ReceiveTemp[11] = {};

while (1)

{

/* Receive data code */

memset(ReceiveTemp, 0, sizeof(ReceiveTemp));

HAL_UART_Receive(&huart2, ReceiveTemp, 11, 0xffff);

if(ReceiveTemp[0] != 0)

{

printf("Receive data:%s\n", ReceiveTemp);

}

HAL_GPIO_TogglePin(GPIOG, GPIO_PIN_7);

}

Linux方面,只需将接收部分换成发送即可,代码逻辑为:定时发送。代码如下:

/* Transmit data in 1s intervals */

char tx_buffer[] = {"0123456789"};

while(1)

{

ssize_t bytes_written = write(serial_fd, tx_buffer, sizeof(tx_buffer));

if(bytes_written != sizeof(tx_buffer))

{

fprintf(stderr, "Filed to send all data. Sent %zd out of %zu bytes.\n",

bytes_written, sizeof(tx_buffer));

}else{

printf("Data send successfully.Data len is:%d\n", bytes_written);

}

sleep(1);

}

实验现象为:

Linux方面:每发送成功一次则打印一次;

STM32方面:每接收成功一次则将接收结果打印出来;

总结

本文实现了STM32 与 Linux平台的串口双向阻塞式通讯,根据实验效果验证效果可行。



声明

本文内容仅代表作者观点,或转载于其他网站,本站不以此文作为商业用途
如有涉及侵权,请联系本站进行删除
转载本站原创文章,请注明来源及作者。