BeagleBone论坛
直播中

陈鹏

12年用户 148经验值
擅长:可编程逻辑 嵌入式技术 模拟技术 接口/总线/驱动 控制/MCU RF/无线
私信 关注
[经验]

【BeagleBone Black试用体验[结项]】-[结项]-小型的二维码接收处理器

本帖最后由 290005999 于 2016-12-7 07:31 编辑

通过二维码扫码器读取目标的信息,通过黑、白像素在矩阵中的不同分布,来进行编码的。我们知道电脑使用二进制(0和1)数来贮存和处理数据,而在二维码中,用黑白矩形表示二进制数据我们肉眼能看到的黑色表示的是二进制“1”,白色表示二进制的“0”


QQ图片20161201102154.jpg QQ图片20161201102213.jpg

这是我使用的扫码模块

现在我们上一个简易的功能图:
未标题-1.jpg


扫码读取,我们已经通过二维码扫码模块已经实现

现在我们要做的就是确认模块的通讯模式:

1.以小段模式传输数据

2.发送的通讯协议栈 例如:eb 00 55 10 31 02 0028 6b   其中eb 00 55为数据头,10 31 02 00 28  分别为具体的有效数据,6b为前面所有字节的累加和。累加和可以用电脑系统自带的计算器来验证。打开电脑上的计算器,点击“查看”下拉的菜单,选“科学型”,然后选左边的“十六进制”,最后选右边的“字节”,然后把前面所有的字节相加,它们的和就是6b,没错吧。

3.作为测试,我们扫码后的数据为:eb 00 55 10 31 02 0028 6b ,我们在BBB上用一组函数来采集判断这组信号,其中eb 00 55 为固定开头 00 02 00 28 为代码接受位,6c为代接接收位的校验和。

4.这次会用到
GPIO0_14  : 接收数据
GPIO0_15 :接收完成反馈位 //  置1表示数据接收完成并正确,否则反馈0重新发送
GPIO3_15 :开始接收信号位 // 此处将端口配置为中断口

5.当二维码模块识别了二维码后,将数据传递到BBB上,因为考虑了便携式的低功耗问题,所以我们采用了中断模式,即设置了中断触发口GPIO3_15,当此端口收到数据的时候,表示发送数据即将开始,在这里我们把此端口设置为下降沿出发。

6.当触发了函数中断以后,我们需要接收数据,而传输的数据是按照位传递的,也可以是通讯协议。因为通讯协议在调试的过程中出现了问题,所以我们通过位传递的方式完成这个项目,在中断函数中对以 0 , 1 传递的数据进行接收,并保存在tru_value 中

7.每次中断函数都会触发一次判断函数,看数据是否接收到8个char 型的大小,当接收到了,在read 函数中进行判断,按照条目3中的代码指令进行校验

8.在确认了所有信息后如果成功,则准备内容发给app。

9.如果不成功则通过GPIO0_15 以 0 ,1 反馈给扫码模块,命令它重新发送数据

全局变量定义:

1.初始化struct

struct _2D_test{
        struct cdev t_cdev;
        int kbuf[KBUF_SIZE];
        size_t current_count;
        size_t data_count;
        wait_queue_head_t read_queue;
};
int tru_value = 0x00;
int rev_kbuf[KBUF_SIZE];
int array_gpio[] = {GPIO_TO_PIN(0, 14), GPIO_TO_PIN(0, 15), GPIO_TO_PIN(3, 15)};
int rev_count = 0;
模块初始化定义:
static const struct file_operations 2D_ops = {
                .owner = THIS_MODULE,
                .open = 2D_open,
                .write = 2D_write,
                .read = 2D_read,
                //.release = 2D_release,
                //.unlocked_ioctl = 2D_ioctl,
};
static struct miscdevice 2D_dev = {
                .name = "users_2D",
                .fops = &2D_ops,
};

