#include "usart2.h"
#include "esp8266.h"
usart2_handler u2_h;
void usart_2_init(void)//初始化的函数(初始化GPIO管脚和串口功能)
{
GPIO_InitTypeDef Gpio_Value;//定义了GPIO固件的结构体变量
USART_InitTypeDef Usart_Value;//定义了USART固件的结构体变量
NVIC_InitTypeDef Nvic_Value;//定义了NVIC固件的结构体变量
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
//通过APB2总线使能GPIOA组的时钟
RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);
//通过PAB1总线使能USART2的时钟
Gpio_Value.GPIO_Mode = GPIO_Mode_AF_PP;//选择了推挽的复用模式
Gpio_Value.GPIO_Pin = GPIO_Pin_2;//选择了 2 号管脚(PA2是发送管脚)
Gpio_Value.GPIO_Speed = GPIO_Speed_50MHz;//选择了50MHz的输出速度
GPIO_Init(GPIOA, &Gpio_Value);//按照上述配置初始化GPIOA组的管脚
Gpio_Value.GPIO_Mode = GPIO_Mode_IN_FLOATING;//选择了浮空的输入模式
Gpio_Value.GPIO_Pin = GPIO_Pin_3;//选择了 3 号管脚(PA3是接收管脚)
GPIO_Init(GPIOA, &Gpio_Value);//按照上述配置初始化GPIOA组的管脚
Usart_Value.USART_BaudRate = 115200;//选择了115200的波特率
Usart_Value.USART_HardwareFlowControl = USART_HardwareFlowControl_None;//选择了关闭硬件流控
Usart_Value.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;//选择了发送模式和接收模式
Usart_Value.USART_Parity = USART_Parity_No;//选择了没有奇偶校验
Usart_Value.USART_StopBits = USART_StopBits_1;//选择了1个停止位
Usart_Value.USART_WordLength = USART_WordLength_8b;//选择了8个数据位
USART_Init(USART2, &Usart_Value);//按照上述配置初始化USART2
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//配置组优先级和子优先级的所占比例
Nvic_Value.NVIC_IRQChannel = USART2_IRQn;//选择了USART2中断源的中断号
Nvic_Value.NVIC_IRQChannelCmd = ENABLE;//选择使能该中断
Nvic_Value.NVIC_IRQChannelPreemptionPriority = 2;//选择了组优先级的级别为2
Nvic_Value.NVIC_IRQChannelSubPriority = 2;//选择了子优先级的级别为2
NVIC_Init(&Nvic_Value);//按照上述配置初始化NVIC中断控制器
USART_ITConfig(USART2, USART_IT_RXNE, ENABLE);//使能了USART2的接收数据触发中断
USART_Cmd(USART2, ENABLE);//使能USART2的功能
}
void usart_2_send_byte(unsigned char c)//发送一个字节的数据
{
USART_SendData(USART2, c);//通过USART2把c变量保存的数据发送出去
while(USART_GetFlagStatus(USART2, USART_FLAG_TC) == RESET);//检验USART2的发送数据是否发送成功了(超时处理)
USART_ClearFlag(USART2, USART_FLAG_TC);//清除USART2的发送成功的标志状态
}
void usart_2_send_data(char *buf)//发送一个字符串的数据
{
while(*buf)//通过while循环把字符串中的有效字符遍历一遍
{
usart_2_send_byte(*buf);//把有效的字符进行发送
buf++;//让buf指针指向下一个字符
}
}
unsigned char usart_2_recv_byte(void)//接收一个字节数据
{
unsigned char ret = 0;//ret变量用来接收USART1接到的数据
if(USART_GetFlagStatus(USART2, USART_FLAG_RXNE) == SET)//判断USART2是否接收到了数据
{
ret = USART_ReceiveData(USART2);//把USART2接收到的数据保存到ret变量中
USART_ClearFlag(USART2, USART_FLAG_RXNE);//清除USART2接收到数据的标志
}
return ret;
}
void USART2_IRQHandler(void)
{
if(USART_GetITStatus(USART2, USART_IT_RXNE) == SET)//判断是否是由USART2的接收数据触发的中断
{
dataHandler(USART_ReceiveData(USART2));//接收USART1的数据,并把接收到的数据以传参的形式传递给回调函数
USART_ClearITPendingBit(USART2, USART_IT_RXNE);//清除USART1接收数据的中断标志
}
}
void set_usart2_handler(usart2_handler h)//设置回调函数
{
u2_h = h;//把形参h所存储的函数地址另存到全局变量u1_h中
}
ESP8266.h文件
#ifndef __ESP8266_H
#define __ESP8266_H
/*
ESP8266模块是WIFI无线通讯模块,该模块是串口接口
连接到了我们开发板上的USART2
*/
#include "stm32f10x_conf.h"//包含该头文件所有的外设头文件均已包含
typedef void (*wifi_recv_handler)(char *buf, int len);//通过typedef定义函数指针类型
extern void set_wifi_recv_handler(wifi_recv_handler h);//设置wifi接收到数据的回调函数
extern void esp8266_init(void);//初始化的函数(初始化串口)
extern void esp8266_link_wifi(char *ssid, char *passwd);//连接路由(需要路由的名称和路由的密码)
extern void esp8266_connect(char *ip, char *port);//连接TCP server
extern void esp8266_disconnect(void);//断开TCP连接
extern void esp8266_send(char *msg, char *len);//发送数据
extern void dataHandler(unsigned char c);//处理接收到的数据
#endif
ESP8266.c文件
#include "esp8266.h"
#include "usart2.h"
#include "delay.h"
#include "stdio.h"
#include "stdlib.h"
#define O_F 1//O的状态
#define K_F 2//K的状态
static int flag = O_F;
static int ok_flag = 0;
static int len = 0;//保存数据长度的整数
//"+IPD,13:1234567890ABC"
#define ADD_S 0//+的状态
#define I_S 1//I的状态
#define P_S 2//P的状态
#define D_S 3//D的状态
#define H_S 4//,的状态
#define LEN_S 5//长度的状态
#define DATA_S 6//数据的状态
static int data_flag = ADD_S;//默认是+的状态
wifi_recv_handler wifi_handler = NULL;
void set_wifi_recv_handler(wifi_recv_handler h)//设置wifi接收到数据的回调函数
{
wifi_handler = h;
}
void dataHandler(unsigned char c)//处理接收到的数据
{
static char len_buf[5];//接收到数据的字节数
static int i = 0;//循环变量
static char data_buf[512];//存储接收到的数据
switch(data_flag)
{
case ADD_S :
if(c == '+')
data_flag = I_S;
break;
case I_S :
if(c == 'I')
data_flag = P_S;
else
data_flag = ADD_S;
break;
case P_S :
if(c == 'P')
data_flag = D_S;
else
data_flag = ADD_S;
break;
case D_S :
if(c == 'D')
data_flag = H_S;
else
data_flag = ADD_S;
break;
case H_S :
if(c == ',')
data_flag = LEN_S;
else
data_flag = ADD_S;
break;
case LEN_S ://+IPD,13:1234567890ABC
if(c == ':')
{
len_buf[i] = '\0';
len = atoi(len_buf);
data_flag = DATA_S;
i = 0;
break;
}
else
len_buf[i] = c;
i++;
break;
case DATA_S:
data_buf[i] = c;
i++;
if(i == len)
{
i = 0;
data_flag = ADD_S;
if(wifi_handler)
wifi_handler(data_buf, len);
break;
}
break;
}
if(c == '>')
ok_flag = 1;
if(ok_flag == 0)
{
switch(flag)
{
case O_F :
if(c == 'O')
flag = K_F;
break;
case K_F :
if(c == 'K')
{
flag = O_F;
ok_flag = 1;
}
else
flag = O_F;
break;
}
}
}
void esp8266_init(void)//初始化的函数(初始化串口)
{
usart_2_init();
}
void esp8266_link_wifi(char *ssid, char *passwd)//连接路由(需要路由的名称和路由的密码)
{
//AT+RST\r\n 重启无线模块
usart_2_send_data("AT+RST\r\n");
delay_ms(2000);//重启之后延时两秒
//AT+CWMODE=1\r\n 选择wifi模式
ok_flag = 0;
usart_2_send_data("AT+CWMODE=1\r\n");//选择模式
while(ok_flag == 0);//等待esp8266的OK
//AT+CWJAP="SSID","password"\r\n 连接路由
ok_flag = 0;
usart_2_send_data("AT+CWJAP=");
usart_2_send_byte('"');
usart_2_send_data(ssid);
usart_2_send_byte('"');
usart_2_send_byte(',');
usart_2_send_byte('"');
usart_2_send_data(passwd);
usart_2_send_byte('"');
usart_2_send_data("\r\n");
while(ok_flag == 0);
//AT+CIFSR\r\n 查询分配到的IP地址(必须要查一下,否则无法建立连接)
usart_2_send_data("AT+CIFSR\r\n");
}
void esp8266_connect(char *ip, char *port)//连接TCP server
{
//AT+CIPSTART="TCP","192.168.3.116",8080\r\n 建立TCP连接
ok_flag = 0;
usart_2_send_data("AT+CIPSTART=");
usart_2_send_byte('"');
usart_2_send_data("TCP");
usart_2_send_byte('"');
usart_2_send_byte(',');
usart_2_send_byte('"');
usart_2_send_data(ip);
usart_2_send_byte('"');
usart_2_send_byte(',');
usart_2_send_data(port);
usart_2_send_data("\r\n");
while(ok_flag == 0);
}
void esp8266_disconnect(void)//断开TCP连接
{
//AT+CIPCLOSE\r\n 断开TCP连接
usart_2_send_data("AT+CIPCLOSE\r\n");
//注意:有可能回复有可能不回复,所以不检测closed ok
}
void esp8266_send(char *msg, char *len)//发送数据
{
//AT+CIPSEND=4\r\n 发送数据
ok_flag = 0;
usart_2_send_data("AT+CIPSEND=");
usart_2_send_data(len);
usart_2_send_data("\r\n");
while(ok_flag == 0);//等待 OK
ok_flag = 0;
while(ok_flag == 0);//等待 >
ok_flag = 0;
usart_2_send_data(msg);
while(ok_flag == 0);//等待 SEND OK
}
main.c
#include "led.h"//包含LED灯的头文件
#include "buzzer.h"//包含BUZZER的头文件
#include "button.h"//包含BUTTON的头文件
#include "delay.h"//包含DELAY的头文件
#include "eint.h"//包含EINT的头文件
#include "iwdg.h"//包含IWDG的头文件
#include "dht.h"//包含DHT的头文件
#include "ldt.h"//包含LDT的头文件
#include "usart1.h"//包含USART1的头文件
#include "stdio.h"//包含标准输入输出的头文件
#include "eeprom.h"//包含EEPROM的头文件
#include "oled.h"//包含OLED的头文件
#include "sht.h"//包含SHT30的头文件
#include "adj_res.h"//包含高精度可调电阻的头文件
#include "rtc.h"//包含RTC的头文件
#include "esp8266.h"//包含ESP8266的头文件
#include "string.h"//包含字符串解析的头文件
void recv_handler(char *buf, int len)//buf里存储的是数据的内容 len里存的是数据的字节数
{
if(strcmp(buf, "BUZZER_ON") == 0)
buzzer_on();
if(strcmp(buf, "BUZZER_OFF") == 0)
buzzer_off();
}
int main(void)
{
char dht_buf[5] = {0};//该数组用于存储DHT11采集到的数据
int dht_value = 0;//该变量用于存储DHT11温湿度结合的数据
int i = 500;//循环变量
int adc_value = 0;//存储高精度可调电阻转换的数据
u8 old_value = 97;//存储要保存的数据
u8 new_value = 0;//存储读取出的数据
double sht_data[2] = {0};//用于存储SHT30传感器采集到的数据
struct time_st old_time = {2021, 11, 29, 1, 15, 0, 0};//要设置的时间
struct time_st new_time;//保存获取到的时间
led_init();//调用LED灯初始化的函数
buzzer_init();//调用蜂鸣器初始化的函数
button_init();//调用功能按键初始化的函数
delay_init();//调用系统定时器初始化的函数
eint_init();//调用按键中断初始化的函数
dht_init();//调用DHT11初始化的函数
ldt_init();//调用数码管初始化的函数
usart_1_init();//调用USART1初始化的函数
eeprom_init();//调用EEPROM初始化的函数
OLED_Init();//调用OLED初始化的函数
sht_init();//调用SHT30初始化的函数
adj_res_init();//调用高精度可调电阻初始化的函数
rtc_init(&old_time);//调用RTC初始化的函数
esp8266_init();//调用ESP8266初始化的函数
OLED_Clear();//清屏
//OLED_ShowChar(0, 0, '%', 16);
//OLED_ShowNum(0, 0, 9527, 4, 16);
//OLED_ShowString(0, 0, "Hello World!", 16);
//OLED_ShowCHinese(0, 0, 7);
picture_1();
sht_write_mode();//设置SHT30的采样频率
led_on(0);
esp8266_link_wifi("UPIOT", "easthome");//需要填写自己的手机热点(需要配置为2.4GHz的频段)
delay_ms(2000);//延时2s
led_off(0);
led_on(1);
esp8266_connect("192.168.248.41", "2222");//建立TCP连接
delay_ms(2000);//延时2s
led_off(1);
//eeprom_byte_write(0xA0, 0x11, old_value);//写数据
set_wifi_recv_handler(recv_handler);//设置回调函数
while(1)
{
esp8266_send("Hello World", "11");
adc_value = get_adj_res_value();//获取高精度可调电阻转换的数据
get_time(&new_time);//把获取到的时间保存到new_time变量中
get_dht_value(dht_buf);//获取DHT11传感器采集到的数据
new_value = eeprom_rand_addr_read(0xA0, 0x11);//读取EEPROM的数据
sht_read_mode();//发送采集SHT30数据的指令
sht_read_data(sht_data);//获取SHT30采集的数据
printf("%d-%d-%d %d %02d:%02d:%02d\n", new_time.Y, new_time.M, new_time.D, new_time.W, new_time.h, new_time.m, new_time.s);
printf("DHT:%d-%d Eeprom:%d SHT:%.2f-%.2f ADC:%d\n", dht_buf[0], dht_buf[2], new_value, sht_data[0], sht_data[1], adc_value);
dht_value = dht_buf[0] * 100 + dht_buf[2];//把湿度的整数以及温度的整数整合成一个4位数据
while(i--)
digit_show_data(dht_value);//通过数码管显示温湿度数据
i = 500;
led_on(0);
delay_ms(500);
led_off(0);
delay_ms(500);
}
}