Kaynağa Gözat

pwm灯光库完善. 串口输出功能调试完成

kindring 1 yıl önce
ebeveyn
işleme
327354e5f7

+ 20 - 10
ble-light.uvprojx

@@ -7,7 +7,7 @@
 
   <Targets>
     <Target>
-      <TargetName>app_wrist</TargetName>
+      <TargetName>wrist</TargetName>
       <ToolsetNumber>0x4</ToolsetNumber>
       <ToolsetName>ARM-ADS</ToolsetName>
       <pArmCC>5060960::V5.06 update 7 (build 960)::.\ARMCC</pArmCC>
@@ -341,7 +341,7 @@
               <MiscControls>-DADV_NCONN_CFG=0x01   -DADV_CONN_CFG=0x02   -DSCAN_CFG=0x04    -DINIT_CFG=0x08   -DBROADCASTER_CFG=0x01 -DOBSERVER_CFG=0x02   -DPERIPHERAL_CFG=0x04   -DCENTRAL_CFG=0x08   -DHOST_CONFIG=0x4</MiscControls>
               <Define>CFG_CP CFG_QFN32 CFG_SLEEP_MODE=PWR_MODE_NO_SLEEP DEBUG_INFO=1 USE_SYS_TICK HUGE_MODE=0</Define>
               <Undefine></Undefine>
-              <IncludePath>.\src;.\components\inc;.\components\common;.\components\osal\include;.\components\ble\include;.\components\ble\hci;.\components\ble\host;.\components\ble\controller\include;.\components\profiles\DevInfo;.\components\profiles\GATT;.\components\profiles\SimpleProfile;.\components\profiles\Roles;.\components\profiles\ota_app;.\components\profiles\hrs;.\components\driver\common;.\components\driver\log;.\components\driver\gpio;.\components\driver\uart;.\components\driver\i2c;.\components\driver\adc;.\components\driver\clock;.\components\driver\pwm;.\components\driver\pwrmgr;.\components\driver\kscan;.\components\driver\flash;.\components\driver\spi;.\components\driver\i2c;.\components\driver\watchdog;.\components\driver\timer;.\components\libraries\console;.\components\libraries\datetime;.\lib;.\src;.\src\ui;.\src\ble;.\src\epticore</IncludePath>
+              <IncludePath>.\src;.\components\inc;.\components\common;.\components\osal\include;.\components\ble\include;.\components\ble\hci;.\components\ble\host;.\components\ble\controller\include;.\components\profiles\DevInfo;.\components\profiles\GATT;.\components\profiles\SimpleProfile;.\components\profiles\Roles;.\components\profiles\ota_app;.\components\profiles\hrs;.\components\driver\common;.\components\driver\log;.\components\driver\gpio;.\components\driver\uart;.\components\driver\i2c;.\components\driver\adc;.\components\driver\clock;.\components\driver\pwm;.\components\driver\pwrmgr;.\components\driver\kscan;.\components\driver\flash;.\components\driver\spi;.\components\driver\i2c;.\components\driver\watchdog;.\components\driver\timer;.\components\libraries\console;.\components\libraries\datetime;.\lib;.\src;.\src\ui;.\src\ble;.\src\pwm_light;.\src\epticore</IncludePath>
             </VariousControls>
           </Cads>
           <Aads>
@@ -451,9 +451,9 @@
           <GroupName>app</GroupName>
           <Files>
             <File>
-              <FileName>OSAL_app.c</FileName>
+              <FileName>OSAL_wrist.c</FileName>
               <FileType>1</FileType>
-              <FilePath>.\src\OSAL_app.c</FilePath>
+              <FilePath>.\src\OSAL_wrist.c</FilePath>
             </File>
             <File>
               <FileName>app_wrist.c</FileName>
@@ -461,15 +461,25 @@
               <FilePath>.\src\app_wrist.c</FilePath>
             </File>
             <File>
-              <FileName>app_Main.c</FileName>
+              <FileName>wrist_Main.c</FileName>
               <FileType>1</FileType>
-              <FilePath>.\src\app_Main.c</FilePath>
+              <FilePath>.\src\wrist_Main.c</FilePath>
+            </File>
+            <File>
+              <FileName>light.c</FileName>
+              <FileType>1</FileType>
+              <FilePath>.\src\light.c</FilePath>
             </File>
             <File>
               <FileName>wrist_service.c</FileName>
               <FileType>1</FileType>
               <FilePath>.\src\ble\wrist_service.c</FilePath>
             </File>