加载初始化模块:
1.申请GPIO 端口
2.申请中断端口
3.使用misc 注册驱动
4.初始化等待队列头
static int __init 2D_test_init(void)
{
        int array_gpio[] = {GPIO_TO_PIN(0, 14), GPIO_TO_PIN(0, 15), GPIO_TO_PIN(3, 15)};
        misc_register(&2D_dev);
        if (gpio_request_array(array_gpio,sizeof(array_gpio) / sizeof(array_gpio[0])){
                printk("gpio is fail n");
        }
        else{
                gpio_direction_output(array_gpio[0],0);
                gpio_direction_output(array_gpio[1],0);
                printk("gpio is success n");
        }
        int ret = request_irq(GPIO_TO_PIN(3,15), irq_handler, IRQF_TRIGGER_FALLING,
        31 "data_get", NULL);
        if(ret){
                printk("request irq fai2D!n");
                return -1;
         }
        init_waitqueue_head(&mydev.read_queue);
        //gpio_set_value(GPIO_TO_PIN(1,22),1);
        return 0;
}

相对的释放函数:
static void __exit 2D_test_exit(void)
{
        gpio_free(GPIO_TO_PIN(0,14));
        gpio_free(GPIO_TO_PIN(0,15));
        free_irq(GPIO_TO_PIN(3,15));
        misc_deregister(&2D_dev);
        free_irq(GPIO_TO_PIN(3,15), NULL);
}

当二维码当有信息扫码过来,发送中断请求,通过BBB gpio 接收,并调用中断处理函数
irqreturn_t irq_handler(int irqno, void *dev_id)
{
        int rev_value = 0;
        int tru_value = 0x00;
        while (count <= BIT_COUNT)
        {
                rev_value = gpio_get_value();
                tru_value =|(rev_value <<7);
                tru_value >> 1
                count ++;
        }
        rev_kbuf[rev_count] = tru_value;
        rev_count ++ ;
        if (rev_count == 8)
        {
                rev_count
                dev->data_count ++;
                wake_up_interruptible(&dev->read_queue);
        }
}

从二维码模块接收的数据进行校验,并发送到app,在这里通过read 函数实施
ssize_t led_read(struct file *filp , const char __user *ubuf, size_t count, loff_t lof)
{
        struct _led_test *dev = filp->private_data;
        int record_count = 0;
        if (wait_event_interruptible(dev->read_queue,dev->current_count>0))
                return -ERESTARTSYS;
        if (record_count == 8)
        {
                record_count = 0;
                        if (dev->kbuf[0]==eb && dev->kbuf[1]==00 && dev->kbuf[2]==55)
                        {
                                if(dev->kbuf[3] + dev->kbuf[4] + dev->kbuf[5] + dev->kbuf[6] == dev->kbuf[7])
                                {
                                        if (copy_to_user(ubuf, dev->kbuf, count))
                                                                        return EFAULT;
                                        dev -> data_count --;
                                }
                                else
                                {
                                        printk("reciver_data add result is error n");
                                        gpio_direction_output(array_gpio[1],1);
                                        dev -> data_count --;
                                        return -1;
                                }
                        }
                        else
                        {
                                printk("reciver_data check is error n");
                                gpio_direction_output(array_gpio[1],1);
                                dev -> data_count --;
                                return -1;
                        }
                        dev->current_count -= count;
        }
        return 0;
}

到此一个小型的处理模块已经完成了小型的驱动程序,下面我们将驱动编译进内核

步骤如下:
第一;先将2D.c拷贝到在内核源代码中drivers/char/,vi /drivers/char/Kconfig
  添加 config 2D_DRIVER
bool"my 2D driver"。
回到源代码目录下make menuconfig,在文本菜单Device Drivers——>character devices就可以发现my 2D driver的选项。
  第二;在内核源代码中vi /drivers/char/Makefile,添加obj-$(CONFIG_HELLO_DRIVER) +=2D.o。这样就可以将hello.c驱动程序直接编译进内核

到此驱动已经装载到了BBB的内核中,这个项目因为时间比较赶,所有还有一些不完全的地方,稍后我会对代码进行优化。
在最后还是要感谢电子发烧友论坛给我们此次机会。非常感谢!!!

回帖(8)

低调de炫耀爱

2016-12-1 14:07:40
牛  点赞
举报

杨永胜

2016-12-2 18:05:41
楼主,如果把代码用代码的形式放在帖子里,就更美观了。
举报

mrplplplpl

2016-12-5 08:31:55
谢谢楼主的分享, 学习了
举报

陈鹏

2016-12-6 15:12:31
引用: iysheng 发表于 2016-12-2 10:05
楼主,如果把代码用代码的形式放在帖子里,就更美观了。

好的,下次注意
举报

更多回帖

发帖
×
20
完善资料,
赚取积分