NRF51822自学笔记(五)蜂鸣器

  蜂鸣器的资料网上也有很多……这里就简单记录一下……有有源蜂鸣器和无源蜂鸣器两种 这里我用的是无源蜂鸣器的模块 ,自带了放大电路,否则要自己焊一个……

这里我设想的是用不同频率的pwm波驱动蜂鸣器发出不同频率的乐音,对于钢琴上的 CDEFGAB。

  一共搞了两个程序,第一个没有实现功能 ,第二个实现了。

(一)只能输出固定频率可调占空比的pwm波形

nrf_pwm.c

#include "nrf_gpiote.h"
#include "nrf_gpio.h"
#if(USE_WITH_SOFTDEVICE == 1)
#include "nrf_sdm.h"
#endif

static uint32_t pwm_max_value,pwm_next_value[PWM_MAX_CHANNELS], pwm_next_max_value, pwm_io_ch[PWM_MAX_CHANNELS], pwm_running[PWM_MAX_CHANNELS];
static bool pwm_modified[PWM_MAX_CHANNELS];
static uint8_t pwm_gpiote_channel[PWM_MAX_CHANNELS];
static uint32_t pwm_num_channels;
static uint32_t pwm_cc_update_margin_ticks = 10;
static const uint8_t pwm_cc_margin_by_prescaler[] = {80, 40, 20, 10, 5, 2, 1, 1, 1, 1};

#define PWM_TIMER_CURRENT  PWM_TIMER->CC[3]
#define PWM_TIMER2_CURRENT PWM_TIMER2->CC[3]

void PWM_IRQHandler(void);

static void apply_pan73_workaround(NRF_TIMER_Type *timer, bool enable)
{
    if(timer == NRF_TIMER0)
    {
        *(uint32_t *)0x40008C0C = (enable ? 1 : 0);
    }
    else if(timer == NRF_TIMER1)
    {
        *(uint32_t *)0x40009C0C = (enable ? 1 : 0);
    }
    else if(timer == NRF_TIMER2)
    {
        *(uint32_t *)0x4000AC0C = (enable ? 1 : 0);
    }
}

static __INLINE bool safe_margins_present(uint32_t timer_state, uint32_t compare_state)  // Approx runtime ~2us
{
    if(compare_state <= pwm_cc_update_margin_ticks)
    {
        if(timer_state >= compare_state && timer_state < (pwm_max_value + compare_state - pwm_cc_update_margin_ticks)) 
					   return true;
        else return false;
    }
    else
    {
        if(timer_state < (compare_state - pwm_cc_update_margin_ticks) || timer_state >= compare_state) 
					   return true;
				  
        else return false;
    }
}

static void ppi_enable_channel(uint32_t ch_num, volatile uint32_t *event_ptr, volatile uint32_t *task_ptr)
{
    if(ch_num >= 16) return;
    else
    {
#if(USE_WITH_SOFTDEVICE == 1)
        sd_ppi_channel_assign(ch_num, event_ptr, task_ptr);
        sd_ppi_channel_enable_set(1 << ch_num);
#else
        // Otherwise we configure the channel and return the channel number
        NRF_PPI->CH[ch_num].EEP = (uint32_t)event_ptr;
        NRF_PPI->CH[ch_num].TEP = (uint32_t)task_ptr;    
        NRF_PPI->CHENSET = (1 << ch_num);   
#endif
    }
}

#if(USE_WITH_SOFTDEVICE == 1)
nrf_radio_signal_callback_return_param_t *nrf_radio_signal_callback(uint8_t signal_type)
{
    static nrf_radio_signal_callback_return_param_t return_params;
    return_params.callback_action = NRF_RADIO_SIGNAL_CALLBACK_ACTION_END;
    switch(signal_type)
    {
        case NRF_RADIO_CALLBACK_SIGNAL_TYPE_START:            /**< This signal indicates the start of the radio timeslot. */
            PWM_IRQHandler();
            break;
        case NRF_RADIO_CALLBACK_SIGNAL_TYPE_TIMER0:            /**< This signal indicates the NRF_TIMER0 interrupt. */
            break;
        case NRF_RADIO_CALLBACK_SIGNAL_TYPE_RADIO:             /**< This signal indicates the NRF_RADIO interrupt. */
            break;
        case NRF_RADIO_CALLBACK_SIGNAL_TYPE_EXTEND_FAILED:     /**< This signal indicates extend action failed. */
            break;
        case NRF_RADIO_CALLBACK_SIGNAL_TYPE_EXTEND_SUCCEEDED:   /**< This signal indicates extend action succeeded. */
            break;
    }
    return &return_params;
}  
#endif

uint32_t nrf_pwm_init(nrf_pwm_config_t *config)
{
    if(config->num_channels == 0 || config->num_channels > PWM_MAX_CHANNELS) return 0xFFFFFFFF;
    
    switch(config->mode)
    {
        case PWM_MODE_C:   // 8-bit resolution, 520Hz PWM frequency, 1us  1923
            PWM_TIMER->PRESCALER = 4; 
            pwm_max_value = 1923;
				    nrf_pwm_set_value(0, 960);
            break;
        case PWM_MODE_D:   // 8-bit resolution, 585Hz PWM frequency, 1us   1709
            PWM_TIMER->PRESCALER = 4;
            pwm_max_value = 1709;  
				    nrf_pwm_set_value(0, 850);
            break;
        case PWM_MODE_E:  // 0-1000 resolution, 650Hz PWM frequency, 1us   1538
   
  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值