+            <File>
+              <FileName>pwm_light.c</FileName>
+              <FileType>1</FileType>
+              <FilePath>.\src\pwm_light\pwm_light.c</FilePath>
+            </File>
           </Files>
         </Group>
         <Group>
@@ -652,13 +662,13 @@
       <component Cclass="CMSIS" Cgroup="CORE" Cvendor="ARM" Cversion="4.3.0" condition="Cortex-M Device">
         <package name="CMSIS" schemaVersion="1.3" url="http://www.keil.com/pack/" vendor="ARM" version="4.5.0"/>
         <targetInfos>
-          <targetInfo name="app_wrist"/>
+          <targetInfo name="wrist"/>
         </targetInfos>
       </component>
       <component Cclass="Device" Cgroup="Startup" Cvendor="ARM" Cversion="1.0.1" condition="ARMCM0 CMSIS">
         <package name="CMSIS" schemaVersion="1.3" url="http://www.keil.com/pack/" vendor="ARM" version="4.5.0"/>
         <targetInfos>
-          <targetInfo name="app_wrist"/>
+          <targetInfo name="wrist"/>
         </targetInfos>
       </component>
     </components>
@@ -668,7 +678,7 @@
         <component Cclass="Device" Cgroup="Startup" Cvendor="ARM" Cversion="1.2.2" condition="ARMCM0 CMSIS"/>
         <package name="CMSIS" schemaVersion="1.7.7" url="http://www.keil.com/pack/" vendor="ARM" version="5.9.0"/>
         <targetInfos>
-          <targetInfo name="app_wrist"/>
+          <targetInfo name="wrist"/>
         </targetInfos>
       </file>
       <file attr="config" category="sourceC" name="Device\ARM\ARMCM0\Source\system_ARMCM0.c" version="1.0.0">
@@ -676,7 +686,7 @@
         <component Cclass="Device" Cgroup="Startup" Cvendor="ARM" Cversion="1.2.2" condition="ARMCM0 CMSIS"/>
         <package name="CMSIS" schemaVersion="1.7.7" url="http://www.keil.com/pack/" vendor="ARM" version="5.9.0"/>
         <targetInfos>
-          <targetInfo name="app_wrist"/>
+          <targetInfo name="wrist"/>
         </targetInfos>
       </file>
       <file attr="config" category="sourceAsm" condition="ARMCC" name="Device\ARM\ARMCM4\Source\ARM\startup_ARMCM4.s" version="1.0.0">

+ 5 - 4
components/driver/gpio/gpio.h

@@ -133,11 +133,12 @@ typedef enum{
 	Bit_ENABLE,
 }BitAction_e;
 
+
 typedef enum{
-	FLOATING = 0x00,
-	WEAK_PULL_UP = 0x01,
-	STRONG_PULL_UP = 0x02,
-	PULL_DOWN = 0x03,
+	FLOATING = 0x00,// 悬空
+	WEAK_PULL_UP = 0x01,// 弱上拉
+	STRONG_PULL_UP = 0x02,// 强上拉
+	PULL_DOWN = 0x03,// 下拉
 }IO_Pull_Type_e;
 
 typedef enum{

+ 2 - 2
src/OSAL_app.c → src/OSAL_wrist.c

@@ -43,7 +43,7 @@ const pTaskEventHandlerFn tasksArr[] =
   GATT_ProcessEvent,
   GAPRole_ProcessEvent,
   GATTServApp_ProcessEvent,
-  App_ProcessEvent
+  appWristProcEvt
 };
 
 const uint8 tasksCnt = sizeof( tasksArr ) / sizeof( tasksArr[0] );
@@ -93,7 +93,7 @@ void osalInitTasks( void )
   GATTServApp_Init( taskID++ );
 
   /* Application */
-  appInit( taskID );
+  appWristInit( taskID );
 }
 
 /*********************************************************************

+ 50 - 26
src/app_wrist.c

@@ -18,9 +18,11 @@
 #include "log.h"
 #include "ll.h"
 
-
+#include "light.h"
 #include "app_wrist.h"
 #include "wrist_service.h"
+
+
 // GAP connection handle
 // 事件处理Id
 uint8 AppWrist_TaskID;  
@@ -35,9 +37,9 @@ static uint8 scanData[] =
 {
   0xa,   // length of this data
   GAP_ADTYPE_LOCAL_NAME_COMPLETE,
-  'P',
-  'h',
-  'y',
+  'b',
+  'l',
+  'e',
   'L',
   'i',
   'g',
@@ -72,7 +74,7 @@ static uint8 advertData[] =
  *
  * @return  none
 */
