TLV 格式及编解码

TLV 格式及编解码,第1张

几乎所有的需要在卡片和终端之间传送的数据都是TLV格式的.

我给你举个例子方便快速理吵隐如解:

TLV 是 tag , length 和 value 的缩写.一个基本的数据元就包括上面三个域. Tag 唯一标识该数据元, length 是 value 域的长度. Value就是数据本身了. 举升启个例子, 下面是一个tlv格式的AID(应用标识符)字节串” 9F0607A0000000031010 ”, 其中 9F06 是tag, 07 是长度, A0000000031010 就是AID本身的值了.

对于程序编写人员来说,如果有类似上面这样的一串TLV编码的字节串从卡片传过来, 怎么样从中提取我们想要的数据. 这就牵扯出TLV解码的问题了

TLV一种可变格式,TLV的意思就是:Type类型, Lenght长度,携困Value值;

Type和Length的长度固定,一般那是2、4个字节;

Value的长度有Length指定;

解析方法:

1.读取type 转换为ntohl、ntohs转换为主机字节序得到类型;指针偏移+2或4

2.读取lenght,转换为ntohl、ntohs转换为主机字节序得到长度;指针偏移+2或4

3.根据得到的长度读取value,指针偏移+Length;

TLV编码就是指先对Tag编码,再对Length编码,最后对Value编码。

有点长,慢慢看吧

Begin VB.Form frmMain

Caption = "Form1"

ClientHeight= 3090

ClientLeft = 60

ClientTop = 450

ClientWidth = 4680

LinkTopic = "Form1"

ScaleHeight = 3090

ScaleWidth = 4680

StartUpPosition = 3 '窗口缺省

Begin VB.CommandButton Command1

Caption = "Command1"

Height = 975

Left= 1320

TabIndex= 0

Top = 1080

Width = 2415

End

End

Attribute VB_Name = "frmMain"

Attribute VB_GlobalNameSpace = False

Attribute VB_Creatable = False

Attribute VB_PredeclaredId = True

Attribute VB_Exposed = False

Option Explicit

Private Const MEM_RELEASE = &H8000

Private Const LVM_FIRST = &H1000

Private Const LVM_GETHEADER = LVM_FIRST + 31

Private Const LVM_GETITEMCOUNT = (LVM_FIRST + 4)

Private Const LVM_GETITEM = (LVM_FIRST + 5)

Private Const LVM_GETSTRINGWIDTH = (LVM_FIRST + 17)

Private Const LVM_GETCOLUMN = (LVM_FIRST + 25)

Private Const LVM_GETITEMTEXT = (LVM_FIRST + 45)

Private Const HDM_FIRST = &H1200

Private Const HDM_GETITEMCOUNT = (HDM_FIRST + 0)

Private Const HDM_ORDERTOINDEX = (HDM_FIRST + 15)

Private Const PROCESS_QUERY_INFORMATION = 1024

Private Const PROCESS_VM_OPERATION = &H8

Private Const PROCESS_VM_READ = &H10

Private Const PROCESS_VM_WRITE = &H20

Private Const STANDARD_RIGHTS_REQUIRED = &HF0000

Private Const MAX_LVMSTRING As Long = 255

Private Const MEM_COMMIT = &H1000

Private Const PAGE_READWRITE = &H4

Private Const LVIF_TEXT As Long = &H1

Private Const LVM_GETCOLUMNCOUNT = &HF11B

Private Type LV_ITEMA

mask As Long

iItemAs Long

iSubItem As Long

stateAs Long

stateMaskAs Long

pszText As Long

cchTextMax As Long

iImage As Long

lParam As Long

iIndent As Long

End Type

Private Declare Function OpenProcess Lib "kernel32" (ByVal dwDesiredAccess As Long, ByVal bInheritHandle As Long, ByVal dwProcId As Long) As Long

Private Declare Function VirtualAllocEx Lib "kernel32" (ByVal hProcess As Long, ByVal lpAddress As Long, ByVal dwSize As Long, ByVal flAllocationType As Long, ByVal flProtect As Long) As Long

Private Declare Function VirtualFreeEx Lib "kernel32" (ByVal hProcess As Long, ByVal lpAddress As Long, ByVal dwSize As Long, ByVal dwFreeType As Long) As Long

