简介:

项目包含对下位机(MCU对外设数据读取与控制),上位机(APP端),云端(云服务平台)的设计。下位机选取正点原子STM32MINI板作为MCU;外设有LED灯,DS18B20温度传感器,ESP8266,OLED;上位机为制作APP;云端选用中国移动旗下的OneNet平台作为服务器。

引脚:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
LED:
PA8(自带)

DS18B20:
VCC --> 3.3V
GND --> GND
DATA-->PA0

ESP8266:
VCC --> 3.3V
GND --> GND
RX--> PA2
TX --> PA3
RST --> PC13
EN --> 3.3V

OLED:
VCC --> 3.3V
GND --> GND
SCL --> PC0
SDA --> PC1
RES --> PC2
DC --> PC3

接线图:

1

OneNet平台使用

注册OneNet平台账号

登入后选择控制台,进入后点击全部产品服务,选择多协议接入;(我们使用MQTT,既可以上传数据也可以下发数据控制,而且都是免费的)

选择MQTT(旧版)之后添加产品,按照自己实际需求填写产品内容;

点击所创建的产品,添加几个设备(免费版用户上限10个设备)

(主要获取信息根据产品概况设备列表的详情查看)

驱动代码

.c文件只截取关键信息函数功能不一一实现,.h文件有函数功能。

led.c

1
2
3
4
5
6
7
8
9
10
11
12
13
void LED_Init(void)
{

GPIO_InitTypeDef GPIO_InitStructure;

RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOD, ENABLE);

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
GPIO_ResetBits(GPIOA,GPIO_Pin_8); //置零,点亮LED
}

led.h

1
2
3
4
5
6
7
8
9
10
11
#ifndef __LED_H
#define __LED_H
#include "sys.h"

#define LED0 PAout(8)
#define LED1 PDout(2)

void LED_Init(void);

#endif

ds18b20.c

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
u8 DS18B20_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;

RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);

GPIO_SetBits(GPIOA,GPIO_Pin_0);

DS18B20_Rst();

return DS18B20_Check();
}

ds18b20.h

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
//IO方向设置
#define DS18B20_IO_IN() {GPIOA->CRL&=0XFFFFFFF0;GPIOA->CRL|=8<<0;}
#define DS18B20_IO_OUT() {GPIOA->CRL&=0XFFFFFFF0;GPIOA->CRL|=3<<0;}
//IO操作函数
#define DS18B20_DQ_OUT PAout(0)
#define DS18B20_DQ_IN PAin(0)

u8 DS18B20_Init(void); //初始化DS18B20
short DS18B20_Get_Temp(void); //获取温度
void DS18B20_Start(void); //开始温度转换
void DS18B20_Write_Byte(u8 dat);//写入一个字节
u8 DS18B20_Read_Byte(void); //读出一个字节
u8 DS18B20_Read_Bit(void); //读出一个位
u8 DS18B20_Check(void); //检测是否存在ds18b20
void DS18B20_Rst(void); //复位

oled.c

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
void OLED_Init(void)
{
GPIO_InitTypeDef GPIO_OLEDInitStruct;
RCC_APB2PeriphClockCmd(GPIO_OLED_CLK, ENABLE);
GPIO_OLEDInitStruct.GPIO_Pin = GPIO_OLED_SCLK_Pin | GPIO_OLED_PIN_Pin | GPIO_OLED_RES_Pin | GPIO_OLED_DC_Pin;
GPIO_OLEDInitStruct.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_OLEDInitStruct.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOC, &GPIO_OLEDInitStruct);
GPIO_SetBits(GPIOC,GPIO_OLED_SCLK_Pin|GPIO_OLED_PIN_Pin|GPIO_OLED_RES_Pin|GPIO_OLED_DC_Pin);

OLED_RST_Set();
delay_ms(100);
OLED_RST_Clr();
delay_ms(100);
OLED_RST_Set();

