分享一款嵌入式开源LED指示灯控制代码框架cotLed

一、工程简介

        cotLed是一款轻量级的LED控制软件框架,可以十分方便地控制及自定义LED的各种状态,移植方便,无需修改,只需要在初始化时实现单片机硬件GPIO初始化,同时为框架接口提供GPIO写函数即可。

        框架代码工程地址:https://gitee.com/cot_package/cot_led

        工程代码结构也很精简,只用两个文件cot_led.c和cot_led.h实现具体功能,对外提供API接口函数,适用于裸机和带操作系统的应用代码。

图片

        通过该软件框架API,可以实现的LED控制接口功能有:

        (1)、单个LED的亮灭、翻转、闪烁、呼吸灯、自定义(如多少秒快闪几次等)等多种功能;

        (2)、多个LED组合的跑马灯、流水灯等功能;

        (3)、上述各个功能模式功能实现的次数设置。


二、工程代码分析

        在头文件cot_led.h中包括:

        (1)定义了LED亮灭的枚举cotLedState_e;

        (2)定义了写入IO状态的函数指针cotLedCtrl_f;

        (3)定义了LED核心控制功能成员变量的结构体cotLedProc_t;

        (4)外部声明的LED控制接口函数。

/* Define to prevent recursive inclusion -----------------------------------------------------------------------------*/
#ifndef _COT_LED_H_
#define _COT_LED_H_

/* Includes ----------------------------------------------------------------------------------------------------------*/
#include <stdint.h>
#include <stddef.h>
#include <stdbool.h>

/* Exported types ----------------------------------------------------------------------------------------------------*/

// 状态bit位所使用的byte数,bit之间的控制时间为时间颗粒度
#define LED_STATE_BYTE_NUM       4

/**
  * @brief  LED亮灭枚举定义
  */
typedef enum{
    COT_LED_OFF = 0,                     /*!< (0)灯灭 */
    COT_LED_ON = !COT_LED_OFF            /*!< (1)灯亮 */
} cotLedState_e;

typedef void (*cotLedCtrl_f)(cotLedState_e state);
typedef uint16_t led_t;

typedef struct
{
    uint8_t validBits;                 /*!< 状态有效bit位 */
    uint8_t offset;                    /*!< 状态bit位偏移 */
    uint8_t count;                     /*!< 控制次数 */
    uint8_t isSetCount : 1;            /*!< 是否设置了控制次数 */
    uint8_t defState : 1;              /*!< 默认状态 */
    uint8_t curState : 1;              /*!< 当前状态 */
    uint8_t pwmDir : 1;                /*!< PWM增减方向 */
    uint8_t isPwm : 1;                 /*!< PWM模式 */
    uint16_t tic;                      /*!< 时间计数器 */
    uint16_t interval;                 /*!< 每次控制的时间颗粒度,单位为1ms */
    union
    {
        struct
        {
            uint16_t onTime;               /*!< 亮的时长 */
            uint16_t tic;                  /*!< PWM计时 */
        } pwm;
        uint8_t state[LED_STATE_BYTE_NUM];  /*!< 状态bit位 */
    } data;
} cotLedProc_t;

typedef struct
{
    cotLedProc_t proc;
    cotLedCtrl_f pfnLedCtrl;
} cotLedCfg_t;

/* Exported constants ------------------------------------------------------------------------------------------------*/
/* Exported macro ----------------------------------------------------------------------------------------------------*/
/* Exported functions ------------------------------------------------------------------------------------------------*/

extern int cotLed_Init(cotLedCfg_t pCfgTable[], size_t num);

extern int cotLed_SetState(led_t led, cotLedState_e state);
extern int cotLed_SetStateWithTime(led_t led, cotLedState_e state, uint16_t time);

extern int cotLed_ON(led_t led);
extern int cotLed_OFF(led_t led);
extern int cotLed_Toggle(led_t led);

extern int cotLed_Twinkle(led_t led, uint16_t time);
extern int cotLed_TwinkleWithCount(led_t led, uint16_t time, uint8_t count, cotLedState_e defState);

extern int cotLed_Breathe(led_t led, uint16_t period);
extern int cotLed_BreatheWithCount(led_t led, uint16_t period, uint8_t count, cotLedState_e defState);