Private Declare Function WriteProcessMemory Lib "kernel32" (ByVal hProcess As Long, ByVal lpBaseAddress As Any, ByRef lpBuffer As Any, ByVal nSize As Long, lpNumberOfBytesWritten As Long) As Long

Private Declare Function ReadProcessMemory Lib "kernel32" (ByVal hProcess As Long, ByVal lpBaseAddress As Any, ByRef lpBuffer As Any, ByVal nSize As Long, lpNumberOfBytesWritten As Long) As Long

Private Declare Function SendMessage Lib "user32" Alias "SendMessageA" (ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Long, ByRef lParam As Any) As Long

Private Declare Function CloseHandle Lib "kernel32" (ByVal hObject As Long) As Long

Private Declare Function GetCurrentProcessId Lib "kernel32" () As Long

Private Function GetListViewTextArray(ByVal hWindow As Long, ByVal ProcessID As Long) As String()

Dim result As Long

Dim myItem() As LV_ITEMA

Dim pHandle As Long

Dim pStrBufferMemoryAs Long

Dim pMyItemMemory As Long

Dim strBuffer() As Byte

Dim index As Long

Dim tmpString As String

Dim strLength As Long

Dim i As Integer, sum As Integer, j As Integer, hCount As Long

Dim strArr() As String, itemString As String

hCount = SendMessage(hWindow, LVM_GETHEADER, 0, 0)

If hCount >0 Then

hCount = SendMessage(hCount, HDM_GETITEMCOUNT, 0, 0)

Else

hCount = 0

End If

ReDim strBuffer(MAX_LVMSTRING)

pHandle = OpenProcess(PROCESS_VM_OPERATION Or PROCESS_VM_READ Or PROCESS_VM_WRITE, False, ProcessID)

ReDim myItem(hCount)

For j = 0 To SendMessage(hWindow, LVM_GETITEMCOUNT, 0, 0) - 1

For i = 0 To hCount

pStrBufferMemory = VirtualAllocEx(pHandle, 0, MAX_LVMSTRING, MEM_COMMIT, PAGE_READWRITE)

myItem(i).mask = LVIF_TEXT

myItem(i).iSubItem = i

myItem(i).pszText = pStrBufferMemory

myItem(i).cchTextMax = MAX_LVMSTRING

pMyItemMemory = VirtualAllocEx(pHandle, 0, Len(myItem(i)), MEM_COMMIT, PAGE_READWRITE)

result = WriteProcessMemory(pHandle, pMyItemMemory, myItem(i), Len(myItem(i)), 0)

result = SendMessage(hWindow, LVM_GETITEMTEXT, j, ByVal pMyItemMemory)

If result = 0 Then

result = VirtualFreeEx(pHandle, pStrBufferMemory, 0, MEM_RELEASE)

result = VirtualFreeEx(pHandle, pMyItemMemory, 0, MEM_RELEASE)

Exit For

End If

result = ReadProcessMemory(pHandle, pStrBufferMemory, strBuffer(0), MAX_LVMSTRING, 0)

result = ReadProcessMemory(pHandle, pMyItemMemory, myItem(i), Len(myItem(i)), 0)

tmpString = StrConv(strBuffer, vbUnicode)

tmpString = Left(tmpString, InStr(tmpString, vbNullChar) - 1)

itemString = itemString &tmpString &","

result = VirtualFreeEx(pHandle, pStrBufferMemory, 0, MEM_RELEASE)

result = VirtualFreeEx(pHandle, pMyItemMemory, 0, MEM_RELEASE)

Next

ReDim Preserve strArr(0 To sum)

strArr(j) = Left(itemString, Len(itemString) - 1)

sum = sum + 1

itemString = ""

Next

result = CloseHandle(pHandle)

GetListViewTextArray = strArr

End Function

Private Sub Command1_Click()

Dim itemStr() As String, i As Integer

itemStr = GetListViewTextArray(frmListView.lvTest.hwnd, GetCurrentProcessId)

For i = 0 To UBound(itemStr)

MsgBox itemStr(i)

Next

End Sub

Private Sub Form_Load()

frmListView.Show

End Sub

VERSION 5.00

Object = "{831FDD16-0C5C-11D2-A9FC-0000F8754DA1}#2.0#0""MSCOMCTL.OCX"

