Linux驱动应用编程(三)UART串口

news2024/11/27 1:41:37

本文目录

  • 前述
  • 一、手册查看
  • 二、命令行调试串口
    • 1. 查看设备节点
    • 2. 使用stty命令设置串口
    • 3. 查看串口配置信息
    • 4. 调试串口
  • 三、代码编写
    • 1. 常用API
    • 2. 例程
      • 线程优化

  

前述

   在开始实验前,请一定要检查测试好所需硬件是否使用正常,不然调试过程中出现的问题,会让你很烦恼。因为我在测试的时候发现一直接收不到消息,后面才知道ttl转usb的tx引脚坏了。所以确保硬件良好是我们后续测试的基本保障。

一、手册查看

   我们前面讲到在Linux中一切皆是文件!无论是上一章节的GPIO,还是串口这边都同样如此。首先,我们就先来使用命令行基本调试一下我们的串口,来确保串口的可用性。无论是什么开发板,我们都需要先查看手册来确定开发板的串口io。这里以香橙派AIPro为例,手册中提醒我们串口0已经被系统使用,不能当作普通串口给用户使用。 所以用户可用串口只有两个。分别是UART7和UART2。

在这里插入图片描述

查看设备节点,如下所示。
在这里插入图片描述

二、命令行调试串口

1. 查看设备节点

设备节点都在 /dev目录下。
在这里插入图片描述

2. 使用stty命令设置串口

常用配置:stty -F /dev/ttyAMA2 115200 cs8 -parenb -cstopb iutf8

在这里插入图片描述

3. 查看串口配置信息

命令:stty -F /dev/ttyAMA2 -a
在这里插入图片描述

4. 调试串口

我们使用TTL转USB接口连接香橙派与电脑,使用串口调试助手测试。注意:在串口助手中要设置为UTF8显示。
坑:在使用TTL连接时,一定要接地线!以保证电气基准电位!不要只接TX和RX!!

(1)香橙派发送数据
在这里插入图片描述

(2)香橙派接收数据
在这里插入图片描述

三、代码编写

   终端设备属性结构体,我们在操作一些设备文件时,常常会用到下面这个结构体。在Unix系统中常用于控制终端的输入输出参数,比如波特率、字符大小、控制字符等。通过操作这个结构体,可以对终端的各种属性进行设置和获取。
头文件:#include<termios.h>

struct termios {
	unsigned short c_iflag;//控制终端的输入方式,如是否启用回车、换行等
	unsigned short c_oflag; //控制终端的输出方式,如是否启用回车、换行等。
	unsigned short c_cflag; //控制终端的控制模式,如波特率、数据位数等。
	unsigned short c_lflag;//控制终端的本地模式,如是否启用回显、是否启用信号等。
	unsigned char c_line;//行(线)规程,指定终端的行规程,比如终端是终端设备还是伪终端设备。
	unsigned char c_cc[NCC]; //控制字符数组,用于定义特殊控制字符的行为,比如终端中的删除、结束、停止等功能键的行为。
};

   这些成员里都有很多配置参数的宏定义,我们只需要将成员与要配置参数的宏定义进行|=(置1)或&=~(置0)操作即可配置相应功能。我这里只先列举出来几个常用的功能。这里我将不再展示参数的宏定义,因为太多了,很多也用不到,有需要的自己去查看其他博客来学习。

●配置举例如下:

struct termios termios_p; //初始化结构体
termios_p.c_cflag |=CS8; //设置八位数据位。
termios_p.c_cflag &=~CSTOPB; //设置一位停止位。
termios_p.c_cflag &=~PARENB; //无奇偶校验位。
termios_p.c_lflag &=~ECHO ; //不回显

1. 常用API

(1)设置波特率。
   波特率,常用 B2400,B4800,B9600,B115200,B460800。

int cfsetispeed(struct termios *termios_p,speed_t speed)  //设置接收波特率
int cfsetospeed(struct termios *termios_p,speed_t speed)  //设置发送波特率
//

(2)清空缓冲区数据。
   主要用于清除输入和输出缓冲区中的数据。这个命令在处理串口通信时非常有用,特别是在初始化或重置通信通道时,以确保没有残留的数据干扰通信。

int tcflush(int fd,int queue_selector)
//int fd :文件描述符
//int queue_selector: 
/*	        TCIFLUSH:清空正读的数据,且不会读出
			TCOFLUSH:清空正写入的数据,且不会发送到终端
			TCIOFLUSH:清空所有正在发生的 I/O 数据.
	*/

(3)获取终端设备参数。
   函数的作用是获取指定文件描述符(fd)所关联的终端设备的当前属性,并将这些属性存储到指定的 termios 结构体(termios_p)中。

