树莓派c语言串口通讯程序

2023-05-16

在网上搜了很多关于树莓派串口通讯的例子,但是都是用python写的,虽然python很有名,而且最近也在学习这门语言,

但是还是想用c语言实现一下,因为需要用到整套系统里,其他内容都是用c语言写的。但是网上没有找打现成的。

还好,之前做过天嵌2440开发板的串口程序(参照天嵌工程师提供的代码),发现串口程序其实是通用的,

驱动层屏蔽了硬件细节,个人猜测,几乎所有移植好的系统的串口,都可以用一样的代码来操作,至少2440和树莓派是通用的。

分享代码如下:

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <termios.h>
#include <errno.h>
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <unistd.h>
#include"pthread.h"
#include "serial.h"


struct serial_config serialread;

static int serial_fd;

int speed_arr[] = {B230400, B115200, B57600, B38400, B19200, B9600, B4800, B2400, B1200, B300,
		   B38400, B19200, B9600, B4800, B2400, B1200, B300};

int name_arr[] = {230400, 115200, 57600, 38400, 19200, 9600, 4800, 2400, 1200, 300,
		  38400, 19200, 9600, 4800, 2400, 1200, 300};

//-----------------------------------------------
//打印配置文件serial.cfg的内容
//-----------------------------------------------
void print_serialread()
{
	printf("serialread.dev is %s\n",serialread.serial_dev);
	printf("serialread.speed is %d\n",serialread.serial_speed);
	printf("serialread.databits is %d\n",serialread.databits);
	printf("serialread.stopbits is %d\n",serialread.stopbits);
	printf("serialread.parity is %c\n",serialread.parity);
}

//-----------------------------------------------
//读取serial.cfg文件并进行配置
//-----------------------------------------------
void readserialcfg()
{
	FILE *serial_fp;
	char j[10];
	
	printf("readserailcfg\n");

	serial_fp = fopen("./serial.cfg","r");
	if(NULL == serial_fp)
	{
		printf("can't open serial.cfg");
	}
	else
	{
		fscanf(serial_fp, "DEV=%s\n", serialread.serial_dev);

		fscanf(serial_fp, "SPEED=%s\n", j);
		serialread.serial_speed = atoi(j);

		fscanf(serial_fp, "DATABITS=%s\n", j);
		serialread.databits = atoi(j);

		fscanf(serial_fp, "STOPBITS=%s\n", j);
		serialread.stopbits = atoi(j);

		fscanf(serial_fp, "PARITY=%s\n", j);
		serialread.parity = j[0];
	}

	fclose(serial_fp);
}

//-----------------------------------------------
//设置波特率
//-----------------------------------------------
void set_speed(int fd)
{
	int i;
	int status;
	struct termios Opt;
	struct termios oldOpt;
	tcgetattr(fd, &oldOpt);
//	printf("serialread.speed is %d\n",serialread.serial_speed);
	for( i = 0; i < sizeof(speed_arr)/sizeof(int); i++)
	{
		if(serialread.serial_speed == name_arr[i])
		{
			tcflush(fd, TCIOFLUSH);
			cfsetispeed(&Opt, speed_arr[i]);
			cfsetospeed(&Opt, speed_arr[i]);
			status = tcsetattr(fd, TCSANOW, &Opt);
			if(status != 0)
			{
				perror("tcsetattr fd1");
				return;
			}
			tcflush(fd, TCIOFLUSH);
		}
	}
}