Begin VB.Form frmListView

Caption = "测试窗体"

ClientHeight= 5730

ClientLeft = 60

ClientTop = 450

ClientWidth = 7425

LinkTopic = "Form2"

ScaleHeight = 5730

ScaleWidth = 7425

StartUpPosition = 3 '窗口缺省

Begin MSComctlLib.ListView lvTest

Height = 4695

Left= 360

TabIndex= 0

Top = 480

Width = 6495

_ExtentX= 11456

_ExtentY= 8281

View= 3

LabelWrap = -1 'True

HideSelection = -1 'True

_Version= 393217

ForeColor = -2147483640

BackColor = -2147483643

BorderStyle = 1

Appearance = 1

NumItems= 0

End

End

Attribute VB_Name = "frmListView"

Attribute VB_GlobalNameSpace = False

Attribute VB_Creatable = False

Attribute VB_PredeclaredId = True

Attribute VB_Exposed = False

Private Sub Form_Load()

With lvTest

.ColumnHeaders.Add , , "序号"

.ColumnHeaders.Add , , "名称"

.ColumnHeaders.Add , , "性别"

.ColumnHeaders.Add , , "年龄"

End With

AddToListview "陈辉", "男", "24"

AddToListview "张三", "男", "22"

AddToListview "李四", "女", "20"

AddToListview "王二", "男", "31"

AddToListview "麻子", "女", "18"

End Sub

Private Sub AddToListview(ByVal sName As String, sSex As String, ByVal sAge As String)

Dim item As ListItem

Set item = lvTest.ListItems.Add(, , CStr(lvTest.ListItems.Count + 1))

item.SubItems(1) = sName

item.SubItems(2) = sSex

item.SubItems(3) = sAge

End Sub

//09/10/24

//lcd1602显示时间 日期 星期 温度

//通过按键校时:K10--小时,K11--分钟,K12--秒(归零),K13-星期,BR1--年,RB2--月,RB3--日。

//芯片要求:PIC16F877A

#include<pic.h> //包含单片机内部资源预定义

__CONFIG(0x1832)

//芯片配置字,看门狗关,上电延时开,掉电检测关,低压编程关,加密,4M晶体HS振迅侍荡

#define i_o RB4 //定义DS1302的数据口

#define sclk RB0 //定义DS1302的时钟口

#define rst RB5 //定义DS1302的复位口

#define rsRA1 //1602

#define rwRA2

#define e RA3

# define DQ RA0//定义18B20数据端口

unsigned char TLV=0//采集到的温度高8位

unsigned char THV=0//采集到的温度低8位

unsigned char bai

unsigned char shi //整数十位

unsigned char ge//整数个位

unsigned char shifen//十分位

float temp

void display()

//定义读取时间和日期存放表格

char table1[7]

//定义0-9的显示代码

const char table2[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90}

unsigned char rx_data,read_data,count,sec,min,hour,day,mon,week,year,time

//----------------------------------------------

//ds18b20部分

//------------------------------------------------

//延时含帆函数

void delay1(unsigned int x)

{

unsigned int i

for(i=xi>0i--)

}

//------------------------------------------------

//延时函数

void delay2(char x,char y)

{

char z

do{

z=y

do{}while(--z)

}while(--x)

}

//其指令时间为:7+(3*(Y-1)+7)*(X-1)谈昌雹如果再加上函数调用的call 指令、页面设定、传递参数花掉的7 个指令。

//则是:14+(3*(Y-1)+7)*(X-1)。

//***************************************

//初始化ds18b20

void ds18b20_init()

{

char presence=1

while(presence)

{

TRISA0=0 //主机拉至低电平

DQ=0

delay2(2,99) //延时503us

TRISA0=1 //释放总线等电阻拉高总线,并保持15~60us

delay2(2,8) //延时70us

if(DQ==1) presence=1//没有接收到应答信号,继续复位

else presence=0 //接收到应答信号

delay2(2,60) //延时430us

}

}

//*****************************************************

//写ds18b20

void ds18b20_write_byte(unsigned char code)

