有谁做过串口通讯方面的东东,CRC校验

bys_home 2002-08-20 06:14:16
厂家提供的 代码如下
i:=$ffff; //1 CRC-16
for k:=0 to count-1 do
begin
ih:=i div 256; //2 data[k]:引导字节开始的数据
il:=i mod 256;
il:=il xor data[k];
i:=ih*256+il;

for j:=0 to 7 do
begin
l:=i;
i:=i div 2; //3
if (l mod 2)<>0 then //4
begin
i:=i xor $a001;
end;
end; //5
end; //6

i:=i mod 65536;
c[0]:=i mod 256;
c[1]:=i div 256;
//
用vb如何写
...全文
52 14 打赏 收藏 转发到动态 举报
写回复
用AI写文章
14 条回复
切换为时间正序
请发表友善的回复…
发表回复
Maxdell 2002-08-24
  • 打赏
  • 举报
回复

不知道下面的代码对你有没有帮助?

  Mscomm控件提供了功能完善的串口数据的发送和接收功能,Mscomm控件具有两种处理方式:1事件驱动方式:由Mscomm控件的OnComm事件捕获并处理通信错误及事件;2查询方式:通过检查CommEvent属性的值来判断事件和错误。

  Mscomm控件的通信功能实现,实际上是调用了API函数,而API函数是由Comm.drv解释并传给设备驱动程序执行的,对于VB程序开发者只需知道Mscomm控件的属性和事件的用法即可以实现串口的操作。


  以下是Mscomm控件的主要属性和方法:


  1)CommPort:设置或返回串行端口号,其取值范围为1~99,缺省为1。


  2)Setting设置或返回串行端口的波特率、奇偶校验位、数据位数、停止位。如:Mscomm.Setting="9600,N,8,1"。


  3)PortOpen:打开或关闭串行端口,格式为:Mscomm.PortOpen={TRUE|FALSE}。


  4)InBufferSize:设置或返回接收缓冲区的大小,缺省为1024字节。


  5)InBufferCount:返回接收缓冲区内的等待读取的字节个数,可通过设置该属性为0来清除接收缓冲区。


  6)RThreshold:该属性为一阀值,它确定当接收缓冲区内字节个数达到或超过该值后就产生代码为MSCOMM_EV_RECEIVE的OnComm事件。


  7)InputLen:设置或返回接收缓冲区内用Input读入的个数。若取0,则INPUT读取整个缓冲区的内容。


  8)Input:该属性表示从接收缓冲区移走一串字符。


  9)OutBufferSize:设置或返回发送缓冲区,缺省为512字节。


  10)OutBufferCounter:返回发送缓冲区内等待发送的字符数,可用来清空缓冲区。


  11)Output:向发送缓冲区传送一字符串。


  12)EOFEnable:若置TRUE,则当输入中出现EOF,就停止输入并产生OnComm事件。


  如果在通信过程中发生错误或事件,就会引发OnComm事件并且改变属性值,由CommEvent属性代码反映错误类型,在通信程序的设计中可根据该属性值来执行不同的操作,以下是部分属性常数值及其含义:


  1)ComEvSend:其值为1,发送缓冲区的内容少于SThreshold指定的值。


  2)ComEvReceive:其值为2,接收缓冲区内字符数达到RThreshold值,该事件在缓冲区中数据被移走前将持续产生。


  3)ComEventFrame:其值为1004,硬件检测到帧错误。


  4)ComEventRxOver:其值为1008,接收缓冲区溢出。


  5)ComEventTxFull:其值为1010,发送缓冲区溢出。


  6)ComEventRxParity:其值为1009,奇偶校验。


  7)ComEvEOF:其值为7,接收数据中出现文件结束(ASCII码为26)字符。


