ESP32-C3 入门笔记04:gpio_key 按键 (ESP-IDF + VSCode)

1.GPIO简介

ESP32-C3是QFN32封装,GPIO引脚一共有22个,从GPIO0到GPIO21。

理论上,所有的IO都可以复用为任何外设功能,但有些引脚用作连接芯片内部FLASH或者外部FLASH功能时,官方不建议用作其它用途。

通过开发板的原理图,可以看到开发板上的ESP32引脚连接情况。这里我们使用BOOT按键,来学习一下GPIO功能。

ESP32的GPIO,可以用作输入、输出,可以配置内部上拉、下拉,可以配置为中断引脚。

这里我们把连接 BOOT按键的IO9 引脚,设置为GPIO中断,接收BOOT按键请求。

在这里插入图片描述

2.编写程序

我们复制 esp-idf-v5.1.4\examples\get-started\sample_project 这个工程到我们的实验文件夹,然后把这个文件夹的名称修改为 gpio_key,方便日后搞清楚这个工程的作用。

在ESP-IDF的安装路径下,打开官方例程:D:\ESP_IDF\INS\Espressif\frameworks\esp-idf-v5.1.4\examples\get-started

在这里插入图片描述

使用 VSCode 打开 gpio_key 这个文件夹。单击打开工程一级目录下的 CMakeLists.txt 文件(注意不是 main 目录下的),然后我们把工程名字修改为 gpio_key,保存后关闭此文件。
在这里插入图片描述

点击打开main.c文件,发现里面只写了这么几行代码:

#include <stdio.h>

void app_main(void)
{

}

从这个工程原来的文件夹名字就可以知道,这是一个示例工程,我们现在需要实现按键中断,比较简单,所以在这个工程上写就可以了。

现在再打开一个VSCode软件,然后打开esp-idf-v5.1.4整个工程文件夹,然后我们依次找到
examples\peripherals\gpio\generic_gpio这个工程作为参考,注意不要修改这个工程中的内容和配置,只是作为参考。

在这里插入图片描述

单击gpio_example_main.c打开这个文件,找到app_main函数。

/* GPIO Example

   This example code is in the Public Domain (or CC0 licensed, at your option.)
   
   Unless required by applicable law or agreed to in writing, this
   software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
   CONDITIONS OF ANY KIND, either express or implied.
*/

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <inttypes.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/queue.h"
#include "driver/gpio.h"

/**
 * Brief:
 * This test code shows how to configure GPIO and how to use GPIO interrupts.
 *
 * GPIO status:
 * GPIO18: output (ESP32C2/ESP32H2 uses GPIO8 as the second output pin)
 * GPIO19: output (ESP32C2/ESP32H2 uses GPIO9 as the second output pin)
 * GPIO4:  input, pulled up, interrupt from rising edge and falling edge
 * GPIO5:  input, pulled up, interrupt from rising edge.
 *
 * Note. These are the default GPIO pins to be used in the example. You can
 * change IO pins in menuconfig.
 *
 * Test:
 * Connect GPIO18(8) with GPIO4
 * Connect GPIO19(9) with GPIO5
 * Generate pulses on GPIO18(8)/19(9), that triggers interrupt on GPIO4/5
 */

#define GPIO_OUTPUT_IO_0    CONFIG_GPIO_OUTPUT_0
#define GPIO_OUTPUT_IO_1    CONFIG_GPIO_OUTPUT_1
#define GPIO_OUTPUT_PIN_SEL  ((1ULL<<GPIO_OUTPUT_IO_0) | (1ULL<<GPIO_OUTPUT_IO_1))

#define GPIO_INPUT_IO_0     CONFIG_GPIO_INPUT_0
#define GPIO_INPUT_IO_1     CONFIG_GPIO_INPUT_1
#define GPIO_INPUT_PIN_SEL  ((1ULL<<GPIO_INPUT_IO_0) | (1ULL<<GPIO_INPUT_IO_1))

#define ESP_INTR_FLAG_DEFAULT 0 // 中断标志的宏定义

// 将 GPIO 中断事件发送到这个队列gpio_evt_queue,以便在任务中处理。
// gpio_evt_queue 被用来接收中断处理程序发送的 GPIO 事件然后由 gpio_task_example 任务处理这些事件。

static QueueHandle_t gpio_evt_queue = NULL; // 静态队列句柄