extern int cotLed_Custom(led_t led, ...);
extern int cotLed_CustomWithCount(led_t led, uint8_t count, cotLedState_e defState, ...);

extern int cotLed_Marquee(led_t led[], uint8_t ledNum, int32_t time);
extern int cotLed_MarqueeWithCount(led_t led[], uint8_t ledNum, int32_t time, uint8_t count, cotLedState_e defState);
extern int cotLed_Waterfall(led_t led[], uint8_t ledNum, int32_t time);
extern int cotLed_WaterfallWithCount(led_t led[], uint8_t ledNum, int32_t time, uint8_t count, cotLedState_e defState);

extern int cotLed_Ctrl(uint32_t sysTime);

#endif

        由于cot_led.c中代码比较多,这里暂时就不贴出,可以参考具体文件中的函数定义和注释内容。

        在头文件cot_led.c中包括:

        (1)呼吸灯软件模拟PWM频率;

        (2)在LED控制接口中需要用到的一些宏定义;

        (3)各类型的LED控制接口。

图片


三、工程代码应用

        工程代码的使用可以参考工程代码包中的examples和readme文件。这里以在stm32平台上使用带有freertos的应用代码中进行各个LED接口函数的测试,测试时使用宏开关TEST_LED_MODE控制分别进行接口功能测试。在应用代码中进行了接口使用的注释。

        应用的流程顺序为:

        (1)初始化各个LED对应GPIO口驱动。

        (2)定义各个LED的IO状态控制函数,调用LED控制初始化函数cotLed_Init,入参为各个LED的IO状态控制函数和LED数量。

        (3)创建周期执行逻辑代码,在带操作系统的代码中创建周期任务;而在裸机系统代码中则创建周期计数逻辑或定时器逻辑。

        (4)在周期执行逻辑代码中周期调用LED控制函数cotLed_Ctrl,入参为当前时间戳ms级的系统时长。

        (5)条件触发调用执行对应的各个LED控制接口函数。

        应用时的一些注意点如下:

        (1)调用接口函数时,不要重复调用,重复调用设置函数相关信息会复位,使用触发式调用即达到某一触发条件时调用接口一次。在实际测试时LED翻转接口cotLed_Toggle需要在循环中重复调用。

        (2)在调用的带时间设置入参的LED控制接口时,该时间需要设置为任务调度周期的倍数;裸机调用时设置为定时器或计数器周期的倍数。比如调度周期或计数器周期为500ms,为该接口设置的时间参数就为500*N。

        (3)如果设置某个LED为呼吸灯模式,则需要保证cotLed_Ctrl调用周期为1ms(优先级需要最高,或者定时器调度效果最好)。

        (4)在操作系统下使用时非线程安全,最好可以使用读写锁,如果没有读写锁则至少使用互斥锁。

#include "sys.h"
#include "delay.h"
#include "FreeRTOS.h"
#include "task.h"
#include "cot_led.h"

//任务优先级
#define START_TASK_PRIO     1
//任务堆栈大小    
#define START_STK_SIZE      128  
//任务句柄
TaskHandle_t StartTask_Handler;
//任务函数
void start_task(void *pvParameters);

//任务优先级
#define LED0_TASK_PRIO      2
//任务堆栈大小    
#define LED0_STK_SIZE       50  
//任务句柄
TaskHandle_t LED0Task_Handler;
//任务函数
void led0_task(void *pvParameters);

//任务优先级
#define LED1_TASK_PRIO      3
//任务堆栈大小    
#define LED1_STK_SIZE       50  
//任务句柄
TaskHandle_t LED1Task_Handler;
//任务函数
void led1_task(void *pvParameters);

typedef enum
{
    LED_0 = 0,
    LED_1,
    /* 勿删除,用来统计LED的数目 */
    LED_MAX_NUM
} LedType_e;

//LED的IO驱动初始化
void LED_Init(void)
{       
  GPIO_InitTypeDef  GPIO_InitStructure;
  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOF, ENABLE);  //使能GPIOF时钟
  //GPIOF9,F10初始化设置
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9 | GPIO_Pin_10;  //LED0和LED1对应IO口
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;      //普通输出模式
  GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;      //推挽输出
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;    //100MHz
  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;      //上拉
  GPIO_Init(GPIOF, &GPIO_InitStructure);          //初始化GPIO
  GPIO_SetBits(GPIOF,GPIO_Pin_9 | GPIO_Pin_10);      //GPIOF9,F10设置高,灯灭

}

