返回列表 发新帖我要提问本帖赏金: 80.00元(功能说明)

[开发工具] 新定义NBK-EBS002基础功能扩展板,功能不简单哦!

[复制链接]
 楼主| xld0932 发表于 2023-2-14 22:38 | 显示全部楼层 |阅读模式
<
本帖最后由 xld0932 于 2023-2-16 12:12 编辑

#申请原创#   @21小跑堂


2022年随着新定义入住了21ic,幸运的参与了新定义在21ic的首次评测活动,基于NBK-RD8x3x作为核心底板结合了NBK-EBS001触控扩展板的硬件资源,让我开始去了解新定义,芯片功能、性能、选型、以及它的优势;后来在年末的时候,新定义官方又送了两块扩展板,作为新年礼物:分别是NBK-EBS002基础功能扩展板和NBK-EBS003 IOT扩展板;新定义不断的在丰富着自己的硬件平台、也在不断的完善了软件套件(易码魔盒),为的就是让使用新定义的开发者有更好的体感,能够更快的上手、不受限于芯片底层驱动、软件架构、硬件等等,你能想到的,新定义可能都在准备的进行中……让开发者将更多的精力投入在产品上……能够实现项目敏捷开发的同时,兼顾产品的功能和性能……

本文将详细介绍一下基于NBK-RD8x3x核心底板结合NBK-EBS002基础功能扩展板实现的全部功能测试,以及在调试过程中做过的一些尝试和使用心得,分享给大家;首先我们还是将提前准备的的资料罗列一下:
1、RD8T36P48J芯片数据手册
2、易码魔盒EasyCodeCube_RDSV3.2.5_20230105
3、新定义NBK-RD8x3x应用资料
上面3个都可以在新定义官网的下载中心进行下载:https://www.rdsmcu.com/
4、NBK-EBS002基础功能扩展板原理图: NBK-EBS002原理图.pdf (308.55 KB, 下载次数: 10)

除了软件资料外,我们硬件平台也是不可缺少的:
1、NBK-RD8x3x核心底板
2、NBK-EBS002基础功能扩展板
3、RD LINK PRO
因为在NBK-RD8x3x核心底板上已经带有ISP下载功能模块,所以RD LINK PRO是可选择工具;ISP仅可以下载程序到MCU运行,通过实际的运行结果验证功能是否正常;而RD LINK PRO除了具有下载程序的功能之外,还带有脱机烧录、在线调试、仿真等等丰富的功能……各位小伙伴可以根据需要自行选择
微信图片_20230214230410.png

细心的小伙伴可以看出,在每一个功能外设旁边都已经标有了使用了MCU的资源了,这样可以让我们在不看原理图的状态下,就可以知道原理设计,点赞哦


我们结合NBK-EBS002基础功能扩展板实现的软件功能如下:
1、自定义时间片任务管理、调度机制(链表实现)
2、GPIO输出控制LED、GPIO输入检测KEY输入状态
3、3路PWM输出控制RGB灯,根据人体视觉感观,控制RGB亮度调节、颜色切换
4、1路PWM控制蜂鸣器
5、通过芯片的LCD/LED外设功能驱动显示4位8段数码管
6、通过板载的可调节电阻实现ADC检测与显示、通过2个可调节电阻实现比较器的功能
7、NTC实时温度检测与显示
最后综合实现一个功能:
系统启动后,RGB自动进行亮度调节显示、颜色切换;通过按键切换工作模式,每按一次切换一个工作模式,对应的LED亮一次,蜂鸣器响一声、模式1为LCD数码管显示累加数值、模式2为数码管显示ADC采样数值、模式3为数码管显示NTC实时温度、模式4为比较器功能,将比较结果通过蜂鸣器的形式进行体现;