OLED_WR_Byte(0xAE,OLED_CMD);//--turn off oled panel
OLED_WR_Byte(0x00,OLED_CMD);//---set low column address
OLED_WR_Byte(0x10,OLED_CMD);//---set high column address
OLED_WR_Byte(0x40,OLED_CMD);//--set start line address Set Mapping RAM Display Start Line (0x00~0x3F)
OLED_WR_Byte(0x81,OLED_CMD);//--set contrast control register
OLED_WR_Byte(0xCF,OLED_CMD);// Set SEG Output Current Brightness
OLED_WR_Byte(0xA1,OLED_CMD);//--Set SEG/Column Mapping
OLED_WR_Byte(0xC8,OLED_CMD);//Set COM/Row Scan Direction
OLED_WR_Byte(0xA6,OLED_CMD);//--set normal display
OLED_WR_Byte(0xA8,OLED_CMD);//--set multiplex ratio(1 to 64)
OLED_WR_Byte(0x3f,OLED_CMD);//--1/64 duty
OLED_WR_Byte(0xD3,OLED_CMD);//-set display offset Shift Mapping RAM Counter (0x00~0x3F)
OLED_WR_Byte(0x00,OLED_CMD);//-not offset
OLED_WR_Byte(0xd5,OLED_CMD);//--set display clock divide ratio/oscillator frequency
OLED_WR_Byte(0x80,OLED_CMD);//--set divide ratio, Set Clock as 100 Frames/Sec
OLED_WR_Byte(0xD9,OLED_CMD);//--set pre-charge period
OLED_WR_Byte(0xF1,OLED_CMD);//Set Pre-Charge as 15 Clocks & Discharge as 1 Clock
OLED_WR_Byte(0xDA,OLED_CMD);//--set com pins hardware configuration
OLED_WR_Byte(0x12,OLED_CMD);
OLED_WR_Byte(0xDB,OLED_CMD);//--set vcomh
OLED_WR_Byte(0x40,OLED_CMD);//Set VCOM Deselect Level
OLED_WR_Byte(0x20,OLED_CMD);//-Set Page Addressing Mode (0x00/0x01/0x02)
OLED_WR_Byte(0x02,OLED_CMD);//
OLED_WR_Byte(0x8D,OLED_CMD);//--set Charge Pump enable/disable
OLED_WR_Byte(0x14,OLED_CMD);//--set(0x10) disable
OLED_WR_Byte(0xA4,OLED_CMD);// Disable Entire Display On (0xa4/0xa5)
OLED_WR_Byte(0xA6,OLED_CMD);// Disable Inverse Display On (0xa6/a7)
OLED_WR_Byte(0xAF,OLED_CMD);//--turn on oled panel

OLED_WR_Byte(0xAF,OLED_CMD); /*display ON*/
OLED_Clear();
OLED_Set_Pos(0,0);
}

oled.h

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
#ifndef __OLED_H
#define __OLED_H
#include "sys.h"
#include "stdlib.h"

#define OLED_MODE 0

#define GPIO_OLED_CLK RCC_APB2Periph_GPIOC
#define GPIO_OLED_SCLK_Pin GPIO_Pin_0 /* D0 */
#define GPIO_OLED_PIN_Pin GPIO_Pin_1 /* D1 */
#define GPIO_OLED_RES_Pin GPIO_Pin_2 /* RES */
#define GPIO_OLED_DC_Pin GPIO_Pin_3 /* DC */


#define DATAOUT(x) GPIO_Write(GPIOB,x);

#define OLED_RST_Clr() GPIO_ResetBits(GPIOC,GPIO_Pin_2)
#define OLED_RST_Set() GPIO_SetBits(GPIOC,GPIO_Pin_2)

#define OLED_DC_Clr() GPIO_ResetBits(GPIOC,GPIO_Pin_3)
#define OLED_DC_Set() GPIO_SetBits(GPIOC,GPIO_Pin_3)

#define OLED_SCLK_Clr() GPIO_ResetBits(GPIOC,GPIO_Pin_0)
#define OLED_SCLK_Set() GPIO_SetBits(GPIOC,GPIO_Pin_0)

#define OLED_SDIN_Clr() GPIO_ResetBits(GPIOC,GPIO_Pin_1)
#define OLED_SDIN_Set() GPIO_SetBits(GPIOC,GPIO_Pin_1)



#define OLED_CMD 0
#define OLED_DATA 1

void OLED_WR_Byte(u8 dat,u8 cmd);
void OLED_Display_On(void);
void OLED_Display_Off(void);
void OLED_Refresh_Gram(void);
void OLED_Init(void);
void OLED_Clear(void);
void OLED_DrawPoint(u8 x,u8 y,u8 t);
void OLED_Fill(u8 x1,u8 y1,u8 x2,u8 y2,u8 dot);
void OLED_ShowChar(u8 x,u8 y,u8 chr,u8 size,u8 mode);
void OLED_ShowNum(u8 x,u8 y,u32 num,u8 len,u8 size);
void OLED_ShowString(u8 x,u8 y,const u8 *p,u8 size);
void OLED_ShowChinese(u16 x,u16 y,u8 index,u8 size);
#endif

esp8266.c

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
#define ESP8266_WIFI_INFO		"AT+CWJAP=\"wy\",\"18770080824\"\r\n"  
//连接手机热点

#define ESP8266_ONENET_INFO "AT+CIPSTART=\"TCP\",\"183.230.40.39\",6002\r\n"
//连接onenet的mqtt