//-----------------------------------------------
//设置其他参数
//-----------------------------------------------
int  (int fd)
{
	struct termios options;
	struct termios oldoptions;
	if(tcgetattr(fd, &oldoptions) != 0)
	{
		perror("SetupSerial 1");
		return(FALSE);
	}

	options.c_cflag |= (CLOCAL|CREAD);
	options.c_cflag &=~CSIZE;
//	printf("serialread.databits is %d\n",serialread.databits);
	switch(serialread.databits)
	{
		case 7:
			options.c_cflag |= CS7;
			break;
		case 8:
			options.c_cflag |= CS8;
			break;
		default:
			options.c_cflag |= CS8;
			fprintf(stderr, "Unsupported data size\n");
			return(FALSE);
	}
//	printf("serialread.parity is %c\n",serialread.parity);
	switch(serialread.parity)
	{
		case 'n':
		case 'N':
			options.c_cflag &= ~PARENB;
			options.c_iflag &= ~INPCK;
			break;
		case 'o':
		case 'O':
			options.c_cflag |= (PARODD | PARENB);
			options.c_iflag |= INPCK;
			break;
		case 'e':
		case 'E':
			options.c_cflag |= PARENB;
			options.c_cflag &= ~PARODD;
			options.c_iflag |= INPCK;
			break;
		default:
			options.c_cflag &= ~PARENB;
			options.c_iflag &= ~INPCK;
			fprintf(stderr, "Unsupported parity\n");
			return(FALSE);
	}
//	printf("serialread.stopbits is %d\n",serialread.stopbits);
	switch(serialread.stopbits)
	{
		case 1:
			options.c_cflag &= ~CSTOPB;
			break;
		case 2:
			options.c_cflag |= CSTOPB;
			break;
		default:
			options.c_cflag &= ~CSTOPB;
			fprintf(stderr, "Unsupported stop bits\n");
			return(FALSE);
	}
	if(serialread.parity != 'n')
		options.c_iflag |= INPCK;
	options.c_cc[VTIME] = 0;	//150;			//15 seconds
	options.c_cc[VMIN] = 0;
#if 1
	options.c_iflag |= IGNPAR|ICRNL;
	options.c_oflag |= OPOST; 
	options.c_iflag &= ~(IXON|IXOFF|IXANY);                     
#endif
	tcflush(fd, TCIFLUSH);
	if(tcsetattr(fd, TCSANOW, &options) != 0)
	{
		perror("SetupSerial 3");
		return(FALSE);
	}
	return(TRUE);
}

//-----------------------------------------------
//打开串口设备
//-----------------------------------------------
int OpenDev(char *Dev)
{
	int fd = open(Dev, O_RDWR, 0);
	if(-1 == fd)
	{
		perror("Can't Open Serial Port");
		return -1;
	}
	else
		return fd;
}

//--------------------------------------------------
//串口初始化
//--------------------------------------------------
void serial_init()
{
	char *Dev;

	int i;

	readserialcfg();
	//print_serialread();
    printf("init serial\n");

	Dev = serialread.serial_dev;
	//打开串口设备
	serial_fd = OpenDev(Dev);

	if(serial_fd > 0)
		set_speed(serial_fd);		//设置波特率
	else
	{
		printf("Can't Open Serial Port!\n");
		exit(0);
	}
	//恢复串口未阻塞状态
	if (fcntl(serial_fd, F_SETFL, O_NONBLOCK) < 0)
	{
		printf("fcntl failed!\n");
		exit(0);
	}
	//检查是否是终端设备
#if 0	//如果屏蔽下面这段代码,在串口输入时不会有回显的情况,调用下面这段代码时会出现回显现象。
	if(isatty(STDIN_FILENO)==0)
	{
		printf("standard input is not a terminal device\n");
	}
	else
		printf("isatty success!\n");
#endif
	//设置串口参数
	if(set_Parity(serial_fd) == FALSE)
	{
		printf("Set parity Error\n");
		exit(1);
	}

}

int serial_write(char* cmd, int count)
{
    printf("serial write for %d bytes\n",count);
    return write(serial_fd,cmd,count);
}

void serial_close()
{
    printf("close serial\n");
    close(serial_fd);
}

/*
void serial_rw()
{
	int i;
	char buff[512];
	
	int nread,nwrite;

     char buff2[] = "hello!\n";
	nwrite = write(serial_fd,buff2,sizeof(buff2));
	printf("nwrite=%d\n",nwrite);
	while(1)
	{
		if((nread = read(serial_fd,buff,512))>0)
		{ 
			buff[nread] = '\0';
#if 1	//调用这段代码可以实现回显,如果配合上面的回显,就会出现回显两次的情况。
			write(serial_fd,buff,nread);
#endif
			printf("recv:%d\n",nread);
#if 1
			for(i=0;i<nread;i++)
			{
				printf("%c",buff[i]);
			}
			printf("\n");
#else
			printf("%s",buff);
			printf("\n");
#endif
		}
	}
 


}
*/
/*
int main(int argc, char **argv)
{
	serial_init();

    char cmd[]={0xfc,0x01,0x01,0x02,0x01,0x00,0x03,0x01,0xcf};
    write(serial_fd,cmd,sizeof(cmd));
    close(serial_fd);
    
	return 0;
//	close(serialread.serial_dev);
//	serial_test(telnum, telmoney);
}
*/

