首页 > 评测 > 基于CH32V103实现HC-SR04 超声波测距模块轮询读取距离数据
基于CH32V103实现HC-SR04 超声波测距模块轮询读取距离数据
- [导读]
- 本帖最后由 lilijin1995 于 2023-3-17 23:13 编辑 一般的我自己学习单片机,为了更加了解硬件,我都会画了一块CH32V103最小系统板,然后外接其他功能模块实现一些应用,现在秀一秀自己画的板子,虽然设计得不
本帖最后由 lilijin1995 于 2023-3-17 23:13 编辑
一般的我自己学习单片机,为了更加了解硬件,我都会画了一块CH32V103最小系统板,然后外接其他功能模块实现一些应用,现在秀一秀自己画的板子,虽然设计得不怎样,哈哈哈!!!
最近翻箱底有一款超声波测距,HC-SR04,
那么现在就开始实现HC-SR04 超声波测距模块轮询读取距离数据
硬件接口:根据规格书可以看到接口定义如下图:
我们定义PA0映射TRIG,PA1-TIM2CH2映射ECHO,供电为5V。
软件说明:
超声波时序图如下:
以上时序图表明你只需要提供一个 10uS 以上脉冲触发信号,该模块内部将
发出 8 个 40kHz 周期电平并检测回波。一旦检测到有回波信号则输出回响信号 。
回响信号的脉冲宽度与所测的距离成正比。由此通过发射信号到收到的回响信号
时间间隔可以计算得到距离。公式:uS/58=厘米或者 uS/148=英寸;或是:距离=
高电平时间*声速(340M/S)/2;建议测量周期为 60ms 以上,以防止发射信号对
回响信号的影响。
这里主要是ECHO配置TIMCH2输入捕获配置,如下代码:
- /*********************************************************************
- * @fn TIM2_ICapture_Init
- *
- * [url=home.php?mod=space&uid=247401]@brief[/url] Initializes TIM1 input capture.
- *
- * @param arr - the period value.
- * psc - the prescaler value.
- * ccp - the pulse value.
- *
- * [url=home.php?mod=space&uid=266161]@return[/url] none
- */
- void TIM2_ICapture_Init(u16 arr, u16 psc)
- {
- GPIO_InitTypeDef GPIO_InitStructure = {0};
- TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure = {0};
- NVIC_InitTypeDef NVIC_InitStructure = {0};
- RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
- RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE); //使能TIM2时钟
- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD;
- GPIO_Init(GPIOA, &GPIO_InitStructure);
- GPIO_ResetBits(GPIOA, GPIO_Pin_1);
- TIM_TimeBaseInitStructure.TIM_Period = arr;
- TIM_TimeBaseInitStructure.TIM_Prescaler = psc;
- TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;
- TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;
- TIM_TimeBaseInit(TIM2, &TIM_TimeBaseInitStructure);
- TIM_ICInitStructure.TIM_Channel = TIM_Channel_2;
- TIM_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1;
- TIM_ICInitStructure.TIM_ICFilter = 0x00;
- TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising;
- TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI;
- TIM_ICInit(TIM2,&TIM_ICInitStructure);
- NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;
- NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;
- NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
- NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
- NVIC_Init(&NVIC_InitStructure);
- TIM_ITConfig(TIM2, TIM_IT_Update | TIM_IT_CC2, ENABLE);
- TIM_Cmd(TIM2, ENABLE);
- }
我们直接在中断里面计算高电平时间,这里面参考了正点原子的输入捕获实验
- //TIM2CH2_CAPTURE_STA
- //bit7:捕获完成标志
- //bit6:捕获到高电平标志
- //bit5~0:捕获到高电平后定时器溢出的次数
- u8 TIM2CH2_CAPTURE_STA=0; //输入捕获状态
- u16 TIM2CH2_CAPTURE_VAL; //输入捕获值,用来记录捕获到下降沿的时候,TIM2_CNT的值
- //定时器2中断服务程序
- void TIM2_IRQHandler(void)
- {
- if((TIM2CH2_CAPTURE_STA&0X80)==0)//还未成功捕获
- {
- if (TIM_GetITStatus(TIM2, TIM_IT_Update) != RESET)
- {
- if(TIM2CH2_CAPTURE_STA&0X40)//已经捕获到高电平了
- {
- if((TIM2CH2_CAPTURE_STA&0X3F)==0X3F)//高电平太长了
- {
- TIM2CH2_CAPTURE_STA|=0X80;//标记成功捕获了一次
- TIM2CH2_CAPTURE_VAL=0XFFFF;
- }else TIM2CH2_CAPTURE_STA++;
- }
- }
- if (TIM_GetITStatus(TIM2, TIM_IT_CC2) != RESET)//捕获2发生捕获事件
- {
- if(TIM2CH2_CAPTURE_STA&0X40) //捕获到一个下降沿
- {
- TIM2CH2_CAPTURE_STA|=0X80; //标记成功捕获到一次高电平脉宽
- TIM2CH2_CAPTURE_VAL=TIM_GetCapture2(TIM2);
- TIM_OC2PolarityConfig(TIM2,TIM_ICPolarity_Rising); //CC2P=0 设置为上升沿捕获
- }else //还未开始,第一次捕获上升沿
- {
- TIM2CH2_CAPTURE_STA=0; //清空
- TIM2CH2_CAPTURE_VAL=0;
- TIM_SetCounter(TIM2,0);
- TIM2CH2_CAPTURE_STA|=0X40; //标记捕获到了上升沿
- TIM_OC2PolarityConfig(TIM2,TIM_ICPolarity_Falling); //CC1P=1 设置为下降沿捕获
- }
- }
- }
- TIM_ClearITPendingBit(TIM2, TIM_IT_CC2|TIM_IT_Update); //清除中断标志位
- }
捕获了高电平时间,直接除以58就是距离值:我们直接看我们的SR04驱动:
- void SR04_Init(void)
- {
- GPIO_InitTypeDef GPIO_InitStructure;
- RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); //使能PB,PE端口时钟
- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0; //LED0-->PB.5 端口配置
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //推挽输出
- GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //IO口速度为50MHz
- GPIO_Init(GPIOA, &GPIO_InitStructure); //根据设定参数初始化GPIOB.5
- GPIO_SetBits(GPIOA,GPIO_Pin_0); //PB.5 输出高
- TIM2_ICapture_Init(0xFFFF,71);
- TRIG(0);
- }
- u32 SR04_Handler(void)
- {
- u32 temp=0,Distance=0;
- //TRig
- Delay_Ms(1);
- TRIG(1);
- Delay_Ms(15);
- TRIG(0);
- //计算距离
- if(TIM2CH2_CAPTURE_STA&0X80) //成功捕获到了一次高电平
- {
- temp=TIM2CH2_CAPTURE_STA&0X3F;
- temp*=65536; //溢出时间总和
- temp+=TIM2CH2_CAPTURE_VAL; //得到总的高电平时间
- Distance=(temp/58);
- printf("Distance:%d cm\r\n",Distance); //打印总的高点平时间
- TIM2CH2_CAPTURE_STA=0; //开启下一次捕获
- return Distance;
- }
- return 0;
- }
下载验证:
- 本文系21ic原创,未经许可禁止转载!
网友评论
- 联系人:巧克力娃娃
- 邮箱:board@21ic.com
- 我要投稿
-
欢迎入驻,开放投稿
-
人均百万?英伟达中国员工收入曝光! 2024-08-29
-
《黑神话:悟空》玩家硬盘升级攻略:提升游戏体验,畅享3A大作 2024-08-29
-
数睿数据参加《系统与软件工程 低代码开发平台通用技术要求》国家标准编制 2024-08-29
- NRF52810蓝牙数字耳机找人定制
预算:¥30005天前
- 125KW模块式PCS软硬件外包开发
预算:¥1100000015小时前
- 12V汽车启动电源项目BMS设计
预算:¥50000023小时前
- 数据可视化软件 开发
预算:¥5000023小时前
- PLC项目调试修改
预算:¥100001天前
- 起动电机控制器开发
预算:¥1100001天前