基于STM32的环境监测器

0x00 背景&功能描述

研究性学习课题要用到这玩意…于是尝试用stm32捏了一个… 第一次玩stm32,为了方便就直接拿STM32CubeMX生成了这个工程… 芯片为STM32F407GZT6,使用了外部RTC,具体时钟树设置参考CubeMX工程文件。 功能嘛,每隔一段时间获取实时PM2.5,PM10,CO2浓度与环境温湿度,并将其存储入SD卡(FAT32分区)中。同时也会向USART1中打印日志。 USART1-3波特率均为9600,

0x01 硬件部分

温湿度传感器(DHT22/AM2303) -> PA1 *USART1(PA9 PA10) PM2.5(G7 PMS7003) -> USART2(PA3 PA4) CO2(DS-CO2-20) -> USART3(PE14 PE15)

0x02 代码

项目由CubeMX自动生成,以下仅展示部分代码 GitHub项目地址 ps:请忽视逼死强迫症的缩进…就让Keil uvision那个辣鸡的IDE背锅吧

RTC_DateTypeDef sDate;
RTC_TimeTypeDef sTime;
uint8_t second_tmp = 0;

void LED0_off(){HAL_GPIO_WritePin(LED0_GPIO_Port, LED0_Pin, GPIO_PIN_SET);}
void LED1_off(){HAL_GPIO_WritePin(LED1_GPIO_Port, LED1_Pin, GPIO_PIN_SET);}

void LED0_on(){HAL_GPIO_WritePin(LED0_GPIO_Port, LED0_Pin, GPIO_PIN_RESET);}
void LED1_on(){HAL_GPIO_WritePin(LED1_GPIO_Port, LED1_Pin, GPIO_PIN_RESET);}

uint8_t PMSensorBuffer[128];
uint8_t PMSensor[17];
int TOT = 0, PMSensorLen;

//PM Sensor

struct PMSensor{
	int PM1_0_CF, PM2_5_CF, PM10_CF, PM1_0, PM2_5, PM10;
}PMResult;

void ListenPMSensor(){
	memset(PMSensorBuffer, 0, sizeof(PMSensorBuffer));
	memset(PMSensor, 0, sizeof(PMSensor));
	
	HAL_UART_Receive(&huart2, (uint8_t*)PMSensorBuffer, 128, 3200);
	HAL_Delay(800);
	
	//printf("", PMSensorBuffer);
	for(int i = 0; i <= 127; ++i){
		//printf("%c \n", PMSensorBuffer[i]);
		if(PMSensorBuffer[i] == 'B' && PMSensorBuffer[i+1] == 'M'){			
			for(PMSensorLen = 0; PMSensorLen <= 31; ++PMSensorLen){
				PMSensor[PMSensorLen] = PMSensorBuffer[i + PMSensorLen];
			}
			break;
		}
	}
	
	HAL_Delay(2000);
	return ;
}

void GetPMSensor(void){
	uint16_t Buffer_Len;
	Buffer_Len = (uint16_t)((PMSensor[2] << 8) | PMSensor[3]);
	if(Buffer_Len == 28) {
		
		PMResult.PM1_0_CF = (uint16_t)((PMSensor[4]<<8) | PMSensor[5]);
		PMResult.PM2_5_CF = (uint16_t)((PMSensor[6]<<8) | PMSensor[7]);
		PMResult.PM10_CF 	= (uint16_t)((PMSensor[8]<<8) | PMSensor[9]);
		PMResult.PM1_0 	= (uint16_t)((PMSensor[10]<<8) | PMSensor[11]);
		PMResult.PM2_5 	= (uint16_t)((PMSensor[12]<<8) | PMSensor[13]);
		PMResult.PM10 	= (uint16_t)((PMSensor[14]<<8) | PMSensor[15]);		
		
	}
	else if(Buffer_Len == 20){
		
		PMResult.PM1_0_CF = (uint16_t)((PMSensor[4]<<8) | PMSensor[5]);
		PMResult.PM2_5_CF = (uint16_t)((PMSensor[6]<<8) | PMSensor[7]);
		PMResult.PM10_CF 	= (uint16_t)((PMSensor[8]<<8) | PMSensor[9]);
		PMResult.PM1_0 	= (uint16_t)((PMSensor[10]<<8) | PMSensor[11]);
		PMResult.PM2_5 	= (uint16_t)((PMSensor[12]<<8) | PMSensor[13]);
		PMResult.PM10 	= (uint16_t)((PMSensor[14]<<8) | PMSensor[15]);
		
	}
}

