判断高电平,低电平和方波的几种方法

读取某一个上拉电平信号,它可能输出是低电平,可能是高电平,可能是方波,并且这个方波不知道频率何占空比,那么如何来通过程序来判断呢?高电平和低电平都好说,利用hal库读取即可,如下:
int main(void) { hal_init(); systemclock_config();
// 初始化 gpio gpio_inittypedef gpio_initstruct; __hal_rcc_gpioa_clk_enable(); // 启用 gpioa 时钟
gpio_initstruct.pin = gpio_pin_0; // 选择要读取的引脚 gpio_initstruct.mode = gpio_mode_input; // 设置为输入模式 gpio_initstruct.pull = gpio_nopull; // 没有上下拉电阻 hal_gpio_init(gpioa, &gpio_initstruct);
// 读取 gpio 电平 uint8_t gpiostate = hal_gpio_readpin(gpioa, gpio_pin_0);
// 现在 gpiostate 包含了引脚的电平状态 (gpio_pin_set 或 gpio_pin_reset)
while (1) { // 在这里可以执行其他任务 }}
重点是方波,如何读取方波信号呢?
方法一:读取adc电压高电平是3.3v左右,低电平是0v左右,那么介于中间的就是方波,这个是很直观的,以下便是读取adc的程序:
#include stm32f4xx.h#include stm32f4xx_hal.h
adc_handletypedef hadc1;
void error_handler(void) { // 处理错误}
void systemclock_config(void) { // 配置系统时钟}
void adc_config(void) { // 初始化adc外设 hadc1.instance = adc1; hadc1.init.clockprescaler = adc_clock_sync_pclk_div2; hadc1.init.resolution = adc_resolution_12b; hadc1.init.scanconvmode = disable; hadc1.init.continuousconvmode = enable; // 连续模式,以便不断地测量电压 hadc1.init.discontinuousconvmode = disable; hadc1.init.nbrofdiscconversion = 0; hadc1.init.externaltrigconvedge = adc_externaltrigconvedge_none; hadc1.init.externaltrigconv = adc_software_start; hadc1.init.dataalign = adc_dataalign_right; hadc1.init.nbrofconversion = 1; hadc1.init.dmacontinuousrequests = disable; hadc1.init.eocselection = adc_eoc_seq_conv; if (hal_adc_init(&hadc1) != hal_ok) { error_handler(); }
// 配置adc通道 adc_channelconftypedef sconfig = {0}; sconfig.channel = adc_channel_0; // 选择要读取的adc通道 sconfig.rank = 1; sconfig.samplingtime = adc_sampletime_84cycles; if (hal_adc_configchannel(&hadc1, &sconfig) != hal_ok) { error_handler(); }}
int main(void) { hal_init(); systemclock_config(); adc_config();
// 启动adc转换 if (hal_adc_start(&hadc1) != hal_ok) { error_handler(); }
uint32_t adcvalue; while (1) { // 等待adc转换完成 if (hal_adc_pollforconversion(&hadc1, hal_max_delay) == hal_ok) { // 读取adc数据寄存器 adcvalue = hal_adc_getvalue(&hadc1); // 判断电压值来判断是高电平、低电平还是方波信号 } }} 
方法二:外部中断
如果是方波,外部中断肯定会触发,外部电路是上拉,我们需要将stm32配置成上拉,下降沿触发外部中断。在1s内如果有中断被触发就是方波,否则就是高或者低电平,以下是hal的示例代码: 
#include stm32f4xx.h #include stm32f4xx_hal.h
void error_handler(void) { // 处理错误}
void systemclock_config(void) { // 配置系统时钟}
void exti_config(void) { // 配置外部中断 __hal_rcc_gpioa_clk_enable(); // 启用gpioa时钟 __hal_rcc_syscfg_clk_enable(); // 启用syscfg时钟
gpio_inittypedef gpio_initstruct; gpio_initstruct.pin = gpio_pin_0; // 配置外部中断引脚,例如gpioa的引脚0 gpio_initstruct.mode = gpio_mode_it_rising_falling; // 上升沿和下降沿触发外部中断 gpio_initstruct.pull = gpio_pullup; // 上拉电阻 hal_gpio_init(gpioa, &gpio_initstruct);
// 配置外部中断线 hal_nvic_setpriority(exti0_irqn, 0, 0); // 配置中断优先级 hal_nvic_enableirq(exti0_irqn); // 启用外部中断
// 配置外部中断触发 exti_inittypedef exti_initstruct; exti_initstruct.line = exti_line_0; // 配置外部中断线 exti_initstruct.mode = exti_mode_interrupt; exti_initstruct.trigger = exti_trigger_rising_falling; // 上升沿和下降沿触发 hal_exti_setconfigline(&exti_initstruct);}
void hal_gpio_exti_callback(uint16_t gpio_pin) { // 外部中断回调函数,当外部中断触发时执行
// 在这里可以执行你的方波信号检测逻辑 // 如果外部中断触发,表示方波信号 // 否则,表示高电平或低电平}
int main(void) { hal_init(); systemclock_config(); exti_config();
while (1) { // 在这里可以执行其他任务 }}
方法三:读取方波的频率和占空比
这个是直接的,也是最直观的,我们还可以额外知道该方波的一些信息。以下是示例代码:
#include stm32f4xx.h#include stm32f4xx_hal.h
tim_handletypedef htim2;uint32_t highpulse = 0;uint32_t lowpulse = 0;uint32_t period = 0;uint32_t frequency = 0;float dutycycle = 0.0f; 
void error_handler(void) { // 处理错误}
void systemclock_config(void) { // 配置系统时钟}
void tim2_config(void) { // 初始化定时器2 (tim2) htim2.instance = tim2; htim2.init.prescaler = 0; htim2.init.countermode = tim_countermode_up; htim2.init.period = 0xffffffff; // 设置定时器周期为最大值 if (hal_tim_base_init(&htim2) != hal_ok) { error_handler(); }}
void hal_tim_periodelapsedcallback(tim_handletypedef *htim) { if (htim->instance == tim2) { // 每当定时器2溢出时执行
// 更新方波频率和占空比的测量值 frequency = hal_rcc_getpclk1freq() / (period + 1); dutycycle = (float)highpulse / (period + 1); highpulse = 0; lowpulse = 0; }}
void hal_tim_ic_capturecallback(tim_handletypedef *htim) { if (htim->instance == tim2) { // 每当定时器2的捕获比较中断时执行
if (hal_gpio_readpin(gpioa, gpio_pin_0) == gpio_pin_set) { // 当外部信号为高电平时执行 highpulse = __hal_tim_get_compare(htim, tim_channel_1); } else { // 当外部信号为低电平时执行 lowpulse = __hal_tim_get_compare(htim, tim_channel_1); period = highpulse + lowpulse; } }}
int main(void) { hal_init(); systemclock_config(); tim2_config();
// 配置外部中断线 __hal_rcc_gpioa_clk_enable(); gpio_inittypedef gpio_initstruct; gpio_initstruct.pin = gpio_pin_0; gpio_initstruct.mode = gpio_mode_input; gpio_initstruct.pull = gpio_pullup; hal_gpio_init(gpioa, &gpio_initstruct);
// 配置外部中断引脚 exti_inittypedef exti_initstruct; exti_initstruct.line = exti_line_0; exti_initstruct.mode = exti_mode_interrupt; exti_initstruct.trigger = exti_trigger_rising_falling; hal_exti_setconfigline(&exti_initstruct);
// 配置中断优先级 hal_nvic_setpriority(exti0_irqn, 0, 0); hal_nvic_enableirq(exti0_irqn);
// 启动定时器 if (hal_tim_base_start(&htim2) != hal_ok) { error_handler(); } 
while (1) { // 在这里可以执行其他任务 }}
以上就是想到的3种方法,欢迎方法补充,最后如果你知道方波的频率和占空比,还有一个方法,你知道吗?

生活,是一场体验——2016智能家居&未来生活体验博览会即将开幕
怎么区分开关电源的PFM与PWM模式?
小米6之前小米旗舰依然联发科!红米Pro2新机曝光
魅族官方发布纪念海报称:“16年,蜕变打磨,初心不改,追求源于热爱”
Bulgin6000系列Buccaneer 连接器正式上市
判断高电平,低电平和方波的几种方法
哪几个物联网方案具有影响力
武汉大学研发出一款迷你软体机器人
自适应AI的优势是什么?
斯坦德赋能富通集团自动化升级,领跑智能叉车批量落地
迎接开学季,学生们该准备的数码产品,蓝牙耳机推荐
变电站设备实时监控,三光谱防明火摄像机为您守护
智能水表的定义与分类
74系列芯片功能中文资料
英特尔Tiger Lake处理器现身Geekbench 5,主频达到3.9GHz
车电分离会是纯电动车的最佳出路吗
09年半导体市场下滑幅度小于预期,三星表现出色
AIX G5反应器平台5x200 mm硅基氮化镓技术
高云半导体将参加日本2019嵌入式及物联网综合技术展
显微红外热测试系统在驱动电源的应用案例