一、任务简介
本次活动是使用FRDM-MCXA153开发板驱动超声波传感器测距,用LCD1601显示屏显示测距结果。
二、方案介绍
1、显示部分

由于LCD1601使用的是并口,并且是工作于5V电源的,而FRDM-MCXA153开发板的GPIO、外设默认是3.3V的逻辑电平,因此并口模式下要考虑并口的接口的电平匹配问题。所以这里选择PCF8574T模块,将并口通讯转为I2C通讯,减少了接口引脚,测试上也更方便。
2、传感器部分

本次活动使用的是HC-SR04,工作电源同样是5V。这种传感器的特点是,提供触发信号后,等待返回信号的电平变化,根据脉冲的高电平的持续时间计算距离。而在这个信号是微秒级的,因此使用FRDM-MCXA153驱动时,考虑使用CTimer外设捕捉回波信号的电平变化。
三、方案设计
1、电路组成框图

2、程序流程
1)主程序

2)CTimer中断处理

四、方案实现
1、主程序
程序以frdmmcxa153_lpi2c_polling_b2b_master例程为主,参考frdmmcxa153_ctimer_capture例程,加入CTimer的处理部分。主程序部分代码如下:
// 初始化CTimer0
void InitCTimerCapture(void) {
ctimer_config_t ctimerConfig;
CTIMER_GetDefaultConfig(&ctimerConfig);
// 可选:设置预分频器以调整计数时钟,这里使用默认的96MHz
CTIMER_Init(DEMO_CTIMER, &ctimerConfig);
// 配置通道0捕获上升沿、下降沿,并使能中断
CTIMER_SetupCapture(DEMO_CTIMER, kCTIMER_Capture_0, kCTIMER_Capture_BothEdge, true);
// 使能CTIMER中断
CTIMER_EnableInterrupts(DEMO_CTIMER, kCTIMER_Capture0InterruptEnable);
// 开放CTIMER0中断
EnableIRQ(CTIMER0_IRQn);
// 启动CTIMER0
CTIMER_StartTimer(DEMO_CTIMER);
}
// CTIMER0 中断处理函数
void CTIMER0_IRQHandler(void) {
uint32_t status = CTIMER_GetStatusFlags(DEMO_CTIMER);
if (status & kCTIMER_Capture0Flag) {
// 1. 立即清除标志位,防止重复进入
CTIMER_ClearStatusFlags(DEMO_CTIMER, kCTIMER_Capture0Flag);
// 2. 读取捕获值(此时硬件已锁存)
uint32_t captureValue = CTIMER_GetCaptureValue(DEMO_CTIMER, kCTIMER_Capture_0);
// 3. 根据当前状态处理
if (edgeState == WAITING_RISING) {
riseValue = captureValue; // 保存上升沿时刻
edgeState = WAITING_FALLING; // 切换状态
// 配置为下降沿捕获,为下一个边沿做准备
//CTIMER_SetupCapture(DEMO_CTIMER, CAPTURE_FALL_CH, kCTIMER_Capture_FallEdge, true);
captureDone = 2;
}
else if (edgeState == WAITING_FALLING) {
fallValue = captureValue; // 保存下降沿时刻
edgeState = WAITING_RISING; // 恢复状态,准备下一次测量
// 配置为上升沿捕获
//CTIMER_SetupCapture(DEMO_CTIMER, CAPTURE_FALL_CH, kCTIMER_Capture_RiseEdge, true);
captureDone = 4; // 标记一次完整测量完成
}
}
}
// 触发一次测距,并等待结果
void TriggerAndGetDistance(void) {
uint8_t str[17]={0};
//PRINTF("CaptureDone = %d \r\n", captureDone);
if (captureDone == 0) {
// 1. 触发 Trig:至少10us高电平(占用绿色LED - P3.13所在引脚)
GPIO_PinWrite(TRIG_PIN_GPIO, TRIG_PIN, 1U);
SDK_DelayAtLeastUs(10, CLOCK_GetFreq(kCLOCK_CoreSysClk));
GPIO_PinWrite(TRIG_PIN_GPIO, TRIG_PIN, 0U);
captureDone = 1;
// 测试用代码,产生ECHO上升沿信号,模拟输出ECHO信号(占用蓝色LED - P3.0所在引脚)
// 需要短接 P3.0 -> P1.8
ECHO_1();
} else if (captureDone == 2) {
// 捕捉到上升沿了
//PRINTF("TriggerAndGetDistance captureDone = 2 \r\n");
captureDone = 3;
// 等待 captureDone 变成4
} else if (captureDone == 3) {
// 测试用代码,产生下降沿信号
ECHO_0();
}
if (captureDone == 4) {
// 计算时间差和距离
uint32_t pulseWidth = fallValue - riseValue;
// 假设CTimer时钟为96MHz,每个计数周期约为10.4ns (1/96MHz)
// 距离 (cm) = 时间 (us) * 声速 (cm/us) / 2
//float distance = (float)pulseWidth * 0.0000000104f * 34600.0f / 2.0f;
float distance = (float)pulseWidth * 0.0001802;
//PRINTF("Dist = %.2fcm \r\n", distance);
PRINTF("Dist = %d.%02dcm \r\n", (int)distance, (int)((distance - (int)distance) * 100));
snprintf(str, sizeof(str), "Dist:%6d.%02dcm", (int)distance, (int)((distance - (int)distance) * 100));
// 禁止所有可屏蔽中断 (防止干扰I2C通讯)
__disable_irq();
LCD_SetCursor(0, 0);
LCD_Print(str);
LCD_SetCursor(0, 1);
LCD_Print(&str[8]);
// 允许所有可屏蔽中断
__enable_irq();
// 延迟200mS,准备执行下一次(SDK_DelayAtLeastUs:微秒级阻塞延时函数)
SDK_DelayAtLeastUs(200000, CLOCK_GetFreq(kCLOCK_CoreSysClk));
captureDone = 0;
}
}
/*!
* @brief Main function
*/
int main(void) {
uint32_t currentCounter = 0U;
uint8_t str[16]={0};
BOARD_InitHardware();
// 初始化CTimer
DEMO_InitCtimerInput();
// 初始化LED
LED_INIT();
// 输出假的echo信号(蓝色LED所在P3.0,要短路到P1.8上模拟上,模拟超声波传感器的echo信号)
GPIO_PinWrite(BOARD_LED_RED_GPIO, BOARD_LED_RED_GPIO_PIN, LOGIC_LED_ON);
GPIO_PinWrite(BOARD_LED_RED_GPIO, BOARD_LED_GREEN_GPIO_PIN, LOGIC_LED_ON);
GPIO_PinWrite(BOARD_LED_RED_GPIO, BOARD_LED_BLUE_GPIO_PIN, LOGIC_LED_ON);
// 初始化I2C
InitI2C();
// 初始化LPTMR
InitLptmr();
// 初始化CTIMER
InitCTimerCapture();
// 初始化LCD
LCD_Init();
LCD_SetCursor(0, 0);
LCD_Print(" EEPW & ");
LCD_SetCursor(0, 1);
LCD_Print("DigiKey ");
// 启动LPTMR
LPTMR_StartTimer(DEMO_LPTMR_BASE);
delay_ms(5000);
LCD_Clear();
while (1) {
// 开始测距
TriggerAndGetDistance();
}
}五、实测效果
<iframe src="//player.bilibili.com/player.html?isOutside=true&aid=117036382429042&bvid=BV1jouc6xEXi&cid=40587300587&p=1" scrolling="no" border="0" frameborder="no" framespacing="0" allowfullscreen="true"></iframe>
我要赚赏金
