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