设备间的指令通信

指令通信的概念

在这里插入图片描述
要进行设备和设备之间的交流就需要通过串口发送数据进行交流 而串口发送简单的数据只需要传输介质
但是要发送复杂的数据就需要介质和传输的规则了
在这里插入图片描述
三种应用场景
在这里插入图片描述
比如在上位机和mcu之间 通过上位机管理控制器 从而控制电池
在这里插入图片描述
单片机和单片机之间 用户输入数据到达控制的单片机 把指令给到负责图形显示的单片机 控制单片机和图形显示单片机就需要串口来进行数据的通信和交流

在这里插入图片描述
单片机要实现没有的功能需要外部模块的实现 也需要串口来进行通信和数据的传输

指令通信的方案概述

在这里插入图片描述
无论是什么情景都需要类似于主机给从机发指令 从机接收完成任务发送数到主机 这个过程 所以指令的学习很重要

单字符指令在这里插入图片描述
单个字符 如果通过串口给小车发w就是前进一米
dw就是右转前进一米 类似与这样 但是也有缺陷 就是如果想让小车前进0.5米就无法实现
字符串指令
在这里插入图片描述
如walk forwa 1就是表明走 前进 一格 turn left 向左转 通过发送不同的字符就可以发送不同的指令
但是效率有点低
二进制指令
在这里插入图片描述
二进制指令的格式为一个字节的同步码 两个字节的消息ID 一个字节的数据长度 一个字节的头校验 n个字节的数据 一个字节的数据校验
同步码 就是标志着二进制指令的开始 接收方看到这个0x5a就知道要从这里开始向后接收二进制指令了
消息ID 表示二进制指令的身份和作用 如图中的行走
0x0000代表行走 0x0001代表转弯
数据长度就代表数据的长度
数据 数据的长度不确定 根据消息的多少不确定 接收方在读取到数据长度了之后就知道要接受多长的数据了
头校验 在这里插入图片描述
把指令分为头和数据两个部分 校验头的正确或者错误
比如说有一个行走指令 行走的方向和行走的距离 就可以把这两个参数放到数据里面进行传输
那么就可以给小车设置一套指令集就是如行走消息ID就是0x0000 参数就为两个DIR方向 DIS 距离 如果想要向前就传入数0x000 向后就传入0x01 距离就传入1代表走1m 转弯也是如此在这里插入图片描述
注意第三个指令 在我们使用二进制传输的时候肯定是低字节在前高字节在低 如0x00 01 肯定是0x00在前 0x01在后 所以传输时是0x01在前 0x00在后 效率高很多 准确性也高很多
AT指令
在这里插入图片描述
总结
在这里插入图片描述

单字符指令

闪灯实验
在这里插入图片描述
具体就是led灯在两种模式下进行切换 状态变量stage 在case语句中 在这里插入图片描述
如在b点需要由亮起转为熄灭状态 判断时间是否超时 如调用函数PAL_GetTick()获得此时b点的时间 如果这个时间大于上次切换状态的时间(a点由熄灭转化为亮起的状态的时间)也就是这个黄色段内的时间在这里插入图片描述
加上需要亮起的时间onTime 就熄灭 然后获取当前的时间 切换状态 超时条件 b点时间大于a点由熄灭转化为亮起的状态的时间+需要亮起的时间onTime
也就是程序case1的代码
在这里插入图片描述
通过这四个函数就可以控制亮灭的不同 控制不同模式的闪烁

单字符指令实验

在这里插入图片描述
指令进程的编码思路
在这里插入图片描述
首先需要明确进程函数 有两个并行的任务一个是LED闪烁 一个是指令的接收
一个接受命令的初始化 一个中断函数(接收命令是通过串口 使用PAL库接收数据需要用到中断)
接受指令的函数的编写
首先需要从串口读取一个字节 超时时间为0因为在进程函数中不允许使用延时 所以设置超时时间TimeOut为0 然后判断是否接收到的数据是有效的 然后把接收到的数据强制类型转换为字符类型(因为我们接收到的指令是字符指令) 然后判断字符执行命令
app_blinky_led.c

