(1)esp8266.c
#include "esp8266.h"
char *wifi="317";
char *wifiPasswd="88888888";
//返回值:0,发送成功;1,发送失败
u8 esp8266_send_cmd(u8 *cmd,u8 *ack,u16 waittime)
{
u8 res=0;
USART3_RX_STA=0;
u3_printf("%s\r\n",cmd); //发送命令
if(ack&&waittime) //需要等待应答
{
while(--waittime) //等待倒计时
{
delay_ms(10);
if(USART3_RX_STA&0X8000)//接收到期待的应答结果
{
if(esp8266_check_cmd(ack))
{
printf("sendcmd_OK\r\n");
break;//得到有效数据
}
USART3_RX_STA=0;
}
}
if(waittime==0)
{
res=1;
printf("sendcmd_ERR\r\n");
}
}
return res;
}
u8* esp8266_check_cmd(u8 *str)
{
char *strx=0;
if(USART3_RX_STA&0X8000) //接收到一次数据了
{
USART3_RX_BUF[USART3_RX_STA&0X7FFF]=0;//添加结束符
strx=strstr((const char*)USART3_RX_BUF,(const char*)str);
}
return (u8*)strx;
}
//连接wifi
void esp8266_init(char *url)
{
char tempBuf[100]={0};
esp8266_send_cmd("AT+RST","ready",100);//让Wifi模块重启的命令
delay_ms(1000); //延时3S等待重启成功
delay_ms(1000);
delay_ms(1000);
//设置工作模式 1:station模式 2:AP模式 3:兼容 AP+station模式
esp8266_send_cmd("AT+CWMODE=1","OK",100);
esp8266_send_cmd("AT+CWAUTOCONN=0","OK",100);
sprintf(tempBuf,"AT+CWJAP=\"%s\",\"%s\"",wifi,wifiPasswd);
while(esp8266_send_cmd(tempBuf,"WIFI GOT IP",600));
esp8266_send_cmd("AT+CIPMODE=1","OK",20);
esp8266_send_cmd("AT+CIPMUX=0","OK",20);
sprintf(tempBuf,"AT+CIPSTART=\"TCP\",\"%s\",1883,1",url);
while(esp8266_send_cmd(tempBuf,"CONNECT",1000));
esp8266_send_cmd("AT+CIPMODE=1","OK",200);//是否开启透传模式 0:表示关闭 1:表示开启透传
esp8266_send_cmd("AT+CIPSEND","OK",50);//透传模式下 开始发送数据的指令 这个指令之后就可以直接发数据了
}
(2)esp8266.h
#ifndef __ESP8266_H
#define __ESP8266_H
#include "string.h"
#include "stdio.h"
#include "stdlib.h"
#include "usart3.h"
#include "stm32f4xx_conf.h"
#include "delay.h"
extern char *wifi;
extern char *wifiPasswd;
u8 esp8266_send_cmd(u8 *cmd,u8 *ack,u16 waittime);
u8* esp8266_check_cmd(u8 *str);
void esp8266_init(char *url);
#endif
(3)aliyun_mqtt.c
#include "aliyun_mqtt.h"
u8 *mqtt_rxbuf;
u8 *mqtt_txbuf;
u16 mqtt_rxlen;
u16 mqtt_txlen;
u8 _mqtt_txbuf[256];//发送数据缓存区
u8 _mqtt_rxbuf[256];//接收数据缓存区
const u8 parket_connetAck[] = {0x20,0x02,0x00,0x00};
const u8 parket_disconnet[] = {0xe0,0x00};
const u8 parket_heart[] = {0xc0,0x00};
const u8 parket_heart_reply[] = {0xc0,0x00};
const u8 parket_subAck[] = {0x90,0x03};
void MQTT_Init(void)
{
mqtt_rxbuf = _mqtt_rxbuf;
mqtt_rxlen = sizeof(_mqtt_rxbuf);
mqtt_txbuf = _mqtt_txbuf;
mqtt_txlen = sizeof(_mqtt_txbuf);
memset(mqtt_rxbuf,0,mqtt_rxlen);
memset(mqtt_txbuf,0,mqtt_txlen);
memset(USART3_RX_BUF,0,sizeof(USART3_RX_BUF));
USART3_RX_STA=0;
MQTT_Disconnect();
delay_ms(100);
MQTT_Disconnect();
delay_ms(100);
}
u8 MQTT_Connect(char *ClientID,char *Username,char *Password)
{
u8 i,j;
int ClientIDLen = strlen(ClientID);
int UsernameLen = strlen(Username);
int PasswordLen = strlen(Password);
int DataLen;
mqtt_txlen=0;
memset(mqtt_txbuf,0,mqtt_txlen);
DataLen = 10 + (ClientIDLen+2) + (UsernameLen+2) + (PasswordLen+2);
mqtt_txbuf[mqtt_txlen++] = 0x10;
do
{
u8 encodedByte = DataLen % 128;
DataLen = DataLen / 128;
if ( DataLen > 0 )
encodedByte = encodedByte | 128;
mqtt_txbuf[mqtt_txlen++] = encodedByte;
}while ( DataLen > 0 );
mqtt_txbuf[mqtt_txlen++] = 0; // Protocol Name Length MSB
mqtt_txbuf[mqtt_txlen++] = 4; // Protocol Name Length LSB
mqtt_txbuf[mqtt_txlen++] = 'M'; // ASCII Code for M
mqtt_txbuf[mqtt_txlen++] = 'Q'; // ASCII Code for Q
mqtt_txbuf[mqtt_txlen++] = 'T'; // ASCII Code for T
mqtt_txbuf[mqtt_txlen++] = 'T'; // ASCII Code for T
mqtt_txbuf[mqtt_txlen++] = 4; // MQTT Protocol version = 4
mqtt_txbuf[mqtt_txlen++] = 0xc2; // conn flags
mqtt_txbuf[mqtt_txlen++] = 0; // Keep-alive Time Length MSB
mqtt_txbuf[mqtt_txlen++] = 100; // Keep-alive Time Length LSB 100S心跳包
mqtt_txbuf[mqtt_txlen++] = BYTE1(ClientIDLen);// Client ID length MSB
mqtt_txbuf[mqtt_txlen++] = BYTE0(ClientIDLen);// Client ID length LSB
memcpy(&mqtt_txbuf[mqtt_txlen],ClientID,ClientIDLen);
mqtt_txlen += ClientIDLen;
if(UsernameLen > 0)
{
mqtt_txbuf[mqtt_txlen++] = BYTE1(UsernameLen); //username length MSB
mqtt_txbuf[mqtt_txlen++] = BYTE0(UsernameLen); //username length LSB
memcpy(&mqtt_txbuf[mqtt_txlen],Username,UsernameLen);
mqtt_txlen += UsernameLen;
}
if(PasswordLen > 0)
{
mqtt_txbuf[mqtt_txlen++] = BYTE1(PasswordLen); //password length MSB
mqtt_txbuf[mqtt_txlen++] = BYTE0(PasswordLen); //password length LSB
memcpy(&mqtt_txbuf[mqtt_txlen],Password,PasswordLen);
mqtt_txlen += PasswordLen;
}
for(i=0;i<10;i++)
{
memset(mqtt_rxbuf,0,mqtt_rxlen);
MQTT_SendBuf(mqtt_txbuf,mqtt_txlen);
for(j=0;j<10;j++)
{
delay_ms(50);
if(USART3_RX_STA&0x8000)
{
USART3_RX_BUF[USART3_RX_STA&0X7FFF]='\0';
sprintf((char *)mqtt_rxbuf,"%s",USART3_RX_BUF);
USART3_RX_STA=0;
memset(USART3_RX_BUF,0,sizeof(USART3_RX_BUF));
}
if(mqtt_rxbuf[0]==parket_connetAck[0] && mqtt_rxbuf[1]==parket_connetAck[1]) //连接成功
{
return 0;//连接成功
}
}
}
return 1;
}
/*
函数功能: MQTT订阅/取消订阅数据打包函数
函数参数:
topic 主题
qos 消息等级 0:最多分发一次 1: 至少分发一次 2: 仅分发一次
whether 订阅/取消订阅请求包 (1表示订阅,0表示取消订阅)
返回值: 0表示成功 1表示失败
*/
u8 MQTT_SubscribeTopic(char *topic,u8 qos,u8 whether)
{
u8 i,j;
int topiclen = strlen(topic);
int DataLen = 2 + (topiclen+2) + (whether?1:0);//可变报头的长度(2字节)加上有效载荷的长度
//固定报头
//控制报文类型
mqtt_txlen=0;
if(whether)mqtt_txbuf[mqtt_txlen++] = 0x82; //消息类型和标志订阅
else mqtt_txbuf[mqtt_txlen++] = 0xA2; //取消订阅
//剩余长度
do
{
u8 encodedByte = DataLen % 128;
DataLen = DataLen / 128;
// if there are more data to encode, set the top bit of this byte
if ( DataLen > 0 )
encodedByte = encodedByte | 128;
mqtt_txbuf[mqtt_txlen++] = encodedByte;
}while ( DataLen > 0 );
//可变报头
mqtt_txbuf[mqtt_txlen++] = 0; //消息标识符 MSB
mqtt_txbuf[mqtt_txlen++] = 0x01; //消息标识符 LSB
//有效载荷
mqtt_txbuf[mqtt_txlen++] = BYTE1(topiclen);//主题长度 MSB
mqtt_txbuf[mqtt_txlen++] = BYTE0(topiclen);//主题长度 LSB
memcpy(&mqtt_txbuf[mqtt_txlen],topic,topiclen);
mqtt_txlen += topiclen;
if(whether)
{
mqtt_txbuf[mqtt_txlen++] = qos;//QoS级别
}
for(i=0;i<10;i++)
{
memset(mqtt_rxbuf,0,mqtt_rxlen);
MQTT_SendBuf(mqtt_txbuf,mqtt_txlen);
for(j=0;j<10;j++)
{
delay_ms(50);
if((USART3_RX_STA&(1<<15))==1)
{
USART3_RX_BUF[USART3_RX_STA&0X7FFF]='\0';
sprintf((char *)mqtt_rxbuf,"%s",USART3_RX_BUF);
USART3_RX_STA=0;
}
if(mqtt_rxbuf[0]==parket_subAck[0] && mqtt_rxbuf[1]==parket_subAck[1]) //订阅成功
{
return 0;//订阅成功
}
}
}
return 1; //失败
}
//MQTT发布数据打包函数
//topic 主题
//message 消息
//qos 消息等级
u8 MQTT_PublishData(char *topic, char *message, u8 qos)
{
int topicLength = strlen(topic);
int messageLength = strlen(message);
static u16 id=0;
int DataLen;
mqtt_txlen=0;
//有效载荷的长度这样计算:用固定报头中的剩余长度字段的值减去可变报头的长度
//QOS为0时没有标识符
//数据长度 主题名 报文标识符 有效载荷
if(qos) DataLen = (2+topicLength) + 2 + messageLength;
else DataLen = (2+topicLength) + messageLength;
//固定报头
//控制报文类型
mqtt_txbuf[mqtt_txlen++] = 0x30; // MQTT Message Type PUBLISH
//剩余长度
do
{
u8 encodedByte = DataLen % 128;
DataLen = DataLen / 128;
// if there are more data to encode, set the top bit of this byte
if ( DataLen > 0 )
encodedByte = encodedByte | 128;
mqtt_txbuf[mqtt_txlen++] = encodedByte;
}while ( DataLen > 0 );
mqtt_txbuf[mqtt_txlen++] = BYTE1(topicLength);//主题长度MSB
mqtt_txbuf[mqtt_txlen++] = BYTE0(topicLength);//主题长度LSB
memcpy(&mqtt_txbuf[mqtt_txlen],topic,topicLength);//拷贝主题
mqtt_txlen += topicLength;
//报文标识符
if(qos)
{
mqtt_txbuf[mqtt_txlen++] = BYTE1(id);
mqtt_txbuf[mqtt_txlen++] = BYTE0(id);
id++;
}
memcpy(&mqtt_txbuf[mqtt_txlen],message,messageLength);
mqtt_txlen += messageLength;
MQTT_SendBuf(mqtt_txbuf,mqtt_txlen);
return mqtt_txlen;
}
void MQTT_SentHeart(void)
{
MQTT_SendBuf((u8 *)parket_heart,sizeof(parket_heart));
}
void MQTT_Disconnect(void)
{
MQTT_SendBuf((u8 *)parket_disconnet,sizeof(parket_disconnet));
}
void MQTT_SendByte(u8 val)
{
USART_SendData(USART3, val);
while (USART_GetFlagStatus(USART3, USART_FLAG_TC) == RESET); //等待发送完成
}
void MQTT_SendBuf(u8 *buf,u16 len)
{
while(len--) MQTT_SendByte(*buf++);
}
(4)aliyun_mqtt.h
#ifndef __ALIYUN_MQTT_H_
#define __ALIYUN_MQTT_H_
#include "string.h"
#include "stdio.h"
#include "stdlib.h"
#include "stm32f4xx_conf.h"
#include "usart3.h"
#include "delay.h"
#define BYTE0(dwTemp) (*( char *)(&dwTemp))
#define BYTE1(dwTemp) (*((char *)(&dwTemp) + 1))
#define BYTE2(dwTemp) (*((char *)(&dwTemp) + 2))
#define BYTE3(dwTemp) (*((char *)(&dwTemp) + 3))
//阿里云用户名初始化
void Aliyun_LoginInit(char *ProductKey,char *DeviceName,char *DeviceSecret);
//MQTT协议相关函数声明
u8 MQTT_PublishData(char *topic, char *message, u8 qos);
u8 MQTT_SubscribeTopic(char *topic,u8 qos,u8 whether);
void MQTT_Init(void);
u8 MQTT_Connect(char *ClientID,char *Username,char *Password);
void MQTT_SentHeart(void);
void MQTT_Disconnect(void);
void MQTT_SendBuf(u8 *buf,u16 len);
#endif
(5)main.h
#include "sys.h"
#include "delay.h"
#include "usart.h"
#include "led.h"
#include "beep.h"
#include "key.h"
#include "esp8266.h"
char *clientId = "k0wih08FdYq.ESP8266|securemode=2,signmethod=hmacsha256,timestamp=1710944829520|";
char *username = "ESP8266&k0wih08FdYq";
char *passwd = "7d293f515f969ddb5631f85eed895d823d32c6e9f865b0762957b519ab5b8c26";
char *mqttHostUrl = "iot-06z00jb2hfkrh6y.mqtt.iothub.aliyuncs.com";
int main(void)
{
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//设置系统中断优先级分组2
delay_init(168); //延时初始化
uart_init(115200); //串口初始化波特率为115200
LED_Init(); //初始化与LED连接的硬件接口
usart3_init(115200);
esp8266_init(mqttHostUrl);
printf("esp8266初始化成功\r\n");
MQTT_Init();
if(MQTT_Connect(clientId,username,passwd))
{
printf("阿里云连接失败\r\n");
}
else
{
printf("阿里云连接成功\r\n");
}
while(1){}
}
(6)完整工程代码
链接:https://pan.baidu.com/s/1LoOh5QivNyKUwPd3Mje0IA
提取码:生日