最近入手了一块显示屏,又惊喜的发现移动咪咕盒子一直落灰,(反正盒子没破解也不能看电视),那给我的讯为4412开发板刷个安卓系统,写个红外遥控驱动烧进去,这样就能用咪咕盒子的遥控器看电视了。说干就干,开动啦
首先,了解下红外遥控器接收头引脚 ,从左往右,引脚依次是OUT,GND,VCC

红外遥控接收的整个过程是你拿着一个红外遥控器对准红外接收头按时,红外接收头的OUT引脚将会如何变化?这个是由你按下了遥控器哪个键决定的。因为它只是起到一个解码的作用。在当下,我国基本上是用的遥控器都是遵循NEC的编码方式。所以,我们就需要知道NEC红外遥控的编码方式了,然后才能在驱动程序里解码遥控器的信号。
遥控器发送的数据码由以下部分组成:引导码,8位的用户码,8位用户码的补码,8位的按键值,8位按键值的补码;

引导码及数据的定义如下图所示,当一直按住一个按钮的时候,会隔110ms左右发一次引导码(重复),并不带任何数据

解码的过程如下:遥控器的解码是在中断处理函数中完成的,当MCU 的中断引脚发生电平变化时,会引发中断;
void interrupt NEC_IR(void)
{


NEC遥控器中断处理


}

NEC遥控器中断里面处理红外接收头解码的代码如下:

#define UP 1
#define DOWN 2
unsigned char IR_STATE = 0;//信号处理的状态
unsigned char IR_CAPTURE_VAL = DOWN;//默认起始为低电平
unsigned char IR_BIT_POSITION = 0;
unsigned char IR_DATA[4];
long long  IR_CAPTURE_TIME = 0;
time_t  last_time;//上次的时间单位秒
suseconds_t last_time_us;//上次的时间单位微秒
#if 1do_gettimeofday(&tv_time);//linux获得系统时间的函数IR_CAPTURE_TIME = ((tv_time.tv_sec - last_time) * 1000 * 1000) + (tv_time.tv_usec - last_time_us);//捕获高低电平的时间last_time = tv_time.tv_sec;//把捕获触发的时间设置为上一次的时间last_time_us = tv_time.tv_usec;if (IR_STATE == 5)return IRQ_HANDLED;//printk("%d %d(%lld)\n", IR_CAPTURE_VAL, IR_STATE, IR_CAPTURE_TIME);if (IR_CAPTURE_VAL == UP) //如果捕捉到上升沿{//printf("L:%d\n",IR_CAPTURE_TIME);//如果低电平时间有9000us IR_STATE=1  引导码低电平9msif (7000 < IR_CAPTURE_TIME && IR_CAPTURE_TIME < 9500){IR_STATE = 1;}else if (IR_STATE == 2){ if (300 < IR_CAPTURE_TIME && IR_CAPTURE_TIME < 700){IR_STATE = 3;}else{IR_STATE = 0;}}//如果低电平没有9ms.IR_STATE=4else if (IR_STATE == 4){IR_STATE = 5;spend();}IR_CAPTURE_VAL = DOWN;}else{if (IR_STATE == 1){//引导码9ms低电平之后如果是4.5ms的高电平则完成的读取if (3000 < IR_CAPTURE_TIME && IR_CAPTURE_TIME < 6000){IR_BIT_POSITION = 0;IR_DATA[0] = 0;IR_DATA[1] = 0;IR_DATA[2] = 0;IR_DATA[3] = 0;IR_STATE = 2;}//如果引导码后是2.xms的高电平则是重复码,则直接标记读取完成else if (1000 < IR_CAPTURE_TIME && IR_CAPTURE_TIME < 3000){IR_STATE = 5;//既然按下-松开才是一个完整的事件,那么就不需要判断是否重复了spend();}}else if (IR_STATE == 3){//0.56msif (300 < IR_CAPTURE_TIME && IR_CAPTURE_TIME < 700){IR_DATA[IR_BIT_POSITION / 8] |= (0 << (IR_BIT_POSITION % 8));}//1.69mselse if (700 < IR_CAPTURE_TIME && IR_CAPTURE_TIME < 1900){IR_DATA[IR_BIT_POSITION / 8] |= (1 << (IR_BIT_POSITION % 8));}if (IR_BIT_POSITION == 31){//全部读取完成IR_STATE = 4;}else{IR_STATE = 2;IR_BIT_POSITION++;}}IR_CAPTURE_VAL = UP;}
#endif