#include "app_blinky_led.h"
#include "stm32f10x_pal.h"

static uint32_t onTime = 10;
static uint32_t offTime = 100;
static uint8_t stage = 0;
static uint64_t lastToggleTime = 0;

void App_BlinkyLED_SetOnTime(uint32_t Val)
{
	onTime = Val;
}

void App_BlinkyLED_SetOffTime(uint32_t Val)
{
	offTime = Val;
}

uint32_t App_BlinkyLED_GetOnTime(void)
{
	return onTime;
}

uint32_t App_BlinkyLED_GetOffTime(void)
{
	return offTime;
}

void App_BlinkyLED_Init(void)
{
	GPIO_InitTypeDef GPIO_InitStruct;
	
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);
	GPIO_InitStruct.GPIO_Pin = GPIO_Pin_13;
	GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_OD;
	GPIO_InitStruct.GPIO_Speed = GPIO_Speed_2MHz;
	GPIO_Init(GPIOC, &GPIO_InitStruct);
}

void App_BlinkyLED_Proc(void)
{
	switch(stage)
	{
		case 0: // 当前是熄灭状态
			if(PAL_GetTick() >= lastToggleTime + offTime)
			{
				GPIO_ResetBits(GPIOC, GPIO_Pin_13);
				lastToggleTime = PAL_GetTick();
				stage = 1;
			}
			break;
		case 1: // 当前是点亮状态
			if(PAL_GetTick() >= lastToggleTime + onTime)
			{
				GPIO_SetBits(GPIOC, GPIO_Pin_13);
				lastToggleTime = PAL_GetTick();
				stage = 0;
			}
			break;
		default:
			break;
	}
}

app_blinky_led.h

#ifndef __APP_BLINKY_LED_H__
#define __APP_BLINKY_LED_H__

#include "stm32f10x.h"

void App_BlinkyLED_Init(void);
void App_BlinkyLED_Proc(void);
void App_BlinkyLED_SetOnTime(uint32_t Val);
void App_BlinkyLED_SetOffTime(uint32_t Val);
uint32_t App_BlinkyLED_GetOnTime(void);
uint32_t App_BlinkyLED_GetOffTime(void);

#endif

app_cmd.c

#include "app_cmd.h"
#include "stm32f10x_pal_usart.h"
#include "app_blinky_led.h"

static PalUSART_HandleTypeDef hUSART3;

void App_Cmd_Init(void)
{
	hUSART3.Init.USARTx = USART3;
	hUSART3.Init.BaudRate = 115200;
	hUSART3.Init.USART_WordLength = USART_WordLength_8b;
	hUSART3.Init.USART_StopBits = USART_StopBits_1;
	hUSART3.Init.USART_Parity = USART_Parity_No;
	hUSART3.Init.USART_Mode = USART_Mode_Tx | USART_Mode_Rx;
	hUSART3.Init.USART_IRQ_PreemptionPriority = 0;
	hUSART3.Init.USART_IRQ_SubPriority = 0;
	hUSART3.Init.RxBufferSize = 128;
	hUSART3.Init.TxBufferSize = 128;
	PAL_USART_Init(&hUSART3);
}

void App_Cmd_Proc(void)
{
	int16_t tmp;
	
	tmp = PAL_USART_ReceiveByte(&hUSART3, 0);
	
	if(tmp >=0)
	{
		char c = (char)tmp;
		switch(c)
		{
			case 'q': App_BlinkyLED_SetOnTime(App_BlinkyLED_GetOnTime()+10); break;
			case 'w': App_BlinkyLED_SetOnTime(App_BlinkyLED_GetOnTime()-10); break;
			case 'e': App_BlinkyLED_SetOffTime(App_BlinkyLED_GetOffTime()+10); break;
			case 'r': App_BlinkyLED_SetOffTime(App_BlinkyLED_GetOffTime()-10); break;
		}
		PAL_USART_Printf(&hUSART3, "On=%dms, Off=%dms\r\n", App_BlinkyLED_GetOnTime(), App_BlinkyLED_GetOffTime());
	}
}

void USART3_IRQHandler(void)
{
	PAL_USART_IRQHandler(&hUSART3);
}

