linux 与 单片机 串口通信

2023-05-16

  本人最近在尝试在linux下用串口与单片机通信,虽然说网上资料例程五花八门,但是缺乏严格的注释或者完整的实例,或许本人能力有限,某些问题无法理解,在实际过程中遇到不少问题,无从下手,特此写篇文章请求各位大神的斧正。初次写帖,不足处希望指出。

  实验目的:单片机通过串口向linux发送数据。

  环境:单片机 ST90C516RD+,使用USB转串口(驱动PL2303);linux(ubuntu11.10)装载在VM8。

  单片机发送程序如下

/********************************************************************
* 文件名  : 串口发送试验.c
* 描述    :  该文件实现通过串口把数据从单片机发送到电脑,通过串口调试助手显示出来。
			 晶振需要用11.0592的。
***********************************************************************/
#include<reg52.h>
#include<intrins.h>

#define uchar unsigned char
#define uint  unsigned int 

/********************************************************************
* 名称 : Com_Init()
* 功能 : 初始化串口程序,晶振11.0592, 波特率9600
* 输入 : 无
* 输出 : 无
***********************************************************************/
void Com_Init(void)
{
     TMOD = 0x20;
     PCON = 0x00;
     SCON = 0x50;			
     TH1 = 0xFd;
     TL1 = 0xFd;
     TR1 = 1;			
}

void delay_ms(unsigned int n)            //延时10×n毫秒程序
{
	unsigned int i,j;
	for(i=0;i<n;i++)
		for(j=0;j<2000;j++);
}
/********************************************************************
* 名称 : Main()
* 功能 : 主函数
* 输入 : 无
* 输出 : 无
***********************************************************************/
void Main()
{
	char i = 0;
	char code Buffer[] = "abcdef 123456 ABCDEF";
	char *p;
	Com_Init();
	P2 = 0x00;
	while(1)
	{
		p = Buffer;
		while(1)
		{
			SBUF = *p;
			while(!TI)                   	//如果发送完毕,硬件会置位TI = 1
			{
				_nop_();		//延时一个指令周期
			}
			p++;
			if(*p == '\0')
			 break;				//在每个字符串的最后,会有一个'\0'
			TI = 0;		                //TI清零
		}
		TI = 0;		                	//TI清零
		delay_ms(100);
	}
}

linux C代码如下

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

#define SERIAL_PORT			"/dev/ttyUSB0"	//串口地址
#define PORT_SPEED			9600		//串口波特率
#define	DATABITS			8		//数据位
#define STOPBITS			1		//停止位
#define	PARITY				'n'		//校验方式 (不校验)

int speed_arr[] = {B38400, B19200, B9600, B4800, B2400, B1200, B300,B38400, B19200, B9600, B4800, B2400, B1200, B300,};
int name_arr[] = {38400,  19200,  9600,  4800,  2400,  1200,  300, 38400,  19200,  9600, 4800, 2400, 1200,  300,};

int setSpeed(int, int, struct termios);
int setParity(int, int, int, int, struct termios);
int openPort(void);
int init(void);
void readPort(int);

int main()
{
	char *quit = (char*)malloc(sizeof(char*));
	int fd;
       

  char write_buf[256];

	fd = init();//初始化端口设置
	
	printf("configure complete\n"); 
  printf("start send and receive data...\n");
  
  while(1)
  {  	  
      readPort(fd);
	}
	close(fd);
}

void readPort(int fd)
{
		int i;
	  int len;
	  int n; 
	  char read_buf[256];
	  while(1)
	  {
			bzero(read_buf, sizeof(read_buf));    
	     
			while((n = read(fd, read_buf, sizeof(read_buf))) > 0)
	  	{
				printf("Len %d \n", n);
				read_buf[n + 1] = '\0';
	 		 	printf("[%s]\n", read_buf);
	  	}
  	}
}
/************************************
 *init 
 *	初始化串口
 *@global
 *	PORT_SPEED	串口波特率
 *	DATABITS	数据位
 *	STOPBITS	停止位
 *	PARITY		校验方式
 *@return
 *	-1:设置失败  !(-1):设置成功
 ************************************/