int tcgetattr(int fd,struct termios *termios_p)
//int fd :文件描述符。
//struct termios *termios_p: 设备终端结构体。

(4)设置终端设备参数,激活配置。

int tcsetattr(int fd,int optional_actions,cons struct termios *termios_p)
//int fd :文件描述符。
//int optional_actions :
/*			TCSANOW:不等数据传输完毕,立即改变属性
			TCSADRAIN:等所有数据传输完毕,再改变属性
			TCSAFLUSH:清空输入输出缓冲区才改变属性
*/		
//cons struct termios *termios_p :终端设备属性的结构体。

2. 例程

uart.c

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <termios.h>
#include <unistd.h>
#include <string.h>
#include "uart.h"
#include <termios.h>

void UART_Close(int fd)
{
   close(fd);
}

int UART_Send(int fd, char *data)
{
    int num;
    num=write(fd, data, strlen(data));
    return num;
}


int UART_Receive(int fd, char *receive)
{
    int num;
    num=read(fd, receive, sizeof(receive)-1);
    return num;
}

int UART_Init(char *device, int baud)
{
	int fd;
	int ret;
	struct termios termios_p; 
//1.打开串口设备。不当作控制台。
    fd = open(device, O_NOCTTY | O_RDWR);
    if (fd < 0) {
        perror("open error");
        return -1;
    }
//2. 填充设备结构体
	memset(&termios_p, 0 ,sizeof(termios_p));
	termios_p.c_cflag |= CREAD;     //使能接收器的接收功能!必须配置的。
	termios_p.c_cflag |= CLOCAL;    //忽略调制解调器线路状态。
	termios_p.c_cflag |=CS8;        //设置八位数据位。
	
    //这里为了方便观看,所以写出来下面的配置,这里其实可以不写,因为我们已经先前清空结构体了。
	termios_p.c_cflag &=~CSTOPB; //设置一位停止位。
	termios_p.c_cflag &=~PARENB; //无奇偶校验位。
	termios_p.c_lflag &=~ECHO ; //不回显
	
	// 设置超时和最小读取字符数。必须配置!!
    termios_p.c_cc[VTIME] = 1;
    termios_p.c_cc[VMIN] = 128;
	
    switch (baud){  //设置波特率
			case 9600:
						cfsetispeed(&termios_p,B9600);  //设置接收波特率
						cfsetospeed(&termios_p,B9600);  //设置发送波特率
						break;
			case 115200:
						cfsetispeed(&termios_p,B115200);  //设置接收波特率
						cfsetospeed(&termios_p,B115200);  //设置发送波特率
						break;
			default:
						printf("不支持此波特率\n");
						break;
   }
   
//3. 清空接收/发送缓冲,准备发送和接收数据 
	tcflush(fd, TCIOFLUSH);

//4. 将配置好的设备结构体设置上(绑定),激活设置的配置。
	ret =tcsetattr( fd,TCSAFLUSH,&termios_p);
	if (ret < 0) {
        perror("tcsetattr error");
        return -3;
    }
	
	return fd; //返回文件描述符
}

uart.h

#ifndef __UART_H
#define __UART_H

void UART_Close(int fd);
int UART_Init(char *device, int baud);
int UART_Receive(int fd, char *receive);
int UART_Send(int fd, char *data);
#endif

main.c

#include <stdio.h>
#include <stdlib.h>
#include "uart.h" 
#include <unistd.h>
#include <termios.h>
#include <string.h>
int main()
{
	char buff[100];
	int fd;
	fd=UART_Init("/dev/ttyAMA2",115200);
	if(fd<0){
		perror("UART_Init error");
		return -1;
	}
	
	while(1){
		fgets(buff,sizeof(buff),stdin);
		UART_Send(fd, buff);
	}
	
	UART_Close(fd);
	return 0;
}

在这里插入图片描述

线程优化

功能:添加线程实现可收可发!
main.c

#include <stdio.h>
#include <stdlib.h>
#include "uart.h" 
#include <unistd.h>
#include <termios.h>
#include <string.h>
#include <pthread.h>
#include <signal.h>

pthread_attr_t attr; //线程属性
int fd;  //文件描述符

void signal_task(int arg)
{
    printf("销毁相关属性\n");
	pthread_attr_destroy(&attr); //销毁线程属性
    UART_Close(fd);
    exit(0);
}

// 线程任务函数
void *task(void *arg) {
    int fd = *(int *)arg;
    int ret;
    char buff[64];

    while (1) {
		        memset(buff, 0, sizeof(buff));
		        ret = UART_Receive(fd, buff); // 读取数据到buff中
		        if (ret > 0) {
		            buff[ret] = '\0'; // 确保字符串以NULL结尾
		            printf("Receive: %s\n", buff);
		        } 
		        else break;
             }
    pthread_exit(NULL);
}