好了,现在已经把接收到的遥控红外信号解码了,然后我们进行测试,分别按下遥控器的每个按键,串口控制台会输出对应的键值。现在我们要对收到的解码后的编码进行处理了代码如下图:

static void spend(void)
{int i;//如果数据位不等于数据位的反码,则接收错误if (IR_DATA[2] != (IR_DATA[3] ^ 0xff)){//不一致可能是错误数据 直接丢弃printk("verified failed,drop data 0x%02X 0x%02X(%d%d%d%d%d%d%d%d %d%d%d%d%d%d%d%d)\n",(IR_DATA[2]),(IR_DATA[3]),((IR_DATA[2] >> 7) & 0x01),((IR_DATA[2] >> 6) & 0x01),((IR_DATA[2] >> 5) & 0x01),((IR_DATA[2] >> 4) & 0x01),((IR_DATA[2] >> 3) & 0x01),((IR_DATA[2] >> 2) & 0x01),((IR_DATA[2] >> 1) & 0x01),((IR_DATA[2] >> 0) & 0x01),((IR_DATA[3] >> 7) & 0x01),((IR_DATA[3] >> 6) & 0x01),((IR_DATA[3] >> 5) & 0x01),((IR_DATA[3] >> 4) & 0x01),((IR_DATA[3] >> 3) & 0x01),((IR_DATA[3] >> 2) & 0x01),((IR_DATA[3] >> 1) & 0x01),((IR_DATA[3] >> 0) & 0x01));}else//正确就进行上报系统{printk("[0x%02X] ", IR_DATA[2]);for (i = 0; i < ARRAY_SIZE(key_event); i++){//如果键值等于数据码,就上报if (key_event[i].ir_code == IR_DATA[2]){//上报按下事件input_event(buttons_dev, EV_KEY, key_event[i].key_code, 1);input_sync(buttons_dev);//------------------------------------------------------del_timer(&ir_timer);              //删除上次的超时函数ir_timer.expires = jiffies + 25;       //设定超时时间,250毫秒ir_timer.data = key_event[i].key_code; //传递给定时器超时函数的值ir_timer.function = ir_timer_function; //设置定时器超时函数add_timer(&ir_timer);             //添加定时器,定时器开始生效// input_event(buttons_dev, EV_KEY,  key_event[i].key_code, 0);// input_sync(buttons_dev);break;}}}IR_STATE = 0;
}
/*** 超时函数** 如果执行到此函数说明规定时间内没有新的按键信号* 则上报给系统松开按键的事件*/static void ir_timer_function(unsigned long key_code)
{//------------------------------------------------------//上报一个松开事件input_event(buttons_dev, EV_KEY, key_code, 0);input_sync(buttons_dev);
}

好了,现在主要程序已经讲完了,接下来连接硬件,首先查找原理图,找到一个有中断的GPIO口,对应找出核心板的控制引脚,如下图所示。然后连接接收头到开发板上。
然后连接好开发板,进行驱动设备注册,使用命令“vim arch/arm/mach-exynos/mach-itop4412.c”,打开平台 文件,添加注册

接着到 menuconfig 中将其配置上,使用命令“make menuconfig”,进入“Device Drivers —>”→“Character devices —>”→“Enable IR config”,如下图所 示,配置上宏定义“IR_CTL”。
配置后保存退出。这样就确认了宏定义“IR_CTL”已经出现。 接着再次打开“arch/arm/mach-exynos/mach-itop4412.c”平台文件,再添加设备注册。

保存退出,重新编译内核,烧写到开发板。 开发板启动之后,使用命令“ls /sys/devices/platform/”可以查看到新注册的 IR 设 备。最后加载驱动模块“insmod /mnt/sdcard/ir.ko”.按遥控器按键,惊喜的发现可以控制安卓啦,安卓里面安个当贝桌面和电视家APP,这样子就可以看用遥控器遥控选择电视频道啦!美滋滋~
完整代码见下图:

/*以后写驱动可以讲头文件一股脑的加载代码前面*/
#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <mach/gpio.h>
#include <plat/gpio-cfg.h>
#include <linux/miscdevice.h>
#include <linux/platform_device.h>
#include <mach/regs-gpio.h>
#include <asm/io.h>
#include <linux/regulator/consumer.h>
#include <linux/delay.h>
#include <linux/input.h>
/*中断函数头文件*/
#include <linux/interrupt.h>
#include <linux/irq.h>#include <linux/sched.h> //jiffies在此头文件中定义
#include <linux/timer.h> //超时休眠的相关功能再这里定义#define DEBUG#ifndef DEBUG
#define Logd( fmt,... )
#else
#define Logd( fmt,... ) do{printk("[ IR ]" fmt "\r\n",##__VA_ARGS__);}while(0)
#endif#define DRIVER_NAME "ir"#define GPIO_IR EXYNOS4_GPX3(0)
#define IR gpio_get_value(GPIO_IR)#define UP 1
#define DOWN 2//宏定义 按键被按下
#define KEY_PRESSED  1//宏定义 按键已松开
#define KEY_RELEASED 0unsigned char IR_STATE = 0;
unsigned char IR_DATA[4];unsigned char ir_bit_position = 0;
unsigned char ir_capture_val  = DOWN;
unsigned char last_key_code = 0;long long IR_CAPTURE_TIME = 0;time_t last_time;
suseconds_t last_time_us;struct timeval tv_time;static struct timer_list ir_timer;static void spend(void);
static int find_key_code(unsigned char ir_code); //根据红外编码查找键值
static void ir_tasklet_function(unsigned long data);
static void ir_timer_function(unsigned long key_code); //超时函数 用于模拟松开事件
static void input_event_report(unsigned char key_code,unsigned char event); //按键上报DECLARE_TASKLET(tasklet, ir_tasklet_function,(unsigned long)0);struct KEY_EVENT
{int ir_code;  //红外的编码int key_code; //对于的key键值
};struct KEY_EVENT key_event[] = {{.ir_code = 0xca,.key_code = KEY_UP},{.ir_code = 0xd2,.key_code = KEY_DOWN},{.ir_code = 0x99,.key_code = KEY_LEFT},{.ir_code = 0xc1,.key_code = KEY_RIGHT},{.ir_code = 0xce,.key_code = KEY_ENTER},{.ir_code = 0x95,.key_code = KEY_BACK},{.ir_code = 0x82,.key_code = KEY_MENU},{.ir_code = 0x80,.key_code = KEY_VOLUMEUP},{.ir_code = 0x81,.key_code = KEY_VOLUMEDOWN},{.ir_code = 0xf1,.key_code = KEY_POWER},{.ir_code = 0x9c,.key_code = KEY_MUTE},{.ir_code = 0x8d,.key_code = KEY_SELECT},{.ir_code = 0x88,.key_code = KEY_HOME},{.ir_code = 0xd9,.key_code = KEY_PAUSE},{.ir_code = 0xdd,.key_code = KEY_PAGEUP},{.ir_code = 0x8c,.key_code = KEY_PAGEDOWN},{.ir_code = 0x92,.key_code = KEY_1},{.ir_code = 0x93,.key_code = KEY_2},{.ir_code = 0xcc,.key_code = KEY_3},{.ir_code = 0x8e,.key_code = KEY_4},{.ir_code = 0x8f,.key_code = KEY_5},{.ir_code = 0xc8,.key_code = KEY_6},{.ir_code = 0x8a,.key_code = KEY_7},{.ir_code = 0x8b,.key_code = KEY_8},{.ir_code = 0xc4,.key_code = KEY_9},{.ir_code = 0x87,.key_code = KEY_0},
};struct input_dev *buttons_dev; //  定义一个input_dev结构体static void ir_tasklet_function(unsigned long data)
{//用户识别码unsigned char user_code_h     = IR_DATA[0];unsigned char user_code_l     = IR_DATA[1];//操作码和操作反码unsigned char option_data     = IR_DATA[2];unsigned char option_inverse  = IR_DATA[3];IR_STATE = 0;//验证操作码是否正确if (option_data != (option_inverse ^ 0xff)){//不一致可能是错误数据 直接丢弃Logd("verified failed,drop data 0x%02X 0x%02X(%d%d%d%d%d%d%d%d %d%d%d%d%d%d%d%d)",(option_data),(option_inverse),((option_data >> 7) & 0x01),((option_data >> 6) & 0x01),((option_data >> 5) & 0x01),((option_data >> 4) & 0x01),((option_data >> 3) & 0x01),((option_data >> 2) & 0x01),((option_data >> 1) & 0x01),((option_data >> 0) & 0x01),((option_inverse >> 7) & 0x01),((option_inverse >> 6) & 0x01),((option_inverse >> 5) & 0x01),((option_inverse >> 4) & 0x01),((option_inverse >> 3) & 0x01),((option_inverse >> 2) & 0x01),((option_inverse >> 1) & 0x01),((option_inverse >> 0) & 0x01));return;}//判断last_key_code是否为0,不为0 说明是重复码,省去查找的步骤if(last_key_code == 0){//查找对应的KEY键值if((last_key_code = find_key_code(option_data)) == 0){//如果结果为0说明没有查找到Logd("This key event is not support!!");return;}Logd("[0x%02X] ", option_data);//上报按下事件input_event_report(last_key_code,KEY_PRESSED);}//------------------------------------------------------del_timer(&ir_timer);                   //删除上次的超时函数ir_timer.expires = jiffies + 25;       //设定超时时间,250毫秒ir_timer.data = last_key_code;         //传递给定时器超时函数的值ir_timer.function = ir_timer_function; //设置定时器超时函数add_timer(&ir_timer);                 //添加定时器,定时器开始生效return;
}static void input_event_report(unsigned char key_code,unsigned char event)
{//上报按下事件input_event(buttons_dev, EV_KEY,key_code, event);input_sync(buttons_dev);
}/*** 超时函数** 如果执行到此函数说明规定时间内没有新的按键信号* 则上报给系统松开按键的事件*/static void ir_timer_function(unsigned long key_code)
{Logd("松开");//上报一个松开事件input_event_report(key_code,KEY_RELEASED);
}static int find_key_code(unsigned char ir_code)
{int i;for (i = 0; i < ARRAY_SIZE(key_event); i++){if (key_event[i].ir_code == ir_code){return key_event[i].key_code;}}return 0;
}static void spend(void)
{//ir_tasklet_function(123);tasklet_schedule(&tasklet);
}/*** 红外接收的中断处理函数** 需要特别注意的是红外对时间要求较为严格,切勿在解码过程中使用printk* printk 消耗时间可能过长 影响到红外的正常解码*/
static irqreturn_t interrupt_callback(int ir, void *dev_id)
{//读取当前引脚的高低电平ir_capture_val = IR;#if 1do_gettimeofday(&tv_time);IR_CAPTURE_TIME = ((tv_time.tv_sec - last_time) * 1000 * 1000) + (tv_time.tv_usec - last_time_us);last_time = tv_time.tv_sec;last_time_us = tv_time.tv_usec;if (IR_STATE == 5)return IRQ_HANDLED;//printk("%d %d(%lld)\n", ir_capture_val, IR_STATE, IR_CAPTURE_TIME);if (ir_capture_val == UP) //捕捉到上升沿{//printf("L:%d\n",IR_CAPTURE_TIME);//9msif (7000 < IR_CAPTURE_TIME && IR_CAPTURE_TIME < 10000){IR_STATE = 1;}else if (IR_STATE == 2){if (300 < IR_CAPTURE_TIME && IR_CAPTURE_TIME < 700){IR_STATE = 3;}else{IR_STATE = 0;}}else if (IR_STATE == 4){IR_STATE = 5;spend();}//ir_capture_val = DOWN;}else{if (IR_STATE == 1){//引导码9ms低电平之后如果是4.5ms的高电平则完成的读取if (3000 < IR_CAPTURE_TIME && IR_CAPTURE_TIME < 6000){//重置读取的位数 ir_bit_position = 0;//清空数据memset(IR_DATA, 0, sizeof(IR_DATA));IR_STATE = 2;last_key_code = 0;}//如果引导码后是2.xms的高电平则是重复码,则直接标记读取完成else if (1000 < IR_CAPTURE_TIME && IR_CAPTURE_TIME < 3000){IR_STATE = 5;spend();}}else if (IR_STATE == 3){if (300 < IR_CAPTURE_TIME && IR_CAPTURE_TIME < 700){IR_DATA[ir_bit_position / 8] |= (0 << (ir_bit_position % 8));}else if (700 < IR_CAPTURE_TIME && IR_CAPTURE_TIME < 1900){IR_DATA[ir_bit_position / 8] |= (1 << (ir_bit_position % 8));}if (ir_bit_position == 31){//全部读取完成IR_STATE = 4;goto irq_exit;}IR_STATE = 2;ir_bit_position++;}//ir_capture_val = UP;}#endifirq_exit:return IRQ_HANDLED;
}static int ir_probe(struct platform_device *pdev)
{int ret;int i;Logd("ir_probe");//gpio_free(GPIO_IR);ret = gpio_request(GPIO_IR, "GPIO");if (ret < 0){Logd("%s: request GPIO %d for GPIO failed, ret = %d\n", DRIVER_NAME,GPIO_IR, ret);return ret;}Logd("request GPIO  success!");//注册中断s3c_gpio_cfgpin(GPIO_IR, S3C_GPIO_SFN(0xF));s3c_gpio_setpull(GPIO_IR, S3C_GPIO_PULL_UP);ret = request_irq(gpio_to_irq(GPIO_IR), interrupt_callback, IRQ_TYPE_EDGE_BOTH | IRQF_DISABLED, "irint", NULL);if (ret < 0){Logd("Request IRQ %d failed, %d\n", gpio_to_irq(GPIO_IR), ret);return ret;}Logd("request IRQ  success!");//------------------------------------------------------//申请一个定时器init_timer(&ir_timer); //初始化定时器//1.向内核 申请input_dev结构体buttons_dev = input_allocate_device();buttons_dev->name = "irdev";/*2.设置input_dev ,  */set_bit(EV_KEY, buttons_dev->evbit); //支持键盘事件set_bit(EV_REP, buttons_dev->evbit); //支持键盘重复按事件for (i = 0; i < ARRAY_SIZE(key_event); i++){set_bit(key_event[i].key_code, buttons_dev->keybit);}ret = input_register_device(buttons_dev);if(ret < 0){Logd("input_register_device failed:%d",ret);return ret;}Logd("input_register_device success!");return 0;
}static int ir_remove(struct platform_device *pdev)
{Logd("ir_remove");//释放中断free_irq(gpio_to_irq(GPIO_IR), NULL);//删除定时器del_timer(&ir_timer);gpio_free(GPIO_IR);tasklet_kill(&tasklet);input_unregister_device(buttons_dev);input_free_device(buttons_dev); return 0;
}static int ir_suspend(struct platform_device *pdev, pm_message_t state)
{Logd("ir suspend:power off!\n");return 0;
}static int ir_resume(struct platform_device *pdev)
{Logd("ir resume:power on!\n");return 0;
}
static struct platform_driver ir_driver = {.probe = ir_probe,.remove = ir_remove,.suspend = ir_suspend,.resume = ir_resume,.driver = {.name = DRIVER_NAME,.owner = THIS_MODULE,},
};static int __init ir_init(void)
{Logd("ir initialized");return platform_driver_register(&ir_driver);
}static void __exit ir_exit(void)
{Logd("ir_exit");platform_driver_unregister(&ir_driver);
}module_init(ir_init);
module_exit(ir_exit);MODULE_AUTHOR("Liliping && Donggua");
MODULE_DESCRIPTION("ir devices");
MODULE_LICENSE("Dual BSD/GPL");

