顯示具有 nRF52832 標籤的文章。 顯示所有文章
顯示具有 nRF52832 標籤的文章。 顯示所有文章

2018年5月9日 星期三

如何取消Nordic nRF52系列廣播的Timeout功能

如何取消BLE廣播的Timeout功能?讓BLE裝置一直都可以被搜尋到。 以nRF5-SDK-15.0.0的ble_app_uart的範例程式。廣播初時化設定,如下函式。

static void advertising_init(void)
{
uint32_t err_code;
ble_advertising_init_t init;

memset(&init, 0, sizeof(init));

init.advdata.name_type = BLE_ADVDATA_FULL_NAME;
init.advdata.include_appearance = false;
init.advdata.flags = BLE_GAP_ADV_FLAGS_LE_ONLY_LIMITED_DISC_MODE;

init.srdata.uuids_complete.uuid_cnt = sizeof(m_adv_uuids) / sizeof(m_adv_uuids[0]);
init.srdata.uuids_complete.p_uuids = m_adv_uuids;

init.config.ble_adv_fast_enabled = true ;
init.config.ble_adv_fast_interval = APP_ADV_INTERVAL;
init.config.ble_adv_fast_timeout = APP_ADV_DURATION;
init.evt_handler = on_adv_evt;

err_code = ble_advertising_init(&m_advertising, &init);
APP_ERROR_CHECK(err_code);

ble_advertising_conn_cfg_tag_set(&m_advertising, APP_BLE_CONN_CFG_TAG);
}
只要修改兩個地方,廣播Timeout的功能就可以拿掉。如下
 init.advdata.flags = BLE_GAP_ADV_FLAGS_LE_ONLY_GENERAL_DISC_MODE; init.config.ble_adv_fast_timeout = 0 ;
 完整advertising_init()如下,

static void advertising_init(void)
{
uint32_t err_code;
ble_advertising_init_t init;

memset(&init, 0, sizeof(init));

init.advdata.name_type = BLE_ADVDATA_FULL_NAME;
init.advdata.include_appearance = false;
init.advdata.flags = BLE_GAP_ADV_FLAGS_LE_ONLY_GENERAL_DISC_MODE;

init.srdata.uuids_complete.uuid_cnt = sizeof(m_adv_uuids) / sizeof(m_adv_uuids[0]);
init.srdata.uuids_complete.p_uuids = m_adv_uuids;

init.config.ble_adv_fast_enabled = true ;
init.config.ble_adv_fast_interval = APP_ADV_INTERVAL;
init.config.ble_adv_fast_timeout = 0 ; //APP_ADV_DURATION;
init.evt_handler = on_adv_evt;

err_code = ble_advertising_init(&m_advertising, &init);
APP_ERROR_CHECK(err_code);

ble_advertising_conn_cfg_tag_set(&m_advertising, APP_BLE_CONN_CFG_TAG);
}
#CSR #CSR8635 #藍芽 #藍芽立體聲喇叭 #電子外包 #PCB LAYOUT #電子設計 #學生專題製作#電路設計 #數位線路 #類比線路 #單晶片程式設計

2018年4月16日 星期一

Nordic nRF52832 DFU介紹