int init(void)
{
	int fd;
	struct termios opt;	//定义termios结构
 /*
  这个变量被用来提供一个健全的线路设置集合, 如果这个端口在被用户初始化前
  使用. 驱动初始化这个变量使用一个标准的数值集               
  struct termios{
  	unsigned short c_iflag; //输入模式标志
    unsigned short c_oflag; 	//输出模式标志
    unsigned short c_cflag; 	//控制模式标志
    unsigned short c_lflag; 	//区域模式标志或本地模式标志或局部模式
    unsigned char c_line; 	//行控制line discipline 
    unsigned char c_cc[NCC]; 	// 控制字符特性
  };
	*/
  //打开串口
  fd = openPort();
  
  //设置波特率
  if(setSpeed(fd, PORT_SPEED, opt) == 1)
  {	
  	printf("setSpeed failed!\n");
  	exit(1);
  }
  
  //设置数据位、停止位和校验位
  if(setParity(fd, DATABITS, STOPBITS, PARITY, opt) == 1)
  {
  	printf("setParity failed!\n");
  	exit(1);
  } 
  if(tcsetattr(fd, TCSANOW, &opt) != 0)	//TCSANOW:不等数据传输完毕就立即改变属性。
	{				//TCSADRAIN:等待所有数据传输结束才改变属性。
      perror("serial error");
      return -1;
  }
  return fd;
}
/************************************
 *openPort  
 *	打开串口
 *@global
 *	SERIAL_PORT	串口地址
 *@return
 *	-1:设置失败  !(-1):设置成功
 ************************************/
int openPort()
{
	int fd;
	//O_RDWR:	可读写方式打开;
	//O_NOCTTY:	若打开的文件为终端机设备时则不会把该终端机当做进程控制终端机
	//O_NDELAY:	以不可阻断的方式打开文件
	fd = open(SERIAL_PORT, O_RDWR | O_NOCTTY |O_NDELAY);   
  	if(fd == -1)
  	{
		perror("open serial failed!\n");
  		exit(1);
  	}    
  	return fd;
}

/************************************
 *setSpeed  
 *	设置波特率(38400, 19200, 9600, 4800, 2400, 1200, 300)
 *@para
 *	fd				文件标识。
 *	speed				波特率。
 *  struct termios			termios结构变量
 *@return
 *	1:设置失败  0:设置成功
 ************************************/
int setSpeed(int fd, int speed, struct termios Opt)
{
    int i;

    //if(tcgetattr(fd, &Opt) != 0) //获取与终端相关的参数;	#并将获得信息保存在 opt 变量中
    if(tcgetattr(STDIN_FILENO, &Opt) != 0)
    {
        perror("tcgetattr fd\n");
        return 1;
    }
    //识别波特率,设置输入输出波特率
    for(i = 0; i < sizeof(speed_arr) / sizeof(int); i++)
    {
        if(speed == name_arr[i])
        {
            tcflush(fd, TCIOFLUSH);
            //设置波特率
            cfsetispeed(&Opt, speed_arr[i]);
            cfsetospeed(&Opt, speed_arr[i]);
            
            //设置数据接收方式
            if(tcsetattr(fd, TCSANOW, &Opt) != 0)
            {
                perror("tcsetattr fd");
                return 1;
            }
            tcflush(fd, TCIOFLUSH);
        }
    }
    return 0;
}

/************************************
 *setParity 
 *	设置数据位、停止位和校验位
 *@para
 *	fd				文件标识。
 *	databits			数据位。(8 | 7)
 *	stopbits			停止位。(1 | 2)
 *	parity				校验位。(n:无校验位 | o:奇校验 | e:偶校验 | s:空格)
 *@return
 *	1:设置失败  0:设置成功
 ************************************/
