Linux红外驱动重点解析

红外遥控是我们经常见到的一种无线收发设备,比如电视遥控,空调遥控,现在电视遥控有些慢慢变成了蓝牙装置。昨天是在知识星球里面看到有人提问,今天来解析一份网友写的驱动程序。

调试红外需要注意几个细节

1、我们发射的遥控器用肉眼是看不到的,需要拿相机来观察。

2、红外接收管和普通的二极管不同,如果用错物料也是不行的。

1.NEC协议无线传输数据原理

NEC协议的特征: 

1、8位地址和8位指令长度; 

2、地址和命令两次传输;(确保可靠性) 

3、PWM脉冲宽度调制,以发射红外载波的占空比代表“0”和“1”; 

4、载波频率为38KHz 

5、位时间为1.125ms和2.25ms 

NEC码位的定义:一个脉冲对应560us的连续载波,一个逻辑1传输需要2.25ms(560us脉冲+1680us低电平),一个逻辑0的 传输需要1.125ms(560us脉冲+560us低电平)。

而遥控接收头在收到脉冲时为低电平,在没有收到脉冲时为高电平,因此, 我们在接收头端收到的信号为:逻辑1应该是560us低+1680us高,逻辑0应该是560us低+560us高。

如下图:

硬件

2. Linux下的驱动接收程序

参考原文:

https://blog.csdn.net/wllw7176/article/details/110506677

两个驱动文件

gpio-ir-recv.c