// ISR 中断服务函数
static void IRAM_ATTR gpio_isr_handler(void* arg)
{
    uint32_t gpio_num = (uint32_t) arg;
	
	//xQueueSendFromISR是在 ISR(中断服务例程)中发送数据到 FreeRTOS 队列的函数调用。
	//gpio_evt_queue:要发送数据的队列句柄。
	//&gpio_num:要发送的数据,这里是指向 GPIO 编号的指针,表示触发中断的引脚。
	//NULL:优先级参数
    xQueueSendFromISR(gpio_evt_queue, &gpio_num, NULL); 
	
}

// GPIO 任务函数
static void gpio_task_example(void* arg)
{
    uint32_t io_num;
    for(;;) {
		// 任务处理  处理gpio_evt_queue里面的任务
        if(xQueueReceive(gpio_evt_queue, &io_num, portMAX_DELAY)) {
            printf("GPIO[%"PRIu32"] intr, val: %d\n", io_num, gpio_get_level(io_num));
        }
    }
}

void app_main(void)
{
    // 零初始化配置结构
    gpio_config_t io_conf = {};
    
    // 配置输出引脚
    io_conf.intr_type = GPIO_INTR_DISABLE; // 禁用中断
    io_conf.mode = GPIO_MODE_OUTPUT; // 设置为输出模式
    io_conf.pin_bit_mask = GPIO_OUTPUT_PIN_SEL; // 设置引脚gpio0/gpio1
    io_conf.pull_down_en = 0; // 禁用下拉模式
    io_conf.pull_up_en = 0; // 禁用上拉模式
    gpio_config(&io_conf); // 配置 GPIO

    // 配置输入引脚
    io_conf.intr_type = GPIO_INTR_POSEDGE; // 上升沿中断
    io_conf.pin_bit_mask = GPIO_INPUT_PIN_SEL; // 设置引脚gpio0/gpio1
    io_conf.mode = GPIO_MODE_INPUT; // 设置为输入模式
    io_conf.pull_up_en = 1; // 启用上拉模式
    gpio_config(&io_conf); // 配置 GPIO

    // 改变 GPIO 中断类型
    gpio_set_intr_type(GPIO_INPUT_IO_0, GPIO_INTR_ANYEDGE); // 任何边缘中断

    // 创建队列以处理 ISR 的 GPIO 事件
    gpio_evt_queue = xQueueCreate(10, sizeof(uint32_t));
	
    // 启动 GPIO 任务
    xTaskCreate(gpio_task_example, "gpio_task_example", 2048, NULL, 10, NULL);

    // 安装 GPIO ISR 服务
    gpio_install_isr_service(ESP_INTR_FLAG_DEFAULT);
    // 钩住 ISR 处理程序
    gpio_isr_handler_add(GPIO_INPUT_IO_0, gpio_isr_handler, (void*) GPIO_INPUT_IO_0);
    gpio_isr_handler_add(GPIO_INPUT_IO_1, gpio_isr_handler, (void*) GPIO_INPUT_IO_1);

    // 从 GPIO 中移除 ISR 处理程序(可选)
    gpio_isr_handler_remove(GPIO_INPUT_IO_0);
    gpio_isr_handler_add(GPIO_INPUT_IO_0, gpio_isr_handler, (void*) GPIO_INPUT_IO_0); // 再次钩住 ISR

    printf("Minimum free heap size: %"PRIu32" bytes\n", esp_get_minimum_free_heap_size());

    int cnt = 0;
    while(1) {
        printf("cnt: %d\n", cnt++);
        vTaskDelay(1000 / portTICK_PERIOD_MS);
        gpio_set_level(GPIO_OUTPUT_IO_0, cnt % 2); // 切换输出引脚状态
        gpio_set_level(GPIO_OUTPUT_IO_1, cnt % 2); // 切换输出引脚状态
    }
}


复制它的前几行语句(第80~93行)到我们自己的gpio_key工程中,如下所示:

#include <stdio.h>

void app_main(void)
{
    //zero-initialize the config structure.
    gpio_config_t io_conf = {};
    //disable interrupt
    io_conf.intr_type = GPIO_INTR_DISABLE; // 关闭中断
    //set as output mode
    io_conf.mode = GPIO_MODE_OUTPUT; // 输出模式
    //bit mask of the pins that you want to set,e.g.GPIO18/19
    io_conf.pin_bit_mask = GPIO_OUTPUT_PIN_SEL; // 配置引脚号
    //disable pull-down mode
    io_conf.pull_down_en = 0; // 上下拉电阻,0是关闭,1是打开
    //disable pull-up mode
    io_conf.pull_up_en = 0; 
    //configure GPIO with the given settings
    gpio_config(&io_conf);// 使用gpio_config函数进行配置
}