app_cmd.h

#ifndef __APP_CMD_H__
#define __APP_CMD_H__

#include "stm32f10x.h"

void App_Cmd_Init(void);
void App_Cmd_Proc(void);

#endif

main.c

#include "stm32f10x.h"
#include "stm32f10x_pal.h"
#include "app_blinky_led.h"
#include "app_cmd.h"

int main(void)
{
	PAL_Init();
	
	App_BlinkyLED_Init();
	App_BlinkyLED_SetOnTime(50);
	App_BlinkyLED_SetOffTime(50);
	App_Cmd_Init();
	
	
	while(1)
	{
		App_BlinkyLED_Proc();
		App_Cmd_Proc();
	}
}

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

MySQL实战45讲-第1-2讲-一条SQL查询语句是如何执行的? 一条SQL更新语句是如何执行的

大体来说,MySQL可以分为Server层和存储引擎层两部分 Server层:Server层包括连接器、查询缓存、分析器、优化器、执行器等。以及所有的内置函数(如日期、时间、数学和加密函数等),所有跨存储引擎的功能都在这一层实现&a…

添加cpack install功能

修改最外层的CMakeLists.txt, 添加几行代码: # If GNUInstallDirs is not included, CMAKE_INSTALL_BINDIR is empty. include(GNUInstallDirs)# it must go before project in order to work set(CMAKE_INSTALL_PREFIX "${PROJECT_SOURCE_DIR}" CACHE …

记录一下快速上手Springboot登录注册项目

本教程需要安装以下工具,如果不清楚怎么安装的可以看下我的这篇文章 链接: https://blog.csdn.net/qq_30627241/article/details/134804675 管理工具: maven IDE: IDEA 数据库: MySQL 测试工具: Postman 打开IDE…

若依角色与权限字符串

文章目录 一、简介1.基于权限字段串2.基于角色 二、若依的权限控制1.介绍2.实践 一、简介 基于权限字段串和基于角色的访问控制是两种不同的权限管理模型,它们各自有其优点和应用场景。下面是这两种模型的基本概念: 1.基于权限字段串 基于权限字段串&…

产品成本收集器流程演示

感谢大佬的文章,我只是一个翻译搬运工,原文地址:产品成本收集器 概述 SAP 令人兴奋的部分之一是它在不同操作模块之间的集成程度。使用产品成本收集器来跟踪生产就是一个很好的例子。在本博客中,我计划遵循产品成本收集器流程&a…

Unity中C#如何访问并修改Shader材质

文章目录 前言一、我们用点击按钮来改变Shader传入的颜色值1、在渲染GUI时,绘制一个按钮2、我们使用一个公共的成员变量存储需要进行修改的游戏对象3、最后给绘制的按钮点击增加逻辑即可 二、测试使用的代码1、Shader代码:2、C#脚本 前言 我们写好Shade…

揭秘C语言结构体:通往内存对齐的视觉之旅

揭秘C语言结构体:通往内存对齐的视觉之旅 引言 在C语言的编程旅程中,结构体(structs)是一个关键而强大的概念。结构体不仅允许我们组织和存储不同类型的数据,而且通过深入了解内存对齐,我们可以更好地优化…

[b01lers2020]Life on Mars 一个接口的sql schema.schemate表

这里还是很简单的 啥也没有 然后抓包看看 发现传递参数 直接尝试sql 然后如果正确就会返回值 否则 返回1 chryse_planitia union select database(),version() 发现回显 直接开始注入 chryse_planitia union select database(),version()chryse_planitia union select data…

在UniApp中使用uni.makePhoneCall方法调起电话拨打功能

目录 1.在manifest.json文件中添加权限 2. 组件中如何定义 3.如何授权 4.相关知识点总结 1.在manifest.json文件中添加权限 {"permissions": {"makePhoneCall": {"desc": "用于拨打电话"}} }2. 组件中如何定义 <template>…

【论文合集】在非欧空间中的图嵌入方法(Graph Embedding in Non-Euclidean Space)