void CtrlLed0(cotLedState_e state) //LED0的IO状态控制函数
{
    state == COT_LED_ON ? GPIO_ResetBits(GPIOF, GPIO_Pin_9) :  GPIO_SetBits(GPIOF, GPIO_Pin_9);
}

void CtrlLed1(cotLedState_e state) //LED1的IO状态控制函数
{
    state == COT_LED_ON ? GPIO_ResetBits(GPIOF, GPIO_Pin_10) :  GPIO_SetBits(GPIOF, GPIO_Pin_10);
}

void FML_LED_Init(void)
{
    static cotLedCfg_t s_ledTable[LED_MAX_NUM] = {
        {.pfnLedCtrl = CtrlLed0},
        {.pfnLedCtrl = CtrlLed1},
    };

    LED_Init();             //初始化LED驱动IO端口
    cotLed_Init(s_ledTable, LED_MAX_NUM); //LED控制初始化
}

int main(void)
{ 
    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);//设置系统中断优先级分组4
    delay_init(168);        //初始化延时函数
    FML_LED_Init();
    
    //创建开始任务
    xTaskCreate((TaskFunction_t )start_task,            //任务函数
                (const char*    )"start_task",          //任务名称
                (uint16_t       )START_STK_SIZE,        //任务堆栈大小
                (void*          )NULL,                  //传递给任务函数的参数
                (UBaseType_t    )START_TASK_PRIO,       //任务优先级
                (TaskHandle_t*  )&StartTask_Handler);   //任务句柄              
    vTaskStartScheduler();          //开启任务调度
}

#define TEST_LED_MODE  1   //用于测试各个LED控制接口的宏开关

//开始任务任务函数
void start_task(void *pvParameters)
{
    taskENTER_CRITICAL();           //进入临界区
#if ((TEST_LED_MODE >= 1) && (TEST_LED_MODE <= 6))
    //创建LED0任务
    xTaskCreate((TaskFunction_t )led0_task,         
                (const char*    )"led0_task",       
                (uint16_t       )LED0_STK_SIZE, 
                (void*          )NULL,              
                (UBaseType_t    )LED0_TASK_PRIO,    
                (TaskHandle_t*  )&LED0Task_Handler);                        
    vTaskDelete(StartTask_Handler); //删除开始任务
#else                               
    //创建LED1任务
    xTaskCreate((TaskFunction_t )led1_task,     
                (const char*    )"led1_task",   
                (uint16_t       )LED1_STK_SIZE, 
                (void*          )NULL,
                (UBaseType_t    )LED1_TASK_PRIO,
                (TaskHandle_t*  )&LED1Task_Handler);    
#endif                              
    taskEXIT_CRITICAL();            //退出临界区
}