{

unsigned char i,k

for(i=8i>0i--)

{

k=code&0x01

TRISA0=0

DQ=0 //数据线拉低产生时间片

asm("nop")

asm("nop")

if(k) DQ=1//写1则拉高数据电平

delay1(3) //延时42us,ds18b20对数据线采样

asm("nop")

TRISA0=1 //采样结束,释放总线,拉高电平

code=code>>1

delay1(7) //延时82us

}

}

//****************************************************

//读ds18b20

unsigned char ds18b20_read_byte()

{

unsigned char i,k

for(i=8i>0i--)

{

k=k>>1

TRISA0=0

DQ=0//数据线拉低再拉高产生读时间片

asm("nop")

asm("nop")

TRISA0=1

asm("nop")

asm("nop")

if(DQ) k=k|0x80 //15us内要完成读位

delay1(6) //延时72us后释放总线

}

return (k)

}

//********************************************

//启动温度转换函数

void get_temp()

{

int i

signed int t

TRISA0=1

ds18b20_init()//复位等待从机应答

ds18b20_write_byte(0XCC) //忽略ROM匹配

ds18b20_write_byte(0X44) //发送温度转化命令

for(i=2i>0i--)

{

display() //调用多次显示函数,确保温度转换完成所需要的时间

}

ds18b20_init()//再次复位,等待从机应答

ds18b20_write_byte(0XCC) //忽略ROM匹配

ds18b20_write_byte(0XBE) //发送读温度命令

TLV=ds18b20_read_byte()//读出温度低8

THV=ds18b20_read_byte()//读出温度高8位

TRISA0=1 //释放总线

t=THV<<8

t=t|TLV

if(t<0)//负温度

{

temp=(~t+1)*0.0625*10+0.5 //负温度时,取反加1再乘以0.0625得实际温度,乘10+0.5显示小数点一位,且四舍五入

}

else

temp=t*0.0625*10+0.5 //正温度

if(t<0)

bai='-'//负温度时百位显示负号

else

bai=(const) temp/1000+0x30 //百位

shi=((const) temp%1000)/100 //十位

ge=((const) temp%1000)%100/10 //个位

shifen=((const) temp%1000)%100%10 //十分位

NOP()

}

//---------------------------------------------

//------------DS1303部分-----------------------

//---------------------------------------------

//延时程序

void delay() //延时程序

{

int i//定义整形变量

for(i=0x64i--)//延时

}

//写一个字节数据函数

void write_byte(unsigned char data)

{

int j //设置循环变量

for(j=0j<8j++) //连续写8bit

{

i_o=0 //先设置数据为0

sclk=0 //时钟信号拉低

if(data&0x01) //判断待发送的数据位是0或1

{

i_o=1 //待发送数据位是1

}

data=data>>1 //待发送的数据右移1位

sclk=1 //拉高时钟信号

}

sclk=0//写完一个字节,拉低时钟信号

}

//---------------------------------------------

//读一个字节函数

unsigned char read_byte()

{

int j //设置循环变量

TRISB4=1//设置数据口方向为输入

for(j=8j--) //连续读取8bit

{

sclk=0 //拉低时钟信号

rx_data=rx_data>>1//接收寄存器右移1位

if(i_o==1) rx_data=rx_data|0x80

sclk=1 //拉高时钟信号

}

TRISB4=0 //恢复数据口方向为输出

sclk=0 //拉低时钟信号

return(rx_data)//返回读取到的数据

}

//----------------------------------------------

//写DS1302

void write_ds1302(unsigned char addr,unsigned char code)

{

rst=0

sclk=0

rst=1

write_byte(addr)

write_byte(code)

sclk=0

rst=1

}

//-------------------------------------------

//读DS1302

void read_ds1302(unsigned char addr)

{

rst=0

sclk=0

rst=1

write_byte(addr)

read_data=read_byte()

//return read_data

}

//---------------------------------------------

//读取时间函数

void get_time()

{

int i//设置循环变量

rst=1//使能DS1302

write_byte(0xbf) //发送多字节读取命令

for(i=0i<7i++) //连续读取7个字节数据

{

table1[i]=read_byte() //调用读取1个字节数据的函数

}

rst=0 //复位DS1302

}

//DS1302初始化函数

void ds1302_init()

{

sclk=0 //拉低时钟信号

rst =0 //复位DS1302

rst=1//使能DS1302

write_ds1302(0x8e,0) //发控制命令

rst=0//复位

}

