Neza-D1开发板学习之红外发送与接收篇
-
- D1芯片本身有硬件ir-tx ir-rx,但在开发板上通过扩展IO引出的只有IR-RX,IR-TX用不了,被I2C2占用了,只有用IO来发射红外信号了
- 设备对配置
发射引脚,使用的是GPIO 需要在内核打开GPIO IR Bit Banging
ir_send { compatible = "gpio-ir-tx"; gpios = <&pio 3 22 GPIO_ACTIVE_HIGH>; /* PD22 */ status = "okay"; }; 接收引脚 &s_cir0 { pinctrl-names = "default", "sleep"; pinctrl-0 = <&s_cir0_pins_a>; pinctrl-1 = <&s_cir0_pins_b>; linux,rc-map-name = "rc-tbs-nec"; status = "okay"; };
下边是系统log
[ 1.719737] i2c /dev entries driver [ 1.723748] IR NEC protocol handler initialized [ 1.728825] IR RC5(x/sz) protocol handler initialized [ 1.735217] rc rc0: GPIO IR Bit Banging Transmitter as /devices/platform/soc@3000000/soc@3000000:ir_send/rc/rc0 [ 1.746722] rc rc0: lirc_dev: driver gpio-ir-tx registered at minor = 0, no receiver, raw IR transmitter [ 1.758445] sunxi_ir_startup: get ir protocol failed [ 1.758467] (NULL device *): deviceless supply not found, using dummy regulator [ 1.772394] Registered IR keymap rc_map_sunxi [ 1.777404] rc rc1: sunxi-ir as /devices/platform/soc@3000000/7040000.s_cir/rc/rc1 [ 1.786130] rc rc1: lirc_dev: driver sunxi-rc-recv registered at minor = 1, raw IR receiver, no transmitter [ 1.797263] input: sunxi-ir as /devices/platform/soc@3000000/7040000.s_cir/rc/rc1/s_cir_rx
-
查看系统 /dev下的设备
# ls /dev/lirc* /dev/lirc1 /dev/lirc1 /dev/lircd
-
此时查看/dev/input目录下,会有如下显示:
# evtest No device specified, trying to scan all of /dev/input/event* Available devices: /dev/input/event0: sunxi-keyboard /dev/input/event1: soc@3000000:rotary /dev/input/event2: sunxi-ir /dev/input/event3: audiocodec sunxi Audio Jack /dev/input/event4: soc@3000000:gpio_keys /dev/input/event5: ns2009_ts
此时如果用evtest测试按键是没有任何反应的,因为keymap我们没有修改成自己用的遥控器,当然就不上报事件了,但不影响后续操作
-
我们可以用lirc里的工具去测试硬件是否OK,测试之前要先修改默认配置文件,不修改的话,同样没反应
# vi /etc/lirc/lirc_options.conf driver = default device = /dev/lric1 修改这2行就可以,里边driver默认是uinput,device默认是auto 再次测试就有反应了 # mode2 -m -d /dev/lirc1 Using driver default on device /dev/lirc1 Trying device: /dev/lirc1 Using device: /dev/lirc1 Warning: Running as root. 9043 4402 626 497 656 499 624 499 656 499 624 499 656 499 624 499 624 531 624 1630 619 1624 655 1624 624 1624 624 1634 646 1624 624 1624 655 1624 593 1656 624 501 654 1624 593 534 652 1624 624 499 625 1624 656 504 619 499 655 1625 624 499 656 1625 593 531 624 1633 648 498 624 1624 624 40035 9060 2184 624 143451-pulse 483450-space
从这结果上可以明显的看出这些数值代表脉冲宽度,单位是us
-
使用irrecod -f -d /dev/lirc1 --disable-namespace来录制配置文件
录制完成后放到 /etc/lric/liricd.conf.d/下边
!注意,这里录制的结果不准确,需要借助上边的命令来获取每一个按键的值,这里只是借用一下配置文件的格式,里边的数字是右对齐
示例:# Please take the time to finish this file as described in # https://sourceforge.net/p/lirc-remotes/wiki/Checklist/ # and make it available to others by sending it to # <lirc@bartelmus.de> # # This config file was automatically generated # using lirc-0.10.1(default) on Thu Jan 1 01:37:06 1970 # Command line used: -f -d /dev/lirc1 --disable-namespace # Kernel version (uname -r): 5.10.19 # # Remote name (as of config file): elac # Brand of remote device, the thing you hold in your hand: # Remote device model nr: # Remote device info url: # Does remote device has a bundled capture device e. g., a # usb dongle? : # For bundled USB devices: usb vendor id, product id # and device string (use dmesg or lsusb): # Type of device controlled # (TV, VCR, Audio, DVD, Satellite, Cable, HTPC, ...) : # Device(s) controlled by this remote: begin remote name elac flags RAW_CODES|CONST_LENGTH eps 30 aeps 100 gap 108533 begin raw_codes name Power 9043 4403 623 531 593 531 624 531 593 531 624 531 593 531 624 531 593 536 594 1680 592 1656 593 1656 625 1655 593 1666 582 1656 624 1656 593 1655 625 530 593 534 621 530 593 1656 624 1624 624 531 593 530 624 531 595 1655 623 1655 593 1656 593 530 624 531 593 1664 616 1656 593 1656 593 name BT 9041 4407 622 531 593 531 593 562 593 531 593 531 625 533 596 525 624 530 593 1656 624 1656 593 1655 593 1664 616 1655 593 1656 593 1656 624 1658 591 530 624 1656 593 531 624 531 593 531 593 531 624 1661 587 530 624 1656 593 531 593 1687 593 1656 601 1648 624 1656 593 531 593 1656 624 name Vol+ 9013 4437 592 530 593 562 593 531 624 531 593 531 594 565 589 530 593 531 624 1656 593 1656 624 1665 590 1651 591 1656 624 1655 593 1656 593 1667 613 531 593 1656 624 1656 593 531 593 562 595 528 593 1656 624 531 593 1656 624 531 593 530 593 1659 621 1655 593 1656 593 562 593 1656 593 name Vol- 9044 4436 592 531 624 531 593 533 622 530 593 531 593 531 624 531 593 530 624 1656 593 1661 595 1679 593 1655 593 1656 624 1656 593 1667 582 1659 620 530 593 1656 624 1656 600 524 624 1656 593 531 593 531 624 531 593 1656 624 531 598 530 620 1654 593 531 624 1625 624 1656 593 1666 614 name Pre 9048 4403 592 562 593 530 593 562 593 530 593 531 624 531 593 531 624 531 593 1661 593 1680 592 1656 593 1656 624 1656 603 1650 588 1656 623 1656 593 1656 624 1662 587 1655 593 531 624 531 593 531 624 1656 593 531 631 524 593 530 593 562 593 1656 593 1656 624 1663 586 530 624 1624 624 . . . . . end raw_codes end remote
-
接下来使用irw来验证刚才录制的是否正确
# irw lircd-0.10.1[432]: Notice: accepted new client on /var/run/lirc/lircd lircd-0.10.1[432]: Info: [lirc] protocol is enabled 0000000000000001 00 Power elac 0000000000000002 00 BT elac 0000000000000003 00 Vol+ elac 0000000000000004 00 Vol- elac 0000000000000008 00 Ana1 elac 000000000000000a 00 Opt1 elac 000000000000000b 00 Opt2 elac
-
然后在/etc/lirc/目录下创建lircrc配置文件或~/.lircrc
格式如下begin prog = irexec button = Power repeat = 0 config = echo "power" end begin prog = irexec button = Vol+ repeat = 1 config = amixer -M -c 0 sset 'Headphone',0 1%+ > /dev/null end begin prog = irexec button = Vol- repeat = 1 config = amixer -M -c 0 sset 'Headphone',0 1%- > /dev/null end
保存
-
最后就是使用irexec来进行各种操作了,无需编程,到这里可以自由发挥了,想要集成到代码里也很简单,看下图
# irexec lircd-0.10.1[448]: Notice: accepted new client on /var/run/lirc/lircd lircd-0.10.1[448]: Info: [lirc] protocol is enabled volume up click Simple mixer control 'Headphone',0 Capabilities: pvolume pvolume-joined pswitch Playback channels: Front Left - Front Right Limits: Playback 0 - 63 Mono: Front Left: Playback 47 [54%] [-16.00dB] [on] Front Right: Playback 47 [54%] [-16.00dB] [on] volume down click Simple mixer control 'Headphone',0 Capabilities: pvolume pvolume-joined pswitch Playback channels: Front Left - Front Right Limits: Playback 0 - 63 Mono: Front Left: Playback 45 [50%] [-18.00dB] [on] Front Right: Playback 45 [50%] [-18.00dB] [on]
-
LIRC处理流程
+--------+ +-------------+ +--------+ | | | Linux input | | Appli- | --->---| kernel |---->----| layer |---------->----------| cation | | | | | /dev/input/eventX | | +--------+ +-------------+ +--------+ +--------+ +-------------+ | | | Linux input | --->---| kernel |---->----| layer | | | | | +--------+ +-------------+ | v | | +--------+ +-------------+ | Appli- | | lirc |---------->----------| cation |-+ | | lirc socket | | | +-------------+ +--------+ |-+ | | | +--------+ | | | +--------+ +--------+ +-------------+ +--------+ | | | | | Appli- | --->---| kernel |---->----| lirc |---------->----------| cation |-+ | | | | lirc socket | | | +--------+ +-------------+ +--------+ |-+ | | | +--------+ | | | +--------+
-
通过socket使用lirc,不需要引入任何文件,可以方便的集成到代码里,就是上述第三种方式
struct sigaction act; char buf[128]; struct sockaddr_un addr; typedef struct { char addr[32]; char code[8]; char type[16]; char name[16]; } IRW_DATA; IRW_DATA irw_data; act.sa_handler = sigusr1; sigfillset(&act.sa_mask); act.sa_flags = SA_RESTART; /* don't fiddle with EINTR */ sigaction(SIGUSR1, &act, NULL); addr.sun_family = AF_UNIX; strcpy(addr.sun_path, "/var/run/lirc/lircd"); fd_lircd = socket(AF_UNIX, SOCK_STREAM | SOCK_NONBLOCK, 0); if (fd_lircd == -1) { printf("Create socket failed\n"); } if (connect(fd_lircd, (struct sockaddr *)&addr, sizeof(addr)) == -1) { printf("Cannot connect to socket %s\n", addr.sun_path); } while (1) { // lircd if (read(fd_lircd, buf, 128) > 0) { LOG_D("%s\n", buf); char *p = strtok(buf, " "); int i = 0; while (p) { // LOG_D("%s\n", p); if (i == 0) strcpy(irw_data.addr, p); else if (i == 1) strcpy(irw_data.code, p); else if (i == 2) strcpy(irw_data.type, p); else if (i == 3) strcpy(irw_data.name, p); p = strtok(NULL, " "); i++; } LOG_D("%s\n", irw_data.type); switch ((uint8_t)strtol(irw_data.addr, NULL, 10)) { case Vol_up: rotary_encoder_handler(&u8g2, -1); break; case Vol_down: rotary_encoder_handler(&u8g2, 1); break; case Play: rotary_encoder_button_handler(&u8g2); break; case Bt: printf("BT button\n"); break; } } }
-
下边开始向外发射IR信号,发射就使用之前录制的配置文件
irsend SEND_ONCE elac power
- D1芯片本身有硬件ir-tx ir-rx,但在开发板上通过扩展IO引出的只有IR-RX,IR-TX用不了,被I2C2占用了,只有用IO来发射红外信号了
-
root@TinaLinux:/# evtest /dev/input/event0 Input driver version is 1.0.1 Input device ID: bus 0x19 vendor 0x1 product 0x1 version 0x100 Input device name: "sunxi-ir" Supported events: Event type 0 (Sync) Event type 1 (Key) Event code 1 (Esc) Event type 2 (Relative) Event code 0 (X) Event code 1 (Y) Event type 4 (Misc) Event code 4 (ScanCode) Event type 20 (Repeat) Testing ... (interrupt to exit)
果然纹丝不动,遥控器按坏也没反应。
-
root@TinaLinux:/# root@TinaLinux:/# hexdump /dev/lirc0 0000000 0f36 0100 0fac 0000 01d6 0100 03dd 0000 0000010 01e1 0100 03dd 0000 01d6 0100 03dd 0000 0000020 01e1 0100 03dd 0000 01e1 0100 03dd 0000 0000030 01d6 0100 03e3 0000 01d6 0100 03e3 0000 0000040 01d6 0100 03dd 0000 01e1 0100 03ed 0000 * 0000060 01d6 0100 03ed 0000 01d6 0100 03ed 0000 0000070 01d6 0100 03ed 0000 01e1 0100 03ed 0000 0000080 01d6 0100 03ed 0000 01d6 0100 03ed 0000 0000090 01c1 0100 0403 0000 01d6 0100 03ed 0000 00000a0 01e1 0100 03ed 0000 01b6 0100 03ed 0000 00000b0 01e1 0100 03ed 0000 01d6 0100 03dd 0000 00000c0 01e1 0100 03dd 0000 01e1 0100 2059 0000 00000d0 0f41 0100 0fa1 0000 01e1 0100 03dd 0000 00000e0 01d6 0100 03e3 0000 01d6 0100 03e3 0000 00000f0 01d6 0100 03dd 0000 01e1 0100 03dd 0000 0000100 01e1 0100 03dd 0000 01d6 0100 03e3 0000 0000110 01d6 0100 03e3 0000 01d6 0100 03ed 0000 * 0000130 01d6 0100 03ed 0000 01d6 0100 03ed 0000 0000140 01e1 0100 03ed 0000 01d6 0100 03ed 0000 0000150 01c1 0100 0403 0000 01d6 0100 03ed 0000 0000160 01e1 0100 03ed 0000 01d6 0100 03ed 0000 0000170 01d6 0100 03ed 0000 01d6 0100 03e3 0000 0000180 01d6 0100 03ed 0000 01e1 0100 03dd 0000 0000190 01d6 0100 03e3 0000 01d6 0100 2064 0000 00001a0 0f36 0100 0fac 0000 01d6 0100 03e3 0000 00001b0 01f6 0100 03cd 0000 01e1 0100 03dd 0000 00001c0 01e1 0100 03dd 0000 01e1 0100 03dd 0000 00001d0 01d6 0100 03e3 0000 01d6 0100 03dd 0000 00001e0 01e1 0100 03dd 0000 01d6 0100 03f8 0000 00001f0 01d6 0100 03dd 0000 01e1 0100 03ed 0000 0000200 01d6 0100 03ed 0000 01d6 0100 03ed 0000 0000210 01d6 0100 03ed 0000 01e1 0100 03ed 0000 0000220 01d6 0100 03ed 0000 01d6 0100 03ed 0000 0000230 01c1 0100 0403 0000 01e1 0100 03ed 0000 0000240 01d6 0100 03ed 0000 01d6 0100 03e3 0000
直接读 /dev/lirc0 是有数据的 ^_^
-
这玩意终于让我找到了,原来tina sdk 里面没有,在buildroot 里面的。
-
还发现一个问题,如果只勾上NEC,有些遥控器能识别,有些遥控器不能识别,我现在去勾上所有解码器试一试。
-
所有解码器全勾上了,左边两个可以识别,右边两个欧普照明的遥控器不能识别,这两个好像是带学习功能的,估计是自定义协议了。
Copyright © 2024 深圳全志在线有限公司 粤ICP备2021084185号 粤公网安备44030502007680号