实验01 - GPIO输出控制LED

  • 引脚输出配置:nrf_gpio_cfg_output(LED_1);
  • 引脚输出置高:nrf_gpio_pin_set(LED_1);
  • 引脚电平转换:nrf_gpio_pin_toggle(LED_1);
  • 毫秒延时:nrf_delay_ms(100);
 int main(void)
{
nrf_gpio_cfg_output(LED_1);//配置P0.21为输出
nrf_gpio_pin_set(LED_1); //指示灯D1初始状态为熄灭 while (true)
{
//指示灯D1以200ms的间隔闪烁
nrf_gpio_pin_toggle(LED_1);
nrf_delay_ms(100);
}
}

实验02 - 跑马灯(略)

实验03 - GPIO输入按键检测

  • 多个引脚同时初始化输出:nrf_gpio_range_cfg_output(LED_START, LED_STOP);
  • 多个引脚同时初始化输入:nrf_gpio_range_cfg_input(BUTTON_START,BUTTON_STOP,NRF_GPIO_PIN_PULLUP);
  • 读取某引脚的电平状态:nrf_gpio_pin_read(BUTTON_1) == 0
 int main(void)
{
nrf_gpio_range_cfg_output(LED_START, LED_STOP);//配置P0.21~P0.24为输出
nrf_gpio_pin_set(LED_1); //LED初始状态为熄灭
nrf_gpio_range_cfg_input(BUTTON_START,BUTTON_STOP,NRF_GPIO_PIN_PULLUP);//配置P0.17~P0.20为输入 while (true)
{
//检测按键S1是否按下
if(nrf_gpio_pin_read(BUTTON_1) == 0)
{
nrf_gpio_pin_clear(LED_1);
while(nrf_gpio_pin_read(BUTTON_1) == );//等待按键释放
nrf_gpio_pin_set(LED_1);
}
}
}

实验04 - GPIO控制蜂鸣器(略)

实验05 - RGB三色LED(略)

实验06 - UART数据收发

调用了串口FIFO驱动,是在串口上继续封装一层的

  • /**@brief Function for getting a byte from the UART.
    *
    * @details This function will get the next byte from the RX buffer. If the RX buffer is empty
    * an error code will be returned and the app_uart module will generate an event upon
    * reception of the first byte which is added to the RX buffer.
    *
    * @param[out] p_byte Pointer to an address where next byte received on the UART will be copied.
    *
    * @retval NRF_SUCCESS If a byte has been received and pushed to the pointer provided.
    * @retval NRF_ERROR_NOT_FOUND If no byte is available in the RX buffer of the app_uart module.
    */
    uint32_t app_uart_get(uint8_t * p_byte);

  • /**@brief Function for putting a byte on the UART.
    *
    * @details This call is non-blocking.
    *
    * @param[in] byte Byte to be transmitted on the UART.
    *
    * @retval NRF_SUCCESS If the byte was successfully put on the TX buffer for transmission.
    * @retval NRF_ERROR_NO_MEM If no more space is available in the TX buffer.
    * NRF_ERROR_NO_MEM may occur if flow control is enabled and CTS signal
    * is high for a long period and the buffer fills up.
    */
    uint32_t app_uart_put(uint8_t byte);

 int main(void)
{
LEDS_CONFIGURE(LEDS_MASK);
LEDS_OFF(LEDS_MASK);
uint32_t err_code;
6 const app_uart_comm_params_t comm_params =
7 {
8 RX_PIN_NUMBER,
9 TX_PIN_NUMBER,
10 RTS_PIN_NUMBER,
11 CTS_PIN_NUMBER,
12 APP_UART_FLOW_CONTROL_DISABLED,
13 false,
14 UART_BAUDRATE_BAUDRATE_Baud38400
15 };

17 APP_UART_FIFO_INIT(&comm_params,
18 UART_RX_BUF_SIZE,
19 UART_TX_BUF_SIZE,
20 uart_error_handle,
21 APP_IRQ_PRIORITY_LOW,
22 err_code);

APP_ERROR_CHECK(err_code); while (true)
{
uint8_t cr;
while(app_uart_get(&cr) != NRF_SUCCESS); //等待接收串口数据
while(app_uart_put(cr) != NRF_SUCCESS); //返回接收到的串口数据 if (cr == 'q' || cr == 'Q')
{
printf(" \n\rExit!\n\r"); while (true)
{
// Do nothing.
}
}
}
}

实验07 - UART控制指示灯(略)

