机智云案例(ESP8266模块接入机智云平台实现APP控制舵机旋转)

这篇具有很好参考价值的文章主要介绍了机智云案例(ESP8266模块接入机智云平台实现APP控制舵机旋转)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

ESP8266模块

ESP8266模块简介

  • ESP8266是一款超低功耗的UART-WiFi 透传模块,拥有业内极富竞争力的封装尺寸和超低能耗技术,专为移动设备和物联网应用设计,可将用户的物理设备连接到Wi-Fi 无线网络上,进行互联网或局域网通信,实现联网功能。

  • 支持无线802.11 b/g/n 标准

  • 支持STA/AP/STA+AP三种工作模式

  • 内置TCP/IP协议栈,支持多路TCP Client连接

  • 支持丰富的Socket AT指令

  • 支持UART/GPIO数据通信接口

  • 支持Smart Link 智能联网功能

  • 支持远程固件升级(OTA)

  • 内置32位MCU, 可兼作应用处理器

  • 超低能耗,适合电池供电应用

  • 3.3V 单电源供电

引脚介绍

ESP8266硬件接口丰富,可支持UART,IIC,PWM,GPIO,ADC等,适用于各种物联网应用场合

机智云esp8266,单片机学习笔记,嵌入式硬件,stm32,笔记,物联网,单片机

机智云esp8266,单片机学习笔记,嵌入式硬件,stm32,笔记,物联网,单片机

主要功能和工作模式

主要功能

  • ESP8266可以实现的主要功能包括:串口透传,PWM 调控,GPIO控制。

  • 串口透传:数据传输,传输的可靠性好,最大的传输速率为:460800bps。

  • PWM 调控:灯光调节,三色LED 调节,电机调速等。

  • GPIO控制:控制开关,继电器等。

工作模式

  • ESP8266模块支持STA/AP/STA+AP 三种工作模式。
  • STA 模式:ESP8266模块通过路由器连接互联网,手机或电脑通过互联网实现对设备的远程控制。
  • AP 模式:ESP8266模块作为热点,实现手机或电脑直接与模块通信,实现局域网无线控制。
  • STA+AP 模式:两种模式的共存模式,即可以通过互联网控制可实现无缝切换,方便操作。

调试模块

硬件接线

ESP8266WIFI模块 USB转TTL模块 面包板
TX RX None
RX TX None
GND GND GND
EN None VCC
3V3 None VCC
IO0 None VCC
IO2 None VCC
RST None VCC

注意: 面板板处于通电状态

发送AT+RST指令

接好线后,将USB转TTL模块接入电脑打开串口助手,发送AT+RST指令

机智云esp8266,单片机学习笔记,嵌入式硬件,stm32,笔记,物联网,单片机

  • 串口接收到模块返回的信息,调试完成

参考资料

本小节参考:

ESP8266新手入门调试指导(ESP-01).pdf

ESP8266-01 WiFi模块用户手册V1.0

机智云平台

简介

机智云esp8266,单片机学习笔记,嵌入式硬件,stm32,笔记,物联网,单片机

文档中心

机智云esp8266,单片机学习笔记,嵌入式硬件,stm32,笔记,物联网,单片机

开发的一些教程和资料

开发者中心

机智云esp8266,单片机学习笔记,嵌入式硬件,stm32,笔记,物联网,单片机

创建产品、APP和自动生成代码服务

基于机智云平台的物联网开发

机智云esp8266,单片机学习笔记,嵌入式硬件,stm32,笔记,物联网,单片机

开发流程:

  • 在平台开发者界面创建产品和小程序
  • 将GAgent固件烧入WIFI模组中
  • 平台自动生成MCU方案代码
  • 将自动生成的代码移植到ST标准库(主要完成硬件功能设计、WIFI模块与MCU的通信)
  • 下面是开发时比较重要的一些概念

GAgent

机智云esp8266,单片机学习笔记,嵌入式硬件,stm32,笔记,物联网,单片机

  • 官方提供的固件,可将其烧录进ESP8266WIFI模组;烧录后,模组原来的AT指令集失去作用,模组能够接入机智云平台,并自动完成模组与平台间的数据交换

  • GAgent配网方式

    • airlink
    • softap

机智云esp8266,单片机学习笔记,嵌入式硬件,stm32,笔记,物联网,单片机

MCU与WIFI模块的通信

ESP8266用UART通信,并有应答机制;MCU与WIFI模块的通讯可以用MCU自带的USART(支持UART)资源

参考资料

本小节参考:

平台概述 - Gizwits

机智云名词定义解释 - Gizwits

【机智云带你一节课入门物联网APP开发】

实操01: GAgent固件的烧写(ESP8266)

烧录的方法有两种,一是用烧录器烧录,而是用USB转TTL模块烧录,由于我没有烧录器,就只介绍用USB转TTL烧录的方式

1.下载GAgent固件包

机智云esp8266,单片机学习笔记,嵌入式硬件,stm32,笔记,物联网,单片机

下载好的固件包的内容,根据参数选择烧录的固件包

机智云esp8266,单片机学习笔记,嵌入式硬件,stm32,笔记,物联网,单片机

  1. 下载安可信ESP8266资料

机智云esp8266,单片机学习笔记,嵌入式硬件,stm32,笔记,物联网,单片机

安信可ESP8266系列接入机智云方案及问题排查指引 - Gizwits

  1. 硬件接线(ESP-01s为例)(因为我买的是这款)

接线:

ESP-01s USB转TTL 面包板
RX TX None
TX RX None
3V3 VCC None
IO0 None GND
GND GND GND
  1. 打开 第2步 ESP8266资料中的烧录软件

机智云esp8266,单片机学习笔记,嵌入式硬件,stm32,笔记,物联网,单片机

一直点进去直到找到.exe文件

机智云esp8266,单片机学习笔记,嵌入式硬件,stm32,笔记,物联网,单片机

打开后是这样的
机智云esp8266,单片机学习笔记,嵌入式硬件,stm32,笔记,物联网,单片机

查看芯片参数(之前调试的时候有)

机智云esp8266,单片机学习笔记,嵌入式硬件,stm32,笔记,物联网,单片机

参数配置

机智云esp8266,单片机学习笔记,嵌入式硬件,stm32,笔记,物联网,单片机

点击start

机智云esp8266,单片机学习笔记,嵌入式硬件,stm32,笔记,物联网,单片机

完成

机智云esp8266,单片机学习笔记,嵌入式硬件,stm32,笔记,物联网,单片机

参考资料

本小节参考资料:

(1条消息) 个人项目——STM32接入机智云教程_at指令能连机智云吗_唯恋殊雨的博客-CSDN博客

【ESP8266固件烧录详解】

安信可ESP8266系列接入机智云方案及问题排查指引 - Gizwits


说明: 若问题无法解决 ESP01或ESP01-s系列接线可参考B站大佬的视频,烧录的步骤可参考官网文档和另一个大佬写的博客

注意: 烧写失败有可能是线接触不良(Combine包比较大),有时候需重试几次才能烧录成功!!!