int setParity(int fd, int databits, int stopbits, int parity, struct termios Opt)
{
    if(tcgetattr(fd, &Opt) != 0)
    {
        perror("tcgetattr fd");
        return 1;
    }
		Opt.c_cflag |= (CLOCAL | CREAD);       	//CLOCAL:忽略 modem 控制线。 
							//CREAD:	打开接受者。
    switch(databits)       				//设置数据位数
    {
	    case 7:
	        Opt.c_cflag &= ~CSIZE;			//屏蔽字符大小位
	        Opt.c_cflag |= CS7;			//选择7位数据位
	        break;
	    case 8:
	        Opt.c_cflag &= ~CSIZE;
	        Opt.c_cflag |= CS8;
	        break;
	    default:
	        fprintf(stderr, "Unsupported data size.\n");
	        return 1;
    }

    switch(parity)            //设置校验位
    {
    case 'n':
        Opt.c_cflag &= ~PARENB;        			//清除校验位
        Opt.c_iflag &= ~INPCK;        			//启用输入奇偶检测。  
        break;
    case 'o':
        Opt.c_cflag |= PARENB;       			//使能校验位
        Opt.c_cflag |= PARODD;        			//奇校验
        Opt.c_iflag |= INPCK;            		//启用输入奇偶检测。
        break;
    case 'e':
        Opt.c_cflag |= PARENB;       			//使能校验位
        Opt.c_cflag &= ~PARODD;        			//偶校验
        Opt.c_iflag |= INPCK;            		//启用输入奇偶检测。
        break;
    case 's':
        Opt.c_cflag &= ~PARENB;        			//清除校验位
        Opt.c_cflag &= ~CSTOPB;       			//设置一个停止位
        Opt.c_iflag |= INPCK;            		//启用输入奇偶检测。
        break;
    default:
        fprintf(stderr, "Unsupported parity.\n");
        return 1;    
    }

    switch(stopbits)        //设置停止位
    {
    case 1:
        Opt.c_cflag &= ~CSTOPB;
        break;
    case 2:
        Opt.c_cflag |= CSTOPB;
        break;
    default:
        fprintf(stderr, "Unsupported stopbits.\n");
        return 1;
    }

    Opt.c_cflag |= (CLOCAL | CREAD);

    Opt.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);	
 
    Opt.c_oflag &= ~OPOST;		//OPOST :启用具体实现自行定义的输出处理。
    Opt.c_oflag &= ~(ONLCR | OCRNL);    //OCRNL :将输出中的回车映射为新行符  
 						//ONLCR :(XSI) 将输出中的新行符映射为回车-换行。
    
    Opt.c_iflag &= ~(ICRNL | INLCR);		//ICRNL :将输入中的回车翻译为新行 (除非设置了 IGNCR)(否则当输入信号有 CR 时不会终止输入)。 
    						//INLCR :将输入中的 NL 翻译为 CR。(将收到的换行符号转换为Return)
    Opt.c_iflag &= ~(IXON | IXOFF | IXANY);	//IXON 	:启用输出的 XON/XOFF 流控制。
    						//IXOFF :启用输入的 XON/XOFF 流控制。
						//IXANY :(不属于 POSIX.1;XSI) 允许任何字符来重新开始输出。
    tcflush(fd, TCIFLUSH);			//清空输入缓存
    
    //MIN = 0 , TIME =0; 有READ立即回传否则传回 0,不读取任何字元
    Opt.c_cc[VTIME] = 0;        			
    Opt.c_cc[VMIN] = 0;        					
    
    if(tcsetattr(fd, TCSANOW, &Opt) != 0)	//设置数据接收方式
    {
        perror("tcsetattr fd");
        return 1;
    }

    return 0;
}


 

在win7使用串口助手时,能正常接收数据,没有数据错误出现。

在linux首次使用minicom时,能正常接收数据,没有数据错误出现。

然而在运行C以后,开始出现乱码:

乱码有如下两种情况:

1.特殊字符
 

2.接收时序错误

 

实在不知如何解决,后续问题将跟帖提出,特此求助。

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

