找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 7713|回复: 15
收起左侧

基于STM32的室内环境监控系统Proteus仿真程序设计

  [复制链接]
ID:572551 发表于 2020-6-19 00:06 | 显示全部楼层 |阅读模式
我的嵌入式学习作品,算是学习STM32后的总结,如有可改进的地方,欢迎讨论。
1. 功能描述
开机默认温度设定值为25°C,设定湿度设定值为35%LCD界面显示测得温湿度如下。当温湿度传感器读到温度或湿度有一个值大于设定值时,则风机打开,在温度大于36度或湿度大于80%时,则风机100%全开,当温度和湿度都小于设定值时,则风机关闭,当温度在温度设定值到36°之间,湿度在湿度设定值到80%之间,则风机按线性比例以1%~99%占空比输出。另外,根据光照强度,当光敏传感器值小于0.7 v则打开继电器,反之则关闭继电器。
   11.png
各按键功能如下:
·       mode按键:模式设定,按一下进入设定模式,再按一下进入正常运行模式,设定模式下LCD显示如下图:
22.png
·       select按键:选择键,在设定模式按一下select按键,选中设置湿度(H),再按一下选中设置温度(T),若选中H,则H闪烁,若选择T,则T闪烁。在正常工作模式下,此按键没作用。
·       +按键:在设置模式下,如果选中H状态下,则每按下+按键,湿度设置值+1,同样,选中T状态,则温度设定值+1。在正常工作模式下,此按键没作用。
·       -按键:作用和按键3类似,选中H状态下,则每按下-键,湿度是定值-1,选中T状态下,则每按下-键,温度设定值-1。在正常工作模式下,此按键没作用。
·       enter键:为确定键,在设定模式下,按下enter键,则退出设定模式,进入正常工作模式,按照新的设定值进行工作。在正常工作模式下,此按键没作用。

2.Proteus仿真原理图如下:
33.png
3.部分源码如下:代码比较简单,所以注释比较少)
光照AD采集
voidget_ADValue(void)
{
              HAL_ADC_Start(&hadc1);
              HAL_GPIO_WritePin(GPIOC,GPIO_PIN_2,GPIO_PIN_RESET);
              HAL_Delay(100);
              if(HAL_ADC_PollForConversion(&hadc1,50)== HAL_OK)
              {
                     adc_value =HAL_ADC_GetValue(&hadc1);
                     voltage =adc_value*330/4096;

//                  printf("光敏AD值 :%d\n\r",adc_value);
//                  printf("光敏电压 :%d.%d%dV\n\r",voltage/100,voltage/10,voltage%10);
              }
              HAL_GPIO_WritePin(GPIOC,GPIO_PIN_2,GPIO_PIN_SET);
              HAL_ADC_Stop(&hadc1);
              if(voltage<70)//控制继电器开关
              {
                     HAL_GPIO_WritePin(LED4_GPIO_Port,LED4_Pin,GPIO_PIN_RESET);
              }
              else
              {
                     HAL_GPIO_WritePin(LED4_GPIO_Port,LED4_Pin,GPIO_PIN_SET);
              }
              HAL_Delay(500);

}
按键扫描系统
uint8_tkeyscan(uint8_t kk)
{
       static uint8_t keyflag = 1;
       if(kk) keyflag = 1;
       if(keyflag &&(KEY0==0||KEY1==0||KEY2==0||KEY3==0||KEY4==0))
       {
              HAL_Delay(5);
              keyflag = 0;
              if(KEY0==0)     return 1;
              else if(KEY1==0) return 2;
              else if(KEY2==0) return 3;
              else if(KEY3==0) return 4;
              else if(KEY4==0) return 5;
       }
       elseif(KEY0==1&&KEY1==1&&KEY2==1&&KEY3==1&&KEY4==1)keyflag = 1;
       return 0;
}