实操02: 检查GAgent固件是否烧录成功

  1. 进入机智云平台随便新建一个产品

机智云esp8266,单片机学习笔记,嵌入式硬件,stm32,笔记,物联网,单片机

随便加个数据点(不然调试助手会检测不到产品)

机智云esp8266,单片机学习笔记,嵌入式硬件,stm32,笔记,物联网,单片机

  1. 可以看到左上角有PK和PS

机智云esp8266,单片机学习笔记,嵌入式硬件,stm32,笔记,物联网,单片机

  1. 下载机智云的串口调试助手

机智云esp8266,单片机学习笔记,嵌入式硬件,stm32,笔记,物联网,单片机

  1. 打开串口调试助手

机智云esp8266,单片机学习笔记,嵌入式硬件,stm32,笔记,物联网,单片机

  1. 将EPS8266模块与usb-TTL连接
ESP-01s USB转TTL 面包板
RX TX None
TX RX None
3V3 VCC None
IO0 None VCC
GND GND GND

ESP其他引脚都接VCC(手册上说悬空也行,但有的芯片必须得全接好才能正常工作!!!)

  1. 进入模拟MCU、选择串口、SoftAP
    机智云esp8266,单片机学习笔记,嵌入式硬件,stm32,笔记,物联网,单片机
  • 点击SoftAp后,串口向模块发送进入SoftAP模式的信息,模块收到后会进行应答
  • 若能接收到模块的信息则说明GAgent烧录成功
  1. 打开手机WIFI界面可以看到XPG-GAgent开头的WIFI

机智云esp8266,单片机学习笔记,嵌入式硬件,stm32,笔记,物联网,单片机

实操03: 创建产品

机智云esp8266,单片机学习笔记,嵌入式硬件,stm32,笔记,物联网,单片机
机智云esp8266,单片机学习笔记,嵌入式硬件,stm32,笔记,物联网,单片机

机智云esp8266,单片机学习笔记,嵌入式硬件,stm32,笔记,物联网,单片机
机智云esp8266,单片机学习笔记,嵌入式硬件,stm32,笔记,物联网,单片机

参考资料

本小节参考:

【机智云带你一节课入门物联网APP开发】

更多细节参考官方视频

实操04: 虚拟设备

  1. 下载中心下载机智云APP

机智云esp8266,单片机学习笔记,嵌入式硬件,stm32,笔记,物联网,单片机

  1. 开发者中心->虚拟设备->打开APP扫码绑定设备

机智云esp8266,单片机学习笔记,嵌入式硬件,stm32,笔记,物联网,单片机

  1. APP上改变舵机角度,云端数据发生相应变化

机智云虚拟设备

参考资料

本小节参考:

【机智云带你一节课入门物联网APP开发】

更多细节参考官方视频

实操05: MCU自动代码生成+代码移植到标准库(*)

1. 自动生成代码服务

机智云esp8266,单片机学习笔记,嵌入式硬件,stm32,笔记,物联网,单片机

下载代码即可

2. 自动生成代码说明

  1. 两个重要的包

机智云esp8266,单片机学习笔记,嵌入式硬件,stm32,笔记,物联网,单片机

自动生成代码中,Gizwits和Utils是我们需要的(一个建立起与机智云的通讯,一个是工具包)

  1. 打开MDK-ARM文件夹,打开keil工程文件
  2. 可以看到,自动生成的代码是基于Hal库的,我们需要实现自己的功能,并将其移植到标准库中

机智云esp8266,单片机学习笔记,嵌入式硬件,stm32,笔记,物联网,单片机

  1. 打开Gizwits中的gizwits_product.c

机智云esp8266,单片机学习笔记,嵌入式硬件,stm32,笔记,物联网,单片机

  1. 机智云服务用到的三个外设

机智云esp8266,单片机学习笔记,嵌入式硬件,stm32,笔记,物联网,单片机

可以看到,需要用一个定时器(Timer)和两个串口(USART)

说明:

  • 定时器也可以用TIM1、TIM3,同理串口也不一定要用USART1和USART2

  • USART1用于打印调试信息,这一部分功能可以删去,但相应要修改一些代码

关于USART1:

在gizwits_product.c大概两百多行的位置,重写了fputc函数

机智云esp8266,单片机学习笔记,嵌入式硬件,stm32,笔记,物联网,单片机

然后再utils/common.h文件中可以看到GIZWITS_LOG(日志函数)就是printf

机智云esp8266,单片机学习笔记,嵌入式硬件,stm32,笔记,物联网,单片机

在自动生成的代码中,很多调试信息的打印都调用了GIZWITS_LOG

机智云esp8266,单片机学习笔记,嵌入式硬件,stm32,笔记,物联网,单片机

当完成USART1的初始化并重写fputc函数后, 将USART1的端口与usb转TTL模块连接后接入电脑,借助串口助手可以打印调试信息到串口助手

机智云esp8266,单片机学习笔记,嵌入式硬件,stm32,笔记,物联网,单片机

重写的方式如上(本质上就是用USART1发送数据)

6. 主要文件和接口
文件 说明
Gizwits_product.c 该文件为产品相关处理函数,如gizEventProcess()平台相关硬件初始化,如串口、定时器等。
Gizwits_product.h 该文件为gizwits_product.c的头文件,存放产品相关宏定义如:HARDWARE_VERSION、SOFTWARE_VERSION
Gizwits_protocol.c 该文件为SDK API接口函数定义文件
Gizwits_protocol.h 该文件为gizwits_protocol.c对应头文件,相关API的接口声明均在此文件中。
API名称 API功能
Void gizwitsInit(void) gizwits 协议初始化接口。用户调用该接口可以完成 Gizwits 协议相关初始化(包括协议相关定时器、串口的初始化)。
Void gizwitsSetMode(unit8_t mode) 参数mode[in]:仅支持0,1和2,其他数据无效。参数为 0,恢复模组出厂配置接口,调用会清空所有配置参数,恢复到出厂默认配置; 参数为 1 时配置模组进入 SoftAp 模式; 参数为 2 配置模组进入 AirLink 模式。
Void gizwitsHandle(dataPoint_t *dataPoint) 参数 dataPoint[in]:用户设备数据点。该函数中完成了相应协议数据的处理即数据上报的等相关操作。
Int8_t gizwitsEventProcess(eventInfo_t *info,uint8_t *data,uint32_t len) 参数 info[in]:事件队列参数 ; data[in]:数据; 参数 len [in]:数据长度。用户数据处理函数,包括 wifi 状态更新事件和控制事件。a) Wifi 状态更新事件WIFI_开头的事件为 wifi 状态更新事件,data 参数仅在WIFI_RSSI 有效,data 值为 RSSI 值,数据类型为 uint8_t,取值范围 0~7。 b) 控制事件与数据点相关,本版本代码会打印相关事件信息,相关数值也一并打印输出,用户只需要做命令的具体执行即可。

可参考官方文档: 独立MCU方案接入机智云 - Gizwits

3. 代码移植 (需要根据需求进行修改)

串口通信(Serial.c)