文章目录 1. Hyperbolic Models1.1 Hyperbolic Graph Attention Network1.2 Poincar Embeddings for Learning Hierarchical Representations.1.3 Learning Continuous Hierarchies in the Lorentz Model of Hyperbolic Geometry1.4 Hyperbolic Graph Convolutional Neural Net…

推荐一个FL Studio最适配的midi键盘?

Hello大家好&#xff01;好消息&#xff01;好消息&#xff01;特大好消息&#xff01; 水果党们&#xff01;终于有属于自己的专用MIDI键盘啦&#xff01; 万众期待的Novation FLKEY系列 正式出炉&#xff01; 做编曲和音乐制作的朋友们&#xff0c;对水果软件FLSTUDIO应该…

CopyOnWriteArraySet怎么用

简介 CopyOnWriteArraySet是一个线程安全的无序集合&#xff0c;它基于“写时复制”的思想实现。它继承自AbstractSet&#xff0c;可以将其理解成线程安全的HashSet。 CopyOnWriteArraySet在读取操作比较频繁、写入操作相对较少的情况下可以提高程序的性能和可靠性。它的线程…

Rook-ceph(1.12.9最新版)

官网的步骤 git clone --single-branch --branch v1.12.9 https://github.com/rook/rook.git cd rook/deploy/examples kubectl create -f crds.yaml -f common.yaml -f operator.yaml kubectl create -f cluster.yaml整理后的已经替换好的国内镜像的 git clone https://gite…

C++——内部类

class A { public:class B//内部类{private:int _b;}; private:int _a; }; int main() {cout << sizeof(A) << endl;return 0; } 概念及特征&#xff1a; 如果一个类定义在另一个类的内部&#xff0c;这个类就叫内部类。注意此时这个内部类是一个独立的类&#x…

前缀和 LeetCode1423. 可获得的最大点数

几张卡牌 排成一行&#xff0c;每张卡牌都有一个对应的点数。点数由整数数组 cardPoints 给出。 每次行动&#xff0c;你可以从行的开头或者末尾拿一张卡牌&#xff0c;最终你必须正好拿 k 张卡牌。 你的点数就是你拿到手中的所有卡牌的点数之和。 给你一个整数数组 cardPoi…

图的广度优先搜索(数据结构实训)

题目&#xff1a; 图的广度优先搜索 描述&#xff1a; 图的广度优先搜索类似于树的按层次遍历&#xff0c;即从某个结点开始&#xff0c;先访问该结点&#xff0c;然后访问该结点的所有邻接点&#xff0c;再依次访问各邻接点的邻接点。如此进行下去&#xff0c;直到所有的结点都…

Python实现的二叉树的先序、中序、后序遍历示例

一、先序、中序、后序遍历的次序&#xff1a; 创建好一棵二叉树后&#xff0c;可以按照一定的顺序对树中所有的元素进行遍历。按照先左后右&#xff0c;树 的遍历方法有三种&#xff1a;先序遍历、中序遍历和后序遍历。 其中&#xff0c;先序遍历的次序是&#xff1a;如果二叉…

Javascript编程进阶 – 预定义函数

Javascript编程进阶 – 预定义函数 JavaScript Programming Advanced – Predefined Functions By JacksonML JavaScript引擎中包含了一组built-in functions(内建函数)。 本文简要介绍如何通过实践使用这些预定义函数并掌握传递参数和返回值。希望对您有所帮助。 JavaScri…

C语言课程设计

内容与设计思想 1、系统功能与分析&#xff08;填写你所设计的菜单及流程图&#xff09;。 菜单&#xff1a; 日历打印 日历推算 日历间隔倒计时牌 退出程序 模块设计 根据功能需要&#xff1a; 源文件&#xff1a; #include<stdio.h> #include&…

Light-Head R-CNN: In Defense of Two-Stage Object Detector(2017.11)

文章目录 Abstract1. Introduction2. Related works3. Our Approach3.1. Light-Head R-CNN3.1.1. R-CNN subnet3.1.2. Thin feature maps for RoI warping 3.2. Light-Head R-CNN for Object Detection Conclusion 原文链接 Abstract 在本文中&#xff0c;我们首先研究了为什么…