全志V3S嵌入式驱动开发(串口驱动)

news2024/12/23 19:53:12

【 声明:版权所有,欢迎转载,请勿用于商业用途。 联系信箱:feixiaoxing @163.com】

        全志V3S支持三个串口,但是因为其中UART1的pin和其他功能是复用的,所以这个时候一般只用UART0和UART2。当然我们在linux开发必须要进行调试,这就涉及到shell命令,因此就会占用一个串口UART0,所以如果有外接设备需要对接的话,一般用UART2。

1、电路图分析

         如上述电路图所示,分别有两组UART,一个是UART0,一个是UART2。连线的时候,通常10、12、14一组,2、4、7算成一组,这样就基本没有问题了。GND一定要连接上。

2、添加设备树配置

        设备树当中,默认UART0是配置好的,不然在启动启动的时候,也看不到那么多的日志信息。只是如果需要使用UART2的话,那么需要分别在sun8i-v3s.dtsi添加,

	        uart1_pins_a: uart1@0 {
                pins = "PE21", "PE22";
                function = "uart1";
                bias-pull-up; 
            };

            uart2_pins_a: uart2@0 {
                pins = "PB0", "PB1";
                function = "uart2";
                bias-pull-up; 
            };

        在sun8i-v3s-licheepi-zero.dts添加,

&uart1 {
    pinctrl-0 = <&uart1_pins_a>;
    pinctrl-names = "default";
    status = "okay";
};

&uart2 {
    pinctrl-0 = <&uart2_pins_a>;
    pinctrl-names = "default";
    status = "okay";
};

        有的同学也许会说,既然只使用到了UART2,那么UART1相关的配置不添加,行不行。我的实验结果告诉大家,不行。

        配置文件修改后,大家把配置重新编译一下,就可以生成新的dtb文件,拷贝到sd卡即可。代码部分本身zImage里面就有,这里就不需要重新编译了。

3、驱动文件

           细心一点的同学可能会在sun8i-v3s.dtsi看到这些内容,这就是将来UART驱动所要读取的信息,包括了兼容设备、寄存器、中断、时钟、复位、状态等数据。

			   uart0: serial@01c28000 {
                       compatible = "snps,dw-apb-uart";
                       reg = <0x01c28000 0x400>;
                       interrupts = <GIC_SPI 0 IRQ_TYPE_LEVEL_HIGH>;
                       reg-shift = <2>;
                       reg-io-width = <4>;
                       clocks = <&ccu CLK_BUS_UART0>;
                       resets = <&ccu RST_BUS_UART0>;
                       status = "disabled";
               };

               uart1: serial@01c28400 {
                       compatible = "snps,dw-apb-uart";
                       reg = <0x01c28400 0x400>;
                       interrupts = <GIC_SPI 1 IRQ_TYPE_LEVEL_HIGH>;
                       reg-shift = <2>;
                       reg-io-width = <4>;
                       clocks = <&ccu CLK_BUS_UART1>;
                       resets = <&ccu RST_BUS_UART1>;
                       status = "disabled";
               };

               uart2: serial@01c28800 {
                       compatible = "snps,dw-apb-uart";
                       reg = <0x01c28800 0x400>;
                       interrupts = <GIC_SPI 2 IRQ_TYPE_LEVEL_HIGH>;
                       reg-shift = <2>;
                       reg-io-width = <4>;
                       clocks = <&ccu CLK_BUS_UART2>;
                       resets = <&ccu RST_BUS_UART2>;
                       status = "disabled";
               };

        根据前面的经验,我们可以通过全局搜索dw-apb-uart找到对应的驱动文件。当然,也可以到内核drivers/tty目录下,借助于find . -name "*.o"的方法,看看哪一个驱动最像我们要找的那个文件。简单查看下,发现有一个drivers/tty/serial/8250/8250_dw.c最像,因为它也包含了一个dw字母。

static const struct of_device_id dw8250_of_match[] = {
	{ .compatible = "snps,dw-apb-uart" },
	{ .compatible = "cavium,octeon-3860-uart" },
	{ /* Sentinel */ }
};
MODULE_DEVICE_TABLE(of, dw8250_of_match);

static const struct acpi_device_id dw8250_acpi_match[] = {
	{ "INT33C4", 0 },
	{ "INT33C5", 0 },
	{ "INT3434", 0 },
	{ "INT3435", 0 },
	{ "80860F0A", 0 },
	{ "8086228A", 0 },
	{ "APMC0D08", 0},
	{ "AMD0020", 0 },
	{ "AMDI0020", 0 },
	{ "HISI0031", 0 },
	{ },
};
MODULE_DEVICE_TABLE(acpi, dw8250_acpi_match);