1、自己定义时间片任务管理、调度机制(链表实现)
在单片机中我接触到的有两种运行的形式,一个是带RTOS实时操作系统的,比如支持51MCU的RTX、还有老早之前接触过的叫SmallRTOS的;另外一个就是不带操作系统的,一般由前后台系统组成了MCU的整体运行和调用;我们为了方便项目功能的应用,都会有自己的一些规划,有依据状态机的、有依据时间片的……而下面讲到的就是我自己写的一个基于时间片的任务管理和调度机制;
任务调度建立在TIM0定时器,系统默认是使用的32MHz的系统运行频率,我们将TIM0的滴答时间设置到1ms,作为我们系统的基础时间;在TIM0定时器中断中去处理每个节点任务的运行间隔时间是否达到,如果达到则置位运行标志位,为了不在TIM0中断占用太多调用功能函数和处理的时间,我们在while(1)循环中通过判断运行标志位,去调用具体的功能函数;代码如下:
  1. /***********************************************************************************************************************
  2.   * [url=home.php?mod=space&uid=247401]@brief[/url]    :  D1->32000000Hz / 32000 = 1000Hz, 1ms       D12->32000000Hz / 26666 = 100Hz, 10ms
  3.   * @param
  4.   * @retval
  5.   * @attention
  6.   *********************************************************************************************************************/
  7. void TimeSliceInitTIM(void)
  8. {
  9.     TIM0_DeInit();

  10.     TIM0_TimeBaseInit(TIM0_PRESSEL_FSYS_D1, TIM0_MODE_TIMER);

  11.     TIM0_WorkModeConfig(TIM0_WORK_MODE1, (65535 - 32000), 0);

  12.     TIM0_ITConfig(ENABLE, LOW);

  13.     TIM0_Cmd(ENABLE);
  14. }

  15. /***********************************************************************************************************************
  16.   * @brief
  17.   * @param
  18.   * @retval
  19.   * @attention
  20.   *********************************************************************************************************************/
  21. void TIM0_IRQHandler(void)  interrupt 1
  22. {
  23.     TIM0_Mode1SetReloadCounter(65535 - 32000);
  24.     TIM0_Tick++;

  25.     TimeSliceRunning(TIM0_Tick);
  26. }

  27. /***********************************************************************************************************************
  28.   * @brief
  29.   * @param
  30.   * @retval
  31.   * @attention
  32.   *********************************************************************************************************************/
  33. void TimeSliceRunning(uint32_t Tick)
  34. {
  35.     TimeSlice_NodeTypeDef *Node = Head;

  36.     while (NULL != Node)
  37.     {
  38.         if (0 == (Tick % Node->Period))
  39.         {
  40.             Node->RunFlag = 1;
  41.         }

  42.         Node = Node->Next;
  43.     }
  44. }

  45. /***********************************************************************************************************************
  46.   * @brief
  47.   * @param
  48.   * @retval
  49.   * @attention
  50.   *********************************************************************************************************************/
  51. void TimeSlicePolling(void)
  52. {
  53.     TimeSlice_NodeTypeDef *Node = Head;

  54.     while (NULL != Node)
  55.     {
  56.         if (1 == Node->RunFlag)
  57.         {
  58.             Node->RunFlag = 0;
  59.             Node->Handler();
  60.         }

  61.         Node = Node->Next;
  62.     }
  63. }

  64. /***********************************************************************************************************************
  65.   * @brief
  66.   * @param
  67.   * @retval
  68.   * @attention
  69.   *********************************************************************************************************************/
  70. void main(void)
  71. {
  72.     BSP_Init();

  73.     TimeSliceInitTIM();

  74.     enableInterrupts();

  75.     while (1)
  76.     {
  77.         TimeSlicePolling();
  78.     }
  79. }


