实验目标
编写HX1838红外接收器驱动,根据接收的波形脉冲解码红外按键键值
模块连接
模块连接:VCC接Pin 2,GND接Pin1,DATA接Pin16
驱动代码
HX1838 GPIO初始化,申请中断,注意:GPIO48默认是给i2c0使用的,使用前记得注释掉i2c0设备树节点
#define CODE_SIZE 4
#define HX1838_IO 48
#define TIME_UNIT 140
#define GPIO_VALUE gpio_get_value(HX1838_IO)static int __init hx1838_init(void)
{int ret;int irq = gpio_to_irq(HX1838_IO);printk("irq : %d\n", irq);gpio_request(HX1838_IO, "hx1838-gpio");gpio_direction_input(HX1838_IO);ret = request_irq(irq, irq_callback, IRQF_TRIGGER_FALLING, "hx1838-irq", NULL);if (ret < 0)goto LABEL;return 0;LABEL:gpio_free(HX1838_IO);return ret;
}
中断处理函数,解码格式:地址码 + 地址码反码 + 数据码 + 数据码反码,13.5ms为前导波形信号,第56行需要注意数据取反默认是32位的(需要强制转换)
typedef unsigned char uchar;static uchar array[CODE_SIZE];irqreturn_t irq_callback(int irqno, void *arg)
{unsigned char j,k,N=0;udelay(15 * TIME_UNIT);if (GPIO_VALUE == 1){// printk("111\n");return IRQ_HANDLED;}while (!GPIO_VALUE) {udelay(TIME_UNIT);} for (j=0; j < 4; j++) {for (k = 0; k < 8; k++) {while (GPIO_VALUE) {udelay(TIME_UNIT);}while (!GPIO_VALUE) {udelay(TIME_UNIT);}while (GPIO_VALUE) {udelay(TIME_UNIT);N++; if (N >= 30){// printk("222\n");return IRQ_HANDLED;} } array[j] = array[j] >> 1; if(N >= 8){array[j] = array[j] | 0x80; } N = 0;}} if(array[2] != (unsigned char)(~array[3])){// printk("333\n");return IRQ_HANDLED;}printk("%d,%d,%d,%d\n", array[0], array[1], array[2], array[3]);return IRQ_HANDLED;
}
完整驱动代码
#include <linux/init.h>
#include <linux/module.h>
#include <linux/interrupt.h>
#include <linux/delay.h>
#include <linux/gpio.h>#define CODE_SIZE 4
#define HX1838_IO 48
#define TIME_UNIT 140
#define GPIO_VALUE gpio_get_value(HX1838_IO)typedef unsigned char uchar;static uchar array[CODE_SIZE];irqreturn_t irq_callback(int irqno, void *arg)
{unsigned char j,k,N=0;udelay(15 * TIME_UNIT);if (GPIO_VALUE == 1){// printk("111\n");return IRQ_HANDLED;}while (!GPIO_VALUE) {udelay(TIME_UNIT);} for (j=0; j < 4; j++) {for (k = 0; k < 8; k++) {while (GPIO_VALUE) {udelay(TIME_UNIT);}while (!GPIO_VALUE) {udelay(TIME_UNIT);}while (GPIO_VALUE) {udelay(TIME_UNIT);N++; if (N >= 30){// printk("222\n");return IRQ_HANDLED;} } array[j] = array[j] >> 1; if(N >= 8){array[j] = array[j] | 0x80; } N = 0;}} if(array[2] != (unsigned char)(~array[3])){// printk("333\n");return IRQ_HANDLED;}printk("%d,%d,%d,%d\n", array[0], array[1], array[2], array[3]);return IRQ_HANDLED;
}static int __init hx1838_init(void)
{int ret;int irq = gpio_to_irq(HX1838_IO);printk("irq : %d\n", irq);gpio_request(HX1838_IO, "hx1838-gpio");gpio_direction_input(HX1838_IO);ret = request_irq(irq, irq_callback, IRQF_TRIGGER_FALLING, "hx1838-irq", NULL);if (ret < 0)goto LABEL;return 0;LABEL:gpio_free(HX1838_IO);return ret;
}static void __exit hx1838_exit(void)
{free_irq(gpio_to_irq(HX1838_IO), NULL);gpio_free(HX1838_IO);
}module_init(hx1838_init);
module_exit(hx1838_exit);MODULE_LICENSE("GPL");
Makefile文件
obj-m += irda.o
KDIR:=/home/asensing/loongson/linux-4.19
ARCH=loongarch
CROSS_COMPILE=loongarch64-linux-gnu-
PWD?=$(shell pwd)
all:make -C $(KDIR) M=$(PWD) modules
构建脚本
export PATH=$PATH:/home/asensing/loongson/loongson-gnu-toolchain-8.3-x86_64-loongarch64-linux-gnu-rc1.3-1/bin
make -j8
# loongarch64-linux-gnu-gcc test.c -o test
FILE=$PWD/$(basename $PWD).ko
scp $FILE root@192.168.137.232:/home/root
实验效果
装载驱动模块,然后在红外遥控器下按下按键,可以看到打印的红外解码数据:地址及其反码,数据及其反码
参考
本次代码根据51单片机程序移植:HX1838红外无线遥控模块51单片机程序 - 51单片机 (51hei.com)