#include "stm32f10x.h"
#include "Server.h"
#include "gizwits_protocol.h"
/*
 * WIFI模块通信初始化 USART2
 */
void Serial_WIFI_Init(uint32_t BoundRate)
{
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
	
	// 配置GPIO
	// Tx
	GPIO_InitTypeDef GPIO_InitStructure;
	GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF_PP;
	GPIO_InitStructure.GPIO_Pin=GPIO_Pin_2;
	GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
	GPIO_Init(GPIOA, &GPIO_InitStructure);
	// Rx
	GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IN_FLOATING;
	GPIO_InitStructure.GPIO_Pin=GPIO_Pin_3;
	GPIO_Init(GPIOA, &GPIO_InitStructure);
	
	// 配置USART
	USART_InitTypeDef USART_InitStructure;
	USART_InitStructure.USART_BaudRate=BoundRate;
	USART_InitStructure.USART_HardwareFlowControl=USART_HardwareFlowControl_None;
	USART_InitStructure.USART_Mode=USART_Mode_Rx|USART_Mode_Tx;
	USART_InitStructure.USART_Parity=USART_Parity_No;  // 无奇偶校验
	USART_InitStructure.USART_StopBits=USART_StopBits_1; // 一位停止位
	USART_InitStructure.USART_WordLength=USART_WordLength_8b;  // 传输字长
	USART_Init(USART2, &USART_InitStructure);
	
	// 打开USART中断
	USART_ITConfig(USART2, USART_IT_RXNE, ENABLE);  // 打开接收寄存器非空中断
	// 配置NVIC
	NVIC_InitTypeDef NVIC_InitStructure;
	NVIC_InitStructure.NVIC_IRQChannel=USART2_IRQn;
	NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=3;  // 抢占优先级
	NVIC_InitStructure.NVIC_IRQChannelSubPriority=1;  // 响应优先级
	NVIC_Init(&NVIC_InitStructure);
	// 启动USART
	USART_Cmd(USART2, ENABLE);
}

void USART2_IRQHandler(void)
{
	uint8_t Data=0;
	if(USART_GetITStatus(USART2, USART_IT_RXNE)!=RESET)
	{
		Data = USART_ReceiveData(USART2);
		gizPutData(&Data, 1);  // 解析数据
	}
}

/*
 *  调试端口USART1
 */
void Serial_DebugInit(void)
{
	GPIO_InitTypeDef GPIO_InitStructure;
	USART_InitTypeDef USART_InitStructure;
	NVIC_InitTypeDef NVIC_InitStructure;
	 
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1|RCC_APB2Periph_GPIOA, ENABLE);	
	//TX   PA9
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; 
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;	//复用推挽输出
	GPIO_Init(GPIOA, &GPIO_InitStructure);
   
	//RX	PA10
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;//PA10
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
	GPIO_Init(GPIOA, &GPIO_InitStructure);

	//Usart1 NVIC 配置
	NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=3 ;//抢占优先级3
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;		//子优先级3
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;			//IRQ通道使能
	NVIC_Init(&NVIC_InitStructure);	
  
   //USART 初始化设置
	USART_InitStructure.USART_BaudRate = 9600;//串口波特率
	USART_InitStructure.USART_WordLength = USART_WordLength_8b;//字长为8位数据格式
	USART_InitStructure.USART_StopBits = USART_StopBits_1;//一个停止位
	USART_InitStructure.USART_Parity = USART_Parity_No;//无奇偶校验位
	USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;//无硬件数据流控制
	USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;	//收发模式

	USART_Init(USART1, &USART_InitStructure); //初始化串口1
	USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);//开启串口接受中断
	USART_Cmd(USART1, ENABLE);                    
}	

void USART1_IRQHandler(void)   
{
	
}

Timer.c

#include "stm32f10x.h"
#include "Serial.h"
#include "gizwits_product.h"

// TIM3
void Timer_TIM3Init(uint16_t PSC, uint16_t CNT)
{
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
	
	TIM_InternalClockConfig(TIM3);
	// TimeBase
	TIM_TimeBaseInitTypeDef TimerBaseInitStructure;
	TimerBaseInitStructure.TIM_ClockDivision=TIM_CKD_DIV1;
	TimerBaseInitStructure.TIM_CounterMode=TIM_CounterMode_Up;
	TimerBaseInitStructure.TIM_Period=CNT;
	TimerBaseInitStructure.TIM_Prescaler=PSC;
	TimerBaseInitStructure.TIM_RepetitionCounter=0;
	TIM_TimeBaseInit(TIM1, &TimerBaseInitStructure);
	TIM_ClearFlag(TIM1, TIM_FLAG_Update);
	// 使能更新中断
	TIM_ITConfig(TIM1, TIM_IT_Update, ENABLE);
	NVIC_InitTypeDef NVIC_InitStructure;
	NVIC_InitStructure.NVIC_IRQChannel=TIM3_IRQn;
	NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=2;  // 抢占优先级
	NVIC_InitStructure.NVIC_IRQChannelSubPriority=3;  // 响应优先级
	NVIC_Init(&NVIC_InitStructure);
	// 开启TIM
	TIM_Cmd(TIM1, ENABLE);
}

/*
 *  TIM3 中断函数
 */
void TIM3_IRQHandler(void)
{
	if(TIM_GetITStatus(TIM3, TIM_IT_Update))
	{
		gizTimerMs();  // 机智云计数
		// 清除标志位
		TIM_ClearITPendingBit(TIM3, TIM_IT_Update);	
	}
}

Key.c (用于配置模式)

#include "stm32f10x.h"
#include "delay.h"
#include "Server.h"
#include "gizwits_protocol.h"
// PA1作为按键输入
// 2023年4月18日16:32:06

/*
 *  按键初始化函数  下降沿触发 配置为上拉输入
 */
void Key_Init(void)
{
	// RCC 使能时钟
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
	
	// 配置GPIO
	GPIO_InitTypeDef GPIO_InitStructure;
	GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IPU;
	GPIO_InitStructure.GPIO_Pin=GPIO_Pin_1;
	GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
	GPIO_Init(GPIOA, &GPIO_InitStructure);
	
	// 配置AFIO
	GPIO_EXTILineConfig(GPIO_PortSourceGPIOA, GPIO_PinSource1);  // PA1
	
	// 配置EXTI
	EXTI_InitTypeDef EXTI_InitStructure;
	EXTI_InitStructure.EXTI_Line=EXTI_Line1;
	EXTI_InitStructure.EXTI_LineCmd=ENABLE;
	EXTI_InitStructure.EXTI_Mode=EXTI_Mode_Interrupt;
	EXTI_InitStructure.EXTI_Trigger=EXTI_Trigger_Falling;  // 下降沿触发
	EXTI_Init(&EXTI_InitStructure);
	
	// 配置NVIC分组 只需配置一次
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
	// 配置NVIC
	NVIC_InitTypeDef NVIC_InitStructure;
	NVIC_InitStructure.NVIC_IRQChannel=EXTI1_IRQn;
	NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=0;  // 抢占优先级
	NVIC_InitStructure.NVIC_IRQChannelSubPriority=0;  // 响应优先级
	NVIC_Init(&NVIC_InitStructure);
	
}

