IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 嵌入式 -> STM32项目/CubeMx/简易防火装置 -> 正文阅读

[嵌入式]STM32项目/CubeMx/简易防火装置

目录

项目要求

项目完成情况

项目实现流程

使用STMCubeMx创建项目

工程代码

1.软件定时器;

2.重写fputc;

3.ADC转换按键按下时的值和传感器的值;

4.判断火势等级的函数;

5.按键中断回调函数;

遇到的问题与解决方法


项目要求

  1. 同时检测按键和可燃气体(火焰)传感器,按键按下的时候 串口打印“楼层 + 火势情况” ? (按键中断实现),(楼层用五向按键判断 上下左右中分别代表1-5层)?? ?
  2. ADC每500ms开启一次(使用软件定时器)采集火焰值/有害气体值,显示屏实时显示采集到的数值(我自己又显示了楼层和火势等级信息)
  3. 火焰强度/有害气体浓度(一级、二级、三级)
  • ? ? ? ? 一级:亮绿灯 ?(正常状态 没火/无有害气体)
  • ????????二级:亮黄灯 ?(有小火/有害气体浓度较低)
  • ????????三级:蓝灯闪烁(有大火/有害气体浓度高)600ms间隔闪烁(要求使用软件定时器)

项目完成情况

????????使用的光敏传感器代替火焰传感器,效果类似;

????????实现功能:

  1. ADC转换:转换按键按下时的值和传感器值,根据按键不同方向不同值的特性,划分范围区分按键按下的方向,
  2. 按键中断:按键按下时开始在屏幕显示按键方向对应楼层并实时显示传感器值和火势等级,还可以通过串口在电脑打印楼层信息和传感器值;
  3. 串口打印:通过按键中断实现按键按下时串口输出楼层和传感器值;
  4. GPIO:实现led灯闪烁,火势三级时蓝灯闪烁,火势小于三级时led灯停止闪烁并点亮对应等级的led灯。

简易防火装置演示视频

项目实现流程

使用STMCubeMx创建项目

1.配置引脚;

2.由于led灯一端接+3.3V电压,所以led接芯片的引脚初始化为高电平,保证led一开始是灭的;

3.使能EXTI8;

4.外部时钟选择陶瓷谐振器;

5.时基源选择滴答定时器;

6.ADC使能通道IN0和通道IN4;

7.SP1选择全双工主机

每一个像素点为16位,由两个8位拼接起来;

时钟频率为48MHz,所以分频为4分频;

8.串口通信选择异步通信;

9.时钟树设置,时钟频率设置为48MHz;

10.生成工程文件

工程代码

1.软件定时器;

????????自己写一个延时函数(.c文件.h文件),实现延时函数HAL_Delay( )的功能;

#ifndef __DELAYTIME_H__
#define __DELAYTIME_H__
#include "stm32f0xx_hal.h"   
typedef struct
{
uint32_t  start;
uint32_t  delay;
}MY_TIM;
void setTime(MY_TIM *tim,uint32_t delayms);
uint32_t compareTime(MY_TIM *tim);
#endif	
#include "delaytime.h"
//软件定时器配置函数
void setTime(MY_TIM *tim,uint32_t delayms)
{
    tim->start = HAL_GetTick(); //获取当前时间
    tim->delay = delayms;	//获取用户设置的延时时间,单位ms
}
//判断是否到达延时条件
uint32_t compareTime(MY_TIM *tim)
{
    //用当前时间减去用户设置延时时间时的时间
    if(HAL_GetTick() - tim->start < tim->delay)
    {
        return 0;   //未达到延时条件 	
    }else
    {
        return 1;   //已到达延时时间
    }
}

2.重写fputc;

????????重写fputc函数后,可以直接在main函数中使用printf串口打印;

int fputc(int ch,FILE* f)
{
	while(!(USART1->ISR & (1 << 7)));
	USART1->TDR = ch;
	return ch;
}

3.ADC转换按键按下时的值和传感器的值;

????????采集多个通道的传感器数值时,通过判断ADC转换结束后的EOC标志来实现,当单个通道转换完成后会产生EOC信号,即ADC_ISR寄存器第2位被置1;