linux 与 单片机 串口通信 的相关文章

  • gvim配置默认字体、配色等

    gvim配置默认字体 配色等 1 打开软件 xff0c 选择编辑 gt 启动设定 2 在其中添加自己的配置命令 xff0c 例如 xff1a filetype on 34 关闭自动备份 set noundofile set nobackup
  • Pixhawk原生PX4固件中的坑

    作为一名飞控开发的小学生 xff1a xff09 xff0c 最近入坑Pixhawk 43 PX4了 基于Pixhawk硬件平台进行二次开发 xff0c 有两套固件可以选择 xff1a Ardupilot系列也就是常说的APM固件 xff0
  • Linux(CentOS 6.3)设置VNC远程桌面连接

    刚研究Linux xff0c 选的是CentOS6 3的系统 xff0c 由于刚开始研究Linux xff0c 为了这个远程桌面连接走了不少弯路 xff0c 让大家见笑了 为了弄这个VNC远程连接 xff0c 网上找了很多资料 xff0c
  • python中的库和模块有什么区别_Python中模块(Module)和包(Package)的区别详解 python中的模块、库、包有什么区别?...

    python中的模块 xff0c 库 xff0c 包有什么区别 python中的模块 库 包有什么区别 python里面module package library三者有什么不同功能 安装 使用方法上有什么不同 python中的模块 库 包
  • 《大数据时代》读书笔记

    大数据时代 英国人Viktor Mayer Schonberger的著作 最重要的一点是介绍了一种思维模式的变化 主要观点 xff1a 大数据是指获取全部数据样本 xff0c 分析全部数据 xff0c 而不是只做抽样分析 大数据分析更关注相
  • power design初步使用01

    来自大佬 xff1a 别先生 点击即可查看原文 1 xff1a 入门级使用PowerDesigner软件创建数据库 xff08 直接上图怎么创建 xff0c 其他的概念知识可自行学习 xff09 我的PowerDesigner版本是16 5
  • http服务器demo,简单学习 vs下可以运行

    以下是使用C 43 43 在VS环境下编写的一个简单的HTTP服务器示例代码 xff1a include lt iostream gt include lt string gt include lt WS2tcpip h gt includ
  • power design初步使用02

    概念数据模型 逻辑数据模型 物理数据模型详解 出自 xff1a https www cnblogs com joechinochl articles 5252518 html 数据模型所描述的内容包括三个部分 xff1a 数据结构 数据操作
  • power design综合应用

    出自大佬宋辉 xff1a https www cnblogs com dfsxh articles 1295087 html Power Designer是Sybase公司的CASE 工具集 xff0c 使用它可以方便地对管理信息系统进行
  • LTE中layer的概念以及rank的概念

    原帖地址 xff1a https www mscbsc com bbs thread 293293 1 1 html https www mscbsc com askpro question83176 MIMO 表示多输入多输出 MIMO系
  • Endnote--在参考文献列表中添加DOI

    参考了此网站的内容 xff1a https www jianshu com p 11411c1c8495 1 在Endnote中给参考文献列表添加DOI的方法 xff1a Edit gt Output styles gt Eidt AJTR
  • t检验中的t值和p值是什么关系_t检验和p值的关系

    t检验中的t值和p值是什么关系 t检验和p值的关系 t检验 中通过样本均值 总体均值 样本标准差 样本量 可以计算出一个t值 xff0c 这个t值和p值有什么关系 xff1f 根据界值表又会查出一个数 xff0c 这个数和t值比较 xff0
  • ORACLE 之 标识符无效 问题总结及解决方案

    今天自己在家里做毕业设计 xff0c 遇到了ORACLE数据库的一些问题 xff0c 所以来总结一下 自己在上班的时候也遇到客户过提过这样的问题 xff0c 当时自己在百度上查了 xff0c 给客户解决完 自己也没有在意 xff0c 这次又
  • 数据结构总结

    本文目录 xff1a 数据结构分类1 数组2 栈3 队列4 链表5 树6 散列表7 堆8 图 数据结构分类 数据结构是指相互之间存在着一种或多种关系的数据元素的集合和该集合中数据元素之间的关系组成 常用的数据结构有 xff1a 数组 xff
  • Netty源码分析 (八)----- write过程 源码分析

    上一篇文章主要讲了netty的read过程 xff0c 本文主要分析一下write和writeAndFlush 主要内容 本文分以下几个部分阐述一个java对象最后是如何转变成字节流 xff0c 写到socket缓冲区中去的 pipelin
  • 接口调用方法详解

    接口调用方法详解 基础知识 接口定义 xff1a 接口是一组已命名的方法签名 所以接口里可以定义方法 属性 事件 xff0c 因为这些本质上都是方法 但是 xff0c 接口不能定义任何的构造函数 接口的可访问性 xff1a 类本身的修饰符可
  • C++ Primer Plus (Fifth Edition)pdf

    下载地址 xff1a 网盘下载 本书是久负盛名的C 43 43 经典教程 xff0c 其内容是C 43 43 大师Stanley B Lippman丰富的实践经验和C 43 43 标准委员会原负责人Jos e Lajoie对C 43 43
  • ROS----名字空间namespace

    1名称 1 1图资源名称Graph ResourceNames 图形资源名称提供了一个分层命名结构 xff0c 用于ROS计算图中的所有资源 xff0c 例如节点 xff0c 参数 xff0c 主题 和服务 这些名称在ROS中非常强大 xf
  • offboard Control

    1 使用mavlink based软件 没有ROS 2 使用无线连接 xff0c 没有ROS 3 Onboard computer 43 ROS 43 WiFi link recommended Control Methods 有下面两种方
  • 关于485通信不稳定问题解决方案[STM32产品问题]

    485通讯不稳定的问题 xff08 具体表现为有时能通讯上 xff0c 有时通讯不上 xff09 RS485在连接设备过多 通讯距离过长 双绞线质量差 xff0c 接线不规范 等 xff0c 都会导致通讯不稳定的问题 解决方案 xff1a