//LED任务函数 
void led0_task(void *pvParameters)
{       
#if (TEST_LED_MODE == 1)
    cotLed_Twinkle(LED_0, 2000); //设置LED0每隔2s进行闪烁(亮灭间隔时间)
    cotLed_Twinkle(LED_1, 5000); //设置LED1每隔5s进行闪烁(亮灭间隔时间
#elif (TEST_LED_MODE == 2)
  //设置LED0每隔2s秒进行闪烁,共5次(一亮一灭为一次),次数完成后灯灭
    cotLed_TwinkleWithCount(LED_0, 2000, 5, COT_LED_ON);
  //设置LED1每隔1s秒进行闪烁,共4次(一亮一灭为一次),次数完成后点亮
    cotLed_TwinkleWithCount(LED_1, 1000, 4, COT_LED_OFF);
#elif (TEST_LED_MODE == 3)
    cotLed_SetStateWithTime(LED_0, COT_LED_ON, 5000);//设置LED0亮持续5秒后熄灭
    cotLed_SetStateWithTime(LED_1, COT_LED_OFF, 3000);//设置LED1灭持续5秒后点亮
#endif      
    while(1)
    {
#if (TEST_LED_MODE == 4)
        cotLed_Toggle(LED_0);//周期翻转LED0
        cotLed_Toggle(LED_1);//周期翻转LED1   
#elif (TEST_LED_MODE == 5)          
    if (xTaskGetTickCount() == 0) {
      cotLed_ON(LED_0);//点亮LED0
      cotLed_ON(LED_1);//点亮LED1
    } else if (xTaskGetTickCount() == 5000) {
      cotLed_OFF(LED_0);//熄灭LED0
      cotLed_OFF(LED_1);//熄灭LED1
    } else if(xTaskGetTickCount() == 10000) {
      cotLed_ON(LED_0);
      cotLed_ON(LED_1);
    }
#elif (TEST_LED_MODE == 6)              
    if (xTaskGetTickCount() == 0) {
        cotLed_SetState(LED_0, COT_LED_ON);//点亮LED0
      cotLed_SetState(LED_1, COT_LED_ON);//点亮LED1
    } else if(xTaskGetTickCount() == 5000) {
      cotLed_SetState(LED_0, COT_LED_OFF);//熄灭LED0
      cotLed_SetState(LED_1, COT_LED_OFF);//熄灭LED1
    } else if(xTaskGetTickCount() == 10000) {
      cotLed_SetState(LED_0, COT_LED_ON);
      cotLed_SetState(LED_1, COT_LED_ON);
    }
#endif
        //周期调用LED控制函数,入参为当前时间戳ms级的系统时长
        cotLed_Ctrl(xTaskGetTickCount());
        vTaskDelay(100);
    }
} 

//LED1任务函数 
void led1_task(void *pvParameters)
{
#if (TEST_LED_MODE == 7)
  //LED0在2秒内1次快闪,亮100ms,灭1900ms,无限制次数
    cotLed_Custom(LED_0, 100, -1900, 0);
  //LED1在3秒内1次快闪,亮200ms,灭2800ms,无限制次数
    cotLed_Custom(LED_1, 200, -2800, 0);
#elif (TEST_LED_MODE == 8)
    //LED0在2秒内3次快闪,总共5次,次数完成后灯灭  
    cotLed_CustomWithCount(LED_0, 5, COT_LED_OFF, 100, -100, 100, -100, 100, -100, -1400, 0);
  //LED1在3秒内2次快闪,总共8次,次数完成后灯亮  
    cotLed_CustomWithCount(LED_1, 8, COT_LED_ON, 200, -200, 200, -200, -2200, 0);
#elif (TEST_LED_MODE == 9)      
    cotLed_Breathe(LED_0, 2000);//LED0在2秒内完成一次呼吸亮灭操作,一直执行不限次数
    cotLed_Breathe(LED_1, 3000);//LED1在3秒内完成一次呼吸亮灭操作,一直执行不限次数
#elif (TEST_LED_MODE == 10)
  //LED0在2秒内完成一次呼吸亮灭操作,总共3次,次数完成后灯灭
    cotLed_BreatheWithCount(LED_0, 2000, 3, COT_LED_OFF);
  //LED1在3秒内完成一次呼吸亮灭操作,总共5次,次数完成后灯亮
    cotLed_BreatheWithCount(LED_1, 3000, 5, COT_LED_ON);
#elif (TEST_LED_MODE == 11)
    led_t led[] = {LED_0, LED_1};
    cotLed_Waterfall(led, 2, 300);//流水灯一直执行,LED之间亮间隔300ms
#elif (TEST_LED_MODE == 12)
    led_t led[] = {LED_0, LED_1};
    //流水灯执行8次,LED之间亮间隔300ms,执行完后熄灭
    cotLed_WaterfallWithCount(led, 2, 300, 8, COT_LED_OFF);
#elif (TEST_LED_MODE == 13) 
     led_t led[] = {LED_0, LED_1};
    cotLed_Marquee(led, 2, 500);//跑马灯一直执行,LED之间亮间隔500ms
#elif (TEST_LED_MODE == 14) 
    led_t led[] = {LED_0, LED_1};
    //跑马灯执行5次,LED之间亮间隔500ms,执行完后熄灭
    cotLed_MarqueeWithCount(led, 2, 500, 5, COT_LED_OFF);
#endif
    while(1)
    {
    //周期调用LED控制函数,入参为当前时间戳ms级的系统时长
        cotLed_Ctrl(xTaskGetTickCount());
        vTaskDelay(1);
    }
}

