linux4.6 EC11旋转编码器的驱动

2023-11-02

最近项目使用了旋转编码器EC11,遍查内核,发现并没有它的驱动,查了查CSDN,终于找到一篇有用的。根据自己的需要和对最基础的gpio_key.c的理解,我改写出了一份EC11的专用驱动。

感谢下面博主的启发,有了这位高人的指点,我才有信心改写成功。并决定向他学习,将自己成功的代码与大家分享。

https://blog.csdn.net/aifei7320/article/details/50037689

1.了解ec11旋转编码器

参考链接:https://www.yiboard.com/thread-1001-1-1.htmlhttps://www.jianshu.com/p/41fa67ecb248

网上相关的介绍很多,读完以上内容,我对自己使用的产品有了基本的认识:

首先,知道它电路的连接使用,参考说明书上面的电路图。该连电阻连电阻,该接电容接电容,才能正确出波形。

接着,知道它是一定位一脉冲式,通过示波器观察到转动一格,A、B都有完整的脉冲产生。(两定位的驱动没有想)

最后,顺时钟转的波形和逆时钟转的波形。

关于一圈多少格,个人认为,如果说转够一圈有什么特殊波形的话,这个可以留意一下,但是我产品没有,此特性忽略。

此处应该有图

2.分析驱动实现

有了上述不同旋转方向的波形的图片以后,开始思考实现驱动的方案和效果,先初步想一下,然后再参考别人的linux代码、C语言代码进行补充修正。

2.1  驱动的方案

提供的方案有以下

1)记录信号A、B两个的下降沿(或上升沿)出现的时间,然后相减的正负结果,暴露出A与B谁先出现,从而知道是左旋还是右旋。

要点:A与B的中断都要关注,全局变量记录中断出现时间。

2)以其中一个信号作为时钟线(中断线),以上升沿(或下降沿)中断触发,读取另外一根(信号线)的电平状态,从而知左旋还是右旋。

要点:A与B仅选择关注一个中断,不需要全局变量记录。

因为驱动基于gpio_key.c,它是中断发送然后检测电平的方式。参考了其他博主,都是第二种方式,有成功的例子,所以采用了第二种方式。

另外这里考虑另外一个问题,那就是按钮值的处理。有的ec11除了左旋、右旋还可以像普通按钮按下,也就是它有3个值。我研究了手头有按钮功能的按键,发现按钮事件对A、B信号影响不大,它另外通过引脚C输出,波形表现是平时高电平,按键按下变成低,松开又成高。所以按钮事件交给驱动gpio_key.c处理就好,不予关注。而左旋、右旋事件交给驱动gpio_ec11.c(在gpio_key.c基础上修改而成,不影响gpio_key.c驱动)。参考我后面的设备树描述,这个就好懂了。

总结一下要做的工作就是在上,改写出旋转功能(这个驱动不负责按钮部分所以不是旋转按钮)的驱动gpio_ec11.c。

2.2  预计效果

最后驱动要实现的功能是,左旋的时候,输出一个按键值。右旋的时候,输出另外一个按键值。

怎么说呢,效果就是左旋一格相当于按键A完成一次按下松开动作,右旋一格相当于按键B完成一次按下松开动作。

3.驱动编辑

因为修改部分多,而且很多变量类型修改的细节,这里仅展示重点讲解,详情参考提供的源代码

3.1 相关头文件

因为不能影响到gpio_key.c,所以需要创建新的结构体数据。按照参考链接1博主的做法,在struct gpio_keys_button 中增加成员,并修改变量类型。

gpio_ec11.h ——修改自gpio_key.h

修改部分:

#ifndef _GPIO_EC11_H
#define _GPIO_EC11_H

……

struct gpio_ec11_button {  /*重要结构体名字换掉*/
    unsigned int code;  /*没有用到,为了适应旧架构就保留没删除*/
    unsigned int leftcode;  /*记录左旋键值*/
    unsigned int rightcode;  /*记录右旋键值*/
    int gpio;  /*旋转编码器A引脚的gpio号*/
    int subgpio;  /*旋转编码器B引脚的gpio号*/