程序样例


  采用Mscomm控件实现串口通信时,首先添加一Mscomm控件到窗体中,该控件一般不在通用工具窗口中,而是需通过菜单项"工程(P)→部件(O)"进入选择窗口,在控件tab页中选取MicrosoftCommControl5.0,此时工具窗口中出现Mscomm图标,即可被使用。

  以下是事件驱动方式的接收程序的主要部分:


PrivateSubgetdatafromserial_Click()

  CommonDialog1.InitDir="c:\temp"

  CommonDialog1.ShowSave

  mainfrm.MSComm1.CommPort=1

  hfile=FreeFile

  '打开存储接收数据的文件

  Open CommonDialog1.filename For Output As #hfile

  '设接收缓冲区的大小,可按量确定

  mainfrm.MSComm1.InBufferSize=4096

  If Not mainfrm.MSComm1.PortOpen Then'打开串口

  mainfrm.MSComm1.PortOpen=True

  End If

  If Err Then

  MsgBox"Communcationportcannotbeopened!!"

  '清接收缓冲区

  mainfrm.MSComm1.InBufferCount=0

  '设一次读入的长度,可根据数据格式设置

  mainfrm.MSComm1.InputLen=77

  '设置接收事件触发的阀值

  mainfrm.MSComm1.RThreshold=77

  counter=Timer+10

  Do

   If Timer>counter Then

    mainfrm.Label1.Caption="正在通信......"

    mainfrm.Label1.Refresh

    counter=Timer+10

   End If

   DoEvents

  Loop

End Sub


  以下为事件处理子程序,flag为一静态变量记录读取次数,以便改变接收数据的长度,可根据实际需要添加其它处理内容:


Private Sub MSComm1_OnComm()

  Select Case MSComm1.CommEvent

    Case comEvReceive

      If flag>246 Then

        MSComm1.InputLen=0:MSComm1.RThreshold=32

      End If

      buffer=MSComm1.Input

      temp=buffer

      Print #hfile,temp

      counter=Timer+10

      Do While Timer>counter

        DoEvents

      Loop

      flag=flag+1

    Case comEvEOF

      EVMsg$="检测到文件结尾!!!"

    Case comFrame

      ERMsg$="帧出错!!!"

    Case comRxParity

      ERMsg$="奇偶错!!!"

  End Select

  If Len(EVMsg$) Then

    Text1.Text="Status:"&EVMsg$

  ElseIf Len(ERMsg$) Then

    Text1.Text="Status:"&ERMsg$

    Beep

    Ret=MsgBox(ERMsg$,1,"ClickCanceltoquit,OKtoignore.")

    MSComm1.PortOpen=False

  End If

End Sub
itaolu 2002-08-24
  • 打赏
  • 举报
回复
我写了一篇文章是关于CRC-32的,有很详细的原理和实现方法,你不妨去看看?

http://laoluoc.yeah.net
daviddivad 2002-08-21
  • 打赏
  • 举报
回复
厂家代码改为VB如下:

i = &HFFFF
For k = 0 To Count - 1
ih = 1 \ 256
il = i Mod 256
il = il Xor Data(k)
i = ih * 256 + il
For j = 0 To 7
l = i
i = i \ 2
If i Mod 2 = 0 Then
i = i Xor &HA001
End If
Next j
Next k
i = i Mod 65536
c(0) = i Mod 256
c(1) = i \ 256
wwg007 2002-08-21
  • 打赏
  • 举报
回复
高深啊 。。。。
daviddivad 2002-08-21
  • 打赏
  • 举报
回复
这样的算法太慢,不如用查表法,源码如下:

'CRC算法
'"" 表示错误
Public Function fun_CrcCheck(ByVal str_Source As String) As String
'CRC校验(生成多项式为:G(X)=X^16+X^12+X^5+1)
'结果以16进制字符串表示
On Error GoTo doError
Dim int_I As Integer
Dim int_Len As Integer
Dim str_TempSource As String
Dim str_TempReturn As String * 4
Dim int_A0 As Integer
Dim int_A1 As Integer
Dim int_A0_1 As Integer
Dim int_A0_2 As Integer
Dim int_A1_1 As Integer
Dim int_A1_2 As Integer
Dim int_H As Integer
Dim int_L As Integer
Dim int_A2 As Integer
Dim int_A3 As Integer

