51单片机应用开发(进阶)---串口接收字符命令

news2024/12/26 18:24:28

实现目标

1、巩固UART知识;

2、掌握串口接收字符数据;

3、具体实现目标:(1)上位机串口助手发送多字符命令,单片机接收命令作相应的处理(如:openled1  即打开LED1;closeled1  即关闭LED1;)


一、主要知识点

1.1 字符串定义

字符串是由字母、数字、下划线和空格等各种字符组成的一串字符,是一个常量。由一对双引号括起来。字符串的末尾都默认有一个'\0'的结束符。

        C语言存储字符,其实是存储字符所对应的ASCII码,因此字符可以以%c或者%d输出均可以,需要作为常识记住的是:字符'0'对应的ASCII码为48,字符'A'对应的ASCII码为65,字符'Z'对应的ASCII码为90,字符'a'对应的ASCII码为97,字符'z'对应的ASCII码为122; 字符类型char占用1个字节。

      用来存放字符的数组称为字符数组,字符数组实际上是一系列字符的集合,也就是字符串,C语言通常有两种表示字符串的方法:

第一种:定义一个字符数组;char  str[]="abcd";  

 第二种:字符串指针;    const  char * str="hello"; 这种方式不可通过对字符指针解引用进行修改字符串,因为字符串常量不可修改!

        这二者都是使用字符串常量对其进行初始化,从指针角度理解,本质一样,不论是字符数组,还是字符指针,str都代表字符串首字符的起始地址。区别在于:字符数组名为常量,常量不可以作左值!字符指针是变量,但是字符指针不可以进行解引用再修改值。

获取字符串的长度

方法一:sizeof()运算符

方法二:strlen()函数

求字符串“abcd”的长度

int str[]={"abcd"}