/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.** This program is free software; you can redistribute it and/or modify* it under the terms of the GNU General Public License version 2 and* only version 2 as published by the Free Software Foundation.** This program is distributed in the hope that it will be useful,* but WITHOUT ANY WARRANTY; without even the implied warranty of* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the* GNU General Public License for more details.*/#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/interrupt.h>
#include <linux/gpio.h>
#include <linux/slab.h>
#include <linux/of.h>
#include <linux/of_gpio.h>
#include <linux/platform_device.h>
#include <linux/irq.h>
#include <media/rc-core.h>
#include <media/gpio-ir-recv.h>#define GPIO_IR_DRIVER_NAME "gpio-rc-recv"
#define GPIO_IR_DEVICE_NAME "gpio_ir_recv"struct gpio_rc_dev {struct rc_dev *rcdev;int gpio_nr;bool active_low;
};#ifdef CONFIG_OF
/** Translate OpenFirmware node properties into platform_data*/
static int gpio_ir_recv_get_devtree_pdata(struct device *dev,struct gpio_ir_recv_platform_data *pdata)
{struct device_node *np = dev->of_node;enum of_gpio_flags flags;int gpio;gpio = of_get_gpio_flags(np, 0, &flags);if (gpio < 0) {if (gpio != -EPROBE_DEFER)dev_err(dev, "Failed to get gpio flags (%d)\n", gpio);return gpio;}pdata->gpio_nr = gpio;pdata->active_low = (flags & OF_GPIO_ACTIVE_LOW);/* probe() takes care of map_name == NULL or allowed_protos == 0 */pdata->map_name = of_get_property(np, "linux,rc-map-name", NULL);pdata->allowed_protos = 0;return 0;
}static const struct of_device_id gpio_ir_recv_of_match[] = {{ .compatible = "gpio-ir-receiver", },{ },
};
MODULE_DEVICE_TABLE(of, gpio_ir_recv_of_match);#else /* !CONFIG_OF */#define gpio_ir_recv_get_devtree_pdata(dev, pdata) (-ENOSYS)#endifstatic irqreturn_t gpio_ir_recv_irq(int irq, void *dev_id)
{struct gpio_rc_dev *gpio_dev = dev_id;int gval;int rc = 0;enum raw_event_type type = IR_SPACE;gval = gpio_get_value(gpio_dev->gpio_nr);if (gval < 0)goto err_get_value;if (gpio_dev->active_low)gval = !gval;if (gval == 1)type = IR_PULSE;rc = ir_raw_event_store_edge(gpio_dev->rcdev, type);if (rc < 0)goto err_get_value;ir_raw_event_handle(gpio_dev->rcdev);err_get_value:return IRQ_HANDLED;
}static int gpio_ir_recv_probe(struct platform_device *pdev)
{struct gpio_rc_dev *gpio_dev;struct rc_dev *rcdev;const struct gpio_ir_recv_platform_data *pdata =pdev->dev.platform_data;int rc;if (pdev->dev.of_node) {struct gpio_ir_recv_platform_data *dtpdata =devm_kzalloc(&pdev->dev, sizeof(*dtpdata), GFP_KERNEL);if (!dtpdata)return -ENOMEM;rc = gpio_ir_recv_get_devtree_pdata(&pdev->dev, dtpdata);if (rc)return rc;pdata = dtpdata;}if (!pdata)return -EINVAL;if (pdata->gpio_nr < 0)return -EINVAL;gpio_dev = kzalloc(sizeof(struct gpio_rc_dev), GFP_KERNEL);if (!gpio_dev)return -ENOMEM;rcdev = rc_allocate_device();if (!rcdev) {rc = -ENOMEM;goto err_allocate_device;}rcdev->priv = gpio_dev;rcdev->driver_type = RC_DRIVER_IR_RAW;rcdev->input_name = GPIO_IR_DEVICE_NAME;rcdev->input_phys = GPIO_IR_DEVICE_NAME "/input0";rcdev->input_id.bustype = BUS_HOST;rcdev->input_id.vendor = 0x0001;rcdev->input_id.product = 0x0001;rcdev->input_id.version = 0x0100;rcdev->dev.parent = &pdev->dev;rcdev->driver_name = GPIO_IR_DRIVER_NAME;if (pdata->allowed_protos)rcdev->allowed_protocols = pdata->allowed_protos;elsercdev->allowed_protocols = RC_BIT_ALL;rcdev->map_name = pdata->map_name ?: RC_MAP_EMPTY;gpio_dev->rcdev = rcdev;gpio_dev->gpio_nr = pdata->gpio_nr;gpio_dev->active_low = pdata->active_low;rc = gpio_request(pdata->gpio_nr, "gpio-ir-recv");if (rc < 0)goto err_gpio_request;rc  = gpio_direction_input(pdata->gpio_nr);if (rc < 0)goto err_gpio_direction_input;rc = rc_register_device(rcdev);if (rc < 0) {dev_err(&pdev->dev, "failed to register rc device\n");goto err_register_rc_device;}platform_set_drvdata(pdev, gpio_dev);rc = request_any_context_irq(gpio_to_irq(pdata->gpio_nr),gpio_ir_recv_irq,IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING,"gpio-ir-recv-irq", gpio_dev);if (rc < 0)goto err_request_irq;return 0;err_request_irq:rc_unregister_device(rcdev);rcdev = NULL;
err_register_rc_device:
err_gpio_direction_input:gpio_free(pdata->gpio_nr);
err_gpio_request:rc_free_device(rcdev);
err_allocate_device:kfree(gpio_dev);return rc;
}static int gpio_ir_recv_remove(struct platform_device *pdev)
{struct gpio_rc_dev *gpio_dev = platform_get_drvdata(pdev);free_irq(gpio_to_irq(gpio_dev->gpio_nr), gpio_dev);rc_unregister_device(gpio_dev->rcdev);gpio_free(gpio_dev->gpio_nr);kfree(gpio_dev);return 0;
}#ifdef CONFIG_PM
static int gpio_ir_recv_suspend(struct device *dev)
{struct platform_device *pdev = to_platform_device(dev);struct gpio_rc_dev *gpio_dev = platform_get_drvdata(pdev);if (device_may_wakeup(dev))enable_irq_wake(gpio_to_irq(gpio_dev->gpio_nr));elsedisable_irq(gpio_to_irq(gpio_dev->gpio_nr));return 0;
}static int gpio_ir_recv_resume(struct device *dev)
{struct platform_device *pdev = to_platform_device(dev);struct gpio_rc_dev *gpio_dev = platform_get_drvdata(pdev);if (device_may_wakeup(dev))disable_irq_wake(gpio_to_irq(gpio_dev->gpio_nr));elseenable_irq(gpio_to_irq(gpio_dev->gpio_nr));return 0;
}static const struct dev_pm_ops gpio_ir_recv_pm_ops = {.suspend        = gpio_ir_recv_suspend,.resume         = gpio_ir_recv_resume,
};
#endifstatic struct platform_driver gpio_ir_recv_driver = {.probe  = gpio_ir_recv_probe,.remove = gpio_ir_recv_remove,.driver = {.name   = GPIO_IR_DRIVER_NAME,.of_match_table = of_match_ptr(gpio_ir_recv_of_match),
#ifdef CONFIG_PM.pm = &gpio_ir_recv_pm_ops,
#endif},
};
module_platform_driver(gpio_ir_recv_driver);MODULE_DESCRIPTION("GPIO IR Receiver driver");
MODULE_LICENSE("GPL v2");