 ……

};

/*原来struct gpio_keys_button部分都相应改成struct gpio_ec11_button,为减少工作量,变量名不变*/

struct gpio_ec11_platform_data {
    struct gpio_ec11_button *buttons; 

 ……

};

总结,这样修改的主要是保证改的新驱动不会影响就驱动的使用,没换变量名是为了尽可能少改。

3.2 相关源文件

既然要修改源文件,那就得先把基础文件gpio_key.c理解清楚。

采用了最笨的办法,就是在里面的主要功能函数里,首加“printk("%s start\n",__FUNCTION__);”,“尾加printk("%s end\n",__FUNCTION__);” ,再配合按键的使用观察内核打印信息,基本摸清楚驱动调用顺序。最后,搜几篇gpio_key.c驱动详解之类的文章,对每个功能函数加深了解,最后着手改程序。我觉得高手可能直接看代码能理清,emmm~反正我不行,不管什么手段办法,摸清楚原来的框架是必须的。

gpio_ec11.c ——修改自gpio_key.c

…… //25h

#include <linux/gpio_ec11.h>  //20190408替换成改的头文件

…… //35h

struct gpio_ec11_data {
    const struct gpio_ec11_button *button;  //20190408
 ……
};

struct gpio_ec11_drvdata {
    const struct gpio_ec11_platform_data *pdata;  //20190408
 ……
    struct gpio_ec11_data data[0];    //20190408
};

到这里,所有重要的数据结构体就都定义了,然后就是替换程序中原来旧数据类型,如struct gpio_keys_drvdata等的地方了。这一步工程量挺大的,在实验中发现可以借助GCC编译器找。改完直接编译,到时候报出很多的错,然后根据错误精准修改,不到半小时就能改完吧。

不建议一次改很多编译。我是先改了数据类型(此时顶着的是gpio_key的名头),后来实验成功了,才将很多函数名都改了。这是为了避免内核冲突。

重点修改地方的介绍:

3.2.1  设置中断类型

我在实验用gpio_ec11.c的时候,发现它经常不对,后来调试发现gpio_key.c就时灵时不灵。也就是说,新驱动不行的毛病是打娘胎里来的。只好先研究gpio_key.c为什么时灵时不灵。然后就发现,是程序里中断类型(上升沿、下降沿、高电平和低电平触发天剑)设置不对。我不知道为什么这个驱动对中断类型变量有声明,但是没有通过解析设备树赋值给变量,内情以后再研究,自己先加了这个:

static struct gpio_ec11_platform_data *
gpio_keys_get_devtree_pdata(struct device *dev)
{

 ……
    for_each_available_child_of_node(node, pp) {
        //enum of_gpio_flags flags;  /*这个变量值只声明未定义知道是不是原作者忘了……*/  
        button = &pdata->buttons[i++];

        button->gpio = of_get_gpio_flags(pp, 0, &button->irq_flags);  /*时钟的注册*/        
        ……

        if (of_property_read_u32(pp, "irq,flags", &button->irq_flags))
            button->irq_flags = IRQF_TRIGGER_FALLING;  /*默认为下降沿触发20190410*/
         //printk("button->irq_flags=%d",button->irq_flags);

 ……

注意: button->irq_flags的赋值一定要在of_get_gpio_flags()函数之后,实验中发现此函数会修改button->irq_flag归0

总结:像这类改数据值的能在定义处改就改。千万别在使用的地方改,要改很多处,而且二次修改时万一漏了一处,调试很浪费时间。

3.2.2  注册gpio与键值

static struct gpio_ec11_platform_data *gpio_keys_get_devtree_pdata(struct device *dev)
{

 ……

    pdata->rep = !!of_get_property(node, "autorepeat", NULL);

 ……
    for_each_available_child_of_node(node, pp) {
    ……

        button->gpio = of_get_gpio_flags(pp, 0, &button->irq_flags);  /*时钟的注册,管中断gpio叫时钟信号了,仿照某帖子*/        
        button->subgpio = of_get_gpio_flags(pp, 1, &button->irq_flags);  /*信号的注册*/

  ……

        if(button->gpio == button->subgpio) {  /*必要的错误判断,照着button->gpio模板加,详情参考源代码*/
            dev_err(dev, "ERROR:the ec11 pin A——GPIO %d,same as pin B——GPIO %d\n",button->gpio,button->subgpio);
            error = -button->gpio;
            return ERR_PTR(error);
        }

  ……

        if (of_property_read_u32(pp, "left,code", &button->leftcode)) {
            dev_err(dev, "Button without leftcode: 0x%x\n",button->gpio);
            return ERR_PTR(-EINVAL);
        }  /*注册左旋和右旋的按键值*/
        if (of_property_read_u32(pp, "right,code", &button->rightcode)) {
            dev_err(dev, "Button without rightcode: 0x%x\n", button->subgpio);
            return ERR_PTR(-EINVAL);
        }

  ……

        if (of_property_read_u32(pp, "debounce-interval",&button->debounce_interval))
            button->debounce_interval = 5;  /*赋值防抖动时间,实验中发现这个时间最少是10ms,写的小了没什么用,不知为何*/

……

3.2.2  中断处理函数

最重要的当属中断处理函数,这里整理一下函数调用顺序:

当满足中断要求时,函数的调用顺序:

 

/*中断处理函数 传说的顶部*/
static irqreturn_t gpio_ec11_gpio_isr(int irq, void *dev_id)

{

 ……

 /*函数不卡在这,先return IRQ_HANDLED,再经过bdata->software_debounce(ms)延时,执行&bdata->work*/

 mod_delayed_work(system_wq,
              &bdata->work,  // ——> void gpio_keys_gpio_work_func(struct work_struct *work)
              msecs_to_jiffies(bdata->software_debounce));

 ……

 return IRQ_HANDLED;

}

注意:根据函数理解,执行函数gpio_ec11_gpio_isr,到gpio_keys_gpio_work_func的延时为bdata->software_debounce。

实验中通过current_kernel_time()函数打印时间,发现这个延时最少也为10ms。

/*&bdata->work 的实现 传说的底部??*/
static void gpio_keys_gpio_work_func(struct work_struct *work)
{
    struct gpio_ec11_data *bdata =
        container_of(work, struct gpio_ec11_data, work.work);

    gpio_keys_gpio_report_event(bdata);

    if (bdata->button->wakeup)
        pm_relax(bdata->input->dev.parent);
}
 

/*上报按键事件  20190408 背景:下降沿触发*/
static void gpio_keys_gpio_report_event(struct gpio_ec11_data *bdata)
{
    const struct gpio_ec11_button *button = bdata->button;
    struct input_dev *input = bdata->input;
    unsigned int type = button->type ?: EV_KEY;
    int state = gpio_get_value_cansleep(button->gpio);  /*取得时钟线的状态*/
    int dir = 0;  /*旋转方向的变量*/
    ts = current_kernel_time();
    if (state == 1){  /*中断发生后经过一个延时抖动再读时钟线的电平,正常肯定是0,1立刻返回*/
        printk("sec=%ld,nsec=%ld\n",ts.tv_sec, ts.tv_nsec);        
        return;
    }
    if (state < 0) {
        dev_err(input->dev.parent, "failed to get gpio state\n");
        return;
    }

    //state = (state ? 1 : 0) ^ button->active_low;
    
    if(state != state2)/*中断发生时取得的信号线的状态,联合时钟线判断旋转方向*/
        dir = 1;//button->code = bdata->button->rightcode;
    else
        dir = 2;//button->code = bdata->button->leftcode;
    printk("dir=%d~~~state=%d,stateother=%d,~~~~~",dir,state,state2);
    printk("start sec=%ld,nsec=%ld\n",ts.tv_sec, ts.tv_nsec);
    /*上报时间,第一次上报按键按下,第二次上报按键松开。缺点:对active_low进行研究,先忽略了*/
    if(dir == 1){
        input_event(input, type, button->rightcode,1);
        input_sync(input);
        input_event(input, type, button->rightcode,0);
        input_sync(input);printk("input_sync\n");
    }
    else if(dir == 2){
        input_event(input, type, button->leftcode,1);  //!!state
        input_sync(input);
        input_event(input, type, button->leftcode,0);
        input_sync(input);printk("input_sync\n");
    }
}

详情参考上传的资源中。

为什么采用一个中断,但是上报两次事件的方式?

如果把触发方式改成边沿触发,道理上讲可以由程序一一对应上报。但是试验中发现,旋转开关矩形低脉冲的时间有时候比较短,本来按键状态检测就会出错,这样错误概率会高。

为什么信号线电平要在中断顶部读取,而不是中断底部读取?

这个根据实验现象调整的。主要是AB信号下降沿的时差不确定性引起。虽然会拖慢中断释放时间,但是只读取,正真的处理还在中断底部,所以能接受。

时钟下降沿之后,上升沿之前,也就是它低电平的时期,信号线的状态会发生一次变化。要想有正确结果,得读变化前的值。但是,随你怎么设置,中断顶部到中断底部最少就得10ms,那么信号线在时钟线下降沿后 <10ms内变化的,统统得到错误的方向,只好在时钟下降沿也就是中断顶部立刻读取。

此处应该有图(以后再配)

驱动的缺陷是什么?

很遗憾它现在依然会错,

错误情况1,时钟线多了一个脉冲,但是信号线无变化。导致会多报一次事件,但是旋转方向保持了一致,就是明明转了一格,但是系统输出两次按键事件。这个也会发生时钟线无变化,但是信号线多了一个脉冲,但是因为中断触发在时钟线上,所以不会产生影响。

此处真有图(以后再配)

错误情况2,旋转方向报告错误。原因是时钟线抖动引起。时钟线低电平时期,它在信号线变化之后,忽然产生了抖动。这个抖动后,触发中断,在读取时钟线电平时,它刚好还是个低就误判成一个脉冲了。导致多报一次事件,第二次报的是反向。

解决办法:

打算从电路方向着手了。再议。

 

总结:此次调试ec11前后花了一个周的时间大概,初代代码2天完成,后来的时间全在调试上。总结一下:

一是,要先从原理了解清楚。比如,就得先知道旋钮波形,推测判断手段,自己写实现很方便,读懂别人文章也容易。

二是,理清输入框架。本人觉悟很低,每次都得先摸清楚功能函数执行顺序,才能了解到框架。以后加强框架观察能力。

三是,实验配合调试。这次调试遇到很多想不到的错,比如内核没有中断方式的设置,延时设小了没有用,这些原因导致的错误,靠猜还真是难,就得靠示波器,配合内核打印来看。

四是,一步一个脚印的调试。必须保证准备条件的正确。我之前中断错了。努力的改中断处理,就是浪费时间。应该按照事件的发生顺序一步步调。

五是,适当请求帮助。感谢领导,给我提出打印程序执行时间这个好办法。辛苦了我的头发陪我思考。

 

设备树描述:

        gpio_keys {
            compatible = "gpio-keys";
            #address-cells = <0x1>;
            #size-cells = <0x0>;
            /*autorepeat;*/

            button@0 {
                label = "test";
                linux,code = <0x3D>;
                debounce-interval = <0x15>;
                irq,flags = <0x3>;
                gpios = <0x6 0x32 0x0>;
            };    
            button@1 {
                label = "test1";
                linux,code = <0x3f>;
                debounce-interval = <0x15>;
                irq,flags = <0x2>;
                gpios = <0x6 0x33 0x0>;
            };
           
            button@2 {
                label = "ec11 button";  /*ec11的按钮,如果有按钮功能的话*/
                linux,code = <0x3>;
                debounce-interval = <0x15>;
                gpios = <0x6 0x38 0x0>;
            };
           
        };

        gpio_ec11 {
            compatible = "gpio-ec11";
            #address-cells = <0x1>;
            #size-cells = <0x0>;
            /*autorepeat;*/

            button@1 {
                label = "EC11";
                linux,code = <0x3D>;
                left,code = <0x3E>;
                right,code = <0x3f>;
                irq,flags = <0x2>;  /*中断方式设置*/
                debounce-interval = <0x5>;
                gpios = <0x6 0x38 0x0 0x6 0x39 0x0>;
            };
        };

C语言测试程序(还不会上传,先贴图了):

input1.c

/*这是旋转按钮的测试函数。尤其适合在没有显示时,通过串口控制台进行测试。
*屏幕会打印出按下还是松开的状态,
*和输入按键的值,这个值是设备树中描述的值,不是实际效果值。
*比如:在输入框按下按键,上面出现了数字1,1是实际效果值,而它的设备树描述值却是2。
*本实验输出的是 ————描述值
*附:
*怎么知道按键效果和键值的对应关系?
*参阅网址:http://www.verysource.com/code/10989174_1/vcomkeycode.h.html
*怎么知道按键事件的文件路径?
*参阅开机打印信息。比如某实验开机时关于矩阵键盘的信息如下:
*input: amba:matrix_keys as /devices/soc0/amba/amba:matrix_keys/input/input0
*通过上述就知道,开机后/dev/input/event0是按键事件的相关文件。
*假如输入input: amba:matrix_keys as /devices/soc0/amba/amba:matrix_keys/input/input1,就变成了/dev/input/event1
*/       
#include <stdio.h>  
#include <stdlib.h>  
#include <unistd.h>  
#include <string.h>  
#include <sys/types.h>  
#include <fcntl.h>  
#include <errno.h>  
#include <time.h>  
#include <linux/input.h>
 
struct input_event event;
int main()
{  
        int keys_fd,rc;           
        if ((keys_fd = open("/dev/input/event1", O_RDWR, 0)) <= 0){
            printf("open failed:%d\n", keys_fd);
    }    
     printf("ok");
    while (1)
        {
            if (read(keys_fd, &event, sizeof (event)) != sizeof (event))
            break;

                if (event.type == EV_KEY){
            printf("event.code=%d  %s\n",event.code&0xff,(event.value) ? "Pressed" : "Released");
                        if (event.code == KEY_ESC)
            break;
            }
        }

}

使用方法,先用gcc 编译,然后执行,左右转时界面打印不同的值,效果如下:

root@linaro-ubuntu-desktop:~# cd /home/linaro/driver_test/

root@linaro-ubuntu-desktop:/home/linaro/driver_test# gcc -o ./put1 ./input1.c
root@linaro-ubuntu-desktop:/home/linaro/driver_test# ./put1
okevent.code=62  Pressed
event.code=62  Released
event.code=62  Pressed
event.code=62  Released
event.code=62  Pressed
event.code=62  Released
event.code=63  Pressed
event.code=63  Released

介于大家总是看不到我的相关头文件,懒人如我,打算粘贴在这里了。我的ubuntu系统上传不是很友好,没办法设置0积分下载。就只能怎么着了吧。编译时候,建议和.c放同一目录,引用变为,#include "gpio_ec11.h"。有基础的应该懂吧,不解释了。文件名如下:

gpio_ec11.h

内容:

#ifndef _GPIO_EC11_H
#define _GPIO_EC11_H

struct device;
struct gpio_desc;

/**
 * struct gpio_ec11_button - configuration parameters
 * @leftcode:        ec11 left direction input event code (KEY_*, SW_*)
 * @rightcode:        ec11 right direction input event code (KEY_*, SW_*)
 * @gpio:        %-1 if this key does not support gpio
 * @gpio:        %-1 if this key does not support gpio
 * @active_low:        %true indicates that button is considered
 *            depressed when gpio is low
 * @desc:        label that will be attached to button's gpio
 * @type:        input event type (%EV_KEY, %EV_SW, %EV_ABS)
 * @wakeup:        configure the button as a wake-up source
 * @debounce_interval:    debounce ticks interval in msecs
 * @can_disable:    %true indicates that userspace is allowed to
 *            disable button via sysfs
 * @value:        axis value for %EV_ABS
 * @irq:        Irq number in case of interrupt keys
 * @gpiod:        GPIO descriptor
 */
struct gpio_ec11_button {
    unsigned int code;
    unsigned int leftcode;  /*记录左旋键值*/
    unsigned int rightcode;  /*记录右旋键值*/
    int gpio;  /*旋转编码器A引脚的gpio号*/
    int subgpio;  /*旋转编码器B引脚的gpio号*/
    int active_low;
    const char *desc;
    unsigned int type;
    int wakeup;
    int debounce_interval;
    bool can_disable;
    int value;
    unsigned int irq;
    unsigned int irq_flags;
    struct gpio_desc *gpiod;
};

/**
 * struct gpio_ec11_platform_data - platform data for gpio_ec11 driver
 * @buttons:        pointer to array of &gpio_keys_button structures
 *            describing buttons attached to the device
 * @nbuttons:        number of elements in @buttons array
 * @poll_interval:    polling interval in msecs - for polling driver only
 * @rep:        enable input subsystem auto repeat
 * @enable:        platform hook for enabling the device
 * @disable:        platform hook for disabling the device
 * @name:        input device name
 */
struct gpio_ec11_platform_data {
    struct gpio_ec11_button *buttons;
    int nbuttons;
    unsigned int poll_interval;
    unsigned int rep:1;
    int (*enable)(struct device *dev);
    void (*disable)(struct device *dev);
    const char *name;
};

#endif

 

 

 

 

 

 

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

linux4.6 EC11旋转编码器的驱动 的相关文章

随机推荐

  • 最长公共子序列 蓝桥杯 1189

    题目描述 给定一个长度为n数组A和一个长度为m数组B 请你求出它们的最长公共子序列长度为多少 输入描述 输入第一行包含两个整数n m 第二行包含n个整数ai 第三行包含m个整数bi 1 lt n m lt 10 3 1 lt ai bi l
  • BearPi-HM Nano HarmonyOS 环境搭建

    BearPi HM Nano HarmonyOS 环境搭建 BearPi HM Nano 介绍 BearPi HM Nano开发板是一块专门为鸿蒙OS设计的鸿蒙OS开发板 板载高度集成的2 4GHz WLAN SoC芯片Hi3861 并板载
  • java mongodb 关闭连接_未释放资源的教训,开发MongoDB连接一定要关闭连接

    废不少工夫将数据存储 全部迁移至mongodb 未作大量改动则是主因 但遇到奇怪的现象 程序跑起不久后 mongodb即假死 另起客户端想登陆mongodb都不成 要重启mongodb服务器才好转 分析原因是mongodb的连接池满掉且不释
  • elasticsearch学习之cross_fields字段使用

    cross fields字段 在查询阶段解决信号冲突问题 问题 The cross fields type is particularly useful with structured documents where multiple fi
  • Java进阶--Java垃圾回收机制全面解析

    本文同步发布在我的个人博客 如需转载请注明出处 提起Java的垃圾回收机制大家应该都有所了解 它不仅是面试的常客 也是Java体系中相当重要的一块知识 深入理解Java的GC机制 不仅有助于我们在开发中提高程序的性能 更有了在面试官面前炫
  • MySQL索引怎么用?究竟能有多快?看完这篇你就懂了!

    本文介绍的是MySQL索引的具体使用 原理以及本质结构请看我写的上一篇文章 MySQL索引凭什么能让查询效率提高这么多 原理是什么 目录 索引使用的优势 索引使用的劣势 1 维护成本高 2 所占空间大 索引的分类 索引的创建规则 索引的CR
  • 约瑟夫环(数组解决)

    约瑟夫环问题是一个很经典的问题 一个圈共有N个人 N为不确定的数字 第一个人的编号为0或者1 两个都可以 看你的程序如何编写 假设这边我将第一个人的编号设置为1号 那么第二个人的编号就为2号 第三个人的编号就为3号 第N个人的编号就为N号
  • photoshop不能保存bmp格式

    文章目录 前言 一 显示图层无法导出当前的bmp格式图片 二 图层合并 总结 前言 使用位图进行深度学习的特征点标定时间比正常图片格式的时间要缩短一半 所以使用ps新增异常点 但是新增图层后无法保存bmp的格式 一 显示图层无法导出当前的b
  • 详解Spring Ioc(控制反转)

    Spring Ioc 控制反转是一个比较抽象的概念 可以举例来说明 生活中 人们要用到一种东西 人们的基本想法就是找到东西 比如想喝果汁 在没有饮品店的日子里 最直接的做法就是 买果汁机 水果 准备开水 这时我们 主动 创造的过程 也就是一
  • Python自动化测试——基础理论思维导图

    1 自动化测试的定义 2 自动化测试的优势 3 自动化测试和手工测试相比 有哪些区别 4 主流的测试用具 5 自动化测试的流程 6 适用于自动化测试的条件 7 选择自动化测试技术时以语言为主的技术线 主要用到的自动化测试工具是Seleniu
  • ​兔子快跑/rabbit-UI和接口自动化测试平台​

    Rabbit 是一个开源的自动化测试平台 基于经典技术组合 Spring Boot Spring Security MyBatis Jwt Vue 目前版本已支持UI自动化和接口自动化 平台采用关键字驱动 测试人员无需任何代码基础 即可轻松
  • ubuntu18.04解决因没有集成显卡驱动进不去界面问题

    1 问题及设备描述 设备 工控机 ubuntu18 04 i9cpu 集成显卡 问题 更化软件源时不小心将微软Microsoft等的源给删除了 没有备份 查资料发现集显就在主板上 与cpu有很大关系 于是觉得问题在于将集成显卡驱动软件的源给
  • 【计算机网络】——I/O复用之poll

    文章目录 1 poll的概述 2 poll函数的功能和作用 3 poll的特点 4 代码实现I O复用poll 1 poll的概述 在上一篇文章中 我们详细的介绍了I O复用技术中的select使用 这篇文章我们来主要介绍一下poll po
  • node初识

    一 什么是node node官网 https nodejs cn Node js是一个开源的 跨平台的JavaScript运行环境 它基于Chrome V8 JavaScript引擎 使得JavaScript可以在服务器端运行 Node j
  • 关于pandas中to_sql性能太慢的优化

    pd to sql table name db 这种方法虽然很简单 但是性能特别慢 插入6万条数据 需要将近5分钟 engine sqla create engine postgresql psycopg2 user pwd IPCLOUD
  • 台式计算机耳机有杂音怎么办,电脑耳机有杂音滋滋怎么办

    快速导读 Q1 电脑耳机插上有杂音是怎么回事 应该是你打开了麦克风的声音 你可以右击小喇叭 打开音量控制 勾选麦克风下面的静音 试试看 如果还不行的话应该是耳机和电脑音频插口接触不良 你可以对接触处进行清洁 如果是耳机出问题就直接换一个好了
  • 内推名企实习,就来CSDN超级实习生计划,2022年名企实习内推开始发车

    一份拿得出手的大厂实习经验有多重要 对没有经验的大二 大三学生来说 这是为自身真实能力背书 是拓宽视野 结交人脉的好机会 更是为以后拿到互联网大厂offer奠定基础 对秋招失利 错过秋招的应届生来说 这是抓住最后时机给简历镀金 逆袭春招的最
  • ReadTimeoutError报错解决

    ReadTimeoutError报错成功解决 报错 在python安装库的时候 可能会出现像下面的这种报错情况 raise ReadTimeoutError self pool None Read timed out ReadTimeout
  • web前端学习路线(含20个真实web开发项目集合)

    目前web前端工程师日均岗位缺口已经超过50000 随着互联网 的深入发展 html5作为前端展示技术 市场人才需求量将呈直线上涨 Web前端工程师的岗位职责是利用HTML CSS Java DOM等各种web技能结合产品的界面开发 制作标
  • linux4.6 EC11旋转编码器的驱动

    最近项目使用了旋转编码器EC11 遍查内核 发现并没有它的驱动 查了查 终于找到一篇有用的 根据自己的需要和对最基础的gpio key c的理解 我改写出了一份EC11的专用驱动 感谢下面博主的启发 有了这位高人的指点 我才有信心改写成功