-static void appProcOSALMsg( osal_event_hdr_t *pMsg );
+static void appWristProcOSALMsg( osal_event_hdr_t *pMsg );
 static void WristGapStateCB( gaprole_States_t newState);
 
 // GAP Role Callbacks
@@ -82,26 +84,10 @@ static gapRolesCBs_t WristPeripheralCB =
   NULL                            // When a valid RSSI is read from controller
 };
 
-// 事件处理器
-uint16 App_ProcessEvent( uint8 task_id, uint16 events )
-{
-    if ( events & START_DEVICE_EVT )
-    {
-        // LOG("START_DEVICE_EVT\n");
-        // Start the Device
-        VOID GAPRole_StartDevice( &WristPeripheralCB );
 
-        // Register with bond manager after starting device
-    //    GAPBondMgr_Register( (gapBondCBs_t *) &WristBondCB );
-        
-        return ( events ^ START_DEVICE_EVT );
-    }
-     return 0;
-}
-
-static void appProcOSALMsg( osal_event_hdr_t *pMsg )
+static void appWristProcOSALMsg( osal_event_hdr_t *pMsg )
 {
-    LOG("[fn : appProcOSALMsg]  run event is: %d", pMsg->event);
+    LOG("[fn : appWristProcOSALMsg]  run event is: %d", pMsg->event);
 }
 
 // Notification from the profile of a state change
@@ -205,7 +191,7 @@ static void wristCB(uint8 event, uint8 param_size, uint8* param)
 }
 
 
-void appInit( uint8 task_id)
+void appWristInit( uint8 task_id)
 {
     AppWrist_TaskID = task_id;
 	LOG("\n\n\nappWristInit\n\n\n");
@@ -276,9 +262,47 @@ void appInit( uint8 task_id)
     app_datetime_init();
 
     // Setup a delayed profile startup
-   osal_set_event( AppWrist_TaskID, START_DEVICE_EVT );
+    osal_set_event( AppWrist_TaskID, START_DEVICE_EVT );
+
+    LOG("appWristInit end\n");
+    light_init();
+    LOG("light_init end\n");
+    light_set(0, 100);
 
     LOG("appWristInit end\n");
 
 
-}
+}
+
+// 事件处理器
+uint16 appWristProcEvt( uint8 task_id, uint16 events )
+{
+    if ( events & SYS_EVENT_MSG )
+    {
+        uint8 *pMsg;
+
+        if ( (pMsg = osal_msg_receive( AppWrist_TaskID )) != NULL )
+        {
+        appWristProcOSALMsg( (osal_event_hdr_t *)pMsg );
+
+        // Release the OSAL message
+        VOID osal_msg_deallocate( pMsg );
+        }
+
+        // return unprocessed events
+        return (events ^ SYS_EVENT_MSG);
+    }
+
+    if ( events & START_DEVICE_EVT )
+    {
+        // LOG("START_DEVICE_EVT\n");
+        // Start the Device
+        VOID GAPRole_StartDevice( &WristPeripheralCB );
+
+        // Register with bond manager after starting device
+    //    GAPBondMgr_Register( (gapBondCBs_t *) &WristBondCB );
+        
+        return ( events ^ START_DEVICE_EVT );
+    }
+     return 0;
+}

+ 18 - 6
src/app_wrist.h

@@ -8,7 +8,21 @@
 // 事件定义
 
 // 该事件用于同步时间, 组件内依赖该事件. 必须要定义该事件
