最近學習了一下STM32中的ADC采樣,由於手頭正好有一個MQ-2的煙霧傳感器,所以正好可以測試一把。體驗ADC采樣的過程。下面介紹一下這個MQ-2煙霧傳感器。
1.MQ-2煙霧傳感器簡介
MQ-2氣體傳感器所使用的氣敏材料是在清潔空氣中電導率較低的二氧化錫(SnO2)。當傳感器所處環境中存在可燃氣體時,傳感器的電導率隨空氣中可燃氣體濃度的增加而增大。使用簡單的電路即可將電導率的變化轉換為與該氣體濃度相對應的輸出信號。 MQ-2氣體傳感器對液化氣、丙烷、氫氣的靈敏度高,對天然氣和其它可燃蒸汽的檢測也很理想。這種傳感器可檢測多種可燃性氣體,是一款適合多種應用的低成本傳感器。
2.傳感器模塊圖


3.MQ-2傳感器原理圖

4.傳感器規格

查找MQ-2傳感器資料后,可知MQ-2傳感器的加熱電壓為5.0v,當然經測試加熱電壓小於5v也是可以的,比如我在測試的時候,我給單片機的電壓就是小於5V的,我的單片機沒有接電源,直接是J-link接入PC然后pc進行供電,但最好還是單片機接上電源線,這樣傳感器比較靈敏。
5.MQ-2煙霧傳感器模塊特點
1、具有信號輸出指示。
2、雙路信號輸出(模擬量輸出及TTL電平輸出)。
3、TTL輸出有效信號為低電平。(當輸出低電平時信號燈亮,可直接接單片機)
4、模擬量輸出0~5V電壓,濃度越高電壓越高。
5、對液化氣,天然氣,城市煤氣有較好的靈敏度。
6、結果受溫濕度影響。
6.硬件連線
MQ-2傳感器的VCC端用杜邦線接入32開發板的JP2(我的開發板上的JP2可輸入5V電壓),MQ-2傳感器的GND端接32開發板的GND,32開發板上所有的GND可共用,這里最好接攝像頭的GND,MQ-2傳感器的AOUT端接開發板的攝像頭(CAMERA)的PC1-ADC1端。
至於連線為什么這么連,與我寫的代碼以及我的開發板的原理圖有關,如圖:


注意:MQ-2模塊的TTL輸出端是懸空的,至於為啥是懸空的,這是廠家提供的,可以參考這個鏈接:點擊打開鏈接

代碼如下:
主函數:main.c
-
-
-
-
extern __IO uint16_t ADC_ConvertedValue;
-
float ADC_ConvertedValueLocal;
-
int main(void)
-
{
-
adc_init();
-
printf_init();
-
SysTick_Init(); //配置SysTick為1ms中斷一次
-
while(1)
-
{
-
ADC_ConvertedValueLocal =( float) ADC_ConvertedValue/4096*3.3;
-
printf("The current AD value =0x%04X\n",ADC_ConvertedValue);
-
printf("The current AD value =%f V\n",ADC_ConvertedValueLocal);
-
-
Delay_ms( 1000);
-
}
-
-
}
ADC初始化代碼:
-
void adc_init()
-
{
-
GPIO_InitTypeDef GPIO_InitStructure;
-
ADC_InitTypeDef ADC_InitStructure;
-
DMA_InitTypeDef DMA_InitStructure;
-
-
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1,ENABLE);
-
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC|RCC_APB2Periph_ADC1,ENABLE);
-
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_1;
-
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AIN;
-
GPIO_Init(GPIOC,&GPIO_InitStructure);
-
-
DMA_DeInit(DMA1_Channel1);
-
DMA_InitStructure.DMA_PeripheralBaseAddr = ADC1_DR_Address; //ADC地址
-
DMA_InitStructure.DMA_MemoryBaseAddr = ( uint32_t)&ADC_ConvertedValue; //內存地址(要傳輸的變量的指針)
-
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC; //方向(從內存到外設)
-
DMA_InitStructure.DMA_BufferSize = 1; //傳輸內容的大小
-
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; //外設地址固定
-
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Disable; //內存地址固定
-
DMA_InitStructure.DMA_PeripheralDataSize =
-
DMA_PeripheralDataSize_HalfWord ; //外設數據單位
-
DMA_InitStructure.DMA_MemoryDataSize =
-
DMA_MemoryDataSize_HalfWord ; //內存數據單位
-
DMA_InitStructure.DMA_Mode = DMA_Mode_Circular ; //DMA模式:循環傳輸
-
DMA_InitStructure.DMA_Priority = DMA_Priority_High ; //優先級:高
-
DMA_InitStructure.DMA_M2M = DMA_M2M_Disable; //禁止內存到內存的傳輸
-
-
DMA_Init(DMA1_Channel1, &DMA_InitStructure); //配置DMA1的1通道
-
-
DMA_Cmd(DMA1_Channel1,ENABLE);
-
-
ADC_InitStructure.ADC_Mode = ADC_Mode_Independent; //獨立ADC模式
-
ADC_InitStructure.ADC_ScanConvMode = DISABLE; //禁止掃描方式
-
ADC_InitStructure.ADC_ContinuousConvMode = ENABLE; //開啟連續轉換模式
-
ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None; //不使用外部觸發轉換
-
ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right; //采集數據右對齊
-
ADC_InitStructure.ADC_NbrOfChannel = 1; //要轉換的通道數目
-
ADC_Init(ADC1, &ADC_InitStructure);
-
-
RCC_ADCCLKConfig(RCC_PCLK2_Div8); //配置ADC時鍾,為PCLK2的8分頻,即9Hz
-
ADC_RegularChannelConfig(ADC1, ADC_Channel_11, 1, ADC_SampleTime_55Cycles5);//配置ADC1通道11為55.5個采樣周期
-
ADC_DMACmd(ADC1,ENABLE);
-
ADC_Cmd(ADC1,ENABLE);
-
-
ADC_ResetCalibration(ADC1); //復位校准寄存器
-
while(ADC_GetResetCalibrationStatus(ADC1));//等待校准寄存器復位完成
-
-
ADC_StartCalibration(ADC1); //ADC校准
-
while(ADC_GetCalibrationStatus(ADC1));//等待校准完成
-
-
ADC_SoftwareStartConvCmd(ADC1, ENABLE); //由於沒有采用外部觸發,所以使用軟件觸發ADC轉換
-
}
adc.h:
-
-
-
-
-
-
-
void adc_init(void);
-
-
延時函數在我這篇博客:點擊打開鏈接
其實這里最好用用定時器來代替延時的,用定時器的話,不會占用CPU,這樣會大大降低功耗,相反用延時的話會一直占用CPU,功耗增加可想而知,不過由於自己學習32也沒有多久,對定時器的操作還不太熟,以后等自己熟悉了定時器的操作之后再來修改代碼。
硬件連線圖:

測試圖:

其實在實際的應用中,會把ADC的轉換值利用公式換算成為煙霧的濃度值,通過這個濃度值與預設值進行比對然后進行報警。不過為了使ADC的采樣值更加精確,通常會取多個ADC采樣值然后后求平均值,最后將平均值換算成為對應的煙霧濃度值。由於自己只是為了學習這個模塊及了解一下ADC采樣的過程,代碼比較簡單,寫的很新手,有時間我再來優化一下這個代碼。
