• 【单片机毕业设计】【mcuclub-hj-005-3】基于单片机的空气质量(天然气或煤气)检测的设计


      最近设计了一个项目基于单片机的空气质量(天然气或煤气)检测系统,与大家分享一下:

     

    一、基本介绍

    项目名:空气质量(天然气或煤气)
    项目编号:mcuclub-hj-005-3
    单片机类型:STC89C52、STM32F103C8T6
    具体功能:
    1、通过MQ-5检测天然气或煤气值,超过设置最大值进行声光报警,并开启风扇和净化器
    2、通过按键设置上限值,可以手动控制风扇和净化器、切换模式
    3、通过显示屏显示数据
    扩展功能:通过蓝牙模块将测量数据发送到手机端,并可以控制风扇和净化器、切换模式

    二、51实物图

    单片机型号:STC89C52

    板子为绿色PCB板,两层板,厚度1.2,上下覆铜接地。元器件基本上为插针式,个别降压芯片会使用贴片式。

    供电接口:TYPE-C

    三、51仿真图

    仿真软件版本:proteus8.9

    电路连线方式:网络标号连线方式

    注意:部分实物元器件仿真中没有,仿真中会用其他工作原理相似的元件代替,这样可能导致实物程序和仿真程序不一样

     四、32实物图

    单片机型号:STM32F103C8T6

    板子为绿色PCB板,两层板,厚度1.2,上下覆铜接地。元器件基本上为插针式,个别降压芯片会使用贴片式。

    供电接口:TYPE-C

     五、原理图

    软件版本:AD2013

    电路连线方式:网络标号连线方式

    注意:原理图只是画出了模块的引脚图,而并不是模块的内部结构原理图

     六、PCB图

    由原理图导出,封装很大一部分都是作者自己绘制,不提供封装库,只提供连接好的源文件。中间有一个项目编号,隐藏在单片机底座下,插入单片机后不会看到。

    两层板,上下覆铜接地。

    七、系统框图

    本设计以单片机为核心控制器,加上其他模块一起组成此次设计的整个系统,其中包括中控部分、输入部分和输出部分。中控部分采用了单片机控制器,其主要作用是获取输入部分的数据,经过内部处理,逻辑判断,最终控制输出部分。输入由三部分组成,第一部分是可燃气体检测模块,通过该模块检测当前环境的可燃气体 ;第二部分是按键模块,通过该模块可以切换界面、设置阈值、切换模式等;第三部分是供电模块,通过该模块可给整个系统进行供电。输出由三部分组成,第一部分是显示模块,通过该模块可以显示监测的数据以及设置的阈值;第二部分是继电器模块,通过两个继电器分别控制通风和净化;第三部分是声光报警模块,当监测值不在设置的阈值内时进行声光报警。除此之外,蓝牙模块既作为输入又作为输出,蓝牙模块和手机进行连接,可以将监测的数据传输到用户手机端,用户也可以通过手机端发送指令控制继电器的工作及其模式的切换。具体系统框图如图所示。

     八、软件设计流程

    系统的主流程图如图所示。在主程序中:首先对各个模块进行初始化,随后进入while主循环,在主循环中,首先进入第一个函数按键函数,该函数主要分为两部分,第一部分为调用按键扫描函数获取按键键值,第二部分通过键值进行相应的处理操作,包括切换界面、设置阈值等;紧接着进入第二个函数监测函数,该函数主要通过调用相应的驱动函数获取测量值,并通过蓝牙模块将监测的数据传输到手机端,用户也可以通过手机端发送指令,设备根据用户发送的指令执行对应的处理;紧接着进入第三个函数显示函数,该函数显示监测值及阈值;最后进入第四个函数处理函数,该函数主要判断当前可燃气体是否在设置的阈值之内,如果可燃气体大于设置的最大值,则声光报警,并且打开通风和净化继电器,如果可燃气体在设置的阈值之内,则取消声光报警,并关闭所有继电器。

     九、部分程序展示

    软件版本:keil5

    逻辑程序和驱动程序分开,分布于main.c和其他.c文件

    1. /**********************************
    2. 作者:单片机俱乐部
    3. 网站:https://www.mcuclub.cn/
    4. **********************************/
    5. /**********************************
    6. 包含头文件
    7. **********************************/
    8. #include "main.h"
    9. #include "lcd1602.h"
    10. #include "key.h"
    11. #include "uart.h"
    12. #include "adc.h"
    13. /**********************************
    14. 变量定义
    15. **********************************/
    16. uchar key_num = 0; //按键扫描标志位
    17. uchar flag_display = 0; //显示界面标志位
    18. uint time_num = 0; //10ms计时变量
    19. uint fgas_value = 0; //燃气值
    20. uint fgas_max = 80; //燃气最大值
    21. uchar flag_relay = 0; //继电器标志位
    22. bit flag_mode = 0; //模式标志位
    23. uchar fasong_buf[32]; //发送专用数组
    24. /**********************************
    25. 函数声明
    26. **********************************/
    27. void Delay_function(uint x); //延时函数(ms)
    28. void Key_function(void); //按键函数
    29. void Monitor_function(void); //监测函数
    30. void Display_function(void); //显示函数
    31. void Manage_function(void); //处理函数
    32. /****
    33. ******* 主函数
    34. *****/
    35. void main()
    36. {
    37. Lcd1602_Init(); //LCD1602初始化
    38. Delay_function(50); //延时50ms
    39. lcd1602_clean(); //清屏
    40. Delay_function(50); //延时50ms
    41. Uart_Init(); //串口初始化函数
    42. Delay_function(50); //延时50ms
    43. while(1)
    44. {
    45. Key_function(); //按键函数
    46. Monitor_function(); //监测函数
    47. Display_function(); //显示函数
    48. Manage_function(); //处理函数
    49. Delay_function(10); //延时10ms
    50. time_num++; //计时变量+1
    51. if(time_num == 5000)
    52. {
    53. time_num = 0;
    54. }
    55. }
    56. }
    57. /****
    58. ******* 延时 x ms函数
    59. *****/
    60. void Delay_function(uint x)
    61. {
    62. uint m,n;
    63. for(m=x;m>0;m--)
    64. for(n=110;n>0;n--);
    65. }
    66. /****
    67. *******按键函数
    68. *****/
    69. void Key_function(void)
    70. {
    71. key_num = Chiclet_Keyboard_Scan(0); //按键扫描
    72. if(key_num != 0) //有按键按下
    73. {
    74. switch(key_num)
    75. {
    76. case 1: //按键1,切换设置界面
    77. flag_display++;
    78. if(flag_display >= 2)
    79. flag_display = 0;
    80. lcd1602_clean(); //清屏
    81. break;
    82. case 2: //按键2
    83. switch(flag_display)
    84. {
    85. case 0: //界面0:继电器控制标志位+1
    86. flag_relay++;
    87. if(flag_relay >= 2)
    88. flag_relay = 0;
    89. flag_mode = 1;
    90. break;
    91. case 1: //界面:设置燃气最大值+1
    92. if(fgas_max < 200)
    93. fgas_max++;
    94. break;
    95. default:
    96. break;
    97. }
    98. break;
    99. case 3: //按键3
    100. switch(flag_display)
    101. {
    102. case 0: //界面0:切换模式
    103. flag_mode = 0;
    104. break;
    105. case 1: //界面1:设置燃气最大值-1
    106. if(fgas_max > 0)
    107. fgas_max--;
    108. break;
    109. default:
    110. break;
    111. }
    112. break;
    113. default:
    114. break;
    115. }
    116. }
    117. }
    118. /****
    119. *******监测函数
    120. *****/
    121. void Monitor_function(void)
    122. {
    123. if(time_num % 10 == 0) //100ms检测一次
    124. {
    125. if(DO == 0)
    126. fgas_value = 40*((Adc0832_Get_Value(0)/255.0)*5); //获取燃气浓度
    127. else
    128. fgas_value = 0;
    129. }
    130. if(time_num % 100 == 0) //1s发送一次
    131. {
    132. sprintf(fasong_buf,"Fgas:%dppm\r\n",fgas_value);
    133. Uart_Sent_Str(fasong_buf); //发送燃气
    134. }
    135. }
    136. /****
    137. *******显示函数
    138. *****/
    139. void Display_function(void)
    140. {
    141. switch(flag_display) //根据不同的显示模式标志位,显示不同的界面
    142. {
    143. case 0: //界面0:显示
    144. lcd1602_display_str(1,0,"Fgas Max:"); //显示燃气最大值
    145. lcd1602_display_gas(1,9,fgas_max);
    146. lcd1602_display_str(2,0,"Fgas:"); //显示燃气值
    147. lcd1602_display_gas(2,5,fgas_value);
    148. if(flag_mode == 0) //显示模式
    149. lcd1602_display_str(2,12,"Auto");
    150. else
    151. lcd1602_display_str(2,12,"Manu");
    152. break;
    153. case 1: //界面1:显示设置燃气最大值
    154. lcd1602_display_str(1,2,"Set Fgas Max");
    155. if(time_num % 20 == 0)
    156. {
    157. lcd1602_display_num(2,7,fgas_max);
    158. }
    159. if(time_num % 40 == 0)
    160. {
    161. lcd1602_display_str(2,7," ");
    162. }
    163. break;
    164. default:
    165. break;
    166. }
    167. }
    168. /****
    169. *******处理函数
    170. *****/
    171. void Manage_function(void)
    172. {
    173. if(flag_display == 0) //测量界面
    174. {
    175. if(flag_mode == 0 )
    176. {
    177. if(fgas_value > fgas_max) //燃气值大于设置的最大值
    178. {
    179. if(time_num % 20 == 0)
    180. {
    181. LED = ~LED;
    182. BEEP = ~BEEP;
    183. }
    184. RELAY_TF = 0;
    185. RELAY_JH = 0;
    186. }
    187. else //燃气值小于等于设置的最大值
    188. {
    189. LED = 1;
    190. BEEP = 1;
    191. RELAY_TF = 1;
    192. RELAY_JH = 1;
    193. }
    194. }
    195. else
    196. {
    197. LED = 1;
    198. BEEP = 1;
    199. switch(flag_relay)
    200. {
    201. case 0: //通风关,净化关
    202. RELAY_TF = 1;
    203. RELAY_JH = 1;
    204. break;
    205. case 1: //通风开,净化开
    206. RELAY_TF = 0;
    207. RELAY_JH = 0;
    208. break;
    209. default:
    210. break;
    211. }
    212. }
    213. }
    214. else //设置界面,关闭声光报警、继电器
    215. {
    216. LED = 1;
    217. BEEP = 1;
    218. RELAY_TF = 1;
    219. RELAY_JH = 1;
    220. }
    221. }
    222. V

    资料下载请点击跳转到官网下载http://www.mcuclub.cn

  • 相关阅读:
    QT Day5
    JS-17--深拷贝跟浅拷贝的区别?如何实现一个深拷贝?
    TikTok搬运视频怎么做,搬运怎样的视频最好
    Mysql常用函数(汇总)
    网络安全(黑客)自学
    DSA之图(2):图的存储结构
    数据分析知识点搜集(纯粹的搜集)
    维度转换的艺术:Kylin Cube设计的自定义魔法
    Redis学习记录------Redis6常用五大数据类型(三)
    PHP留言反馈管理系统源码
  • 原文地址:https://blog.csdn.net/weixin_61121477/article/details/127412902