目录

1 CubeMX基本配置(针对stm32F407ZGT6,时钟树的配置需要根据单片机的种类而定)

2  接线

2.1 STM32F407ZG单片机连接ST_LINK

2.2  STM32F407ZG单片机连接USB转TTL(用于串口通信)

3  串口通信(附加中断+定时器+PWM综合)

3.1  printf/scanf的重定向

3.2  HAL_UART_Transmit()和HAL_UART_Receive()函数

3.3   中断及中断回调函数

3.3.1  中断函数

3.3.2  中断回调函数

3.4  DMA

3.5  综合基础知识,通过串口通信控制

4  舵机

4.1  相关计算

4.2  接线

5  PID控制算法

5.1  简介

5.2  比例Proportional

5.3  积分Integral

5.4  微分Differential

5.5  公式

5.6  积分限幅

5.7  积分限行

5.8  相关代码

6  systick(定时器,多用于延时)

6.1  寄存器

6.2  代码

7  蓝牙模块


1 CubeMX基本配置(针对stm32F407ZGT6,时钟树的配置需要根据单片机的种类而定)

2  接线

2.1 STM32F407ZG单片机连接ST_LINK

单片机             ST_LINK

9--------------------6

7--------------------2

20------------------3/4

1--------------------7/8

这里附上具体的接线图片:

2.2  STM32F407ZG单片机连接USB转TTL(用于串口通信)

单片机      USB转TTL

TX————RXD

RX————TXD

GND————GND

5V————5V

3  串口通信(附加中断+定时器+PWM综合)

3.1  printf/scanf的重定向

int fputc(int c,FILE *stream)//printf
{uint8_t ch[1]={c};HAL_UART_Transmit(&huart1,ch,1,0xFFFF);return c;
}int fgetc(FILE *stream)//scanf
{uint8_t ch[1];HAL_UART_Receive(&huart1,ch,1,0xFFFF);return ch[0];
}

3.2  HAL_UART_Transmit()和HAL_UART_Receive()函数

HAL_UART_Transmit()是HAL库中的一个函数,用于向UART发送数据。该函数需要传入UART句柄、发送数据的缓冲区指针和发送数据的长度作为参数。在调用该函数时,UART会将缓冲区中的数据发送出去。如果发送成功,该函数会返回HAL_OK,否则会返回错误码。

参数1:使用的串口,2:要发送的数据,3:数据大小,4:发送的超时时间HAL_UART_Transmit(&huart1,Data,sizeof(Data),1000);

HAL_UART_Receive()函数同理,不再赘述

注意:这种发送方式是阻塞式(阻塞模式就像是一个延时函数,当这个函数没处理完那么,所有的按照流程需要执行的代码都不会被执行,要等到这个延时完成,类似 平时看书上写的LED灯闪烁,用的delay()一样。而非阻塞模式就像他定义的那样,一般用的是中断,执行这条语句的时候,开启相应的中断达到一定的条件才进行处理,这样不会影响到流程的执行.我的理解就是,阻塞就是死等,非阻塞就是中断)

3.3   中断及中断回调函数

3.3.1  中断函数

HAL_UART_Transmit_IT(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size)

HAL_UART_Receive_IT()函数同理

3.3.2  中断回调函数

void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart)
{}void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{HAL_UART_Transmit_IT(&huart1,buffer,100);HAL_UART_Receive_IT(&huart1,buffer,100);
}

3.4  DMA

DMA,全称Direct Memory Access,即直接存储器访问。

DMA传输将数据从一个地址空间复制到另一个地址空间,提供在外设和存储器之间或者存储器和存储器之间的高速数据传输。

我们知道CPU有转移数据、计算、控制程序转移等很多功能,系统运作的核心就是CPU,

CPU无时不刻的在处理着大量的事务,但有些事情却没有那么重要,比方说数据的复制和存储数据,如果我们把这部分的CPU资源拿出来,让CPU去处理其他的复杂计算事务,是不是能够更好的利用CPU的资源呢?

因此:转移数据(尤其是转移大量数据)是可以不需要CPU参与。比如希望外设A的数据拷贝到外设B,只要给两种外设提供一条数据通路,直接让数据由A拷贝到B 不经过CPU的处理,

DMA就是基于以上设想设计的,它的作用就是解决大量数据转移过度消耗CPU资源的问题。有了DMA使CPU更专注于更加实用的操作–计算、控制等。