↓↓↓更多技术内容和书籍资料获取,入群技术交流敬请关注“明解嵌入式”↓↓↓ 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/793312.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【电子通识】无源元件与有源元件的定义和区别是什么?

当提到构成电路的电子器件时,许多人可能会想到晶体管、电容器、电感器和电阻器等器件。一般情况下,我们使用的电子器件分为两大类,即“有源元件”和“无源元件”。 有源元件是主动影响(如放大、整流、转换等)所供给电能的元件。 无源元件是对所供给的电能执行被动…

Linux编程第三篇:Linux简介,开源软件简介(Linux是否安全?参考TESEC指标)

业精于勤荒于嬉&#xff0c;行成于思毁于随。 今天这篇算是Linux的正式学习&#xff0c;废话不多说&#xff0c;我们开始吧 第三篇 一、UNIX与Linux发展史1.1、UNIX发展历史和发行版本1.2、UNIX主要发行版本1.3、Linux发展历史1.4、Linux内核版本1.5、Linux主要发行版本 二、开…

土木转行嵌入式,拿到一家初创公司的嵌入式研发offer,值得去吗

在开始前刚好我有一些资料&#xff0c;是我根据网友给的问题精心整理了一份「嵌入式的资料从专业入门到高级教程」&#xff0c; 点个关注在评论区回复“888”之后私信回复“888”&#xff0c;全部无偿共享给大家&#xff01;&#xff01;&#xff01;不论从未来行业的发展前景…

Linux 初识

目录 ​编辑 1.Linux发展史 1.1UNIX发展历史 1.2Linux发展历史 2.Linux的开源属性 2.1 开源软件的定义 2.2 Linux的开源许可证 2.3 开源社区与协作 3.Linux的企业应用现状 3.1 服务器 3.1.1 Web服务器 3.1.2 数据库服务器 3.1.3 文件服务器 3.1.4 电子邮件服务器 …

基于Android平台开发,备忘录记事本

