【CW32F030CxTx StartKit开发板】利用超声波传感器实现智能灯控

目录

1、超声波传感器

2、硬件连线

3. 程序开发

3.1 超声波测距

3.2 LED控制

4. 演示视频


本文首发于21ic。

感谢21ic和武汉芯源提供的测试机会。
在上一篇帖子中介绍了CW32F030CxTxStartKit 评估板的环境构建。本次介绍如何利用超声波传感器实现人来灯亮,人走灯灭的智能灯控。

1、超声波传感器

HC-SR04是一款广泛使用的超声波测距模块,特别适用于机器人、无人车等领域。它利用超声波的发射和接收原理,通过测量超声波从发射到接收的时间来计算物体与传感器之间的距离。
HC-SR04的工作原理基于超声波的发射和接收。它主要由两个压电陶瓷片组成,其中一个用于发射超声波(T),另一个用于接收反射回来的超声波信号(R)。工作时,Trig引脚(触发端)发送一个10us的高电平信号,模块内部随后发出8个40KHZ的周期电平信号,并自动检测是否有信号返回。当有信号返回时,Echo引脚(接收端)会输出一个高电平信号,其脉冲宽度与所测距离成正比。

2、硬件连线

CW32F030CxTxStartKit 评估板把所有I/O口都引出来了,有个好处就是可以方便地进行接口之间的连接,做各种测试。我们把PA01连接到Trig引脚,将PA02连接到Echo引脚。同时将HC-SR04的VCC和GND引导开发板的VDD和GND上。

3. 程序开发

3.1 超声波测距

使用HC-SR04时,只需提供一个10uS以上的脉冲触发信号,模块内部将自动发出超声波并检测回波。通过测量Echo引脚高电平持续的时间,结合声速(340m/s),即可计算出物体与传感器之间的距离。具体计算公式为:距离 = (高电平时间 * 声速) / 2。
在程序中我们开启了BTIM1定时器,并在其中断函数中进行计时,从而用于测量Echo引脚高电平持续的时间。主要的程序代码如下:

//UARTx
#define  DEBUG_USARTx                   CW_UART1
#define  DEBUG_USART_CLK                RCC_APB2_PERIPH_UART1
#define  DEBUG_USART_APBClkENx          RCC_APBPeriphClk_Enable2
#define  DEBUG_USART_BaudRate           9600
#define  DEBUG_USART_UclkFreq           8000000

//UARTx GPIO
#define  DEBUG_USART_GPIO_CLK           RCC_AHB_PERIPH_GPIOA
#define  DEBUG_USART_TX_GPIO_PORT       CW_GPIOA
#define  DEBUG_USART_TX_GPIO_PIN        GPIO_PIN_8
#define  DEBUG_USART_RX_GPIO_PORT       CW_GPIOA
#define  DEBUG_USART_RX_GPIO_PIN        GPIO_PIN_9

//GPIO AF
#define  DEBUG_USART_AFTX               PA08_AFx_UART1TXD()
#define  DEBUG_USART_AFRX               PA09_AFx_UART1RXD()

#define LED_GPIO_PORT CW_GPIOB
#define LED_GPIO_PINS GPIO_PIN_8 | GPIO_PIN_9

#define SetTrig()    PA01_SETHIGH()
#define ResetTrig()  PA01_SETLOW()
#define ReadEcho()   GPIO_ReadPin(CW_GPIOA, GPIO_PIN_2)

/******************************************************************************
 * Global variable definitions (declared in header file with 'extern')
 ******************************************************************************/
extern unsigned int time;

/******************************************************************************
 * Local type definitions ('typedef')
 ******************************************************************************/

/******************************************************************************
 * Local function prototypes ('static')
 ******************************************************************************/

/******************************************************************************
 * Local variable definitions ('static')                                      *
 ******************************************************************************/
void RCC_Configuration(void);
void GPIO_Configuration(void);
void UART_Configuration(void);
unsigned int Measure_Distance(void);

#ifdef __GNUC__
    /* With GCC/RAISONANCE, small printf (option LD Linker->Libraries->Small printf
    set to 'Yes') calls __io_putchar() */
    #define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
#else
    #define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
#endif /* __GNUC__ */

BTIM_TimeBaseInitTypeDef BTIM_TimeBaseInitStruct;
                
/******************************************************************************
 * Local pre-processor symbols/macros ('#define')
 ******************************************************************************/

/*****************************************************************************
 * Function implementation - global ('extern') and local ('static')
 ******************************************************************************/


