【STM32】输入捕获的简单写法

博主分享自己编写的输入捕获代码并进行解释。实验使用引脚PA6对应TIM3_1,初始为下降沿检测。重点解释中断部分代码,包括按键按下、松开时捕获状态标志位、更新中断等操作,最后计算出本次捕获的高电平长度。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

       之前对输入捕获大概原理了解,实际操作不会,我看网上基本都是正点原子的,这次自己写了一次,感觉收获很大,代码送给大家,欢迎指正!!!

       先给出代码,最后把代码解释一波

#include<stm32f10x.h>
#include<timerbuhuo.h>
#include<delay.h>

u8 BUHUO_Flag=0,UPDATE_Flag=0;//前者用于标志捕获上升沿下降沿,后者用于标志溢出更新次数
unsigned int BUHUO_Up=0,BUHUO_Down=0,BUHUO_Num=0;//用于记录捕获到的高电平和低电平时刻
void TIMER_Buhuo()
{
	NVIC_InitTypeDef  NVIC_InitStructure;
	TIM_TimeBaseInitTypeDef TIM_TimeBaseStrycture;
	TIM_ICInitTypeDef TIM_ICInitStructure;
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE);
	/**********时基初始化************/
	TIM_TimeBaseStrycture.TIM_ClockDivision=0;
	TIM_TimeBaseStrycture.TIM_CounterMode=TIM_CounterMode_Up;
	TIM_TimeBaseStrycture.TIM_Period=65535;
	TIM_TimeBaseStrycture.TIM_Prescaler=71;
	TIM_TimeBaseInit(TIM3,&TIM_TimeBaseStrycture);
	/**********设置tim3比较参数,开启输入捕获************/
	TIM_ICInitStructure.TIM_Channel=TIM_Channel_1;
	TIM_ICInitStructure.TIM_ICFilter=0;
	TIM_ICInitStructure.TIM_ICPolarity=TIM_ICPolarity_Falling;
	TIM_ICInitStructure.TIM_ICPrescaler=TIM_ICPSC_DIV1;
	TIM_ICInitStructure.TIM_ICSelection=TIM_ICSelection_DirectTI;
	TIM_ICInit(TIM3,&TIM_ICInitStructure);
	
	NVIC_InitStructure.NVIC_IRQChannel=TIM3_IRQn;
	NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=2;
	NVIC_InitStructure.NVIC_IRQChannelSubPriority=2;
	NVIC_Init(&NVIC_InitStructure);
	
	TIM_Cmd(TIM3,ENABLE);
	TIM_ITConfig(TIM3,TIM_IT_Update|TIM_IT_CC1,ENABLE);
}

void KEY_Test()
{
	GPIO_InitTypeDef GPIO_InitStructure;
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
	
	GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IPU;//此处设置为上拉,与前者检测下降沿对应
	GPIO_InitStructure.GPIO_Pin=GPIO_Pin_6;
	GPIO_Init(GPIOA,&GPIO_InitStructure);
}


void TIM3_IRQHandler()
{
	if(TIM_GetITStatus(TIM3,TIM_IT_Update)==1)
	{
		if(BUHUO_Flag==1)//只有当检测到下降沿之后才有效
		{
			UPDATE_Flag+=1;//记录溢出次数
		}
	}
	if(TIM_GetITStatus(TIM3,TIM_IT_CC1)==1)
	{
		if(BUHUO_Flag==0)//为0时是正在检测下降沿
		{
			BUHUO_Down=TIM_GetCapture1(TIM3);//记录下降沿出现的时刻
			BUHUO_Flag=1;
			TIM_OC1PolarityConfig(TIM3,TIM_ICPolarity_Rising);//设置为上升沿检测
		}
		else 
		{
			if(UPDATE_Flag==0)BUHUO_Up=TIM_GetCapture1(TIM3);//此处需要判别是否已经在检测下降沿后,参数溢出
			else if(UPDATE_Flag>=1)//如果溢出,那么要知道溢出的次数,并且使用设定的溢出值乘次数,我这里是65535
			{
				BUHUO_Up=TIM_GetCapture1(TIM3)+65535*UPDATE_Flag;
				UPDATE_Flag=0;//结束后,别忘了给更新溢出标志位置0
			}
			BUHUO_Num=BUHUO_Up-BUHUO_Down;//计算时间
			TIM_OC1PolarityConfig(TIM3,TIM_ICPolarity_Falling);//重置为下降沿检测
			BUHUO_Flag=0;//给捕获标志位置0,为下一次捕获做准备
		}
		
	}
	TIM_ClearITPendingBit(TIM3,TIM_IT_Update|TIM_IT_CC1);
}

