• 基于STM32设计的酒驾报警系统


    1. 前言

    随着社会的发展和人们生活水平的提高,汽车已经成为人们出行的主要代步工具,与此同时,酒后驾车所引发的事故越来越多,对人们的生命安全带来了威胁。为了控制酒后驾车,本文设计了一款能够安装在车辆驾驶室内的酒后驾车监测系统。

    系统主控芯片采用STM32,采用酒精传感器采集数据进行分析,如果发现酒精超标,会通过GPRS模块向指定的手机号码发送提醒短信;系统还带了一块LCD显示屏,可以实时显示检测的酒精含量,酒精超标后,本地蜂鸣器也会发出警报,提醒驾驶员。

    测量酒驾的标准是:

    (1)饮酒驾车是指车辆驾驶人员血液中的酒精含量大于或者等于20mg/100ml,小于80mg/100ml的驾驶行为。(2)醉酒驾车是指车辆驾驶人员血液中的酒精含量大于或者等于80mg/100ml的驾驶行为。

    需要使用的硬件如下:

    (1)STM32系统板

    (2)酒精检测传感器

    (3)LCD显示屏

    (4)供电模块

    (5)SIM800C模块

    (6)蜂鸣器模块

    image-20220416132842388

    image-20220416142024166

    image-20220416142138765

    为了测试效果,喝了几口。

    image-20220416142200842

    2. 硬件选型

    2.1 STM32系统板

    主控CPU采用STM32F103RCT6,这颗芯片包括48 KB SRAM、256 KB Flash、2个基本定时器、4个通用定时器、2个高级定时器、51个通用IO口、5个串口、2个DMA控制器、3个SPI、2个I2C、1个USB、1个CAN、3个12位ADC、1个12位DAC、1个SDIO接口,芯片属于大容量类型,配置较高,整体符合硬件选型设计。当前选择的这款开发板自带了一个1.4寸的TFT-LCD彩屏,可以显示当前传感器数据以及一些运行状态信息。

    image-20220411152837505

    2.2 酒精检测传感器

    MQ-3 使用的二氧化锡(SnO 2 )作为气敏材料, 当传感器处在存在酒精蒸汽环境中时, 传感器的电导率会随着空气中酒精气体浓度的增加而增大,使用简单的电路即可将电导率的变化转换为与该气体浓度相对应的信号。

    该模块主要特点如下:

    (1)具有信号输出指示。
    (2)输出的双通道信号(模拟量输出与 TTL 输出)。
    (3)TTL 输出有效信号为低电平。
    (4)模拟输出电压为 0~5V, 浓度高则电压高。
    (5)对乙醇蒸汽拥有很高的灵敏度和不错的选择性。
    (6)它具有较长的使用寿命和可靠的稳定性。
    (7)快速的响应恢复特性。

    image-20220416132552711

    image-20220411153034912

    2.3 SIM800C模块

    SIM800C模块是一款高性能高性价比工业级的GSM/GPRS模块。本模块采用SIMCOM公司的工业级四频850/900/ 1800/1900MHz SM800芯片,可以低功耗实现语音、SMS、数据和传真信息的传输。

    image-20220411154906282

    模块特点:

    1、支持极限DC5V-18V宽电压输入

    2、有电源使能开关引脚EN

    3、支持锂电池供电接口VBAT3.5-4.5V

    4、输入支持移动和联通手机卡Micro SIM卡

    5、送51/STM32/ARDUINO驱动例程

    image-20220416115302900

    1、DC 5V-18V电源输入,推荐使用DC 9V

    2、电源开始使能引脚默认使能

    3、电源地

    4、GSM模块的TXD引脚接其它模块的RXD

    5、GSM模块的RXD引脚接其它模块的TXD

    6、数据终端准备

    7、内核音频输出引脚

    8、内核音频输出引脚

    9、锂电池输入引脚,DC 3.5 - 4.5V

    10、电源地

    11、启动引脚和GND短路可实现开机自启动

    12、电源地

    13、RTC外置电池引脚

    14、内核振铃提示引脚

    15、内合音频输入引脚

    16、内核音频输入引脚

    加粗的引脚一般都用到。

    image-20220416120423490

    建议使用V_IN单独供电DC5-18V输入(推荐使用9V),或者VBAT供电锂电池两种供电方式这两种供电方式最稳定。如果只是简单调试,也可使用USB-TTL或者开发板的5V直接给模块供电。不过一般电脑或者开发板的功率有限,可能会不稳定。请根据具体情况自己取舍选择合适电源。

    总结:

    模块本身支持自适应波特率,可以自动根据发送过去的指令计算对应的波特率,一般使用115200即可。

    模块调试总结:

    (1)供电电压5V也可以,采用电脑USB供电(直接插电脑USB口)。正常供电之后,模块上有电源指示灯。

    (2)SIM800C的TX脚接单片机的RX脚

    (3)SIM800C的RX脚接单片机的TX脚

    (4)SIM800C的第11个引脚(PWK)和12个引脚(GND)短接接在一起,才可以开机。

    image-20220416121804182

    电源正常后,右上角有一个黄色的电源灯。

    image-20220416121820844

    通过串口发送AT指令过去测试模块效果。

    image-20220416124331731

    2.4 蜂鸣器模块

    image-20220411155147501

    2.5 杜邦线(2排)

    image-20220411155244469

    2.6 PCB板(2块)

    image-20220411155550744

    3. STM32代码实现

    酒精浓度传感器的预热时间要20秒~1分钟左右,这段时间之后采集的数据才会稳定。预热模块会发热,烫手,这个是正常现象。

    完整项目源码下载地址: https://download.csdn.net/download/xiaolong1126626497/85896114

    视频演示地址:

    基于STM32设计的酒驾报警系统

    3.1 系统框图

    image-20220412152745446

    3.2 系统原理图

    image-20220412152110776

    image-20220412155048985

    3.3 keil工程布局

    image-20220412151909195

    3.4 程序下载

    通过USB进行程序下载: 下载软件在软件包目录下。

    点击开始编程之后,点击板子上的复位键即可下载程序,如果失败,重试几次即可。正常的效果如下。

    image-20220416125527488

    正常程序运行之后,打开串口调试助手看到的初始化信息如下:

    image-20220416131945457

    3.5 字体取模

    image-20220416134432091

    3.6 硬件连线

    硬件连接方式:
    1. TFT 1.44 寸彩屏接线
    GND   电源地
    VCC   接5V或3.3v电源
    SCL   接PC8(SCL)
    SDA   接PC9(SDA)
    RST   接PC10
    DC    接PB7
    CS    接PB8
    BL	  接PB11
    
    2. 蜂鸣器
    VCC--->3.3V
    DAT--->PA6
    GND--->GND
    
    3. 酒精检测传感器MQ3
    VCC--->3.3V
    GND--->GND
    DAT--->PA1
    
    4. 板载LED灯接线
    LED1---PA8
    LED2---PD2
    
    5. 板载按键接线
    K0---PA0 
    K1---PC5 
    K2---PA15
    
    6. SIM800C--GSM模块
    GND----GND
    VCC--->3.3V
    PA2----SIM800C_RXD
    PA3----SIM800C_TXD
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35

    3.7 main.c代码

    #include "stm32f10x.h"
    #include "led.h"
    #include "delay.h"
    #include "key.h"
    #include "usart.h"
    #include 
    #include "timer.h"
    #include "oled.h"
    #include "adc.h"
    #include 
    #include 
    #include "font.h"
    #include "sim800c.h"
    
    /*
    硬件连接方式:
    1. TFT 1.44 寸彩屏接线
    GND   电源地
    VCC   接5V或3.3v电源
    SCL   接PC8(SCL)
    SDA   接PC9(SDA)
    RST   接PC10
    DC    接PB7
    CS    接PB8
    BL	  接PB11
    
    2. 蜂鸣器
    VCC--->3.3V
    DAT--->PA6
    GND--->GND
    
    3. 酒精检测传感器MQ3
    VCC--->3.3V
    GND--->GND
    DAT--->PA1
    
    4. 板载LED灯接线
    LED1---PA8
    LED2---PD2
    
    5. 板载按键接线
    K0---PA0 
    K1---PC5 
    K2---PA15
    
    6. SIM800C--GSM模块
    GND----GND
    VCC--->3.3V
    PA2----SIM800C_RXD
    PA3----SIM800C_TXD
    */
    
    //JTAG模式设置,用于设置JTAG的模式
    //mode:jtag,swd模式设置;00,全使能;01,使能SWD;10,全关闭;	   
    #define JTAG_SWD_DISABLE   0X02
    #define SWD_ENABLE         0X01
    #define JTAG_SWD_ENABLE    0X00		  
    void JTAG_Set(u8 mode)
    {
    	u32 temp;
    	temp=mode;
    	temp<<=25;
    	RCC->APB2ENR|=1<<0;     //开启辅助时钟	   
    	AFIO->MAPR&=0XF8FFFFFF; //清除MAPR的[26:24]
    	AFIO->MAPR|=temp;       //设置jtag模式
    }
    
    
    u16 MQ3_data=0; //酒精浓度
    float MQ3_data_float=0; //mg/l
    
    char data_buff[100];
    //酒精超标提示
    u8 sim800c_buff[100]="Drunk driving reminder";
    
    int main()
    {
        u8 state=0;
        u8 key=0;
        u32 time_cnt=0;
        JTAG_Set(JTAG_SWD_DISABLE); //释放PA15
        LED_Init();  //LED灯初始化
        BEEP_Init(); //蜂鸣器初始化
        KEY_Init();  //按键初始化
        USART1_Init(115200); //串口1初始化-打印调试信息
        Lcd_Init();    //LCD初始化
        Lcd_Clear(0);  //清屏为黑色
        LCD_LED_SET;   //通过IO控制背光亮		
        AdcInit();     //ADC初始化--检测酒精传感器的值
        TIMER2_Init(72,20000);//辅助串口2接收,超时时间为20ms
        USART2_Init(115200); //可能的波特率(测试):  57600 、9600、115200
        
        //预热视频
        LCD_ShowChineseFont(0,16*3,16,HZ_FONT_16[20],RED,0);
        LCD_ShowChineseFont(16,16*3,16,HZ_FONT_16[21],RED,0);
        LCD_ShowChineseFont(16*2,16*3,16,HZ_FONT_16[22],RED,0);
        LCD_ShowChineseFont(16*3,16*3,16,HZ_FONT_16[23],RED,0);
        LCD_ShowChineseFont(16*4,16*3,16,HZ_FONT_16[24],RED,0);
        LCD_ShowChineseFont(16*5,16*3,16,HZ_FONT_16[25],RED,0);
        LCD_ShowChineseFont(16*6,16*3,16,HZ_FONT_16[26],RED,0);
        LCD_ShowChineseFont(16*7,16*3,16,HZ_FONT_16[27],RED,0);
        //delay_ms(30000); //初始化时间30秒
        delay_ms(5000); //初始化时间5秒
        Lcd_Clear(0);  //清屏为黑色
        
       //采集数据的真实数据
       LCD_ShowChineseFont(0,16*2,16,HZ_FONT_16[0],RED,0);
       LCD_ShowChineseFont(16,16*2,16,HZ_FONT_16[1],RED,0);
       LCD_ShowChineseFont(16*2,16*2,16,HZ_FONT_16[2],RED,0);
       LCD_ShowChineseFont(16*3,16*2,16,HZ_FONT_16[3],RED,0);
       
       //酒精含量计算结果
       LCD_ShowChineseFont(0,16*3,16,HZ_FONT_16[4],RED,0);
       LCD_ShowChineseFont(16,16*3,16,HZ_FONT_16[5],RED,0);
       LCD_ShowChineseFont(16*2,16*3,16,HZ_FONT_16[6],RED,0);
       LCD_ShowChineseFont(16*3,16*3,16,HZ_FONT_16[7],RED,0);
    
        //酒精超标显示
        Gui_DrawFont_GBK16(0,16*4,RED,0,(u8*)"        ");
        LCD_ShowChineseFont(0,16*4,16,HZ_FONT_16[16],RED,0);
        LCD_ShowChineseFont(16,16*4,16,HZ_FONT_16[17],RED,0);
        LCD_ShowChineseFont(16*2,16*4,16,HZ_FONT_16[18],RED,0);
        LCD_ShowChineseFont(16*3,16*4,16,HZ_FONT_16[19],RED,0);
    
        //初始化SIM800C
        state=SIM800C_InitCheck();
        printf("SIM800C初始化状态:%d\r\n",state);
        DelayMs(1000);
        
        //设置文本模式
        state=SIM800C_SetNoteTextMode();
        printf("设置文本模式状态:%d\r\n",state);
        DelayMs(1000);
        
        //
        
       while(1)
       {
            //按键可以手动控制开启窗帘和LED灯
            key=KEY_Scan();
            if(key)
            {
                printf("key=%d\r\n",key);
            }
           
            //控制LED灯
            if(key==2)
            {
                LED2=!LED2;
            }    
            
            //手动控制蜂鸣器测试
            //手动发送短信测试
            if(key==1)
            {
                BEEP=1;
                delay_ms(100);
                BEEP=0;
    
                sprintf((char*)sim800c_buff,"Drunk driving reminder:%d",MQ3_data);
                //发送短信
                if(SIM800C_SendNote((u8*)"18171571217",sim800c_buff,strlen((char*)sim800c_buff))==0)
                printf("短信发送成功\r\n");
                else
                printf("短信发送失败\r\n");
            }
            
            //轮询时间到达
            if(time_cnt>300)
            {
                time_cnt=0;
                LED1=!LED1;
                //获取空气质量
                MQ3_data=GetAdcCHxDATA(1);
                printf("采集MQ3数据:%d\r\n",MQ3_data);
              
                //LCD屏实时显示酒精浓度     
                //采集数据
                sprintf(data_buff,"%d",MQ3_data);
                Gui_DrawFont_GBK16(72,16*2,RED,0,(u8*)"       ");
                Gui_DrawFont_GBK16(72,16*2,RED,0,(u8*)data_buff);
                
                //酒精含量
                //MQ3_data_float=((float)MQ3_data*(5.0/4096))*0.36-1.08;
                MQ3_data_float=((float)MQ3_data*(5.0/4096))*0.36;
                sprintf(data_buff,"%0.2f mg/L",MQ3_data_float);
                printf("计算酒精浓度:%s\r\n",data_buff);
                Gui_DrawFont_GBK16(72,16*3,RED,0,(u8*)"        ");
                Gui_DrawFont_GBK16(72,16*3,RED,0,(u8*)data_buff);  
                
                 //判断酒精浓度是否超标,设置阀值
                if(MQ3_data>2000)
                {
                    sprintf((char*)sim800c_buff," :%d",MQ3_data);
                    //发送短信
                    if(SIM800C_SendNote((u8*)"18171571217",sim800c_buff,strlen((char*)sim800c_buff))==0)
                    printf("短信发送成功\r\n");
                    else
                    printf("短信发送失败\r\n");
                }
                
                //采集的值越小,表明酒精浓度越高。反之越大。
                //根据阀值显示不同的文字提示
                if(MQ3_data>2000)
                {
                     //你已酒驾
                    Gui_DrawFont_GBK16(0,16*4,RED,0,(u8*)"        ");
                    LCD_ShowChineseFont(0,16*4,16,HZ_FONT_16[8],RED,0);
                    LCD_ShowChineseFont(16,16*4,16,HZ_FONT_16[9],RED,0);
                    LCD_ShowChineseFont(16*2,16*4,16,HZ_FONT_16[10],RED,0);
                    LCD_ShowChineseFont(16*3,16*4,16,HZ_FONT_16[11],RED,0);
                }
                //正常稳定范围采集的值是500左右
                else
                {
                    //安全范围
                    Gui_DrawFont_GBK16(0,16*4,RED,0,(u8*)"        ");
                    LCD_ShowChineseFont(0,16*4,16,HZ_FONT_16[16],RED,0);
                    LCD_ShowChineseFont(16,16*4,16,HZ_FONT_16[17],RED,0);
                    LCD_ShowChineseFont(16*2,16*4,16,HZ_FONT_16[18],RED,0);
                    LCD_ShowChineseFont(16*3,16*4,16,HZ_FONT_16[19],RED,0);
                }
            }
            
            DelayMs(10);
            time_cnt++;
    	 }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136
    • 137
    • 138
    • 139
    • 140
    • 141
    • 142
    • 143
    • 144
    • 145
    • 146
    • 147
    • 148
    • 149
    • 150
    • 151
    • 152
    • 153
    • 154
    • 155
    • 156
    • 157
    • 158
    • 159
    • 160
    • 161
    • 162
    • 163
    • 164
    • 165
    • 166
    • 167
    • 168
    • 169
    • 170
    • 171
    • 172
    • 173
    • 174
    • 175
    • 176
    • 177
    • 178
    • 179
    • 180
    • 181
    • 182
    • 183
    • 184
    • 185
    • 186
    • 187
    • 188
    • 189
    • 190
    • 191
    • 192
    • 193
    • 194
    • 195
    • 196
    • 197
    • 198
    • 199
    • 200
    • 201
    • 202
    • 203
    • 204
    • 205
    • 206
    • 207
    • 208
    • 209
    • 210
    • 211
    • 212
    • 213
    • 214
    • 215
    • 216
    • 217
    • 218
    • 219
    • 220
    • 221
    • 222
    • 223
    • 224
    • 225
    • 226
    • 227
    • 228
  • 相关阅读:
    线性表章节课后习题答案集锦
    解决react使用redux toolkits时出现的数组对象长度始终为0的怪异问题
    复杂SQL收集
    GitHub每日最火火火项目(9.16)
    【kafka】springboot工程能发消息,不能收消息
    python-数据描述与分析(1)
    Mysql出现问题:慢查询日志失效解决方案
    Python学习笔记 - 异常处理
    python pyqt5 计算下载文件的进度百分比
    并发中级(第二篇)
  • 原文地址:https://blog.csdn.net/xiaolong1126626497/article/details/126049281