int main()
{
	char buff[100];
	int ret;
	pthread_t thread;

	fd=UART_Init("/dev/ttyAMA2",115200);
	if(fd<0){
		perror("UART_Init error");
		return -1;
	}
	
	signal(2, signal_task);
	
	pthread_attr_init(&attr);  //初始化线程属性
	pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); //设置子线程分离属性,子线程推出后自动销毁。
	ret=pthread_create(&thread,NULL,task,(void *)&fd); //只有一个子线程,可以取地址操作。
	if(ret<0){
         perror("pthread_create error");
         return -1;
    }
    
	while(1){
	    memset(buff,0,sizeof(buff));
		fgets(buff,sizeof(buff),stdin);
		UART_Send(fd, buff);
	}
	
	return 0;
}

在这里插入图片描述

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

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

相关文章

[Algorithm][动态规划][两个数组的DP][正则表达式匹配][交错字符串][两个字符串的最小ASCII删除和][最长重复子数组]详细讲解

目录 1.正则表达式匹配1.题目链接2.算法原理详解3.代码实现 2.交错字符串1.题目链接2.算法原理详解3.代码实现 3.两个字符串的最小ASCII删除和1.题目链接2.算法原理详解3.代码实现 4.最长重复子数组1.题目链接2.算法原理详解3.代码实现 1.正则表达式匹配 1.题目链接 正则表达…

Redis Key过期监听配置

默认情况下在Windows系统中双击redis-server.exe用的是内置的配置文件 如果希望用这两个配置文件 redis.windows.conf&#xff1a;这是用于在Windows上运行Redis服务器的标准配置文件。可以使用这个文件通过命令行启动Redis服务器。redis.windows-service.conf&#xff1a;这是…

解锁机器学习的无限可能:深入探究scikit-learn的强大功能

解锁机器学习的无限可能&#xff1a;深入探究scikit-learn的强大功能 第一部分&#xff1a;背景和功能介绍 在数据科学和机器学习领域&#xff0c;scikit-learn&#xff08;简称sklearn&#xff09;是一个广泛使用的Python库。它提供了简单高效的工具用于数据挖掘和数据分析&a…

Echarts 在折线图的指定位置绘制一个图标展示

文章目录 需求分析需求 在线段交汇处用一个六边形图标展示 分析 可以使用 markPoint 和 symbol 属性来实现。这是一个更简单和更标准的方法来添加标记点在运行下述代码后,你将在浏览器中看到一个折线图,其中在 [3, 35] (即图表中第四个数据点 Thu 的 y 值为 35 的位置)处…

CAN总线学习笔记-CAN物理层

CAN介绍 CAN总线&#xff1a;控制器局域网总线&#xff08;类似一个局域网网络&#xff0c;网络中任何一个节点都可以向其他节点发送数据&#xff09; CAN总线特性&#xff1a; 两根通信线&#xff08;CAN_H、CAN_L&#xff09; 差分信号通信&#xff0c;抗干扰能力强 高速CAN…

十足正式在山东开疆拓土!首批店7月初开业,地区便利店现全新面貌!

十足便利店将正式进军山东市场&#xff0c;以济南、淄博两座城市为核心发展起点&#xff0c;目前济南市已经有三家十足门店正在装修施工中&#xff0c;首批15家门店将于7月初开业&#xff0c;这标志着十足集团市场战略布局迈出了至关重要的一步。 随着3月份罗森品牌在济南成功开…

Python语言进阶学习

目录 一、类、对象和成员方法 二、构造方法 三、面向对象 &#xff08;1&#xff09;封装 &#xff08;2&#xff09;继承 单继承 多继承 复写 super&#xff1a;调用父类同名成员 &#xff08;3&#xff09;多态 &#xff08;4&#xff09;抽象类 五、Python操作…

Codeforces Round 951 (Div. 2) C、D(构造、线段树)

1979C - Earning on Bets 构造题&#xff1a;观察到k范围很小&#xff0c;首先考虑最终硬币总数可以是多少&#xff0c;我们可以先假设最终的硬币总数为所有k取值的最小公倍数&#xff0c;这样只需要满足每个结果添加1枚硬币即可赚到硬币。 // Problem: C. Earning on Bets //…

MacOS M系列芯片一键配置多个不同版本的JDK

第一步&#xff1a;下载JDK。 官网下载地址&#xff1a;Java Archive | Oracle 选择自己想要下载的版本&#xff0c;一般来说下载一个jdk8和一个jdk11就够用了。 M系列芯片选择这两个&#xff0c;第一个是压缩包&#xff0c;第二个是dmg可以安装的。 第二步&#xff1a;编辑…