int CheckPMSensor(){
	
	uint16_t 	Cal_CheckSum;
	uint16_t 	Buffer_CheckSum;
	uint16_t 	Buffer_Len;
	uint8_t 	i;
	
	int Result = 0;

	if((PMSensor[0] == 'B')&&(PMSensor[1] == 'M')){
		Buffer_Len = (uint16_t)((PMSensor[2] << 8) | PMSensor[3]);

		Buffer_CheckSum = (uint16_t)((PMSensor[Buffer_Len + 2] << 8) | PMSensor[Buffer_Len + 3]);

		Cal_CheckSum = 0;
		for(i=0;i<(Buffer_Len + 2);i++){
			Cal_CheckSum += PMSensor[i];
		}

		if(Cal_CheckSum == Buffer_CheckSum)
			Result = 1;
	}
	return Result;
}


//CO2 sensor
uint8_t CO2SensorBuffer[12];
uint8_t CO2Sensor[12];

int CO2SensorLen = 0, CO2SensorResult = 0;

void ListenCO2Sensor(){
	memset(CO2SensorBuffer, 0, sizeof(CO2SensorBuffer));
	memset(CO2Sensor, 0, sizeof(CO2Sensor));
	
	uint8_t CO2Transmit[12] = {0x42, 0x4D, 0xE3, 0x00, 0x00, 0x01, 0x72};
	
	HAL_UART_Transmit(&huart3, CO2Transmit, 7, 0xFFFF);
	HAL_UART_Receive(&huart3, (uint8_t*)CO2SensorBuffer, 12, 800);
	HAL_Delay(800);
	
	for(int i = 0; i <= 11; ++i){
		//printf("%c", CO2SensorBuffer[i]);
		if(CO2SensorBuffer[i] == 'B' && CO2SensorBuffer[i+1] == 'M'){
			for(CO2SensorLen = 0; CO2SensorLen <= 11; ++CO2SensorLen){	
				CO2Sensor[CO2SensorLen] = CO2SensorBuffer[i + CO2SensorLen];
			}
			break;
		}
		HAL_Delay(500);
	}
	HAL_Delay(2000);
	return ;
}


int CheckCO2Sensor(){
	
	uint16_t 	Cal_CheckSum;
	uint16_t 	Buffer_CheckSum;
	uint16_t 	Buffer_Len;
	uint8_t 	i;
	
	int Result = 0;

	if((CO2Sensor[0] == 'B')&&(CO2Sensor[1] == 'M')){
		
		Buffer_Len = (uint16_t)((CO2Sensor[2] << 8) | CO2Sensor[3]);
		//printf("LEN:%d \n",Buffer_Len);
		Buffer_CheckSum = (uint16_t)((CO2Sensor[Buffer_Len + 2] << 8) | CO2Sensor[Buffer_Len + 3]);
        
		Cal_CheckSum = 0;
		for(i=0;i<(Buffer_Len + 2);i++){
			Cal_CheckSum += CO2Sensor[i];
		}
		//printf("CALSUM:%d, BUFFSUM:%d \n", Cal_CheckSum, Buffer_CheckSum);
		if(Cal_CheckSum == Buffer_CheckSum)
			Result = 1;
	}
	return Result;
}

void GetCO2Sensor(){
	CO2SensorResult = (uint16_t)((CO2Sensor[4]<<8) | CO2Sensor[5]);
	return ;
}

FATFS SDFatFs;
FIL MyFile;