/*
 *  EXTI 中断函数
 */
void EXTI1_IRQHandler(void)
{
	if(EXTI_GetITStatus(EXTI_Line1))
	{
		// 消抖
		Delay_ms(40);
		if(GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_1)==0)
		{	
			Serve_Angle += 30;
		}
		while(GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_1)==0);
		if(Serve_Angle>180)
		{
			Serve_Angle = 0;
		}
		Server_SetAngle((float)Serve_Angle);
		// 清除标志位
		EXTI_ClearITPendingBit(EXTI_Line1);
	}

}

// 机智云模式配置按钮 AirLink SoftAP Reset 三种模式
void Key_WIFIModeInit(void)
{
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
	
	GPIO_InitTypeDef GPIO_InitStructure;
	// PB10 按下低电平 配置成上拉输入
	GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IPU;
	GPIO_InitStructure.GPIO_Pin=GPIO_Pin_10;
	GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
	GPIO_Init(GPIOB, &GPIO_InitStructure);
	
	// PB12 PB13 按下高电平 配置成下拉输入
	GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IPD;
	GPIO_InitStructure.GPIO_Pin=GPIO_Pin_12|GPIO_Pin_14;
	GPIO_Init(GPIOB, &GPIO_InitStructure);
	
	// AFIO
	GPIO_EXTILineConfig(GPIO_PortSourceGPIOB, GPIO_PinSource10);
	GPIO_EXTILineConfig(GPIO_PortSourceGPIOB, GPIO_PinSource12);
	GPIO_EXTILineConfig(GPIO_PortSourceGPIOB, GPIO_PinSource14);
	
	// EXTI
	// PB1 下降沿触发
	EXTI_InitTypeDef EXTI_InitStructure;
	EXTI_InitStructure.EXTI_Line=EXTI_Line10;
	EXTI_InitStructure.EXTI_LineCmd=ENABLE;
	EXTI_InitStructure.EXTI_Mode=EXTI_Mode_Interrupt;
	EXTI_InitStructure.EXTI_Trigger=EXTI_Trigger_Falling; 
	EXTI_Init(&EXTI_InitStructure);
	
	// PB12 PB14 上升沿触发
	EXTI_InitStructure.EXTI_Line=EXTI_Line12|EXTI_Line14;
	EXTI_InitStructure.EXTI_Trigger=EXTI_Trigger_Rising;
	EXTI_Init(&EXTI_InitStructure);

	// NVIC
	NVIC_InitTypeDef NVIC_InitStructure;
	NVIC_InitStructure.NVIC_IRQChannel=EXTI15_10_IRQn;
	NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=0;  // 抢占优先级
	NVIC_InitStructure.NVIC_IRQChannelSubPriority=1;  // 响应优先级
	NVIC_Init(&NVIC_InitStructure);
}

/*
 *	EXTI通道10-15中断函数 PB10 PB12 PB14 分别对应WIFI模块工作的三种模式
 */
void EXTI15_10_IRQHandler(void)
{
	if(EXTI_GetITStatus(EXTI_Line10))
	{
		// 消抖
		Delay_ms(40);
		if(GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_10)==0)
		{	
			gizwitsSetMode(WIFI_AIRLINK_MODE);
			GIZWITS_LOG("AirLink mode\r\n");
		}
		while(GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_10)==0);
		
		// clear
		EXTI_ClearITPendingBit(EXTI_Line10);
	}
	else if(EXTI_GetITStatus(EXTI_Line12))
	{
		// 消抖
		Delay_ms(40);
		if(GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_12)==1)
		{	
			gizwitsSetMode(WIFI_SOFTAP_MODE);
			GIZWITS_LOG("Soft AP mode\r\n");  
		}
		while(GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_12)==1);
		
		// clear
		EXTI_ClearITPendingBit(EXTI_Line12);
	}
	else if(EXTI_GetITStatus(EXTI_Line14))
	{
		// 消抖
		Delay_ms(40);
		if(GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_14)==1)
		{	
			gizwitsSetMode(WIFI_RESET_MODE);
			GIZWITS_LOG("Reset mode\r\n");
		}
		while(GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_14)==1);
		// clear
		EXTI_ClearITPendingBit(EXTI_Line14);
	}

}

gizwits_product.c (注释掉Hal库的内容, 替换成ST库,完成User Handle部分内容)

/**
************************************************************
* @file         gizwits_product.c
* @brief        Gizwits control protocol processing, and platform-related       hardware initialization 
* @author       Gizwits
* @date         2017-07-19
* @version      V03030000
* @copyright    Gizwits
* 
* @note         机智云.只为智能硬件而生
*               Gizwits Smart Cloud  for Smart Products
*               链接|增值ֵ|开放|中立|安全|自有|自由|生态
*               www.gizwits.com
*
***********************************************************/

#include <stdio.h>
#include <string.h>
// #include "hal_key.h"
#include "gizwits_product.h"
#include "common.h"
#include "LED.h"
#include "Server.h"
#include "AD.h"
static uint32_t timerMsCount;
//static uint32_t timerMsCount;
uint8_t aRxBuffer;

/** User area the current device state structure*/
dataPoint_t currentDataPoint;

//extern TIM_HandleTypeDef htim2;
//extern UART_HandleTypeDef huart1;
//extern UART_HandleTypeDef huart2;

/**@} */
/**@name Gizwits User Interface
* @{
*/

/**
* @brief Event handling interface

* Description:

* 1. Users can customize the changes in WiFi module status

* 2. Users can add data points in the function of event processing logic, such as calling the relevant hardware peripherals operating interface

* @param [in] info: event queue
* @param [in] data: protocol data
* @param [in] len: protocol data length
* @return NULL
* @ref gizwits_protocol.h
*/
int8_t gizwitsEventProcess(eventInfo_t *info, uint8_t *gizdata, uint32_t len)
{
    uint8_t i = 0;
    dataPoint_t *dataPointPtr = (dataPoint_t *)gizdata;
    moduleStatusInfo_t *wifiData = (moduleStatusInfo_t *)gizdata;
    protocolTime_t *ptime = (protocolTime_t *)gizdata;
    
#if MODULE_TYPE
    gprsInfo_t *gprsInfoData = (gprsInfo_t *)gizdata;
#else
    moduleInfo_t *ptModuleInfo = (moduleInfo_t *)gizdata;
#endif

    if((NULL == info) || (NULL == gizdata))
    {
        return -1;
    }

    for(i=0; i<info->num; i++)
    {
        switch(info->event[i])
        {


        case EVENT_Angle:
            currentDataPoint.valueAngle = dataPointPtr->valueAngle;
            GIZWITS_LOG("Evt:EVENT_Angle %4f\n",currentDataPoint.valueAngle);
            //user handle
			Serve_Angle=currentDataPoint.valueAngle;
			Server_SetAngle(currentDataPoint.valueAngle);  // 设置电机角度
            break;


        case WIFI_SOFTAP:
            break;
        case WIFI_AIRLINK:
            break;
        case WIFI_STATION:
            break;
        case WIFI_CON_ROUTER:
 
            break;
        case WIFI_DISCON_ROUTER:
 
            break;
        case WIFI_CON_M2M:
 
            break;
        case WIFI_DISCON_M2M:
            break;
        case WIFI_RSSI:
            GIZWITS_LOG("RSSI %d\n", wifiData->rssi);
            break;
        case TRANSPARENT_DATA:
            GIZWITS_LOG("TRANSPARENT_DATA \n");
            //user handle , Fetch data from [data] , size is [len]
            break;
        case WIFI_NTP:
            GIZWITS_LOG("WIFI_NTP : [%d-%d-%d %02d:%02d:%02d][%d] \n",ptime->year,ptime->month,ptime->day,ptime->hour,ptime->minute,ptime->second,ptime->ntp);
            break;
        case MODULE_INFO:
            GIZWITS_LOG("MODULE INFO ...\n");
#if MODULE_TYPE
            GIZWITS_LOG("GPRS MODULE ...\n");
            //Format By gprsInfo_t
            GIZWITS_LOG("moduleType : [%d] \n",gprsInfoData->Type);
#else
            GIZWITS_LOG("WIF MODULE ...\n");
            //Format By moduleInfo_t
            GIZWITS_LOG("moduleType : [%d] \n",ptModuleInfo->moduleType);
#endif
        break;
        default:
            break;
        }
    }

    return 0;
}