任务的管理主要是创建,首先是定义一个任务,它有运行的间隔时间、可运行标志位、任务具体调用的功能函数、以及下一任务节点指针;通过链表的形式将各个节点的任务串连起来管理;其中使用到了malloc和free这两个动态内存分配和释放的函数,这个跟我们在32位MCU使用上还是有些区别的,主是需要定义一个内存池,对内存池进行初始化后才可以正常的运行malloc这些函数……具体的实现代码如下所示:
  1. /* Exported types *****************************************************************************************************/
  2. typedef void (* Function)(void);

  3. /* Exported types *****************************************************************************************************/
  4. typedef struct _Node_Struct
  5. {
  6.     uint32_t Period;
  7.     uint8_t  RunFlag;
  8.     Function Handler;
  9.     struct _Node_Struct *Next;
  10. } TimeSlice_NodeTypeDef;

  11. /* Private variables **************************************************************************************************/
  12. static uint8_t xdata mempool[1024];
  13. TimeSlice_NodeTypeDef *Head = NULL;

  14. /***********************************************************************************************************************
  15.   * @brief
  16.   * @param
  17.   * @retval
  18.   * @attention
  19.   *********************************************************************************************************************/
  20. void TimeSliceStartup(Function Handler, uint32_t Period)
  21. {
  22.     TimeSlice_NodeTypeDef *Node = Head;

  23.     if (NULL == Head)
  24.     {
  25.         memset(mempool, 0x00, sizeof(mempool));

  26.         init_mempool(mempool, sizeof(mempool));

  27.         Head = (TimeSlice_NodeTypeDef *)malloc(sizeof(TimeSlice_NodeTypeDef));

  28.         if (NULL == Head)
  29.         {
  30.             free(Head);
  31.         }
  32.         else
  33.         {
  34.             Head->Period  = Period;
  35.             Head->RunFlag = 0;
  36.             Head->Handler = Handler;
  37.             Head->Next    = NULL;
  38.         }
  39.     }
  40.     else
  41.     {
  42.         while (NULL != Node->Next)
  43.         {
  44.             if (Node->Handler == Handler)
  45.             {
  46.                 Node->Period = Period;

  47.                 return;
  48.             }
  49.             else
  50.             {
  51.                 Node = Node->Next;
  52.             }
  53.         }

  54.         Node->Next = (TimeSlice_NodeTypeDef *)malloc(sizeof(TimeSlice_NodeTypeDef));

  55.         if (NULL != Node->Next)
  56.         {
  57.             Node = Node->Next;

  58.             Node->Period  = Period;
  59.             Node->RunFlag = 0;
  60.             Node->Handler = Handler;
  61.             Node->Next    = NULL;
  62.         }
  63.         else
  64.         {
  65.             free(Node->Next);
  66.         }
  67.     }
  68. }



2、GPIO输出控制LED、GPIO输入检测KEY输入状态
GPIO是作为MCU的一个最基础的功能,通过新定义提供的低层库函数实现了LED亮灭的控制、通过状态机的方式实现了按键的检测和功能处理,具体代码如下所示:
  1. /***********************************************************************************************************************
  2.   * @brief
  3.   * @param
  4.   * @retval
  5.   * @attention
  6.   *********************************************************************************************************************/
  7. void LED_Init(void)
  8. {
  9.     GPIO_Init(GPIO4, GPIO_PIN_6, GPIO_MODE_OUT_PP); /* L1->P46 */
  10.     GPIO_Init(GPIO4, GPIO_PIN_7, GPIO_MODE_OUT_PP); /* L2->P47 */

  11.     GPIO_WriteLow(GPIO4, GPIO_PIN_6);
  12.     GPIO_WriteLow(GPIO4, GPIO_PIN_7);
  13. }

  14. /***********************************************************************************************************************
  15.   * @brief
  16.   * @param
  17.   * @retval
  18.   * @attention
  19.   *********************************************************************************************************************/
  20. void KEY_StateHandler(uint8_t Index, uint8_t *State, uint8_t *Count, uint8_t InputLevel, uint8_t ActiveLevel)
  21. {
  22.     if (0 == *State)
  23.     {
  24.         if (InputLevel == ActiveLevel)
  25.         {
  26.             *Count += 1;

  27.             if (*Count >= 5)
  28.             {
  29.                 *Count = 0;
  30.                 *State = 1;
  31.                 KEY_EventHandler(Index, 1);
  32.             }
  33.         }
  34.         else
  35.         {
  36.             *Count = 0;
  37.         }
  38.     }
  39.     else
  40.     {
  41.         if (InputLevel != ActiveLevel)
  42.         {
  43.             *Count += 1;

  44.             if (*Count >= 5)
  45.             {
  46.                 *Count = 0;
  47.                 *State = 0;
  48.                 KEY_EventHandler(Index, 0);
  49.             }
  50.         }
  51.         else
  52.         {
  53.             *Count = 0;
  54.         }
  55.     }
  56. }

  57. /***********************************************************************************************************************
  58.   * @brief
  59.   * @param
  60.   * @retval
  61.   * @attention
  62.   *********************************************************************************************************************/
  63. void KEY_Scan(void)
  64. {
  65.     static uint8_t State[2] =
  66.     {
  67.         0, 0
  68.     };
  69.     static uint8_t Count[2] =
  70.     {
  71.         0, 0
  72.     };

  73.     KEY_StateHandler(0, &State[0], &Count[0], GPIO_ReadPin(GPIO3, GPIO_PIN_6), RESET);
  74.     KEY_StateHandler(1, &State[1], &Count[1], GPIO_ReadPin(GPIO5, GPIO_PIN_4), RESET);
  75. }

  76. /***********************************************************************************************************************
  77.   * @brief
  78.   * @param
  79.   * @retval
  80.   * @attention
  81.   *********************************************************************************************************************/
  82. void KEY_Init(void)
  83. {
  84.     GPIO_Init(GPIO3, GPIO_PIN_6, GPIO_MODE_IN_PU);  /* K1->P36 */
  85.     GPIO_Init(GPIO5, GPIO_PIN_4, GPIO_MODE_IN_PU);  /* K2->P54 */

  86.     TimeSliceStartup(KEY_Scan, 10);
  87. }