voidkey_system(void)
{
       key_num=keyscan(0);
       switch(key_num)
       {
              case 1:
                     mode1++;//模式标志位
                     flag=1;//设定模式下更新屏幕显示的标志位 可减少闪屏
                     LCD1602_WriteCmd(0x01);//清屏
                     if(mode1>1)
                     {
                            mode1 = 0;
                            menu = 0;
                            LCD1602_WriteCmd(0x0c);//关光标关闪烁
                     }
                     break;
              case 2:
                     if(mode1==0) break;
                     else
                     {
                            flag=1;
                            menu++;//设置对象选择标志位
                            if(menu>1) menu =0;
                     }
                     break;
              case 3:
                     if(mode1==0) break;
                     flag=1;
                     if(menu==0) humi++;
                     else              temp++;
                     break;
              case 4:
                     if(mode1==0) break;
                     flag=1;
                     if(menu==0) humi--;
                     else              temp--;
                     break;
              case 5:
                     if(mode1==0) break;
                     else
                     {
                            mode1 = 0;
                            menu = 0;
                            LCD1602_WriteCmd(0x01);
                            LCD1602_WriteCmd(0x0c);
                     }
                     break;
              default: break;
       }
}
风机PWM调速控制
uint8_tMAX(uint8_t x,uint8_t y)//较大值判断
{
       uint8_t max;
       if(x>y) max=x;
       else max=y;
       return max;
}

uint16_tFAN_control(void)
{
       uint16_t pwm;
       if(temperature<temp &&humidity<humi)  pwm=0;
       if(temperature>36 &&temperature>temp) pwm=100;
       if(humidity>80 &&humidity>humi)       pwm=100;
       if(temperature>=temp ||humidity>=humi)
       {
              if(humidity<=80 &&humidity>=humi)
              {
                     num1=(uint8_t)humidity-humi;
                     num2=80-humi;
                     pwmh=num1*100/num2;
              }
              if(temperature<=36 &&temperature>=temp)
              {
                     num1=(uint8_t)temperature-temp;
                     num2=36-temp;
                     pwmh=num1*100/num2;
              }
              pwm=MAX(pwmh,pwmt);
       }
       if(temperature>36 &&temperature>temp) pwm=100;
       if(humidity>80 &&humidity>humi)       pwm=100;
       return pwm;
}
主程序
int main(void)
{
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
LCD1602_Init();
LCD1602_ShowStr(0,0,"INT...",6);
MX_TIM4_Init();
MX_ADC1_Init();
MX_USART1_UART_Init();
HAL_TIM_PWM_Start(&htim4,TIM_CHANNEL_3);
HAL_Delay(100);  while (1)
  {
              DHT11_Show_Data();//调用温湿度检测子程序
              get_ADValue();//调用光强AD值子程序
              do//这里用do循环先执行,再判断模式标志位值,为1时只执行循环体内程序,可减少软件仿真时卡顿,未测试单片机运行
              {
                     key_system();
                     if(mode1==0)
                     {
                            LCD1602_ShowStr(0,0,"H  T   FAN    ",15);
                            LCD1602_ShowChar(0,1,(uint8_t)humidity/10+0x30);
                            LCD1602_ShowChar(1,1,(uint8_t)humidity%10+0x30);
                            LCD1602_ShowChar(4,1,(uint8_t)temperature/10+0x30);
                            LCD1602_ShowChar(5,1,(uint8_t)temperature%10+0x30);
                            if(pwm_value==0) LCD1602_ShowStr(8,1,"OFF",3);
                            else                      LCD1602_ShowStr(8,1,"ON",3);
                     }
                     else
                     {
                            if(menu==0&&flag==1)//标志位为1时更新显示
                            {
                                   LCD1602_ShowStr(0,0,"SET  H   T",11);
                                   LCD1602_ShowChar(6,1,humi/10+0x30);
                                   LCD1602_ShowChar(7,1,humi%10+0x30);
                                   LCD1602_ShowChar(10,1,temp/10+0x30);
                                   LCD1602_ShowChar(11,1,temp%10+0x30);
                                   write_guanbiao(6,0,1);
                                   flag=0;//标志位置0
                                   HAL_Delay(200);
                            }
                            else if(flag==1)
                            {
                                   LCD1602_ShowStr(0,0,"SET  H   T",11);
                                   LCD1602_ShowChar(6,1,humi/10+0x30);
                                   LCD1602_ShowChar(7,1,humi%10+0x30);
                                   LCD1602_ShowChar(10,1,temp/10+0x30);
                                   LCD1602_ShowChar(11,1,temp%10+0x30);
                                   write_guanbiao(10,0,1);
                                   flag=0;
                                   HAL_Delay(200);
                            }
                     }
              }while(mode1==1);
              pwm_value=FAN_control();
              __HAL_TIM_SET_COMPARE(&htim4,TIM_CHANNEL_3,pwm_value);
              HAL_Delay(10);
  }
}