ir-nec-decoder.c

/* ir-nec-decoder.c - handle NEC IR Pulse/Space protocol** Copyright (C) 2010 by Mauro Carvalho Chehab** This program is free software; you can redistribute it and/or modify*  it under the terms of the GNU General Public License as published by*  the Free Software Foundation version 2 of the License.**  This program is distributed in the hope that it will be useful,*  but WITHOUT ANY WARRANTY; without even the implied warranty of*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the*  GNU General Public License for more details.*/#include <linux/bitrev.h>
#include <linux/module.h>
#include "rc-core-priv.h"#define NEC_NBITS  32
#define NEC_UNIT  562500  /* ns */
#define NEC_HEADER_PULSE (16 * NEC_UNIT)
#define NECX_HEADER_PULSE (8  * NEC_UNIT) /* Less common NEC variant */
#define NEC_HEADER_SPACE (8  * NEC_UNIT)
#define NEC_REPEAT_SPACE (4  * NEC_UNIT)
#define NEC_BIT_PULSE  (1  * NEC_UNIT)
#define NEC_BIT_0_SPACE  (1  * NEC_UNIT)
#define NEC_BIT_1_SPACE  (3  * NEC_UNIT)
#define NEC_TRAILER_PULSE (1  * NEC_UNIT)
#define NEC_TRAILER_SPACE (10 * NEC_UNIT) /* even longer in reality */
#define NECX_REPEAT_BITS 1enum nec_state {STATE_INACTIVE,STATE_HEADER_SPACE,STATE_BIT_PULSE,STATE_BIT_SPACE,STATE_TRAILER_PULSE,STATE_TRAILER_SPACE,
};/*** ir_nec_decode() - Decode one NEC pulse or space* @dev: the struct rc_dev descriptor of the device* @duration: the struct ir_raw_event descriptor of the pulse/space** This function returns -EINVAL if the pulse violates the state machine*/
static int ir_nec_decode(struct rc_dev *dev, struct ir_raw_event ev)
{struct nec_dec *data = &dev->raw->nec;u32 scancode;u8 address, not_address, command, not_command;bool send_32bits = false;if (!(dev->enabled_protocols & RC_BIT_NEC))return 0;if (!is_timing_event(ev)) {if (ev.reset)data->state = STATE_INACTIVE;return 0;}IR_dprintk(2, "NEC decode started at state %d (%uus %s)\n",data->state, TO_US(ev.duration), TO_STR(ev.pulse));switch (data->state) {case STATE_INACTIVE:if (!ev.pulse)break;if (eq_margin(ev.duration, NEC_HEADER_PULSE, NEC_UNIT * 2)) {data->is_nec_x = false;data->necx_repeat = false;} else if (eq_margin(ev.duration, NECX_HEADER_PULSE, NEC_UNIT / 2))data->is_nec_x = true;elsebreak;data->count = 0;data->state = STATE_HEADER_SPACE;return 0;case STATE_HEADER_SPACE:if (ev.pulse)break;if (eq_margin(ev.duration, NEC_HEADER_SPACE, NEC_UNIT)) {data->state = STATE_BIT_PULSE;return 0;} else if (eq_margin(ev.duration, NEC_REPEAT_SPACE, NEC_UNIT / 2)) {if (!dev->keypressed) {IR_dprintk(1, "Discarding last key repeat: event after key up\n");} else {rc_repeat(dev);IR_dprintk(1, "Repeat last key\n");data->state = STATE_TRAILER_PULSE;}return 0;}break;case STATE_BIT_PULSE:if (!ev.pulse)break;if (!eq_margin(ev.duration, NEC_BIT_PULSE, NEC_UNIT / 2))break;data->state = STATE_BIT_SPACE;return 0;case STATE_BIT_SPACE:if (ev.pulse)break;if (data->necx_repeat && data->count == NECX_REPEAT_BITS &&geq_margin(ev.duration,NEC_TRAILER_SPACE, NEC_UNIT / 2)) {IR_dprintk(1, "Repeat last key\n");rc_repeat(dev);data->state = STATE_INACTIVE;return 0;} else if (data->count > NECX_REPEAT_BITS)data->necx_repeat = false;data->bits <<= 1;if (eq_margin(ev.duration, NEC_BIT_1_SPACE, NEC_UNIT / 2))data->bits |= 1;else if (!eq_margin(ev.duration, NEC_BIT_0_SPACE, NEC_UNIT / 2))break;data->count++;if (data->count == NEC_NBITS)data->state = STATE_TRAILER_PULSE;elsedata->state = STATE_BIT_PULSE;return 0;case STATE_TRAILER_PULSE:if (!ev.pulse)break;if (!eq_margin(ev.duration, NEC_TRAILER_PULSE, NEC_UNIT / 2))break;data->state = STATE_TRAILER_SPACE;return 0;case STATE_TRAILER_SPACE:if (ev.pulse)break;if (!geq_margin(ev.duration, NEC_TRAILER_SPACE, NEC_UNIT / 2))break;address     = bitrev8((data->bits >> 24) & 0xff);not_address = bitrev8((data->bits >> 16) & 0xff);command     = bitrev8((data->bits >>  8) & 0xff);not_command = bitrev8((data->bits >>  0) & 0xff);if ((command ^ not_command) != 0xff) {IR_dprintk(1, "NEC checksum error: received 0x%08x\n",data->bits);send_32bits = true;}if (send_32bits) {/* NEC transport, but modified protocol, used by at* least Apple and TiVo remotes */scancode = data->bits;IR_dprintk(1, "NEC (modified) scancode 0x%08x\n", scancode);} else if ((address ^ not_address) != 0xff) {/* Extended NEC */scancode = address     << 16 |not_address <<  8 |command;IR_dprintk(1, "NEC (Ext) scancode 0x%06x\n", scancode);} else {/* Normal NEC */scancode = address << 8 | command;IR_dprintk(1, "NEC scancode 0x%04x\n", scancode);}if (data->is_nec_x)data->necx_repeat = true;rc_keydown(dev, RC_TYPE_NEC, scancode, 0);data->state = STATE_INACTIVE;return 0;}IR_dprintk(1, "NEC decode failed at count %d state %d (%uus %s)\n",data->count, data->state, TO_US(ev.duration), TO_STR(ev.pulse));data->state = STATE_INACTIVE;return -EINVAL;
}static struct ir_raw_handler nec_handler = {.protocols = RC_BIT_NEC,.decode  = ir_nec_decode,
};static int __init ir_nec_decode_init(void)
{ir_raw_handler_register(&nec_handler);printk(KERN_INFO "IR NEC protocol handler initialized\n");return 0;
}static void __exit ir_nec_decode_exit(void)
{ir_raw_handler_unregister(&nec_handler);
}module_init(ir_nec_decode_init);
module_exit(ir_nec_decode_exit);MODULE_LICENSE("GPL");
MODULE_AUTHOR("Mauro Carvalho Chehab");
MODULE_AUTHOR("Red Hat Inc. (http://www.redhat.com)");
MODULE_DESCRIPTION("NEC IR protocol decoder");

