设备间的指令通信

news2024/9/19 10:48:29

指令通信的概念

在这里插入图片描述
要进行设备和设备之间的交流就需要通过串口发送数据进行交流 而串口发送简单的数据只需要传输介质
但是要发送复杂的数据就需要介质和传输的规则了
在这里插入图片描述
三种应用场景
在这里插入图片描述
比如在上位机和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();
	}
}

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

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

相关文章

MySQl int(1)、int(20) 的区别到底在哪里

MySQl int(1)、int(20) 的区别到底在哪里 常思一二,便得自然… int(1)数据类型介绍 在MySQL中,INT(1) 是一种定义整数类型的数据字段,其中的数字表示显示宽度而不是存储范围。具体说,INT(1) 中的数字 1 表示显示宽度&#xff0…

VividTalk创新AI语音匹配图片技术:照片+语音=逼真说话视频!

VividTalk是一个由南京大学、阿里巴巴、字节跳动和南开大学共同开发的项目工具。它通过先进的音频到3D网格映射技术和网格到视频的转换技术,实现了高质量、逼真的音频驱动的说话头像视频生成。这一创新技术使得只需提供一张人物的静态照片和一段语音录音&#xff0c…

KeePass开源密码管理器

KeePass开源密码管理器 KeePass 是一款免费的开源密码管理器,KeePass 将密码存储为一个数据库,而这个数据库由一个主密码或密码文件锁住,也就是说我们只需要记住一个主密码,或使用一个密码文件,就可以解开这个数据库&a…

JavaSE基础50题:8. 获取一个数二进制序列中所有的偶数和奇数位,分别输出二进制序列。

概述 获取一个数二进制序列中所有的偶数和奇数位,分别输出二进制序列。 如:从右往左数 0111(如图) 偶数位:01 奇数位:11 代码 public static void main(String[] args) {Scanner scanner new Scanner(Sys…

动态规划学习——最长回文子序列,让字符串变成回文串的最小插入次数

一,最长回文串 1.题目 给你一个字符串 s ,找出其中最长的回文子序列,并返回该序列的长度。 子序列定义为:不改变剩余字符顺序的情况下,删除某些字符或者不删除任何字符形成的一个序列。 示例 1: 输入&…

Dockerfile详解#如何编写自己的Dockerfile

文章目录 前言编写规则指令详解FROM:基础镜像LABEL:镜像描述信息MAINTAINER:添加作者信息COPY:从宿主机复制文件到镜像中ADD:从宿主机复制文件到镜像中WORKDIR:设置工作目录 前言 Dockerfile是编写docker镜…

#HarmonyOS:装饰器UI描述---@Link

装饰器 装饰器(Decorator)是一种语法结构,用来在定义时修改类(class)的行为。 在语法上,装饰器有如下几个特征。 第一个是字符(或者说前缀)是,后面是一个表达式后面的…

机器学习算法(7)-朴素贝叶斯算法和K最近邻算法

一、说明 在在这篇文章中,我将解释两种机器学习算法,称为贝叶斯定理和 K 最近邻算法。贝叶斯定理以 18 世纪英国数学家托马斯贝叶斯的名字命名,是确定条件概率的数学公式。k 最近邻算法,也称为 KNN 或 k-NN,是一种非参…

Python基础知识-变量、数据类型(整型、浮点型、字符类型、布尔类型)详解

1、基本的输出和计算表达式: prinit(12-3) printf(12*3) printf(12/3) prinit(12-3) printf(12*3) printf(12/3) 形如12-3称为表达式 这个表达式的运算结果称为 表达式的返回值 1 2 3 这样的数字,叫做 字面值常量 - * /称为 运算符或者操作符 在C和j…

k8s中的Pod网络;Service网络;网络插件Calico

Pod网络;Service网络;网络插件Calico Pod网络 在K8S集群里,多个节点上的Pod相互通信,要通过网络插件来完成,比如Calico网络插件。 使用kubeadm初始化K8S集群时,有指定一个参数–pod-network-cidr10.18.0…

再识二叉树

1. 二叉树的存储 二叉树的存储结构分为:顺序存储和类似于链表的链式存储。 其中二叉树的链式存储是通过一个一个的节点引用起来的,常见的表示方式有二叉和三叉表示方式(这里本主主要讲的是链式存储),具体代码如下&…

2个月拿下信息系统项目管理师攻略(攻略超级全)

信息系统项目管理师(高项)一次性过啦!结合这次备考经验,给大家总结一下复习方法。 先上图,开心一下! 一、我为什么选择了高项 为什么我会选信息系统项目管理师,也就是我们常说的高项。 原因1…

bpftrace原理与使用方法

Bpftrace 概念和原理bpftrace安装bpftrace 语法结构bpftrace 变量内置变量自定义变量Map变量 内置函数Bpftrace操作案例文件系统磁盘进程内存 bpftrace是一种基于eBPF(Extended Berkeley Packet Filter)的跟踪工具,用于在Linux系统中进行动态…

PostGIS学习教程十一:投影数据

PostGIS学习教程十一:投影数据 地球不是平的,也没有简单的方法把它放在一张平面纸地图上(或电脑屏幕上),所以人们想出了各种巧妙的解决方案(投影)。 每种投影方案都有优点和缺点,一…

有了安卓模拟器,就能在Windows 10或11上像使用安卓操作系统一样使用安卓

你可以使用Android模拟器在Windows 11或Windows 10中运行Android应用程序。如果你喜欢的应用程序只在手机上运行,但你想在电脑上使用,这些模拟器会很有用。 BlueStacks 与整个操作系统模拟器不同,BlueStacks只在Windows上模拟Android应用程序。它真的很容易使用,所以你不需…

鸿蒙OS应用开发的开发环境

鸿蒙OS应用开发的开发环境 鸿蒙系统发展越来越快,已经开始走进千家万户,从手机到电视机,再到汽车,以后各种手表、智能设备等等。这已经是一个广泛应用的操作系统,也是跟大家生活密切相关的操作系统。要想在这个平台上…

人脸识别安卓主板_MTK方案智能闸机门禁工业安卓主板定制开发

人脸识别主板广泛应用于各个领域,包括人脸支付系统、人脸识别监控系统、写字楼办公楼门禁闸机、校园、地铁、住宅门禁、考勤机、智能门锁、广告机、售卖机等。 主板基于联发科MTK方案,并由行业PCBA和MTK的核心板组成。根据产品需求,可以选择…

SpringBoot3.x代码生成器构建的三层架构主启动类报错

【场景复现】 jdk21环境变量springboot3.x、mybatisplus generator3.5.3构建工程启动: 【原因分析】 显示 factoryBeanObjectType 属性的值类型不正确,应该是一个实现了 FactoryBean 接口的类的全限定名。 注解注入每层对象,找不到Factory…

嵌入式系统

嵌入式系统 目前国内一个普遍认同的嵌入式系统定义是:以应用为中心、以计算机技术为基础,软件硬件可裁剪,适应应用系统对功能、可靠性、成本、体积、功耗严格要求的专用计算机系统。(引用自《嵌入式系统设计师教程》) …

node后端接口无法插入数据为emoji的表情的问题

原因 emoji的表情一般是这样的\xF0\x9F\x98\x80或者是\xF0\x9F\x98 ,事实上 一般数据库的utf8的编码类型都是能保存\xF0\x9F\x98 但是不能保存\xF0\x9F\x98\x80这种样的emoji,要将数据库编码格式为utf8mb4 也就是utf8的超集 另外,除了 数据库…