3、3路PWM输出控制RGB灯,根据人体视觉感观,控制RGB亮度调节、颜色切换
RGB的亮度调节是通过修改PWM的占空比实现的,颜色的切换是通过开关不同的PWM通道实现的,在亮度调节上我们使用了LOG参数的形式进行计算后调节,使人体视觉感观更自然,调节更舒适,具体代码如下所示:
  1. /***********************************************************************************************************************
  2.   * @brief
  3.   * @param
  4.   * @retval
  5.   * @attention
  6.   *********************************************************************************************************************/
  7. double RGB_GetLOG(double Level, double MAX)
  8. {
  9.     return pow(10, Level * log10(999) / MAX);
  10. }

  11. /***********************************************************************************************************************
  12.   * @brief
  13.   * @param
  14.   * @retval
  15.   * @attention
  16.   *********************************************************************************************************************/
  17. void RGB_Scan(void)
  18. {
  19.     static uint8_t Index = 0;
  20.     static uint8_t State = 0, Level = 0, MAX = 100;

  21.     switch (Index)
  22.     {
  23.         case 0:
  24.             PWM_IndependentModeConfig(PWM01, RGB_GetLOG(Level, MAX));
  25.             PWM_IndependentModeConfig(PWM00, 0);
  26.             PWM_IndependentModeConfig(PWM03, 0);
  27.             break;

  28.         case 1:
  29.             PWM_IndependentModeConfig(PWM01, 0);
  30.             PWM_IndependentModeConfig(PWM00, RGB_GetLOG(Level, MAX));
  31.             PWM_IndependentModeConfig(PWM03, 0);
  32.             break;

  33.         case 2:
  34.             PWM_IndependentModeConfig(PWM01, 0);
  35.             PWM_IndependentModeConfig(PWM00, 0);
  36.             PWM_IndependentModeConfig(PWM03, RGB_GetLOG(Level, MAX));
  37.             break;

  38.         default:
  39.             break;
  40.     }

  41.     if (State == 0)
  42.     {
  43.         if (Level >= MAX)
  44.         {
  45.             Level = MAX;
  46.             State = 1;
  47.         }
  48.         else
  49.         {
  50.             Level++;
  51.         }
  52.     }
  53.     else
  54.     {
  55.         if (Level <= 1)
  56.         {
  57.             Level = 1;
  58.             State = 0;
  59.             Index = (Index + 1) % 3;
  60.         }
  61.         else
  62.         {
  63.             Level--;
  64.         }
  65.     }
  66. }

  67. /***********************************************************************************************************************
  68.   * @brief
  69.   * @param
  70.   * @retval
  71.   * @attention
  72.   *********************************************************************************************************************/
  73. void RGB_Init(void)
  74. {
  75.     PWM_Init(PWM0_PRESSEL_FHRC_D1, 255);

  76.     PWM_IndependentModeConfigEX(PWM00, 0, PWM_OUTPUTSTATE_ENABLE);
  77.     PWM_IndependentModeConfigEX(PWM01, 0, PWM_OUTPUTSTATE_ENABLE);
  78.     PWM_IndependentModeConfigEX(PWM03, 0, PWM_OUTPUTSTATE_ENABLE);

  79. //    PWM_Aligned_Mode_Select(PWM0_Edge_Aligned_Mode);
  80. //    PWM_FaultDetectionConfigEX(PWM0_Type, DISABLE);
  81. //    PWM_FaultDetectionModeConfigEX(PWM0_Type, PWM0_Immediate_Mode, PWM0_FaultDetectionVoltage_Low, PWM0_WaveFilteringTime_0us);

  82.     PWM_CmdEX(PWM0_Type, ENABLE);

  83.     TimeSliceStartup(RGB_Scan, 20);
  84. }