实验08 - 随机数发生器

Random number generator

利用NRF51822 随机数发生器生成随机数,每隔500ms 通过串口输出一次随机数数值

/** @brief Function for getting vector of random numbers.
*
* @param[out] p_buff Pointer to unit8_t buffer for storing the bytes.
* @param[in] length Number of bytes to take from pool and place in p_buff.
*
* @retval Number of bytes actually placed in p_buff.
*/
uint8_t random_vector_generate(uint8_t * p_buff, uint8_t size)
{
        uint8_t available;
        uint32_t err_code;
        err_code = nrf_drv_rng_bytes_available(&available);
        APP_ERROR_CHECK(err_code);
        uint8_t length = (size<available) ? size : available;
        err_code = nrf_drv_rng_rand(p_buff,length);
        APP_ERROR_CHECK(err_code);
        return length;
}

 int main(void)
{
......
while (true)
{
uint8_t p_buff[RANDOM_BUFF_SIZE];
uint8_t length = random_vector_generate(p_buff,RANDOM_BUFF_SIZE);
printf("Random Vector:");
for(uint8_t i = ; i < length; i++) //串口输出RNG
{
printf(" %3d",(int)p_buff[i]);
}
printf("\r\n");
nrf_delay_ms(); //延时,方便观察数据
nrf_gpio_pin_toggle(LED_1); //指示灯D1指示程序运行
}
}

实验09 - 看门狗

  配置NRF51822 的看门狗超时周期为2 秒,CPU 休眠时看门狗保持运行。

  • NRF51822 的看门狗定时器是倒计数器,当计数值减少到0 时产生TIMEOUT 事件。
  • 通过START task 来启动看门狗定时器。
  • 看门狗定时器启动时,如没有其他32.768KHz 时钟源提供时钟,看门狗定时器会强制打开32.768KHz RC 振荡器。
  • 默认情况下,看门狗定时器会在CPU 睡眠期间,或是debugger 将CPU 暂停的时候保持运行。但是,可以通过配置看门狗定时器,使其在CPU 睡眠期间,或是debugger 将CPU 暂停的时候自动暂停。

  • 看门狗定时器超时周期:超时时间= ( CRV + 1 ) / 32768 秒
 int main(void)
{
uint32_t err_code = NRF_SUCCESS; //配置开发板上的4个用户LED指示灯
LEDS_CONFIGURE(LEDS_MASK);
LEDS_OFF(LEDS_MASK); //4个指示灯轮流闪烁一次,指示系统启动
for(uint32_t i = ; i < LEDS_NUMBER; i++)
{ nrf_delay_ms();
LEDS_ON(BSP_LED_0_MASK << i);
} //BSP configuration for button support: button pushing will feed the dog.
err_code = nrf_drv_clock_init(NULL);
APP_ERROR_CHECK(err_code);//检查返回值
nrf_drv_clock_lfclk_request(); APP_TIMER_INIT(APP_TIMER_PRESCALER, APP_TIMER_MAX_TIMERS, APP_TIMER_OP_QUEUE_SIZE, false);//定时器设置
21 err_code = bsp_init(BSP_INIT_BUTTONS, APP_TIMER_TICKS(100, APP_TIMER_PRESCALER), bsp_event_callback);//按键中断配置
APP_ERROR_CHECK(err_code); //配置WDT.
nrf_drv_wdt_config_t config = NRF_DRV_WDT_DEAFULT_CONFIG;//采用默认设置
err_code = nrf_drv_wdt_init(&config, wdt_event_handler);//使用默认参数配置看门狗。即CPU睡眠时,看门狗保持运行;看门狗超时周期2秒
APP_ERROR_CHECK(err_code);
err_code = nrf_drv_wdt_channel_alloc(&m_channel_id);//分配一个通道id
APP_ERROR_CHECK(err_code);
nrf_drv_wdt_enable();//使能看门狗

while()
{
__SEV(); //设置事件
__WFE(); //进入睡眠,等待事件唤醒
__WFE();
}
}
  • 每按下一次S1 按键,进行一次喂狗操作:
 1 void bsp_event_callback(bsp_event_t event)
2 {
3 switch(event)
4 {
5 case BSP_EVENT_KEY_0:
6 nrf_drv_wdt_channel_feed(m_channel_id);
7 break;
8 default : //Do nothing. break;
9 }
10 } 
  • 如果2 秒内,按下按键S1 进行喂狗,系统正常运行,4 个指示灯常亮。如果2 秒内,不进行喂狗操作,系统复位:
1 void wdt_event_handler(void)
2 {
3 LEDS_OFF(LEDS_MASK);
4 //NOTE: The max amount of time we can spend in WDT interrupt is two cycles of 32768[Hz] clock - after that, reset occurs
5 }

实验10 - 定时器

 配置NRF51822 的TIMER0 如下:

  • 时钟:16MHz。
  • 模式:定时器。
  • 位宽:32 位。
  • 比较时间:500ms。

计数器开始计数后,当计数器里的值和比较寄存器里的值相等时,产生输出比较匹配事件,触发中断。在中断服务函数中轮流翻转开发板上的4 个LED 指示灯D1~D4。

  • NRF51822 共有3 个定时器TIMER0,TIMER1,TIMER2。
  • NRF51822 的TIMER 有两种工作模式:定时模式和计数模式。在两种模式下都是通过START task 启动TIMER,通过STOP task 停止TIMER。当TIMER 停止时可以通过START task 让TIMER 恢复运行,恢复运行后,TIMER 从停止时的定时/计数值继续定时/计数。
  • 定时器时钟:定时器的时钟由PCLK16M 分频而来,公式如下:ftimer=16MHz/(2^PRESCALER)

  • 定时器通过一个四位的分频器进行分频,PRESCALER 寄存器中数值即为分频系数,如果fTIMER <= 1 MHz,定时器将使用PCLK1M 时钟源取代PCLK16M,以降低功耗。
 int main(void)
{
uint32_t time_ms = ; //Time(in miliseconds) between consecutive compare events.
uint32_t time_ticks;
uint32_t err_code = NRF_SUCCESS; LEDS_CONFIGURE(LEDS_MASK);//配置开发板上驱赌LED的管脚为输出
LEDS_OFF(LEDS_MASK); //熄灭LED D1~D4 //Configure TIMER_LED for generating simple light effect - leds on board will invert his state one after the other.
err_code = nrf_drv_timer_init(&TIMER_LED, NULL, timer_led_event_handler);//初始化
APP_ERROR_CHECK(err_code); time_ticks = nrf_drv_timer_ms_to_ticks(&TIMER_LED, time_ms); 17 nrf_drv_timer_extended_compare(//设置比较寄存器中的值(本实验设置的值对应于500ms)。计数器开始计数后,当计数器里的值和比较寄存器里的值相等时,产生输出比较匹配事件,触发中断。
18 &TIMER_LED, NRF_TIMER_CC_CHANNEL0, time_ticks, NRF_TIMER_SHORT_COMPARE0_CLEAR_MASK, true);

nrf_drv_timer_enable(&TIMER_LED);//启动

while()
{
__WFI(); //进入睡眠,等待中断
}
}

定时器(TIMER0)启动后,系统通过“__WFI();”指令进入睡眠等待比较匹配事件触发中断唤醒,中断发生后,在中断服务函数中轮流翻转开发板上的4 个LED 指示灯的状态:

 1 /**
2 * @brief Handler for timer events. 轮流翻转开发板上的4个指示灯D1~D4的状态
3 */
4 void timer_led_event_handler(nrf_timer_event_t event_type, void *p_context)
5 {
6 static uint32_t i;
7 uint32_t led_to_invert = (1 << leds_list[(i++) % LEDS_NUMBER]);
8
9 switch(event_type)
10 {
11 case NRF_TIMER_EVENT_COMPARE0:
12 LEDS_INVERT(led_to_invert);
13 break;
14
15 default:
16 //Do nothing.
17 break;
18 }
19 }

 

@beautifulzzzz - 物联网&普适计算实践者
e-mail:beautifulzzzz@qq.com 
i-blog:blog.beautifulzzzz.com

