一、需求分析
隨著社會的發展和生活水平的提高,人們對于行車安全、家庭安全的要求越來越高,而酒駕等問題也日漸突出,為此,開發一款基于STM32的酒精檢測儀,通過檢測酒精濃度,實時顯示結果并進行報警,可以有效避免因酒后駕車帶來的安全隱患。
二、設計思路
2.1 硬件設計
1、主控芯片采用STM32F103RCT6,該芯片具有較高的性能和穩定性,能夠滿足本設計的各項需求。
2、酒精傳感器采用MQ-3模塊,該模塊具有高精度、響應速度快等特點,能夠準確檢測酒精濃度。
4、蜂鳴器,用于進行聲音報警。
5、按鍵,用于設定報警閾值。
2.2 軟件設計
1、IO口配置:將相應的IO口配置為輸入輸出,并使能對應的時鐘。
2、ADC配置:將ADC采樣通道、采樣時間、采樣頻率等參數進行配置。
3、OLED配置:初始化OLED。
4、中斷初始化:對按鍵進行中斷初始化,并在中斷服務函數中實現相應的操作。
5、主程序:定時讀取酒精傳感器的濃度值并將其轉換為電壓值,然后通過ADC進行采樣,最后通過OLED顯示屏進行實時顯示。同時也需要根據設定的閾值進行判斷,并觸發相應的報警。
2.3 程序設計思路
main()
{
初始化IO口
初始化ADC
初始化OLED
配置中斷
while(1)
{
讀取濃度值并轉換為電壓
進行ADC采樣
計算實際濃度值
顯示實時濃度值
判斷是否超過設定閾值
觸發相應的報警
}
}
?
void EXTIx_IRQHandler()
{
檢測按鍵狀態
根據按鍵狀態進行相應的操作
}
三、代碼設計
//頭文件引用
#include "stm32f10x.h"
#include "OLED.h"
#include "ADC.h"
#include "MQ3.h"
?
//定義相關參數
#define THRESHOLD1 100
#define THRESHOLD2 200
#define THRESHOLD3 300
?
//定義中斷服務函數
void EXTI0_IRQHandler(){
if(GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_0) == 0){
threshold++;
if(threshold == 4) threshold = 1;
OLED_Clear();
OLED_ShowString(0,0,"Threshold:");
switch(threshold){
case 1:{
OLED_ShowString(70,0,"100");
break;
}
case 2:{
OLED_ShowString(70,0,"200");
break;
}
case 3:{
OLED_ShowString(70,0,"300");
break;
}
default:{
break;
}
}
}
EXTI_ClearITPendingBit(EXTI_Line0);
}
?
int main(void)
{
//初始化IO口
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC | RCC_APB2Periph_GPIOA, ENABLE); //使能端口時鐘
GPIO_InitTypeDef GPIO_InitStructure; //定義GPIO結構體
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //輸出模式
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //速度50MHz
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13; //LED所在引腳
GPIO_Init(GPIOC, &GPIO_InitStructure); //初始化GPIOC13
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; //浮空輸入模式
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0; //按鍵所在引腳
GPIO_Init(GPIOA, &GPIO_InitStructure); //初始化GPIOA0
?
//初始化ADC
ADC_Configuration();
?
//初始化OLED
OLED_Init();
OLED_Clear();
?
//配置中斷
EXTI_InitTypeDef EXTI_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
GPIO_EXTILineConfig(GPIO_PortSourceGPIOA, GPIO_PinSource0);
EXTI_InitStructure.EXTI_Line = EXTI_Line0;
EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising;
EXTI_InitStructure.EXTI_LineCmd = ENABLE;
EXTI_Init(&EXTI_InitStructure);
NVIC_InitStructure.NVIC_IRQChannel = EXTI0_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
?
//定義相關變量
uint16_t adc_value = 0;
float voltage = 0.0;
float concentration = 0.0;
uint8_t threshold = 1;
?
while(1)
{
//讀取酒精傳感器的濃度值并轉換為電壓值
adc_value = Get_ADC1_ConvertedValue(ADC_Channel_6);
voltage = (adc_value * 3.3) / 4096;
?
//計算實際濃度值
concentration = Get_MQ3_Concentration(voltage);
?
//顯示實時濃度值
OLED_ShowString(0, 0, "Concentration:");
OLED_ShowNum(100, 0, concentration, 1, 2);
?
//判斷是否超過設定閾值
if(concentration > THRESHOLD3){
GPIO_SetBits(GPIOC, GPIO_Pin_13); //LED燈亮
BEEP_ON; //蜂鳴器報警
}
else