这边就是对PWM的PWM_FaultDetectionConfigEX、PWM_FaultDetectionModeConfigEX这两个函数的应用功能不是太了解……


4、1路PWM控制蜂鸣器
对于蜂鸣器的控制我们可以使用将PWM使能或禁止的方式来控制,也可以通过修改PWM占空比的方式来控制;对于这两种方式,都做过尝试:使用将PWM使能或禁止的方式控制便捷,语句调度简单,但在下载MCU程序时,PWM存在触发蜂鸣器的嗒嗒声;而通过修改PWM占空比的方式,在下载程序时蜂鸣器不会误响,但在控制上需要注意,不能以极快的速度去切换PWM的占空比,这样有可能会导致程序卡死或者是MCU卡死(具体哪个卡了,还没分析),参考程序如下:
  1. /***********************************************************************************************************************
  2.   * @brief
  3.   * @param
  4.   * @retval
  5.   * @attention
  6.   *********************************************************************************************************************/
  7. void BUZZER_Init(void)
  8. {
  9. #if 0
  10.     uint16_t Frequency = 32000000 / BUZZER_PWM_FREQ;
  11.     uint16_t Duty      = 32000000 / BUZZER_PWM_FREQ * BUZZER_PWM_DUTY / 100;

  12.     PWM_DeInit();
  13.     PWM_Init(PWM4_PRESSEL_FHRC_D1, Frequency);
  14.     PWM_IndependentModeConfigEX(PWM40, Duty, PWM_OUTPUTSTATE_ENABLE);
  15.     PWM_CmdEX(PWM4_Type, DISABLE);
  16. #else
  17.     PWM_DeInit();
  18.     PWM_Init(PWM4_PRESSEL_FHRC_D1, 32000000 / BUZZER_PWM_FREQ);
  19.     PWM_IndependentModeConfigEX(PWM40, 0, PWM_OUTPUTSTATE_ENABLE);
  20.     PWM_CmdEX(PWM4_Type, ENABLE);
  21. #endif
  22. }

  23. /***********************************************************************************************************************
  24.   * @brief
  25.   * @param
  26.   * @retval
  27.   * @attention
  28.   *********************************************************************************************************************/
  29. void BUZZER_Enable(uint8_t State)
  30. {
  31. #if 0
  32.     if (ENABLE == State)
  33.     {
  34.         PWM_CmdEX(PWM4_Type, ENABLE);
  35.     }
  36.     else
  37.     {
  38.         PWM_CmdEX(PWM4_Type, DISABLE);
  39.     }
  40. #else
  41.     if (ENABLE == State)
  42.     {
  43.         PWM_IndependentModeConfig(PWM40, 32000000 / BUZZER_PWM_FREQ * BUZZER_PWM_DUTY / 100);
  44.     }
  45.     else
  46.     {
  47.         PWM_IndependentModeConfig(PWM40, 0);
  48.     }
  49. #endif
  50. }



