文章目录
- 1- ADC(Analog-to-Digital Converter)
- 2- 原理图分析
- 3- 配置使能ADC
- 4- 添加代码
- 5- 烧录连接测试
- 6- 蜂鸣器原理图
- 7- 配置蜂鸣器
- 8- 添加代码
1- ADC(Analog-to-Digital Converter)
什么是ADC:
单片机中的ADC是Analog(模拟量)-to-Digital(数字量) Converter(转换器)的缩写,指模/数转换器或者模数转换器。真实世界的模拟信号,例如温度、压力、声音或者图像等,需要转换成更容易储存、处理和发射的数字形式,模/数转换器可以实现这个功能。
ADC就是数模转换,将模拟量转换为数字量
2- 原理图分析
我们可以看见开发板上的声音传感器和光强传感器,他们工作的原理都是ADC采样。
原理图我们可以看见,声音传感器连接在了CPU的PA6管脚上,环境光强传感器连接在了CPU的PA4管脚上。
从原理图和CPU的管脚我们看到,环境光强传感器使用的是ADC_IN9(第一个ADC采样的第9个通道上),声音传感器使用的是ADC_IN11。后面我们配置的时候也是需要注意的。
3- 配置使能ADC
配置ADC1,使能通道IN9 和IN11,选择Single-ended (Differential为差分信号)。这时候PA4 和PA6两个管脚就设置为ADC输入模式了,另外我们也可以鼠标右键点在这两个管脚上,对这两个管脚重命名,分别为AdcLux和AdcMix。
我们将ADC的时钟设置为12MHZ。
按住Ctrl+s生成代码。
4- 添加代码
修改adc.c文件,添加环境光强传感器和的声音传感器实现。
/* USER CODE BEGIN 1 */
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;
}
/* USER CODE END 1 */
adc.h中添加ADC采样的函数声明。
/* USER CODE BEGIN Includes */
extern int adc_sample_lux_noisy(uint32_t *lux, uint32_t *noisy);
/* USER CODE END Includes */
在main.c添加源代码:
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
adc_sample_lux_noisy(&lux, &noisy);
printf("Lux:[%lu] Noisy[%lu]\r\n", lux, noisy);
HAL_Delay(500);
}
/* USER CODE END 3 */
5- 烧录连接测试
烧录之后连接sscom进行测试,我们对着开发板声音改变或者光强改变的时候数字是不一样的,说明测试成功。
6- 蜂鸣器原理图
下图是BearKE1开发板原理图上蜂鸣器的电路图,由下图可知它受PA1管脚的控制。
在该开发板上我们采用的是无源蜂鸣器,因为人耳能听到的频率范围在20Hz–20kHz之间,此时我们只需要使用PA1管脚的定时器PWM输出功能,输出一个2.4KHz左右的PWM方波蜂鸣器就会发声了,通过调整PWM的频率就可以调整蜂鸣器的音色了。
PWM(Pulse Width Modulation,脉冲宽度调制)是通过对一系列脉冲的宽度进行调制,输出所需要的波形(包含形状以及幅值)。在PWM里有两个重要的专业术语:
- 频率是指1秒内高低电平周期性出现的次数。
- 占空比就是指在一个周期内,信号处于高电平的时间占据整个信号周期的百分比,例如下图所示的PWM波形占空比为25%,而方波则是指占空比为50%的PWM波形。
PWM在很多场合都会使用,我们经常见到的就是交流调光电路,也可以说是无级调速,高电平占多一点,也就是占空比大一点亮度就亮一点,占空比小一点亮度就没有那么亮,前提是PWM的频率要大于我们人眼识别频率,要不然会出现闪炼现象。除了在调光电路应用,还有在直流斩波电路、蜂鸣器驱动、电机驱动、逆变电路、加湿机雾化量等都会有应用。
在STM32的通用定时器中有两个重要的寄存器:
- ARR(Auto-reload register,自动重装载寄存器)是个16位的寄存器,这里面装着计数器能计数的最大数值。如果使能了中断,当计数到达这个值时定时器就产生溢出中断;
- CCR(Capture/Compare Registers,捕获/比较寄存器), CCR与定时器的值进行比较:如果CCR大则输出低电平,反之则输出高电平。通过改变CCR值可以改变PWM的占空比;
7- 配置蜂鸣器
首先配置使能TIM2,让Channel2输出PWM。这时PA1管脚的状态就被设置成TIM2_CH2功能模式了。
因为PWM会输出高低电平,接着设置GPIO下拉防止蜂鸣器误发声音。
配置预分频:
TIM2的输入时钟为APB1时钟80MHz,这个速率对定时器来说实在太快,这时需要对它做个预分频: CK_CNT = TIMxCLK/(PSC+1)=80MHz/(80-1+1)=1MHz
配置PWM时钟:
通过TIM2定时器的ARR(自动重装载寄存)的值可以调整PWM的输出频率,这里想让蜂鸣器工作在2.7KHz,则: ARR=1MHz/2700 约等于 370
配置占空比:
这里我们设置占空比为50%,则Pulse=370/2=185
Ctrl+s生成代码。
8- 添加代码
修改tim.c文件,添加蜂鸣器操作函数beep_start()实现,其中times为蜂鸣器响几次,而interval 为响、停的时间间隔。
/* USER CODE BEGIN 1 */
void beep_start(uint8_t times, uint16_t interval)
{
while(times--)
{
if(HAL_TIM_PWM_Start(&htim2, TIM_CHANNEL_2) != HAL_OK)
{
Error_Handler();
}
HAL_Delay(interval);
if(HAL_TIM_PWM_Stop(&htim2, TIM_CHANNEL_2) != HAL_OK)
{
Error_Handler();
}
HAL_Delay(interval);
}
}
/* USER CODE END 1 */
修改tim.h,添加蜂鸣器操作函数的声明。
/* USER CODE BEGIN Includes */
void beep_start(uint8_t times, uint16_t interval);
/* USER CODE END Includes */
main.c函数中调用 beep_start(2, 300);
/* USER CODE BEGIN WHILE */
/*响两次,间隔300毫秒*/
beep_start(2, 300);
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
/*这一部分为ADC采样的例子*/
adc_sample_lux_noisy(&lux, &noisy);
printf("Lux:[%lu] Noisy[%lu]\r\n", lux, noisy);
HAL_Delay(500);
}
/* USER CODE END 3 */
运行测试之后会听见开发板滴滴叫两声。