這次用的是STM32F103的開發板(這里面的exti.c文件沒有how to use this driver 配置說明)
對射式紅外傳感器
由一個紅外發光二極管和NPN光電三極管組成,M3固定安裝孔,有輸出狀態指示燈,輸出高電平燈滅,輸出低電平燈亮。有遮擋,輸出高電平。無遮擋,輸出低電平。使用3.3-5VDC 寬電壓LM393比較器輸出,信號干凈,波形好,驅動能力強,超過15mA。輸出形式:數字開關量輸出(0和1)。廣泛用于電機轉速檢測,脈沖計數,位置限位等。
引腳:
VCC:接電源正極3.3V-5V
GND:接電源負極
DO:TTL開關信號輸出
AO:此模塊不起作用
操作說明:
1、接好VCC和GND,模塊電源指示燈會亮
2、模塊槽中無遮擋時,接收管導通,模塊DO輸出低電平,開關指示燈亮;遮擋時,DO輸出高電平,開關指示燈滅。
3、模塊DO可與繼電器相連,組成限位開關等功能,也可以與有源蜂鳴器模塊相連,組成報警器。
4、DO輸出接口可以與單片機10口直接相連,一般接外部中斷,檢測傳感器是否有遮檔,如用電機碼盤則可檢測電機的轉速。
原理:
測距離: 測速傳感器輸出為脈沖信號,一個脈沖中斷一次;紅外射線導通的時候是低電平,所以我們設置中斷為低電平觸法模式。一般碼盤上有整數格子,無論是多少格其實原理一樣,例如10格碼盤,也就是有10個空格子,電機轉一圈后便是射線導通10次,外部低電平觸法10次;安裝上面的思路,我們的測速傳感器就可以發揮出效果了,我們知道一圈就有10個中斷,于是我們計算中斷次數,得到的總次數除于10也就是電機轉動次數了,然后按照輪子的周長,計算輪子一圈是多長,就可以推算出小車已經跑多遠了。
測速度: 按照測距離的思路,我們用一個MCU定時器計算,1秒內接收多少個外部中斷,例如一秒內接收了20個外部中斷,我們就可以判斷小車速度為1秒小車輪子轉兩圈,然后再計算出小車輪子的周長,就可得知小車1秒行駛的速度。
接線圖:
代碼配置:
分為GPIO配置、中斷線與GPIO引腳的連接、EXTI配置、NVIC配置(與上一章的按鍵中斷一樣)
EXTI函數解析:
//調用它,就可以把EXTI的配置都清除,恢復成上電的默認的狀態
void EXTI_DeInit(void);//調用這個函數,就可以根據這個結構體里的參數配置EXTI外設,初始化EXTI要用到這個函數
void EXTI_Init(EXTI_InitTypeDef* EXTI_InitStruct);//調用這個函數,可以把參數傳遞的結構體變量賦一個默認值
void EXTI_StructInit(EXTI_InitTypeDef* EXTI_InitStruct);//這個函數是用來軟件觸發外部中斷的,調用這個函數,參數給一個指定的中斷線,就能軟件觸發一次外部中斷
void EXTI_GenerateSWInterrupt(uint32_t EXTI_Line);
在外設運行的過程中,會產生一些狀態標志位 ? 比如外部中斷來了,會有一個掛起的寄存器置了一個標志位,對于其他外設,如串口收到數據,會置標志位,定時器時間到也會置標志位,這些標志位都是放在狀態寄存器的,當程序想要看這些標志位時,就會用到這四個函數
FlagStatus EXTI_GetFlagStatus(uint32_t EXTI_Line);//可以獲取指定的標志位是否被置1void EXTI_ClearFlag(uint32_t EXTI_Line);//可以對置1的標志位進行清除//在中斷函數里,如果你想查看標志位和清除標志位,用下面兩個函數
ITStatus EXTI_GetITStatus(uint32_t EXTI_Line);//獲取中斷標志位是否被置1void EXTI_ClearITPendingBit(uint32_t EXTI_Line);//清除中斷掛起標志位
總結:如果想要在主程序里查看和清除標志位,就用上面兩個函數。
???????????如果想要在中斷函數里查看和清除標志位,就用下面兩個函數。
NVIC函數解析:
//這個函數是用來中斷分組的,參數是中斷分組的方式
void NVIC_PriorityGroupConfig(uint32_t NVIC_PriorityGroup);//根據結構體里面指定的參數初始化NVIC
void NVIC_Init(NVIC_InitTypeDef* NVIC_InitStruct);//設置中斷向量表
void NVIC_SetVectorTable(uint32_t NVIC_VectTab, uint32_t Offset);//系統低功耗配置
void NVIC_SystemLPConfig(uint8_t LowPowerMode, FunctionalState NewState);
代碼:
void CountSensor_Init(void)
{//------------------------定義結構體變量-----------------------------------GPIO_InitTypeDef GPIO_InitStructure; //定義GPIO結構體變量EXTI_InitTypeDef EXTI_InitStructure; //定義EXTI結構體變量NVIC_InitTypeDef NVIC_InitStructure; //定義NVIC結構體變量RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);//開啟GPIO的時鐘RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE); //開啟AFIO的時鐘//---------------------GPIO配置--------------------------------------GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; //模式選擇上拉輸入GPIO_InitStructure.GPIO_Pin = GPIO_Pin_14; //配置引腳GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //速率GPIO_Init(GPIOB,&GPIO_InitStructure); //GPIO初始化//---------------------GPIO配置--------------------------------------GPIO_EXTILineConfig(GPIO_PortSourceGPIOB,GPIO_PinSource14);//將中斷線與GPIO引腳連接//---------------------EXTI配置--------------------------------------EXTI_InitStructure.EXTI_Line = EXTI_Line14; //配置中斷線EXTI_InitStructure.EXTI_LineCmd = ENABLE; //中斷使能EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt; //選擇中斷模式EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling; //下降沿觸發EXTI_Init(&EXTI_InitStructure);//---------------------EXTI配置--------------------------------------NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//中斷分組,這里放到模塊函數里了,一般情況放在主函數第一行(如上一章按鍵中斷)//---------------------NVIC配置--------------------------------------NVIC_InitStructure.NVIC_IRQChannel = EXTI15_10_IRQn; //選擇中斷通道NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //使能中斷通道NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; //搶占優先級配置NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; //響應優先級配置NVIC_Init(&NVIC_InitStructure);//---------------------NVIC配置--------------------------------------}
中斷函數:
uint16_t CountSensor_Count;
//中斷函數
void EXTI15_10_IRQHandler(void)
{//判斷中斷標志位是否為 1 EXTI_GetITStatus的返回值為 SET(1) 或者RESET(0)if(EXTI_GetITStatus(EXTI_Line14) == SET){//判斷電平,以免發生抖動if(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_14) == 0){CountSensor_Count++;}//中斷標志位置1,程序就會跳轉到中斷函數,//如果不清除中斷標志位,就會一直申請中斷,這樣就會不斷響應中斷,執行中斷函數,//程序就會卡死在中斷函數里,所以每次中斷程序結束后,都應該清除一下中斷標志位EXTI_ClearITPendingBit(EXTI_Line14);}}//返回值
uint16_t CountSensor_Get(void)
{return CountSensor_Count;
}
主函數:
功能:擋住傳感器模塊槽,OLDE顯示數字變化+1
#include "CountSensor.h"
int main(void)
{LED_Init();OLED_Init();CountSensor_Init();OLED_ShowString(1, 1, "Count:");while(1){OLED_ShowNum(1, 7, CountSensor_Get(),5);} }