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
            PWM_TIMER->PRESCALER = 4;
            pwm_max_value = 1538;
				    nrf_pwm_set_value(0, 765);
            break;
        case PWM_MODE_F:   // 0-100 resolution, 693Hz PWM frequency, 1us
            PWM_TIMER->PRESCALER = 4;
            pwm_max_value = 1443;
				    nrf_pwm_set_value(0, 720);
            break;
        case PWM_MODE_G:    // 8-bit resolution, 780Hz PWM frequency, 1us
            PWM_TIMER->PRESCALER = 4;
            pwm_max_value = 1282;
			     	nrf_pwm_set_value(0, 640);
            break;
        case PWM_MODE_A:  // 8-bit resolution, 867Hz PWM frequency, 1us
            PWM_TIMER->PRESCALER = 4;
            pwm_max_value = 1153;
				    nrf_pwm_set_value(0, 575);
            break;
				case PWM_MODE_B:  // 8-bit resolution, 975Hz PWM frequency, 1us
            PWM_TIMER->PRESCALER = 4;
            pwm_max_value = 1026;
				    nrf_pwm_set_value(0, 510);
            break;
        default:
            return 0xFFFFFFFF;
    }
    pwm_cc_update_margin_ticks = pwm_cc_margin_by_prescaler[PWM_TIMER->PRESCALER];
    pwm_num_channels = config->num_channels;
    for(int i = 0; i < pwm_num_channels; i++)
    {
        pwm_io_ch[i] = (uint32_t)config->gpio_num[i];
        nrf_gpio_cfg_output(pwm_io_ch[i]);
        pwm_running[i] = 0;
        pwm_gpiote_channel[i] = config->gpiote_channel[i];
    }
    PWM_TIMER->TASKS_CLEAR = 1;
    PWM_TIMER->BITMODE = TIMER_BITMODE_BITMODE_16Bit;
    PWM_TIMER->CC[2] = pwm_next_max_value = pwm_max_value;
	  PWM_TIMER->MODE = TIMER_MODE_MODE_Timer;
    PWM_TIMER->SHORTS = TIMER_SHORTS_COMPARE2_CLEAR_Msk;
    PWM_TIMER->EVENTS_COMPARE[0] = PWM_TIMER->EVENTS_COMPARE[1] = PWM_TIMER->EVENTS_COMPARE[2] = PWM_TIMER->EVENTS_COMPARE[3] = 0;     

    if(pwm_num_channels > 2)
    {
        PWM_TIMER2->TASKS_CLEAR = 1;
        PWM_TIMER2->BITMODE = TIMER_BITMODE_BITMODE_16Bit;
        PWM_TIMER2->CC[2] = pwm_next_max_value = pwm_max_value;
        PWM_TIMER2->MODE = TIMER_MODE_MODE_Timer;
        PWM_TIMER2->SHORTS = TIMER_SHORTS_COMPARE2_CLEAR_Msk;
        PWM_TIMER2->EVENTS_COMPARE[0] = PWM_TIMER2->EVENTS_COMPARE[1] = PWM_TIMER2->EVENTS_COMPARE[2] = PWM_TIMER2->EVENTS_COMPARE[3] = 0;
        PWM_TIMER->PRESCALER = PWM_TIMER2->PRESCALER;
    }

    for(int i = 0; i < pwm_num_channels && i < 2; i++)
    {
        ppi_enable_channel(config->ppi_channel[i*2],  &PWM_TIMER->EVENTS_COMPARE[i], &NRF_GPIOTE->TASKS_OUT[pwm_gpiote_channel[i]]);
        ppi_enable_channel(config->ppi_channel[i*2+1],&PWM_TIMER->EVENTS_COMPARE[2], &NRF_GPIOTE->TASKS_OUT[pwm_gpiote_channel[i]]);
        pwm_modified[i] = false;
    }
    for(int i = 2; i < pwm_num_channels; i++)
    {
        ppi_enable_channel(config->ppi_channel[i*2],  &PWM_TIMER2->EVENTS_COMPARE[i-2], &NRF_GPIOTE->TASKS_OUT[pwm_gpiote_channel[i]]);
        ppi_enable_channel(config->ppi_channel[i*2+1],&PWM_TIMER2->EVENTS_COMPARE[2], &NRF_GPIOTE->TASKS_OUT[pwm_gpiote_channel[i]]);
        pwm_modified[i] = false;
    }