/**
* User data acquisition

* Here users need to achieve in addition to data points other than the collection of data collection, can be self-defined acquisition frequency and design data filtering algorithm

* @param none
* @return none
*/
void userHandle(void)
{
	currentDataPoint.valueLED = LED_Info();//Add Sensor Data Collection
    currentDataPoint.valueAD_Voltage = AD_Voltage;//Add Sensor Data Collection
}

/**
* Data point initialization function

* In the function to complete the initial user-related data
* @param none
* @return none
* @note The developer can add a data point state initialization value within this function
*/
void userInit(void)
{
    memset((uint8_t*)&currentDataPoint, 0, sizeof(dataPoint_t));
    
    /** Warning !!! DataPoint Variables Init , Must Within The Data Range **/ 
    /*
    currentDataPoint.valueLED = ;
    currentDataPoint.valueAD_Voltage = ;
    currentDataPoint.valueAngle = ;
    */

}


/**
* @brief Millisecond timing maintenance function, milliseconds increment, overflow to zero

* @param none
* @return none
*/
void gizTimerMs(void)
{
    timerMsCount++;
}

/**
* @brief Read millisecond count

* @param none
* @return millisecond count
*/
uint32_t gizGetTimerCount(void)
{
    return timerMsCount;
}

/**
* @brief MCU reset function

* @param none
* @return none
*/
void mcuRestart(void)
{
    __set_FAULTMASK(1);
    NVIC_SystemReset();
}

/**@} */

#ifdef __GNUC__
  /* With GCC/RAISONANCE, small printf (option LD Linker->Libraries->Small printf
     set to 'Yes') calls __io_putchar() */
  #define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
#else
  #define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
#endif /* __GNUC__ */
/**
  * @brief  Retargets the C library printf function to the USART.
  * @param  None
  * @retval None
  */
PUTCHAR_PROTOTYPE
{
  /* Place your implementation of fputc here */
  /* e.g. write a character to the USART1 and Loop until the end of transmission */
//  HAL_UART_Transmit(&huart1, (uint8_t *)&ch, 1, 0xFFFF);
	USART_SendData(USART1, (uint8_t)ch);
	while(USART_GetFlagStatus(USART1, USART_FLAG_TXE)==RESET);
	return ch;
}

///**
//  * @brief  Period elapsed callback in non blocking mode 
//  * @param  htim : TIM handle
//  * @retval None
//  */
//void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
//{
//	if(htim==&htim2)
//	{
//			keyHandle();
//			gizTimerMs();
//	}
//}

///**
//* @brief Timer TIM3 init function

//* @param none
//* @return none
//*/
//void timerInit(void)
//{
//	HAL_TIM_Base_Start_IT(&htim2);
//}

///**
//  * @brief  This function handles USART IDLE interrupt.
//  */
//void HAL_UART_RxCpltCallback(UART_HandleTypeDef*UartHandle)  
//{  
//    if(UartHandle->Instance == USART2)  
//    {  
//				gizPutData((uint8_t *)&aRxBuffer, 1);

//        HAL_UART_Receive_IT(&huart2, (uint8_t *)&aRxBuffer, 1);//开启下一次接收中断  
//    }  
//}  

///**
//* @brief USART init function

//* Serial communication between WiFi modules and device MCU
//* @param none
//* @return none
//*/
//void uartInit(void)
//{
//	HAL_UART_Receive_IT(&huart2, (uint8_t *)&aRxBuffer, 1);//开启下一次接收中断  
//}

/**
* @brief Serial port write operation, send data to WiFi module
*
* @param buf      : buf address
* @param len      : buf length
*
* @return : Return effective data length;-1,return failure
*/
int32_t uartWrite(uint8_t *buf, uint32_t len)
{
	uint8_t crc[1] = {0x55};
    uint32_t i = 0;
	
    if(NULL == buf)
    {
        return -1;
    }

    for(i=0; i<len; i++)
    {
//        HAL_UART_Transmit_IT(&huart2, (uint8_t *)&buf[i], 1);
//				while (huart2.gState != HAL_UART_STATE_READY);//Loop until the end of transmission

//        if(i >=2 && buf[i] == 0xFF)
//        {
//						HAL_UART_Transmit_IT(&huart2, (uint8_t *)&crc, 1);
//						while (huart2.gState != HAL_UART_STATE_READY);//Loop until the end of transmission
//        }
		USART_SendData(USART2, (uint8_t)buf[i]);
		while(USART_GetFlagStatus(USART2, USART_FLAG_TXE)==RESET);
		if(i>=2 && buf[i] == 0xFF)
		{
			USART_SendData(USART2, crc[0]);
			while(USART_GetFlagStatus(USART2, USART_FLAG_TXE)==RESET);
		}
    }

#ifdef PROTOCOL_DEBUG
    GIZWITS_LOG("MCU2WiFi[%4d:%4d]: ", gizGetTimerCount(), len);
    for(i=0; i<len; i++)
    {
        GIZWITS_LOG("%02x ", buf[i]);

        if(i >=2 && buf[i] == 0xFF)
        {
            GIZWITS_LOG("%02x ", 0x55);
        }
    }
    GIZWITS_LOG("\n");
#endif
		
		return len;
}  

gizwits_protocol.c (注释掉Hal库的代码)

main.c

#include "stm32f10x.h" 
#include "delay.h"
#include "OLED.h"
#include "key.h"
#include "Server.h"
#include "Timer.h"
#include "Serial.h"
#include "AD.h"
#include "LED.h"
#include "gizwits_protocol.h"
#include "gizwits_product.h"

