Chinaunix首页 | 论坛 | 博客

fx

  • 博客访问: 1372961
  • 博文数量: 115
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 3964
  • 用 户 组: 普通用户
  • 注册时间: 2013-05-02 14:36
文章分类
文章存档

2022年(2)

2019年(2)

2018年(10)

2017年(1)

2016年(50)

2015年(12)

2014年(9)

2013年(29)

分类: 嵌入式

2015-12-28 14:49:35


nordic BLE 蓝牙技术交流群498676838

本讲教程还是会基于 9.0 sdk中的uart例子。 在该例子上使用 sdk中自带的软件定时器来实现一些功能

Uart例子在sdk 中如下目录

XXX\Keil_v5\ARM\Pack\NordicSemiconductor\nRF_Examples\9.0.0\ble_peripheral\ble_app_uart 

 

 

首先 了解一下相关API

 

Sdk中的app timer(软件定时器) 是用51822中的RTC来模拟出的一个定时器队列来实现通过一个硬件RTC来模拟多个软件定时器。

 

使用app timer模块之前需要调用

uint32_t app_timer_init

(

uint32_t 

prescaler,

uint8_t 

max_timers,

uint8_t 

op_queues_size,

void * 

p_buffer,

app_timer_evt_schedule_func_t 

evt_schedule_func 

)

 

来初始化模块,通常都不直接使用该函数,而是使用SDK中提供的宏。

这个宏会根据帮你的参数申请合适的buff然后再调用app_timer_init函数

#define APP_TIMER_INIT

(

 

PRESCALER,


 

MAX_TIMERS,

 

OP_QUEUES_SIZE,

 

SCHEDULER_FUNC 

)

Value:

do                                                                 \

{                                                                        \

static uint32_t APP_TIMER_BUF[CEIL_DIV(APP_TIMER_BUF_SIZE((MAX_TIMERS), \

                                                    (OP_QUEUES_SIZE) + 1), \

                                                    sizeof(uint32_t))]; \

uint32_t ERR_CODE = app_timer_init((PRESCALER), \

                                   (MAX_TIMERS), \

                                   (OP_QUEUES_SIZE) + 1, \

                                   APP_TIMER_BUF, \

                                   SCHEDULER_FUNC); \

                                   APP_ERROR_CHECK(ERR_CODE); \

} while (0)

 

 

 

然后就可以创建自己的定时器了。

uint32_t app_timer_create

(

app_timer_id_t * 

p_timer_id,

app_timer_mode_t 

mode,

app_timer_timeout_handler_t 

timeout_handler 

)

 

可以通过mode模式来选择是只运行一次还是周期性的定时器。

APP_TIMER_MODE_SINGLE_SHOT,

APP_TIMER_MODE_REPEATED

Timeout_handler为注册的回调函数,在定时到期后执行

 

 

定时器创建完成后需要主动调用开始函数

uint32_t app_timer_start(app_timer_id_t timer_id,uint32_t timeout_ticks,void * p_context )

定时时间 timeout_ticks 需要通过宏 APP_TIMER_TICKS(MS, PRESCALER) 来或得,MS为需要定时的ms, PRESCALER就是上面的 初始化模块时的参数PRESCALER

P_context 为传递给回调函数的参数。 在定时到期执行定时函数时这个参数会作为他的参数

 

 

下面我们在uart工程的基础上创建一个定时器,这个定时器在手机使能了rx特征值的notify功能后启动,然后周期性的递增发送一个数据给手机

 

Uart工程中 app timer模块的初始化已经有了,我们只要创建一个定时器然后在手机使能notify时开启他就行了。

 

添加如下变量和函数。

app_timer_id_t my_test_timer;

uint8_t g_send_data = 0;

 

void my_timer_handler(void *params){

        

         ble_nus_string_send(&m_nus, &g_send_data, 1);

         g_send_data++;

}

 

 

 

 

 

 

 

修改main函数,初始化最后创建定时器。

int main(void)

{

    uint32_t err_code;

    bool erase_bonds;

    uint8_t  start_string[] = START_STRING;

   

    // Initialize.

APP_TIMER_INIT(APP_TIMER_PRESCALER,APP_TIMER_MAX_TIMERS,APP_TIMER_OP_QUEUE_SIZE, false);                    //原工程中已经初始化了app timer模块

    uart_init();

    buttons_leds_init(&erase_bonds);

    ble_stack_init();

    gap_params_init();

    services_init();

    advertising_init();

    conn_params_init();

     printf("start");

    err_code = ble_advertising_start(BLE_ADV_MODE_FAST);

    APP_ERROR_CHECK(err_code);

         //添加创建定时器代码

         err_code = app_timer_create(&my_test_timer,

                                APP_TIMER_MODE_REPEATED,

                                my_timer_handler);    

         printf("create timere err_code:%d\r\n",err_code);

         // Enter main loop.

    for (;;)

    {

        power_manage();

    }

}

 

然后 在 ble_nus.c 中 找到on_write函数添加红色部分

extern app_timer_id_t my_test_timer;  //声明下变量

static void on_write(ble_nus_t * p_nus, ble_evt_t * p_ble_evt)

{

         int err_code;

    ble_gatts_evt_write_t * p_evt_write = &p_ble_evt->evt.gatts_evt.params.write;

    if ( (p_evt_write->handle == p_nus->rx_handles.cccd_handle)&&(p_evt_write->len == 2))

    {

        if (ble_srv_is_notification_enabled(p_evt_write->data))

        {

            p_nus->is_notification_enabled = true;

                            //定时1s,   PRESCALER直接填 0

                            app_timer_start(my_test_timer,  APP_TIMER_TICKS(1000, 0), NULL);

        }

        else

        {

            p_nus->is_notification_enabled = false;

        }

    }

    else if ((p_evt_write->handle == p_nus->tx_handles.value_handle)

&&(p_nus->data_handler != NULL)

            )

    {

      ……………………………………….

    }

    else

    {

        // Do Nothing. This event is not relevant for this service.

    }

}

 

 

现在下载程序后,手机连接,然后点使能Notify后就能周期收到数据了。

 

如果创建timer出错。是允许创建的定时器已经达到最大值了,可以修改一下宏。

Main.c中的

#define APP_TIMER_MAX_TIMERS            (3 + BSP_APP_TIMERS_NUMBER)                

将原来的2 改为3 如果想创建更多的定时器,同样也要改大这里的值

阅读(7089) | 评论(1) | 转发(2) |
给主人留下些什么吧!~~

yunjie1672017-10-16 22:13:44

作者这篇文章发布的很早,现在使用的nrf52832,使用的协议版本是s132,已经有一点点变化,例如定义一个定时器,必须用宏,例如APP_TIMER_DEF(m_battery_timer_id);                        /**< Battery timer. */