串口通信(6)应用定时器中断+串口中断实现接收一串数据

news2024/11/25 21:19:03

 本文为博主 日月同辉,与我共生,csdn原创首发。希望看完后能对你有所帮助,不足之处请指正!一起交流学习,共同进步!

> 发布人:@日月同辉,与我共生_单片机-CSDN博客

> 欢迎你为独创博主日月同辉,与我共生点赞❤❤❤+关注👍+收藏🌹+评论☺。

系列专栏: CSDN-单片机串口通信学习系列🎁

> 我的格言是:“尽最大努力,做最好的自己!💪

要转载,请提前告知!!!

版权声明:本文为CSDN博主「日月同辉,与我共生」的原创文章,CSDN独一份。

10bc64f8fd3241a0948c08e1dcf000ca.png

目录

一、系统设计要求

二、系统设计原理

三、硬件设计

四、软件设计

4.1串口初始化

4.2接收中断

4.3定时器初始化

4.4定时器中断

4.5主程序

4.6发送数据

4.7清除缓存

4.8uart.h

五、结果展示

一、系统设计要求

最开始,单片机com1发送字符串Wait for Serial Communication Tset Start.和Please Send a string of data:给虚拟串口com3,接着虚拟串口发送多个数据(数据长度不定,但限制在20以下)给单片机com1,com1接收后重新将数据发送回com3。

二、系统设计原理

com3每发1个数据,单片机需要时间来接收,这个时间一般不会超过5ms,若超过5ms,则说明接收数据的工作已经完成,则将接收完成标志位recv_flag置1,最后在主程序中处理接收的数据(这里是重新发送给com3),因此可以利用c51单片机内部的定时器0定时1ms,定义计数变量recv_timer_cnt,该变量超过5,则说明接收完成,每接收一个数据,计数变量要清0。接收完成数据后,软件定时器变量清0(让定时器不再工作),同时重新发送数据给com3,并清除缓冲。

三、硬件设计

com1发送端TXD接com2发送端TXD,com1接收端RXD接com2接收端RXD。

虚拟终端RXD接TXD(因为单片机发送数据给com3,而虚拟终端可以理解为虚拟串口com3)。

2b076428a73546d18466361547f84710.png

四、软件设计

4.1串口初始化

串口工作方式为方式1(8位异步通信),定时器采用定时器T1的工作方式2(8位自动重载),波特率为9600bit/s,晶振频率为11.0592Mhz。接收一帧数据的初始化,采用中断法。

void UartInit(void)		//9600bps@11.0592MHz
{
	PCON &= 0x7F;		//波特率不倍速
	SCON = 0x50;		//8位数据,可变波特率
	TMOD &= 0x0F;		//设置定时器模式
	TMOD |= 0x20;		//设置定时器模式
	TL1 = 0xFD;			//设置定时初始值
	TH1 = 0xFD;			//设置定时重载值
	ET1 = 0;			  //禁止定时器中断
	ES=1;           //串口中断打开
	TR1 = 1;			  //定时器1开始计时
}

4.2接收中断

软件定时器标志位置1(定时器工作,开始定时)-->接收数据-->每接收一帧数据就计数清0

void ES_timers() interrupt 4 //接收中断
{
	if(RI)
	{ 
		RI=0; 
		start_timer=1;//1.开定时器标志位置1
        if(recv_cnt<MAX_REX_NUM)	//在规定字符长度范围内接收数据	
		{
			recv_buf[recv_cnt]=SBUF; //2.接收数据
			recv_cnt++; 
		}
		else
		{
			recv_cnt=MAX_REX_NUM;
		}
		recv_timer_cnt=0; //3.每接收一帧数据就计数清0
	}
}

4.3定时器初始化

定时1ms:

void Timer0_Init(void)		//1毫秒@11.0592MHz
{
	TMOD &= 0xF0;			//设置定时器模式
	TMOD |= 0x01;			//设置定时器模式
	TL0 = 0x66;				//设置定时初始值
	TH0 = 0xFC;				//设置定时初始值
	TF0 = 0;				//清除TF0标志
	ET0=1;
	TR0 = 1;				//定时器0开始计时
}

