【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+超声波传感器实现智能灯控

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

神一样的老师

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值