注意:1、本次实验使用的是引脚PA6,对应TIM3_1.,使用对应引脚按键来测试

           2、初始检测为下降沿沿检测,因为我的按键低电平有效。

           3、由于本实验知识点都在中断部分,所以只解释中断部分代码

中断代码解释:

按键不按下,没有产生下降沿,捕获中断不进入。按键按下,进入捕获中断,捕获状态标志位(BUHUO_Flag)初始值为0,获取当前下降沿出现时刻(BUHUO_Down),捕获状态标志位置1,标志我将要获取的应该是上升沿,并设置上升沿检测。此时的更新中断也在运行,若是判断到更新溢出,那么溢出次数(UPDATE_Flag)参数加1。松开按键,获取到上升沿,记录上升沿出现的时刻(BUHUO_Up),此时更新中断已经发生过很多次,所以要使用溢出值乘溢出次数,我设置的溢出值为65535,然后用获取到的当前的值加上溢出值乘溢出次数(BUHUO_Up=TIM_GetCapture1(TIM3)+65535*UPDATE_Flag;)。记录结束后,别忘了给捕获状态标志位和更新中断标志位置0,以便下次的检测。接下来计算本次捕获的高电平长度,这里就很简单了,上升沿出现时刻减去下降沿出现时刻就是(BUHUO_Num=BUHUO_Up-BUHUO_Down;)。