-#define TIMER_DT_EVT                            0x0002  //for datetime sync
+#define TIMER_UI_EVT                            0x0002  //for UI timer event
+#define TIMER_DT_EVT                            0x0004  //for datetime sync
+#define TOUCH_PRESS_EVT                         0x0008  //for touch key event
+#define TIMER_HR_EVT                            0x0010  //for heartrate detect
+#define TIMER_BATT_EVT                          0x0020  //for battery detect
+#define BATT_VALUE_EVT                          0x0040  //event for battery voltage value update
+#define BATT_CHARGE_EVT                         0x0080  //event for battery charge status change
+#define ACC_DATA_EVT                            0x0100  //event for accelerator data change
+#define TIMER_LIGHT_EVT                         0x0200  //for led light timeout
+#define TIMER_KSCAN_DEBOUNCE_EVT                0x0400  //for keyscan debounce
+#define TIMER_KSCAN_REPEAT_EVT                  0x0800  //for keyscan repeat
+#define TIMER_KSCAN_LONG_EVT                    0x1000  //for keyscan long press
+#define TIMER_KSCAN_LONG_REPEAT_EVT             0x2000  //for keyscan long press repeat
+#define TIMER_KSCAN_LONG_REPEAT_STOP_EVT        0x4000  //for keyscan long press repeat stop
+
 
 // 电池电量监测
 #define BATTERY_MONITOR_EVT                     0x0004
@@ -66,14 +80,12 @@ static uint16 gapConnHandle;
 
 
 // 初始化 蓝牙应用
-extern void App_Init( uint8 task_id );
+extern void appWristInit( uint8 task_id );
 
 // 应用事件处理器
-extern uint16 App_ProcessEvent( uint8 task_id, uint16 events );
-
-
+extern uint16 appWristProcEvt( uint8 task_id, uint16 events );
 
+static void wristCB(uint8 event, uint8 param_size, uint8* param);
 
 
-static void wristCB(uint8 event, uint8 param_size, uint8* param);
 #endif /* __WRIST_H */

+ 5 - 20
src/ble/wrist_service.c

@@ -496,26 +496,11 @@ int on_recieved_cmd_packet(const uint8* data, uint16 len)
   print_hex(data, len);
   int i = 0;
   // 第一位为命令字 第二位为 值
-  switch(data[0]){
-    case 0xf0:
-      LOG("breathing light close\n");
-      osal_stop_timerEx(AppWrist_TaskID, 0x66ff);
-      break;
-    case 0xf1:
-      LOG("breathing light open\n");
-      osal_start_reload_timer(AppWrist_TaskID, 0x66ff, 100);
-      break;
-    case 0xf2:
-      LOG("change pwm mode\n");
-      // light_mode_change(data[1]);
-      break;
-    default :
-      // 直接视作灯光控制 转为10进制
-      LOG("light ctrl %d\n", data[0]);
-
-      //light_ctrl(1, data[0]);
-      break;
-  }
+  // cmdParse();
+  LOG("light ctrl %d\n", data[0]);
+  
+  light_set(0, data[0]);
+
   return ret;
 }
 

+ 42 - 0
src/light.c

@@ -0,0 +1,42 @@
+#include "pwm.h"
+#include "gpio.h"
+
+#include "OSAL.h"
+#include "log.h"
+
+#include "pwm_light.h"
+
+#include "light.h"
+
+// pwm 结构体数组 不定长 最大5个
+pwm_t pwm_light_list[] = {
+    {PWM_CH0, GPIO_WARM, 0, 100, 5, PWM_CLK_DIV_16},
+    {PWM_CH1, GPIO_COLD, 0, 100, 5, PWM_CLK_DIV_16},
+    {PWM_CH2, GPIO_FAN, 0, 100, 5, PWM_CLK_DIV_16},
+};
+
+int light_init(){
+    LOG("[light_init]\n");
+    // 初始化pwm
+    int ret = 0;
+    for (int i = 0; i < sizeof(pwm_light_list) / sizeof(pwm_t); i++) {
+        ret = pwm_light_init(&pwm_light_list[i]);
+        if (ret != 0) {
+            LOG("pwm_light_init err %d\n", ret);
+            return ret;
+        }
+    }
+    return ret;
+}
+
+int light_set(uint8_t ch, uint8_t val){
+    LOG("[light_set] set ch%d val to %d\n", ch, val);
+    int ret = 0;
+    if (ch >= sizeof(pwm_light_list) / sizeof(pwm_t)) {
+        LOG("ch%d not exist\n", ch);
+        return -1;
+    }
+    pwm_t *pwm = &pwm_light_list[ch];
+    ret = pwm_light_set_val(pwm, val);
+    return ret;
+}

+ 25 - 0
src/light.h

@@ -0,0 +1,25 @@
+
+#ifndef __LIGHT_H__
+#define __LIGHT_H__
+
+// 暖光 pwm脚
+#define GPIO_WARM P24
+// 冷光 pwm脚
+#define GPIO_COLD P25
+
+// 风扇 pwm
+#define GPIO_FAN P23
+// btn +
+#define GPIO_BTN_PLUS P26
+// btn -
+#define GPIO_BTN_MINUS P27
+
+
+// adc 电源监测脚
+#define GPIO_POWER P28
+
+extern int light_init(void);
+
+extern int light_set(uint8_t ch, uint8_t val);
+
+#endif