当然,还需要对应的头文件:

#define FALSE		0
#define TRUE		1

#define WORDLEN 32

struct serial_config
{
	unsigned char serial_dev[WORDLEN];
	unsigned int serial_speed;
	unsigned char databits;
	unsigned char stopbits;
	unsigned char parity;
};

void serial_init();
int serial_write(char* cmd, int count);
void serial_close();

以及分离出来的配置文件:

DEV=/dev/ttyAMA0
SPEED=9600
DATABITS=8
STOPBITS=1
PARITY=N


看到c文件可以发现,main函数被注释了,因为是编译的整个系统,这个文件只提供接口,所以没有main函数,如果需要,可以去掉注释。

内容很粗糙,有时间再修缮


本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

树莓派c语言串口通讯程序 的相关文章

  • 博客搬家至Github

    为了使用Markdown写作更方便一些 xff0c 以后将使用github pages来管理博客 地址 xff1a Rannie s Page 欢迎来访
  • C++使用http向服务器发送json数据

    span class token macro property span class token directive hash span span class token directive keyword include span spa
  • 如何使用Git将Github项目拉到本地

    如何使用Git将Github项目拉到本地 前言 因为国内访问GIthub速度比较慢 xff0c 复制粘贴代码又慢效率也低 xff0c 所以建议下载Git工具 xff0c 直接把Github的项目整个下载到本地的文件夹 安装配置git 步骤如
  • 笔记本 - 数据分析百宝箱

    Numpy 一 基本操作 xff1a 属性 xff1a improt numpy as np 生成数组 xff1a array 61 np array 1 2 3 2 3 4 xff0c dtype 61 np int float arra
  • Faiss(5):IndexIVFPQ原理

    说明 原本想尝试自己从头写 xff0c 但看了下网上的各位前辈的博客后 xff0c 感觉自己还是才疏学浅 xff0c 没有理解透彻 xff0c 所以在这里做个搬运工 xff0c 偶尔加些个人的理解在里面 原文链接 xff1a https b
  • cmake(3):编译库和链接可执行文件

    1 说明 在实际开发的过程当中 xff0c 我们会经常需要将部分程序编译成静态或动态库的形式 xff0c 供其他应用程序调用而不是将所有文件一次编译为一个可执行文件 这篇笔记就记录使用cmake编译动态和静态库以及将库链接到可执行文件中的过
  • RTOS原理与实现02:基本任务切换实现

    目录 1 任务定义与切换原理 1 1 任务是什么 1 1 1 任务的外观 1 1 2 任务的内在 1 2 任务切换原理 1 2 1 任务切换的本质 1 2 2 要保存哪些任务运行状态 1 2 3 任务运行状态保存方案 1 3 设计实现 1
  • cmake(5):选择编译器及设置编译器选项

    1 说明 在实际的项目平台中可能安装有多个版本的编译器 xff0c 同时由于不同的功能可能会需要设置不同的编译参数 xff0c 这篇笔记就记录如何选择指定的编译器和配置参数 2 选择编译器 2 1 初始状态 我使用的开发平台默认安装的gcc
  • Faiss(14):IndexIVFPQ的CPU search过程分析

    1 说明 之前分析过了faiss 在GPU中的search过程 xff0c 这里分析一下IndexIVFPQ在CPU中的search过程 xff0c 即不将index拷贝到GPU中 2 过程分析 2 1 python接口 CPU searc
  • cmake(8):install命令详解

    1 说明 之前的示例中有提到使用cmake的install命令来自动安装库和头文件 xff0c 但是只是使用到了install命令很基础很少的部分 xff0c 其实该命令作用十分丰富 xff0c 本篇文档用于说明该命令的详细使用方法 2 i
  • cmake(9):包含指定目录的头文件

    1 说明 在编译程序时 xff0c 如果需要用到外部的头文件 xff0c 而该头文件又没有被添加到系统默认的路径中 xff08 如 xff1a usr include xff0c usr local include和 usr lib gcc
  • cmake(10):使用cmake编译linux驱动或内核模块

    1 说明 这篇笔记用于说明如何使用cmake构建Linux驱动 xff0c 这样可以方便地将driver和app作为一个整体统一构建 2 示例 首先来看一个代码示例 xff0c 为了简化起见 xff0c 我直接在驱动目录下进行构建而没有作为
  • Boost(1):Boost库简介及安装

    1 Boost库介绍 Boost是一个功能强大 构造精巧 跨平台 开源并且完全免费的C 43 43 程序库 xff0c 在1998年由Beman G Dawes发起倡议并建立 使用了许多现代C 43 43 编程技术 xff0c 内容涵盖字符
  • Ubuntu:与Windows共享文件夹

    1 说明 我个人更喜欢在windows下编辑代码或文档 xff0c 而运行环境又经常在Linux环境下进行 xff0c 那么Windows和Linux之间的协作就显得很有必要了 通常有两种方式来实现两个系统之间的文件共享 xff1a 在Li
  • C语言处理参数的 getopt() 函数

    前言 C语言程序主要通过 main 函数的参数来传递命令行参数 xff1a 默认传递命令行参数 int main int argc char argv 其中 argc 表示参数个数 xff08 包含程序本身 xff09 xff0c argv
  • SPD5详解

    SPD介绍 SPD xff08 serial presence detect xff09 xff0c 即串行存在检测 xff0c 是DIMM的相关描述信息 在每根内存条上 xff0c 都有一份SPD数据 xff0c 这份数据保存在一个可擦写
  • 基于CentOS更新 glibc - 解决 `GLIBC_2.29‘ not found

    说明 在一个 CentOS Stream8 上安装或运行某些程序时 xff0c 报 96 GLIBC 2 29 39 not found xff0c 因为系统自带的 glibc 库版本只到 glibc 2 28 strings usr li
  • FreeRTOS源码分析与应用开发05:信号量

    目录 1 信号量概述 1 1 信号量概念 1 2 4种信号量 1 2 1 二值信号量 1 2 2 计数信号量 1 2 3 互斥信号量 1 2 4 递归互斥信号量 1 3 信号量相关控制结构 1 3 1 队列结构 1 3 2 任务结构 2 二

随机推荐

  • FreeRTOS Task switch

    vTaskSwitchContext中看pxCurrentTCB traceTASK SWITCHED OUT 切出 taskSELECT HIGHEST PRIORITY TASK traceTASK SWITCHED IN 切入新的ta
  • 嵌入式常见总线分类总结

    任何一个微处理器都要与一定数量的部件和外围设备连接 xff0c 但如果将各部件和每一种外围设备都分别用一组线路与CPU直接连接 xff0c 那么连线将会错综复杂 xff0c 甚至难以实现 为了简化硬件电路设计 简化系统结构 xff0c 常用
  • linux压测工具stress和stress-ng下载

    1 下载 2020 5 16实测以下地址能下载 stress https fossies org linux privat stress 1 0 4 tar gz stress ng https aur tuna tsinghua edu
  • 设备树Device Tree详解

    原文 xff1a https www cnblogs com aaronLinux p 5496559 html 目录 1 设备树 xff08 Device Tree xff09 基本概念及作用 2 设备树的组成和使用 2 1 DTS和DT
  • 十六进制与ascii码互转 C语言实现

    十六进制与ascii码互转 C语言实现 1 ascii转16进制 func char to hex desc convert ascii to 16 hex input ascii return hex unsigned char char
  • Android 11.0 支持exFAT文件系统

    Android 11 0 支持exFAT文件系统 U盘常见文件系统类型有FAT32 NTFS exFAT xff0c Android默认支持FAT32 一般也有NTFS类型编译选项 xff0c 但是exFAT由于版权或者其他原因 xff0c
  • repo sync遇到warning: project ‘repo‘ branch ‘stable‘ is not signed

    warning project 39 repo 39 branch 39 stable 39 is not signed This can happen on Linux and Mac I 39 ve personally experie
  • C语言单链表基本操作总结

    C语言单链表基本操作 本文是参考他人实现的C语言单链表 xff0c 对多篇博文整理的结果 xff0c 仅作为学习笔记 文末有参考出处 1 单链表定义 链表是通过一组任意的存储单元来存储线性表中的数据元素 xff0c 这些存储单元可以是连续的
  • 开源项目-类似58同城的项目启动

    已经进入编程这行已经3年 xff0c 最近想做一个自己的开源项目 xff0c 最后选来选去 xff0c 选中了类似58同城的功能的项目作为开始 下面是一些列的工作 xff0c 里面会体系我是怎样把这个项目做出来 xff0c 包括思路 技术
  • CMakeLists完整解析(一)

    CMakeLists完整解析 xff08 一 xff09 首先 xff0c 我们先通过介绍一下相关的核心概念来引入CMakeLists 1 gcc make和cmake gcc xff08 GNU Compiler Collection x
  • FreeRTOS源码分析与应用开发08:任务通知

    目录 1 概述 1 1 任务通知概念 1 2 任务通知控制结构 2 发送任务通知 2 1 任务级发送 2 2 中断级发送 2 2 1 xTaskNotifyFromISR函数 2 2 2 vTaskNotifyGiveFromISR函数 3
  • 基于ROS机器人的3D物体识别与三维重建(一) 介绍篇

    基于ROS机器人的3D物体识别与三维重建 一 xff09 介绍篇 由来 xff1a 清理电脑硬盘 xff0c 发现了当时做毕设的一些资料 xff0c 所以打算整理一下资料和代码写成专栏 xff0c 记录下当时的暗金岁月 xff0c 尽管现在
  • WIFI模块实现网络连接

    WiFi模块连接 xff0c 通过串口调试助手来配置 STA 43 连接TCP Server 1 AT 43 CWMODE DEF 61 1 工作在单station模组 xff0c 设置参数保存到flash 2 AT 43 CWJAP DE
  • 关于飞机绕地球飞行一圈的加油问题

    已知 xff1a 每个飞机只有一个油箱 xff0c 飞机之间可以相互加油 xff0c 注意是相互 xff0c 没有加油机 xff0c 一箱油可供一架飞机绕地球飞半圈 问题 xff1a 为使至少一架飞机绕地球一圈回到起飞时的飞机场 xff0c
  • 【C/C++/QT/ 移植/导入Mavlink V2.0/Mavlink V1.0教程】

    提示 xff1a 本文针对的实例是Mavlink V2 0版本 xff0c Mavlink V1 0版本其实也是类似的的步骤 xff0c 选择的mavlink库不一样而已 官方链接放在此 xff1a Install MAVLink MAVL
  • 无需修改bios即可让任意主板实现NVME启动

    使用Clover四叶草引导加载NVMe驱动 除了对BIOS的硬改之外 xff0c 还有一种更安全的软件方案 xff1a 使用Clover四叶草引导加载NVMe驱动 Clover是著名的黑苹果引导软件 xff0c 这里借用它来实现对预引导 x
  • 如何将PX4 User Guide导出为PDF

    PX4 Autopilot User Guide PDF导出 如何将PX4 User Guide导出为PDF1 工具安装安装nodejs安装ebook conver安装svgexport安装gitbook 2 输出PX4 Guide文档下载
  • CentOS7 yum安装docker失败的看过来

    背景 在百度上搜到一些前辈关于安装docker教程 xff0c 例如 xff1a 点击打开链接 但都报出找不到源的信息 xff0c 估计导致该情况往往是国内使用外国源被和谐的原因吧 解决 1 使用阿里云的yum源 cd etc yum re
  • 持续交付(CD)与持续集成(CI)

    测试基础设施是指支持自动化测试运行 测试开发 测试管理以及与研发环境集成的综合性平台 敏捷测试离不开稳定 高效 准确的基础设施 xff0c 以满足对于持续测试 持续反馈的需要 xff1b 同时 xff0c 持续集成 持续交付和 DevOps
  • 树莓派c语言串口通讯程序

    在网上搜了很多关于树莓派串口通讯的例子 xff0c 但是都是用python写的 xff0c 虽然python很有名 xff0c 而且最近也在学习这门语言 xff0c 但是还是想用c语言实现一下 xff0c 因为需要用到整套系统里 xff0c