参考文章中的dts文件:

gpio-ir-receiver {compatible = "gpio-ir-receiver";gpios = <&gpio4 19 GPIO_ACTIVE_HIGH>; //连接红外的中断引脚active_low = <1>;                     //红外接收器是否将信号取反,有些红外接收器会将接收到的高低电平信号反向输出,比如我使用的hx1838红外接收器linux,rc-map-name = "rc-hx18380-carmp3"; //红外scancode与实际input_evnent code映射表名称,要在rc_register_device注册,具体见gpio-ir-recv.callowed_protos = <0x100>; /*NEC protocol*/ //保留,驱动中并未使用
};

另一个文件里面调用的

ir-nec-decoder.c

这个函数是Linux内核中的红外处理申请函数

这里主要是注册一个解码的结构体

ir-nec-decoder.c

3.中断处理程序解析

gpio-ir-recv.c

ir_raw_event_store_edge() 这个函数用来计算电平的持续时间。

ir_raw_event_handle() 用来处理这个电平表示什么含义。

驱动程序里面,首先是判断当前GPIO电平,如果是低电平,就进入红外解析,如果不是,或者获取失败,就退出程序。

4.红外数据处理程序解析

内核专门开了一个线程来处理数据解析

rc-ir-raw.c

处理函数其实就是处理电平时间长短来决定数字信号