void ESP8266_Init(void)
{
ESP8266_Clear();

UsartPrintf(USART_DEBUG, "0. AT\r\n");
while(ESP8266_SendCmd("AT\r\n", "OK"))
delay_ms(500);

UsartPrintf(USART_DEBUG,"1.rst\r\n");
ESP8266_SendCmd("AT+RST\r\n","");
delay_ms(500);
ESP8266_SendCmd("AT+CIPCLOSE\r\n","");
delay_ms(500);

UsartPrintf(USART_DEBUG, "2. CWMODE\r\n");
while(ESP8266_SendCmd("AT+CWMODE=1\r\n", "OK"))
delay_ms(500);

UsartPrintf(USART_DEBUG, "3. AT+CWDHCP\r\n");
while(ESP8266_SendCmd("AT+CWDHCP=1,1\r\n", "OK"))
delay_ms(500);

UsartPrintf(USART_DEBUG, "4. CWJAP\r\n");
while(ESP8266_SendCmd(ESP8266_WIFI_INFO, "GOT IP"))
delay_ms(500);

UsartPrintf(USART_DEBUG, "5. CIPSTART\r\n");
while(ESP8266_SendCmd(ESP8266_ONENET_INFO, "CONNECT"))
delay_ms(500);

UsartPrintf(USART_DEBUG, "6. ESP8266 Init OK\r\n");

}

esp8266.h

1
2
3
4
5
6
7
8
9
10
11
12
13
#ifndef _ESP8266_H_
#define _ESP8266_H_

void ESP8266_Init(void);

void ESP8266_Clear(void);

void ESP8266_SendData(unsigned char *data, unsigned short len);

unsigned char *ESP8266_GetIPD(unsigned short timeOut);


#endif

onenet.c

1
2
3
4
5
6
#define PROID		"617134"  //产品ID

#define AUTH_INFO "led" //鉴权信息

#define DEVID "1151407832" //设备ID

onenet.h

1
2
3
4
5
6
7
8
9
10
11
12
13
#ifndef _ONENET_H_
#define _ONENET_H_

_Bool OneNet_DevLink(void);

void OneNet_Subscribe(const char *topics[], unsigned char topic_cnt);

void OneNet_Publish(const char *topic, const char *msg);

void OneNet_RevPro(unsigned char *cmd);

#endif

main.c

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
#include "stm32f10x.h"

#include "delay.h"
#include "usart.h"
#include "led.h"
#include "oled.h"
#include "dht11.h"
#include "lsens.h"
#include "esp8266.h"
#include "onenet.h"
#include "ds18b20.h"

unsigned char usart1Len = 0; //usart1接收数据长度
unsigned char usart1Buf[64]; //usart1接收缓存

int main(void)
{
const char *deviceSubTopic[]={"/1/sub"};
const char devicePubTopic[]="/1/pub";
char PUB_BUF[256];
char tmp[20]={0};
unsigned short timeCount=0;
unsigned char *dataPtr=NULL;
u8 temperature;
u8 humidity;
u8 adcx;

delay_init();
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
Usart1_Init(115200);
Usart2_Init(115200);
LED_Init();
OLED_Init();
DS18B20_Init();
UsartPrintf(USART_DEBUG," Hardware init OK\r\n");

ESP8266_Init();
while(OneNet_DevLink())
delay_ms(500);

OneNet_Subscribe(deviceSubTopic,1);


while(1)
{

if(timeCount%40==0)
{
temperature=DS18B20_Get_Temp();

OLED_ShowChinese(0,0,30,16);
OLED_ShowChinese(16,0,31,16);
sprintf(tmp,":%d",temperature);
OLED_ShowString(32,0,tmp,16);
OLED_ShowChinese(60,0,32,16);
OLED_Refresh_Gram();

UsartPrintf(USART_DEBUG,"温度:%d ,temperature);
}
if(++timeCount>=300)
{
UsartPrintf(USART_DEBUG,"OneNet_Publish\r\n");

OneNet_Publish(devicePubTopic,PUB_BUF);
timeCount=0;
ESP8266_Clear();
}
dataPtr=ESP8266_GetIPD(3);
if(dataPtr!=NULL)
{
OneNet_RevPro(dataPtr);
}
delay_ms(10);
}
}

在串口中断函数中实现开关灯

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
void USART2_IRQHandler(void)
{

if(USART_GetITStatus(USART2, USART_IT_RXNE) != RESET) //接收中断
{
if(esp8266_cnt >= sizeof(esp8266_buf)) esp8266_cnt = 0; //防止串口刷爆
esp8266_buf[esp8266_cnt++] = USART2->DR;
if(USART2->DR==1)
GPIO_SetBits(GPIOA,GPIO_Pin_8);
else
GPIO_ResetBits(GPIOA,GPIO_Pin_8);
USART_ClearFlag(USART2, USART_FLAG_RXNE);
}

}

下位机与云端实现效果

3

4

5

数据可视化可以进入此处进行配置

6

上位机APP

7