随机推荐

  • pixhawk与linux通信,模块 & 命令 – 通信 - PX4 开发指南

    mavlink 说明 该模块实现MAVLink协议 xff0c 该协议可以在串行链路或UDP网络连接上使用 它通过uORB与系统通信 xff1a 一些消息直接在模块中处理 例如 xff0c 任务协议 xff0c 其他则通过uORB发布 例如
  • ROS进阶学习笔记(11)- Turtlebot Navigation and SLAM - ROSMapModify - ROS地图修改

    ROS进阶学习笔记 xff08 11 xff09 Turtlebot Navigation and SLAM ROSMapModify ROS地图修改 ROS进阶学习笔记 xff08 11 xff09 Turtlebot Navigatio
  • STM32F103ZET6的中断管理

    1 STM32的中断 STM32的中断管理是属于内核部分的 xff0c 所以中断管理的寄存器也是属于内核组 xff0c 不属于芯片外设 xff0c 在查看相关资料的时候 xff0c 需要查看相对应的内核手册 STM32F103ZET6是Co
  • c语言strrchr()函数,C 库函数 – strrchr() ——jQuery中文网

    C 库函数 strrchr 描述 C 库函数 char strrchr const char str int c 在参数 str 所指向的字符串中搜索最后一次出现字符 c 一个无符号字符 的位置 声明 下面是 strrchr 函数的声明 c
  • 让我持续下去的理由

    牛仔裤 格子衬衫 运动鞋和双肩包 如果把这四个词放在一个人的身上 xff0c 似乎不用描述长相 xff0c 大家就对他的职业有了猜测 八成是个程序员吧 这个被笑称 月入五万过成月入五千样子 的群体 xff0c 以 收入高 脑回路简单 一成不
  • 一个工作多年的嵌入式工程师漫谈

    1 关于公司 公司是做什么的 xff1f 是属于项目型公司还是属于产品型公司 xff1f 我觉得公司分为两种 xff0c 一种做产品 xff0c 一种做项目 做产品的公司 xff0c 老板一般都会讲梦想 xff0c 情怀 梦想是什么 xff
  • 优秀APP启动页的设计思维

    一 APP启动项的定义 启动APP时 xff0c 第一画面一般都会是一张含有logo的图片 这张图片就叫做启动页面 二 APP启动页的设计方法 启动页设计要与主界页面要相似 xff0c 颜色 xff0c 风格等都不要有太大的跨度 xff0c
  • GAAS installlation on Ubuntu 18.04

    GAAS installlation on Ubuntu 18 04 GAAS 安装教程 xff1a document GAAS 中的安装教程中提到的 ROS Kinetic xff08 LTS 版 xff09 并不是最新的版本 xff0c
  • Django使用request和response对象

    size 61 large url http iluoxuan iteye com blog 1738522 url size 当请求一张页面时 xff0c Django把请求的metadata数据包装成一个HttpRequest对象 xf
  • 去哪儿网2015校招研发类笔试题

    从网上找到的题目 xff0c 自己做了一遍 1 二分查找 2 给定一个字符串 xff0c 得到这个字符串中首先出现两次的那个字符 方法 xff1a 可以用一个hash map或者数组来存储字符出现的次数 xff0c 一旦有一个出现了2次 x
  • 如何查看mysql镜像参数_Docker中查看Mysql数据库中的各环境参数

    通过官方的文档可以看到运行MySQL容器的命令是 xff1a docker run name some mysql e MYSQL ROOT PASSWORD 61 mypwd d mysql tag 如 xff1a docker run
  • 趣味离散数学题(巧猜围棋子)

    甲手里有一个围棋子 xff0c 要乙来猜棋子的颜色是白的还是黑的 xff0e 条件是 xff1a 只允许乙问一个只能回答 是 或 否 的问题 xff0c 但甲可以说真话 xff0c 也可以说假话 xff0e 问乙可以向甲提出一个什么问题 x
  • nrm安装与使用

    一 什么是nrm nrm 是一个 npm 源管理器 xff0c 允许你快速地在 npm源间切换 什么意思呢 xff0c npm默认情况下是使用npm官方源 xff08 使用npm config ls命令可以查看 xff09 xff0c 在国
  • Docker中的Dockerfile命令详解FROM RUN COPY ADD ENTRYPOINT...

    Dockerfile指令 这些建议旨在帮助您创建高效且可维护的Dockerfile FROM FROM指令的Dockerfile引用 尽可能使用当前的官方图像作为图像的基础 我们推荐Alpine图像 xff0c 因为它是严格控制的并且尺寸小
  • 视觉单词模型、词袋模型BoW

    多用于图像检索 分类 3 2 1 4 视觉单词模型 视觉词袋 xff08 BoVW xff0c Bag of Visual Words xff09 模型 xff0c 是 词袋 xff08 BoW xff0c Bag of Words xff
  • 卡尔曼滤波器推导与解析 - 案例与图片

    在SLAM的后端优化中有存在这两大类优化方法 滤波器优化和非线性优化 目前大多数基于视觉的SLAM算法都是采用的非线性优化的相关方法 如应用较多的G2O图优化框架 但是滤波器的方法仍然在某些情况下有应用 且以前不少论文都是基于滤波器优化的方
  • Ubuntu下使用USB串口接收数据

    环境 xff1a VMware xff0c Ubuntu 14 xff0c uBlox EVK M8L 1 把包含USB接口的uBlox插入PC中 xff0c 确定虚拟机右下角uBlox连接到虚拟机中 xff1b 2 在Ubuntu的终端中
  • docker ubuntu桌面

    docker run it rm p 8080 80 dorowu ubuntu desktop lxde vnc 转载于 https www cnblogs com fengjian2016 p 11417340 html
  • 三种蓝牙架构实现方案(蓝牙协议栈方案)

    蓝牙架构实现方案有哪几种 xff1f 我们一般把整个蓝牙实现方案叫做蓝牙协议栈 xff0c 因此这个问题也可以这么阐述 xff1a 蓝牙协议栈有哪些具体的架构方案 xff1f 在蓝牙协议栈中 xff0c host是什么 xff1f cont
  • linux 与 单片机 串口通信

    本人最近在尝试在linux下用串口与单片机通信 xff0c 虽然说网上资料例程五花八门 xff0c 但是缺乏严格的注释或者完整的实例 xff0c 或许本人能力有限 xff0c 某些问题无法理解 xff0c 在实际过程中遇到不少问题 xff0