[nRF51822] 7、基础实验代码解析大全(前十)

本文涉及的产品
全局流量管理 GTM,标准版 1个月
云解析 DNS,旗舰版 1个月
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
简介:


 

实验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 
 8     while (true)
 9     {
10         //检测按键S1是否按下
11         if(nrf_gpio_pin_read(BUTTON_1) == 0)
12         {
13             nrf_gpio_pin_clear(LED_1);
14             while(nrf_gpio_pin_read(BUTTON_1) == 0);//等待按键释放
15             nrf_gpio_pin_set(LED_1);
16         }
17     }
18 }
复制代码

实验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     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     };
16 
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);
23 
24     APP_ERROR_CHECK(err_code);
25 
26     while (true)
27     {
28         uint8_t cr;
29         while(app_uart_get(&cr) != NRF_SUCCESS);  //等待接收串口数据
30         while(app_uart_put(cr) != NRF_SUCCESS);   //返回接收到的串口数据
31 
32         if (cr == 'q' || cr == 'Q')
33         {
34             printf(" \n\rExit!\n\r");
35 
36             while (true)
37             {
38                 // Do nothing.
39             }
40         }
41     }
42 }
复制代码

实验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 = 0; i < length; i++) //串口输出RNG 9 { 10 printf(" %3d",(int)p_buff[i]); 11 } 12 printf("\r\n"); 13 nrf_delay_ms(500); //延时,方便观察数据 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 = 0; i < LEDS_NUMBER; i++)
11     {   nrf_delay_ms(200);
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     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     
25     //配置WDT.
26     nrf_drv_wdt_config_t config = NRF_DRV_WDT_DEAFULT_CONFIG;//采用默认设置
27     err_code = nrf_drv_wdt_init(&config, wdt_event_handler);//使用默认参数配置看门狗。即CPU睡眠时,看门狗保持运行;看门狗超时周期2秒
28     APP_ERROR_CHECK(err_code);
29     err_code = nrf_drv_wdt_channel_alloc(&m_channel_id);//分配一个通道id
30     APP_ERROR_CHECK(err_code);
31     nrf_drv_wdt_enable();//使能看门狗
32 
33     while(1)
34     {
35         __SEV();  //设置事件
36         __WFE();  //进入睡眠,等待事件唤醒
37         __WFE();
38     }
39 }
复制代码
  • 每按下一次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,以降低功耗。
复制代码
 1 int main(void)
 2 {
 3     uint32_t time_ms = 500; //Time(in miliseconds) between consecutive compare events.
 4     uint32_t time_ticks;
 5     uint32_t err_code = NRF_SUCCESS;
 6     
 7     
 8     LEDS_CONFIGURE(LEDS_MASK);//配置开发板上驱赌LED的管脚为输出
 9     LEDS_OFF(LEDS_MASK);      //熄灭LED D1~D4
10     
11     //Configure TIMER_LED for generating simple light effect - leds on board will invert his state one after the other.
12     err_code = nrf_drv_timer_init(&TIMER_LED, NULL, timer_led_event_handler);//初始化
13     APP_ERROR_CHECK(err_code);
14     
15     time_ticks = nrf_drv_timer_ms_to_ticks(&TIMER_LED, time_ms);
16     
17     nrf_drv_timer_extended_compare(//设置比较寄存器中的值(本实验设置的值对应于500ms)。计数器开始计数后,当计数器里的值和比较寄存器里的值相等时,产生输出比较匹配事件,触发中断。
18          &TIMER_LED, NRF_TIMER_CC_CHANNEL0, time_ticks, NRF_TIMER_SHORT_COMPARE0_CLEAR_MASK, true);
19     
20     nrf_drv_timer_enable(&TIMER_LED);//启动
21 
22     while(1)
23     {
24         __WFI(); //进入睡眠,等待中断
25     }
26 }
复制代码