static struct platform_driver dw8250_platform_driver = {
	.driver = {
		.name		= "dw-apb-uart",
		.pm		= &dw8250_pm_ops,
		.of_match_table	= dw8250_of_match,
		.acpi_match_table = ACPI_PTR(dw8250_acpi_match),
	},
	.probe			= dw8250_probe,
	.remove			= dw8250_remove,
};

module_platform_driver(dw8250_platform_driver);

MODULE_AUTHOR("Jamie Iles");
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("Synopsys DesignWare 8250 serial port driver");
MODULE_ALIAS("platform:dw-apb-uart");

        看了一下驱动末尾的几段代码,应该就是这个文件。有兴趣的同学可以通过调试和打印,加深一下印象。

4、准备测试代码、开始测试

        有了编译好的dtb文件,重新烧录后,下面就可以开始测试了。我们的测试方法就是,准备一个ttyS2的读写程序,此外再准备两个usb2ttl,一个用作shell输入,一个用作效果验证。网上关于linux串口编程的代码很多,可以找一个适合我们的查看下即可,

#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <termios.h>
#include <errno.h>
 
int set_opt(int,int,int,char,int);
void main()
{
	int fd,nByte,flag=1;
	char *uart2 = "/dev/ttyS2";
	char buffer[512];
	char *uart_out = "Please input,waiting....\r\n";
    char *uart_demo = "Linux uart demo\r\n";
	char *line = "\r\n";
	memset(buffer, 0, sizeof(buffer));

    if((fd = open(uart2, O_RDWR|O_NONBLOCK))<0)//非阻塞读方式
		printf("open %s is failed",uart2);
	else{
		set_opt(fd, 115200, 8, 'N', 1);
		write(fd,uart_demo, strlen(uart_demo));
        write(fd,uart_out, strlen(uart_out));

		while(1){
			while((nByte = read(fd, buffer, 512))>0){
				buffer[nByte+1] = '\0';
				write(fd, line, strlen(line));
				write(fd,buffer,strlen(buffer));
				memset(buffer, 0, strlen(buffer));
				nByte = 0;
			}
		}
	}
}
 
int set_opt(int fd,int nSpeed, int nBits, char nEvent, int nStop)
{
	struct termios newtio,oldtio;
	if  ( tcgetattr( fd,&oldtio)  !=  0) { 
		perror("SetupSerial 1");
		return -1;
	}
	bzero( &newtio, sizeof( newtio ) );
	newtio.c_cflag  |=  CLOCAL | CREAD;
	newtio.c_cflag &= ~CSIZE;
 
	switch( nBits )
	{
		case 7:
			newtio.c_cflag |= CS7;
			break;
		case 8:
			newtio.c_cflag |= CS8;
			break;
	}
 
	switch( nEvent )
	{
	case 'O':
		newtio.c_cflag |= PARENB;
		newtio.c_cflag |= PARODD;
		newtio.c_iflag |= (INPCK | ISTRIP);
		break;
	case 'E': 
		newtio.c_iflag |= (INPCK | ISTRIP);
		newtio.c_cflag |= PARENB;
		newtio.c_cflag &= ~PARODD;
		break;
	case 'N':  
		newtio.c_cflag &= ~PARENB;
		break;
	}
 
	switch( nSpeed )
	{
		case 2400:
			cfsetispeed(&newtio, B2400);
			cfsetospeed(&newtio, B2400);
			break;
		case 4800:
			cfsetispeed(&newtio, B4800);
			cfsetospeed(&newtio, B4800);
			break;
		case 9600:
			cfsetispeed(&newtio, B9600);
			cfsetospeed(&newtio, B9600);
			break;
		case 115200:
			cfsetispeed(&newtio, B115200);
			cfsetospeed(&newtio, B115200);
			break;
		case 460800:
			cfsetispeed(&newtio, B460800);
			cfsetospeed(&newtio, B460800);
			break;
		default:
			cfsetispeed(&newtio, B9600);
			cfsetospeed(&newtio, B9600);
			break;
	}
	if( nStop == 1 )
		newtio.c_cflag &=  ~CSTOPB;
	else if ( nStop == 2 )
		newtio.c_cflag |=  CSTOPB;
		newtio.c_cc[VTIME]  = 100;///* 设置超时10 seconds*/
		newtio.c_cc[VMIN] = 0;
		tcflush(fd,TCIFLUSH);
	if((tcsetattr(fd,TCSANOW,&newtio))!=0)
	{
		perror("com set error");
		return -1;
	}
	
	return 0;
}

        这个代码的内容比较简单,主要的部分就是回显。用xshell打开两个串口,接着用arm-linux-gnueabihf-gcc编译好程序之后,通过python http & wget下载到开发板,重新chmod +x之后就可以开始运行了。不出意外的话,就能在/dev/ttyS2的串口下面实现数据的回显功能了。

        市面上关于串口的设备还是很多的,比如电池、gps、运动控制、二维码结果输出等等,很多设备都是这种232接口的设备,所以小伙伴多多掌握linux下面232如何编程还是大有裨益的。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/604215.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Hive---5、分区表和分桶表

