stm32F407+ESP8266+AT指令+阿里云+代码进阶版(4)

(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
提取码:生日

  • 5
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
简单明了 oid sim_at_response(u8 mode) { if(USART2_RX_STA&0X8000) //接收到一次数据了 { USART2_RX_BUF[USART2_RX_STA&0X7FFF]=0;//添加结束符 printf("%s",USART2_RX_BUF); //发送到串口 if(mode)USART2_RX_STA=0; } } /////////////////////////////////////////////////////////////////////////////////////////////////////////// //ATK-SIM900A 各项测试(拨号测试、短信测试、GPRS测试)共用代码 //sim900a发送命令后,检测接收到的应答 //str:期待的应答结果 //返回值:0,没有得到期待的应答结果 // 其他,期待应答结果的位置(str的位置) u8* sim900a_check_cmd(u8 *str) { char *strx=0; if(USART2_RX_STA&0X8000) //接收到一次数据了 { USART2_RX_BUF[USART2_RX_STA&0X7FFF]=0;//添加结束符 strx=strstr((const char*)USART2_RX_BUF,(const char*)str); } return (u8*)strx; } //向sim900a发送命令 //cmd:发送的命令字符串(不需要添加回车了),当cmd<0XFF的时候,发送数字(比如发送0X1A),大于的时候发送字符串. //ack:期待的应答结果,如果为空,则表示不需要等待应答 //waittime:等待时间(单位:10ms) //返回值:0,发送成功(得到了期待的应答结果) // 1,发送失败 u8 sim900a_send_cmd(u8 *cmd,u8 *ack,u16 waittime) { u8 res=0; USART2_RX_STA=0; if((u32)cmd<=0XFF) { while(DMA1_Channel7->CNDTR!=0); //等待通道7传输完成 USART2->DR=(u32)cmd; }else u2_printf("%s\r\n",cmd);//发送命令 if(ack&&waittime) //需要等待应答 { while(--waittime) //等待倒计时 { delay_ms(10); if(USART2_RX_STA&0X8000)//接收到期待的应答结果 { if(sim900a_check_cmd(ack))break;//得到有效数据 USART2_RX_STA=0; } } if(waittime==0)res=1; } return res; } //将1个字符转换为16进制数字 //chr:字符,0~9/A~F/a~F //返回值:chr对应的16进制数值 u8 sim900a_chr2hex(u8 chr) { if(chr>='0'&&chr<='9')return chr-'0'; if(chr>='A'&&chr<='F')return (chr-'A'+10); if(chr>='a'&&chr<='f')return (chr-'a'+10); return 0; } //将1个16进制数字转换为字符 //hex:16进制数字,0~15; //返回值:字符 u8 sim900a_hex2chr(u8 hex) { if(hex<=9)return hex+'0'; if(hex>=10&&hex<=15)return (hex-10+'A'); return '0'; } //unicode gbk 转换函数 //src:输入字符串 //dst:输出(uni2gbk时为gbk内码,gbk2uni时,为unicode字符串) //mode:0,unicode到gbk转换; // 1,gbk到unicode转换; void sim900a_unigbk_exchange(u8 *src,u8 *dst,u8 mode) { u16 temp; u8 buf[2]; if(mode)//gbk 2 unicode { while(*src!=0) { if(*src<0X81) //非汉字 { temp=(u16)ff_convert((WCHAR)*src,1); src++; }else //汉字,占2个字节 { buf[1]=*src++; buf[0]=*src++; temp=(u16)ff_convert((WCHAR)*(u16*)buf,1); } *dst++=sim900a_hex2chr((temp>>12)&0X0F); *dst++=sim900a_hex2chr((temp>>8)&0X0F); *dst++=sim900a_hex2chr((temp>>4)&0X0F); *dst++=sim900a_hex2chr(temp&0X0F); } }else //unicode 2 gbk { while(*src!=0) { buf[1]=sim900a_chr2hex(*src++)*16; buf[1]+=sim900a_chr2hex(*src++); buf[0]=sim900a_chr2hex(*src++)*16; buf[0]+=sim900a_chr2hex(*src++); temp=(u16)ff_convert((WCHAR)*(u16*)buf,0); if(temp<0X80){*dst=temp;dst++;} else {*(u16*)dst=swap16(temp);dst+=2;} } }
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值