|
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端退出阻塞式接收,代码如下:- 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端可以一直接收到数据,直到STM32端exit数据发送。
可以看到最后一个数据为"exitreceiveTemp"这是为什么呢?
从STM32端的代码可以发现:
这两个发送间距很快,因此接收端认为其是一次发送;
Linux 向 STM32 串口发送数据
发送完成后,接收就大同小异,STM32方面代码较为简单,逻辑为:阻塞式接收,通过判断接收首位是否为0及字符'\0',判断是否接收到数据,若接收到数据则printf出来,代码如下:- #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方面,只需将接收部分换成发送即可,代码逻辑为:定时发送。代码如下:- 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方面:每发送成功一次则打印一次;
STM32方面:每接收成功一次则将接收结果打印出来;
总结
本文实现了STM32 与 Linux平台的串口双向阻塞式通讯,根据实验效果验证效果可行。
来源:https://www.cnblogs.com/muheandrabbit/p/18381596/STM32UartLinux
免责声明:由于采集信息均来自互联网,如果侵犯了您的权益,请联系我们【E-Mail:cb@itdo.tech】 我们会及时删除侵权内容,谢谢合作! |
本帖子中包含更多资源
您需要 登录 才可以下载或查看,没有账号?立即注册
x
|