直接控制GPIO引脚读取磁卡数据

来源:互联网 发布:mac自带五笔输入法 编辑:程序博客网 时间:2024/04/30 12:08

1、硬件GPIO引脚使用情况:

GPIO[495557]对应磁卡器的RCP[3]RDD[3]CLSNPWN

2、磁卡各引脚的使用情况:

CLS 刷卡开始为下降沿,磁卡走行中保持低电频,走向结束上升沿,无磁卡走行时保持高电频

RCP记录采样频率,每半个周期的幅度为100千欧 14毫秒;620千欧 60毫秒,前半周期高电,后半周期为低频

RDD数据采样端,当采样引脚RCP为高电频(前半周期)时,该段开始采样

CLS 为共用引脚,RCPRDD在磁卡不同的情况下分别使用1-3个不同的引脚

3、实现读取磁卡数据的思路:

  思路一

ACLS下降沿时发生中断,置bit计数器为0,以便记录最终得到数据量(以bit为单位);上升沿时,返回逻辑中断向量,唤醒IST

  BRCP上升沿时发生中断,使用时钟中断(2-3微妙发生一次),RDD端进行数据采样;RCP下降沿时关闭时钟中断,根据RDD数据采样计算最终数据,将数据保存至共享的内存空间,以便磁卡驱动来读取数据

  思路二:

A   CLS下降沿时发生中断,置位计数器为0,以便记录最终得到数据量(以bit为单位);上升沿时结束中

BRCP上升沿时发生中断,使用while语句以轮询方式,采样RDD段的数据;RCP下降沿时,根据RDD数据采样计算最终数据,将数据保存至共享的内存空间,以便磁卡驱动来读取数据

4、实现步骤:

  1)、CLS端中断机制的建立,

  2)、RCP端中断机制的建立

  3)、时钟中断机制的建立(暂时忽略,数据采样工作在RCP上升沿发生中断时进行一次)

5、具体实现方法:

   比较觉得:思路二轮询采样RDD数据线的方式不合适,其效率比较低,并且,对于采样的时机比较难把握,因此思路一成为首选方案。按照思路一,已经实现磁卡的读写功能。

  1)、中断机制的建立:

a. BSP中定义中断的逻辑值。如:wince60/PlatForm/XXX/src/inc/bsp_cfg.h中添加定义

#define  SYSINTR_MYINTR  (SYSINTR_FIRMWARW+23)

b. BSPOALintr.c文件中,添加具体的物理中断的定义以及中断处理代码。

根据硬件连接情况及资料得知,需要将相关中断是作为IRQ_GPIOXX_2的子中断进行处理。在XXX/SoC/PXA310/OAL/INTR/intr.c中,IRQ_GPIOXX_2的相关处理会调用到XXX/ src /oal/oallib/intr.c中的中断处理函数BSPIntrActiveIrq()(该函数会返回对应得物理中断号)、BSPIntrDisableIrq()、BSPIntrDoneIrq()、BSPIntrEnableIrq()、BSPIntrInit()、BSPIntrRequestIrqs()等。因此,在XXX/ src /oal/oallib/intr.c中添加相应得物理中断的定义和处理代码,如:

#define  IRQ_GPIO55_MCARD_CLS_R  (IRQ_MONAHANS_MAX + 17)

需要注意的是,定义物理中断号的同时,不要忘记修改IRQ_XXX_GPIO_MAX等的定义,至于具体实现操作的代码,就是根据需要来修改了。

c. 修改OEMInterruptHandler()函数对应逻辑中断和物理中断

在这里添加的这个中断GPIO55_R的物理中断号,就是用于在读卡结束时(GPIO55号引脚回有上升沿的跳变),对应逻辑中断SYSINTR_MYINTR,唤起相应的中断程序。对于逻辑中断和物理中断的对应,是由XXX/SoC/PXA310/OAL/INTR/intr.c中的OEMInterruptHandler()函数来完成的,它会调用BSPIntrActiveIrq(),然后,根据返回的物理中断值来修改sysIntr值。