void BTIM_Init(void)
{
        RCC_APBPeriphClk_Enable2(RCC_APB2_PERIPH_BTIM, ENABLE);  //使能APB外设时钟
        
        BTIM_TimeBaseInitTypeDef BTIM_Initstruct;
        BTIM_Initstruct.BTIM_Mode = BTIM_Mode_TIMER;  //工作模式-->定时模式
        BTIM_Initstruct.BTIM_OPMode = BTIM_OPMode_Repetitive;//连续计数模式
        BTIM_Initstruct.BTIM_Period = 80-1;  //计数重载周期,16bit自动重载寄存器ARR,ARR的值最大为65535
        BTIM_Initstruct.BTIM_Prescaler = BTIM_PRS_DIV8;        //预分频
        BTIM_TimeBaseInit(CW_BTIM1, &BTIM_Initstruct);
        //定时时长=预分频/计数器时钟源频率*(计数重载周期+1),即T=8/64000000*800s=10us
        BTIM_ITConfig(CW_BTIM1, BTIM_IT_OV, ENABLE); //设置ARR溢出引发中断
        BTIM_Cmd(CW_BTIM1, ENABLE); //BTIM使能
        NVIC_EnableIRQ(BTIM1_IRQn);//中断使能
}

/**
 * [url=home.php?mod=space&uid=247401]@brief[/url] 配置RCC
 *
 */
void RCC_Configuration(void)
{
        //SYSCLK = HSI = 8MHz = HCLK = PCLK
    RCC_HSI_Enable(RCC_HSIOSC_DIV6);
    //外设时钟使能
    RCC_AHBPeriphClk_Enable(DEBUG_USART_GPIO_CLK, ENABLE);
    __RCC_BTIM_CLK_ENABLE();
                DEBUG_USART_APBClkENx(DEBUG_USART_CLK, ENABLE);
}


/**
 * [url=home.php?mod=space&uid=247401]@brief[/url] 配置GPIO
 *
 */
void GPIO_Configuration(void)
{
    GPIO_InitTypeDef GPIO_InitStruct;
    RCC_HSI_Enable(RCC_HSIOSC_DIV6);
    __RCC_GPIOB_CLK_ENABLE();
    GPIO_InitStruct.IT = GPIO_IT_NONE;
    GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
    GPIO_InitStruct.Pins = LED_GPIO_PINS;
    GPIO_InitStruct.Speed = GPIO_SPEED_HIGH;
    GPIO_Init(LED_GPIO_PORT, &GPIO_InitStruct);

    __RCC_GPIOA_CLK_ENABLE();
    GPIO_InitStruct.IT = GPIO_IT_NONE;
    GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
    GPIO_InitStruct.Pins = GPIO_PIN_1; // Trig引脚初始化
    GPIO_InitStruct.Speed = GPIO_SPEED_HIGH;
    GPIO_Init(CW_GPIOA, &GPIO_InitStruct);

    GPIO_InitStruct.Pins = GPIO_PIN_2; // Echo引脚初始化
    GPIO_InitStruct.Mode = GPIO_MODE_INPUT_PULLDOWN;
    GPIO_InitStruct.IT   = GPIO_IT_NONE;
    GPIO_Init(CW_GPIOA, &GPIO_InitStruct);
        
           GPIO_InitTypeDef GPIO_InitStructure;
    //UART TX RX 复用
    DEBUG_USART_AFTX;
    DEBUG_USART_AFRX;
    GPIO_InitStructure.Pins = DEBUG_USART_TX_GPIO_PIN;
    GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_PP;
    GPIO_InitStructure.Speed = GPIO_SPEED_HIGH;
    GPIO_Init(DEBUG_USART_TX_GPIO_PORT, &GPIO_InitStructure);
    GPIO_InitStructure.Pins = DEBUG_USART_RX_GPIO_PIN;
    GPIO_InitStructure.Mode = GPIO_MODE_INPUT_PULLUP;
    GPIO_Init(DEBUG_USART_RX_GPIO_PORT, &GPIO_InitStructure);
}

unsigned int Measure_Distance(void) //测距
{
        unsigned int distance=0;
        
        SetTrig();     //10us的脉冲触发信号
        delay10us(1);
        ResetTrig();
        while(ReadEcho() == 0); //等待Echo输出高电平
        time = 0;               //开始记录回波信号脉宽
        while(ReadEcho() == 1); //等待Echo输出低电平           
        distance = time * 1.7;//根据声速和时间计算距离,即distance=time*340/2/100
        /*
                        关于分辨力(mm):
                                        定时器每次对time加1是10us,10us=0.01ms,340m/s=340mm/ms
                                        计算距离时,最小分辨力为:0.01(ms) * 340(mm/ms) / 2 = 1.7(mm)
                                        小于模块标准精度3mm,故测距结果十分精准
        */
        return distance; //返回距离,单位mm
}