什麼是DFU?就是Device Firmware Update 。Nordic提供nRF Toolbox APP可以在Play商店下載。可以經由over-the-air(OTA)方式來更新程式。
Screenshot_20180222-131341
如何讓你裝置有DFU功能?可以分成三個部份。
1.先修改Bootloader程式,因為有專屬private key
2.燒錄檔.hex轉成.zip
3.利用nRF Toolbox的DFU來更新程式
Bootloader程式,請參考nRF5-SDK-zip 的examples/duf/bootloader_secure_ble的範例。我是用Keil去編譯,出現錯誤,如下。
dfu-1
顯示錯誤訊息如下
#error “Debug public key not valid for production. Please see https://github.com/NordicSemiconductor/pc-nrfutil/blob/master/README.md to generate it"
點選以上網址,根據網頁內容步驟去執行,步驟如下。
1.下載pc-nrfutil 的檔案。
3.安裝pip
4.在Windows系統,新增環境變數內系統變數的Path路徑如下。
C:\Python27\Scripts;C:\Python27\;
5.接下來的指令都是在DOS畫面下執行,請在開始的搜尋檔案處,打上cmd,就會出現如下圖示。
dos
6.Installing from PyPi ,請在DOS畫面輸入以下指令
pip install nrfutil
7.PyInstall,請在DOS畫面輸入以下指令
pip install pyinstaller
8.在DOS畫面,跳到下載pc-nrfutil檔案的pc-nrfutil-master資料夾下,執行以下的指令
pip install -r requirements.txt
python nordicsemi/__main__.py
python setup.py install
pyinstaller nrfutil.spec
9.產生key.pem,請在DOS畫面輸入以下指令,請把key.pem存到pc-nrfutil-master\nordicsemi\dfu\tests下。
nrfutil keys generate key.pem
10.把key.pem轉換成code ,請在DOS畫面輸入以下指令。把code如下圖紅色框框,複蓋到SDK的dfu_public_key.c
nrfutil keys display --key pk --format code key.pem
keypem
11.Keil編譯應該就可以成功了。
12.利用nRFgo Studio軟體把.hex燒錄到板子上,先燒錄SoftDevice,再燒錄Application,最後才燒錄Bootlader。這樣機板就有DFU功能。
13.把.hex轉成.zip檔案,請在DOS畫面輸入以下指令,選用nRF52xxx系列–hw-version 就填52,--sd-req 請參考下圖,--application填寫要燒錄的檔案名稱,--key-file key.pem就是dfu_public_key.c,不同key.pem就無法DFU,這一點要特別注意。app_dfu_package.zip是你要轉出的.zip檔案,名稱可以自訂。
nrfutil pkg generate --hw-version 52 --sd-req 0x9D --application-version 4 --application app.hex --key-file key.pem app_dfu_package.zip
SoftDevice
14.打開手機的nRF Toolbox APP,選擇DFU,把app_dfu_package.zip上傳到手機,選擇藍芽裝置,就可以更新程式了。
PS.  藍芽裝置要先進入Bootloader才可以DFU,藍芽裝置按住按鍵再上電就可以進入Bootloader。
#CSR #CSR8635 #藍芽 #藍芽立體聲喇叭 #電子外包 #PCB LAYOUT #電子設計 #學生專題製作#電路設計 #數位線路 #類比線路 #單晶片程式設計

2018年4月13日 星期五

Nordic nRF52832 Timer程式介紹

#include <stdbool.h>
#include <stdint.h>
#include "nrf.h"
#include "nrf_drv_timer.h"
#include "bsp.h"
#include "app_error.h"

const nrf_drv_timer_t TIMER_LED = NRF_DRV_TIMER_INSTANCE(0);

/**
 * @brief Handler for timer events.
 */
void timer_led_event_handler(nrf_timer_event_t event_type, void* p_context)
{
    static uint32_t i;
    uint32_t led_to_invert = ((i++) % LEDS_NUMBER);

    switch (event_type)
    {
        case NRF_TIMER_EVENT_COMPARE0:
            bsp_board_led_invert(led_to_invert);  
            break;

        default:
            //Do nothing.
            break;
    }
}

/**
 * @brief Function for main application entry.
 */