while (1)
    {
        //软件定时器,判断延时是否结束
        if(compareTime(&tim1) == 1)
        {
            HAL_ADC_Start(&hadc); //启动ADC
            //HAL_ADC_PollForConversion(&hadc,1000); //只采集单个通道时需要添加该句
            while(!(ADC1->ISR &(1<<2))); //等待转换结束
            key_value = HAL_ADC_GetValue(&hadc);  //获取按键的转换结果
            while(!(ADC1->ISR &(1<<2)));
            fire_value = HAL_ADC_GetValue(&hadc); //获取转换后光敏(火焰)传感器的值
            HAL_ADC_Stop(&hadc);  //停止ADC

            //使用标志位,保证按键按下后屏幕上显示按键方向的代表楼层和传感器动态数值
            if(flag == 1)
            {
                getFire(fire_value);
            }

            //重新设置延时时间
            setTime(&tim1,500);
        }
    }

4.判断火势等级的函数;

????????由于使用的传感器是光敏传感器,所以我们可以使用三种情况下的传感器数值来分别代表三个火势等级,即

  1. 正常光照下的传感器数值的范围;
  2. 明亮光源照射下的传感器数值范围;
  3. 遮挡光照后的传感器数值的范围;

????????经实验测得,正常光照下的范围大约为2300~3200;明亮光源照射下的范围大约为0~2000;遮挡光照下的范围大约为3200~5000;

????????在函数中判断当ADC转换后的传感器的值在某一范围时,向lcd屏幕上显示对应得火势等级和传感器数值,并控制对应的led灯的亮灭;

void getFire(uint16_t fire_value)
{
    if(fire_value > 0 && fire_value < 2000)
    {
        Gui_DrawFont_GBK16(10,30,WHITE,BLACK,"LEVEL 2:"); //向lcd屏幕上打印火势等级
        HAL_GPIO_WritePin(GPIOB,GPIO_PIN_2,GPIO_PIN_RESET); //点亮对应led灯
        HAL_GPIO_WritePin(GPIOB,GPIO_PIN_0|GPIO_PIN_1,GPIO_PIN_SET); //熄灭对应led灯

    }else if(fire_value > 2300 && fire_value < 3200)
    {
        Gui_DrawFont_GBK16(10,30,WHITE,BLACK,"LEVEL 1:");
        HAL_GPIO_WritePin(GPIOB,GPIO_PIN_0,GPIO_PIN_RESET);
        HAL_GPIO_WritePin(GPIOB,GPIO_PIN_1|GPIO_PIN_2,GPIO_PIN_SET);
    }else if(fire_value > 3200 && fire_value < 5000)
    {
        Gui_DrawFont_GBK16(10,30,WHITE,BLACK,"LEVEL 3:");
        HAL_GPIO_WritePin(GPIOB,GPIO_PIN_0|GPIO_PIN_2,GPIO_PIN_SET);
        while(1)
            {
                //软件定时器
                if(compareTime(&tim2) == 1)
                {
                    //在循环中使用翻转电平的库函数,实现led灯的闪烁
                    HAL_GPIO_TogglePin(GPIOB,GPIO_PIN_1);
                    memset(fire_array,0,32);
                    //将传感器数值转换成字符串,方便使用lcd的字符串显示函数
                    sprintf(fire_array,"%d",fire_value);
                    Gui_DrawFont_GBK16(74,30,WHITE,BLACK,fire_array);

                    setTime(&tim2,600);
                }

                //为了能够在循环中读取传感器新测得的数值,重新进行ADC的开启和关闭过程
                HAL_ADC_Start(&hadc); 
                //HAL_ADC_PollForConversion(&hadc,1000);
                while(!(ADC1->ISR &(1<<2)));		//等待转换
                key_value = HAL_ADC_GetValue(&hadc);
                while(!(ADC1->ISR &(1<<2)));
                fire_value = HAL_ADC_GetValue(&hadc);
                HAL_ADC_Stop(&hadc);
                //当判断出光敏传感器的值不处于该范围时,跳出循环
                if(fire_value < 3200)
                    break;
            }	
    }
    
    memset(fire_array,0,32);
    sprintf(fire_array,"%d",fire_value);
    Gui_DrawFont_GBK16(74,30,WHITE,BLACK,fire_array);
}