/*
 *  单片机课设
 *  2023年4月18日16:06:37
 *  需求: 1. 上位机控制舵机旋转的角度(0-180°)
 *        2. 每5秒返回一次信息(传给上位机和OLED屏幕)
 *        3. 按下按键使舵机角度增加30°(若超过180°则回到0°)
 *        4. LED灯闪烁作为系统指示灯
 *        5. 光敏传感器 控制蜂鸣器报警
 *        6. 加入机智云物联网方案
 *  程序设计:
 *        1. 硬件: STM32F103c8t6、面包板、舵机、OLED屏幕
 *        2. 上位机与单片机的通信用USART1和DMA1(PA9 Tx, PA10 Rx)
 *        3. TIM1用来计时
 *        4. TIM2_CH1 用来输出PWM信号控制舵机旋转角度  PA0
 * 		  5. B6、B7、B8、B9接OLED屏幕
 *        6. PA1作为按键输入 
 */

void Gitwits_Init(void)
{
	Timer_TIM3Init(10-1, 7200-1);  // 1ms
	Serial_WIFI_Init(9600);  // 波特率9600
	Serial_DebugInit();  // 串口初始化
	userInit();  // 数据初始化
	gizwitsInit();  // 机智云初始化
	Key_WIFIModeInit();  // 模式选择按键初始化
}

int main(void)
{
	OLED_Init();
	Gitwits_Init();
	Key_Init();
	Server_Init();
	AD_Init();
	LED_Init();
	OLED_ShowString(1, 1, "Angle:");
	OLED_ShowString(2, 1, "AD_Value:");
	OLED_ShowString(3, 1, "Voltage:0.00V");
	
	while(1)
	{
		gizwitsHandle((dataPoint_t *)&currentDataPoint);  // 机智云协议处理 必须
		OLED_ShowNum(1, 7, Serve_Angle, 3);
		OLED_ShowNum(2, 10, AD_Value, 4);
		AD_Voltage = (float)AD_Value*3.3/4096;
		OLED_ShowNum(3, 9, AD_Voltage, 1);
		OLED_ShowNum(3, 11, (uint16_t)(AD_Voltage * 100)% 100, 2);
		LED_Off();
		userHandle(); //数据上行 必须  上行的数据可在gizwits_product.c中修改
	}
}

4. 其他代码 (MCU实现的功能)

LED.c

#include "stm32f10x.h"
#include "delay.h"

/*
 *	初始化LED  PB10  低电平驱动
 */
void LED_Init(void)
{
	// RCC使能时钟
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
	
	// 配置GPIO
	GPIO_InitTypeDef GPIO_InitStructure;
	GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP;
	GPIO_InitStructure.GPIO_Pin=GPIO_Pin_10;
	GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
	GPIO_Init(GPIOB, &GPIO_InitStructure);
	
	GPIO_SetBits(GPIOB, GPIO_Pin_10);
}

/*
 *  LED灭
 */
void LED_Off(void)
{
	GPIO_SetBits(GPIOB, GPIO_Pin_10);
}

/*
 *  LED亮
 */
void LED_On(void)
{
	GPIO_ResetBits(GPIOB, GPIO_Pin_10);

}

uint8_t LED_Info(void)
{
	return GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_10);
}
#include "stm32f10x.h"
#include "delay.h"

/*
 *	初始化LED  PB10  低电平驱动
 */
void LED_Init(void)
{
	// RCC使能时钟
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
	
	// 配置GPIO
	GPIO_InitTypeDef GPIO_InitStructure;
	GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP;
	GPIO_InitStructure.GPIO_Pin=GPIO_Pin_10;
	GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
	GPIO_Init(GPIOB, &GPIO_InitStructure);
	
	GPIO_SetBits(GPIOB, GPIO_Pin_10);
}

/*
 *  LED灭
 */
void LED_Off(void)
{
	GPIO_SetBits(GPIOB, GPIO_Pin_10);
}

/*
 *  LED亮
 */
void LED_On(void)
{
	GPIO_ResetBits(GPIOB, GPIO_Pin_10);

}

uint8_t LED_Info(void)
{
	return GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_10);
}

Server.c (舵机驱动)

#include "stm32f10x.h"
float Serve_Angle;
// TIM2_CH1 用来输出PWM信号控制舵机旋转角度  PA0
// 频率50Hz
void Server_Init(void)
{
	// RCC使能时钟
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
	
	// 配置GPIO
	GPIO_InitTypeDef GPIO_InitStructure;
	GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF_PP;
	GPIO_InitStructure.GPIO_Pin=GPIO_Pin_0;
	GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
	GPIO_Init(GPIOA, &GPIO_InitStructure);

	// 选择内部时钟作为TIM2的时钟
	TIM_InternalClockConfig(TIM2);
	
	// 配置时基单元
	TIM_TimeBaseInitTypeDef TimeBase_InitStructure;
	TimeBase_InitStructure.TIM_ClockDivision=TIM_CKD_DIV1;
	TimeBase_InitStructure.TIM_CounterMode=TIM_CounterMode_Up;
	TimeBase_InitStructure.TIM_Period=20000-1;   // ARR
	TimeBase_InitStructure.TIM_Prescaler=72-1;
	TimeBase_InitStructure.TIM_RepetitionCounter=0;
	TIM_TimeBaseInit(TIM2, &TimeBase_InitStructure);
	
	// 配置OC单元(输出比较单元 OutPut Compare)  OC1
	TIM_OCInitTypeDef OC_InitStructure;
	TIM_OCStructInit(&OC_InitStructure);
	OC_InitStructure.TIM_OCMode=TIM_OCMode_PWM1;
	OC_InitStructure.TIM_Pulse=0;  // CCR寄存器
	OC_InitStructure.TIM_OCPolarity=TIM_OCPolarity_High; // 设置有效电平
	OC_InitStructure.TIM_OutputState=TIM_OutputState_Enable;
	TIM_OC1Init(TIM2, &OC_InitStructure);
	
	// 开启TIM
	TIM_Cmd(TIM2, ENABLE);
}

/*
 *  设置OC1 CCR寄存器的值
 */
void Server_Set_Compare1(uint16_t Compare)
{
	TIM_SetCompare1(TIM2, Compare);  
}


/*
	设置舵机角度 
	因为舵机需要20ms的波长来驱动 可知频率为50Hz 若ARR设置为 20000-1 则PSC设置为72-1
	又0.5ms~2.5ms对应舵机角度的0~180°
	0.5ms 对应ARR为500  2.5ms 对应ARR为2500
	对应角度的CCR应该设置为(Angle / 180 * 2000 + 500)
*/
void Server_SetAngle(float Angle)
{
	Server_Set_Compare1(Angle / 180 * 2000 + 500);
}


AD.c

#include "stm32f10x.h"
#include "MyDMA.h"
#include "LED.h"
uint16_t AD_Value;
float AD_Voltage;
/*
 *  初始化ADC
 */