在interrupts_cw32f030.c中加入如下代码:

unsigned int time = 0;

/**
 * [url=home.php?mod=space&uid=247401]@brief[/url] This funcation handles BTIM1
 */
void BTIM1_IRQHandler(void)
{
    /* USER CODE BEGIN */
                if(BTIM_GetITStatus(CW_BTIM1,BTIM_IT_OV))  
                {
                        BTIM_ClearITPendingBit(CW_BTIM1,BTIM_IT_OV); //清除标志位
                        time++;
                }
                /* USER CODE END */
}

3.2 LED控制

我们在while循环中不断进行测距工作,当发现测量的距离值小于100mm,就认为有人靠近,从而打开LED灯,否则就关闭LED灯。
代码如下:

  unsigned int distance;
    while (1)
    {
                                distance = Measure_Distance();
                                printf("Distance is : %dmm\r\n", distance);
                          if(distance > 100)
                                {
                                                GPIO_WritePin(LED_GPIO_PORT, LED_GPIO_PINS, GPIO_Pin_RESET);
                                }
                                else
                                {
                                                GPIO_WritePin(LED_GPIO_PORT, LED_GPIO_PINS, GPIO_Pin_SET);
                                }
                                delay1ms(500);
    }

 完整的代码可以点此下载:  hrsr04.zip (1.49 MB)


4. 演示视频

演示视频已经发在B站了:【CW32+超声波传感器实现智能灯控】

CW32+超声波传感器实现智能灯控

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/783998.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Milvus lite start 及存储策略

背景 今天开始写下Milvus,为了方便,我直接使用的是 milvus-lite 版本,default 情况下,你可能不知道他到底将 db 存储到什么位置了。启动 default-server,看下Milvus 的start及存储逻辑 主逻辑 def start(self):sel…

合并pdf的方法,如何合并pdf文件到一个pdf,简单方法

在现代办公和学习中,pdf格式的文件因其跨平台兼容性和安全性得到了广泛应用。然而,有时我们需要将多个pdf文件合并成一个,以便于管理和分享。本文将详细介绍几种合并pdf的方法,帮助读者轻松完成pdf文件的合并工作。 方法一、使用p…

【NLP学习路线的总结】

🎥博主:程序员不想YY啊 💫CSDN优质创作者,CSDN实力新星,CSDN博客专家 🤗点赞🎈收藏⭐再看💫养成习惯 ✨希望本文对您有所裨益,如有不足之处,欢迎在评论区提出指正,让我们共同学习、交流进步! 目录 0. 👉前言1. 👉前置知识👉基础数学知识👉编程语言👉…

matlab:对带参数a关于x的方程求解

题目 讲解 简洁对各个式子的内部含义用浅显易懂的话语总结出来了,耐心体会 f(a) (x)exp(x)x^ax^(sqrt(x))-100;%因为下面的fzero的第一个数需要一个fun,所以这里有两个句柄,第一个a是输入的,第二个x是需要被解出的 A0:0.1:2;%创…

12种增强Python代码的函数式编程技术

前言 什么是函数式编程? 一句话总结:函数式编程(functional programming)是一种编程范式,之外还有面向对象(OOP)、面向过程、逻辑式编程等。 函数式编程是一种高度抽象的编程范式,它倡导使用纯函数&#x…

VTD的RDB介绍,从入门到放弃

文章目录 前言一、二、常见的RDB数据类型1、RDB_OBJECT_STATE_BASE_t2、RDB_OBJECT_STATE_EXT_t3、RDB_OBJECT_STATE_t4、RDB_SENSOR_OBJECT_t5、RDB_COORD_t6 RDB_GEOMETRY_t7、RDB_MSG_ENTRY_HDR_t 三、疑惑的问题点:1、在RDB_OBJECT_STATE_EXT_t中这两个的区别是…

前端面试题26(vue3中响应式实现原理)

Vue 3 中响应式系统的实现主要依赖于 ES6 的 Proxy 对象,这与 Vue 2 中使用 Object.defineProperty 的方式有着本质的区别。Proxy 提供了一种更为强大且灵活的方法来拦截和定制对象的操作,例如获取、设置属性值等。下面是对 Vue 3 响应式系统实现方式的详…