HAL_UART_Receive_DMA(&huart1,buffer,100);__HAL_UART_ENABLE_IT(&huart1,UART_IT_IDLE);

注意:如果要想能够保证不止一次输入数据,需要在回调函数里写内容(放在it文件里)

void USART1_IRQHandler(void)
{/* USER CODE BEGIN USART1_IRQn 0 */if(__HAL_UART_GET_FLAG(&huart1,UART_FLAG_IDLE)!=RESET){__HAL_UART_CLEAR_IDLEFLAG(&huart1);HAL_UART_DMAStop(&huart1);//len=100-__HAL_DMA_GET_COUNTER(huart1.hdmarx);//rintf("%d\r\n",len);*/}/* USER CODE END USART1_IRQn 0 */HAL_UART_IRQHandler(&huart1);/* USER CODE BEGIN USART1_IRQn 1 *//* USER CODE END USART1_IRQn 1 */
}

3.5  综合基础知识,通过串口通信控制

实现功能如下:

1.LED灯的亮灭

2.定时器中断控制LED灯按频率闪烁

3.PWM波控制呼吸灯

4.PWM波控制舵机转动

5.按键控制灯的亮灭

6.高电平控制蜂鸣器(注意蜂鸣器声音挺大的,第一次用的时候吓一跳)

注意事项:

1.头文件加一个stdio.h,因为用到了printf和scanf,并且需要重定向(这两个函数原本是在显示屏上进行的)

2.最好定义全局变量,防止值的改变

3.利用中断控制时在CubeMX配置时要注意打开global interrupt选项

4.我的单片机PF9和PF10引脚对应两个LED灯

5.PWM波在Keil编写程序时要加上Start函数打开PWM波

6.我加的printf(check)是用来检验程序是否正常运行

7.在使用PWM波控制呼吸灯时要看好灯对应的那个引脚连接了哪个定时器

8.在使用PWM波控制舵机时要看好自己开的定时器对应哪个引脚,插信号线要插对

9.有关舵机的具体计算在下面有,可以先看下面的再回来看

10.输入数据到buffer【0】的位置来控制程序

11.如果不加DMA_Stop()函数则后续输入的数据会累积到buffer【1】【2】等等,这样if判断句就没用了

12.windows换行的话需要同时写\r\n

13.按键和亮灯原理:(我的单片机KEY1对应PE3,KEY0对应PE4)

14.按键达不到预期效果(PF9定时器占用了),意会即可

这样算是用到了所有stm32的基础知识,包括:

1.GPIO控制高低电平

2.定时器中断

3.PWM波控制

4.串口通信(阻塞、非阻塞、DMA)

CubeMX整体配置:

代码:

/* USER CODE BEGIN Header */
/********************************************************************************* @file           : main.c* @brief          : Main program body******************************************************************************* @attention** <h2><center>&copy; Copyright (c) 2023 STMicroelectronics.* All rights reserved.</center></h2>** This software component is licensed by ST under BSD 3-Clause license,* the "License"; You may not use this file except in compliance with the* License. You may obtain a copy of the License at:*                        opensource.org/licenses/BSD-3-Clause********************************************************************************/
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "dma.h"
#include "tim.h"
#include "usart.h"
#include "gpio.h"
#include "stdio.h"
/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
uint8_t buffer[100];
uint8_t len;
/* USER CODE END Includes *//* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD *//* USER CODE END PTD *//* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
/* USER CODE END PD *//* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM *//* USER CODE END PM *//* Private variables ---------------------------------------------------------*//* USER CODE BEGIN PV *//* USER CODE END PV *//* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
/* USER CODE BEGIN PFP *//* USER CODE END PFP *//* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
int fputc(int c,FILE *stream)//printf
{uint8_t ch[1]={c};HAL_UART_Transmit(&huart1,ch,1,0xFFFF);return c;
}int fgetc(FILE *stream)//scanf
{uint8_t ch[1];HAL_UART_Receive(&huart1,ch,1,0xFFFF);return ch[0];
}void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart)
{}void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{HAL_UART_Transmit_DMA(&huart1,buffer,100);HAL_UART_Receive_DMA(&huart1,buffer,100);
}
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{HAL_GPIO_TogglePin(GPIOF,GPIO_PIN_10);
}
/* USER CODE END 0 *//*** @brief  The application entry point.* @retval int*/
int main(void)
{/* USER CODE BEGIN 1 *//* USER CODE END 1 *//* MCU Configuration--------------------------------------------------------*//* Reset of all peripherals, Initializes the Flash interface and the Systick. */HAL_Init();/* USER CODE BEGIN Init *//* USER CODE END Init *//* Configure the system clock */SystemClock_Config();/* USER CODE BEGIN SysInit *//* USER CODE END SysInit *//* Initialize all configured peripherals */MX_GPIO_Init();MX_DMA_Init();MX_USART1_UART_Init();MX_TIM14_Init();MX_TIM2_Init();MX_TIM3_Init();MX_USART2_UART_Init();/* USER CODE BEGIN 2 */HAL_TIM_PWM_Start(&htim14,TIM_CHANNEL_1);HAL_TIM_PWM_Start(&htim3,TIM_CHANNEL_1);HAL_GPIO_WritePin(GPIOF,GPIO_PIN_9,GPIO_PIN_SET);HAL_GPIO_WritePin(GPIOF,GPIO_PIN_10,GPIO_PIN_SET);/* USER CODE END 2 *//* Infinite loop *//* USER CODE BEGIN WHILE */while (1){/* USER CODE END WHILE *//* USER CODE BEGIN 3 *///HAL_UART_Transmit(&huart1,"HELLO",5,0xFFFF);//uint8_t buffer[100];HAL_UART_Receive_DMA(&huart1,buffer,100);__HAL_UART_ENABLE_IT(&huart1,UART_IT_IDLE);//printf("check0\r\n");printf("%d\r\n",buffer[0]);HAL_Delay(1000);if(buffer[0]==1){printf("check1\r\n");HAL_GPIO_WritePin(GPIOF,GPIO_PIN_9,GPIO_PIN_SET);HAL_GPIO_WritePin(GPIOF,GPIO_PIN_10,GPIO_PIN_RESET);HAL_Delay(500);printf("check2\r\n");HAL_Delay(1000);//memset(buffer,0,sizeof(buffer));}if(buffer[0]==2){printf("check3\r\n");HAL_GPIO_WritePin(GPIOF,GPIO_PIN_9,GPIO_PIN_RESET);HAL_GPIO_WritePin(GPIOF,GPIO_PIN_10,GPIO_PIN_SET);HAL_Delay(500);printf("check4\r\n");HAL_Delay(1000);//memset(buffer,0,sizeof(buffer));}if(buffer[0]==3){printf("check5\r\n");for(uint16_t cnt=0;cnt<1000;cnt++){__HAL_TIM_SetCompare(&htim14,TIM_CHANNEL_1,cnt);HAL_Delay(1);}for(uint16_t cnt=1000;cnt>0;cnt--){__HAL_TIM_SetCompare(&htim14,TIM_CHANNEL_1,cnt);HAL_Delay(1);}printf("check6\r\n");HAL_Delay(1000);}if(buffer[0]==4){printf("check7\r\n");HAL_TIM_Base_Start_IT(&htim2);printf("check8\r\n");HAL_Delay(1000);}if(buffer[0]==5){printf("check9\r\n");for(uint16_t cnt=500;cnt<=2500;cnt++){__HAL_TIM_SetCompare(&htim3,TIM_CHANNEL_1,cnt);HAL_Delay(1);}for(uint16_t cnt=2500;cnt>=500;cnt--){__HAL_TIM_SetCompare(&htim3,TIM_CHANNEL_1,cnt);HAL_Delay(1);}printf("check10\r\n");HAL_Delay(1000);}if(buffer[0]==6){printf("check11\r\n");if(HAL_GPIO_ReadPin(GPIOE,GPIO_PIN_4)==RESET){HAL_GPIO_WritePin(GPIOF,GPIO_PIN_9,GPIO_PIN_SET);printf("check12\r\n");}if(HAL_GPIO_ReadPin(GPIOE,GPIO_PIN_4)==SET){HAL_GPIO_WritePin(GPIOF,GPIO_PIN_9,GPIO_PIN_RESET);printf("check13\r\n");}if(HAL_GPIO_ReadPin(GPIOE,GPIO_PIN_3)==RESET){HAL_GPIO_WritePin(GPIOF,GPIO_PIN_10,GPIO_PIN_SET);printf("check14\r\n");}if(HAL_GPIO_ReadPin(GPIOE,GPIO_PIN_3)==SET){HAL_GPIO_WritePin(GPIOF,GPIO_PIN_10,GPIO_PIN_RESET);printf("check15\r\n");}printf("check16\r\n");HAL_Delay(1000);}if(buffer[0]==7)                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      ){printf("check17\r\n");HAL_GPIO_WritePin(GPIOF,GPIO_PIN_8,GPIO_PIN_SET);HAL_Delay(500);HAL_GPIO_WritePin(GPIOF,GPIO_PIN_8,GPIO_PIN_RESET);HAL_Delay(500);printf("check18\r\n");}/*if(buffer[0]!='\0'){printf("%s\r\n",buffer);memset(buffer,0,sizeof(buffer));printf("%d\r\n",len);}*/HAL_Delay(100);/*uint8_t  SendBuffer[30]={"hello,world!"};HAL_UART_Transmit(&huart2, (uint8_t *)SendBuffer, sizeof(SendBuffer), HAL_MAX_DELAY);*/}/* USER CODE END 3 */
}

4  舵机

4.1  相关计算

我们打开TIM3定时器,这个定时器是挂在APB1总线上的,根据配置好的时钟树可知

频率是84MHz

然后为了方便计算,我们把分频系数设置成84-1,这样相当于1秒钟点1000000次

由于舵机的驱动信号是50Hz,周期是0.02s,所以在一个周期内会点20000次

舵机的转动角度是按照高电平的占空比来计算的

经过手算,我们可以大致推出角度和比较值之间的关系,舵机的难点也就在这了

4.2  接线

舵机                  单片机

信号线(黄)-------PA6(根据自己的定时器而定)

电源线(红)-------ST-LINK上的5V(9/10)

地线(棕)----------GND

5  PID控制算法

5.1  简介

PID控制中有P、I、D三个参数,PID即:Proportional(比例)、Integral(积分)、Differential(微分)的缩写。只有明白这三个参数的含义和作用才能完成控制器PID参数整定,让控制器到达最佳控制效果。

PID是经典的闭环控制算法,具有原理简单,易于实现,适用面广,控制参数相互独立,参数的选定比较简单等优点。

凡是需要将某一个物理量“保持稳定”的场合(比如维持平衡,稳定温度、转速等),PID都会派上大用场。

5.2  比例Proportional

比例控制器实际上就是个放大倍数可调的放大器,即△P=Kp×e,式中Kp为比例增益,即Kp可大于1,也可小于1;e为控制器的输入,也就是测量值与给定值之差,又称为偏差。

比例控制有个缺点,就是会产生余差,要克服余差就必须引入积分作用。

只有比例系数无法准确到达目标位置,但增大比例系数有利于减小误差

5.3  积分Integral

控制器的积分作用就是为了消除自控系统的余差而设置的。所谓积分,就是随时间进行累积的意思,即当有偏差输入e存在时,积分控制器就要将偏差随时间不断累积起来,也就是积分累积的快慢与偏差e的大小和积分速度成正比。只要有偏差e存在,积分控制器的输出就要改变,也就是说积分总是起作用的,只有偏差不存在时,积分才会停止。

实际上积分作用很少单独使用,通常与比例作用一起使用,使其既具有把偏差放大(或缩小)的比例作用,又具有将偏差随时间累积的积分作用,且其作用方向是一致的。这时控制器的输出为:△P=Ke+△Pi,式中△P为控制器输出值的变化;Ke为比例作用引起的输出;△Pi为积分作用引起的输出。

同时使用比例系数和积分可以准确到达目标位置,但当比例系数过大时会出现不稳定性

5.4  微分Differential

微分作用主要是用来克服被控对象的滞后,常用于温度控制系统。除采用微分作用外,在使用控制系统时要注意测量传送的滞后问题,如温度测量元件的选择和安装位置等。

在常规PID控制器中,微分作用的输出变化与微分时间和偏差变化的速度成比例,而与偏差的大小无关,偏差变化的速度越大,微分时间越长,则微分作用的输出变化越大。但如果微分作用过强,则可能由于变化太快而由其自身引起振荡,使控制器输出中产生明显的“尖峰”或“突跳”。为了避免这一扰动,在PID调节器和DCS中可使用微分先行PID运算规律,即只对测量值PV进行微分,当人工改变控制器的给定值SP时,不会造成控制器输出的突变,避免了改变SP的瞬间给控制系统带来的扰动。如TDC-3000,则在常规PID算法中增加一个软开关,组态时供用户选择控制器对偏差、还是测量值进行微分。

微分保证系统能够平稳运行,不至于出现太大的波动

5.5  公式

连续形式:

离散形式(常用,由连续形式推导):

5.6  积分限幅

试想一下,使用P和I项进行控制,无人机在地面准备起飞,期望高度是100m。此时一个人摁住无人机,那么误差值一直为100m,控制器P项输出保持不变,控制器I项输出是线性增长的

一段时间后,那个人突然不摁了,此时控制器I项输出可能非常大,再加上控制器P项输出,控制器给电机的输出非常大,那么无人机速度就非常快并且飞的非常高。对于这种情况,我们对积分限幅,I项增加到一定值时就不再增了。那么无人机在上面这种情况下就不至于飞的很快很高,这就是积分限幅的作用。

5.7  积分限行

我们直接将传感器的反馈值分出来一路给到控制器的D项,这样做有一个好处就是如果希望无人机快速反应移动,当期望高度突变的时候,影响会先给到P和I项,由于开始时无人机位置没有突变,传感器反馈的实际高度值也不会突变,因此不会马上给到D项,这样就有效减小了D项开始的缓冲作用,使无人机可以快速反应移动。如果不这样做,那么如果期望高度突变,D项的微分值也会突变变得很大,缓冲作用非常大,使相应效果大大降低。

5.8  相关代码

chassis_motor_pid[i].SpeedPID.current=motor_chassis[i].speed_rpm;
pid_calc(&chassis_motor_pid[i].SpeedPID);void pid_calc(_pid* pid)
{pid->e=pid->target-pid->current;pid->p_out=(int32_t)(pid->Kp*pid->e);if(fabs(pid->e)<I_Band)//积分限幅和积分分离 {pid->i_out+=(int32_t)(pid->Ki*pid->e);limit(&(pid->i_out),pid->IntegralLimit);}else{pid->i_out=0;}pid->d_out=(int32_t)(pid->Kd*(pid->e-pid->last_e));pid->total_out=pid->p_out+pid->i_out+pid->d_out;//公式 limit(&(pid->total_out),pid->MaxOutput);//输出限制 pid->last_e=pid->e;//更新last值 } 

6  systick(定时器,多用于延时)

6.1  寄存器

Systick的寄存器分为:

CTRL

LOAD

VAL

CALIB

ENABLE位就是开关Systick

TICKINT的作用是当写入的值为"1"时,会进入SysTick_Handler()中断服务函数,随后执行用户代码。

CLKSOURCE该位要联合最上方的图来理解,当值为0时Systick的时钟频率为AHB/8也就是72MHz/8=9MHz,当值为1时Systick的时钟频率为AHB桥的频率。AHB桥的频率常用为72MHz。

COUNTFLAG该位的作用就是告诉使用者(芯片程序)Systick已经计数完成,用户程序可以通过检测该位是否为"1"来判断Systick的计数状态。

RELOAD该位是一个24位的寄存器,也就是说最大支持0xFFFFFF,同时还是能够自动重装载值,自动重装载的理解就是当RELOAD倒数至0后,能够重新将用户预设值填充,比如说预设值为0xFF,那么当倒数至0时,它能够自动将0xFF填充进RELOAD。

 CURRENT该位是与RELOAD相对应的,它的值就等于RELOAD的值,只不过当我们对该寄存器进行写操作时,会强行将RELOAD的值清0,同时会将CTRL->COUNTFLAG的标志位置0。读操作则只是返回RELOAD的值。

6.2  代码

static uint8_t us = 0;
static uint16_t ms = 0;void SysTickConfig(void)
{SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK_Div8);us = SystemCoreClock / 8000000;ms = (uint16_t )us *1000;
}void delay_us(uint32_t nus)
{uint32_t flags;SysTick->LOAD     = nus * us;SysTick->VAL     = 0x00;SysTick->CTRL   |= SysTick_CTRL_ENABLE_Msk;do{flags = SysTick->CTRL;}while((flags&0x01)&&!(flags&(1<<16)));SysTick->CTRL  &= ~SysTick_CTRL_ENABLE_Msk;SysTick->VAL     = 0x00;
}void delay_ms(uint16_t nms)
{uint32_t flags;SysTick->LOAD     = (uint32_t )nms * ms;SysTick->VAL  = 0x00;SysTick->CTRL   |= SysTick_CTRL_ENABLE_Msk;do{flags = SysTick->CTRL;}while((flags&0x01)&&!(flags&(1<<16)));SysTick->CTRL  &= ~SysTick_CTRL_ENABLE_Msk;SysTick->VAL     = 0x00;
}

SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK_Div8)

配置CTRL->CLKSOURCE,将其选择为外部时钟源。

us = SystemCoreClock / 8000000

这里是整个Systick的重点,定时器准不准就看这里的参数,SystemCoreClock 是系统时钟频率,这里取72MHz,同时又由于上方代码进行了一个8分频,所以需要除以8。但如果单单只是/8,那么此时一个us应该为1s,而Systick的计数速度是由时钟频率决定的,此时时钟频率为9MHz,代表计数一秒需要数9M个数,而1s中有1M个us,所以用9M/1M就等于Systick计时1us需要数的数,完整的式子应该是 us = (72,000,000 / 8) / 1,000,000=9

ms = (uint16_t )us *1000

这里不难理解,1ms就是等于1000us,前面加个强制类型转换是为了让数据类型匹配上,避免编译器优化,造成数据丢失。

SysTick->LOAD      = nus * us

此处就是给LOAD->RELOAD填充计数值自动重装载值,切记此处最大不超过24位。

SysTick->VAL     = 0x00 

这里是为了清空计数器,确保计数精准。

SysTick->CTRL    |= SysTick_CTRL_ENABLE_Msk

启动Systick。

do
    {
        flags = SysTick->CTRL;
    }while((flags&0x01)&&!(flags&(1<<16)));

此处作用是等待计数完成,flags&(1<<16)这里就是检测计数完成COUNTFLAG标志位是否为'1'

SysTick->CTRL    &= ~SysTick_CTRL_ENABLE_Msk 

关闭Systick。

SysTick->VAL     = 0x00 

再次清空计数器。

下方的delay_ms()的原理同上方一样,只不过是将SysTick->LOAD      = nus * us 的us换成ms,SysTick->LOAD      = nms * ms ,当使用delay_ms()时,最大延时建议不超过1500ms

7  蓝牙模块

CH340模块(USB转TTL)       HC-05模块

VCC(5V)  ——————————  VCC

GND   ——————————  GND

RXD   ——————————  TXD

TXD   ——————————  RXD

最开始,用USB转TTL连接HC-05模块(注意此时需要先按住HC-05模块上面的按钮再上电),这时会进入AT模式(此时的灯应该是间隔比较长时间才灭一次),然后打开串口调试助手,波特率设为38400,接下来进行初始化操作

按照步骤

配置蓝牙模块基本信息

AT+NAME=HC-05   修改蓝牙模块名称为HC-05

AT+ROLE=0    蓝牙模式为从模式

AT+CMODE=1   蓝牙连接模式为任意地址连接模式,也就是说 该模块可以被任意蓝牙设备连接

AT+PSWD=1234   蓝牙配对密码为1234

AT+UART=9600,0,0  蓝牙通信串口波特率为9600,停止位1位, 无校验位

我们直接把蓝牙模块插到原来USB转TTL的位置上(蓝牙模块的用处就是可以无线调试而不用电脑上的虚拟串口调试) (注意不要按按钮)

我们在手机上安装蓝牙串口调试软件,并配对(注意在这之前手机的设置->蓝牙里已经连接成功)

然后这时会发现灯处于长灭状态(偶尔亮一会),就可以正常使用了,我们在手机里输入数据,跟原来用电脑的虚拟串口一模一样

stm32攻略(随时更新,更新时间:2023.5.5)相关推荐

  1. 阿里巴巴大数据计算平台MaxCompute(原名ODPS)全套攻略(持续更新20171127)

    概况介绍 大数据计算服务(MaxCompute,原名ODPS,产品地址:https://www.aliyun.com/product/odps)是一种快速.完全托管的TB/PB级数据仓库解决方案.Ma ...

  2. 【面试技巧】最全的面试求职攻略_每日更新

    12.02更新~ ◣◤◣大家想看哪方面的更多?或者有什么关于职场的疑惑想要提问哒~都可以在这里留言或者给小白白发豆油~小白白都会去搜集整理编辑最终更新出来~ ◣◤◣如果觉得对大家有帮助,将继续更新~ ...

  3. 服务器维护必刷稀有宠物,诛仙手游稀有宠物捕捉攻略 稀有宠物刷新时间地点汇总...

    诛仙手游稀有宠物捕捉攻略,稀有宠物刷新时间地点汇总.希望能够帮助大家早日入手自己喜欢的宠物,下面一起来看看攻略吧. 宠物的捕捉等级表 所谓冲级的优势在这里就体现出来了. 系统设置调到最佳位置 最重要的 ...

  4. cipher攻略(不断更新)

    cipher是一个在线解谜.闯关.很烧脑细胞的游戏,适合于推理狂,数学Geek,各类变态玩家.在享受游戏的过程中,你还可以学习到:编解码,密码学,进制转换,图像处理,基础乐理,世界地理,各地习俗,历史 ...

  5. CentOS 5.5 安装配置全攻略 (无线上网 更新源 显卡驱动 firefox3.6 flash插件 编译boost1.43.0 雅黑字体...

    unbuntu虽然很好,但用来开发并不是很好,很多东西库都比较新,在上面开发的东西兼容性和可移植性差,所以最终还是选择了centos5.4. centos安装后首先 解决上网的问题 安装好后,无法识别 ...

  6. 黑客丛林通关攻略参考(更新中)

    黑客丛林之旅游戏链接地址:http://www.fj543.com/hack/ 1.提示语:在浏览器端用脚本进行身份验证是很容易被破解的. 查看源代码,密码在JS脚本中,典型的本地验证(在浏览器按F1 ...

  7. 小花仙攻略 各种花成熟时间和经验点

    盆栽类 ·吊兰(成熟时间:6~12小时) 白色吊兰(没授粉)经验值1点 6~12小时/经验点 白色吊兰(授粉的)经验值2点 6~12小时/经验点 粉色吊兰(没授粉)经验值2点 3~6小时/经验点 粉色 ...

  8. 奶块1月25日服务器维护时间,奶块1月25更新公告 | 手游网游页游攻略大全

    发布时间:2016-01-15 LOL8月25更新排位赛BUG是什么?LOL英雄联盟在8月25日的更新之后出现了排位赛的BUG,导致了可以晋级但是没有晋级.下面就是多游攻略带来的LOL8月25更新排位 ...

  9. 方舟linux服务器更新,方舟怎么更新服务器版本 | 手游网游页游攻略大全

    发布时间:2016-06-01 pokemon go官方在2016年7月31日进行了一个重大的版本更新,新版本带给玩家太多的惊喜和刺激,但是老的玩家会感到微微的失落,毕竟很多格局已经被打破,你需要重新 ...

最新文章

  1. c# 字符串是否相等
  2. Cocos2d-x win7 + vs2010 配置图文详解 .
  3. 'putText' is not a member of 'cv'
  4. php 类 静态调用 实例化 效率,php类的静态调用和实例化调用有哪些不同点?
  5. mahout基于Hadoop的CF代码分析(转)
  6. 寻址(实模式和保护模式)
  7. 浅谈MD5加密算法中的加盐值(SALT)
  8. 图论--Floyd总结
  9. (pytorch-深度学习系列)卷积神经网络中的填充(padding)和步幅(stride)
  10. 原生语言开发web版万岳网校源码 v2.2.0
  11. 关于@SuppressWarnings(unchecked)注解
  12. ScrollView各属性,及代理方法汇总
  13. 怎样快速学习shell语言
  14. Vova and Train (codeforces 1066A)
  15. 23岁的Python,这些年在编程语言排行榜上直线上升的原因是什么?很多人都不解
  16. Ubuntu 16 NFS的安装与使用
  17. css04 float
  18. 项目使用jdk17人傻了
  19. IP与MAC绑定的难题
  20. java futuretask 单例_集群环境下java单例查询多了就异常

热门文章

  1. std::map与std::unordered_map
  2. 无法嵌入互操作类型“stdole.StdFontClass”的解决方法
  3. kafka manager安装和使用
  4. 《沟通的方法》笔记三:反向叙述
  5. Attributes.add
  6. 国际经济合作真题全集
  7. python使用清华源镜像安装包
  8. 福州市计算机等级考试培训点,计算机等级考试培训
  9. YII2 使用qiniu插件 上传多张图片回调显示
  10. shell编程(六) : [shell基础] 基本shell脚本