int_Len = Len(str_Source)
For int_I = 1 To int_Len
str_TempSource = str_TempSource & Right$("00" & Hex(Asc(Mid$(str_Source, int_I, 1))), 2)
Next int_I
str_TempSource = str_TempSource & "0000"
int_Len = Len(str_TempSource)
Do While int_Len > 4
int_A0 = Val("&H" & Mid$(str_TempSource, 1, 1))
int_A1 = Val("&H" & Mid$(str_TempSource, 2, 1))

int_A0 = int_A0 + 1
int_A0_1 = Choose(int_A0, &H0, &H12, &H24, &H36, &H48, &H5A, &H6C, &H7E, &H91, &H83, &HB5, &HA7, &HD9, &HCB, &HFD, &HEF)
int_A0_2 = Choose(int_A0, &H0, &H31, &H62, &H53, &HC4, &HF5, &HA6, &H97, &H88, &HB9, &HEA, &HDB, &H4C, &H7D, &H2E, &H1F)

int_A1 = int_A1 + 1
int_A1_1 = Choose(int_A1, &H0, &H10, &H20, &H30, &H40, &H50, &H60, &H70, &H81, &H91, &HA1, &HB1, &HC1, &HD1, &HE1, &HF1)
int_A1_2 = Choose(int_A1, &H0, &H21, &H42, &H63, &H84, &HA5, &HC6, &HE7, &H8, &H29, &H4A, &H6B, &H8C, &HAD, &HCE, &HEF)

int_H = int_A0_1 Xor int_A1_1
int_L = int_A0_2 Xor int_A1_2

int_A2 = Val("&H" & Mid$(str_TempSource, 3, 2))
int_A3 = Val("&H" & Mid$(str_TempSource, 5, 2))

str_TempReturn = Right$("00" & Hex(int_H Xor int_A2), 2) & Right$("00" & Hex(int_L Xor int_A3), 2)
str_TempSource = str_TempReturn & Mid$(str_TempSource, 7)
int_Len = Len(str_TempSource)

Loop
fun_CrcCheck = str_TempSource
Exit Function
doError:
fun_CrcCheck = ""
End Function

例子:
Private Sub Command1_Click()
Debug.Print fun_CrcCheck("daviddivad")
End Sub
hfycl 2002-08-20
  • 打赏
  • 举报
回复
我有c的
rushing 2002-08-20
  • 打赏
  • 举报
回复
i=0xffff
count是前面程序提供的
bys_home 2002-08-20
  • 打赏
  • 举报
回复
i:=$ffff; 为何意
count   哪来的
rushing 2002-08-20
  • 打赏
  • 举报
回复
你按照我说的直接替换就行了。
for语句你自己会写吧?
Pipi0714 2002-08-20
  • 打赏
  • 举报
回复
这是Pascal语言:
Pascal vb的差别
:= =
; 一行语句的结束
if (true) then
begin
end;
相当于vb的if (true) then
endif
bys_home 2002-08-20
  • 打赏
  • 举报
回复
如何用vb写成函数//100分相送
rushing 2002-08-20
  • 打赏
  • 举报
回复
xor是异或,mod是取模。
rushing 2002-08-20
  • 打赏
  • 举报
回复
div是除号,用/代替。
rushing 2002-08-20
  • 打赏
  • 举报
回复
这是pascal语言。
其中 ;=是赋值,与=一样。
begin, end 是开始和结束标志相当于end sub 或end function
方括号改成圆括号,分号去掉。

7,789

社区成员

发帖
与我相关
我的任务
社区描述
VB 基础类
社区管理员
  • VB基础类社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