基于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 */
}