void AD_Init(void)
{
	// 初始化DMA通道1运输ADC1的数据
	AD_MyDMA_Init();
	// RCC使能时钟
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);
	RCC_ADCCLKConfig(RCC_PCLK2_Div6);  // 12MHz mm
	// 配置GPIO口
	GPIO_InitTypeDef GPIO_InitStructure;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7;
	GPIO_Init(GPIOA, &GPIO_InitStructure);
	// 选择规则通道
	ADC_RegularChannelConfig(ADC1, ADC_Channel_7, 1, ADC_SampleTime_55Cycles5);
	
	// 配置ADC转换器
	ADC_InitTypeDef ADC_InitStructure;
	ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;  // 单次转换或者连续转换
	ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;  // 数据对齐模式
	ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;  // ADC模式, 单独还是交叉
	ADC_InitStructure.ADC_NbrOfChannel = 1;  // 扫描的通道数
	ADC_InitStructure.ADC_ScanConvMode = DISABLE;  // 扫描模式或者非扫描模式
	ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;  // 触发控制
	ADC_Init(ADC1, &ADC_InitStructure);
	
	// 开启DMA转运
	ADC_DMACmd(ADC1, ENABLE);
	
	// 开启模拟看门狗
	ADC_AnalogWatchdogThresholdsConfig(ADC1, 0xFFF, 0x5DC);  // 设置看门狗阈值
	ADC_AnalogWatchdogSingleChannelConfig(ADC1, ADC_Channel_7); // 对通道7设置看门狗
	ADC_AnalogWatchdogCmd(ADC1, ADC_AnalogWatchdog_SingleRegEnable);  // 使能单通道模拟看门狗
	ADC_ITConfig(ADC1, ADC_IT_AWD, ENABLE);  // 开启模拟看门狗中断
	
	// 配置NVCI
	NVIC_InitTypeDef NVIC_InitStructure;
	NVIC_InitStructure.NVIC_IRQChannel=ADC1_2_IRQn;
	NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=0;
	NVIC_InitStructure.NVIC_IRQChannelSubPriority=2;
	NVIC_Init(&NVIC_InitStructure);
	// 开启ADC功能
	ADC_Cmd(ADC1, ENABLE);
	
	// ADC校准
	ADC_ResetCalibration(ADC1);
	while(ADC_GetResetCalibrationStatus(ADC1) == SET);  // 已初始化为零
	ADC_StartCalibration(ADC1);
	while (ADC_GetCalibrationStatus(ADC1) == SET); 
	ADC_SoftwareStartConvCmd(ADC1, ENABLE);
}

/*
 *  ADC中断函数
 */
void ADC1_2_IRQHandler(void)
{
	if(ADC_GetITStatus(ADC1, ADC_IT_AWD)==SET)
	{
		// 开启警报灯
		LED_On();
		// 清除中断标志
		ADC_ClearITPendingBit(ADC1, ADC_IT_AWD);
	}

}

MyDMA.c

#include "stm32f10x.h"
#include "Serial.h"
#include "AD.h"
#define TXBUFFERSIZE 11
#define RXBUFFERSIZE 15

/*
 *	ADC DMA初始化
 */
void AD_MyDMA_Init(void)
{
	// RCC使能时钟
	RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);
	// 配置DMA
	DMA_InitTypeDef DMA_InitStructure;
	DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&ADC1->DR; // ADC的数据寄存器
	DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;
	// 地址非自增, ADC可以理解为上菜的桌子只有一个
	DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;  
	DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)&AD_Value;  // 保存的地址
	DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;
	DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;  // 这里要自增
	DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;  // 转运方向
	DMA_InitStructure.DMA_BufferSize = 1;
	DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;  // 自动重装
	DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;	 // 硬件触发
	DMA_InitStructure.DMA_Priority = DMA_Priority_Medium;
	DMA_Init(DMA1_Channel1, &DMA_InitStructure);
	// 开启DMA
	DMA_Cmd(DMA1_Channel1, ENABLE);  // 通道1
}

将移植后的代码下载进单片机中,连接好硬件电路后,即可进入下一步

接线示范 (仅供参考,根据自己的实际需求接)

机智云esp8266,单片机学习笔记,嵌入式硬件,stm32,笔记,物联网,单片机

说明:

  • A2、A3为USART的端口,分别接WIFI模块的TX、RX
  • WIFI模块出了TX、RX和GND,其余引脚工作时接高电平(手册解释有些引脚浮空也行,但我这块实测都得接高电平)
  • B10、B12、B14为选择WIFI模块工作模式的三个按键分别对应(RESET、SoftAP、AirLink)
  • A7为光敏传感器模拟信号输入口
  • A0为控制舵机PWM信号输出口
  • A1接按键,控制角度加30°
  • 这里USART1的A9、A10未接线,可接USB转TTL模块将调试信息打印到电脑的串口助手

5. 设备连网

  1. 准备工作

    需要: 机智云APP,两台移动设备(手机,一台用来开热点,热点频率为2.4G)

  2. 机智云APP下载

机智云esp8266,单片机学习笔记,嵌入式硬件,stm32,笔记,物联网,单片机

  1. 用另外一台设备开启热点 (注意频段为2.4G)

机智云esp8266,单片机学习笔记,嵌入式硬件,stm32,笔记,物联网,单片机

  1. 进入机智云连接设备,然后…
    机智云esp8266,单片机学习笔记,嵌入式硬件,stm32,笔记,物联网,单片机
    机智云esp8266,单片机学习笔记,嵌入式硬件,stm32,笔记,物联网,单片机

输入热点密码,下一步

机智云esp8266,单片机学习笔记,嵌入式硬件,stm32,笔记,物联网,单片机

选择乐鑫 (选择模块对应的模组) 继续点直到进入,这时候先别点,先按下B10的按键(SoftAP模式的按键)让模组进入SoftAP工作模式,然后点几蓝色字体

机智云esp8266,单片机学习笔记,嵌入式硬件,stm32,笔记,物联网,单片机

点击XPG-GAgent-7067(漏了一步,在点击XPG前,手机要先连上热点)

机智云esp8266,单片机学习笔记,嵌入式硬件,stm32,笔记,物联网,单片机

若找不到: XPG开头的,则可将MCU与WIFI模组通信的串口的发送口,通过USB转TTL接到电脑上,用串口助手查看发送的信息是否正确(与实操02中的协议一致),若不一致则需进一步进行检查

机智云esp8266,单片机学习笔记,嵌入式硬件,stm32,笔记,物联网,单片机

还有一种情况,需接受调试串口的信息,看程序是否运行正常,见参考资料【STM32移植机智云】超详细教程#2ESP8266移植机智云教程‘代码移植的最后

这是大佬文章的最后:
机智云esp8266,单片机学习笔记,嵌入式硬件,stm32,笔记,物联网,单片机

回到机智云调试APP,等待设备连接

机智云esp8266,单片机学习笔记,嵌入式硬件,stm32,笔记,物联网,单片机

若连接失败: 则检查热点质量,检查输入的热点密码是否正确

可以看到设备在线,点进去后

机智云esp8266,单片机学习笔记,嵌入式硬件,stm32,笔记,物联网,单片机