int main(void)
{
    uint32_t time_ms = 500; //Time(in miliseconds) between consecutive compare events.
    uint32_t time_ticks;
    uint32_t err_code = NRF_SUCCESS;

    //Configure all leds on board.
    bsp_board_leds_init();
 
    //Configure TIMER_LED for generating simple light effect - leds on board will invert his state one after the other.
    nrf_drv_timer_config_t timer_cfg = NRF_DRV_TIMER_DEFAULT_CONFIG;
    err_code = nrf_drv_timer_init(&TIMER_LED, &timer_cfg, timer_led_event_handler);
    APP_ERROR_CHECK(err_code);

    time_ticks = nrf_drv_timer_ms_to_ticks(&TIMER_LED, time_ms);

    nrf_drv_timer_extended_compare(
         &TIMER_LED, NRF_TIMER_CC_CHANNEL0, time_ticks, NRF_TIMER_SHORT_COMPARE0_CLEAR_MASK, true);

    nrf_drv_timer_enable(&TIMER_LED);

    while (1)
    {
        __WFI();
    }
}
const nrf_drv_timer_t TIMER_LED = NRF_DRV_TIMER_INSTANCE(0);設定為Timer0。
void timer_led_event_handler(nrf_timer_event_t event_type, void* p_context);Timer中斷副程式。
nrf_drv_timer_config_t timer_cfg = NRF_DRV_TIMER_DEFAULT_CONFIG;設定為default config。
nrf_drv_timer_init(&TIMER_LED, &timer_cfg, timer_led_event_handler);Timer初時化設定及中斷副程式。
nrf_drv_timer_ms_to_ticks(&TIMER_LED, time_ms);中斷時間轉為ticks.
nrf_drv_timer_extended_compare( &TIMER_LED, NRF_TIMER_CC_CHANNEL0, time_ticks, NRF_TIMER_SHORT_COMPARE0_CLEAR_MASK, true);
nrf_drv_timer_enable(&TIMER_LED);Timer啟動
此程式每500ms產生中斷,程式會跳到void timer_led_event_handler(nrf_timer_event_t event_type, void* p_context)去執行LED控制。




#CSR #CSR8635 #藍芽 #藍芽立體聲喇叭 #電子外包 #PCB LAYOUT #電子設計 #學生專題製作#電路設計

2018年4月11日 星期三

Nordic nRF52832 PWM Library介紹

#include "nrf.h"
#include "app_error.h"
#include "bsp.h"
#include "app_pwm.h"
#include "nrf_delay.h"

APP_PWM_INSTANCE(PWM0,0); // Create the instance "PWM0" using TIMER0.
void pwm_ready_callback(uint32_t pwm_id)    // PWM callback function
{
    ready_flag = true;
}
int main(void)
{
 ret_code_t err_code;
 
 /* 2-channel PWM, 1000Hz, output on p0.17 & p0.18 */
        app_pwm_config_t pwm0_cfg = APP_PWM_DEFAULT_CONFIG_2CH(1000L, 17, 18);
 
 /* Switch the polarity of the second channel. */
 pwm0_cfg.pin_polarity[0] = APP_PWM_POLARITY_ACTIVE_HIGH;
 pwm0_cfg.pin_polarity[1] = APP_PWM_POLARITY_ACTIVE_LOW;
 
 app_pwm_init(&PWM0,&pwm0_cfg,pwm_ready_callback);
 app_pwm_enable(&PWM0);
 
 ready_flag = false;
 while (app_pwm_channel_duty_set(&PWM0, 0, 0) == NRF_ERROR_BUSY);
 while (!ready_flag);
 ready_flag = false;
 while (app_pwm_channel_duty_set(&PWM0, 1, 0) == NRF_ERROR_BUSY);
 while (!ready_flag);
 
 uint32_t value;
        while (true)
        {
            for (uint8_t i = 0; i < 40; ++i)
            {
            value = (i < 20) ? (i * 5) : (100 - (i - 20) * 5);

            ready_flag = false;
            // Set the duty cycle - keep trying until PWM is ready... 
            while (app_pwm_channel_duty_set(&PWM0, 0, value) == NRF_ERROR_BUSY);

            // ... or wait for callback. 
            while (!ready_flag);
            APP_ERROR_CHECK(app_pwm_channel_duty_set(&PWM0, 1, value));
            nrf_delay_ms(25);
            }
        }
}
函式APP_PWM_INSTANCE(PWM0,0) ;是指PWM0模組時序是TIMER0。
函式APP_PWM_DEFAULT_CONFIG_2CH(1000L, 17, 18);PWM模組有兩個頻道輸出,為channel0為P0.17,channel1為P0.18,頻率為1000Hz。
pwm0_cfg.pin_polarity[0] = APP_PWM_POLARITY_ACTIVE_HIGH;
channel0 的PWM POLARITY為High。
pwm0_cfg.pin_polarity[1] = APP_PWM_POLARITY_ACTIVE_LOW;
channel1 的PWM POLARITY為Low。
函式app_pwm_init(&PWM0,&pwm0_cfg,pwm_ready_callback);PWM0初時化設定及設定callback函式。
函式app_pwm_enable(&PWM0);啟動PWM0
函式app_pwm_channel_duty_set(&PWM0, 0, value);channel0 pwm duty設定,value為0~100。