在这里插入图片描述

gpio_example_main.c文件中的GPIO_INTR_DISABLE上单击右键,然后选择“转到定义”,就可以找到这几个宏定义,如下所示:

typedef enum {
GPIO*INTR_DISABLE = 0, //*!< Disable GPIO interrupt 禁用 GPIO 中断 _/
GPIO_INTR_POSEDGE = 1, //_!< GPIO interrupt type : rising edge 中断类型:上升沿_/
GPIO_INTR_NEGEDGE = 2, //_!< GPIO interrupt type : falling edge 中断类型:下降沿_/
GPIO_INTR_ANYEDGE = 3, //_!< GPIO interrupt type : both rising and falling edge 中断类型:上升沿和下降沿均可_/
GPIO_INTR_LOW_LEVEL = 4, //_!< GPIO interrupt type : input low level trigger 中断类型:低电平触发_/
GPIO_INTR_HIGH_LEVEL = 5,//_!< GPIO interrupt type : input high level trigger 中断类型:高电平触发\_/
GPIO_INTR_MAX,
} gpio_int_type_t;

上面的代码,总结来说一下,就是先定义一个GPIO结构体,然后给GPIO结构体成员变量赋值,然后使用GPIO配置函数配置GPIO。给结构体成员变量赋值,也可以在定义的时候直接赋值,如下代码所示:

方法1:

void app_main(void)
{
gpio_config_t io_conf = {
.intr_type = GPIO_INTR_NEGEDGE, //falling edge interrupt
.mode = GPIO_MODE_INPUT, //set as input mode
.pin_bit_mask = 1<<GPIO_NUM_9, //bit mask of the pins GPIO9
.pull_down_en = 0, //disable pull-down mode
.pull_up_en = 1 //enable pull-up mode
};
//configure GPIO with the given settings
gpio_config(&io_conf);
}

方法2:

void app_main(void)
{
//zero-initialize the config structure.
gpio_config_t io_conf = {};
//falling edge interrupt
io_conf.intr_type = GPIO_INTR_NEGEDGE;
//set as input mode
io_conf.mode = GPIO_MODE_INPUT;
//bit mask of the pins GPIO9
io_conf.pin_bit_mask = 1<<GPIO_NUM_9;
//disable pull-down mode
io_conf.pull_down_en = 0;
//enable pull-up mode
io_conf.pull_up_en = 1;
//configure GPIO with the given settings
gpio_config(&io_conf);
}

接下来,我们再复制gpio_example_main.c文件中的第108~116行代码到我们的main.c文件中。

    //create a queue to handle gpio event from isr
    gpio_evt_queue = xQueueCreate(10, sizeof(uint32_t));
    //start gpio task
    xTaskCreate(gpio_task_example, "gpio_task_example", 2048, NULL, 10, NULL);

    //install gpio isr service
    gpio_install_isr_service(ESP_INTR_FLAG_DEFAULT);
    //hook isr handler for specific gpio pin
    gpio_isr_handler_add(GPIO_INPUT_IO_0, gpio_isr_handler, (void*) GPIO_INPUT_IO_0);

开始,定义了一个队列句柄,用来处理gpio队列消息。

然后,定义了两个函数。

第一个函数是gpio 中断服务函数,当GPIO产生中断的时候呢,会进入这个函数,xQueueSendFromISR函数将参数GPIO_NUM_9添加到队列消息。

第二个函数是gpio的 任务函数,在任务函数中,接收队列消息,当接收到一个队列消息时,打印字符串。

PRIu32 是C语言中用于格式化输出的宏,用于打印32位无符号整数。它是由C99标准引入的,位于inttypes.h头文件中。在使用该宏时,需要包含inttypes.h头文件。

gpio_get_level函数用于获取引脚的电平。 这些内容,不需要做修改。 接下来,我们再把需要的头文件添加到我们的main.c文件就可以了。

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <inttypes.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/queue.h"
#include "driver/gpio.h"

使用printf函数,需要添加stdio.h头文件。string.h和stdlib.h我们这里用不着,可以去掉。接下来是3个freeRTOS的头文件,最后一个头文件是用于gpio的配置。