5.按键中断回调函数;

????????该回调函数在main.c文件中重写定义即可,不需要手动调用和声明,当按键按下时自动调用;

????????同样先进行实验来判断按键向不同方向按下时的ADC转换值,

  1. 向下按时,转换值范围大约为2500~2600;
  2. 向前按时,转换值范围大约为2000~2200;
  3. 向后按时,转换值范围大约为400~500;
  4. 向左按时,转换值范围大约为1400~1600;
  5. 向右按时,转换值范围大约为2900~3000;
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
    //判断对应按键是否按下
	if(GPIO_Pin == GPIO_PIN_8)
	{
        //按键按下时使标志位等于1,使光敏传感器的值能够输出到屏幕上;
		flag = 1;
        
		HAL_ADC_Start(&hadc); 
		//HAL_ADC_PollForConversion(&hadc,1000);
		while(!(ADC1->ISR &(1<<2)));		//等待转换
		key_value = HAL_ADC_GetValue(&hadc);
		while(!(ADC1->ISR &(1<<2)));
		fire_value = HAL_ADC_GetValue(&hadc);
		HAL_ADC_Stop(&hadc);
		
		if(key_value > 2500 && key_value < 2600)
		{
			Gui_DrawFont_GBK16(10,10,WHITE,BLACK,"1 floor");
			printf("1 floor/fire_data:%d",fire_value);
		}else if(key_value > 2000 && key_value < 2200)
		{
			Gui_DrawFont_GBK16(10,10,WHITE,BLACK,"2 floor");
			printf("2 floor/fire_data:%d",fire_value);
		}else if(key_value > 400 && key_value < 500)
		{
			Gui_DrawFont_GBK16(10,10,WHITE,BLACK,"3 floor");
			printf("3 floor/fire_data:%d",fire_value);
		}else if(key_value > 1400 && key_value < 1600)
		{
			Gui_DrawFont_GBK16(10,10,WHITE,BLACK,"4 floor");
			printf("4 floor/fire_data:%d",fire_value);
		}else if(key_value > 2900 && key_value < 3000)
		{
			Gui_DrawFont_GBK16(10,10,WHITE,BLACK,"5 floor");
			printf("5 floor/fire_data:%d",fire_value);
		}
	}
}

遇到的问题与解决方法

问题1:刚开始做这个项目的时候,我只知道传感器的值可以根据不同情况来区分不同等级,但是不清楚如何判断按键按下时的方向。

解决方法:后来经过查阅资料,无意间发现五向键按下不同方向时,产生的电压不同,所以我联想到,按键按下不同方向时ADC转换的值应该也不一样,经过实验后,发现确实如此。

问题2:火势等级为三级时,要求为蓝灯闪烁,但是蓝灯闪烁后,显示屏的传感器数值不再更新,而且蓝灯有时闪烁,有时不闪烁。

解决方法:通过在蓝灯闪烁的while循环代码中,添加ADC转换传感器数值的程序代码,并且判断转换的值是否在该火势等级的范围内,不在则break跳出循环。

问题3:lcd屏幕的字符串显示函数只能传字符串,不能传数值。

解决方法:使用sprintf函数将转换的传感器数值转换成字符串;

  嵌入式 最新文章
基于高精度单片机开发红外测温仪方案
89C51单片机与DAC0832
基于51单片机宠物自动投料喂食器控制系统仿
《痞子衡嵌入式半月刊》 第 68 期
多思计组实验实验七 简单模型机实验
CSC7720
启明智显分享| ESP32学习笔记参考--PWM(脉冲
STM32初探
STM32 总结
【STM32】CubeMX例程四---定时器中断(附工
上一篇文章      下一篇文章      查看所有文章
加:2022-09-25 23:18:15  更:2022-09-25 23:19:03 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/25 20:13:45-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码