移动咪咕盒子红外遥控驱动相关推荐

  1. android红外遥控驱动

    在 Linux 内核中,IR 驱动仅支持 NEC 编码格式. 设备树文件 pwm0: pwm@ff680000 {compatible = "rockchip,rk-pwm";re ...

  2. Amlogic电视盒子红外遥控适配笔记

    前一阵做了个安卓6的固件, 在R3300L和Q7上跑的, 其他问题没有, 但是有用户反映原来的遥控器用不了了, 于是检查了一下遥控器配置, 顺便学习一下此类设备的红外遥控机制. 为了方便测试还上淘宝买 ...

  3. Linux红外遥控驱动HS0038

    测试平台imx6q linux5.4.215 华为电信高清IPTV遥控器 使用其它遥控器可以更改key_table和user_id #include <linux/module.h> #i ...

  4. 遥控窗帘c语言程序,使用AT89C2051的红外遥控窗帘

    本文介绍一款使用微电脑管理的.红外遥控器控制的多功能窗帘控制器.该窗帘控制器采用89C2051单片机的最小系统设计,控制一个220V的可逆.变速电动机控制窗帘的拉开和关闭.窗帘控制器可以使用红外遥控器 ...

  5. AutoLeaders控制组——51单片机学习笔记(AD/DA、红外遥控)

    本篇内容是观看B站江科大自化协UP主的教学视频所做的笔记,对其中内容有所引用,并结合自己的单片机板块进行了更改调整. 以下笔记内容以一个视频为一个片段(内容较多,可能不适合速食,望见谅) 一些内容涉及 ...

  6. 遥控汽车的编程c语言,智能小车循迹、避障、红外遥控C语言代码.docx

    //智能小车避障.循迹.红外遥控C语言代码 // 实现功能有超声波避障, 红外遥控智能小车, 红外传感器实现小车自动循迹, 1602 显示小 车的工作状态,另有三个独立按键分别控制三种状态的转换 // ...

  7. 搭建红外遥控arm-hadoop集群过程

    很多人玩开发板用树莓派,树莓派的确很好,但是对于hadoop来说,内存有点小,只有512MB.所以我找了一圈,最后用的是国内一个开源硬件团队的产品叫CubieTruck.内存有2G,板载存储有8G,千 ...

  8. 基于红外遥控的arduino遥控小车

    遥控小车是每个人童年的最爱,不仅好奇它的奇妙,更是喜欢它带来的刺激.小编为大家带来几篇博客,来给大家讲讲制作遥控小车的程序. 看大标题可知我们一共有五个方法去制作一款带有遥控功能的小车,小编分开来给大 ...

  9. 循迹智能小车c语言主程序,智能小车循迹、避障、红外遥控C语言代码

    <智能小车循迹.避障.红外遥控C语言代码>由会员分享,可在线阅读,更多相关<智能小车循迹.避障.红外遥控C语言代码(13页珍藏版)>请在人人文库网上搜索. 1.智能小车避障.循 ...

最新文章

  1. linux内核 -内存管理模块概图
  2. php显示服务器文件,php-无法显示从新服务器下载文件的进度(在以前的服务器上工作)...
  3. 秋色园QBlog技术原理解析:性能优化篇:用户和文章计数器方案(十七)
  4. JSP自定义标签rtexprvalue属性
  5. (28)SpringBoot启动时的Banner设置【从零开始学Spring Boot】
  6. Implicit conversion from enumeration type 'enum CGImageAlphaInfo' to different enumeration type 'CGB
  7. 如果再不要求进步,那么你就是下一个陨落的巨头
  8. ThinkPHP整合百度Ueditor图文教程
  9. 09. 用两个栈实现队列
  10. 牛客多校第二场 G transform
  11. php 5.4.5,PHP 5.4.5 和 5.3.15 发布
  12. 程序猿跳槽季,为什么你的薪水总升不上去?
  13. codevs——1230 元素查找
  14. click事件在什么时候出发_如何解决移动端Click事件300ms延迟的问题?
  15. 20190911-代码生成器生成表单
  16. 搭建国外海外多语言一元云购软件夺宝购商城网站
  17. unity给头发添加物理_U3D实时渲染教程之角色头发各向异性表达(上)
  18. MathJax 支持的 Latex 符号总结
  19. 需求工程规格说明、需求验证、需求管理
  20. Windows系统设置多账户步骤

热门文章

  1. 关于程序运行中出现的bug“Project1.exe 已触发了一个断点”和“ntdll.dll处引发的异常”和“指针对象为0xdddddddd”
  2. java socket 重连_java socket 重连问题
  3. 【有利可图网】PS实战教程47:制作水墨喷溅烟雾效果文字图片
  4. jdbcTemplate.queryForList 返回值 大小写敏感的问题
  5. element ui - el-select 添加可输入功能
  6. matlab直角坐标转换极坐标,matlab-在MATLAB中怎么将直角坐标转化为极坐标 – 手机爱问...
  7. beego利用casbin进行权限管理——第二节 策略存储
  8. Android关于易源数据网络接口的使用
  9. win10打印图片中间空白以及选择打印机预览重启
  10. 计算机自带的超级锁怎么设置,万能锁加锁了文件夹加密超级大师的快捷方式怎么办?...