3.编译和下载

接下来,依次配置VSCode左下角的配置选项,串口号、目标芯片、下载方式、menuconfig里面,把FLASH大小修改为8MB,其它不做修改。

在这里插入图片描述

中断输入是项目中常用的方式,如果你想试试查询法,可以不开中断,使用gpio_get_level函数查询引脚电平。 引脚设置为输出,可以使用gpio_set_level来控制引脚的电平。具体使用方法,可以查看我们刚才参考的gpio例程。 ESP32还有一个特殊的引脚,就是GPIO11,它默认是VDD_SPI引脚,VDD_SPI默认是一个3.3V输出的电源引脚,可以用来给外部的FLASH芯片供电,这个引脚也可以修改为GPIO11,作为通用引脚使用。需要注意的是,这个修改是不可逆的,修改成GPIO11以后,就不能再修改为3.3V输出电源引脚了。我们在设计电路的时候,可以根据需求,决定是否用这个引脚给外部FLASH供电。我们的开发板没有用这个引脚给外部FLASH供电,而是作为GPIO引脚。这个引脚设置为GPIO的方法,我们会在I2S音频接口章节介绍。



源文件 main.c

#include <stdio.h>
#include <inttypes.h>// C99标准  PRIu32无符号32位数据类型
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/queue.h"
#include "driver/gpio.h"

// 声明一个静态队列句柄,用于处理 GPIO 事件
static QueueHandle_t gpio_evt_queue = NULL;

// GPIO 中断服务例程(ISR)处理函数
static void IRAM_ATTR gpio_isr_handler(void* arg)
{
    uint32_t gpio_num = (uint32_t) arg; // 获取触发中断的 GPIO 编号
    xQueueSendFromISR(gpio_evt_queue, &gpio_num, NULL); // 将 GPIO 编号发送到队列
}

// GPIO 任务示例
static void gpio_task_example(void* arg)
{
    uint32_t io_num; // 存储接收到的 GPIO 编号
    for(;;) {
        // 从队列中接收 GPIO 事件,阻塞直到有数据可用  portMAX_DELAY表示如果没有接收到消息,则会一直等待
        if(xQueueReceive(gpio_evt_queue, &io_num, portMAX_DELAY)) {
            // 打印触发中断的 GPIO 编号及其当前电平值
            printf("GPIO[%"PRIu32"] intr, val: %d\n", io_num, gpio_get_level(io_num));
            // gpio_set_level( GPIO_NUM_9,1)
        }
    }
}

// 主应用程序入口
void app_main(void)
{
    // 零初始化配置结构
    gpio_config_t io_conf = {
        .intr_type =  GPIO_INTR_NEGEDGE, // 设置为下降沿中断
        .mode = GPIO_MODE_INPUT,         // 设置为输入模式
        .pin_bit_mask = 1ULL << GPIO_NUM_9, // 设置引脚位掩码,指定为 GPIO_NUM_9
        .pull_down_en = 0,               // 禁用下拉模式
        .pull_up_en = 1                   // 启用上拉模式
    };

    // 根据配置设置 GPIO
    gpio_config(&io_conf);

    // 创建一个队列(句柄),用于处理 ISR 发送的 GPIO 事件
    gpio_evt_queue = xQueueCreate(10, sizeof(uint32_t));
    // 创建一个任务
    xTaskCreate(gpio_task_example, "gpio_task_example", 2048, NULL, 10, NULL);//任务的函数、任务的名称、堆栈大小、传递给任务函数的参数、任务的优先级,值越大表示优先级越高、用于接收任务句柄的指针

    // 安装 GPIO ISR 服务
    gpio_install_isr_service(0); // 默认值0
    // 为特定 GPIO 引脚钩住 ISR 处理程序
    gpio_isr_handler_add(GPIO_NUM_9, gpio_isr_handler, (void*) GPIO_NUM_9);// 中断源 中断函数的名称 中断函数的入口参数(void* arg)
}



xTaskCreate(gpio_task_example, "gpio_task_example", 2048, NULL, 10, NULL); 是用于在 FreeRTOS 中创建新任务的函数调用。具体说明如下:

参数说明:

  1. gpio_task_example:要执行的任务函数名。
  2. "gpio_task_example":任务的名称,用于调试和监控。
  3. 2048:为任务分配的堆栈大小(以字节为单位),这里为 2048 字节。
  4. NULL:任务的参数,这里设置为 NULL,表示没有传递参数。
  5. 10:任务的优先级,值越大优先级越高。这里设置为 10。
  6. NULL:用于接收任务句柄的指针,这里设置为 NULL,表示不需要句柄。

功能:

  • 创建一个名为 gpio_task_example 的任务,该任务将运行 gpio_task_example 函数。
  • 这个任务将负责从 GPIO 中断队列中接收事件,并处理这些事件。

如果你有更多问题或需要进一步的解释,请告诉我!

4.实验效果

在这里插入图片描述


5.参考资料

  • [1] 立创·实战派ESP32-C3开发板 立创开发板技术文档中心
  • [2] 【B站】立创·实战派ESP32-C3【手把手带你拥有项目经验】教程-04-gpio_key按键

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

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

相关文章

【Vue】Vue3.0 (十二)、watchEffect 和watch的区别及使用

上篇文章&#xff1a; 【Vue】Vue3.0 &#xff08;十二&#xff09;、watch对ref定义的基本类型、对象类型&#xff1b;reactive定义的对象类型的监视使用 &#x1f3e1;作者主页&#xff1a;点击&#xff01; &#x1f916;Vue专栏&#xff1a;点击&#xff01; ⏰️创作时间&…

数据仓库基础概念

数据仓库 概念 数据仓库&#xff08;Data Warehouse, DW&#xff09;是一个面向主题的、集成的、相对稳定的、反映历史变化的数据集合。它是为满足企业决策分析需求而设计的。 面向主题&#xff1a;数据仓库围绕特定的主题组织数据&#xff0c;例如“销售”或“人力资源”&am…

线上交友小程序源码系统 一元盲盒小程序在线开好友 带完整的安装代码包以及搭建部署教程

系统概述 线上交友小程序源码系统是基于先进的技术架构开发的一套完整的解决方案&#xff0c;旨在为用户提供一个便捷、有趣的线上交友平台。该系统通过一元盲盒的形式&#xff0c;让用户在未知中寻找惊喜&#xff0c;增加了交友的趣味性和神秘感。 该系统采用了先进的编程技…

UE5蓝图中忽略触发区域进行碰撞

Event Hit :只会在碰撞到实体的时候产生碰撞。如果是触发区域则会忽略。 Destroy Actor&#xff1a;销毁自身。

openrtp 音视频时间戳问题

解决音视频发送的rtp问题 openrtp增加了音频aac的发送&#xff0c;地址 OpenRTP Gitee开源地址 同时使用两个rtp &#xff0c;来发送音频和视频 使用以下音频rtp&#xff0c;是可以发送和接收的&#xff0c;音频端口在视频端口上2 v0 o- 0 0 IN IP4 127.0.0.1 sMy Stream cI…

sentinel dashboard分布式改造落地设计实现解释(二)-分布式discovery组件

discovery discovery负责维护app/机器资料库&#xff0c;transport健康检测&#xff0c; transport上下线处理。discovery关键是分布式存储&#xff0c;后续研究一下raft&#xff0c;其复制&#xff0c;状态机&#xff0c;快照技术&#xff0c;但个人觉得&#xff0c;discover…

【网络安全】护网蓝队之应急响应

蓝队技术栈 Linux入侵排查 系统排查 一、查看历史命令 在Linux系统中&#xff0c;检查历史命令记录是安全审计的重要步骤之一&#xff0c;它可以帮助您了解系统上用户&#xff08;包括潜在的黑客&#xff09;的活动。以下是对您描述的重新表述和补充&#xff1a; 检查历史命…

webpack自定义插件 ChangeScriptSrcPlugin