可以通过手机控制舵机的角度

机智云esp8266,单片机学习笔记,嵌入式硬件,stm32,笔记,物联网,单片机

参考资料

本小节参考以下资料

参考文档:

独立MCU方案接入机智云 - Gizwits

GAgent详解 - Gizwits

安信可ESP8266系列接入机智云方案及问题排查指引 - Gizwits

参考视频:

【机智云带你一节课入门物联网APP开发】

【机智云移植到stm32F103C8T6基于标准库】

参考博客:

【STM32移植机智云】超详细教程#2ESP8266移植机智云教程‘代码移植

实操06: APP生成

  1. 创建 → \rightarrow 移动应用 → \rightarrow 应用名称、应用包名随便填(应用包名最好英文) → \rightarrow 关联应用,不关联
    在这里插入图片描述

  2. 关联应用 → \rightarrow 选择产品 (图标壁纸可以根据喜好,自己上传资源)

机智云esp8266,单片机学习笔记,嵌入式硬件,stm32,笔记,物联网,单片机
机智云esp8266,单片机学习笔记,嵌入式硬件,stm32,笔记,物联网,单片机

  1. 构建应用 → \rightarrow 应用构建 → \rightarrow 构建测试版

机智云esp8266,单片机学习笔记,嵌入式硬件,stm32,笔记,物联网,单片机

  1. 构建成功后可以用手机下载

机智云esp8266,单片机学习笔记,嵌入式硬件,stm32,笔记,物联网,单片机

  1. 添加设备 (过程与在调试APP添加设备类似)

  2. 展示一下

机智云esp8266,单片机学习笔记,嵌入式硬件,stm32,笔记,物联网,单片机
机智云esp8266,单片机学习笔记,嵌入式硬件,stm32,笔记,物联网,单片机文章来源地址https://www.toymoban.com/news/detail-751437.html

到了这里,关于机智云案例(ESP8266模块接入机智云平台实现APP控制舵机旋转)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • ESP8266/ESP32 NodeMCU接入阿里云物联网平台

    阿里云物联网平台公共实例是免费的,且不像然也等服务器一样无法区分不同用户发布的话题。本文采用常规的pubsubclient库连接阿里云。ESP8266/ESP32用pubsubclient接入阿里云平台截至写稿的现在,网上有的资源较少,现在我就来介绍一下使用方法 1.登录阿里云官网https://www.aliyu

    2024年02月02日
    浏览(65)
  • esp8266 TCP接入巴法云物联网云平台

    前言 巴法云物联网云平台,就如它的文档介绍的,是一个专注物体联网的神奇的设备云平台(cloud.bemfa.com),它有以下特征,轻量级,支持发布/订阅模式,提供遗嘱机制,支持TCP长连接,全平台兼容。本文,将介绍如何通过esp8266这个芯片连接到巴法云的TCP设备云。 (一)注册

    2024年02月04日
    浏览(47)
  • ESP8266控制LED点灯和按钮,配合巴法云平台和微信小程序实现远程控制

    ESP8266控制LED点灯和按钮,配合巴法云平台和微信小程序实现远程控制 本文将介绍如何使用ESP8266控制LED点灯和按钮,同时利用巴法云平台和微信小程序实现远程控制。具体实现过程如下: 一、硬件准备 ESP8266模块 LED灯 按钮 杜邦线 面包板 二、开发环境搭建 ESP8266使用Arduino

    2024年02月12日
    浏览(49)
  • 使用ATK-ESP8266 WIFI 模块实现手机APP与DSP28027的数据传输(1)

           首先对AT--ESP8266进行简单的介绍,该模块有六个引脚,各引脚的功能如下图所示,在28027上留入SCI接口来进行数据的发送和接收。    28027硬件接口  对于AT--ESP8266,该WIFI集成模块可以有三个模式: 串口无线AP模式:产生WIFI信号,让其他设备连接 串口无线STA模式:站点

    2024年02月06日
    浏览(45)
  • ESP32/ESP8266 WIFI接入通过HTTP响应远程控制(附可用源码)

    ESP共有三种工作模式,分别是无线接入点模式(AP)、无线终端模式STA(Wireless Station)以及混合模式(以上两种模式的混合)。 ESP的WiFi设置是储存在它的闪存系统中的。因此在启动ESP8266并连接WiFi时,它都会尝试使用闪存系统中储存的信息来进行WiFi连接 连接网络基本步骤

    2023年04月09日
    浏览(43)
  • ESP8266WIFI模块(ESP01)上云端(OneNet平台,HTTP)

    1.注册账号并登录 Onenet平台 2.打开控制台 3.在控制台点击全部产品,选择基础服务的多协议接入 4.选择·HTTP并点击添加产品。 5.填写产品信息,名称随便起,行业任选一个,类别也任选,联网方式选择wifi 6.添加设备 并填写设备名称,随便起名个字,随便输入编号,但是同一

    2024年02月04日
    浏览(56)
  • stm32+AT指令+ESP8266接入华为云物联网平台并完成属性上报与命令响应

    (示例:stm32f103c8t6+esp 01s 串口A T 指令模式) 流程简介:       本期教程使用的是stm32+AT指令控制esp01s接入华为云联网平台完成数据上报与命令处理,在先前如果使用Arduino开发过后的esp8266可能已经无法使用AT指令,或者出厂固件不支持全部的MQTT功能,这里我们首先对esp8266进

    2024年02月02日
    浏览(50)
  • 从零开始,我的第一个物联网平台搭建好了,ESP8266+DHT11+阿里云平台+IOT StudioWEB应用开发,实现网页实时查看设备上报的信息,控制开关

        记录下自己做的第一个物联网项目,真正从零开始,断断续续花了2个月时间看各种视频,网站学习有关物联网的知识,期间碰到过好多问题,没有人指导,都得靠自己慢慢研究,有时会很迷茫,没有方向,但还得坚持下去,当经过自己的努力解决一个个问题时,会很兴奋

    2024年01月19日
    浏览(93)
  • STM32--ESP8266物联网WIFI模块(贝壳物联)--远程无线控制点灯

    本文适用于STM32F103C8T6等MCU,其他MCU可以移植,完整资源见文末链接 一、简介 随着移动物联网的发展,各场景下对于物联控制、数据上传、远程控制的诉求也越来越多,基于此乐鑫科技推出了便宜好用性价比极高的wifi物联模块——ESP8266,话不多少我们先来看看这个神奇的模

    2024年02月08日
    浏览(64)
  • ESP8266从点灯到遥控小车(三)——组装小车,0代码开发APP控制小车

    ESP8266开发板 已配置好的Arduino IDE环境(配置传送门) 数据线 L298N电机驱动模块 12V电池组(电源) 充电宝 小车车身及零件(传送门) 1.ESP8266-NodeMCU 开发板 ESP8266 是一款适用于物联网和家庭自动化项目的 Wi-Fi 模块。 ​ ESP8266-NodeMCU是一个开源硬件开发板,由于它允许您像使用

    2024年01月17日
    浏览(55)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包