5、通过芯片的LCD/LED外设功能驱动显示4位8段数码管
新定义的这款MCU不仅支持触摸功能,还带有LCD/LED段码显示功能,每一个段和位在MCU都对应一个显示内存,根据硬件设计在配置好相应的显示参数后,可以直接操作内存显示我们想要的内容,参考代码如下:
  1. /* Private typedef ****************************************************************************************************/
  2. typedef struct
  3. {
  4.     char    ch;
  5.     uint8_t Data;
  6. } LED_CodeTypeDef;

  7. /* Private define *****************************************************************************************************/

  8. /* Private macro ******************************************************************************************************/

  9. /* Private variables **************************************************************************************************/
  10. code LED_CodeTypeDef LED_CODE_TAB[38] =
  11. {
  12.     { ' ', 0x00 },
  13.     { '0', 0x3F },
  14.     { '1', 0x06 },
  15.     { '2', 0x5B },
  16.     { '3', 0x4F },
  17.     { '4', 0x66 },
  18.     { '5', 0x6D },
  19.     { '6', 0x7D },
  20.     { '7', 0x07 },
  21.     { '8', 0x7F },
  22.     { '9', 0x6F },
  23.     { 'A', 0x77 },
  24.     { 'b', 0x7C },
  25.     { 'c', 0x58 },
  26.     { 'C', 0x39 },
  27.     { 'd', 0x5E },
  28.     { 'E', 0x79 },
  29.     { 'F', 0x71 },
  30.     { 'g', 0x6F },
  31.     { 'H', 0x76 },
  32.     { 'h', 0x74 },
  33.     { 'i', 0x04 },
  34.     { 'I', 0x30 },
  35.     { 'J', 0x1E },
  36.     { 'l', 0x30 },
  37.     { 'L', 0x38 },
  38.     { 'n', 0x54 },
  39.     { 'o', 0x5C },
  40.     { 'O', 0x3F },
  41.     { 'P', 0x73 },
  42.     { 'q', 0x67 },
  43.     { 'r', 0x50 },
  44.     { 'S', 0x6D },
  45.     { 't', 0x78 },
  46.     { 'u', 0x1C },
  47.     { 'U', 0x3E },
  48.     { 'y', 0x6E },
  49.     { '-', 0x40 },
  50. };
  51. uint8_t LED_DisplayMode = 0;

  52. /* Private functions **************************************************************************************************/

  53. /***********************************************************************************************************************
  54.   * @brief
  55.   * @param
  56.   * @retval
  57.   * @attention
  58.   *********************************************************************************************************************/
  59. void LED_DisplayNumber(uint8_t Index, uint8_t Data)
  60. {
  61.     DDIC_Control_COM_TypeDef DDIC_COMn[4] =
  62.     {
  63.         DDIC_COM3, DDIC_COM2, DDIC_COM1, DDIC_COM0
  64.     };

  65.     DDIC_Control(DDIC_SEG4,  DDIC_COMn[Index], (Data >> 0x00) & 0x01);
  66.     DDIC_Control(DDIC_SEG16, DDIC_COMn[Index], (Data >> 0x01) & 0x01);
  67.     DDIC_Control(DDIC_SEG18, DDIC_COMn[Index], (Data >> 0x02) & 0x01);
  68.     DDIC_Control(DDIC_SEG20, DDIC_COMn[Index], (Data >> 0x03) & 0x01);
  69.     DDIC_Control(DDIC_SEG23, DDIC_COMn[Index], (Data >> 0x04) & 0x01);
  70.     DDIC_Control(DDIC_SEG6,  DDIC_COMn[Index], (Data >> 0x05) & 0x01);
  71.     DDIC_Control(DDIC_SEG17, DDIC_COMn[Index], (Data >> 0x06) & 0x01);
  72.     DDIC_Control(DDIC_SEG19, DDIC_COMn[Index], (Data >> 0x07) & 0x01);
  73. }

  74. /***********************************************************************************************************************
  75.   * @brief
  76.   * @param
  77.   * @retval
  78.   * @attention
  79.   *********************************************************************************************************************/
  80. void LED_DisplayString(char *str)
  81. {
  82.     uint8_t i = 0, Index = 0;

  83.     while ((*str != '\0') && (Index < 4))
  84.     {
  85.         for (i = 0; i < 38; i++)
  86.         {
  87.             if (*str == LED_CODE_TAB[i].ch)
  88.             {
  89.                 LED_DisplayNumber(Index, LED_CODE_TAB[i].Data);
  90.             }
  91.         }

  92.         str++;
  93.         Index++;
  94.     }
  95. }

  96. /***********************************************************************************************************************
  97.   * @brief
  98.   * @param
  99.   * @retval
  100.   * @attention
  101.   *********************************************************************************************************************/
  102. void LED_Scan(void)
  103. {
  104.     static uint16_t Count = 0;
  105.     char str[10];

  106.     if (0 == LED_DisplayMode)
  107.     {
  108.         memset(str, 0, sizeof(str));

  109.         sprintf(str, "%04d", Count);

  110.         LED_DisplayString(str);

  111.         Count = (Count + 1) % 10000;
  112.     }
  113. }

  114. /***********************************************************************************************************************
  115.   * @brief
  116.   * @param
  117.   * @retval
  118.   * @attention
  119.   *********************************************************************************************************************/
  120. void LED_Init(void)
  121. {
  122.     DDIC_DMOD_Selcet(DMOD_LED);
  123.     DDIC_Init(DDIC_DUTYCYCLE_D4,
  124.               DDIC_PIN_X0 | DDIC_PIN_X3,
  125.               DDIC_PIN_X0 | DDIC_PIN_X2,
  126.               DDIC_PIN_X4 | DDIC_PIN_X5 | DDIC_PIN_X6 | DDIC_PIN_X7,
  127.               DDIC_PIN_X0 | DDIC_PIN_X1 | DDIC_PIN_X2 | DDIC_PIN_X3);
  128.     DDIC_OutputPinOfDutycycleD4(SEG4_27COM0_3);
  129.     DDIC_Cmd(ENABLE);

  130.     TimeSliceStartup(LED_Scan, 100);
  131. }