4.4定时器中断

计数变量recv_timer_cnt超过5时,说明接收完成,计数变量recv_timer_cnt清0。

void T0_timer() interrupt 1
{
	TR0=0;
	if(start_timer == 1)
	{
		recv_timer_cnt++;
		if(recv_timer_cnt>MAX_timer_cnt) //计数值超过规定范围说明接收完成
	  {
		  recv_timer_cnt=0; 
		  recv_cnt=0;
		  recv_flag=1;//接收完成标志位置1
	  }
	}
	TL0 = 0x66;				//设置定时初始值
	TH0 = 0xFC;				//设置定时初始值
	TR0=1;
}

4.5主程序

软件定时器变量清0(定时器不再工作)-->接收完成标志位清0-->发送数据-->清除缓存

void main()
{
	UartInit();     //调用串口初始化函数
	Timer0_Init();
	EA=1;           //总中断允许
	printf("Wait for Serial Communication Tset Start.\r\n");
	printf("Please Send a string of data:\r\n");
	while(1)
	{
		if(recv_flag)
		{
			start_timer=0;
			recv_flag=0;//接收完成标志位清0
			sendString(recv_buf);//发送数据
            clr_recvbuffer(recv_buf);//清除缓冲函数
		}
	}
}

4.6发送数据

void sendByte(unsigned char dat) //发送一帧数据功能函数
{
	SBUF=dat;
	while(!TI);
	TI=0;
}

void sendString(unsigned char *dat)//发送字符串函数
{
	while(*dat != '\0')
	{
		sendByte(*dat++);
	}
}

char putchar(char c)
{
	sendByte(c);
	return c;
}

4.7清除缓存

unsigned char *buf=recv_buf,则buf[i]=0是将第i+1个数据清0。

void clr_recvbuffer(unsigned char *buf)
{
	unsigned char i;
	for(i=0;i<MAX_REX_NUM;i++)
	{
	  buf[i]=0;
	}
}

4.8uart.h

#ifndef __UART_H__
#define __UART_H__

#include <reg51.h>
#include <stdio.h>

#define MAX_REX_NUM 20 //规定最大长度
#define MAX_timer_cnt 5 //定时计数规定值,超过该值,说明接收完成

extern unsigned char recv_buf[MAX_REX_NUM];//将数据存储到该数组中
extern unsigned char recv_cnt;
extern unsigned char start_timer;//软件定时器变量,=1说明定时器开始工作
extern unsigned char recv_timer_cnt;//软件定时器计数变量
extern unsigned char recv_flag;//接收完成标志位

void UartInit(void);
void sendByte(unsigned char dat);
void sendString(unsigned char *dat);
char putchar(char c);
void clr_recvbuffer(unsigned char *buf);

#endif

五、结果展示

最开始:显示正确

00bc45c236624e9fbe82e7296bce4cbe.png

为了测试能否接收到不同长度的数据,做了2次实验。

第一次实验(长度为8):1 2 abc b cc 6 7 8

9d935dea82ca44e0ae1824c196a407c1.png

92931fa34c744d6cadc5aedb9f4e319f.png

第二次实验(长度为4):1 2 abc 600

b9127ccfa2a3403197efe8ede5e766af.png

053a34320e5b413f80349cab904c4e89.png

下一文将着重判断数据帧头来接收一串数据,亲爱的读者敬请期待,下一文更精彩!!!

一日不读书,胸臆无佳想。我叫不白吃,喜欢我的,可以支持我,博主名叫@日月同辉,与我共生

@日月同辉,与我共生_单片机基础,单片机串口通信-CSDN博客@日月同辉,与我共生擅长单片机基础,单片机串口通信,等方面的知识,@日月同辉,与我共生关注stm32,c语言,51单片机,proteus,单片机领域.https://blog.csdn.net/LIN___IT?spm=1000.2115.3001.5343

 

 

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

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