//---------------------------------------------

//设置时间函数

void set_time()

{

//定义待设置的时间: 秒、 分、 时、 日、月、星期、年、控制字

const char table[]={0x00,0x00,0x12,0x23,0x10,0x05,0x09,0x00}

int i//定义循环变量

rst=1//使能DS1302

write_byte(0xbe) //时钟多字节写命令

for(i=0i<8i++) //连续写8个字节数据

{

write_byte(table[i]) //调用写一个字节函数

}

rst=0//复位

}

//-------------------------------------------

//8位二进制数转换为十进制数

void two_to_ten(unsigned char i)

{

time=(table1[i]&0x0f)+(table1[i]>>4)*0x0a

}

//-------------------------------------------

//十进制数转换为BCD码

void ten_to_bcd(unsigned char i)

{

time=((i/0x0a)<<4)|(i%0x0a)

}

//------------------------------------------

//校时程序

void change_time()

{

if(RC0==0) //改变星期---k13

{

delay()

if(RC0==0)

{

if(count==0)

{

count=1

two_to_ten(5)

week=time

week++

if(week>=8)

{

week==1

write_ds1302(0x8A,1)

}

else

write_ds1302(0x8A,week)

}

}

}

else if(RC1==0) //秒归零--k12

{

delay()

if(RC1==0)

{

if(count==0)

{

count=1

write_ds1302(0x80,0)

}

}

}

else if(RC2==0)//改变分位--k11

{

delay()

if(RC2==0)

{

if(count==0)

{

count=1

two_to_ten(1)//BCD码转换成十进制数

min=time

min++

if(min>=60)

{

min=0

write_ds1302(0x82,min)

}

else

{

ten_to_bcd(min)//十进制数转换为BCD码存进DS1302

write_ds1302(0x82,time)

}

}

}

}

else if(RC3==0)//改变小时位--k10

{

delay()

if(RC3==0)

{

if(count==0)

{

count=1

two_to_ten(2)//BCD码转换成十进制数

hour=time

hour++

if(hour>=24)

{

hour=0

write_ds1302(0x84,hour)

}

else

{

ten_to_bcd(hour)

write_ds1302(0x84,time)

}

}

}

}

else if(RB2==0)

{

delay()

if(RB2==0)

{

if(count==0)

{

count=1

two_to_ten(4)//BCD码转换成十进制数

mon=time

mon++

if(mon>=13)

{

mon=1

write_ds1302(0x88,mon)

}

else

{

ten_to_bcd(mon)

write_ds1302(0x88,time)

}

}

}

}

else if(RB3==0)

{

delay()

if(RB3==0)

{

if(count==0)

{

count=1

two_to_ten(3)//BCD码转换成十进制数

day=time

day++

if((table1[6]%4==0)&&(table1[4]==2)&&(day>=30)) //润年2月

{

day=1

write_ds1302(0x86,day)

}

else if(((table1[6]%4)!=0)&&(table1[4]==2)&&(day>=29))//非润年的2月

{

day=1

write_ds1302(0x86,day)

}

else if(((table1[4]==1)||(table1[4]==3)||(table1[4]==5)||(table1[4]==7)||(table1[4]==8)||(table1[4]==0x10)||(table1[4]==0x12))&&(day>=32))

{

day=1

write_ds1302(0x86,day)

}

else if(((table1[4]==4)||(table1[4]==6)||(table1[4]==9)||(table1[4]==0x11))&&(day>=31))

{

day=1

write_ds1302(0x86,day)

}

else

{

ten_to_bcd(day)

write_ds1302(0x86,time)

}

}

}

}

else if(RB1==0)

{

delay()

if(RB1==0)

{

if(count==0)

{

count=1

two_to_ten(6)//BCD码转换成十进制数

year=time

year++

if(year>=16)

{

year=0x00

write_ds1302(0x8c,0)

}

else

{

ten_to_bcd(year)

write_ds1302(0x8c,time)

}

}

}

}

else

count=0

}

//****************************************

//**************lcd1602*******************

//****************************************

//延时程序

//void delay()

// {

// unsigned char i

// for(i=100i>0i--)

// }

//****************************************

//LCD写一个字节数据

void write_lcd(unsigned char code)

{

PORTD=code

rs=1

rw=0

e=0

delay()

e=1

}