定时器(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博客园博客,原文链接:http://www.cnblogs.com/zjutlitao/p/5750342.html,如需转载请自行联系原作者
目录
打赏
0
0
0
0
23
分享
相关文章
实现一个带有昼夜背景切换的动态时钟:从代码到功能解析
本文介绍了一个使用Python和Tkinter库实现的动态时钟程序,具有昼夜背景切换、指针颜色随机变化及整点和半点报时功能。通过设置不同的背景颜色和随机变换指针颜色,增强视觉吸引力;利用多线程技术确保音频播放不影响主程序运行。该程序结合了Tkinter、Pygame、Pytz等库,提供了一个美观且实用的时间显示工具。欢迎点赞、关注、转发、收藏!
138 94
保单AI识别技术及代码示例解析
车险保单包含基础信息、车辆信息、人员信息、保险条款及特别约定等关键内容。AI识别技术通过OCR、文档结构化解析和数据校验,实现对保单信息的精准提取。然而,版式多样性、信息复杂性、图像质量和法律术语解析是主要挑战。Python代码示例展示了如何使用PaddleOCR进行保单信息抽取,并提出了定制化训练、版式分析等优化方向。典型应用场景包括智能录入、快速核保、理赔自动化等。未来将向多模态融合、自适应学习和跨区域兼容性发展。
如何在 Java 代码中使用 JSqlParser 解析复杂的 SQL 语句?
大家好,我是 V 哥。JSqlParser 是一个用于解析 SQL 语句的 Java 库,可将 SQL 解析为 Java 对象树,支持多种 SQL 类型(如 `SELECT`、`INSERT` 等)。它适用于 SQL 分析、修改、生成和验证等场景。通过 Maven 或 Gradle 安装后,可以方便地在 Java 代码中使用。
359 11
鸿蒙登录页面好看的样式设计-HarmonyOS应用开发实战与ArkTS代码解析【HarmonyOS 5.0(Next)】
鸿蒙登录页面设计展示了 HarmonyOS 5.0(Next)的未来美学理念,结合科技与艺术,为用户带来视觉盛宴。该页面使用 ArkTS 开发,支持个性化定制和无缝智能设备连接。代码解析涵盖了声明式 UI、状态管理、事件处理及路由导航等关键概念,帮助开发者快速上手 HarmonyOS 应用开发。通过这段代码,开发者可以了解如何构建交互式界面并实现跨设备协同工作,推动智能生态的发展。
213 10
鸿蒙登录页面好看的样式设计-HarmonyOS应用开发实战与ArkTS代码解析【HarmonyOS 5.0(Next)】
PHP命名空间深度解析:避免命名冲突与提升代码组织####
本文深入探讨了PHP中命名空间的概念、用途及最佳实践,揭示其在解决全局命名冲突、提高代码可维护性方面的重要性。通过生动实例和详尽分析,本文将帮助开发者有效利用命名空间来优化大型项目结构,确保代码的清晰与高效。 ####
77 20
强化学习与深度强化学习:深入解析与代码实现
本书《强化学习与深度强化学习:深入解析与代码实现》系统地介绍了强化学习的基本概念、经典算法及其在深度学习框架下的应用。从强化学习的基础理论出发,逐步深入到Q学习、SARSA等经典算法,再到DQN、Actor-Critic等深度强化学习方法,结合Python代码示例,帮助读者理解并实践这些先进的算法。书中还探讨了强化学习在无人驾驶、游戏AI等领域的应用及面临的挑战,为读者提供了丰富的理论知识和实战经验。
134 5
揭秘前端高手的秘密武器:深度解析递归组件与动态组件的奥妙,让你代码效率翻倍!
【10月更文挑战第23天】在Web开发中,组件化已成为主流。本文深入探讨了递归组件与动态组件的概念、应用及实现方式。递归组件通过在组件内部调用自身,适用于处理层级结构数据,如菜单和树形控件。动态组件则根据数据变化动态切换组件显示,适用于不同业务逻辑下的组件展示。通过示例,展示了这两种组件的实现方法及其在实际开发中的应用价值。
67 1
高级java面试---spring.factories文件的解析源码API机制
【11月更文挑战第20天】Spring Boot是一个用于快速构建基于Spring框架的应用程序的开源框架。它通过自动配置、起步依赖和内嵌服务器等特性,极大地简化了Spring应用的开发和部署过程。本文将深入探讨Spring Boot的背景历史、业务场景、功能点以及底层原理,并通过Java代码手写模拟Spring Boot的启动过程,特别是spring.factories文件的解析源码API机制。
141 2
【23种设计模式·全精解析 | 创建型模式篇】5种创建型模式的结构概述、实现、优缺点、扩展、使用场景、源码解析
创建型模式的主要关注点是“怎样创建对象?”,它的主要特点是"将对象的创建与使用分离”。这样可以降低系统的耦合度,使用者不需要关注对象的创建细节。创建型模式分为5种:单例模式、工厂方法模式抽象工厂式、原型模式、建造者模式。
【23种设计模式·全精解析 | 创建型模式篇】5种创建型模式的结构概述、实现、优缺点、扩展、使用场景、源码解析

热门文章

最新文章

推荐镜像

更多
AI助理

你好,我是AI助理

可以解答问题、推荐解决方案等