[nRF51822] 3、 新年也来个总结——图解nRF51 SDK中的Button handling library和FIFO library

时间:2022-12-19 20:39:52

 

:本篇是我翻译并加入自己理解的nRF51 SDK中按钮相关操作的库和先进先出队列库。虽然是nRF51的SDK,但是通过此文你将更多地了解到在BSP(板级支持)上层嵌入式程序或OS的构建方法。

 

1、按钮相关操作库

  按键管理程序是通过GPIO事务和事件管理程序来检测一个按钮是否被按下的。当然,其中也做了消抖的工作——在GPIOTE事件中启动一个定时器用来延时一段时间,当该定时器失效后如果按钮仍然处于按下状态,则会产生一个按钮事件。如果在延时的过程中又有一个新的GPIOTE,那么这个定时器会重新被启动。此外,在APP_BUTTON_INIT()参数中,使用USE_SCHEDULER参数来决定是否使用scheduler。(关于GPIOTE和SCHEDULER会在下面详细讲)

  app_button模块会用到app_timer模块。用户必须确保app_timer的队列足够大来容纳app_timer_stop()和app_timer_start()操作(注意:这两个操作会在每个GPIOTE事件中执行,所以频度很高!)

ps:即使scheduler没被用,app_button.h也要包含app_scheduler.h!

[nRF51822] 3、 新年也来个总结——图解nRF51 SDK中的Button handling library和FIFO library

2、先进先出队列

该队列采用环形缓冲,其大小和缓冲区在初始化的地方配置,如下:

1 // Create a FIFO 
2 structureapp_fifo_t my_fifo;
3 
4 // Create a buffer for the FIFO
5 uint16_t buffer_size = 8;
6 uint8_t buffer[buffer_size];
7 
8 // Initialize FIFO structure
9 uint32_t err_code = app_fifo_init(&test_fifo, buffer, (uint16_t)sizeof(buffer));

ps:1.通过app_fifo_init函数,test_fifo会被初始化(其结构体如下)。2.buffer的大小应该是2的倍数。3.一定要确保当FIFO在用的时候,app_fifo_t的缓冲内存不被回收了

 

1 typedef struct{    
2     uint8_t *          p_buf;           /**< Pointer to FIFO buffer memory. */    
3     uint16_t           buf_size_mask;   /**< Read/write index mask. Also used for size checking. */    
4     volatile uint32_t  read_pos;        /**< Next read position in the FIFO buffer.              */    
5     volatile uint32_t  write_pos;       /**< Next write position in the FIFO buffer.             */
6 } app_fifo_t;

这是个环形FIFO队列,p_buf是调用初始化函数中传入的数据池地址,read_pos和write_pos是读地址和写地址~此外,既然是环形FIFO就要用到mod,即:假设环形fifo数据池大小为n,当前写入数据为第x个,则应该写在xmodn位置。这里官方用了个小技巧(如下英语),首先要保证buffer-size是2的倍数,这样xMODn就等于xAND(n-1)。

>>To simplify the index handling, the FIFO is restricted to require the buffer size <n>, to be a power of two, as this reduces the modulus operation to become a simple  AND operation with <n> - 1

n     = 8 = 0b00001000
n - 1 = 7 = 0b00000111

ANDing any number with <n>-1 , is identical to the modulus operation of <n>, when <n> is a power of two, see below:
3 = 11 mod 8 = 11 AND 7 = 0b00001011 & 0b00000111 = 0b00000011 = 3 . 

 

♠ 若n=8,则初始状态下FIFO为:

[nRF51822] 3、 新年也来个总结——图解nRF51 SDK中的Button handling library和FIFO library

 

♠ 插入一个8位uint8数据则:

1 uint8_t data = 88;
2 // Add an element to the FIFO
3 err_code = app_fifo_put(&my_fifo, data);

[nRF51822] 3、 新年也来个总结——图解nRF51 SDK中的Button handling library和FIFO library

 [nRF51822] 3、 新年也来个总结——图解nRF51 SDK中的Button handling library和FIFO library

  上图为插入4个uint8的效果~

 

 ♠ 取出一个8位uint8数据的代码为:

1 // Consume one element from FIFO
2 uint8_t return_val;
3 err_code = app_fifo_get(&my_fifo, &return_val);

   下图为取出两个的效果~

 [nRF51822] 3、 新年也来个总结——图解nRF51 SDK中的Button handling library和FIFO library

 

♠ Empty Buffer

当read_pos=write_pos时表示buffer是空的。

初始化的时候读写位置都置为0、buffer内的内容被取完或者调用app_fifo_flush。

此时再调用读函数则返回没数据。

 

♠ Full Buffer

write_pos == read_pos + <n>时表示buffer是满的。

此时再调用写函数则返回没内存。

 

 

@beautifulzzzz 2016-01-01 continue~