9.1.1 简述目标检测领域中的单阶段模型和两阶段模型的性能差异及其原因

9.1目标检测 场景描述 目标检测&#xff08;Object Detection&#xff09;任务是计算机视觉中极为重要的基础问题&#xff0c;也是解决实例分割&#xff08;Instance Segmentation&#xff09;、场景理解&#xff08;Scene Understanding&#xff09;、目标跟踪&#xff08;Ob…

【机器学习】Qwen1.5-14B-Chat大模型训练与推理实战

目录 一、引言 二、模型简介 2.1 Qwen1.5 模型概述 2.2 Qwen1.5 模型架构 三、训练与推理 3.1 Qwen1.5 模型训练 3.2 Qwen1.5 模型推理 四、总结 一、引言 Qwen是阿里巴巴集团Qwen团队的大语言模型和多模态大模型系列。现在&#xff0c;大语言模型已升级到Qwen1.5&…

Git使用总结(git使用,git实操,git命令和常用指令)

简介&#xff1a;Git是一款代码版本管理工具&#xff0c;可以记录每次提交的代码&#xff0c;防止代码丢失&#xff0c;可实现版本迭代&#xff0c;解决代码冲突&#xff0c;常用的远程Git仓库&#xff1a;Gitee&#xff08;国内&#xff09;、GitHub&#xff08;国外&#xff…

全球AI新闻速递6.7

1.智谱 AI 宣布全模型矩阵降价&#xff0c;开源 GLM-4-9B 系列模型。 2.复旦大学计划在2024-2025新学年推出至少100门。 3.思科&#xff1a;启动 10 亿美元 AI 基金&#xff0c;投资AI初创公司。 4.OpenAI和谷歌DeepMind员工联名发声&#xff1a;高级AI风险巨大&#xff0c;…

Flutter开发效率提升1000%,Flutter Quick教程之对Widget进行删除,剪切,粘贴

一&#xff0c;删除操作 1&#xff0c;首先我们选中要删除的Widget。 2&#xff0c;在左边的侧边栏&#xff0c;点击删除按钮&#xff0c;即可完成对组件的删除操作。 二&#xff0c;剪切。剪切是相同的道理&#xff0c;都是先选中&#xff0c;再点击对应的按钮。 1&#xff…

UE4_环境_材质函数

学习笔记&#xff0c;不喜勿喷&#xff0c;欢迎指正&#xff0c;侵权立删&#xff01; 1、建立材质函数Distance_Fun&#xff0c;勾选公开到库。 2、添加函数输入节点FunctionInput&#xff0c; 这个输入我们想作为混合材质属性BlendMaterialAttributes的alpha输入节点&#x…

钓鱼攻击的隐性经济

近年来&#xff0c;网络钓鱼形势发生了重大变化&#xff0c;涵盖了各种类型的攻击。许多公司已经开发了分类法来对不同的网络钓鱼攻击进行分类&#xff0c;类似于BlueVoyant 提出的分类法。该分类法概述了几种类型的网络钓鱼攻击&#xff0c;例如&#xff1a; 1. 电子邮件钓鱼…

一举高“粽“,考生请注意!AI监考来了...

&#x1f4e2;&#x1f4e2;&#x1f4e2;&#x1f4e3;&#x1f4e3;&#x1f4e3; 作者&#xff1a;IT邦德 中国DBA联盟(ACDU)成员&#xff0c;10余年DBA工作经验&#xff0c; Oracle、PostgreSQL ACE CSDN博客专家及B站知名UP主&#xff0c;全网粉丝10万 擅长主流Oracle、My…

什么是Swagger UI ,swagger ui 的authorization怎么获取?

什么是Swagger UI Swagger UI 是一个用于可视化和交互式地展示API文档的工具。它是Swagger&#xff08;现称为OpenAPI&#xff09;生态系统的一部分&#xff0c;旨在帮助开发者和API用户更好地理解、测试和调试API。 主要功能和作用 1. API文档自动生成&#xff1a; Swagge…

用户管理的小demo--过滤器filter

1、创建 CharEncodingFilter.java package com.by.filter; import javax.servlet.*; import java.io.IOException; public class CharEncodingFilter implements Filter {Overridepublic void init(FilterConfig filterConfig) throws ServletException {}Overridepublic void …

一个AI板卡电脑--香橙派 AIpro

本文算是一个开箱测评&#xff0c;主要评估它和一个电脑的距离。 香橙派官网&#xff1a;香橙派(Orange Pi)-Orange Pi官网-香橙派开发板,开源硬件,开源软件,开源芯片,电脑键盘香橙派&#xff08;Orange Pi&#xff09;是深圳市迅龙软件有限公司旗下开源产品品牌;香橙派&#x…