ir-nec-decoder.c

这里是判断头,这个时间和9ms进行比较

9ms 从哪里来的,可以看看这里

ir-nec-decoder.c

拿到头后,这个switch函数就继续往下跑

ir-nec-decoder.c

然后就是判断 1 和 0  的时候了

ir-nec-decoder.c


上面那个就是1,下面那个就是0。

4.然后数据怎么上报呢?

ir-nec-decoder.c

这里是在另一个模块中注册的映射

不同的红外键值对应不同的上报按键键值

rc-trekstor.c

6.参考

https://cloud.tencent.com/developer/article/1354479

https://blog.csdn.net/wllw7176/article/details/110506677


推荐阅读:

专辑|Linux文章汇总

专辑|程序人生

专辑|C语言

我的知识小密圈

关注公众号,后台回复「1024」获取学习资料网盘链接。

欢迎点赞,关注,转发,在看,您的每一次鼓励,我都将铭记于心~

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

每日一题(5) —— 逗号表达式

分析下面的代码&#xff0c;求运算结果。 #include <stdio.h>int main(void) {int a[3][2] {(0, 1), (2, 3), (4, 5)};int *p a[0];printf("%d\n", p[0]);return 0; }分析&#xff1a; 仔细观察可以看出&#xff0c;大括号里面的是(),而不是花括号&#xff…

整理一篇Linux drm显示系统的文章

这篇文章主要是回答一位同学的提问&#xff0c;当然也是做一次总结&#xff0c;我相信关注我号的很多人也有做LCD相关的驱动或者系统开发&#xff0c;即使不是专门做LCD&#xff0c;但是在开发过程中也难免会遇到这样或者那样的问题。所以找了几篇和drm不错的文章分享给大家&am…

Java实现十进制数转十六进制数

Now~Lets begin our second question~ 如何利用Java语言将十进制数字转换成十六进制数字呢&#xff1f; 我第一次编码出来的效果是酱紫的~ /*** */ package com.succez.task2;import java.util.Scanner;/*** <p>Copyright: Copyright (c) 2018</p>* <p>succe…

[转]JavaScript:只能输入数字(IE、FF)

本文转自&#xff1a;http://www.cnblogs.com/ly5201314/archive/2009/03/04/1402993.htmlJavaScript&#xff1a;只能输入数字(IE、FF) 为了解决只能输入数字的问题&#xff0c;网上有许多资料&#xff0c;现归拢一下。 一、不带负号的输入 这里&#xff0c;没有解决“正负号”…

每日一题(6)—— sizeof用法

已知int a&#xff0c;一下那种写法是错误的&#xff1f; A. sizeof(int); B. sizeof(a); C. sizeof int; D. sizeof a;以下答案是来自《C语言深度剖析》&#xff1a;

现在做硬件工程师还有前途吗?

这个问题是我在知乎看到的。问这个问题的&#xff0c;要么是正在从事硬件工作&#xff0c;要么是准备入行的新人。我工作年限不久&#xff0c;工作4年多。我先发表自己的一些观点&#xff0c;可能不对&#xff0c;勿喷&#xff0c;然后我再截取部分知乎上网友的回答。我大学的专…

58同城沈剑:好的架构是进化来的,不是设计来的

虽然这篇文章写的比较早&#xff0c;但是&#xff0c;还是很有参考意义&#xff0c;值得好好品读思考。看看别人是怎么思考就架构这种事情。 好的架构不是设计出来的而是演进出来的 对很多创业公司而言&#xff0c;在初期的时候&#xff0c;我们很难在初期就预估到流量十倍以后…

[译]5 Mac OS X RSS Readers Worth Giving a Shot

5 Mac OS X RSS Readers Worth Giving a Shot Mac OS X 下5款值得关注的RSS 阅读工具 There was once a time when my favorite RSS reader cost a fair but not insignificant price and the open source alternative wasn’t up-to-snuff. I won’t name any names, though y…

每日一题(7) —— 求余运算符

设有以下语句:int x10;x3x%(-3),则x的值是: A.11 B.12 C.14 D.15分析&#xff1a; 求余运算&#xff0c;除数和被除数都可以是负的&#xff0c;求余后的值 与 被除数 的符号相同&#xff0c;比如 -10 % -3 -1, 10 % -3 1。

一文读懂 Linux 内存分配全过程

