当前位置: 首页 > news >正文

Linux驱动开发之串口驱动移植

原理图

         从上图可以看到RS232的串口接的是UART3,接下来我们需要使能UART3的收发功能。一般串口的驱动程序在内核中都有包含,我们配置使能适配即可。

设备树

复用功能配置

        查看6ull如何进行uart3的串口复用配置:

        设备树下添加uart3的串口复用配置:

pinctrl_uart3: uart3grp {
            fsl,pins = <
                MX6UL_PAD_UART3_RX_DATA__UART3_DTE_TX 0x1b0b1
                MX6UL_PAD_UART3_RX_DATA__UART3_DCE_RX 0x1b0b1
            >;
        };

添加设备树节点 

        设备树下添加uart3的设备树节点:

&uart3 {
    pinctrl-names = "default";
    pinctrl-0 = <&pinctrl_uart3>;
    status = "okay";
};

        重新编译设备树make dtbs,并拷贝到开发板对应位置替换之前的设备树文件。

查看串口功能配置

        重启开发板后,查看配置是否生效:

        由上图看出UART3功能配置已经生效。

串口应用编程

应用层代码参考

#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <termios.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <pthread.h>
#include <sys/ioctl.h>
#include <errno.h>



#define ttyname "/dev/ttymxc2"
int fd;
static char wbuff[128];
static char rbuff[128];

void *read_handler(void * arg){
	int ret;
	while(1){
		memset(rbuff, 0, sizeof(rbuff));
		ret = read(fd, rbuff, sizeof(rbuff));
		if(ret == -1 ){
			perror("read");
			close(fd);
			pthread_exit(NULL);
		}else if(ret > 0){
			printf("RCV: %s\n", rbuff);
			fflush(stdout);
		}

	}

	pthread_exit(NULL);
}

int main(int argc, char **argv){
	int ret;
	pthread_t thread;
	struct termios tty;
	fd = open(ttyname, O_RDWR | O_NOCTTY | O_NDELAY);
	if (fd == -1){// 打开端口失败
		perror("open_port: Unable to open /dev/tty ");
	}

	if(fcntl(fd, F_SETFL, 0)<0) /* 设置串口为阻塞状态*/
	{
		printf("fcntl failed!\n");
		close(fd);
		return -1;
	}
	// 获取当前串口配置
	memset(&tty, 0, sizeof(tty));

	if (tcgetattr(fd, &tty) != 0) {
		perror("Error from tcgetattr: ");
	}

	// 配置波特率
	cfsetispeed(&tty, B115200);
	cfsetospeed(&tty, B115200);

	// 配置数据位、停止位和校验
	tty.c_cflag &= ~CSIZE;
	tty.c_cflag |= CS8;     // 8数据位
	tty.c_cflag &= ~CSTOPB; // 1停止位
	tty.c_cflag &= ~PARENB; // 无校验位

	/*设置等待时间和最小接收字符*/
	tty.c_cc[VTIME]  = 1;
	tty.c_cc[VMIN] = 1;

	tty.c_cflag |= CREAD | CLOCAL; // 开启接收,忽略modem控制线
	// tty.c_iflag = IGNPAR | ICRNL; // 忽略校验错误,输入时将回车转换为换行
	tty.c_oflag = ~(ONLCR | ICRNL); //

	tty.c_iflag &= ~(INLCR | ICRNL |IGNCR); //

	tty.c_oflag &= ~OPOST;

	/*处理未接收字符*/
	tcflush(fd,TCIFLUSH);

	// 设置串口配置
	tcsetattr(fd, TCSANOW, &tty);

	pthread_create(&thread, NULL, read_handler, NULL);

	while(1){
		memset(wbuff, 0 , sizeof(wbuff));
		printf("请输入发送数据:\n");
		scanf("%s", wbuff);
		//printf("wbuff:%s\n", wbuff);
		strncpy(wbuff + strlen(wbuff) - 2, "\r\n", 2);
		ret = write(fd, wbuff, strlen(wbuff)+2);
		if(ret == -1){
			perror("write");
			close(fd);
			return EXIT_FAILURE;
		}
		printf("Write success %d\n",ret);
	}

	pthread_join(thread, NULL);
	close(fd);
	return 0;
}

编译没报错:

        最后拷贝到开发板进行验证

开发板验证

        开发板接好线,PC上开启串口助手进行功能验证:

 

相关文章:

  • Android Studio 新版本Gradle发布本地Maven仓库示例
  • The Rust Programming Language 学习 (二)
  • jupyter汉化、修改默认路径详细讲解
  • STM32标准库之编码器接口示例代码
  • Flutter管理项目实战
  • 蓝桥试题:斐波那契数列
  • 【Leetcode 每日一题】1278. 分割回文串 III
  • SpringBoot系列之Spring AI+DeekSeek创建AI应用
  • 【每日八股】计算机网络篇(二):TCP 和 UDP
  • 虚拟机配置
  • ThreadLocal的Key是弱引用给垃圾回收带来的问题
  • 深入探究Python机器学习算法:无监督学习(聚类算法如 K-Means、DBSCAN,降维算法如 PCA、SVD)
  • 每日一题之宝石组合
  • Docker + Vue2 热重载:为什么需要 CHOKIDAR_USEPOLLING=true?
  • 健康饮食,健康早餐
  • 低功耗抄表方案-支持Modbus、DL/T645 及 DL/T698 协议‌电表
  • 简易的微信聊天网页版【项目测试报告】
  • Spring Boot 自动装配深度解析与实践指南
  • Libgdx游戏开发系列教程(2)——接水滴游戏实现
  • 知识周汇|SAP脚本自动化-淋过雨的人更懂得伞的价值
  • 港交所与香港证监会就“中概股回流意向”已与部分相关企业进行接触
  • 今年我国电影票房破250亿领跑全球,“电影+”带动文旅消费热潮
  • 美加征“对等关税”后,调研显示近半外贸企业将减少对美业务
  • 最新研究挑战男性主导说:雌性倭黑猩猩联盟对付雄性攻击,获得主导地位
  • 魔都眼·上海车展⑤|被主播包围的新车
  • 神舟二十号3名航天员顺利进驻中国空间站