stm32f103c8t6 多个超声波模块
时间: 2025-06-18 13:58:46 浏览: 25
### STM32F103C8T6多超声波模块方案及代码示例
在使用STM32F103C8T6微控制器连接和管理多个超声波模块时,需要合理分配GPIO引脚以驱动每个模块的触发(Trigger)和回响(Echo)信号。同时,利用定时器或DMA技术可以优化资源占用,确保测距结果的准确性。
#### 1. 接线图设计
为了支持多个超声波模块,需为每个模块单独分配一个Trigger引脚和一个Echo引脚。例如:
- **Trigger 引脚**:用于发送触发信号,启动超声波发射。
- **Echo 引脚**:用于接收反射信号,测量时间间隔。
以下是一个典型的接线图示例(假设使用两个超声波模块):
| 模块编号 | Trigger 引脚 | Echo 引脚 |
|----------|---------------|-----------|
| 超声波模块1 | PA0 | PA1 |
| 超声波模块2 | PA2 | PA3 |
所有模块的VCC和GND应连接到STM32F103C8T6的电源引脚。确保电源稳定且满足模块的工作电压要求[^1]。
#### 2. 示例代码
以下代码展示了如何初始化GPIO和定时器,并实现多模块测距功能:
```c
#include "stm32f10x.h"
#define TRIGGER1 GPIO_Pin_0
#define ECHO1 GPIO_Pin_1
#define TRIGGER2 GPIO_Pin_2
#define ECHO2 GPIO_Pin_3
void GPIO_Configuration(void);
void TIM_Configuration(void);
uint32_t time1 = 0, time2 = 0;
int main(void) {
GPIO_Configuration();
TIM_Configuration();
while (1) {
// 触发超声波模块1
GPIO_SetBits(GPIOA, TRIGGER1);
delay_us(10); // 高电平持续10us
GPIO_ResetBits(GPIOA, TRIGGER1);
// 等待Echo信号并记录时间
while (!GPIO_ReadInputDataBit(GPIOA, ECHO1));
TIM_Cmd(TIM2, ENABLE); // 开始计时
while (GPIO_ReadInputDataBit(GPIOA, ECHO1));
TIM_Cmd(TIM2, DISABLE);
time1 = TIM_GetCounter(TIM2);
// 触发超声波模块2
GPIO_SetBits(GPIOA, TRIGGER2);
delay_us(10); // 高电平持续10us
GPIO_ResetBits(GPIOA, TRIGGER2);
// 等待Echo信号并记录时间
while (!GPIO_ReadInputDataBit(GPIOA, ECHO2));
TIM_Cmd(TIM2, ENABLE); // 开始计时
while (GPIO_ReadInputDataBit(GPIOA, ECHO2));
TIM_Cmd(TIM2, DISABLE);
time2 = TIM_GetCounter(TIM2);
// 计算距离
float distance1 = time1 * 0.034 / 2; // 声速340m/s
float distance2 = time2 * 0.034 / 2;
}
}
void GPIO_Configuration(void) {
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
// 配置Trigger引脚为输出模式
GPIO_InitStructure.GPIO_Pin = TRIGGER1 | TRIGGER2;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
// 配置Echo引脚为输入模式
GPIO_InitStructure.GPIO_Pin = ECHO1 | ECHO2;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_Init(GPIOA, &GPIO_InitStructure);
}
void TIM_Configuration(void) {
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
TIM_TimeBaseStructure.TIM_Period = 0xFFFF;
TIM_TimeBaseStructure.TIM_Prescaler = 72 - 1;
TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);
}
```
#### 3. 驱动程序优化
为了提高效率,可以结合DMA或中断机制来减少CPU负载。例如,通过配置外部中断捕获Echo信号的变化,从而避免轮询等待[^3]。
```c
void EXTI_Configuration(void) {
EXTI_InitTypeDef EXTI_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
GPIO_EXTILineConfig(GPIO_PortSourceGPIOA, GPIO_PinSource1);
GPIO_EXTILineConfig(GPIO_PortSourceGPIOA, GPIO_PinSource3);
EXTI_InitStructure.EXTI_Line = EXTI_Line1 | EXTI_Line3;
EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising_Falling;
EXTI_InitStructure.EXTI_LineCmd = ENABLE;
EXTI_Init(&EXTI_InitStructure);
NVIC_InitStructure.NVIC_IRQChannel = EXTI1_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x00;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x00;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
}
```
#### 4. 注意事项
- 确保每个超声波模块的Trigger信号之间有足够的延迟,避免相互干扰[^2]。
- 使用高精度定时器(如TIM2)以保证时间测量的准确性。
- 如果需要同时处理多个模块的数据,建议启用DMA以减轻CPU负担。
阅读全文
相关推荐
