在《你真的理解内存分配》一文中&#xff0c;我们介绍了 malloc 申请内存的原理&#xff0c;但其在内核怎么实现的呢&#xff1f;所以&#xff0c;本文主要分析在 Linux 内核中对堆内存分配的实现过程。本文使用 Linux 2.6.32 版本代码内存分区对象在《你真的理解内存分配》一文…

CodeForces - 540D Bad Luck Island —— 求概率

题目链接&#xff1a;https://vjudge.net/contest/226823#problem/D The Bad Luck Island is inhabited by three kinds of species: r rocks, s scissors and p papers. At some moments of time two random individuals meet (all pairs of individuals can meet equiprobabl…

你真的理解内存分配吗?

内存是计算机中必不可少的资源&#xff0c;因为 CPU 只能直接读取内存中的数据&#xff0c;所以当 CPU 需要读取外部设备&#xff08;如硬盘&#xff09;的数据时&#xff0c;必须先把数据加载到内存中。我们来看看可爱的内存长什么样子的吧&#xff0c;如图1所示&#xff1a;一…

每日一练(8)—— 野指针

int *p&#xff1b; int a 20; *p a; printf("%d",*p);运行结果是什么&#xff1f;A.10 B.a 的 地址值 C.编译错误 D.运行异常分析&#xff1a; 一、指针变量没有被初始化。任何指针变量刚被创建时不会自动成为NULL指针&#xff0c;它的缺省值是随机的&#xff0…

深信服2021秋招笔试题

来源于读者投稿&#xff0c;作者Angel。笔试时间&#xff1a;2020.08.25&#xff0c;19&#xff1a;00---21&#xff1a;00。岗位&#xff1a;嵌入式软件工程师。题型&#xff1a;5个不定项选择题&#xff0c;16分5个填空题&#xff0c;19分2道编程题&#xff0c;65分不定项选择…

每日一题(9)—— 写一个标准宏MIN,这个宏输入两个参数并返回较小的一个

写一个标准宏MIN&#xff0c;这个宏输入两个参数并返回较小的一个。 分析&#xff1a; 宏定义的注意两点&#xff1a; 1、数据类型是否有溢出的风险&#xff08;如一年有多少个秒的宏&#xff09;&#xff1b; 2、带参宏的每个参数都要用括号括起来。 #define MIN(x,y) ((x)…

用ISA阻挡用户向论坛发贴子

右击访问网站这条策略&#xff0c;点击“配置HTTP”<?XML:NAMESPACE PREFIX V /><?XML:NAMESPACE PREFIX O />找到方法选项&#xff0c;并添加一条阻止的HTTP命令POST应用ISA的配置转载于:https://blog.51cto.com/freemanluo/186829

看我解决Linux下的OTG切换问题

1.硬件原理图看下面的原理图VCC_OTG_EN 引脚&#xff0c;这个脚主要是用来控制给外部OTG设备提供电源控制的。如果设备作为DEVICE设备&#xff0c;这时候VBUS的电是由外部提供的&#xff0c;比如通过USB线和电脑连接&#xff0c;这个时候&#xff0c;VBUS的电压是由电脑提供的。…

每日一题(10)—— 数组与指针

分析下面的代码&#xff0c;求输出结果。 int a[5] {1,2,3,4,5};int *p (int *)(&a 1);printf("%d %d",*(a 1),*(p - 1)); 分析&#xff1a; a —— 数组首元素的地址 等价于 &a[0] &a —— 数组的首地址 int —— 4字节 *(a 1) a[1] 2&…

美图赏析:拆解USB无线网卡,电路方案非常经典

很多台式机没有无线网卡&#xff0c;只能插网线。想要使用WiFi&#xff0c;插个USB无线网卡就行&#xff0c;简单方便&#xff1a;USB无线网卡非常小巧&#xff0c;以至于会好奇&#xff0c;电路板是怎么塞进去的&#xff1a;下面拆解其中某个厂家的一款&#xff1a;另一个角度…

程序员经常说的「设计模式」到底是什么?

当程序员说去「设计模式」时&#xff0c;你是否会一脸懵逼&#xff0c;到底什么是设计模式呢&#xff1f; 很多人应该听说过设计模式&#xff08;Design pattern&#xff09;&#xff0c;又或多或少的看过或用过设计模式&#xff0c;但是实际用在开发过程中总有点心有余而力不足…