51hei.png
仿真原理图及源工程文件下载:
程序+仿真.7z (517.58 KB, 下载次数: 393)

评分

参与人数 1黑币 +50 收起 理由
admin + 50 共享资料的黑币奖励!

查看全部评分

回复

使用道具 举报

ID:785236 发表于 2020-6-20 22:33 | 显示全部楼层
想问问我怎么打开就是各个数值都是0
回复

使用道具 举报

ID:572551 发表于 2020-6-21 11:56 来自手机 | 显示全部楼层
本帖最后由 昔影 于 2020-6-21 18:05 编辑
啥也不会罗小白 发表于 2020-6-20 22:33
想问问我怎么打开就是各个数值都是0

可能是Proteus仿真的问题
回复

使用道具 举报

ID:572551 发表于 2020-6-21 14:51 | 显示全部楼层
啥也不会罗小白 发表于 2020-6-20 22:33
想问问我怎么打开就是各个数值都是0

我这边仿真没问题,如果你也用的仿真,可能是因为DHT11时序未完成就执行显示代码了,可以试试在do循环前加个短的延时
回复

使用道具 举报

ID:725124 发表于 2020-6-21 18:44 | 显示全部楼层
请问有硬件原理图吗
回复

使用道具 举报

ID:572551 发表于 2020-6-21 22:47 | 显示全部楼层
奈克y 发表于 2020-6-21 18:44
请问有硬件原理图吗

还没有用单片机运行,根据仿真原理图做应该不难,我这有个Arduino板子准备试试
回复

使用道具 举报

ID:634955 发表于 2020-6-22 10:25 | 显示全部楼层
可以,感觉和烟雾报警的差不多,没有本质区别。
回复

使用道具 举报

ID:790463 发表于 2020-6-27 15:12 | 显示全部楼层
请问为什么我运行一段时间之后就自动关闭工程了?
回复

使用道具 举报

ID:572551 发表于 2020-6-28 17:39 来自手机 | 显示全部楼层
WSP666 发表于 2020-6-27 15:12
请问为什么我运行一段时间之后就自动关闭工程了?

应该是仿真软件的问题,proteus对stm32F4适配支持不太好
回复

使用道具 举报

ID:904379 发表于 2021-4-21 02:12 来自手机 | 显示全部楼层
能把光照改成PM2.5吗
回复

使用道具 举报

ID:574661 发表于 2021-5-17 20:56 | 显示全部楼层
proteus小白,请问debug.elf not found是什么问题呢?
回复

使用道具 举报

ID:574661 发表于 2021-5-17 20:58 | 显示全部楼层
请问debug.elf not found是什么问题呢
回复

使用道具 举报

ID:572551 发表于 2021-6-15 07:40 来自手机 | 显示全部楼层
he1415926 发表于 2021-5-17 20:58
请问debug.elf not found是什么问题呢

试一下用hex文件导入
回复

使用道具 举报

ID:440028 发表于 2021-12-3 15:56 | 显示全部楼层
改成烟雾报警系统是不是要加延迟
回复

使用道具 举报

ID:1023206 发表于 2022-5-16 08:50 | 显示全部楼层
两个hex文件都怎么用啊
回复

使用道具 举报

ID:228452 发表于 2022-5-16 20:52 | 显示全部楼层


use project666.hex
or
pwm_key1.hex
cant use both in same time..


回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表