#if(USE_WITH_SOFTDEVICE == 1)
    sd_radio_session_open(nrf_radio_signal_callback);
#else
    NVIC_SetPriority(PWM_IRQn, 0);
    NVIC_EnableIRQ(PWM_IRQn);
#endif
    apply_pan73_workaround(PWM_TIMER, true);
    PWM_TIMER->TASKS_START = 1;
    if(pwm_num_channels > 2)
    {
        apply_pan73_workaround(PWM_TIMER2, true);
        PWM_TIMER2->TASKS_START = 1;
    }
    return 0;
}

void nrf_pwm_set_value(uint32_t pwm_channel, uint32_t pwm_value)
{
    pwm_next_value[pwm_channel] = pwm_value;
    pwm_modified[pwm_channel] = true;
#if(USE_WITH_SOFTDEVICE == 1)
    nrf_radio_request_t radio_request;
    radio_request.request_type = NRF_RADIO_REQ_TYPE_EARLIEST;
    radio_request.params.earliest.hfclk = NRF_RADIO_HFCLK_CFG_DEFAULT;
    radio_request.params.earliest.length_us = 250;
    radio_request.params.earliest.priority = NRF_RADIO_PRIORITY_HIGH;
    radio_request.params.earliest.timeout_us = 100000;
    sd_radio_request(&radio_request);
#else
    NVIC_SetPendingIRQ(PWM_IRQn);
#endif
}

void nrf_pwm_set_values(uint32_t pwm_channel_num, uint32_t *pwm_values)
{
    for(int i = 0; i < pwm_channel_num; i++)
    {
        pwm_next_value[i] = pwm_values[i];
        pwm_modified[i] = true;
    }
#if(USE_WITH_SOFTDEVICE == 1)
    nrf_radio_request_t radio_request;
    radio_request.request_type = NRF_RADIO_REQ_TYPE_EARLIEST;
    radio_request.params.earliest.hfclk = NRF_RADIO_HFCLK_CFG_DEFAULT;
    radio_request.params.earliest.length_us = 250;
    radio_request.params.earliest.priority = NRF_RADIO_PRIORITY_HIGH;
    radio_request.params.earliest.timeout_us = 100000;
    sd_radio_request(&radio_request);
#else
    NVIC_SetPendingIRQ(PWM_IRQn);
#endif
}

void nrf_pwm_set_max_value(uint32_t max_value)
{
    pwm_next_max_value = max_value;
}

void nrf_pwm_set_enabled(bool enabled)
{
    if(enabled)
    {
        PWM_TIMER->TASKS_START = 1;
        if(pwm_num_channels > 2) PWM_TIMER2->TASKS_START = 1;
    }
    else
    {
        PWM_TIMER->TASKS_STOP = 1;
        if(pwm_num_channels > 2) PWM_TIMER2->TASKS_STOP = 1;
        for(uint32_t i = 0; i < pwm_num_channels; i++)
        {
            nrf_gpiote_unconfig(pwm_gpiote_channel[i]);
            nrf_gpio_pin_write(pwm_io_ch[i], 0);
            pwm_running[i] = 0;
        }
    }
}