[nRF51822] 7、基础实验代码解析大全(前十)的更多相关文章

  1. [nRF51822] 12、基础实验代码解析大全 · 实验19 - PWM

    一.PWM概述: PWM(Pulse Width Modulation):脉冲宽度调制技术,通过对一系列脉冲的宽度进行调制,来等效地获得所需要波形. PWM 的几个基本概念: 1) 占空比:占空比是指 ...

  2. [nRF51822] 11、基础实验代码解析大全 · 实验16 - 内部FLASH读写

     一.实验内容: 通过串口发送单个字符到NRF51822,NRF51822 接收到字符后将其写入到FLASH 的最后一页,之后将其读出并通过串口打印出数据. 二.nRF51822芯片内部flash知识 ...

  3. [nRF51822] 10、基础实验代码解析大全 · 实验15 - RTC

    一.实验内容: 配置NRF51822 的RTC0 的TICK 频率为8Hz,COMPARE0 匹配事件触发周期为3 秒,并使能了TICK 和COMPARE0 中断. TICK 中断中驱动指示灯D1 翻 ...

  4. [nRF51822] 9、基础实验代码解析大全 · 实验12 - ADC

    一.本实验ADC 配置 分辨率:10 位. 输入通道:5,即使用输入通道AIN5 检测电位器的电压. ADC 基准电压:1.2V. 二.NRF51822 ADC 管脚分布 NRF51822 的ADC ...

  5. [nRF51822] 8、基础实验代码解析大全 · 实验11 - PPI

    前一篇分析了前十个基础实验的代码,从这里开始分析后十个~ 一.PPI原理: PPI(Programmable Peripheral Interconnect),中文翻译为可编程外设互连. 在nRF51 ...

  6. 基础Gan代码解析

    initializer总结: #f.constant_initializer(value) 将变量初始化为给定的常量,初始化一切所提供的值. #tf.random_normal_initializer ...

  7. MYSQL常见出错mysql_errno()代码解析

    如题,今天遇到怎么一个问题, 在理论上代码是不会有问题的,但是还是报了如上的错误,把sql打印出來放到DB中却可以正常执行.真是郁闷,在百度里面 渡 了很久没有相关的解释,到时找到几个没有人回复的 & ...

  8. 【原创】大数据基础之Spark(4)RDD原理及代码解析

    一 简介 spark核心是RDD,官方文档地址:https://spark.apache.org/docs/latest/rdd-programming-guide.html#resilient-di ...

  9. 【原创】大数据基础之Spark(5)Shuffle实现原理及代码解析

    一 简介 Shuffle,简而言之,就是对数据进行重新分区,其中会涉及大量的网络io和磁盘io,为什么需要shuffle,以词频统计reduceByKey过程为例, serverA:partition ...

随机推荐

  1. i春秋url地址编码问题

    i春秋学院是国内比较知名的安全培训平台,前段时间看了下网站,顺便手工简单测试常见的XSS,发现网站搜索功能比较有意思. 其实是对用户输入的内容HTML编码和URL编码的处理方式在这里不合理,提交到乌云 ...

  2. 学习微信小程序之css10外边距

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  3. react native 键盘遮挡按钮点击事件

    在做项目的时候,我遇到一个很奇怪的问题,我先描述一下问题,在InputText输入内完成以后,点击按钮进行下一步的操作的时候,第一次点击的时候,按钮没有响应,第二次点击的时候才会响应.这样对用户体验有 ...

  4. TOP 和 OFFSET 筛选(转)

    SQL Server 对行数的排序提供了 TOP 筛选.SQL Server 2012 新增了 OFFSET 筛选. 一.TOP 筛选 如果有 ORDER BY 子句,TOP 筛选将根据排序的结果返回 ...

  5. mybatis map常用数据类型

    JDBC Type Java Type CHAR String VARCHAR String LONGVARCHAR String NUMERIC java.math.BigDecimal DECIM ...

  6. JavaScript(二) DOM

    当网页被加载时,浏览器会创建页面的文档对象模型(Document Object Model)通过 HTML DOM,可访问 JavaScript HTML 文档的所有元素. 通过 id 查找 HTML ...

  7. Code Complete 笔记—— 第二章 用隐喻来更充分理解软件开发

    在这章里面,提到的隐喻,类同于比喻(建模)的方法的去理解软件开发. 隐喻的优点在于其可预期的效果能被所有人所理解.不必要的沟通和误解也因此大为减低,学习与教授更为快速,实际上,隐喻是对概念进行内在化和 ...

  8. c++书

    http://www.enet.com.cn/eschool/video/c++/   视频 http://www.runoob.com/cplusplus/cpp-inheritance.html ...

  9. 用百度webuploader分片上传大文件

    一般在做文件上传的时候,都是通过客户端把要上传的文件上传到服务器,此时上传的文件都在服务器内存,如果上传的是视频等大文件,那么服务器内存就很紧张,而且一般我们都是用flash或者html5做异步上传, ...

  10. Android事件分发小结

      ******** ******** 第一部分: 介绍说明 ******** ********        个人感觉在做交互的时候, 对于Android的按键分发的理解还是比较重要的. 这些内容在 ...