- #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命令来进行编译
编译之前记得source一下编译环境
- source SDK/environment-setup-cortexa7t2hf-neon-vfpv4-ostl-linux-gnueabi
编译完成后会生成uart的可执行文件
将uart可执行文件上传到开发板后,进入到开发板终端执行uart程序:
- root@stm32mp1:~# ./uart /dev/ttySTM1
此时,串口助手上已经能看到开发板发出来的消息了:
然后,通过串口助手发送消息给开发板,开发板会将收到的消息打印在终端上:
串口终端发送字符串1234,开发板终端打印的消息如下:
以上,可以用看出得到的结果符合程序预期的运行结果,测试完成。