:本篇是我翻译并加入自己理解的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!
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
, to be a power of two, as this reduces the modulus operation to become a simple AND operation with
.
- 1
n = 8 = 0b00001000
n - 1 = 7 = 0b00000111
ANDing any number with
3 = 11 mod 8 = 11 AND 7 = 0b00001011 & 0b00000111 = 0b00000011 = 3 .
♠ 若n=8,则初始状态下FIFO为:
♠ 插入一个8位uint8数据则:
1 uint8_t data = 88; 2 // Add an element to the FIFO 3 err_code = app_fifo_put(&my_fifo, data);
上图为插入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);
下图为取出两个的效果~
♠ Empty Buffer
当read_pos=write_pos时表示buffer是空的。
初始化的时候读写位置都置为0、buffer内的内容被取完或者调用app_fifo_flush。
此时再调用读函数则返回没数据。
♠ Full Buffer
当write_pos == read_pos +
此时再调用写函数则返回没内存。
@beautifulzzzz 2016-01-01 continue~