<think>嗯,用户想了解STM32与ESP32之间的通信和控制方法。从查询历史看,用户似乎在做物联网项目开发,需要整合这两种芯片。用户可能已经具备基础硬件知识,但需要具体实现指导。 用户的核心需求很明确:如何建立STM32与ESP32的物理连接和软件交互。考虑到ESP32的功能特性,通信方式选择尤为关键。UART是最简单直接的方案,适合大多数基础应用;SPI则适用于高速数据传输场景;而I2C在引脚资源紧张时更有优势。 硬件设计方面需要特别注意电平匹配问题,STM32通常是3.3V逻辑电平,与ESP32兼容,但若使用5V Arduino等设备就需要电平转换。引脚的复用功能也要提前规划,比如ESP32的GPIO6-11通常被内部Flash占用。 软件层面最常使用AT指令集控制ESP32,但实际开发中发现官方AT固件有时不够稳定。更可靠的方案是给ESP32烧录自定义固件,通过定义私有协议通信。比如用"WIFI,SSID,PASSWORD"这样的指令格式实现配置,比标准AT指令更不易出错。 测试阶段建议先用USB转TTL模块单独调试ESP32,确认其能正常连接WiFi后再接入STM32系统。常见的ESP32启动失败问题,多半是电源供电不足或EN引脚未上拉导致的。 考虑到用户可能的后续需求,准备几个延伸方向:如何实现OTA更新、低功耗设计技巧、以及双芯片间的安全认证机制。特别是物联网设备的安全问题容易被忽视,可以提醒用户增加TLS加密或设备证书验证。 最后要注意代码示例的实用性,给出GPIO配置和中断处理的示范时,特意选用STM32CubeMX和HAL库的写法,这是目前最主流的开发方式。对于实时性要求高的场景,额外标注了DMA配置的注意事项。</think>以下是STM32与ESP32通信及控制的详细指南,涵盖硬件连接、通信协议和软件实现: --- ### **一、硬件连接方式** 1. **UART通信(最常用)** - **接线方案**: | STM32引脚 | ESP32引脚 | 说明 | |-----------|-----------|---------------| | TX | RX | 数据发送 | | RX | TX | 数据接收 | | GND | GND | 共地 | | 3.3V | VCC/EN | 供电(需电流>500mA)| - **关键点**: - ESP32的`EN`引脚需上拉至3.3V(10kΩ电阻) - 若ESP32独立供电,须确保两地线连接 2. **SPI通信(高速场景)** - **接线方案**: | STM32引脚 | ESP32引脚 | |-----------|-----------| | SCK | SCK | | MISO | MISO | | MOSI | MOSI | | CS | GPIO5 | 自定义片选引脚 | 3. **I2C通信(节省引脚)** - **接线方案**: | STM32引脚 | ESP32引脚 | |-----------|-----------| | SCL | SCL | | SDA | SDA | | GND | GND | --- ### **二、软件通信实现** #### **1. UART控制ESP32(AT指令)** ```c // STM32发送WiFi连接指令 void ESP32_ConnectWiFi(UART_HandleTypeDef *huart, const char *ssid, const char *pwd) { char cmd[128]; sprintf(cmd, "AT+CWJAP=\"%s\",\"%s\"\r\n", ssid, pwd); HAL_UART_Transmit(huart, (uint8_t*)cmd, strlen(cmd), 1000); } // 示例:获取IP地址 HAL_UART_Transmit(&huart2, (uint8_t*)"AT+CIFSR\r\n", 10, 1000); ``` #### **2. 自定义协议通信(推荐)** ```c // 定义通信帧结构 typedef struct { uint8_t header; // 0xAA uint8_t cmd; // 指令类型 uint8_t len; // 数据长度 uint8_t data[32]; uint8_t checksum; } ESP32_Frame; // STM32发送控制指令 void Send_ESP32_Command(uint8_t cmd, uint8_t* data, uint8_t len) { ESP32_Frame frame = {0xAA, cmd, len, {0}, 0}; memcpy(frame.data, data, len); frame.checksum = Calculate_Checksum(&frame); HAL_UART_Transmit(&huart2, (uint8_t*)&frame, sizeof(frame), 100); } ``` --- ### **三、典型应用场景** 1. **WiFi数据传输** - STM32采集传感器数据 → ESP32通过MQTT上传至云端 ```c // 示例:发送温度数据 float temp = Read_Temperature(); char mqtt_msg[64]; sprintf(mqtt_msg, "{\"temp\":%.2f}", temp); Send_ESP32_Command(CMD_SEND_MQTT, (uint8_t*)mqtt_msg, strlen(mqtt_msg)); ``` 2. **蓝牙控制** - ESP32作为BLE从机 → 接收手机指令 → STM32执行动作 3. **双核协同计算** - ESP32处理复杂算法(如FFT)→ 结果通过SPI传回STM32 --- ### **四、调试技巧** 1. **ESP32独立调试** - 使用USB转TTL模块连接PC,用串口助手(如Putty)测试AT指令 2. **通信故障排查** - 检查电平:确保双方均为3.3V电平 - 测量波形:用逻辑分析仪捕获UART/SPI信号 3. **电源问题** - ESP32峰值电流可达500mA,建议使用独立电源模块 --- ### **五、进阶优化** 1. **通信效率** - UART使用DMA传输(波特率≥115200) - SPI启用双工模式(时钟频率≥10MHz) 2. **错误处理** ```c // 添加重发机制 for(int i=0; i<3; i++) { if(Send_Command() == ACK_OK) break; HAL_Delay(100); } ``` 3. **低功耗设计** - 空闲时通过`AT+SLEEP=1`使ESP32进入睡眠模式 > **注意事项**: > - ESP32的`GPIO0`需上拉,避免进入下载模式 > - 复位电路设计:`EN`引脚加100nF电容防误触发 > - 抗干扰:UART线路串联33Ω电阻并并联100pF电容[^3] ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值