插件文件 class ChangeScriptSrcPlugin {apply(compiler) {const pluginName "ChangeScriptSrcPlugin";compiler.hooks.compilation.tap(pluginName, (compilation, callback) > {compilation.hooks.htmlWebpackPluginAlterAssetTags.tapAsync(pluginName,(html…

LabVIEW提高开发效率技巧----节省内存

在LabVIEW开发过程中&#xff0c;内存管理是保障程序稳定性和性能的关键。本文将详细介绍如何通过队列处理来节省内存&#xff0c;尤其是如何通过解耦释放不再需要的数据&#xff0c;防止内存泄漏。通过多个实际例子&#xff0c;从不同角度探讨队列处理在大数据量或长时间运行的…

使用Airtest自动化某云音乐爬取歌曲名称

简介 本文将介绍如何使用Airtest自动化工具来模拟用户操作&#xff0c;从某云音乐中爬取与特定关键词相关的歌曲名称。我们将以搜索“文字”相关的歌曲为例&#xff0c;并将结果保存到本地文件。 准备工作 安装Airtest并配置好Android设备或模拟器。确保你的设备上已安装某云…

C0027.在Clion中解决CPU和内存过高的问题

解决办法 最新版的 clion 在 advance setting里&#xff0c;可以勾选 Use the Resharper C language engine (CLion Nova)。 有显著的性能提升。

深入探索JavaCV:功能强大的Java计算机视觉库

&#x1f9d1; 博主简介&#xff1a;历代文学网&#xff08;PC端可以访问&#xff1a;https://literature.sinhy.com/#/literature?__c1000&#xff0c;移动端可微信小程序搜索“历代文学”&#xff09;总架构师&#xff0c;15年工作经验&#xff0c;精通Java编程&#xff0c;…

积木报表静态资源不生效,界面乱码 解决方法

目录 前言1. 问题所示2. 原理分析3. 解决方法前言 从实战中分析问题,解决问题,以下笔记学习为主 关于JimuReport的网站:文档中心 1. 问题所示 引入积木报表之后,界面静态文件不生效,最终截图如下: 大致浏览器终端报错如下: 基本信息如下: Uncaught SyntaxError: U…

项目管理的坎坷之路与 MBTI 的启示录

项目管理这一路走来&#xff0c;经历了无数的坎坷、不顺和阻碍。幸运的是&#xff0c;遇见 MBTI 之后&#xff0c;我仿佛看到了新的希望&#xff0c;终于我也看到了花团锦簇&#xff0c;也看到了灯彩佳话。那一夜&#xff0c;我也曾梦见百万雄兵。 什么是 MBTI &#xff1f; M…

AI大模型学习路线路径,巨详细!

大模型技术已经成为推动人工智能发展的关键力量。无论你是初学者还是有经验的开发者&#xff0c;想要掌握大模型应用&#xff0c;都需要遵循一定的学习路线。 从核心技术解析到模型微调与私有化部署&#xff0c;逐步深入大模型应用的世界。 这份学习路线图详细的介绍了那年每…

gitee建立/取消关联仓库

目录 一、常用指令总结 二、建立关联具体操作 三、取消关联具体操作 一、常用指令总结 首先要选中要关联的文件&#xff0c;右击&#xff0c;选择Git Bash Here。 git remote -v //查看自己的文件有几个关联的仓库git init //初始化文件夹为git可远程建立链接的文件夹…

【CSS3】css开篇基础(3)

1.❤️❤️前言~&#x1f973;&#x1f389;&#x1f389;&#x1f389; Hello, Hello~ 亲爱的朋友们&#x1f44b;&#x1f44b;&#xff0c;这里是E绵绵呀✍️✍️。 如果你喜欢这篇文章&#xff0c;请别吝啬你的点赞❤️❤️和收藏&#x1f4d6;&#x1f4d6;。如果你对我的…

经营异常移除申请操作流程

经营异常是怎么回事&#xff1f;是什么意思&#xff1f;企业工商异常通常由以下几个原因造成1.未及时填报年度报告&#xff08;补报年报后解除&#xff0c;目前新规最高罚款一万&#xff09;2.公司地址是挂靠或者搬迁地址未及时变更&#xff0c;被列入地址异常名录。&#xff0…

MFC工控项目实例二十六创建数据库

承接专栏《MFC工控项目实例二十五多媒体定时计时器》 用选取的型号为文件名建立文件夹&#xff0c;再在下面用测试的当天的时间创建文件夹&#xff0c;在这个文件中用测试的时/分/秒为数据库名创建Adcess数据库。 1、在StdAfx.h文件最下面添加代码 #import "C:/Program F…

flutter TabBar自定义指示器(带文字的指示器、上弦弧形指示器、条形背景指示器、渐变色的指示器)

带文字的TabBar指示器 1.绘制自定义TabBar的绿色带白色文字的指示器 2.将底部灰色文字与TabrBar层叠&#xff0c;并调整高度位置与胶囊指示器重叠 自定义的带文字的TabBar指示器 import package:atui/jade/utils/JadeColors.dart; import package:flutter/material.dart; im…