扫码读取,我们已经通过二维码扫码模块已经实现
现在我们要做的就是确认模块的通讯模式:
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的内核中,这个项目因为时间比较赶,所有还有一些不完全的地方,稍后我会对代码进行优化。
在最后还是要感谢电子发烧友论坛给我们此次机会。非常感谢!!!