赞
踩
观察电路图:
TXD(底板) ————————> PA10
RXD(底板) ————————> PA9
AD按键端口(底板) ————————> PA1
通过 ADC 采样获取按键的状态,根据采样值判断按键是否被按下,并返回对应的按键编号(ADKEY_AK1、ADKEY_AK2、ADKEY_AK3、ADKEY_AK4)或者无按键情况(ADKEY_NO),并打印在串口助手中
步骤1:复制工程模板“1_Template”重命名为“14_ADC”。
步骤2:修改项目工程名,先删除projects文件夹内除了Template.uvprojx文件外的所有内容并修改为“ADC.uvprojx”。并删除output/obj和output/lst中的所有文件。
步骤3:运行“PassiveBeep.uvprojx”打开目标选项“Options for Target”中的“Output”输出文件,并修改可执行文件名称为“ADC”点击“OK”保存设置。最后点击“Rebuild”编译该工程生成Usart文件。
步骤4:复制2_LEDTest中的"1_LED"和文件复制到hardware中。
步骤5:在system文件夹中新建一个adc文件夹并在该文件夹下新建adc.c和adc.h两个文件。
步骤6:工程组文件中添加“1_LED”和“2_ADCKEY”文件夹内的所有文件。
步骤7:工程组文件中添加“adc”文件夹内的所有文件。
步骤6:目标选项添加添加头文件路径。
基于STM32的检测定时器超时状态并翻转LED的状态,同时检测AD按键状态并输出按下的按键编号到串口。
步骤2:循环函数编写
while(1) // 进入无限循环
{
if(WaitTimerOut(3)) // 如果等待计时器超时(3秒)
LED = !LED; // 切换 LED 的状态(取反)
temp = AdKeyScan(); // 读取 AD 按键的状态
if(temp) // 如果检测到按键按下(按键值不为0)
printf("AK%d被按下!\r\n", temp); // 打印按下的按键编号
}
步骤1:初始化ADC
/********************************************************************* @Function : 初始化ADC @Parameter : N/A @Return : N/A **********************************************************************/ void Adc_Init(void) { /*初始化结构体*/ ADC_InitTypeDef ADC_InitStructure; // 定义 ADC 初始化结构体 GPIO_InitTypeDef GPIO_InitStructure; // 定义 GPIO 初始化结构体 /* 时钟使能 */ RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_ADC1, ENABLE); /* 设置ADC分频因子 */ RCC_ADCCLKConfig(RCC_PCLK2_Div6); // 将ADC时钟设置为PCLK2的1/6,此处PCLK2为72MHz,分频后为12MHz /* 引脚配置 */ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1; // 配置PA1为ADC输入 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN; // 模拟输入模式 GPIO_Init(GPIOA, &GPIO_InitStructure); // 初始化GPIOA /* 复位ADC1 */ ADC_DeInit(ADC1); /* ADC配置 */ ADC_InitStructure.ADC_Mode = ADC_Mode_Independent; // 独立模式,单独使用ADC1 ADC_InitStructure.ADC_ScanConvMode = DISABLE; // 关闭扫描模式,单通道模式 ADC_InitStructure.ADC_ContinuousConvMode = DISABLE; // 关闭连续转换模式,单次转换模式 ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None; // 软件触发转换 ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right; // 数据右对齐 ADC_InitStructure.ADC_NbrOfChannel = 1; // 转换通道数量为1 ADC_Init(ADC1, &ADC_InitStructure); // 初始化ADC1 /* 使能ADC */ ADC_Cmd(ADC1, ENABLE); /* 复位校准 */ ADC_ResetCalibration(ADC1); while (ADC_GetResetCalibrationStatus(ADC1)); // 等待复位校准结束 /* 开始校准 */ ADC_StartCalibration(ADC1); while (ADC_GetCalibrationStatus(ADC1)); // 等待校准结束 /* 使能软件转换启动功能(可根据需要启用) */ // ADC_SoftwareStartConvCmd(ADC1, ENABLE); }
/********************************************************************* @Function : 获得ADC值 @Parameter : ch : 通道值 0~3 @Return : ADC值 **********************************************************************/ uint16_t Get_Adc(uint8_t ch) { /*设置指定ADC的规则组通道,一个序列,采样时间*/ ADC_RegularChannelConfig(ADC1, ch, 1, ADC_SampleTime_239Cycles5 ); //ADC1,ADC通道,采样时间为239.5周期 ADC_SoftwareStartConvCmd(ADC1, ENABLE); //使能指定的ADC1的软件转换启动功能 while(!ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC )); //等待转换结束 return ADC_GetConversionValue(ADC1); //返回最近一次ADC1规则组的转换结果 }
/********************************************************************* @Function : 获得ADC的平均值 @Parameter : ch : 通道值 0~3 times :采集次数 @Return : ADC平均值 **********************************************************************/ uint16_t Get_Adc_Average(uint8_t ch, uint8_t times) { uint32_t temp_val = 0; // 初始化累加变量为0 uint8_t t; // 循环计数变量 for (t = 0; t < times; t++) // 循环执行指定次数 { temp_val += Get_Adc(ch); // 获取指定通道的ADC值并累加到temp_val delay_ms(5); // 延时5毫秒,等待下一次采样 } return temp_val / times; // 返回ADC采样值的平均值 }
/********************************************************************* @Function : AD按键初始化 @Parameter : N/A @Return : N/A **********************************************************************/ uint8_t AdKeyScan(void) { uint16_t adcx; // 定义ADC采样值变量adcx /* 读取ADC */ adcx = Get_Adc_Average(ADC_Channel_1, 10); // 读取ADC通道1的平均值,采样次数为10次 /* 键值判断 */ if (adcx > 500) // 如果ADC值大于500 { if ((adcx > 3500) && (adcx < 4200)) return ADKEY_AK1; // 返回ADKEY_AK1,表示检测到按键1被按下 if ((adcx > 2500) && (adcx < 3200)) return ADKEY_AK2; // 返回ADKEY_AK2,表示检测到按键2被按下 if ((adcx > 1500) && (adcx < 2200)) return ADKEY_AK3; // 返回ADKEY_AK3,表示检测到按键3被按下 if ((adcx > 800) && (adcx < 1200)) return ADKEY_AK4; // 返回ADKEY_AK4,表示检测到按键4被按下 } }
步骤1:adc所需头文件添加
#include "stm32f10x_rcc.h"
#include "stm32f10x_gpio.h"
#include "stm32f10x_adc.h"
#include ".\adc\adc.h"
#include ".\delay\delay.h"
步骤2:添加adckey源文件所需的头文件
#include "stm32f10x_adc.h"
#include ".\adc\adc.h"
#include "adckey.h"
步骤3:函数声明
uint32_t temp=0;
delay_init(); //启动滴答定时器
usart1_init(9600); //USART1初始化
SystemTinerInit(1000-1,3600-1); //系统时间初始化 定时100ms
AdKeyInit(); //AD按键初始化
//bord.h #ifndef __BORD_H_ #define __BORD_H_ #include "system_config.h" //头文件包含 /*************SYSTEM*****************/ /*#include ".\sys\sys.h"*/ #include ".\delay\delay.h" #include ".\usart\usart.h" #include ".\timer\timer.h" #include ".\adc\adc.h" /***********Hardweare***************/ #include "led.h" #include "adckey.h" /***********Funlibrary***************/ #endif
步骤2:添加函数声明
//adc.h
#ifndef __ADC_H_
#define __ADC_H_
#include <stdint.h>
/*函数声明*/
void Adc_Init(void);
uint16_t Get_Adc(uint8_t ch);
uint16_t Get_Adc_Average(uint8_t ch,uint8_t times);
#endif
步骤2:添加中断源文件所需的头文件
//adckey.h #ifndef __ADKEY_H_ #define __ADKEY_H_ #include <stdint.h> //AD键值枚举 enum ADkey { ADKEY_NO=0, ADKEY_AK1, ADKEY_AK2, ADKEY_AK3, ADKEY_AK4 }; /*函数声明*/ void AdKeyInit(void); uint8_t AdKeyScan(void); #endif
ADC引脚:
ADC 框图中的引脚用于连接外部模拟信号。通常有一个或多个引脚作为模拟输入,将待转换的模拟信号输入给 ADC。此外,可能还有其他引脚用于控制、时钟输入和数字输出。
ADC输入通道:
ADC 输入通道是连接到 ADC 的引脚,用于接收模拟信号。每个输入通道对应一个物理引脚或者电路连接,可以选择不同的通道来进行模拟信号的采集和转换。
规则通道组和注入通道组:
规则通道组和注入通道组是 ADC 中用于管理转换通道的组织方式。
规则通道组用于常规的模拟输入信号转换,可以选择一个或多个通道进行顺序转换。
注入通道组允许在常规转换中插入一个或多个优先级更高的转换(例如紧急事件处理),通常用于特殊需求或优先级较高的采样。
触发源:
ADC 可以通过不同的触发源启动转换。触发源可以是软件触发(通过编程触发)、定时器触发(定时器计数到特定值触发)、外部触发(外部引脚触发)等。选择合适的触发源可以灵活控制 ADC 的转换时机。
转换时间:
转换时间是 ADC 完成一次模拟到数字转换所需的时间。这个时间取决于 ADC 的工作模式、时钟频率以及转换精度等因素。在设计中需要考虑转换时间来确定系统的响应速度和性能。
数据寄存器:
转换完成后,ADC 将数字化的采样值存储在数据寄存器中。系统可以通过读取数据寄存器来获取 ADC 的转换结果,进而进行后续的数据处理和分析。
中断:
ADC 可以通过中断来提醒系统转换完成或者出现特定的转换事件。通过配置中断使能和中断优先级,可以实现在转换完成后自动触发特定的处理程序,提高系统的实时性和效率。
基本原理是利用电阻分压的方式,通过按下不同的按键改变电路中的电压值,然后使用 ADC(模数转换器)引脚对这些电压进行采集。采集到的电压值随后用于判断按下了哪个按键,从而实现按键功能。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。