概述
一. 曼彻斯特码理论分析:
曼彻斯特码编码的ID卡每次输出64bit 数据/8个字节,其载波编码为曼彻斯特码.
其时序图如下:
曼彻斯特码调制方式下,EM4100卡片每传送一位数据的时间是64个振荡周期。125KHZ载波时,卡片传送一bit数据理论频率为125KHz / 64 = 1.953125KHz。那么得到一个周期为:1 000 000us / 1.953125KHz = 512us。
也就是说:曼彻斯特码一个完整的数据跳变为一个周期(512us)。
但是特别需要注意的是:存在空跳则半个跳变为半个周期(256us)。
那么如何得到一个bit的数据呢?
如果捕获到一个电平变化,这个电平距离上次检测到电平变化时间为512us,则该位按以下读取:
低电平-bit = 1,
高电平-bit = 0;
如果捕获到一个电平变化,这个电平距离上次检测到电平变化时间256us,则此次不作判断,再次捕获到一个边沿时再判断如下:
上次bit = 1 此次bit = 1,
上次bit = 0,此次bit = 0.
此处有一个特别注意的地方,如果上次读取到256us,不管这次读取间隔是256us还是512us,都应该读取上一次的电平,并且重新检测跳包。
二.设备树配置:
配置设备树节点,用于内核驱动程序找到对应能检波的IO口。在anyka v300 平台如下:
编辑:anycloud_ak39ev330_common.dtsi
添加节点:在 gpiokeys: gpiokeys {
compatible = "anyka,ak39ev330-gpiokeys";
status = "disable";
};
附近添加以下节点信息:
rfid_control: rfid_control {
compatible = "leo_rfid_control";
status = "disable";
};
编辑:C500_SQ38_AK3918EV330_GC2063_MIPI_V1.0.0.dts:
在"$gpio" 节点内部添加
rfid_pins:rfid_pins{
anyka,pins = <0>;
anyka,function = <0>;
anyka,pull = <0x00000001>;
};
然后退出$gpio节点,使能“rfid_control”节点,如下:
&rfid_control{
gpios = <&gpio 0 1>;
pinctrl-names ="default";
pinctrl-0 = <&rfid_pins>;
status = "okay";
};
好了,完成了设备树信息的编写,
第二部:接下来开始写驱动内核程序。
整个代码如下:
#include <linux/module.h>
#include <linux/poll.h>
#include <linux/fs.h>
#include <linux/errno.h>
#include <linux/miscdevice.h>
#include <linux/kernel.h>
#include <linux/major.h>
#include <linux/mutex.h>
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
#include <linux/stat.h>
#include <linux/init.h>
#include <linux/device.h>
#include <linux/tty.h>
#include <linux/kmod.h>
#include <linux/gfp.h>
#include <linux/gpio/consumer.h>
#include <linux/platform_device.h>
#include <linux/of_gpio.h>
#include <linux/of_irq.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/slab.h>
#include <linux/fcntl.h>
#include <linux/timer.h>
#include <linux/workqueue.h>
#include <asm/current.h>
#include <linux/kthread.h>
#include <linux/delay.h>
#define diff_us(t1,t2) ((u64)t1.tv_sec - (u64)t2.tv_sec) * 1000000 + ((u64)t1.tv_usec - (u64)t2.tv_usec);
#define rfid_code_bit_value(data,index) ((data[(index)/8] >> (7 - (index)%8))&0x01)
/* 主设备号 */
static int major = 0;
/* 创建设备类的结构体 */
static struct class* rfid_class;
/* 记录设备树信息的结构体*/
static int rfid_gpio_index;
static struct task_struct *rfid_kthread;
static char rfid_data_code[16] = {0};
static int rfid_data_count = 0;
static char rfid_code_number[4] = {0};
static char rfid_code_number_ready = 0;
static DEFINE_MUTEX(rfid_code_mutex);
static ssize_t rfid_read(struct file* file,char __user*buf,size_t size,loff_t* offset){
int len = 0;
if(size < 4){
return 0;
}
len = sizeof(rfid_code_number);
//printk("read rfid value n");
mutex_lock(&rfid_code_mutex);
if(rfid_code_number_ready == 0){
mutex_unlock(&rfid_code_mutex);
return 0;
}
copy_to_user(buf, rfid_code_number , len);
rfid_code_number_ready = 0;
mutex_unlock(&rfid_code_mutex);
return len;
}
/* 创建设备方法 */
static struct file_operations rfid_control_fops = {
.owner = THIS_MODULE,
.read = rfid_read,
};
static int rfid_code_leave_wait(int* level,int min,int middle,int max,struct timeval* pre_tv){
u64 us = 0;
struct timeval tv;
int cur_level = gpio_get_value(rfid_gpio_index) ;
while(gpio_get_value(rfid_gpio_index) == cur_level){
do_gettimeofday(&tv);
us = diff_us(tv,(*pre_tv));
if(us > max){
return -1;
}
}
do_gettimeofday(&tv);
us = diff_us(tv,(*pre_tv));
*level = cur_level?0:1;
if(us < min){
return -1;
}
else if((us > min)&&(us < middle)){
return 0;
}
return 1;
}
static char rfid_code_jump_flg = 0;
static int rfid_code_read_proc(void){
int i = 0;
int reslut = 0;
int level = 0;
struct timeval tv;
unsigned char value = 0;
memset(rfid_data_code,0,sizeof(rfid_data_code));
rfid_data_count = 0;
rfid_code_jump_flg = 0;
do_gettimeofday(&tv);
while(1){
reslut = rfid_code_leave_wait(&level,125,375,625,&tv);
do_gettimeofday(&tv);
if((reslut == 0)&&(rfid_code_jump_flg == 0)){
rfid_code_jump_flg = 1;
}
else if((reslut == 1)||((reslut == 0)&&(rfid_code_jump_flg == 1))){
if(rfid_code_jump_flg == 1){
value = ((rfid_data_code[(rfid_data_count - 1) / 8] >> (7 - (rfid_data_count - 1) % 8)) & 0x01) ? 1 : 0;
}
else{
value = level?0:1;
}
rfid_code_jump_flg = 0;
rfid_data_code[rfid_data_count / 8] |= (value << (7 - rfid_data_count % 8));
rfid_data_count++;
if(rfid_data_count >= 128){
return 1;
}
}
else if(reslut < 0){
return -1;
}
}
return 0;
}
static int rfid_code_data_check(void){
int index = 0,i = 0,j = 0,n = 0;
int value = 0;
for(index = 0; index < 64 ; index++){
value = 0;
for(i = 0 ; i < 9 ; i++){
value <<= 1;
value |= rfid_code_bit_value(rfid_data_code,index + i);
//printk("%d",rfid_code_bit_value(rfid_data_code,index + i));
}
if(value == 0x1FF){
index += 9;
break;
}
}
if(index == 64){
printk("check rfid data failed (%s,%d)n",__func__,__LINE__);
return -1;
}
for(i = index; i < (index + 45) ; i+=5){
value = 0;
for( j = 0 ;j < 4 ; j++){
value += rfid_code_bit_value(rfid_data_code,i + j);
}
if((value %2) != rfid_code_bit_value(rfid_data_code,i + j)){
printk("check rfid data failed (%s,%d)n",__func__,__LINE__);
return -1;
}
}
for( i = index; i < (index + 4) ; i++){
value = 0;
for( j = 0 ; j < 50 ; j+= 5){
value += rfid_code_bit_value(rfid_data_code,i + j);
}
if((value %2) != rfid_code_bit_value(rfid_data_code,i + j)){
printk("check rfid data failed (%s,%d)n",__func__,__LINE__);
return -1;
}
}
if(rfid_code_bit_value(rfid_data_code,index + 54) != 0){
printk("stop failed n");
return -1;
}
n = 0;
mutex_lock(&rfid_code_mutex);
rfid_code_number_ready = 0;
mutex_unlock(&rfid_code_mutex);
memset(rfid_code_number,0,sizeof(rfid_code_number));
for(i = index + 10 ; i < (index + 50) ; i+=10){
value = 0;
for( j = 0 ; j < 9; j++){
if(j == 4){
continue;
}
value <<= 1;
value |= rfid_code_bit_value(rfid_data_code,i+j);
}
rfid_code_number[n++] = value;
//printk("%02x ",value);
}
//printk("n");
mutex_lock(&rfid_code_mutex);
rfid_code_number_ready = 1;
mutex_unlock(&rfid_code_mutex);
return 1;
}
static int k_rfid_task(void*data){
int pre_level = gpio_get_value(rfid_gpio_index);
int cur_level = pre_level;
char det_start_flag = 0;
printk("leo:kernel rfid card task success! n");
while(1){
if(kthread_should_stop()){
break;
}
if(det_start_flag == 0){
cur_level = gpio_get_value(rfid_gpio_index);
if(cur_level == 0){
det_start_flag = 1;
pre_level = cur_level;
}
else
{
msleep(100);
}
}
else{
if(rfid_code_read_proc() == 1){
//printk("check data n");
rfid_code_data_check();
}
gpio_set_value(rfid_gpio_index,1);
pre_level = gpio_get_value(rfid_gpio_index);
det_start_flag = 0;
msleep(10);
}
}
return 0;
}
static int rfid_probe(struct platform_device*pdev){
int irq;
struct device_node *np = pdev->dev.of_node;
printk("leo:rfid probe success n");
rfid_gpio_index = of_get_named_gpio(np, "gpios", 0);
if(rfid_gpio_index < 0){
printk("rfid gpio setting failedn");
}
else{
printk("rfid setting gpio%dn",rfid_gpio_index);
}
device_create(rfid_class,NULL,MKDEV(major,0),NULL,"rfid_control");
gpio_direction_output(rfid_gpio_index,1);
msleep(100);
gpio_direction_input(rfid_gpio_index);
mutex_init(&rfid_code_mutex);
rfid_kthread = kthread_create(k_rfid_task,NULL,"rfid_kthread");
if(IS_ERR(rfid_kthread)){
printk("create rfid_kthread faieldn");
return 0;
}
wake_up_process(rfid_kthread);
return 0;
}
static int rfid_remove(struct platform_device*pdev)
{
int irq;
printk("leo:rfid driver removen");
kthread_stop(rfid_kthread);
device_destroy(rfid_class,MKDEV(major,0));
return 0;
}
static const struct of_device_id rfid_board_control[]={
{.compatible = "leo_rfid_control"},
{}
};
static struct platform_driver rfid_platform_drv = {
.probe = rfid_probe,
.remove = rfid_remove,
.driver = {
.name = "rfid_control",
.of_match_table = rfid_board_control,
},
};
static int __init rfid_drv_init(void){
printk("leo:rfid drv init startn");
//注册主字符设备号
major = register_chrdev(0,"rfid_control",&rfid_control_fops);
//创建设备类
rfid_class = class_create(THIS_MODULE,"rfid_class");
if(IS_ERR(rfid_class)){
printk("rfid class create failedn");
unregister_chrdev(major,"rfid_control");
return PTR_ERR(rfid_class);
}
return platform_driver_register(&rfid_platform_drv);
}
static void __exit rfid_drv_exit(void){
platform_driver_unregister(&rfid_platform_drv);
class_destroy(rfid_class);
unregister_chrdev(major,"rfid_control");
}
/*
* ko创建
*/
module_init(rfid_drv_init);
module_exit(rfid_drv_exit);
MODULE_LICENSE("GPL");
生成rfid.ko之后,上次insom rfid.ko,完成内核模块的安装。
第三步:应用层的编写:
整体代码如下:
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#define RFID_DEVICE_PATH "/dev/rfid_control"
int main(int argc,char** argv){
if(access(RFID_DEVICE_PATH,F_OK) != 0){
printf("%s not exitn",RFID_DEVICE_PATH);
return 0;
}
int fd = open(RFID_DEVICE_PATH,O_RDONLY);
if(fd < 0 ){
printf("open %s failed n",RFID_DEVICE_PATH);
return 0;
}
unsigned char data[4] = {0};
while(1){
if(read(fd,data,sizeof(data)) == 4){
printf("%02x%02x%02x%02xn",data[0],data[1],data[2],data[3]);
}
usleep(1000*10);
}
return 0;
}
最后
以上就是甜美大白为你收集整理的125KHZ RFID 曼彻斯特码在内核域解码的全部内容,希望文章能够帮你解决125KHZ RFID 曼彻斯特码在内核域解码所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复