1、分区表和分桶表 1.1 分区表 Hive中的分区就是把一张大表的数据按照业务需求分散的存储到多个目录&#xff0c;每个目录就称为该表的一个分区。在查询时通过where子句中的表达式选择查询所需要的分区&#xff0c;这样的查询效率会提高很多。 1.1.1 分区表基本语法 1、创建…

scratch舞蹈演出 中国电子学会图形化编程 少儿编程 scratch编程等级考试一级真题和答案解析2023年5月

目录 scratch舞蹈演出 一、题目要求 1、准备工作 2、功能实现 二、案例分析

Spring MVC的高级功能(异常处理器,拦截器,文件操作)

目录&#xff1a; 异常处理拦截器文件上传和下载 1.异常处理&#xff08;简单异常处理&#xff0c;自定义异常处理&#xff0c;异常处理注解&#xff09; 简单异常处理器 HandlerExceptionResolver接口 如果希望对Spring MVC中所有异常进行统一处理&#xff0c;可以使用S…

【Spring】——Spring的创建与使用

目录 一、传统程序开发与控制反转&#x1f36d; 1、传统程序开发&#x1f349; 传统程序开发的缺陷&#x1f353; 解决传统开发中的缺陷&#x1f353; 2、控制反转思维程序开发&#x1f349; 3 对比总结规律&#x1f349; 二、Spring创建与使用&#x1f36d; 1、创建Sp…

js解构记录

1.字符串结构 1.1 字符串转数组 1.2 字符串转成变量 1.3 结构字符串的属性 2. 数组结构 2.1 交换变量 2.2 允许指定默认值 只有赋值为undefined时默认值才生效&#xff0c;及时赋值null都不好使&#xff0c;会赋值为null 对是否是默认值在后面没有要求 3、对象结构 3.1 结…

spring cloud搭建(feign)

天行健&#xff0c;君子以自强不息&#xff1b;地势坤&#xff0c;君子以厚德载物。 每个人都有惰性&#xff0c;但不断学习是好好生活的根本&#xff0c;共勉&#xff01; 文章均为学习整理笔记&#xff0c;分享记录为主&#xff0c;如有错误请指正&#xff0c;共同学习进步。…

I.MX RT1170加密启动详解(2):HAB认证原理

文章目录 1 基础2 使能过程3 Boot flow 1 基础 HAB认证是基于RSA或ECDSA算法的公钥密码学&#xff0c;它用一系列的私钥对image进行加密&#xff0c;然后BootROM在上电后用对应的公钥验证加密的镜像是否被修改。这个密钥结构就是PKI(Public Key Infrastructure)树 (1)normal …

DTU助力气象行业数字化转型,让数据更智能

近年来&#xff0c;随着社会的不断发展&#xff0c;气象行业在现代社会中扮演着极为重要的角色。天气对于人们的日常生活、农业、交通运输等方方面面都有着深远的影响。然而&#xff0c;在数据采集与监测过程中&#xff0c;气象行业也面临着一些问题。不准确的数据、不稳定的传…

基于simulink仿真无人机比赛场景

一、前言 展示了如何使用虚拟碰撞传感器以交互方式控制仿真&#xff0c;以及如何使用 Simulink3D 动画更改虚拟世界对象的外观。该示例表示一个简单的无人机 &#xff08;UAV&#xff09; 挑战。无人机比赛场景基于2013年在法国图卢兹举行的IMAV飞行比赛。 穿越窗口 降落直升机…

java基于springboot+vue的在线教育课程作业网站n5138