5款好用公司监控软件分享|管理者必看

当今社会,企业数据安全和员工工作效率成为了管理者不可忽视的重要议题。 选择合适的公司监控软件,不仅有助于提升管理效率,还能有效保障企业信息安全。 下面小编将为您分享五款备受好评的公司监控软件,助力管理者更好地管理企业…

faskapi好用的模板

在Web开发领域,FastAPI作为一个基于Python的高性能Web框架,因其快速、易用以及强大的功能而备受开发者青睐。关于FastAPI的好用模板,这里介绍几个不同角度的模板或项目框架,以帮助您更好地理解和选择适合自己的起点。 1. FastAPI…

《基于 Kafka + Flink + ES 实现危急值处理措施推荐和范围校准》

📢 大家好,我是 【战神刘玉栋】,有10多年的研发经验,致力于前后端技术栈的知识沉淀和传播。 💗 🌻 近期刚转战 CSDN,会严格把控文章质量,绝不滥竽充数,欢迎多多交流。&am…

.locked勒索病毒解析与防护指南

引言 随着信息技术的飞速发展,网络安全问题日益严峻,其中勒索病毒成为威胁企业和个人数据安全的重要隐患之一。在众多勒索病毒家族中,.locked勒索病毒以其独特的加密方式和广泛的传播途径,引起了广泛的关注。本文将从多个方面详细…

张量分解(1)——初探张量

🍅 写在前面 👨‍🎓 博主介绍:大家好,这里是hyk写算法了吗,一枚致力于学习算法和人工智能领域的小菜鸟。 🔎个人主页:主页链接(欢迎各位大佬光临指导) ⭐️近…

解决线程不安全问题的几种方式

线程不安全问题 日常生活中我们会经常碰到在不同的平台上买各种票的问题,例如在App、线下售票窗口等购买火车票、电影票。这里面就存在着线程安全的问题,因为当多个线程访问同一个资源时,会导致数据出错,例如甲和乙两人同时看中了…

2024最新版若依-RuoYi-Vue3-PostgreSQL前后端分离项目部署手册教程

项目简介: RuoYi-Vue3-PostgreSQL 是一个基于 RuoYi-Vue3 框架并集成 PostgreSQL 数据库的项目。该项目提供了一套高效的前后端分离的开发解决方案,适用于中小型企业快速构建现代化的企业级应用。此项目结合了 RuoYi-Vue-Postgresql 和 RuoYi-Vue3 的优点&#xff0…

libaom 编码器实验 AV1 标准 SVC 分层编码

SVC编码 视频SVC编码,即Scalable Video Coding(可适性视讯编码或可分级视频编码),是H.264/MPEG-4 AVC编码的一种扩展,它提供了更大的编码弹性,并且具有时间可适性(Temporal Scalability&#x…

React Hooks:上天在提醒你,别再用Class组件了!

React Hooks:上天在提醒你,别再用Class组件了! React Hooks 的出现可以说是前端界的一场革命。它不仅让我们告别了繁琐的 Class 组件,还让代码变得更加简洁、易读、易维护。如果你还在固守 Class 组件的阵地,那么这篇…

vue3项目实战中的接口调用

vue项目组成 一个项目往往由这几个部分组成。👇👇 其中在src文件夹中的内容如下👇👇 我们常常将接口文件,新建在文件夹src下,一般命名为api,api内的文件便是接口文件。👇&#x1f4…

【北京迅为】《i.MX8MM嵌入式Linux开发指南》-第一篇 嵌入式Linux入门篇-

i.MX8MM处理器采用了先进的14LPCFinFET工艺,提供更快的速度和更高的电源效率;四核Cortex-A53,单核Cortex-M4,多达五个内核 ,主频高达1.8GHz,2G DDR4内存、8G EMMC存储。千兆工业级以太网、MIPI-DSI、USB HOST、WIFI/BT…

OpenCV基础(2)

目录 滤波处理 均值滤波 基本原理 函数用法 程序示例 高斯滤波 基本原理 函数用法 程序示例 中值滤波 基本原理 函数用法 程序示例 形态学 腐蚀 膨胀 通用形态学函数 前言:本部分是上一篇文章的延续,前面部分请查看:OpenCV…

MyBatis的底层机制

手写MyBatis底层机制 读取配置文件,得到数据库连接 思路 引入必要的依赖需要写一个自己的config.xml文件,在里面配置一些信息,driver,url ,password,username需要编写Configuration类,对 自己…