实验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);
  1. int main(void)
  2. {
  3. nrf_gpio_cfg_output(LED_1);//配置P0.21为输出
  4. nrf_gpio_pin_set(LED_1); //指示灯D1初始状态为熄灭
  5.  
  6. while (true)
  7. {
  8. //指示灯D1以200ms的间隔闪烁
  9. nrf_gpio_pin_toggle(LED_1);
  10. nrf_delay_ms(100);
  11. }
  12. }

实验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
  1. int main(void)
  2. {
  3. nrf_gpio_range_cfg_output(LED_START, LED_STOP);//配置P0.21~P0.24为输出
  4. nrf_gpio_pin_set(LED_1); //LED初始状态为熄灭
  5. nrf_gpio_range_cfg_input(BUTTON_START,BUTTON_STOP,NRF_GPIO_PIN_PULLUP);//配置P0.17~P0.20为输入
  6.  
  7. while (true)
  8. {
  9. //检测按键S1是否按下
  10. if(nrf_gpio_pin_read(BUTTON_1) == 0)
  11. {
  12. nrf_gpio_pin_clear(LED_1);
  13. while(nrf_gpio_pin_read(BUTTON_1) == );//等待按键释放
  14. nrf_gpio_pin_set(LED_1);
  15. }
  16. }
  17. }

实验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);

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

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

  22. APP_ERROR_CHECK(err_code);
  23.  
  24. while (true)
  25. {
  26. uint8_t cr;
  27. while(app_uart_get(&cr) != NRF_SUCCESS); //等待接收串口数据
  28. while(app_uart_put(cr) != NRF_SUCCESS); //返回接收到的串口数据
  29.  
  30. if (cr == 'q' || cr == 'Q')
  31. {
  32. printf(" \n\rExit!\n\r");
  33.  
  34. while (true)
  35. {
  36. // Do nothing.
  37. }
  38. }
  39. }
  40. }

实验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;
}

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