本基于springboot的在线教育网站的设计与实现有管理员&#xff0c;教师和学生三个角色。管理员功能有个人中心&#xff0c;教师管理&#xff0c;科目管理&#xff0c;学生管理&#xff0c;课程信息管理&#xff0c;课程作业管理&#xff0c;学生作业管理&#xff0c;学生成绩管…

Ubuntu下让matplotlib显示中文字体

文章目录 安装中文字体显示matplotlib库的字体文件夹删除matplotlib 的缓存文件&#xff08;可选&#xff09; matplotlib中设置字体&#xff0c;显示&#xff01; 参考文章&#xff1a; https://zodiac911.github.io/blog/matplotlib-chinese.html Ubuntu下python的matplotli…

七篇深入理解机器学习和深度学习的读物推荐

在这篇文章中将介绍7篇机器学习和深度学习的论文或者图书出版物&#xff0c;这些内容都论文极大地影响了我对该领域的理解&#xff0c;如果你想深入了解机器学习的内容&#xff0c;哪么推荐阅读。 Attention Is All You Need 在自然语言处理和序列建模领域&#xff0c;Vaswani…

华为OD机试真题 Java 实现【水仙花数】【2022Q4 100分】

一、题目描述 所谓水仙花数&#xff0c;是指一个n位的正整数&#xff0c;其各位数字的n次方和等于该数本身。 例如153是水仙花数&#xff0c;153是一个3位数&#xff0c;并且153 1^3 5^3 3^3。 二、输入描述 第一行输入一个整数n&#xff0c;表示一个n位的正整数。n在3到…

chatgpt赋能python:Python教程:如何创建一个Rectangle类

Python教程&#xff1a;如何创建一个Rectangle类 Python是一种简单易学的编程语言&#xff0c;适用于各种应用场景。在本教程中&#xff0c;我们将探讨如何使用Python创建一个Rectangle类。Rectangle类是一个简单的图形类&#xff0c;用于描述长方形的特征&#xff0c;如宽度和…

双域多尺度融合深度神经网络的PPG生物特征识别研究

目录 前言概述研究背景PPG存在的问题本文的创新点数据处理数据预处理数据分割特征提取 模型结构LSTM网络多尺度特征提取模块双域注意模块识别与验证 实验部分数据集识别指标 前言 本文是根据一篇论文总结写的。 论文英文名为&#xff1a;Dual-domain and Multiscale Fusion D…

Redis底层学习(三)—存储类型-List篇

文章目录 特点具体服务器操作命令具体操作应用场景 特点 适⽤场景&#xff1a;消息队列。 它的特点就是内部元素有序、重复&#xff0c;并且插⼊和删除很快 O(1) &#xff0c;但是查找却很慢 O(n) 。功能⽀持队列和栈操作。 具体服务器操作命令 左侧插⼊元素&#xff1a; LP…

基于同步矩阵的多通道脑电功能连接分析_kaic

摘 要 本文研究了基于同步矩阵的多通道脑电功能连接分析方法&#xff0c;旨在揭示脑区之间的功能联系。首先&#xff0c;介绍了脑电信号的产生和特点&#xff0c;以及功能连接分析的概念和方法。其次&#xff0c;详细讨论了多通道脑电数据的采集和预处理流程&#xff0c;包括…

JAVA并发学习

1 基础准备 1.1 并发与并行 并发是不同的代码块交替执行&#xff0c;也就是交替可以做不同的事情。 并行是不同的代码块同时执行&#xff0c;也就是同时可以做不同的事情。 根据CPU 核数&#xff0c;线程运行是不同的 单核CPU&#xff08;微观串行&#xff0c;宏观并行&…

YOLOV5 + PYQT5双目测距(一)

YOLOV5 PYQT5双目测距 1. 测距源码2. 测距原理3. PYQT环境配置4. 实验结果4.1 界面1&#xff08;简洁版&#xff09;4.2 界面2&#xff08;改进版&#xff09; 1. 测距源码 详见文章 YOLOV5 双目测距&#xff08;python&#xff09; 2. 测距原理 如果想了解双目测距原理&a…

Stable Diffusion 指定模型人物,Lora 训练全流程

简介 在使用 Stable Diffusion 的时候&#xff0c;可以选择别人训练好的 Lora&#xff0c;那么如何训练自己的 Lora&#xff0c;本篇文章介绍了介绍了如何训练Lora&#xff0c;如何从训练的模型中选择好的模型&#xff0c;如何在 Stable Diffusion 中使用。 闲话不多说&#…