+ 23 - 3
src/main.c

@@ -18,7 +18,7 @@
 #include "adc.h"
 #include "pwrmgr.h"
 #include "string.h"
-// #include "phy_console.h"
+#include "phy_console.h"
 
 extern void  ble_main(void);
 
@@ -38,6 +38,24 @@ static void rf_wakeup_handler(void){
 }
 
 
+void cons_callback(uint16_t cmd_id, uint8_t argc, char** argv)
+{
+	LOG("cmd id is 0x%x, parameter num is %d\n", cmd_id, argc);
+	for(uint8_t i = 0; i<argc; i++){
+		LOG("param %d : %s\n", i, argv[i]);
+	}
+}
+const cons_cmd_t s_cmd_list[] = {
+	{0x0010, "cmd1"},
+	{0x0011, "cmd2"},
+	{0x0012, "cmd3"},
+	{0x0013, "cmd4"},
+	{0x0014, "cmd5"},
+	{0x0015, "cmd6"},
+	{0, NULL},
+};
+
+
 static void hal_init(void)
 {
 
@@ -57,7 +75,8 @@ static void hal_init(void)
 //   初始化 ADC(模数转换器)模块
   hal_adc_init();
 	
-//   console_init(s_cmd_list, cons_callback);
+  // 初始化log模块
+  console_init(s_cmd_list, cons_callback);
 	
   LOG("all driver init OK!\n");
 
@@ -110,7 +129,8 @@ int  main(void)
     hal_pwrmgr_init();
 
     hal_rfphy_init();  
-    							
+
+    LOG("start hal_init!\n");		
     hal_init();
 
     app_main();	

+ 137 - 0
src/pwm_light/pwm_light.c

@@ -0,0 +1,137 @@
+#include "pwm.h"
+#include "gpio.h"
+
+#include "pwm_light.h"
+
+// 申请5个通道的内存
+pwm_t pwm_light_chann_list[5];
+
+// 刷新 pwm 引脚
+static void pwm_light_reflash(void)
+{
+
+    // 遍历 pwm_light_chann_list
+    for (int i = 0; i < sizeof(pwm_light_chann_list) / sizeof(pwm_t); i++)
+    {
+        // 获取 pwm
+        pwm_t *pwm = &pwm_light_chann_list[i];
+
+        hal_pwm_close_channel(pwm->pwm_ch);
+        hal_pwm_destroy(pwm->pwm_ch);
+
+        hal_pwm_stop();
+
+        hal_gpio_pin_init(pwm->pin, IE);
+        hal_gpio_write(pwm->pin, WEAK_PULL_UP);
+
+        hal_pwm_init(pwm->pwm_ch, pwm->div, PWM_CNT_UP, PWM_POLARITY_FALLING);
+
+        hal_pwm_set_count_val(PWM_CH0, pwm->val, pwm->total);
+
+        hal_pwm_open_channel(PWM_CH1, pwm->pin);
+    }
+    hal_pwm_start();
+}
+
+// 创建 pwm
+int pwm_light_init(pwm_t *pwm)
+{
+    // 判断 pwm_ch 是否合法
+    if (pwm->pwm_ch < PWM_CH0 || pwm->pwm_ch > PWM_CH4)
+    {
+        return -1;
+    }
+
+    // 判断 pin 是否合法
+    if (pwm->pin < GPIO_P00 || pwm->pin > GPIO_P34)
+    {
+        return -2;
+    }
+
+    // 判断 val 是否合法
+    if (pwm->val > pwm->total)
+    {
+        return -3;
+    }
+
+    // 判断 step 是否合法
+    if (pwm->step > pwm->total)
+    {
+        return -4;
+    }
+
+    // 判断 div 是否合法
+    if (pwm->div < PWM_CLK_DIV_2 || pwm->div > PWM_CLK_DIV_128)
+    {
+        return -5;
+    }
+
+    // 判断 pwm_light_chann_list 是否已满
+    if (sizeof(pwm_light_chann_list) / sizeof(pwm_t) >= 5)
+    {
+        return -6;
+    }
+
+    // 判断 pwm 是否已存在
+    for (int i = 0; i < sizeof(pwm_light_chann_list) / sizeof(pwm_t); i++)
+    {
+        if (pwm_light_chann_list[i].pwm_ch == pwm->pwm_ch)
+        {
+            return -7;
+        }
+    }
+
+    // 添加 pwm
+    pwm_light_chann_list[sizeof(pwm_light_chann_list) / sizeof(pwm_t)] = *pwm;
+
+    // 刷新 pwm 引脚
+    pwm_light_reflash();
+
+    return 0;
+}
+
+int pwm_light_set_val(pwm_t *pwm, uint8_t val)
+{
+    // 判断 pwm_ch 是否合法
+    if (pwm->pwm_ch < PWM_CH0 || pwm->pwm_ch > PWM_CH4)
+    {
+        return -1;
+    }
+
+    // 判断 val 是否合法
+    if (val > pwm->total)
+    {
+        return -2;
+    }
+
+    // 设置 pwm
+    pwm->val = val;
+
+    // 刷新 pwm 引脚
+    pwm_light_reflash();
+
+    return 0;
+}
+
+int pwm_light_set_div(pwm_t *pwm, PWM_CLK_DIV_e div)
+{
+    // 判断 pwm_ch 是否合法
+    if (pwm->pwm_ch < PWM_CH0 || pwm->pwm_ch > PWM_CH4)
+    {
+        return -1;
+    }
+
+    // 判断 div 是否合法
+    if (div < PWM_CLK_DIV_2 || div > PWM_CLK_DIV_128)
+    {
+        return -2;
+    }
+
+    // 设置 pwm
+    pwm->div = div;
+
+    // 刷新 pwm 引脚
+    pwm_light_reflash();
+
+    return 0;
+}

+ 43 - 0
src/pwm_light/pwm_light.h

@@ -0,0 +1,43 @@
+#ifndef __PWM_LIGHT_H__
+#define __PWM_LIGHT_H__
+
+#include "gpio.h"
+
+
+
+// pwm 结构体
+typedef struct pwm_t {
+    PWMN_e pwm_ch;// pwm通道
+    GPIO_Pin_e pin;// gpio引脚
+    uint8_t val;// 当前值 15
+    uint8_t total;// 总量 0-100
+    uint8_t step;// 步长 5
+    PWM_CLK_DIV_e div;// pwm时钟分频
+} pwm_t;
+
+// pwm结构体数组 不定长 最大5个
+extern pwm_t pwm_light_list[];
+
+/**
+ * @brief 初始化pwm
+ * @param pwm pwm结构体
+*/
+extern int pwm_light_init(pwm_t *pwm);
+
+/**
+ * @brief 设置pwm值
+ * @param pwm pwm结构体
+ * @param val 新值
+ * @return 0 成功 -1 失败
+*/
+extern int pwm_light_set_val(pwm_t *pwm, uint8_t val);
+
+/**
+ * @brief 设置pwm频率
+ * @param pwm pwm结构体
+ * @param div 目标频率
+*/
+extern int pwm_light_set_div(pwm_t *pwm, PWM_CLK_DIV_e div);
+
+
+#endif

+ 0 - 0
src/app_Main.c → src/wrist_Main.c


+ 24 - 0
开发笔记.md

@@ -0,0 +1,24 @@
+
+# 开发笔记
+> 安信可蓝牙模块 pb02  
+> 相关笔记记录
+## 关键信息记录
+### 日志输出至串口
+> 想要开启日志必须要初始化log模块 `console_init`  
+> 在`main.c`中
+
+## 相关知识记录
+### `GPIO` 引脚 `上下拉`
+> 这部分代码在 `components/driver/gpio/gpio.h` 中  
+> 具体参考 `IO_Pull_Type_e`  
+
+#### `#d` 四种引脚模式
+
+1. (悬空):引脚处于高阻态,不连接到电源或地,没有外部电流流过。
+2. (弱上拉):引脚连接到电源,通过一个较大的电阻上拉到高电平,使引脚保持高电平。
+3. (强上拉):引脚连接到电源,通过一个较小的电阻上拉到高电平,使引脚保持高电平。
+4. (下拉):引脚连接到地,通过一个电阻下拉到低电平,使引脚保持低电平。
+
+#### `#e` 作用
+这个枚举类型用于描述IO引脚的上拉/下拉电路类型,对于数字电路设计和嵌入式系统开发非常有用。
+