相关视频教程在某站上面(&#x1f50d;浩宇软件开发) 1. 项目功能思维导图 2. 项目涉及到的技术点 使用CountDownTimer实现开屏页倒计时使用SQLite数据库存储数据使用BottomNavigationView实现底部导航栏使用ActivityFragment实现底部导航栏页面切换使用RecyclerViewadapter实…

uni-app/vue项目如何封装全局消息提示组件

效果图&#xff1a; 第一步&#xff1a;封装组件和方法&#xff0c;采用插件式注册&#xff01; 在项目目录下新建components文件夹&#xff0c;里面放两个文件&#xff0c;分别是index.vue和index.js. index.vue&#xff1a; <template><div class"toast&quo…

为什么广告需要教育视频

教育视频作为一种广告工具越来越受欢迎&#xff0c;因为它们能够有效地传达信息并吸引观众的注意力。以下是需要此类视频的几个关键原因&#xff1a; 提高参与度 互动性&#xff1a;教育视频吸引注意力&#xff0c;让观众长时间参与&#xff0c;并让他们参与学习过程。产品演…

具有 0.5V 超低输入电压的 3A 升压转换器TPS61021

1 特性 输入电压范围&#xff1a;0.5V 至 4.4V 启动时的最小输入电压为 0.9V 可设置的输出电压范围&#xff1a;1.8V 到 4.0V 效率高达 91%&#xff08;VIN 2.4V、VOUT 3.3V 且 IOUT 1.5A 时&#xff09; 2.0MHz 开关频率 IOUT > 1.5A&#xff0c;VOUT 3.3V&#xff08;V…

【C语言】C语言-学生籍贯信息记录系统(源码+论文)【独一无二】

&#x1f449;博__主&#x1f448;&#xff1a;米码收割机 &#x1f449;技__能&#x1f448;&#xff1a;C/Python语言 &#x1f449;公众号&#x1f448;&#xff1a;测试开发自动化【获取源码商业合作】 &#x1f449;荣__誉&#x1f448;&#xff1a;阿里云博客专家博主、5…

使用Docker制作python项目镜像

各docker桌面版本集合&#xff1a;如果提示新版本系统不支持&#xff0c;可下载旧版本 我也分享在下面。 链接: https://pan.baidu.com/s/1HvaO2wOIE3pNE0bM7Qm3sA?pwdg7ky 提取码: g7ky –来自百度网盘超级会员v2的分享 来源参考&#xff1a;https://zhuanlan.zhihu.com/p/65…

C++|智能指针

目录 引入 一、智能指针的使用及原理 1.1RAII 1.2智能指针原理 1.3智能指针发展 1.3.1std::auto_ptr 1.3.2std::unique_ptr 1.3.3std::shared_ptr 二、循环引用问题及解决方法 2.1循环引用 2.2解决方法 三、删除器 四、C11和boost中智能指针的关系 引入 回顾上…

休息时间c++

题目描述 小杨计划在某个时刻开始学习&#xff0c;并决定在学习k秒后开始休息。 小杨想知道自己开始休息的时刻是多少。 输入 前三行每行包含一个整数&#xff0c;分别表示小杨开始学习时刻的时h、分m、秒s(h&#xff0c;m&#xff0c;s的值符合1≤h≤12,0≤m≤59,0≤s≤59)…

外贸展示型网站设计

清洁能源风能设备wordpress外贸公司模板 风能设备wordpress外贸公司模板&#xff0c;做新能源网通设备的公司网站模板。 https://www.jianzhanpress.com/?p3606 钢材wordpress外贸公司模板 金属钢材wordpress外贸公司模板&#xff0c;做金属成品贸易公司的企业网站模板。 …

智慧营区人员考勤管理系统|DW-S406系统实现无感考勤

智慧营区人员管理系统&#xff08;DW-S406系统&#xff09;通过建设人员基本信息管理功能&#xff0c;实现人力资源可视化、规范化管理&#xff0c;使人力资源管理工作决策的高效化、制度化得到有力保障&#xff0c;真正达到集中管理、集权管理的目标。主要实现营区人员管理、访…

Apache Dubbo与Nacos整合过程

Dubbo服务发现 Dubbo 提供的是一种 Client-Based 的服务发现机制&#xff0c;依赖第三方注册中心组件来协调服务发现过程&#xff0c;支持常用的注册中心如 Nacos、Consul、Zookeeper 等。 以下是 Dubbo 服务发现机制的基本工作原理图&#xff1a; 服务发现包含提供者、消费者…

C++:重定义

派生类和基类的同名成员问题 派生类中再实现一个基类中的方法会怎样 (1)代码实验&#xff1a;派生类和基类中各自实现一个内容不同但函数原型完全相同的方法&#xff0c;会怎么样 (2)结论&#xff1a;基类对象调用的是基类的方法&#xff0c;派生类对象调用执行的是派生类中重…

AWS认证考试流程:从准备到通过

AWS认证是IT行业中备受推崇的专业资格认证之一&#xff0c;它不仅可以验证您的AWS技能&#xff0c;还能提升您的职业竞争力。本文将为您详细介绍AWS认证考试的完整流程&#xff0c;从初步准备到最终通过认证。 选择适合的认证级别 AWS提供多个级别的认证&#xff0c;包括&…

OWASP ZAP

OWASP ZAP简介 开放式Web应用程序安全项目&#xff08;OWASP&#xff0c;Open Web Application Security Project&#xff09;是一个组织&#xff0c;它提供有关计算机和互联网应用程序的公正、实际、有成本效益的信息。ZAP则是OWASP里的工具类项目&#xff0c;也是旗舰项目&a…

DP(2) | Java | LeetCode 62, 63, 343, 96 做题总结(96 未完)

62.不同路径 我的代码&#xff08;报错&#xff09; 写的过程中感到很迷惑的点&#xff1a;①二维数组和这道题目的对应弄不清除&#xff0c;m n的初始化 是 dp[m][n] 还是 dp[n][m] ② class Solution {public int uniquePaths(int m, int n) {int[][]dp new int[m1][n1];d…

JavaScript(9)——作用域的一些问题

如果在函数内部&#xff0c;变量没有声明直接赋值&#xff0c;也会当做全局变量看。强烈不推荐&#xff01;&#xff01; function op() {num 80}op()console.log(num) 在不同作用域下&#xff0c;可能存在变量命名冲突的情况&#xff1a; let num 10 function fn(){let num…