6、通过板载的可调节电阻实现ADC检测与显示、通过2个可调节电阻实现比较器的功能
板载两个可调电阻,一个可调电阻是用于ADC采样调节的,另外一个电阻是用来调节比较器的外部比较电压的;通过这两个可调电阻,我们既可以实现ADC的功能,也可以实现比较器的功能,参考代码如下:
  1. /***********************************************************************************************************************
  2.   * @brief
  3.   * @param
  4.   * @retval
  5.   * @attention
  6.   *********************************************************************************************************************/
  7. void ADC_Configure(void)
  8. {
  9.     ADC_Init(ADC_PRESSEL_3CLOCK, ADC_Cycle_Null);
  10.     ADC_EAINConfig(ADC_EAIN_7,  ENABLE);
  11.     ADC_EAINConfig(ADC_EAIN_15, ENABLE);
  12.     ADC_Cmd(ENABLE);

  13.     TimeSliceStartup(ADC_Scan, 200);
  14. }

  15. /***********************************************************************************************************************
  16.   * @brief
  17.   * @param
  18.   * @retval
  19.   * @attention
  20.   *********************************************************************************************************************/
  21. uint16_t ADC_GetADCValue(ADC_Channel_TypeDef Channel)
  22. {
  23.     uint16_t Value = 0;

  24.     ADC_ChannelConfig(Channel, ENABLE);

  25.     ADC_StartConversion();

  26.     while (RESET == ADC_GetFlagStatus())
  27.     {
  28.         _nop_();
  29.     }

  30.     return (ADC_GetConversionValue());
  31. }

  32. /***********************************************************************************************************************
  33.   * @brief
  34.   * @param
  35.   * @retval
  36.   * @attention
  37.   *********************************************************************************************************************/
  38. void CMP_Scan(void)
  39. {
  40.     static uint8_t State = 0;

  41.     if (3 == LED_DisplayMode)
  42.     {
  43.         if (CMPCON & (ACMP_FLAG_CMPSTA)) /* CMP3 > CMPR */
  44.         {
  45.             if (1 != State)
  46.             {
  47.                 State = 1;
  48.                 BUZZER_Enable(ENABLE);
  49.             }
  50.         }
  51.         else                           /* CMP3 < CMPR */
  52.         {
  53.             if (0 != State)
  54.             {
  55.                 State = 0;
  56.                 BUZZER_Enable(DISABLE);
  57.             }
  58.         }

  59.         LED_DisplayString("----");
  60.     }
  61. }

  62. /***********************************************************************************************************************
  63.   * @brief
  64.   * @param
  65.   * @retval
  66.   * @attention
  67.   *********************************************************************************************************************/
  68. void CMP_Init(void)
  69. {
  70.     ACMP_Init(ACMP_VREF_8D16VDD, ACMP_VREF_EXTERNAL);
  71.     ACMP_Cmd(ENABLE);

  72.     TimeSliceStartup(CMP_Scan, 20);
  73. }



7、NTC实时温度检测与显示