void WriteFile(){
	
	LED0_off();
	LED1_off();
	
	uint32_t byteswritten;
	char nowdate[21];
	sprintf(nowdate, "[20%02d-%02d-%02d %02d:%02d:%02d]\n",
				sDate.Year,
				sDate.Month,
				sDate.Date,
				sTime.Hours,
				sTime.Minutes,
				sTime.Seconds
	);
	char wtext[150] = " ";
	sprintf(wtext, "%sCO2 : _%04d_ ppm\nPM2.5 : _%04d_ ug/m3\nPM10 : _%04d_ ug/m3\n", 
		nowdate,
		CO2SensorResult, 
		PMResult.PM2_5, 
		PMResult.PM10
	);
	char FileName[25] = " ";
	sprintf(FileName, "Sensor_%02d%02d%02d%02d%02d_.txt", 
		sDate.Year,
		sDate.Month,
		sDate.Date,
		sTime.Hours,
		sTime.Minutes
	);
	printf("%s\nFileName:%s\n", wtext, FileName);
	if(f_mount(&SDFatFs, (TCHAR const*)SDPath, 0) == FR_OK){
		PrintTime();
		printf("[SD_FATFS_STAT] Mount Successful!\n");
		if(f_open(&MyFile, (TCHAR const*)FileName, FA_CREATE_ALWAYS | FA_WRITE) == FR_OK){
			PrintTime();
			printf("[SD_FATFS_STAT] Open File Successful!\n");
			FRESULT res = f_write(&MyFile, wtext, (unsigned int)strlen(wtext), (void *)&byteswritten);
			if((byteswritten == 0) || (res != FR_OK)){
				PrintTime();
				printf("[SD_FATFS_STAT] Write Failed!\n");
			}
			else{
				f_close(&MyFile);
				PrintTime();
				printf("[SD_FATFS_STAT] Write Successful!\n");
			}
		}
		else{
				PrintTime();
				printf("[SD_FATFS_STAT] Open File Failed!\n");
		}
	}else{
		PrintTime();
		printf("[SD_FATFS_STAT] Mount Failed!\n");
	}
	
}

void PrintTime(){
	
	printf("[20%02d-%02d-%02d %02d:%02d:%02d]",
				sDate.Year,
				sDate.Month,
				sDate.Date,
				sTime.Hours,
				sTime.Minutes,
				sTime.Seconds
	);
	return ;
}

void CheckState(){
	
	LED0_on();
	LED1_off();
	
	ListenCO2Sensor();
	if(CheckCO2Sensor()){
		PrintTime();
		printf("[CO2_SENSOR_STATE] Success!\n");
		GetCO2Sensor();
	}
	
	else{
		PrintTime();
		printf("[CO2_SENSOR_STATE] Error!\n");
	}
	
	/*PM SENSOR READ*/
	HAL_Delay(100);
	LED0_on();
	LED0_off();
	ListenPMSensor();
	if(CheckPMSensor()){
		PrintTime();
		printf("[PM_SENSOR_STATE] Success!\n");
		GetPMSensor();
	}
	else{
		PrintTime();
		printf("[PM_SENSOR_STATE] Error!\n");
	}
	
	PrintTime();
	printf("\nCO2: %d ppm \nPM2.5: %d ug/m^3\nPM10: %d ug/m^3\n", CO2SensorResult, PMResult.PM2_5, PMResult.PM10);
	WriteFile();
	//WriteFile(filename);
	HAL_Delay(1000);
	
	return ;
 }

/* USER CODE END 0 */

int main(void){
	
  /* USER CODE BEGIN 1 */
	/* USER CODE END 1 */

  /* MCU Configuration--------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* Configure the system clock */
  SystemClock_Config();

  /* USER CODE BEGIN SysInit */

  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_DMA_Init();
  MX_SDIO_SD_Init();
  MX_USART1_UART_Init();
  MX_USART2_UART_Init();
  MX_USART3_UART_Init();
  MX_FATFS_Init();
  MX_RTC_Init();
  /* USER CODE BEGIN 2 */

  /* USER CODE END 2 */
	
  while (1){
    
		/* USER CODE BEGIN 3 */
		
		HAL_Delay(100);
		HAL_RTC_GetTime(&hrtc, &sTime, RTC_FORMAT_BIN);
		HAL_RTC_GetDate(&hrtc, &sDate, RTC_FORMAT_BIN);
		if(second_tmp != sTime.Seconds){
			second_tmp = sTime.Seconds;
			//printf("20%d%d-%d%d-%d%d\n", sDate.Year/10%10, sDate.Year%10, sDate.Month/10%10, sDate.Month%10, sDate.Date/10%10, sDate.Date%10);
			printf("[20%02d-%02d-%02d %02d:%02d:%02d] LOOP = %d\n",
				sDate.Year,
				sDate.Month,
				sDate.Date,
				sTime.Hours,
				sTime.Minutes,
				sTime.Seconds,
				TOT
			);
		}
		
		TOT++;
		LED0_on();
		LED1_on();
		
		CheckState();
		
		HAL_Delay(100);

  }
  /* USER CODE END 3 */
}