void PWM_IRQHandler(void)
{
    static uint32_t i, new_capture, old_capture;
    PWM_TIMER->CC[2] = pwm_max_value = pwm_next_max_value;
    if(pwm_num_channels > 2) PWM_TIMER2->CC[2] = pwm_max_value;
    for(i = 0; i < pwm_num_channels; i++)
    {
        if(pwm_modified[i])
        {
            pwm_modified[i] = false;
            if(pwm_next_value[i] == 0)
            {
                nrf_gpiote_unconfig(pwm_gpiote_channel[i]);
                nrf_gpio_pin_write(pwm_io_ch[i], 0);
                pwm_running[i] = 0;
            }
            else if (pwm_next_value[i] >= pwm_max_value)
            {
                nrf_gpiote_unconfig(pwm_gpiote_channel[i]);
                nrf_gpio_pin_write(pwm_io_ch[i], 1);
                pwm_running[i] = 0;
            }
            else
            {
                if(i < 2)
                {
                    new_capture = pwm_next_value[i];
                    old_capture = PWM_TIMER->CC[i];
                    if(!pwm_running[i])
                    {
                        nrf_gpiote_task_config(pwm_gpiote_channel[i], pwm_io_ch[i], NRF_GPIOTE_POLARITY_TOGGLE, NRF_GPIOTE_INITIAL_VALUE_HIGH);
                        pwm_running[i] = 1;
                        PWM_TIMER->TASKS_CAPTURE[3] = 1;
                        if(PWM_TIMER->CC[3] > new_capture) NRF_GPIOTE->TASKS_OUT[pwm_gpiote_channel[i]] = 1;
                        PWM_TIMER->CC[i] = new_capture;
                    }
                    else
                    {
                        while(1)
                        {
                            PWM_TIMER->TASKS_CAPTURE[3] = 1;
                            if(safe_margins_present(PWM_TIMER_CURRENT, old_capture) && safe_margins_present(PWM_TIMER_CURRENT, new_capture)) break;
                        }
                        if((PWM_TIMER_CURRENT >= old_capture && PWM_TIMER_CURRENT < new_capture) || (PWM_TIMER_CURRENT < old_capture && PWM_TIMER_CURRENT >= new_capture))
                        {
                            NRF_GPIOTE->TASKS_OUT[pwm_gpiote_channel[i]] = 1;
                        }
                        PWM_TIMER->CC[i] = new_capture;
                    }
                }
                else
                {
                    new_capture = pwm_next_value[i];
                    old_capture = PWM_TIMER2->CC[i-2];
                    if(!pwm_running[i])
                    {
                        nrf_gpiote_task_config(pwm_gpiote_channel[i], pwm_io_ch[i], NRF_GPIOTE_POLARITY_TOGGLE, NRF_GPIOTE_INITIAL_VALUE_HIGH);
                        pwm_running[i] = 1;
                        PWM_TIMER2->TASKS_CAPTURE[3] = 1;
                        if(PWM_TIMER2->CC[3] > new_capture) NRF_GPIOTE->TASKS_OUT[pwm_gpiote_channel[i]] = 1;
                        PWM_TIMER2->CC[i-2] = new_capture;
                    }
                    else
                    {
                        while(1)
                        {
                            PWM_TIMER2->TASKS_CAPTURE[3] = 1;
                            if(safe_margins_present(PWM_TIMER2_CURRENT, old_capture) && safe_margins_present(PWM_TIMER2_CURRENT, new_capture)) break;
                        }
                        if((PWM_TIMER2_CURRENT >= old_capture && PWM_TIMER2_CURRENT < new_capture) || (PWM_TIMER2_CURRENT < old_capture && PWM_TIMER2_CURRENT >= new_capture))
                        {
                            NRF_GPIOTE->TASKS_OUT[pwm_gpiote_channel[i]] = 1;
                        }
                        PWM_TIMER2->CC[i-2] = new_capture;
                    }
                }
            }
        }
    }
}

main.c

#include <stdbool.h>
#include <stdint.h>
#include "nrf.h"
#include "nrf_gpio.h"
#include "nrf_delay.h"
#include "nrf_pwm.h"
#include "boards.h"

#define FREQ_HALF_NOTE_FACTOR 1.059463f
nrf_pwm_config_t pwm_config = PWM_DEFAULT_CONFIG; 

void pwm_init(nrf_pwm_mode_t nrf_pwm_mode)
{
    pwm_config.mode             = nrf_pwm_mode;
    // Initialize the PWM library
    nrf_pwm_init(&pwm_config);
	  nrf_delay_ms(300);
}

int main(void)
{

	  pwm_config.num_channels     = 1;
    pwm_config.gpio_num[0]      = 7;

    // Start the external 16 MHz clock for a more accurate PWM frequency
    NRF_CLOCK->TASKS_HFCLKSTART = 1;

    //pwm_init(PWM_MODE_C);

    while (true)
    {
			pwm_init(PWM_MODE_C);
			pwm_init(PWM_MODE_D);
			pwm_init(PWM_MODE_E);
			pwm_init(PWM_MODE_F);
			pwm_init(PWM_MODE_G);
			pwm_init(PWM_MODE_A);
			pwm_init(PWM_MODE_B);
    }
}

仿真一下发现,出现的波形前后只会有占空比的不同,频率是相同的。。这里为了方便看  用了四个通道