相关文章

LICEcap使用教程

打开LICEcap&#xff0c;显示如下 点击Record&#xff0c;开始录制 点击Stop&#xff0c;停止录制 点击Record&#xff0c;进入该页面 display in animation&#xff08;在动画中显示&#xff09; title frame&#xff08;标题框&#xff09; - - - sec&#xff08;秒&…

网络安全应急响应工具(系统痕迹采集)-FireKylin

文章目录 网络安全应急响应工具(系统痕迹采集)-FireKylin1.FireKylin介绍【v1.4.0】 2021-12-20【v1.0.1】 2021-08-09 2.客户端界面Agent支持的操作系统FireKylinAgent界面使用方式比较传统方式与FireKylin比较无法可达目标的场景应用对比 3.使用教程设置语言Agent配置&#x…

Vue路由导航(replace、push、forward、back、go)

Vue路由导航&#xff08;replace、push、forward、back、go&#xff09; 先了解栈结构&#xff0c;再学习以下内容 栈的数据结构&#xff1a;先进后出&#xff0c;后进先出。原理&#xff1a;push将元素压入栈内&#xff0c;pop将元素弹出&#xff0c;栈有分别有栈底指针和栈顶…

Linux系统编程,socket通信编程实践练习(C语言)

文章目录 Linux系统编程&#xff0c;socket通信编程实践练习&#xff08;C语言&#xff09;1.服务端代码2.客户端代码 Linux系统编程&#xff0c;socket通信编程实践练习&#xff08;C语言&#xff09; 1.服务端代码 #include <stdio.h> #include <stdlib.h> #in…

Linux纯C串口开发

为什么要用纯C语言 为了数据流动加速&#xff0c;实现低配CPU建立高速数据流而不用CPU干预&#xff0c;避免串口数据流多次反复上升到软件应用层又下降低到硬件协议层。 关于termios.h 麻烦的是&#xff0c;在 Linux 中使用串口并不是一件最简单的事情。在处理 termios.h 标头…

Geth的进行合约部署和调用合约方法

环境 Ubuntu20 geth : 1.10.5-stable go: 1.17 前言 还未安装geth的读者可以参考这篇文章 Geth的安装并简单使用篇 我们需要进入geth交互式控制台进行操作 root192-168-19-133:~# geth --dev console INFO [10-03|22:25:29.918] Starting Geth in ephemeral dev mode... INFO…

list集合中的元素排序

目录 一、利用lambda对list集合排序 二、对对象集合操作&#xff0c;其实与基本类型集合操作类似 三、对 JSONArray 排序 一、利用lambda对list集合排序 先定义一个集合 List<Integer> list new ArrayList<>(); list.add(1); list.add(5); list.add(4); list…

基于SSM的酒店客房预定管理系统

基于SSM的酒店客房预定管理系统的设计与实现~ 开发语言&#xff1a;Java数据库&#xff1a;MySQL技术&#xff1a;SpringSpringMVCMyBatis工具&#xff1a;IDEA/Ecilpse、Navicat、Maven 系统展示 前台主页 客房详情 登录界面 管理员界面 用户界面 摘要 基于SSM&#xff08;…

逻辑分析仪与示波器选择

一、简介 逻辑分析仪是利用时钟从测试设备上采集和显示数字信号的仪器&#xff0c;最主要的作用在于时序判定。逻辑分析仪与示波器不同&#xff0c;它不能显示连续的模拟量波形&#xff0c;而只显示高低两种电平状态&#xff08;逻辑1和0&#xff09;。在设置了参考电压后&…

JDK环境变量配置

windows系统 1. win建 r 输入sysdm.cpl打开系统属性界面。选择高级栏目&#xff0c;点击环境变量菜单。 2. 选择系统变量中的新建&#xff0c;变量名输入JAVA_HOME&#xff0c;变量值输入jdk安装目录&#xff0c;例如&#xff1a;D:\Java\jdk1.8.0_91。 3. 选择编辑系统变量中…

