实验目标
编写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)