[STM32MP1]

【STM32MP135F-DK测评】编写串口应用程序

[复制链接]
185|0
手机看帖
扫描二维码
随时随地手机跟帖
xinmeng_wit|  楼主 | 2024-2-25 21:09 | 显示全部楼层 |阅读模式
本帖最后由 xinmeng_wit 于 2024-2-25 21:14 编辑

上一篇(https://bbs.21ic.com/icview-3360172-1-1.html)中已经完成了UART的设备树的配置和编译,以及使用shell脚本进行简单的UART的数据的收发测试,这一篇将编写应用程序来发送UART数据,同时打印接收到的UART数据。
本篇将使用termios 结构体以及相关的api来实现对串口的设置、数据的写入和读取。

1、编写应用代码
先是调用serial_open函数对UART硬件进行初始化,其中设备名(串口号)需要作为参数传入,其它参数已经被程序指定死了,不可传入。默认波特率9600,8N1。
初始化完成后,进入while(1)循环中,循环发送字符串Hello STM32MP135F-DK,同时查看串口是否有消息接收到,若有则通过控制台打印出来。
uart.c源代码如下:

#include <stdio.h> /* Standard input/output */

#include <fcntl.h> /* File control definitions */

#include <string.h>

#include <stdlib.h>

#include <termio.h> /* POSIX terminal control definitions */

#include <sys/time.h> /* Time structures for select() */

#include <unistd.h> /* POSIX Symbolic Constants */

#include <assert.h>

#include <errno.h> /* Error definitions */

#include <sys/mman.h>

#define CMSPAR 010000000000

#define SERIAL_FLUSH_TX1

#define SERIAL_FLUSH_RX2

#define SERIAL_PARITY_NO 0

#define SERIAL_PARITY_ODD 1

#define SERIAL_PARITY_EVENT 2

#define SERIAL_PARITY_MARK 3

#define SERIAL_PARITY_SPACE 4

#define SERIAL_STOPBIT_ONE 1

#define SERIAL_STOPBIT_TWO 2

static int serial_fd = -1;

struct termios old_tios;

static void serial_print_buf(unsigned char *buf,int len) /* 打印输出 */

{

int i;

for(i=0;i<len;i++)

printf("%02X ",buf[i]);

printf("\n");

}

char *get_serial_dev_name(char *serial_name) /* 获取串口名称 */

{

if (strcasecmp(serial_name, "/dev/ttySTM1") == 0)

return serial_name;

else

return "NULL";

}

static int termios_init(struct termios *tios,int baud,int parity,int data_bits,int stop_bits) //串口 传入波特率,校验位,数据位,停止位。

{

speed_t baud_rate;

if (tios == NULL)

return -1;

tios->c_line = 0;

tios->c_cc[VMIN ] = 0;

tios->c_cc[VTIME] = 0;

/* configure the input modes... */

tios->c_iflag = IGNBRK | IGNPAR | INPCK;

/* configure the output modes... */

tios->c_oflag = 0; /* enable implementation-defined output processing */

/* configure the control modes... */

tios->c_cflag = CREAD | CLOCAL;

if (data_bits == 5) //对传入的数据位进行判断

tios->c_cflag |= CS5;

else if (data_bits == 6)

tios->c_cflag |= CS6;

else if (data_bits == 7)

tios->c_cflag |= CS7;

else if (data_bits == 8)

tios->c_cflag |= CS8;

else

return -1;

if (stop_bits == 1)//对传入的停止位进行判断

tios->c_cflag &=~ CSTOPB;

else if (stop_bits == 2)

tios->c_cflag |= CSTOPB;

else

return -1;

if(parity == 0)//校验位: 0:无校验 1:奇校验 2:偶校验 3:mark parity 4:space parity

{ /* none */

tios->c_cflag &=~ PARENB;

tios->c_cflag &=~ PARODD;

}

else if(parity == 2)

{ /* even */

tios->c_cflag |= PARENB;

tios->c_cflag &=~ PARODD;

}

else if(parity == 1)

{ /* odd */

tios->c_cflag |= PARENB;

tios->c_cflag |= PARODD;

}

else if (parity == 3)/* 2008.12.17 add for support mark and space parity */

{

/* mark */

tios->c_cflag |= PARENB;

tios->c_cflag |= CMSPAR;

tios->c_cflag |= PARODD;

}

else if (parity == 4)

{

/* space */

tios->c_cflag |= PARENB;

tios->c_cflag |= CMSPAR;

}

else

return -1;

/* configure the local modes... */

tios->c_lflag = 0; /* enable implementation-defined input processing */

/* Set the baud rate */

switch(baud)//对传入的波特率进行判断

{

case 110:

baud_rate = B110;

break;

case 300:

baud_rate = B300;

break;

case 600:

baud_rate = B600;

break;

case 1200:

baud_rate = B1200;

break;

case 2400:

baud_rate = B2400;

break;

case 4800:

baud_rate = B4800;

break;

case 9600:

baud_rate = B9600;

break;

case 19200:

baud_rate = B19200;

break;

case 38400:

baud_rate = B38400;

break;

case 57600:

baud_rate = B57600;

break;

case 115200:

baud_rate = B115200;

break;

case 230400:

baud_rate = B230400;

break;

case 460800:

baud_rate = B460800;

break;

case 576000:

baud_rate = B576000;

break;

case 921600:

baud_rate = B921600;

break;

default:

return -1;

}

if ((cfsetispeed(tios, baud_rate) < 0) ||(cfsetospeed(tios, baud_rate) < 0))

return -1;

return 0;

}

//return serial fd, error return -1

int serial_open(char *serial_name, int baud,int parity,int data_bits,int stop_bits,int timeout) //打开串口

{

struct termios settings;

int fd;

char *serial_dev_name;

if (serial_fd >= 0)

return 0;

if (termios_init(&settings, baud,parity,data_bits,stop_bits) < 0)

return 0;

serial_dev_name = get_serial_dev_name(serial_name);

if (serial_dev_name == NULL)

{

fprintf(stderr, "invalid serial name:%s\n", serial_name);

return 0;

}

if((fd = open(serial_dev_name, O_RDWR | O_NOCTTY | O_NDELAY))< 0)

return 0;

if(tcgetattr(fd, &old_tios) < 0)

{

close(fd);

return 0;

}

if(tcsetattr(fd, TCSANOW, &settings) < 0)

{

close(fd);

return 0;

}

serial_fd = fd;

return 1;

}

int serial_close() //关闭串口

{

if (serial_fd < 0)

return 0;

tcsetattr(serial_fd, TCSANOW, &(old_tios));

close(serial_fd);

serial_fd = -1;

return 1;

}

int serial_flush(int flag)

{

if (serial_fd < 0)

return 0;

if (flag == SERIAL_FLUSH_TX)

tcflush(serial_fd,TCOFLUSH);

else if (flag == SERIAL_FLUSH_RX)

tcflush(serial_fd,TCIFLUSH);

else if (flag == (SERIAL_FLUSH_RX|SERIAL_FLUSH_TX) )

tcflush(serial_fd,TCIOFLUSH);

return 1;

}

int serial_write(char *buf,size_t size) //串口写入数据

{

int writesize = 0;

writesize = write(serial_fd,buf,size);

//printf("serial write: length=%d, packet: ",writesize);

//serial_print_buf(buf,writesize);

return writesize;

}

int serial_read(char *buf,size_t size) //串口读取数据

{

int readsize = 0;

if (size<=0)

return 0;

readsize = read(serial_fd,buf,size);

printf("serial read: length=%d, packet: ",readsize);

serial_print_buf(buf, readsize);

return readsize;

}

//return 1: poll ok, 0: timeout, -1: error

int serial_poll(int timeout)

{

int fd = serial_fd;

fd_set rfds;

struct timeval tv;

int sel_res;

FD_ZERO(&rfds);

FD_SET(fd, &rfds);

tv.tv_sec = timeout/1000;

tv.tv_usec = (timeout % 1000)*1000;

return select(fd + 1, &rfds, NULL,NULL,&tv);

}

int main(int argc, char *argv[])

{

int fd;

char send_buffer[100] = "Hello STM32MP135F-DK\r\n";

char recv_buffer[100];

int i, ret;

if (argc != 2) //需要传入串口对应的设备名

{

fprintf(stderr, "usage:serialtest com_port\n");

return -1;

}

ret = serial_open(argv[1], 9600, SERIAL_PARITY_NO, 8, SERIAL_STOPBIT_ONE, 1000); //调用上面封装好的打开串口函数 传入设备名,波特率,校验位,数据位,停止位以及超时时间

if (ret == 0)//打开失败

{

fprintf(stderr, "open serial failed\n");

return -1;

}

/*

for(i=0; i<20; i++)

{

send_buffer[i] = i;

}

*/

while(1)

{

serial_write(send_buffer, strlen(send_buffer)); //写入数据

//read

while (serial_poll(1000)>0)//当另一端传入数据时会接收到数据

{

serial_read(recv_buffer, sizeof(recv_buffer));

}

}

serial_close();

return 0;

}

Makeifle文件:

uart:uart.c

$(CC) -Iinclude -o uart uart.c

clean:

rm *.o uart


2、编译应用程序
使用make命令来进行编译
75e6504061d5125359ddecbf199677ee
编译之前记得source一下编译环境
source SDK/environment-setup-cortexa7t2hf-neon-vfpv4-ostl-linux-gnueabi

编译完成后会生成uart的可执行文件
9189dcfa095ccb34696b22c148d39232
将uart可执行文件上传到开发板后,进入到开发板终端执行uart程序:
root@stm32mp1:~# ./uart /dev/ttySTM1

c959cce51bc3a7596aef4de355427b0b
此时,串口助手上已经能看到开发板发出来的消息了:
0ba46b0a40c470bb03ac24011981910a
然后,通过串口助手发送消息给开发板,开发板会将收到的消息打印在终端上:
串口终端发送字符串1234,开发板终端打印的消息如下:
9dc78c78311bb766bd54f120690f3d3e
以上,可以用看出得到的结果符合程序预期的运行结果,测试完成。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

61

主题

214

帖子

1

粉丝