[小结]:如果一切顺利,那么,到此有关于由IRQ_GPIOXX_2的子中断引起的中断机制就建立完毕了,重新编译生成新的nk.bin就可以了。该中断与非IRQ_GPIOXX_2的中断相比可能会麻烦一些。对于非IRQ_GPIOXX_2的中断,直接在XXX/SoC/PXA310/OAL/INTR/intr.c文件中修改代码即可。

  2)、用户层对内核数据的使用:

a.对于数据的读取,是在RCP引脚的发生跳变的时候进行的,因此,代码是写在XXX/ src /oal/oallib/intr.c中的,在RCP[n]引脚发生中断时,读数据、并将数据保存下来,以便读卡结束时驱动层可以读到数据。具体读数据的函数代码如下:(一共有三个磁道需要分别读写数据、进行保存,每个磁道的物理特性不同)

void ReadDataFromRDD(UINT32 XLLP_GPIO_BIT_RDD)

{

switch(XLLP_GPIO_BIT_RDD){

        case XLLP_GPIO_BIT_CIF_DD5:                                       

              if (g_bitIndex1 == MAX_BIT_NUMBER)// MAX_BIT_NUMBER=8

              {

                            g_bitIndex1 = 0;

                            g_byteIndex1 += 1;

              }

 

              if (g_byteIndex1 > MAX_BYTE_NUMBER)// MAX_BYTE_NUMBER=1024

              {

                             return;

              }

 

              if (g_pGPIORegs->gplr1 & XLLP_GPIO_BIT_RDD)//读数据寄存器的值

              {

                            g_chBuf1[g_byteIndex1] &= ~(1<<g_bitIndex1);                                                                  //三个磁道使用的均是负逻辑

              }

              else

              {                                                                                  

                            g_chBuf1[g_byteIndex1] |= (1 << g_bitIndex1);

              }            

              g_bitIndex1++;

              break;

 

              //data type is tract2

              case XLLP_GPIO_BIT_CIF_DD3:                                 

                            ……

                            break;

 

              //data type is tract3

              case XLLP_GPIO_BIT_CIF_DD1:

                            ……

                            break;

 

              default:

                            break;

        }

        return;

}

b.使用KernelIoControl ()来完成数据由OAL层向驱动层的传输。

(有些东西具体什么作用不是很清楚,都是是仿照现有BSP中其他使用了KernelIoControl的代码写的)

首先,在XXX/ SRC/INC/ioctl_cfg.h文件中,宏定义一个资源号,该资源号是作为CTL_CODE的第二个参数使用的;宏定义KernelIoControl 中需要的IOControlID。如:

#define MAGNETIC_CARD_DATA_TRANS 4003

#define  IOCTL_HAL_MAGNETIC_CARD_TRANS

CTL_CODE(FILE_DEVICE_HAL, (MAGNETIC_CARD_DATA_TRANS), METHOD_BUFFERED, FILE_ANY_ACCESS)

其次,在XXX/ SRC/INC/ioctl_tab.h中,添加映射,如:

{ IOCTL_HAL_MAGNETIC_CARD_TRANS,     0,OALIoCtlHalTransMagneticCardData},

最后,在XXX/ SRC/INC/ioctl.c中添加OALIoCtlHalTransMagneticCardData ()函数的具体代码

c. 使用DeviceIoControl(对应驱动层的XXX_IOControl)或者XXX_Read函数,把数据传递给用户层。

 

 

通过以上的操作,直接使用GPIO控制读取磁卡信息的功能已经实现,并且在用户层的测试程序中得到了正确的数据。我也是第一次接触中断机制、第一次从内核中读取数据,可能理解的还不是很透彻。如果有问题,还请大家指出,呵呵,不过,请不要讲一些过于极端的话(偶会被打击的失去信心的),谢谢^_^

 

原创粉丝点击