STM32單片機酒精檢測防酒駕系統(tǒng)酒精報警器(程序+原理圖+PCB+視頻講解)
程序編譯器:keil 5
編程語言:C語言
設(shè)計編號:C0062
功能描述
本系統(tǒng)由STM32F103C8T6單片機核心板、酒精傳感器、LCD1602液晶顯示、蜂鳴器報警、按鍵控制及電源組成。
1、通過傳感器檢測傳感器實際值,并將傳感器實際值顯示在LCD1602液晶上;
2、感器檢測采用的是AD數(shù)據(jù)轉(zhuǎn)換,然后經(jīng)過運算獲得的;
3、三個按鍵設(shè)置閾值,分別為設(shè)置鍵、設(shè)置+、設(shè)置-,其中設(shè)置+、設(shè)置-只有在設(shè)置模式下才能進(jìn)行操作;
4、在設(shè)置模式下,液晶有對應(yīng)的顯示標(biāo)志,設(shè)置閾值存儲到單片機Flash中,具有掉電不丟失,無需重新設(shè)置;
5、設(shè)置值與采集值實時對比,如果出現(xiàn)異常情況,蜂鳴器報警提醒。
原理圖
STM32系列處理器是意法半導(dǎo)體ST公司生產(chǎn)的一種基于ARM 7架構(gòu)的32位、支持實時仿真和跟蹤的微控制器。選擇此款控制芯片是因為本系統(tǒng)設(shè)計并非追求成本的最低或更小的功耗,而是在實現(xiàn)本設(shè)計功能的前提下能夠提供更豐富的接口和功能以便于設(shè)計實驗系統(tǒng)各實驗項目所需的外圍擴展電路。此款控制芯片在完成單片機課程的學(xué)習(xí)后上手較為容易,在醫(yī)療器械中應(yīng)用廣泛,具有很好的學(xué)習(xí)、實驗研究價值。
一、STM32的主要優(yōu)點:
(1)使用ARM最新的、先進(jìn)架構(gòu)的Cortex-M3內(nèi)核
(2) 優(yōu)異的實時性能
(3) 杰出的功耗控制
(4) 出眾及創(chuàng)新的外設(shè)
(5) 最大程度的集成整合
(6) 易于開發(fā),可使產(chǎn)品快速將進(jìn)入市場
二、STM32——最佳的平臺選項
對于使用同一平臺進(jìn)行多個項目開發(fā)而言,STM32是最
佳的選擇:
(1) 從僅需少量的存儲空間和管腳應(yīng)用到需要更多的存儲空間和管腳的應(yīng)用
(2) 從苛求性能的應(yīng)用到電池供電的應(yīng)用
(3) 從簡單而成本敏感的應(yīng)用到高端應(yīng)用
(4) 全系列腳對腳、外設(shè)及軟件的高度兼容性,給您帶來全方位的靈活性。您可以在不必修改您原始框架及軟件的條件下,將您的應(yīng)用升級到需要更多存儲空間或精簡到使用更少存儲空間/ 或改用不同的封裝的規(guī)格。
PCB
程序
main函數(shù)
#include "led.h"
#include "delay.h"
#include "sys.h"
#include "usart.h"
#include <stdio.h>
#include "timer.h"
#include "key.h"
#include <stdio.h>
#include "lcd1602.h"
#include "adc.h"
#include "stmflash.h"
//#define BASICS_VAL 36 //用于數(shù)據(jù)轉(zhuǎn)換的基礎(chǔ)值
#define DEFAULT_SET_VAL 100 //第一次下載默認(rèn)設(shè)置值
char dis0[17]; //暫存數(shù)組
char dis1[17]; //暫存數(shù)組
unsigned int sensorVal = 0; //當(dāng)前采集值
unsigned int adcx;
long midData = 0;//中間變量
unsigned int setNum = DEFAULT_SET_VAL; //設(shè)置值
unsigned char setMode = 0;//默認(rèn)手動模式
unsigned char disFlag = 0;//顯示標(biāo)志
#define FLASH_SAVE_ADDR 0X08010000 // 注意不同芯片 扇區(qū)flash地址不一樣 設(shè)置FLASH 保存地址(必須為偶數(shù),且其值要大于本代碼所占用FLASH的大小+0X08000000)
//stm32f103R8T6 flash地址范圍 0x8010000-0x801FFFF
//stm32f103C8T6 flash地址范圍 0x8000000-0x807FFFF
#define SIZE 10 //數(shù)組長度
unsigned char setFlashBuf[10];//存儲數(shù)據(jù)'
unsigned char initFlagData; //初始化數(shù)據(jù)存讀取
/******************把數(shù)據(jù)保存到單片機內(nèi)部eepom中******************/
void write_FlashBuf(void)
{
setFlashBuf[0] = initFlagData;
setFlashBuf[1] = setNum / 256; //重新寫入值
setFlashBuf[2] = setNum % 256;
STMFLASH_Write(FLASH_SAVE_ADDR,(u16*)setFlashBuf,SIZE); //讀取數(shù)據(jù)
}
/******************把數(shù)據(jù)從單片機內(nèi)部eepom中讀出來*****************/
void read_FlashBuf(void)
{
STMFLASH_Read(FLASH_SAVE_ADDR,(u16*)setFlashBuf,SIZE); //讀取flash值
initFlagData = setFlashBuf[0]; //數(shù)據(jù)初始化讀取
setNum = setFlashBuf[1]; //讀取高字節(jié)
setNum <<= 8;
setNum |= setFlashBuf[2]; //讀取低字節(jié) 并合并
}
/**************開機初始化保存的數(shù)據(jù)*****************/
void init_FlashBuf(void)
{
read_FlashBuf(); //讀取flash值
if(initFlagData != 0x55) //新的單片機初始單片機內(nèi)問eeprom 如果不是0x55重新寫入
{
setNum = DEFAULT_SET_VAL;//設(shè)置上限
initFlagData = 0x55; //修改值
delay_ms(20);
write_FlashBuf(); //讀取數(shù)據(jù)
}
}
void CheckKey(void);
int main(void)
{
delay_init(); //延時函數(shù)初始化
uart_init(9600); //串口初始化為115200
TIM3_Int_Init(499,7199); //定時器初始化
LED_Init(); //初始化接口
KEY_Init();
Adc_Init(); //初始化ad轉(zhuǎn)換
init_FlashBuf();//初始化讀取存儲數(shù)據(jù)
buzzer = 1; //蜂鳴器報警一下
delay_ms(200);
buzzer = 0;//蜂鳴器 停止報警
Lcd_GPIO_init(); //液晶接口初始化
Lcd_Init(); //液晶配置初始化
delay_ms(20);
while(1)
{
CheckKey(); //按鍵處理
if(disFlag==1)//定時讀取標(biāo)志
{
disFlag=0;//清空標(biāo)志
adcx=Get_Adc_Average(ADC_Channel_0,5);//讀取ad轉(zhuǎn)換值 5次求平均
midData = adcx * 450 * 2 / 4096; //讀取的ad值轉(zhuǎn)換
midData = midData - 250; //首先減去零點漂移,一般是1V
if(midData < 0)
midData = 0;
sensorVal = midData * 2; //將mV轉(zhuǎn)變成mg/L,系數(shù)需要校準(zhǔn)
//電壓每升高0.1V,實際被測氣體的濃度增加20ppm
//1ppm=1mg/kg=1mg/L=1×10-6 常用來表示氣體濃度,或者溶液濃度。
//以上根據(jù)手冊來的
sprintf(dis0,"nowValue:%03dmg/L",sensorVal); //打印
Lcd_Puts(0,0,(u8 *)dis0);//顯示
if(setMode){
sprintf(dis1,"setValue:%03d< ",setNum); //打印
}
else{
sprintf(dis1,"setValue:%03d ",setNum);
}
Lcd_Puts(0,1,dis1);//顯示
if(sensorVal > setNum) //采集值 和 設(shè)置值 對比
{buzzer = !buzzer;} //蜂鳴器報警
else {buzzer = 0;} //不報警
}
}
}
void CheckKey(void)
{
static unsigned char rekey =0;
if((key1==0)||(key2==0)||(key3==0)) //檢測到按鍵按下
{
delay_ms(10); //小抖動
if(rekey==0)
{
if(key1==0) //檢測是否按下
{
rekey=1;
if(setMode){
setMode = 0; //取消設(shè)置
}
else {
setMode = 1; //設(shè)置狀態(tài)
}
}
else if(key2==0)//設(shè)置值鍵
{
rekey=1;
if(setMode){ //設(shè)置條件下
if(setNum < 999 ){setNum=setNum+1;} //+1
}
}
else if(key3==0)//設(shè)置值鍵
{
rekey=1;
if(setMode){ //設(shè)置條件下
if(setNum > 0 ){setNum=setNum-1;}
}
}
write_FlashBuf();//存儲數(shù)據(jù)
}
}
else
{
rekey=0; //防止重復(fù)檢測到按鍵
}
}