int len1=sizeof(str)/sizeof(str[0);

int len2=strlen(str);

解析:结果len1=5;len2=4;

sizeof 和strlen总结

①sizeof是运算符;strlen是库函数,包含在string.h头文件中

②sizeof功能是获得所建立对象的字节大小;strlen函数是获得字符串所占内存的有效字节数;

③sizeof运算符的参数可以是数组、指针、对象、函数等;strlen函数的参数必须是以'\0'结尾的字符串的指针;

④sizeof运算符计算大小在编译时就完成,因此不能用来计算动态分配内存大小;strlen函数结果要在运行时才能计算出来。

1.2 strstr 函数应用

(1) 头文件

#include <string.h>

(2) 函数原型

char *strstr(const char *haystack, const char *needle);

(3) 函数作用

1、strstr() 函数搜索一个字符串在另一个字符串中的第一次出现。
2、找到所搜索的字符串,则该函数返回第一次匹配的字符串的地址;
3、如果未找到所搜索的字符串,则返回NULL。

情景一:

用于单次匹配
返回的是匹配成功的字符串以及后面的字符串

#include <stdio.h>
#include <string.h>
main()
{
    char *s="GoldenGlobalView";
    char *l="lob";
    char *p;
    p=strstr(s,l);
    if(p)
        printf("%s",p);
    else
        printf("NotFound!");
    return 0;
}

二、原理图设计

STC89C52RC/RD+系列单片机串行口对应的硬件部分对应的管脚是P3.0/RxD和P3.1/TxD。

        

三、程序设计

3.1单片机接收上位机PC的命令

参数:波特率9600 ;SMOD为0,波特率不加倍;定时器1,工作模式2,8位自动重装。

具体功能:发字符 a,开启LED1; 发字符 b,关闭LED1;

#include <REGX52.H>
 
#define FOSC 11059200L      //System frequency
#define BAUD 9600           //UART baudrate

sbit LED1 = P2^0;

int cmd = 0;//命令 
bit flag = 0;

void Uart_send(unsigned char dat);
void Uart_send_str(unsigned char *p);
void Delay500ms();
 
void  main()
{
    PCON &= 0x7F;		    //波特率不倍速
    SCON = 0x50;            //8-bit variable UART
    TMOD = 0x20;//0010 0000 //Set Timer1 as 8-bit auto reload mode
    TH1 = TL1 = -(FOSC/12/32/BAUD); //Set auto-reload vaule
    TR1 = 1;                //Timer1 start run
    ES = 1;                 //Enable UART interrupt
    EA = 1;                 //Open master interrupt switch
    while(1)
	{
		if(flag == 1)//查询是否接收一字节的命令
        {
			flag = 0;//标志位清零0
			if(cmd == 'a')
			{
				LED1 = 0;
			    Uart_send(cmd);
			}
			else if(cmd == 'b')
			{
				LED1 = 1;
			    Uart_send(cmd);
			}		
		}
	}
}
void Uart_send(unsigned char dat)
{
     SBUF = dat;
	 while(!TI);
	 TI = 0;
}
 
void Uart_send_str(unsigned char *p)
{
    while(*p!='\0')
    {
       Uart_send(*p);	
       p++;	
    }
}
 
void Uart_Isr() interrupt 4 
{
    if (RI == 1)
    {
        RI = 0;             //Clear receive interrupt flag   
        flag = 1;
		cmd = SBUF; 
    }
    if (TI == 1)
    {
        TI = 0;             //Clear transmit interrupt flag
    }
}
 
void Delay500ms()		//@11.0592MHz
{
	unsigned char i, j, k;
	i = 4;
	j = 129;
	k = 119;
	do
	{
		do
		{
			while (--k);
		} while (--j);
	} while (--i);
}
 

3.2  字符串命令控制LED

具体功能:发字符串open,开启LED1; 发字符串close,关闭LED1;

#include <REGX52.H>
#include <stdio.h> 
#include <string.h> 
 
#define FOSC 11059200L      //System frequency
#define BAUD 9600           //UART baudrate
 
sbit LED1 = P2^0; 
 
typedef struct
{
	unsigned char buff[32];    //用于存放接收到的字符串
	unsigned char flag;        //接收完成中断标志位
	unsigned char len;         //用于偏移字符串指针,可以理解为长度,如果buff设得很长,对应这里需要改成u16
}REC;
 
REC UART_rec={0};              //初始化结构体 
const char *substr1 = "open"; 
const char *substr2 = "close"; 

void Uart_send(unsigned char dat);
void Uart_send_str(unsigned char *p);
void Delay500ms();
 
void  main()
{
	PCON &= 0x7F;		    //波特率不倍速
    SCON = 0x50;            //8-bit variable UART
    TMOD = 0x20;//0010 0000 //Set Timer1 as 8-bit auto reload mode
    TH1 = TL1 = -(FOSC/12/32/BAUD); //Set auto-reload vaule
    TR1 = 1;                //Timer1 start run
    ES = 1;                 //Enable UART interrupt
	TI = 1;	
    EA = 1;                 //Open master interrupt switch
		while(1)
		{
		   if(UART_rec.flag == 1)//若接收完成
			{
				if (strstr(UART_rec.buff,substr1)!= NULL)
            {
					printf("开启LED1\n"); 
					LED1 = 0;							
            }
            else if(strstr(UART_rec.buff,substr2)!= NULL)
            {
					printf("关闭LED1\n"); 
					LED1 =1;									
            }
			
				 // printf("接收到了:%s\r\n",UART_rec.buff);
				    UART_rec.flag = 0;     //接收标志位清零,准备接收下一字符串  
		}
	}
}


void Uart_send(unsigned char dat)
{
		SBUF = dat;
		while(!TI);
		TI = 0;
}
 
void Uart_send_str(unsigned char *p)
{
    while(*p!='\0')
    {
       Uart_send(*p);	
       p++;	
    }
}
 
void Uart_Isr() interrupt 4 
{
	  unsigned char temp = 0;	
    if (RI == 1)
    {	
				RI = 0;                //清除接收中断标志	
				temp = SBUF;	
			
				if(temp=='\r'||temp=='\n'||UART_rec.len >= 32)	
				{
					UART_rec.buff[UART_rec.len]='\0';
					UART_rec.flag = 1 ;	//数据包接收完成标志
					UART_rec.len=0; 	  //为下一个数据包做准备
				}
				else
				{
					UART_rec.buff[UART_rec.len++] = temp;
				}
	 }
}


void Delay500ms()		//@11.0592MHz
{
	unsigned char i, j, k;
	i = 4;
	j = 129;
	k = 119;
	do
	{
		do
		{
			while (--k);
		} while (--j);
	} while (--i);
}
 

四、实验效果

五、仿真实现

5.1单片机接收的字符命令仿真


总结

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

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

相关文章

【查询基础】.NET开源 ORM 框架 SqlSugar 系列

&#x1f4a5; .NET开源 ORM 框架 SqlSugar 系列 &#x1f389;&#x1f389;&#x1f389; 【开篇】.NET开源 ORM 框架 SqlSugar 系列【入门必看】.NET开源 ORM 框架 SqlSugar 系列【实体配置】.NET开源 ORM 框架 SqlSugar 系列【Db First】.NET开源 ORM 框架 SqlSugar 系列…

基于Matlab BP神经网络的电力负荷预测模型研究与实现

随着电力系统的复杂性和规模的不断增长&#xff0c;准确的电力负荷预测对于电网的稳定性和运行效率至关重要。传统的负荷预测方法依赖于历史数据和简单的统计模型&#xff0c;但这些方法在处理非线性和动态变化的负荷数据时&#xff0c;表现出较大的局限性。近年来&#xff0c;…

LeetCode - #150 逆波兰表达式求值

文章目录 前言1. 描述2. 示例3. 答案关于我们 前言 我们社区陆续会将顾毅&#xff08;Netflix 增长黑客&#xff0c;《iOS 面试之道》作者&#xff0c;ACE 职业健身教练。&#xff09;的 Swift 算法题题解整理为文字版以方便大家学习与阅读。 LeetCode 算法到目前我们已经更新…

mysql基础学习1

useradd -r -g mysql -s /bin/false mysql (-r)系统用户 不能登录 A temporary password is generated for rootlocalhost: d>#jT7rfoaz) 看是否启动 看进程 端口 直接连接 看日志 varchar (20) char(20)更耗空间 create table student_info(id int,name varchar(20),s…

PPT怎样做的更加精美

目录 PPT怎样做的更加精美 3D的GIF图片 3维空间图​编辑 结果有明显的对比 阅读高质量文献,采用他们的图 PPT怎样做的更加精美 3D的GIF图片 3维空间图 结果有明显的对比

Marvell第四季度营收预计超预期,定制芯片需求激增

芯片制造商Marvell Technology&#xff08;美满电子科技&#xff09;&#xff08;MRVL&#xff09;在周二发布了强劲的业绩预告&#xff0c;预计第四季度的营收将超过市场预期&#xff0c;得益于企业对其定制人工智能芯片的需求激增。随着人工智能技术的快速发展&#xff0c;特…

爬虫第四篇:Xpath 路径表达式全解析:从网页基础到爬取百度贴吧图片实战

简介&#xff1a;本文围绕 Xpath 路径表达式展开讲解&#xff0c;先是介绍了网页相关基础如 html、css、vue 以及前后端分离的概念与示例&#xff0c;包括各部分的结构、作用及简单代码展示&#xff0c;随后详细阐述了 xml 的节点关系、选取节点、谓语等理论知识&#xff0c;最…

使用lumerical脚本语言创建弯曲波导并进行数据分析(纯代码实现)

本文使用lumerical脚本语言创建弯曲波导、设置有限差分时域(FDTD)模拟、改变波导弯曲半径计算损耗、绘制图像展示电场强度分布情况及对具有不同弯曲半径的波导进行一系列模拟和分析操作(代码均有注释讲解)。 一、创建弯曲波导 1.1 基本结构讲解 (1)包层(Clad) 在波导结…

HarmonyOS4+NEXT星河版入门与项目实战(23)------实现手机游戏摇杆功能

文章目录 1、案例效果2、案例实现1、代码实现2、代码解释4、总结1、案例效果 2、案例实现 1、代码实现 代码如下(示例): import router from @ohos.router import {ResizeDirection } from @ohos.UiTest import curves

Redis面试专题-持久化

前言 开始Redis面试知识的复习和资料的收集&#xff08;收集和参考了网上的优质文章&#xff09;&#xff0c;本篇文章会不断更新&#xff0c;本系列文章主要分为两部分&#xff0c;一部分是该专题所涉及的相关基础知识&#xff0c;另一部分是面试题与思考题&#xff0c;大部分…

Blender导入下载好的fbx模型像的骨骼像针戳/像刺猬

为什么我下载下来的骨骼模型和我自己绑定的模型骨骼朝向完全不一样 左边是下载的模型 右边是我自己绑定的模型 左边的模型刚刚感觉都是像针一样往外戳的&#xff0c;像刺猬一样那种。 解决方法勾选自动骨骼坐标系

Ubuntu22.04上kdump和crash的使用

0.前言 1.引用&#xff1a; 解决Linux内核问题实用技巧之 - Crash工具结合/dev/mem任意修改内存-腾讯云开发者社区-腾讯云 解决Linux内核问题实用技巧之-dev/mem的新玩法-腾讯云开发者社区-腾讯云 ubuntu内核转储分析——kdump和crash的下载和使用_ubuntu kdump-CSDN博客 U…

linux安全-firewalld防火墙-基础讲解

目录 一、 防火墙技术分类 二、 firewalld 三、 firewalld支持的类型的NAT 四、 富语言 五、 firewalld配置方式 六、 firewall-cmd命令 七、 小实验 这篇文章将对 firewalld 防火墙的基础知识进行介绍 firewalld简介&#xff1a;firewalld的作用是为包过滤机制提供匹配…

Android中使用NSD扫描,实现局域网内设备IP的发现

0. 前言 本文介绍了什么是NSD协议&#xff0c;并介绍了如何在Android中实现NSD的服务端和客户端&#xff0c;实现局域网内的设备发现功能。 1. NSD是什么 在Android开发中&#xff0c;NSD&#xff08;Network Service Discovery&#xff09;是一种用于在局域网内发现其他设备…

ROS2 系列学习教程(总目录)

ROS2Learning ROS1 系列学习教程(总目录) 一、ROS2 简介 1.1 ROS2简介及学习资源汇总 二、ROS2 基础 2.1 ROS2安装详细教程&#xff08;以Humble为例&#xff09; 2.2 ROS2 构建系统 colcon 介绍、安装与使用 2.3 ROS2 与 ROS1 编码方式对比 ROS2 与 ROS1 编码方式对比&am…

万字长文解读深度学习——VQ-VAE和VQ-VAE-2

&#x1f33a;历史文章列表&#x1f33a; 深度学习——优化算法、激活函数、归一化、正则化 深度学习——权重初始化、评估指标、梯度消失和梯度爆炸 深度学习——前向传播与反向传播、神经网络&#xff08;前馈神经网络与反馈神经网络&#xff09;、常见算法概要汇总 万字长…

Vue 组件通信全面解析

Vue 组件通信全面解析&#xff1a;方式、原理、优缺点及最佳实践 在 Vue 开发中&#xff0c;组件通信是一个重要的核心问题。随着应用复杂度的增加&#xff0c;如何在组件之间有效传递数据、触发事件&#xff0c;直接影响代码的可维护性和可扩展性。Vue 提供了多种组件通信方式…

对力扣77组合优化的剪枝操作的理解

77. 组合 代码随想录放出了这一张图 我乍一看觉得想当然,但是仔细想想,又不知道以下剪枝代码作何解释,因此我想通过这篇文章简要解释一下 class Solution { private:vector<vector<int>> result;vector<int> path;void backtracking(int n, int k, int sta…

SpringMVC其他扩展

一、全局异常处理机制: 1.异常处理两种方式: 开发过程中是不可避免地会出现各种异常情况的&#xff0c;例如网络连接异常、数据格式异常、空指针异常等等。异常的出现可能导致程序的运行出现问题&#xff0c;甚至直接导致程序崩溃。因此&#xff0c;在开发过程中&#xff0c;…

运行 GreatSQL 时为什么要求关闭透明大页

在大部分运维规范中&#xff0c;一般都会要求在运行 GreatSQL/MySQL 的环境中要关闭透明大页&#xff0c;那么到底什么是透明大页&#xff0c;为什么要关闭&#xff0c;打开有什么风险吗&#xff1f; 在此之前&#xff0c;我也是有点懵的&#xff0c;本文试着回答这个疑问&…