2018年4月9日 星期一

Nordic nRF52832 PWM driver程式介紹

nRF52832 有三個PWM模組,每個模組有4各channels,所以總共有12各channels可以使用,每支GPIO都可以設定為PWM。以下圖是PWM模組的方塊圖。
PWM 方塊圖
Wave Counter有兩種模式,分別為PWM up counter與PWM up and down counter。主要是產生duty-cycle pulses,如下兩圖示。
PWM up counter
PWM up and down counter
Decoder with EasyDMA,分成四種模式Common、Grouped、Single、WaveForm,如下圖示。
Decoder
以下是SDK的PWM範例程式
static void demo5(void)
{
    NRF_LOG_INFO("Demo 5");

    /*
     * This demo, similarly to demo1, plays back a sequence with different
     * values for individual channels. Unlike demo 1, however, it does not use
     * an event handler. Therefore, the PWM peripheral does not use interrupts
     * and the CPU can stay in sleep mode.
     * The LEDs (1-4) blink separately. They are turned on for 125 ms each,
     * in counterclockwise order (looking at the board).
     */

    nrf_drv_pwm_config_t const config0 =
    {
        .output_pins =
        {
            BSP_LED_0 | NRF_DRV_PWM_PIN_INVERTED, // channel 0
            BSP_LED_2 | NRF_DRV_PWM_PIN_INVERTED, // channel 1
            BSP_LED_3 | NRF_DRV_PWM_PIN_INVERTED, // channel 2
            BSP_LED_1 | NRF_DRV_PWM_PIN_INVERTED  // channel 3
        },
        .irq_priority = APP_IRQ_PRIORITY_LOWEST,
        .base_clock   = NRF_PWM_CLK_125kHz,
        .count_mode   = NRF_PWM_MODE_UP,
        .top_value    = 15625,
        .load_mode    = NRF_PWM_LOAD_INDIVIDUAL,
        .step_mode    = NRF_PWM_STEP_AUTO
    };
    APP_ERROR_CHECK(nrf_drv_pwm_init(&m_pwm0, &config0, NULL));
    m_used |= USED_PWM(0);

    // This array cannot be allocated on stack (hence "static") and it must
    // be in RAM (hence no "const", though its content is not changed).
    static nrf_pwm_values_individual_t /*const*/ seq_values[] =
    {
        { 0x8000,      0,      0,      0 },
        {      0, 0x8000,      0,      0 },
        {      0,      0, 0x8000,      0 },
        {      0,      0,      0, 0x8000 }
    };
    nrf_pwm_sequence_t const seq =
    {
        .values.p_individual = seq_values,
        .length              = NRF_PWM_VALUES_LENGTH(seq_values),
        .repeats             = 0,
        .end_delay           = 0
    };

    (void)nrf_drv_pwm_simple_playback(&m_pwm0, &seq, 1, NRF_DRV_PWM_FLAG_LOOP);
}
PWM範例程式參數設定介紹
.output_pins 設定4組PWM channel的輸出PIN。
.base_clock設定基頻,NRF_PWM_CLK_16MHz、NRF_PWM_CLK_8MHz、NRF_PWM_CLK_4MHz、NRF_PWM_CLK_2MHz、NRF_PWM_CLK_1MHz、NRF_PWM_CLK_500kHz、NRF_PWM_CLK_250kHz、NRF_PWM_CLK_125kHz。可設定這8種頻率。
.count_mode設定Wave Counter模式,NRF_PWM_MODE_UP、NRF_PWM_MODE_UP_AND_DOWN。