实验09 - 看门狗

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

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

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

  31. while()
  32. {
  33. __SEV(); //设置事件
  34. __WFE(); //进入睡眠,等待事件唤醒
  35. __WFE();
  36. }
  37. }
  • 每按下一次S1 按键,进行一次喂狗操作:
  1. 1 void bsp_event_callback(bsp_event_t event)
  2. 2 {
  3. 3 switch(event)
  4. 4 {
  5. 5 case BSP_EVENT_KEY_0:
  6. 6 nrf_drv_wdt_channel_feed(m_channel_id);
  7. 7 break;
  8. 8 default : //Do nothing. break;
  9. 9 }
  10. 10 } 
  • 如果2 秒内,按下按键S1 进行喂狗,系统正常运行,4 个指示灯常亮。如果2 秒内,不进行喂狗操作,系统复位:
  1. 1 void wdt_event_handler(void)
  2. 2 {
  3. 3 LEDS_OFF(LEDS_MASK);
  4. 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. 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,以降低功耗。
  1. int main(void)
  2. {
  3. uint32_t time_ms = ; //Time(in miliseconds) between consecutive compare events.
  4. uint32_t time_ticks;
  5. uint32_t err_code = NRF_SUCCESS;
  6.  
  7. LEDS_CONFIGURE(LEDS_MASK);//配置开发板上驱赌LED的管脚为输出
  8. LEDS_OFF(LEDS_MASK); //熄灭LED D1~D4
  9.  
  10. //Configure TIMER_LED for generating simple light effect - leds on board will invert his state one after the other.
  11. err_code = nrf_drv_timer_init(&TIMER_LED, NULL, timer_led_event_handler);//初始化
  12. APP_ERROR_CHECK(err_code);
  13.  
  14. time_ticks = nrf_drv_timer_ms_to_ticks(&TIMER_LED, time_ms);
  15.  
  16. 17 nrf_drv_timer_extended_compare(//设置比较寄存器中的值(本实验设置的值对应于500ms)。计数器开始计数后,当计数器里的值和比较寄存器里的值相等时,产生输出比较匹配事件,触发中断。
  17. 18 &TIMER_LED, NRF_TIMER_CC_CHANNEL0, time_ticks, NRF_TIMER_SHORT_COMPARE0_CLEAR_MASK, true);

  18. nrf_drv_timer_enable(&TIMER_LED);//启动

  19. while()
  20. {
  21. __WFI(); //进入睡眠,等待中断
  22. }
  23. }

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

  1. 1 /**
  2. 2 * @brief Handler for timer events. 轮流翻转开发板上的4个指示灯D1~D4的状态
  3. 3 */
  4. 4 void timer_led_event_handler(nrf_timer_event_t event_type, void *p_context)
  5. 5 {
  6. 6 static uint32_t i;
  7. 7 uint32_t led_to_invert = (1 << leds_list[(i++) % LEDS_NUMBER]);
  8. 8
  9. 9 switch(event_type)
  10. 10 {
  11. 11 case NRF_TIMER_EVENT_COMPARE0:
  12. 12 LEDS_INVERT(led_to_invert);
  13. 13 break;
  14. 14
  15. 15 default:
  16. 16 //Do nothing.
  17. 17 break;
  18. 18 }
  19. 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. 微信小程序开发—快速掌握组件及API的方法---转载

    微信小程序框架为开发者提供了一系列的组件和API接口. 组件主要完成小程序的视图部分,例如文字.图片显示.API主要完成逻辑功能,例如网络请求.数据存储.音视频播放控制,以及微信开放的微信登录.微信支 ...

  2. Oracle存储过程语法

    原文链接:http://www.jb51.net/article/31805.htm Oracle存储过程基本语法 存储过程  1 CREATE OR REPLACE PROCEDURE 存储过程名  ...

  3. android 查看当前正在运行的进程

    转载至 https://github.com/wenmingvs/AndroidProcess 因为Android5.0以上的权限封锁,无法直接获取正在运行的进程,此文总共介绍6中方法获取, 详细介绍 ...

  4. unity3d关于碰撞问题

    这个是我做忍者游戏出现的问题,做个记录也为以后有人遇到也可以借鉴.因为刚接触unity,所以对其所知甚少,说错的地方请指教. 问题:角色碰撞墙为什么会先触发碰撞地面,然后再触发碰撞墙 想要的效果:是角 ...

  5. Open 语法的使用

    我们通常会需要在命令中,打开文件输入信息,在python中我们就会使用open语法,进行此方面的操作.详细方式如下:#Python open 函数# 作用:打开一个文件# 语法:open(file[, ...

  6. VS自定义项目模板:[2]创建VSIX项目模板扩展

    VS自定义项目模板:[2]创建VSIX项目模板扩展 听语音 | 浏览:1237 | 更新:2015-01-02 09:21 | 标签:软件开发 1 2 3 4 5 6 7 分步阅读 一键约师傅 百度师 ...

  7. Unity 依赖注入之二

    1. 构造子注入 1.1 构造子注入初级代码 container.RegisterType<IMyWork, MyWork>(new InjectionConstructor(new Bo ...

  8. < meta > 元素

    < meta > 元素 概要 标签提供关于HTML文档的元数据.元数据不会显示在页面上,但是对于机器是可读的.它可用于浏览器(如何显示内容或重新加载页面),搜索引擎(关键词),或其他 we ...

  9. 从零开始山寨Caffe·柒:KV数据库

    你说你会关系数据库?你说你会Hadoop? 忘掉它们吧,我们既不需要网络支持,也不需要复杂关系模式,只要读写够快就行.    ——论数据存储的本质 浅析数据库技术 内存数据库——STL的map容器 关 ...

  10. [知识点]字符串Hash

    1.前言 字符串的几大主要算法都多少提及过,现在来讲讲一个称不上什么算法, 但是非常常用的东西——字符串Hash. 2.Hash的概念 Hash更详细的概念不多说了,它的作用在于能够对复杂的状态进行简 ...