#include "main.h"#include "stm32l4xx_hal.h"#include "i2c.h"#include "usart.h"#include "gpio.h"#include "E53_IA1.h"#include "lcd.h"#include "spi.h"#include "mqtt.h"#include "esp8266.h"
/* USER CODE BEGIN Includes */#include "stdio.h"/* USER CODE END Includes */
void SystemClock_Config(void);
#define ESP8266_WIFI_AP_SSID "CMCC-Cqvn" //将要连接的路由器名称 --不要出现中文、空格等特殊字符#define ESP8266_AP_PASSWORD "99pu58cb" //将要连接的路由器密码
//华为云IOT物联网服务器的设备信息#define MQTT_ClientID "61cd1d97078a93029b84e7b6_1126626497_0_0_2021123003"#define MQTT_UserName "61cd1d97078a93029b84e7b6_1126626497"#define MQTT_PassWord "b219f3a0099fa0284a2671a5c699b67a7cf6d5f7355d9ee8190011f3b64f71b5" //订阅与发布的主题#define SET_TOPIC "$oc/devices/61cd1d97078a93029b84e7b6_1126626497/sys/messages/down" //订阅#define POST_TOPIC "$oc/devices/61cd1d97078a93029b84e7b6_1126626497/sys/properties/report" //发布
//保存温湿度、光照强度E53_IA1_Data_TypeDef E53_IA1_Data;
//显示文本char lcd_text_str[50];
UART_HandleTypeDef at_usart;
//低功耗串口初始化int32_t at_usart_init(void){ at_usart.Instance = LPUART1; at_usart.Init.BaudRate = 115200;
at_usart.Init.WordLength = UART_WORDLENGTH_8B; at_usart.Init.StopBits = UART_STOPBITS_1; at_usart.Init.Parity = UART_PARITY_NONE; at_usart.Init.HwFlowCtl = UART_HWCONTROL_NONE; at_usart.Init.Mode = UART_MODE_RX | UART_MODE_TX; if(HAL_UART_Init(&at_usart) != HAL_OK) { _Error_Handler(__FILE__, __LINE__); } // __HAL_UART_CLEAR_FLAG(usart, UART_FLAG_TC); __HAL_UART_ENABLE_IT(&at_usart, UART_IT_IDLE); __HAL_UART_ENABLE_IT(&at_usart, UART_IT_RXNE); HAL_NVIC_EnableIRQ(LPUART1_IRQn); //使能USART1中断通道 HAL_NVIC_SetPriority(LPUART1_IRQn, 3, 3); //抢占优先级3,子优先级3 return 0;}
unsigned char ESP8266_RecvBuf[MAX_RECV_CNT];unsigned int ESP8266_Recv_cnt=0;unsigned int ESP8266_Recv_flag=0;void LPUART1_IRQHandler(){ //接收到数据 if(__HAL_UART_GET_FLAG(&at_usart, UART_FLAG_RXNE) != RESET) { if(ESP8266_Recv_cnt<MAX_RECV_CNT-1) { ESP8266_RecvBuf[ESP8266_Recv_cnt++] = (uint8_t)(at_usart.Instance->RDR & 0x00FF); } else { ESP8266_Recv_flag=1; } } else if (__HAL_UART_GET_FLAG(&at_usart, UART_FLAG_IDLE) != RESET) { __HAL_UART_CLEAR_IDLEFLAG(&at_usart); ESP8266_Recv_flag=1; }}
void AT_SendData(unsigned char *p,unsigned int len){ int i=0; for(i=0;i<len;i++) { while((LPUART1->ISR & 0X40) == 0); //循环发送,直到发送完毕 LPUART1->TDR = p[i]; }}
char mqtt_message[200];int main(void){ int i=0; int cnt=0; int motor_state=0; HAL_Init(); SystemClock_Config(); MX_GPIO_Init(); MX_I2C1_Init(); MX_SPI2_Init(); MX_USART1_UART_Init(); at_usart_init(); //初始化硬件 Init_E53_IA1();
LCD_Init(); LCD_Clear(BLACK);//清屏为黑色 LCD_ShowString(0, 00, 240, 32, 32, "Init ESP8266");//显示字符串,字体大小32*32
if(ESP8266_Init()) { printf("ESP8266硬件检测错误.\n"); LCD_Clear(BLACK);//清屏为黑色 LCD_ShowString(0, 00, 240, 32, 32, "ESP8266 ERROR");//显示字符串,字体大小32*32 } else { LCD_Clear(BLACK);//清屏为黑色 LCD_ShowString(0, 00, 240, 32, 32, "ESP8266 OK");//显示字符串,字体大小32*32 printf("准备连接到指定的服务器.\n"); //非加密端口 printf("WIFI:%d\r\n",ESP8266_STA_TCP_Client_Mode(ESP8266_WIFI_AP_SSID,ESP8266_AP_PASSWORD,"106.55.124.154",1883,1)); } //2. MQTT协议初始化 MQTT_Init(); //3. 连接华为云IOT服务器 while(MQTT_Connect(MQTT_ClientID,MQTT_UserName,MQTT_PassWord)) { printf("服务器连接失败,正在重试...\n"); HAL_Delay(500); } printf("服务器连接成功.\n"); //3. 订阅主题 if(MQTT_SubscribeTopic(SET_TOPIC,0,1)) { printf("主题订阅失败.\n"); } else { printf("主题订阅成功.\n"); } while (1) { if(HAL_GPIO_ReadPin(KEY1_GPIO_Port,KEY1_Pin)==GPIO_PIN_RESET)//查询按键KEY1低电平 { HAL_Delay(10);//消抖 if(HAL_GPIO_ReadPin(KEY1_GPIO_Port,KEY1_Pin)==GPIO_PIN_RESET)//查询按键KEY1低电平 { HAL_GPIO_WritePin(LED_GPIO_Port,LED_Pin,GPIO_PIN_SET);//亮 //补光灯亮 HAL_GPIO_WritePin(IA1_Light_GPIO_Port, IA1_Light_Pin, GPIO_PIN_SET); //电机转 HAL_GPIO_WritePin(IA1_Motor_GPIO_Port, IA1_Motor_Pin, GPIO_PIN_SET); motor_state=1; } } if(HAL_GPIO_ReadPin(KEY2_GPIO_Port,KEY2_Pin)==GPIO_PIN_RESET)//查询按键KEY2低电平 { HAL_Delay(10);//消抖 if(HAL_GPIO_ReadPin(KEY2_GPIO_Port,KEY2_Pin)==GPIO_PIN_RESET)//查询按键KEY2低电平 { HAL_GPIO_WritePin(LED_GPIO_Port,LED_Pin,GPIO_PIN_RESET);//灭 //补光灯灭 HAL_GPIO_WritePin(IA1_Light_GPIO_Port, IA1_Light_Pin, GPIO_PIN_RESET); //电机停 HAL_GPIO_WritePin(IA1_Motor_GPIO_Port, IA1_Motor_Pin, GPIO_PIN_RESET); motor_state=0; } } cnt++; HAL_Delay(10); if(cnt>=100) { cnt=0; E53_IA1_Read_Data(); printf("光照强度:%d %%\r\n", (int)E53_IA1_Data.Lux); printf("湿度:%d %%\r\n",(int)E53_IA1_Data.Humidity); printf("温度:%d ℃\r\n", (int)E53_IA1_Data.Temperature);
sprintf(lcd_text_str,"L: %d %%",(int)E53_IA1_Data.Lux); LCD_ShowString(40, 50+10+32*1, 240, 32, 32,lcd_text_str);
sprintf(lcd_text_str,"H: %d %%",(int)E53_IA1_Data.Humidity); LCD_ShowString(40, 50+10+32*2, 240, 32, 32,lcd_text_str);
sprintf(lcd_text_str,"T: %d C",(int)E53_IA1_Data.Temperature); LCD_ShowString(40, 50+10+32*3, 240, 32, 32,lcd_text_str);
//切换引脚的状态 HAL_GPIO_TogglePin(LED_GPIO_Port,LED_Pin); //上传数据 sprintf(mqtt_message,"{\"services\": [{\"service_id\": \"motor\",\"properties\":{\"motor\":%d}}," "{\"service_id\": \"motor\",\"properties\":{\"SHT30_H\":%d}},{\"service_id\": \"motor\",\"properties\":" "{\"SHT30_L\":%d}},{\"service_id\": \"motor\",\"properties\":{\"BH1750\":%d}}]}", motor_state,(int)E53_IA1_Data.Humidity,(int)E53_IA1_Data.Temperature,(int)E53_IA1_Data.Lux); MQTT_PublishData(POST_TOPIC,mqtt_message,0); //根据湿度自动灌溉 if((int)E53_IA1_Data.Humidity<50) //小于50自动灌溉 { printf("自动灌溉....\n"); motor_state=1; //电机状态更新 //电机转 HAL_GPIO_WritePin(IA1_Motor_GPIO_Port, IA1_Motor_Pin, GPIO_PIN_SET); } }
//接收到数据 if(ESP8266_Recv_flag) { //如果是下发了属性,判断是开锁还是关锁 if(ESP8266_Recv_cnt>5) { ESP8266_RecvBuf[ESP8266_Recv_cnt]='\0'; //使用字符串查找函数 if(strstr((char*)&ESP8266_RecvBuf[5],"\"machine\":1")) { motor_state=1; //电机状态更新 //电机转 HAL_GPIO_WritePin(IA1_Motor_GPIO_Port, IA1_Motor_Pin, GPIO_PIN_SET); printf("开启电机...\n"); } else if(strstr((char*)&ESP8266_RecvBuf[5],"\"machine\":0")) { //电机停 HAL_GPIO_WritePin(IA1_Motor_GPIO_Port, IA1_Motor_Pin, GPIO_PIN_RESET); motor_state=0; printf("关闭电机...\n"); } for(i=0;i<ESP8266_Recv_cnt;i++)printf("%c",ESP8266_RecvBuf[i]); ESP8266_Recv_cnt=0; } ESP8266_Recv_flag=0; } }}
void SystemClock_Config(void){
RCC_OscInitTypeDef RCC_OscInitStruct; RCC_ClkInitTypeDef RCC_ClkInitStruct; RCC_PeriphCLKInitTypeDef PeriphClkInit;
/**Initializes the CPU, AHB and APB busses clocks */ RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI|RCC_OSCILLATORTYPE_MSI; RCC_OscInitStruct.HSIState = RCC_HSI_ON; RCC_OscInitStruct.HSICalibrationValue = 16; RCC_OscInitStruct.MSIState = RCC_MSI_ON; RCC_OscInitStruct.MSICalibrationValue = 0; RCC_OscInitStruct.MSIClockRange = RCC_MSIRANGE_6; RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON; RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_MSI; RCC_OscInitStruct.PLL.PLLM = 1; RCC_OscInitStruct.PLL.PLLN = 40; RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV7; RCC_OscInitStruct.PLL.PLLQ = RCC_PLLQ_DIV2; RCC_OscInitStruct.PLL.PLLR = RCC_PLLR_DIV2; if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) { _Error_Handler(__FILE__, __LINE__); }
/**Initializes the CPU, AHB and APB busses clocks */ RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2; RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK; RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1; RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1; RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_4) != HAL_OK) { _Error_Handler(__FILE__, __LINE__); }
PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_USART1|RCC_PERIPHCLK_I2C1; PeriphClkInit.Usart1ClockSelection = RCC_USART1CLKSOURCE_PCLK2; PeriphClkInit.I2c1ClockSelection = RCC_I2C1CLKSOURCE_HSI; if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK) { _Error_Handler(__FILE__, __LINE__); }
/**Configure the main internal regulator output voltage */ if (HAL_PWREx_ControlVoltageScaling(PWR_REGULATOR_VOLTAGE_SCALE1) != HAL_OK) { _Error_Handler(__FILE__, __LINE__); }
/**Configure the Systick interrupt time */ HAL_SYSTICK_Config(HAL_RCC_GetHCLKFreq()/1000);
/**Configure the Systick */ HAL_SYSTICK_CLKSourceConfig(SYSTICK_CLKSOURCE_HCLK);
/* SysTick_IRQn interrupt configuration */ HAL_NVIC_SetPriority(SysTick_IRQn, 0, 0);}
/* USER CODE BEGIN 4 */
/* USER CODE END 4 */
/** * @brief This function is executed in case of error occurrence. * @param file: The file name as string. * @param line: The line in file as a number. * @retval None */void _Error_Handler(char *file, int line){ /* USER CODE BEGIN Error_Handler_Debug */ /* User can add his own implementation to report the HAL error return state */ while(1) { } /* USER CODE END Error_Handler_Debug */}
#ifdef USE_FULL_ASSERT/** * @brief Reports the name of the source file and the source line number * where the assert_param error has occurred. * @param file: pointer to the source file name * @param line: assert_param error line source number * @retval None */void assert_failed(uint8_t* file, uint32_t line){ /* USER CODE BEGIN 6 */ /* User can add his own implementation to report the file name and line number, tex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */ /* USER CODE END 6 */}#endif /* USE_FULL_ASSERT */
评论