找到环境光与声音传感器对应的管教,使能,再在时钟树中设置频率为12Mhz,一般不要太高
在adc.c 中可以添加如下代码:
enum { ADCCHN_NOISY, ADCCHN_LUX, ADCCHN_MAX, }; int adc_sample_lux_noisy(uint32_t *lux,uint32_t *noisy) { uint8_t i; uint32_t timeout = 0xffffff; for(i = 0;i<ADCCHN_MAX;i++) { HAL_ADC_Start(&hadc1); HAL_ADC_PollForConversion(&hadc1,timeout); if(ADCCHN_NOISY == i) { *noisy = HAL_ADC_GetValue(&hadc1); } else if(ADCCHN_LUX == i) { *lux = HAL_ADC_GetValue(&hadc1); } HAL_Delay(10); } HAL_ADC_Stop(&hadc1); return 0; }
在adc.h中声明函数后,可以在main函数中调用,用串口调试助手测试结果:
基于此,我们可以实现简单的声光控灯了。
----------------------------------------------------------------------------------------------------------------
继电器介绍:
以下是用开发板上的rgb灯,根据环境光和声音情况模拟继电器开关控制灯的代码:
if( OFF == light_status) { adc_sample_lux_noisy(&lux,&noisy); printf("lux: %ld,noisy: %ld\n",lux,noisy); if(lux <30 && noisy >800) { printf("turn light on\r\n"); turn_relay(ON); turn_led(RedLed,ON); light_status = ON; start = HAL_GetTick(); } } else { if(time_after(HAL_GetTick(),start+15000)) { printf("Turn Light off\r\n"); turn_relay(OFF); turn_led(RedLed,OFF); HAL_Delay(200); light_status = OFF; } } HAL_Delay(300);
代码中,我们通过ADC采样当前的光强和噪音值,如果光线较弱并且声音比较大的话就控制继电器开灯。为了符合实际情况,做了一个时间的控制,15s后将自动关灯。
延时15s 的控制逻辑实现里,我们并没有直接用HAL_Delay(1500),而是在点灯的时候记录当前时间,然后循环获取当前时间看有没有超时,如果超时则”控制继电器关灯”。(这样可以在每次循环间隙做一些其他的操作)
在判断时间是否到没有,我们不能直接if((HAL_GetTick() - start) - 15000)这个条件判断,因为变量的最大记值是有限制的(uint32_t最大计数到2^32-1),而时间是无限的,这样会存在时间回绕的问题。
(参考Linux内核里的jiffies回绕解决方案,使用了time_after()这个宏来判断是否超时。这个宏需要添加到main.h头文件中。)
#define time_after(a,b) ((int32_t)(b) - (int32_t)(a) <0) #define time_before(a,b) time_after(b,a) #define time_after_eq(a,b) ((int32_t(a) - (int32_t)(b) >=0)) #define time_before_eq(a,b) time_after_eq(b,a)
标签:HAL,lux,继电器,STM32,turn,ADC,time,光控,noisy From: https://www.cnblogs.com/genm/p/17517791.html