//****************************************

//lcd写命令函数

void lcd_enable(unsigned char code)

{

PORTD=code

rs=0

rw=0

e=0

delay()

e=1

}

//*****************************************

//lcd显示设置

void lcd_init()

{

lcd_enable(0x01)//清除显示

lcd_enable(0x38)//设置16X2显示,5X7点阵

lcd_enable(0x0c)//开显示,不显示光标

lcd_enable(0x06)//光标左移

}

//-------------------------------------------

//显示函数

void display()

{

//PORTD=0X80 //小时

lcd_enable(0X80)

write_lcd((table1[2]>>4)+0x30)

// PORTD=0x81

lcd_enable(0x81)

write_lcd((table1[2]&0x0f)+0x30)

// PORTD=0X82

lcd_enable(0X82)

write_lcd(':')

// PORTD=0X83 //分

lcd_enable(0X83)

write_lcd((table1[1]>>4)+0x30)

// PORTD=0x84

lcd_enable(0x84)

write_lcd((table1[1]&0x0f)+0x30)

// PORTD=0X85

lcd_enable(0X85)

write_lcd(':')

// PORTD=0X86 //秒

lcd_enable(0X86)

write_lcd((table1[0]>>4)+0x30)

// PORTD=0x87

lcd_enable(0x87)

write_lcd((table1[0]&0x0f)+0x30)

// PORTD=0X89//温度的百位

lcd_enable(0X89)

write_lcd(bai)

// PORTD=0X8a//温度的十位

lcd_enable(0X8a)

write_lcd(shi+0x30)

// PORTD=0X8b //温度的个位

lcd_enable(0X8b)

write_lcd(ge+0x30)

// PORTD=0X8c

lcd_enable(0X8c)

write_lcd('.')

// PORTD=0X8d //温度的十分位

lcd_enable(0X8d)

write_lcd(shifen+0x30)

// PORTD=0X8e //显示'C'

lcd_enable(0X8e)

write_lcd('C')

//

// PORTD=0XC0//年

lcd_enable(0XC0)

write_lcd((table1[6]>>4)+0x30)

//PORTD=0XC1

lcd_enable(0XC1)

write_lcd((table1[6]&0x0f)+0x30)

// PORTD=0XC2

lcd_enable(0XC2)

write_lcd('-')

// PORTD=0XC3 //月

lcd_enable(0XC3)

write_lcd((table1[4]>>4)+0x30)

// PORTD=0xC4

lcd_enable(0xC4)

write_lcd((table1[4]&0x0f)+0x30)

// PORTD=0XC5

lcd_enable(0XC5)

write_lcd('-')

// PORTD=0XC6 //日

lcd_enable(0XC6)

write_lcd((table1[3]>>4)+0x30)

// PORTD=0xC7

lcd_enable(0xC7)

write_lcd((table1[3]&0x0f)+0x30)

// PORTD=0XCD //星期

lcd_enable(0XCD)

write_lcd((table1[5]&0x0f)+0x30)

}

//--------------------------------------------

//引脚定义函数

void port_init()

{

TRISA=0x00//设置A口全输出

TRISD=0X00//设置D口全输出

ADCON1=0X06 //设置A口为普通I/O口

TRISB=0X0E//

OPTION=0X00 //开启B口弱上拉

PORTA=0XFF

PORTD=0XFF//先熄灭所有显示

lcd_init()

TRISC=0XEF//RC3输出,其他为输入

PORTC=0XEF

count=0

}

//----------------------------------------------

//主函数

void main()

{

port_init()//调用引脚初始化函数

read_ds1302(0x81)//查看DS1302是否起振

if(read_data&0x80) //否,则初始化DS1302

{

ds1302_init() //调用DS1302初始化函数

set_time() //调用设置时间函数

}

while(1)

{

get_time()//调用取时间函数

change_time()

get_temp() //调用温度转换函数

display() //调用显示函数

}

}


欢迎分享,转载请注明来源:内存溢出

原文地址:https://www.54852.com/yw/12433745.html

(0)
打赏 微信扫一扫微信扫一扫 支付宝扫一扫支付宝扫一扫
上一篇 2023-05-23
下一篇2023-05-23

发表评论

登录后才能评论

评论列表(0条)

    保存