若把分频改成-->5,则之后出现的波形频率都是5分频,更改最大值的话 则还是依从配置的所有最大值里最大的一个……出波形……很神奇

(二)频率可调的pwm控制蜂鸣器发出乐音

#include <stdbool.h>
#include <stdint.h>
#include "nrf.h"
#include "nrf_assert.h"
#include "nrf_gpiote.h"
#include "nrf_gpio.h"
#include "boards.h"
#include "nrf_delay.h"

#define PWM_OUTPUT_PIN_NUMBER  7 /**< Pin number for PWM output. */

unsigned long MAX_SAMPLE_LEVELS = 1923;   /**< Maximum number of sample levels. */

#define TIMER_PRESCALERS 4U           /**< Prescaler setting for timer. */

/** @brief Function for getting the next sample.
 *  @return sample_value computed sample.
 */
static __INLINE uint32_t next_sample_get(void)
{
    static uint32_t sample_value = 8;

    // Read button input.
    sample_value = (~NRF_GPIO->IN & 0x000000FFUL);

    // This is to avoid having two CC events happen at the same time,
    // CC1 will always create an event on 0 so CC0 and CC2 should not.
    if (sample_value == 0)
    {
        sample_value = 8;
    }

    return (uint32_t)sample_value;
}

/** @brief Function for handling timer 2 peripheral interrupts.
 */
void TIMER2_IRQHandler(void)
{
    static bool cc0_turn = false; /**< Keeps track of which CC register to be used. */

    if ((NRF_TIMER2->EVENTS_COMPARE[1] != 0) &&
       ((NRF_TIMER2->INTENSET & TIMER_INTENSET_COMPARE1_Msk) != 0))
    {
        // Sets the next CC1 value
        NRF_TIMER2->EVENTS_COMPARE[1] = 0;
        NRF_TIMER2->CC[1]             = (NRF_TIMER2->CC[1] + MAX_SAMPLE_LEVELS);

        // Every other interrupt CC0 and CC2 will be set to their next values.
        uint32_t next_sample = next_sample_get();

        if (cc0_turn)
        {
            NRF_TIMER2->CC[0] = NRF_TIMER2->CC[1] + MAX_SAMPLE_LEVELS*0.5;  //duty
        }
        else
        {
            NRF_TIMER2->CC[2] = NRF_TIMER2->CC[1] + MAX_SAMPLE_LEVELS*0.5;  //duty
        }
        // Next turn the other CC will get its value.
        cc0_turn = !cc0_turn;
    }
}

/** @brief Function for initializing the Timer 2 peripheral.
 */
static void timer2_init(void)
{
    // Start 16 MHz crystal oscillator .
    NRF_CLOCK->EVENTS_HFCLKSTARTED  = 0;
    NRF_CLOCK->TASKS_HFCLKSTART     = 1;

    // Wait for the external oscillator to start up.
    while (NRF_CLOCK->EVENTS_HFCLKSTARTED == 0)
    {
        //Do nothing.
    }

    NRF_TIMER2->MODE        = TIMER_MODE_MODE_Timer;
    NRF_TIMER2->BITMODE     = TIMER_BITMODE_BITMODE_16Bit << TIMER_BITMODE_BITMODE_Pos;
    NRF_TIMER2->PRESCALER   = TIMER_PRESCALERS;

    // Clears the timer, sets it to 0.
    NRF_TIMER2->TASKS_CLEAR = 1;

    // Load the initial values to TIMER2 CC registers.
    NRF_TIMER2->CC[0] = MAX_SAMPLE_LEVELS + next_sample_get();
    NRF_TIMER2->CC[1] = MAX_SAMPLE_LEVELS;

    // CC2 will be set on the first CC1 interrupt.
    NRF_TIMER2->CC[2] = 0;

    // Interrupt setup.
    NRF_TIMER2->INTENSET = (TIMER_INTENSET_COMPARE1_Enabled << TIMER_INTENSET_COMPARE1_Pos);
}

/** @brief Function for initializing the GPIO Tasks/Events peripheral.
 */
