一、光电开关
左侧有一个光敏三极管,当无遮挡物时,有光,三极管导通,电压减小,即电压比较器正输入减小,正输入电压小于负输入电压时,输出低电平,LD5的电路导通,LD5亮。
当有遮挡物时,无光,三极管截止,电压增大,电压比较器正输入电压大于负输入电压时,输出高电平,LD5电路截止,LD5灯灭。
注意:需要调节滑动变阻器R55,使负输入的电压值大于0.6且小于3.3,这样才能在有无遮挡物时输出不同的电平。
光电开关 --> PE15 --> EXTI15 --> 输入事件编号15 --> 选择上升沿检测 --> 中断号:159
二、火焰传感器
火焰传感器的原理是利用火焰产生的红外线对它非常敏感的特点,
当火焰亮度变大时,发出的红外线越多,火焰传感器管脚间的阻抗变小,
当火焰亮度变小时,发出的红外线越少,火焰传感器管脚间的阻抗变大。
当有火焰时,火焰传感器阻抗变小,分压变小(负输入那一点的电压与火焰传感器是并联,电压相等,因此火焰传感器分压变小,负输入的电压就减小),电压比较器负输入电压减小,正输入电压大于负输入电压,输出高电平,LD6熄灭
当没有火焰时,火焰传感器阻抗变大,分压变大,,电压比较器的负输入增大,正输入小于负输入电压,输出低电平,LD6亮
注:当没有火焰时,需要调节滑动变阻器R67, 让LD6指示灯亮。
火焰传感器 --> PF5 --> EXTI5 --> 输入事件编号5 --> 选择上升沿检测 --> 中断号:55
三、人体红外传感器
如图可知,需要找网络标号RELOUT的引脚。
人体红外传感器 --> PF12 --> EXTI12 --> 输入事件编号12 --> 选择上升沿检测 --> 中断号:108
四、代码实现
sentor.c
#include "../include/sentor.h"
//光电开关 PE15
void sentor_light_gpio_init(){
RCC_AHB4->gpioe_en=1;
gpio_init_t gpioInit;
gpioInit.mode = GPIO_MODE_INPUT;
gpioInit.pupd = GPIO_PUPD_NONE;
gpioInit.type = GPIO_TYPE_OUTPUT_PP;
gpio_init(GPIOE,GPIO_PIN_15,&gpioInit);
}
//火焰传感器 PF5
void sentor_fire_gpio_init(){
RCC_AHB4->gpiof_en=1;
gpio_init_t gpioInit;
gpioInit.mode = GPIO_MODE_INPUT;
gpioInit.pupd = GPIO_PUPD_NONE;
gpioInit.type = GPIO_TYPE_OUTPUT_PP;
gpio_init(GPIOF,GPIO_PIN_5,&gpioInit);
}
//红外传感器 PF12
void sentor_red_gpio_init(){
RCC_AHB4->gpiof_en=1;
gpio_init_t gpioInit;
gpioInit.mode = GPIO_MODE_INPUT;
gpioInit.pupd = GPIO_PUPD_NONE;
gpioInit.type = GPIO_TYPE_OUTPUT_PP;
gpio_init(GPIOF,GPIO_PIN_12,&gpioInit);
}
gic.c
void gic_sentor_init(void){
/***EXTI****/
//GPIO引脚与EXTI关联
EXTI->EXTICR4.GPIO3_7_11_15=PE; //将EXTI7和PF7关联
EXTI->EXTICR2.GPIO1_5_9_13=PF;
EXTI->EXTICR4.GPIO0_4_8_12=PF;
//配置上升沿触发
EXTI->RTSR1.event15=1;
EXTI->RTSR1.event5=1;
EXTI->RTSR1.event12=1;
//使能EXTI
EXTI->C1IMR1.event15=1;
EXTI->C1IMR1.event5=1;
EXTI->C1IMR1.event12=1;
//使能GICD中断号
GICD->ISENABLER[4] |= (0x1<<31); //使能GICD中断号 159/32=4...31
GICD->ISENABLER[1] |= (0x1<<23); //55/32=1...23
GICD->ISENABLER[3] |= (0x1<<12); //108/32=3...12
//设置优先级
GICD->IPRIORITYR[39] &= ~(0xf<<27);
GICD->IPRIORITYR[39] |= (0x5<<27); //设置优先级 159/4=39...3
GICD->IPRIORITYR[13] &= ~(0xf<<27);
GICD->IPRIORITYR[13] |= (0x5<<27); //设置优先级 55/4=13...3
GICD->IPRIORITYR[27] &= ~(0xf<<3);
GICD->IPRIORITYR[27] |= (0x5<<3); //设置优先级 108/4=27...0
//分配CPU
GICD->ITARGETSR[39] &= ~(0x3<<24);
GICD->ITARGETSR[39] |= (0x1<<24); //设置中断给CPU0 159/4=39...3
GICD->ITARGETSR[13] &= ~(0x3<<24);
GICD->ITARGETSR[13] |= (0x1<<24);
GICD->ITARGETSR[27] &= ~(0x3<<0);
GICD->ITARGETSR[27] |= (0x1<<0);
GICD->CTRL |= (0x1<<0); //使能GICD组0
//配置GICC
GICC->PMR |= 0x1f<<3; //31
GICC->CTLR|= 0x1<<0; //使能GICC
}
do_irq.c
void do_irq(void)
{
int irqnum=0;
irqnum = GICC->IAR & 0x1ff;
switch(irqnum){
case 159:
printf("sentor light!\n");
EXTI->RPR1.event15=1;
GICD->ICPENDR[4] |= (0x1<<31); //159/32=4...31
break;
case 55:
printf("sentor fire~\n");
EXTI->RPR1.event5=1;
GICD->ICPENDR[1] |= (0x1<<23); //55/32=1...23
break;
case 108:
printf("sentor human red!\n");
EXTI->RPR1.event12=1;
GICD->ICPENDR[3] |= (0x1<<12); //108/32=3...12
break;
}
GICC->EOIR = irqnum;
}