容斥原理,多步容斥

容斥意义法 设计状态表示容斥的过程。比较简单的容斥题目一般可以容斥意义。 如果我们要求方案数的话&#xff0c;通常情况下我们的把限制视为两个方面&#xff0c;一方面是总限制&#xff0c;一方面是对于每个物品的限制&#xff0c;这样设集合 S i S_i Si​表示满足总限制以及…

VSCode 如何设置背景图片

VSCode 设置背景图片 1.打开应用商店&#xff0c;搜索 background &#xff0c;选择第一个&#xff0c;点击安装。 2. 安装完成后点击设置&#xff0c;点击扩展设置。 3.点击在 settings.json 中编辑。 4.将原代码注释后&#xff0c;加入以下代码。 // { // "workben…

中海达守护电力人员作业安全

近日&#xff0c;中海达为电网某换流站作业人员提供的160余套北斗高精度定位产品顺利完成交付。通过使用北斗高精度定位技术&#xff0c;帮助换流站实现了人员&#xff08;车辆&#xff09;位置实时定位、电子围栏实时预警、远程作业指导等应用效果&#xff0c;用高科技保障电网…

红米redmi note7救砖/线刷/ROOT教程

一直循环开机界面&#xff0c;需要刷机 准备 使用windows电脑安装如下 MiUsbDriver.exe电脑连接小米手机驱动。可以去https://www.miui.com/unlock/index.html下载压缩包&#xff0c;里面有这个程序小米ROM固件包找一个适合自己手机型号的的即可&#xff0c;官网也可以下载但…

3D RPG Course | Core 学习日记三:Navigation智能导航地图烘焙

前言 前面我们已经绘制好了一个简单的地图场景&#xff0c;现在我们需要使用Navigation给地图做智能导航&#xff0c;以实现AI自动寻路&#xff0c;以及设置地图的可行走区域以及不可行走区域&#xff0c;Navigation的基础知识、原理、用法在Unity的官方文档&#xff0c;以及网…

Modelsim 使用教程(2)——Basic Simulation

一、概述 在本文中&#xff0c;我们将介绍Modelsim基本的仿真流程&#xff0c;包括有&#xff1a; Create the Working Design Library&#xff08;创建工具库&#xff09; Compile the Design Units&#xff08;编译设计单元&#xff09; Optimize the Design&#xff08;优化…

单工通信、半双工通信、全双工通信分别是什么?

单工通信&#xff1a; 单工通信是一种单向传输数据的通信方式&#xff0c;只允许信息在一个方向上流动。在单工通信中&#xff0c;通信的两个节点中的一个节点只能作为发送方&#xff0c;而另一个节点只能作为接收方。发送方只负责发送数据&#xff0c;而接收方只负责接收数据&…

LLMs之Agent之AutoGen:AutoGen的简介、安装、使用方法之详细攻略

LLMs之Agent之AutoGen&#xff1a;AutoGen的简介、安装、使用方法之详细攻略 目录 AutoGen的简介、安装、使用方法 1、多Agent对话框架 2、AutoGen的对话流程 3、增强的LLM推理 AutoGen的安装 1、安装 2、快速测试 AutoGen的使用方法 1、基础用法 (1)、启动两个代理之…

C++:map和set的基本使用

文章目录 搜索模型关联式容器setset的基本使用set的其他使用 multisetmapmap的基本使用map中的[] multimap 搜索模型 在实际搜索中有两个搜索模型&#xff1a;Key的搜索模型和Key/Value的搜索模型 Key的搜索模型&#xff1a; 简单来说就是在一个搜索树&#xff0c;搜索树中的…

大桌子安装笔记

单位弄了个服务器&#xff0c;里面全是虚拟机&#xff0c;自己也学着建了一个测试用的虚拟机&#xff0c;不知道干点啥好&#xff0c;朋友说做个网盘吧&#xff0c;就用大桌子。 于是&#xff0c;干起来&#xff0c;不会配制&#xff0c;就跟朋友一步一步学起来。 他说&#…