static void gpiote_init(void)
{
    // Connect GPIO input buffers and configure PWM_OUTPUT_PIN_NUMBER as an output.
    nrf_gpio_range_cfg_input(BUTTON_START, BUTTON_STOP, NRF_GPIO_PIN_NOPULL);
    nrf_gpio_cfg_output(PWM_OUTPUT_PIN_NUMBER);

    NRF_GPIO->OUT = 0x00000000UL;

    // Configure GPIOTE channel 0 to toggle the PWM pin state
	// @note Only one GPIOTE task can be connected to an output pin.
    nrf_gpiote_task_config(0, PWM_OUTPUT_PIN_NUMBER,                            NRF_GPIOTE_POLARITY_TOGGLE, NRF_GPIOTE_INITIAL_VALUE_LOW);
}

/** @brief Function for initializing the Programmable Peripheral Interconnect peripheral.
 */
static void ppi_init(void)
{
    // Configure PPI channel 0 to toggle PWM_OUTPUT_PIN on every TIMER2 COMPARE[0] match.
    NRF_PPI->CH[0].EEP = (uint32_t)&NRF_TIMER2->EVENTS_COMPARE[0];
    NRF_PPI->CH[0].TEP = (uint32_t)&NRF_GPIOTE->TASKS_OUT[0];

    // Configure PPI channel 1 to toggle PWM_OUTPUT_PIN on every TIMER2 COMPARE[1] match.
    NRF_PPI->CH[1].EEP = (uint32_t)&NRF_TIMER2->EVENTS_COMPARE[1];
    NRF_PPI->CH[1].TEP = (uint32_t)&NRF_GPIOTE->TASKS_OUT[0];

    // Configure PPI channel 1 to toggle PWM_OUTPUT_PIN on every TIMER2 COMPARE[2] match.
    NRF_PPI->CH[2].EEP = (uint32_t)&NRF_TIMER2->EVENTS_COMPARE[2];
    NRF_PPI->CH[2].TEP = (uint32_t)&NRF_GPIOTE->TASKS_OUT[0];

    // Enable PPI channels 0-2.
    NRF_PPI->CHEN = (PPI_CHEN_CH0_Enabled << PPI_CHEN_CH0_Pos)
                    | (PPI_CHEN_CH1_Enabled << PPI_CHEN_CH1_Pos)
                    | (PPI_CHEN_CH2_Enabled << PPI_CHEN_CH2_Pos);
}

/**
 * @brief Function for application main entry.
 */
int main(void)
{
    gpiote_init();
    ppi_init();
    timer2_init();

    // Enabling constant latency as indicated by PAN 11 "HFCLK: Base current with HFCLK
    // running is too high" found at Product Anomaly document found at
    // https://www.nordicsemi.com/eng/Products/Bluetooth-R-low-energy/nRF51822/#Downloads
    //
    // @note This example does not go to low power mode therefore constant latency is not needed.
    //       However this setting will ensure correct behaviour when routing TIMER events through
    //       PPI (shown in this example) and low power mode simultaneously.
    NRF_POWER->TASKS_CONSTLAT = 1;

    // Enable interrupt on Timer 2.
    NVIC_EnableIRQ(TIMER2_IRQn);
    __enable_irq();

    // Start the timer.
    NRF_TIMER2->TASKS_START = 1;

    while (true)
    {
      MAX_SAMPLE_LEVELS = 1923;
			nrf_delay_ms(200);
			MAX_SAMPLE_LEVELS = 1709;
			nrf_delay_ms(200);
			MAX_SAMPLE_LEVELS = 1538;
			nrf_delay_ms(200);
			MAX_SAMPLE_LEVELS = 1443;
			nrf_delay_ms(200);
			MAX_SAMPLE_LEVELS = 1282;
			nrf_delay_ms(200);
			MAX_SAMPLE_LEVELS = 1153;
			nrf_delay_ms(200);
			MAX_SAMPLE_LEVELS = 1026;
			nrf_delay_ms(200);
    }
}
时间: 2024-12-25 01:17:59

nrf51822自学笔记(五)蜂鸣器的相关文章

NRF51822自学笔记(一) 流水灯

最近在学nrf51822这个板子,下载程序点灯啥的零零碎碎弄了一天……例程blinky_example中包含了gpio.h和delay.c 看main.c之前我先看了这两个,例程里应用了一个简单不精确的延时函数,用循环内延时微秒函数实现延时毫秒,挺有意思的…… void nrf_delay_ms(uint32_t volatile number_of_ms) { while(number_of_ms != 0) { number_of_ms--; nrf_delay_us(999); } } v