NTC也是通过MCU的ADC功能来实现的,首先采样NTC的ADC数据,然后根据NTC的特性表对应的温度进行查表换算,最后通过LED数码管显示出来,参考代码如下:
  1. /* Private variables **************************************************************************************************/
  2. code uint16_t NTC_ADC_MapTable[100] =                        
  3. {
  4.     248 , 262 , 277 , 293 , 310 , 327 , 345 , 364 , 384 , 404 ,
  5.     425 , 447 , 470 , 494 , 518 , 543 , 570 , 597 , 624 , 653 ,
  6.     683 , 713 , 744 , 776 , 809 , 842 , 877 , 912 , 948 , 984 ,
  7.     1022, 1060, 1098, 1137, 1177, 1217, 1258, 1299, 1341, 1383,
  8.     1425, 1468, 1511, 1554, 1598, 1641, 1685, 1729, 1772, 1816,
  9.     1860, 1903, 1946, 1990, 2033, 2075, 2117, 2159, 2201, 2243,
  10.     2283, 2324, 2364, 2403, 2442, 2481, 2519, 2556, 2593, 2629,
  11.     2664, 2699, 2734, 2767, 2800, 2833, 2864, 2895, 2926, 2956,
  12.     2985, 3013, 3041, 3069, 3095, 3121, 3147, 3172, 3195, 3219,
  13.     3242, 3265, 3286, 3308, 3328, 3348, 3368, 3388, 3406, 3424,
  14. };

  15. /***********************************************************************************************************************
  16.   * @brief
  17.   * @param
  18.   * @retval
  19.   * @attention
  20.   *********************************************************************************************************************/
  21. void ADC_Scan(void)
  22. {
  23.     char   str[10];
  24.     uint16_t i = 0;
  25.     uint16_t Value;

  26.     if (1 == LED_DisplayMode)   /* CMP3 */
  27.     {
  28.         Value = ADC_GetADCValue(ADC_CHANNEL_15);

  29.         memset(str, 0, sizeof(str));
  30.         sprintf(str, "%04d", Value);
  31.         LED_DisplayString(str);
  32.     }

  33.     if (2 == LED_DisplayMode)   /* NTC */
  34.     {
  35.         Value = ADC_GetADCValue(ADC_CHANNEL_7);

  36.         for(i = 0; i < 99; i++)
  37.         {
  38.             if((Value >= NTC_ADC_MapTable[i]) && (Value < NTC_ADC_MapTable[i + 1]))
  39.             {
  40.                 break;
  41.             }
  42.         }

  43.         memset(str, 0, sizeof(str));

  44.         if(i < 15)
  45.         {
  46.             sprintf(str, "-%02dC", 15 - i);
  47.         }
  48.         else
  49.         {
  50.             sprintf(str, "%03dCC", i - 15);
  51.         }

  52.         LED_DisplayString(str);
  53.     }
  54. }



最后直接贴上完整的工程源代码:
Project_NBK-RD8x3x_NBK-EBS002.zip (203.31 KB, 下载次数: 12)


最终效果演示视频:


打赏榜单

21小跑堂 打赏了 80.00 元 2023-02-15
理由:恭喜通过原创审核!期待您更多的原创作品~

评论

一次玩遍扩展板的所有功能,一文道扩展板全部能力。通过作者扎实的自我能力和新定义强大的开发板结合,将一个51内核的芯片发光发热。  发表于 2023-2-15 14:03
www5911839 发表于 2023-2-16 07:48 | 显示全部楼层
大佬,文章写得太棒了,但是附件无法提取,方便上传百度网盘吗?谢谢


 楼主| xld0932 发表于 2023-2-16 18:56 | 显示全部楼层
www5911839 发表于 2023-2-16 07:48
大佬,文章写得太棒了,但是附件无法提取,方便上传百度网盘吗?谢谢

百度网盘要钱……看来你的爬虫还需要加强一下功能哈……
豌豆爹 发表于 2023-3-2 10:40 来自手机 | 显示全部楼层
爬虫是个什么梗
burgessmaggie 发表于 2023-3-11 19:42 | 显示全部楼层
板载功能不错的。              
primojones 发表于 2023-3-11 19:49 | 显示全部楼层
RD8x3x功能太强大了。              
primojones 发表于 2023-3-11 21:42 | 显示全部楼层
NBK-EBS002还可以互相叠加吗?
万图 发表于 2023-4-19 12:13 | 显示全部楼层
原来还有贴片的蜂鸣器
yorkbarney 发表于 2023-5-10 21:35 | 显示全部楼层
NBK-EBS002基础功能扩展板板载外设很给力。
janewood 发表于 2023-5-10 21:41 | 显示全部楼层
这个板子的性能怎么样              
mmbs 发表于 2023-5-10 21:59 | 显示全部楼层
NBK-EBS002基础功能扩展板很棒
mnynt121 发表于 2023-5-11 15:48 | 显示全部楼层
外设的板子之间的IO不会互相干扰吗
jonas222 发表于 2023-5-11 16:48 | 显示全部楼层
可以作为物联网的开发板了。              
您需要登录后才可以回帖 登录 | 注册

本版积分规则

个人签名:King.Xu

77

主题

3023

帖子

38

粉丝
快速回复 在线客服 返回列表 返回顶部
个人签名:King.Xu

77

主题

3023

帖子

38

粉丝
快速回复 在线客服 返回列表 返回顶部