热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

物联网学习之旅:微信小程序控制STM32(三)STM32代码编写

STM32代码编写STM32端不需要写关于连接MQTT服务器的代码,连接的工作交给ESP8266来做,STM32只需要通过串口接收和发送数据,间接的与服务器交互。串口三配置串口一已




STM32代码编写

STM32端不需要写关于连接MQTT服务器的代码,连接的工作交给ESP8266来做,STM32只需要通过串口接收和发送数据,间接的与服务器交互。



  1. 串口三配置

    串口一已经与电脑连接了,为了避免干扰,使用其它串口与ESP8266串口通信。这里我用的串口三,串口三的输入输出在PB10和PB11,配置这两个GPIO,然后配置中断就可以了。

    串口三配置代码:

    usart3.c

#include "usart3.h"
#include "sys.h"
u8 USART_RX_BUF3[USART_REC_LEN3]; //接收缓冲,最大USART_REC_LEN个字节.末字节为换行符
u16 USART_RX_STA3; //接收状态标记
void USART3_Config(uint32_t MyBaudRate)
{
GPIO_InitTypeDef GPIO_InitStructure;
USART_InitTypeDef USART_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;

RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB , ENABLE); //使能IO口始终
RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3 , ENABLE); //使能串口三

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //复用推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB , &GPIO_InitStructure);

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11;
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; //浮空输入
GPIO_Init(GPIOB , &GPIO_InitStructure);

USART_InitStructure.USART_BaudRate = MyBaudRate;
USART_InitStructure.USART_WordLength = USART_WordLength_8b;
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_Tx|USART_Mode_Rx;
USART_Init(USART3,&USART_InitStructure);

NVIC_InitStructure.NVIC_IRQChannel = USART3_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptiOnPriority= 1;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);

USART_ITConfig(USART3, USART_IT_RXNE, ENABLE);
USART_Cmd(USART3,ENABLE);
}