NRF51822自学笔记(二)PWM

PWM这个东西我在32上用来电机调速过……通过改变高低电平占空比来实现一些功能. keil的nrf51822目录下没有pwm.c..就在网上找了个pwm蜂鸣器的例程……看画风应该是官方的……吧…… 例程的define为NRF51 SETUPA BOARD_PCA10028..修改一下,设置如下. 然后通过两个灯来实现一下两路pwm波……pin为20和21的LED_2和LED_3 先看main.c(非例程) [cpp] view plain copy print? #include <stdboo

CSS自学笔记(5):CSS的样式

CSS中拥有各种各样的样式表,而基本的样式有背景,文本,字体,链接,列表,表格,轮廓. 一.CSS-背景 CSS中允许用纯色背景,也允许用图片来创建复杂的个性背景. p {background-color: #000;} 是用纯色作为背景.这时你可以定义其他属性,生成不同效果的背景. CSS中也可以用图片作为背景,这是就需要使用background-image属性了,如果属性值为一个URL值,并且图片文件存在,那么就可以看到用该图片做为背景的网页了 body {background-image:

qml自学笔记------自己写相似于劲舞团的按键小游戏(中)

接上篇<qml自学笔记------自己写类似于劲舞团的按键小游戏(上)> 第三部分DisplayPart.qml 代码的其它部分都是渣,就这里花了点时间,整个小游戏就靠这个文件. 首先,屏幕上要随机的滑过空格或者箭头,每个图片就是一个项目,那么就要动态的创建项目. 动态创建项目方法有三种(我所知道的),第一种是通过JavaScript调用Qt.createComponent(),Qt.createQmlObject()来创建对象,这里要注意的是创建时必须传父对象,由于图形项目没有父对象是无法显

qml自学笔记------自己写类似于劲舞团的按键小游戏(中)

接上篇<qml自学笔记------自己写类似于劲舞团的按键小游戏(上)> 第三部分DisplayPart.qml 代码的其他部分都是渣,就这里花了点时间,整个小游戏就靠这个文件. 首先,屏幕上要随机的滑过空格或者箭头,每一个图片就是一个项目,那么就要动态的创建项目.动态创建项目方法有三种(我所知道的),第一种是通过JavaScript调用Qt.createComponent(),Qt.createQmlObject()来创建对象,这里要注意的是创建时必须传父对象,因为图形项目没有父对象是无法显

Log4j自学笔记

log4j十一个开源的日志记录组件,在工程中用于代替System.out语句.它允许开发人员以任意的精细程度控制哪些日志说明被输出,通过使用外部的配置文件,可以在运行的时候配置它.Log4jPO有三个主要的组件:Loggers(记录器).Appenders(输出源).Layout(布局),可以简单的理解为日志类别,日志要输的地方.输出的格式. Loggers组件在此系统中被分为五个级别:DEBUG<INFO<WARN<ERROR<FATAL.这五个级别是有顺序的.DEBUG Log

Caliburn.Micro学习笔记(五)----协同IResult

Caliburn.Micro学习笔记(五)----协同IResult 今天说一下协同IResult 看一下IResult接口 /// <summary> /// Allows custom code to execute after the return of a action. /// </summary> public interface IResult { /// <summary> /// Executes the result using the specif

斯坦福大学机器学习(Andrew [email&#160;protected])--自学笔记

今天学习Andrew NG老师<机器学习>之6 - 6 - Advanced Optimization,做笔记如下: 用fminunc函数求代价函数最小值,分两步: 1.自定义代价函数 function [jVal,gradient] = costFunction(theta)jVal = (theta(1)-5)^2 + (theta(2)-5)^2;gradient = zeros(2,1);gradient(1) = 2*(theta(1)-5);gradient(2) = 2*(the

5. 蛤蟆的计算机组成原理笔记五输入输出系统

5. 蛤蟆的计算机组成原理笔记五输入输出系统 本篇名言:"质朴却比巧妙的言辞更能打动我的心. --莎士比亚" 欢迎转载,转载请标明出:http://blog.csdn.net/notbaron/article/details/48037245 1.  输入输出系统 1.1             I/O 软件 (1) I/O 指令 CPU 指令的一部分 (2) 通道指令 通道自身的指令 1.2             I/O设备与主机信息传送的控制方式 1. 程序查询方式 2. 程序中