void Usart_SendByte( USART_TypeDef * pUSARTx, uint8_t ch)
{
USART_SendData(pUSARTx,ch);
while (USART_GetFlagStatus(pUSARTx, USART_FLAG_TXE) == RESET);
}
void Usart_SendArray( USART_TypeDef * pUSARTx, char *array, uint16_t num)
{
uint8_t i;
for(i=0; i {
Usart_SendByte(pUSARTx,array[i]);
}
while(USART_GetFlagStatus(pUSARTx,USART_FLAG_TC)==RESET);
}
void Usart_SendString( USART_TypeDef * pUSARTx, char *str) //将传进来字符串,相当于char *str="xyz"
{
unsigned int k=0;
do
{
Usart_SendByte( pUSARTx, *(str + k) ); //去除此str指针下一个地址指向的值
k++;
} while(*(str + k)!='\0');
while(USART_GetFlagStatus(pUSARTx,USART_FLAG_TC)==RESET);
}

void USART3_IRQHandler(void)
{
uint8_t Res;
if(USART_GetITStatus(USART3, USART_IT_RXNE) != RESET) //接收中断(接收到的数据必须是0x0d 0x0a结尾)
{
Res =USART_ReceiveData(USART3);//(USART3->DR); //读取接收到的数据

if((USART_RX_STA3&0x8000)==0)//接收未完成
{
if(USART_RX_STA3&0x4000)//接收到了0x0d
{
if(Res!=0x0a)USART_RX_STA3=0;//接收错误,重新开始
else USART_RX_STA3|=0x8000; //接收完成了
}
else //还没收到0X0D
{
if(Res==0x0d)USART_RX_STA3|=0x4000;
else
{
USART_RX_BUF3[USART_RX_STA3&0X3FFF]=Res ;
USART_RX_STA3++;
if(USART_RX_STA3>(USART_REC_LEN3-1))USART_RX_STA3=0;//接收数据错误,重新开始接收
}
}
}
}

usart3.h

#ifndef __USART3_H
#define __USART3_H
#include "stdio.h"
#include "sys.h"
#define USART_REC_LEN3 200 //定义最大接收字节数 200
#define EN_USART1_RX3 1 //使能(1)/禁止(0)串口1接收

extern u8 USART_RX_BUF3[USART_REC_LEN3]; //接收缓冲,最大USART_REC_LEN个字节.末字节为换行符
extern u16 USART_RX_STA3; //接收状态标记
void USART3_Config(uint32_t MyBaudRate);
void Usart_SendByte( USART_TypeDef * pUSARTx, uint8_t ch);
void Usart_SendArray( USART_TypeDef * pUSARTx, char *array, uint16_t num);
void Usart_SendString( USART_TypeDef * pUSARTx,char *str);

#endif


  1. 串口数据处理

    因为设备之间传输的数据是JSON格式的,所以当我STM32在串口中接收完数据之后,需要对JSON数据进行解析,得到真正需要的数据,我用的是cJSON这个库来解析,百度网盘cJSON库下载:

    链接:https://pan.baidu.com/s/1uae-wtAgU8U2UMOfCeayRw

    提取码:fpad

    下载好后把里面的cJSON.c和cJSON.h引入项目中即可,编译时会有几个警告,但不影响使用。

    data.c

#include "data.h"
#include "usart.h"
#include "usart3.h"
#include "cJSON.h"
#include "led.h"
#include "lcd.h"
#include "string.h"
#include "stdio.h"
#include "stdlib.h"
#include "delay.h"
#include "dht11.h"
u8 ProcessData(){
u8 i;
u8 temp;
u8 humi;
cJSON *json;
if(USART_RX_STA3&0x8000) //数据接收完毕
{
if(USART_RX_BUF3[0]=='{'){//检测是不是JSON数据
json=cJSON_Parse((char *)USART_RX_BUF3);//解析JSON数据
if (!json) { //如果解析失败
printf("Error before: [%s]\n",cJSON_GetErrorPtr());
return 0;
}
else{
cJSON *src=cJSON_GetObjectItem(json,"src"); //获取src字段
cJSON *des=cJSON_GetObjectItem(json,"des");
cJSON *msg=cJSON_GetObjectItem(json,"msg");
cJSON *cOntent=cJSON_GetObjectItem(msg,"content"); //获取msg下的content字段
cJSON *type=cJSON_GetObjectItem(msg,"type");
cJSON *which=cJSON_GetObjectItem(msg,"which");
char *source=src->valuestring; //获取字段数据
char *command=content->valuestring;
char *tp=type->valuestring;
char *wih=which->valuestring;
printf("content:%s\r\n",content->valuestring);
if(strcmp(source, "wx")==0){
if(strcmp(tp, "ask")==0){
if(strcmp(wih, "stm32")==0){ //收到询问在线消息
STfeedback(); //发送在线回应
}
if(strcmp(wih, "data")==0){ //收到询问温湿度数据
DHT11_Read_Data(&temp,&humi);//读取温湿度数据
THfeedback(temp,humi); //发送温湿度数据
}

}
if(strcmp(tp, "ctrl")==0){ //收到控制类型数据
if(strcmp(command, "on")==0){
ControlLED1(1); //开灯
}
if(strcmp(command, "off")==0){
ControlLED1(0); //关灯
}
}
}
cJSON_Delete(json); //解析JSON数据很占内存,及时删除json
}
}
USART_RX_STA3=0;
for(i=0;i USART_RX_BUF3[i]=0;
}

}
return 1;
}
u8 THfeedback(u8 temperature,u8 humidity){
u8 t[100]; //这里拼接之后的字符串存放必须是分配了内存空间的变量,直接写成*t这样的指针没有足够的内存。
u8 h[100];
sprintf((char*)t,"{\"src\":\"stm32\",\"des\":\"wx\",\"msg\":{\"type\":\"data\",\"which\":\"temperature\",\"content\":%d}}",temperature); //这里在把字符数组转成指针就可以了,不然运行到这里就直接卡住了
sprintf((char*)h,"{\"src\":\"stm32\",\"des\":\"wx\",\"msg\":{\"type\":\"data\",\"which\":\"humidity\",\"content\":%d}}",humidity);
Usart_SendString( USART3, (char*)t); //通过串口三发送拼接好的字符串
delay_ms(100); //延时一段时间再发送,否则只能发送最后一条数据
Usart_SendString( USART3, (char*)h);
return 1;
}
void STfeedback(){
Usart_SendString( USART3, "{\"src\":\"stm32\",\"des\":\"wx\",\"msg\":{\"type\":\"feedback\",\"which\":\"stm32\",\"content\":\"ok\"}}");
}
u8 ControlLED1(u8 state){
LED1=state; //LED灯执行相应的操作
if(state==1){
LCD_ShowString(30,110,200,16,16,"LED1=ON");
Usart_SendString( USART3, "{\"src\":\"stm32\",\"des\":\"wx\",\"msg\":{\"type\":\"feedback\",\"which\":\"led1\",\"content\":\"on\"}}");
}
if(state==0){
LCD_ShowString(30,110,200,16,16,"LED1=OF");
Usart_SendString( USART3, "{\"src\":\"stm32\",\"des\":\"wx\",\"msg\":{\"type\":\"feedback\",\"which\":\"led1\",\"content\":\"off\"}}");
}
return 1;
}

data.h

#ifndef __DATA_H
#define __DATA_H
#define USART_REC_LEN3 200 //定义最大接收字节数 200
#include "sys.h"
extern u8 USART_RX_BUF3[USART_REC_LEN3]; //接收缓冲,最大USART_REC_LEN个字节.末字节为换行符
extern u16 USART_RX_STA3; //接收状态标记
u8 ProcessData(void);
u8 THfeedback(u8 temperature,u8 humidity);
void STfeedback(void);
u8 ControlLED1(u8 state);

#endif


  1. 主程序设计

    这里要考虑到两种情况,当stm32 启动时有可能微信小程序没有打开;当微信小程序打开了,但stm32有可能不在线。所以在程序中需要在初始化时,向微信小程序发送一条在线消息,如果微信小程序上线的时候也会询问STM32是否在线,STM32接收到询问数据,再回应就可以了。

#include "led.h"
#include "delay.h"
#include "key.h"
#include "sys.h"
#include "usart.h"
#include "usart3.h"
#include "lcd.h"
#include "wifi.h"
#include "cJSON.h"
#include "dht11.h"
#include "string.h"
#include "stdio.h"
#include "stdlib.h"
#include "data.h"
void display(){
POINT_COLOR=RED;

LCD_ShowString(30,50,200,16,16,"temperature:");
LCD_ShowString(30,70,200,16,16,"humidity:");
}
int main(void)
{
int j=0;
u8 oldtemp,oldhumi;
u8 temperature;
u8 humidity;
delay_init(); //延时函数初始化
NVIC_Configuration(); //设置NVIC中断分组2:2位抢占优先级,2位响应优先级
uart_init(115200); //串口初始化为115200
USART3_Config(115200); //串口三初始化位115200
LED_Init(); //LED端口初始化
KEY_Init(); //初始化与按键连接的硬件接口
LCD_Init();
while(DHT11_Init()) //DHT11初始化
{
LCD_ShowString(30,130,200,16,16,"DHT11 Error");
delay_ms(200);
LCD_Fill(30,130,239,130+16,WHITE);
delay_ms(200);
}
Usart_SendString( USART3, "{\"src\":\"stm32\",\"des\":\"wx\",\"msg\":{\"type\":\"feedback\",\"which\":\"stm32\",\"content\":\"ok\"}}"); //发送在线应答
display();
while(1){
ProcessData();
if(j==250){ //每个一定的时间读取一次温湿度
DHT11_Read_Data(&temperature,&humidity);
if((temperature!=oldtemp)||(humidity!=oldhumi)){ //温湿度发生改变时再发送
THfeedback(temperature,humidity); //返回温湿度数据
LCD_ShowNum(130,50,temperature,2,16);
LCD_ShowNum(100,70,humidity,2,16);
oldtemp=temperature;
oldhumi=humidity;
}
j=0;
}
delay_ms(10);
j++;
}
}

这样STM32端的代码就写好了。

个人能力有限,有什么错误的地方欢迎指正,有问题也可以提,可以一起探讨




推荐阅读
  • 本文详细探讨了VxWorks操作系统中双向链表和环形缓冲区的实现原理及使用方法,通过具体示例代码加深理解。 ... [详细]
  • 从 .NET 转 Java 的自学之路:IO 流基础篇
    本文详细介绍了 Java 中的 IO 流,包括字节流和字符流的基本概念及其操作方式。探讨了如何处理不同类型的文件数据,并结合编码机制确保字符数据的正确读写。同时,文中还涵盖了装饰设计模式的应用,以及多种常见的 IO 操作实例。 ... [详细]
  • 题目Link题目学习link1题目学习link2题目学习link3%%%受益匪浅!-----&# ... [详细]
  • 本实验主要探讨了二叉排序树(BST)的基本操作,包括创建、查找和删除节点。通过具体实例和代码实现,详细介绍了如何使用递归和非递归方法进行关键字查找,并展示了删除特定节点后的树结构变化。 ... [详细]
  • 本文详细介绍了C语言中链表的两种动态创建方法——头插法和尾插法,包括具体的实现代码和运行示例。通过这些内容,读者可以更好地理解和掌握链表的基本操作。 ... [详细]
  • 本教程涵盖OpenGL基础操作及直线光栅化技术,包括点的绘制、简单图形绘制、直线绘制以及DDA和中点画线算法。通过逐步实践,帮助读者掌握OpenGL的基本使用方法。 ... [详细]
  • Codeforces Round #566 (Div. 2) A~F个人题解
    Dashboard-CodeforcesRound#566(Div.2)-CodeforcesA.FillingShapes题意:给你一个的表格,你 ... [详细]
  • 在多线程编程环境中,线程之间共享全局变量可能导致数据竞争和不一致性。为了解决这一问题,Linux提供了线程局部存储(TLS),使每个线程可以拥有独立的变量副本,确保线程间的数据隔离与安全。 ... [详细]
  • 实体映射最强工具类:MapStruct真香 ... [详细]
  • 本文介绍了一种解决二元可满足性(2-SAT)问题的方法。通过具体实例,详细解释了如何构建模型、应用算法,并提供了编程实现的细节和优化建议。 ... [详细]
  • 本题涉及一棵由N个节点组成的树(共有N-1条边),初始时所有节点均为白色。题目要求处理两种操作:一是改变某个节点的颜色(从白变黑或从黑变白);二是查询从根节点到指定节点路径上的第一个黑色节点,若无则输出-1。 ... [详细]
  • Linux设备驱动程序:异步时间操作与调度机制
    本文介绍了Linux内核中的几种异步延迟操作方法,包括内核定时器、tasklet机制和工作队列。这些机制允许在未来的某个时间点执行任务,而无需阻塞当前线程,从而提高系统的响应性和效率。 ... [详细]
  • dotnet 通过 Elmish.WPF 使用 F# 编写 WPF 应用
    本文来安利大家一个有趣而且强大的库,通过F#和C#混合编程编写WPF应用,可以在WPF中使用到F#强大的数据处理能力在GitHub上完全开源Elmis ... [详细]
  • 本次考试于2016年10月25日上午7:50至11:15举行,主要涉及数学专题,特别是斐波那契数列的性质及其在编程中的应用。本文将详细解析考试中的题目,并提供解题思路和代码实现。 ... [详细]
  • 本文探讨了在使用Azure Active Directory进行用户身份验证时,结合AddAuthentication和RequireAuthenticatedUser的必要性及其潜在冗余问题。 ... [详细]
author-avatar
爱你真好958_358
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有