基於STM32F103的Modbus通訊(32做從機)

最近做了個實驗,用STM32做從機接收主機發送過來的數據包(也是基於mobus協議),而後從機將一些數據發送給主機。

首先呢還是介紹下modbus協議。其實modbus協議你不需要了解太多。既然是要使用,那麼你只需要明白一點,modbus協議就是在你要發送的數據的基礎上,在數據前面加上一個幀頭,數據後面加一個幀尾。嗯,是不是還是有點迷?舉個例子吧。

所以主機會發過來一幀數據:01 03 00 6B 00 03 17 74(這個01是我假設主機的地址,這個域名的作用就是用來判斷是否是主機發送過來的數據。因爲通信過程可能因爲各種原因而導致主機發送過來的數據異常,故而我們從機接收到數據之後會先對數據進行分析主機發過來的數據是否正常,正常從機再發送數據過去,異常則不對這幀數據進行響應即從機不發數據。17 74是根據01 03 00 6B 00 03計算出來的CRC校驗值。)

當從機接收到這串數據,並且判斷數據正常則發送一幀數據到主機:02 03 06 02 2B 00 00 00 64 11 8A(同樣的02是我假設的這個從機的地址,需注意的是咱們假設自己的從機地址不要與主機的地址相同。)在這幀數據中幀頭就是02 03 06,11 8A是根據02 03 06 02 2B 00 00 00 64計算出來的CRC 校驗值也是幀尾。

(提供一個在線計算CRC校驗值的網站:http://www.ip33.com/crc.html

那麼問題來了。。。程序中我們怎麼去計算CRC校驗值呢???這個嘛 ,下方我會貼上整個實驗的例程,其中CRC.c中h函數unsigned int GetCRC16(unsigned char *ptr,  unsigned char len)我們只需要調用這個函數就可以算出CRC校驗值了。有興趣的也可以去額外瞭解下CRC校驗具體是怎麼實現的。

 

整個實驗例程如下:

main.c:

#include "stm32f10x.h"
#include "bsp_485.h"
#include "bsp_led.h"
#include "crc16.h"

/*描述:硬件:RS485接口		協議:Modbus RTU
 *功能:採用DMA方式發送數據,中斷方式接收數據。
 *注:  接收到指令之後,判斷是否是相應指令而進行DMA數據發送。
 */

/*DMA:開啓DMA,DMA發送完一幀數據後產生髮送完成中斷,
 *		 在DMA發送完成中斷中,開啓USART接收中斷(字節)
 *		 在USART接收中斷中保存接收到的數據。
 *注: 本程序額外開啓了USART空閒中斷,在空閒中斷中將	
 *		 USART接收中斷中接收到的數據發送至串口調試助手顯示
 *		 並開啓DMA請求
 */
 
extern uint8_t u3Temp;
extern uint16_t uart3_p;
extern uint16_t ReceivedUsart3Flag,tempU3,uart3_RXbuff[];
extern uint8_t SendU3Buff[SENDU3BUFF_SIZE];

uint16_t len,iU3;
uint8_t u2_Temp;
char *pbuf;

void SendUsart3Buff(void);
void SendU3DatatoDebug(void);
void load_U3_SendBuff(void);

int main(void)
{	
	load_U3_SendBuff();
	
	LED_GPIO_Config();
  USART3_Config();	

	while(1)
	{			
	}
}

/*Description:調試通信程序專用,用於將接收到的數據再發送到串口調試助手顯示*/
void SendU3DatatoDebug()
{
	
			for(uart3_p= 1; uart3_p <= u3Temp; uart3_p++)
			{
				Usart_SendByte(USART3,uart3_RXbuff[uart3_p]);				
			}				
			uart3_p = 1;
			RS485_RX_EN();
			ReceivedUsart3Flag = 0;
}
/*將USART3需要發送的數據存放在SendU3Buff[]中*/
void load_U3_SendBuff()
{
	uint16_t CRCtemp;

	SendU3Buff[0]=0x01;//ID
	SendU3Buff[1]=0x03;//功能碼
	SendU3Buff[2]=0x0C;//內容數據字節數

	/*填充將要發送的數據(兩個字節爲一個寄存器的值)*/	
	SendU3Buff[3]=0x00;	//數據1(slave地址0,網站上地址40001)
	SendU3Buff[4]=0x64;
	SendU3Buff[5]=0x00;//數據2(slave地址1,網站上地址40002)
	SendU3Buff[6]=0x96;
	SendU3Buff[7]=0x00;//數據3
	SendU3Buff[8]=0xC8;
	SendU3Buff[9]=0x00;	//4	
	SendU3Buff[10]=0xFA;
	SendU3Buff[11]=0x01;//5頁面未添加該數據
	SendU3Buff[12]=0x2B;
	SendU3Buff[13]=0x01;//6
	SendU3Buff[14]=0x5E;

	CRCtemp = GetCRC16(SendU3Buff, 15);
	/*CRC校驗值*/
	SendU3Buff[15] = CRCtemp;//存放CRCl
	SendU3Buff[16] = (CRCtemp >> 8);	//保存CRCh//SendBuff[i] = ((CRCtemp<<8)|(CRCtemp>>8));	//保存CRCh

}


	
 

485.c:

#include "bsp_485.h"

uint8_t SendU3Buff[SENDU3BUFF_SIZE];

static void NVIC_USART3_Configuration(void)
{
  NVIC_InitTypeDef NVIC_InitStructure;
  
  /* 嵌套向量中斷控制器組選擇 */
  NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
  
  /* 配置USART爲中斷源 */
  NVIC_InitStructure.NVIC_IRQChannel = USART3_IRQn;
  /* 搶斷優先級*/
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
  /* 子優先級 */
  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
  /* 使能中斷 */
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  /* 初始化配置NVIC */
  NVIC_Init(&NVIC_InitStructure);
}

static void NVIC_DMA1_2_Configuration(void)
{
  NVIC_InitTypeDef NVIC_InitStructure;
  
  /* 嵌套向量中斷控制器組選擇 */
  NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
  
  /* 配置USART爲中斷源 */
  NVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel2_IRQn;
  /* 搶斷優先級*/
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
  /* 子優先級 */
  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
  /* 使能中斷 */
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  /* 初始化配置NVIC */
  NVIC_Init(&NVIC_InitStructure);
}	

//static void NVIC_DMA1_2_Configuration(void)
//{
//  NVIC_InitTypeDef NVIC_InitStructure;     /* Configure one bit for preemption priority */
//  NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);     
//  NVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel2_IRQn;     
//  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
//  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
//  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;          
//  NVIC_Init(&NVIC_InitStructure);
//}	
 /**
  * U3:TX:PB10	RX:PB11	TXRXEN:PD3
  * U5:TX:PC12	RX:PD1 	TXRXEN:PD0
  * 
  */
void USART3_Config(void)
{
	GPIO_InitTypeDef GPIO_InitStructure;
	USART_InitTypeDef USART_InitStructure;

	// 打開串口GPIO的時鐘
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);//TX、RX是時鐘
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOD, ENABLE);//EN時鐘
	// 打開串口外設的時鐘
	DEBUG_USART_APBxClkCmd(RCC_APB1Periph_USART3, ENABLE);//USART時鐘

	// 將USART Tx的GPIO配置爲推輓複用模式
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOB, &GPIO_InitStructure);

  // 將USART Rx的GPIO配置爲浮空輸入模式
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
	GPIO_Init(GPIOB, &GPIO_InitStructure);
	
	/* 設置485收發控制管腳爲推輓輸出Out_PP */
	GPIO_InitStructure.GPIO_Pin = RS485_RE_PIN;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOD , &GPIO_InitStructure);
	
	// 配置串口的工作參數
	// 配置波特率
	USART_InitStructure.USART_BaudRate = 115200;
	// 配置 針數據字長
	USART_InitStructure.USART_WordLength = USART_WordLength_8b;
	// 配置停止位
	USART_InitStructure.USART_StopBits = USART_StopBits_1;
	// 配置校驗位
	USART_InitStructure.USART_Parity = USART_Parity_No ;
	// 配置硬件流控制
	USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
	// 配置工作模式,收發一起
	USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
	// 完成串口的初始化配置
	USART_Init(USART3, &USART_InitStructure);
	
	// 串口中斷優先級配置
	NVIC_USART3_Configuration();
	
	// 使能串口接收中斷
	USART_ITConfig(USART3, USART_IT_RXNE, ENABLE);
	// 使能串口空閒中斷(用於檢測一幀數據接收完畢)
	USART_ITConfig(USART3, USART_IT_IDLE, ENABLE);	
	// 使能串口
	USART_Cmd(USART3, ENABLE);		
  
	/*控制 485 芯片進入接收模式*/
	RS485_RX_EN();//
}



void USART3_DMA_Config(void)
{
		DMA_InitTypeDef DMA_InitStructure;
	
		// 開啓DMA時鐘
		RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);
		/* 復位初始化 DMA 數據流 */
		DMA_DeInit(DMA1_Channel2);
		// 設置DMA外設地址:串口數據寄存器地址*/
    DMA_InitStructure.DMA_PeripheralBaseAddr = USART_DR_ADDRESS;
		// 內存地址(要傳輸的變量的指針)
		DMA_InitStructure.DMA_MemoryBaseAddr = (u32)SendU3Buff;
		// 方向:從內存到外設	
		DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;
		// 傳輸大小	
		DMA_InitStructure.DMA_BufferSize = SENDU3BUFF_SIZE;
		// 外設地址不增	    
		DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
		// 內存地址自增
		DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
		// 外設數據單位	
		DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
		// 內存數據單位
		DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;	 
		// DMA模式,一次或者循環模式
		DMA_InitStructure.DMA_Mode = DMA_Mode_Normal ;
		//DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;	
		// 優先級:中	
		DMA_InitStructure.DMA_Priority = DMA_Priority_Medium; 
		// 禁止內存到內存的傳輸
		DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
		// 配置DMA通道		   
		DMA_Init(USART_TX_DMA_CHANNEL, &DMA_InitStructure);	

		NVIC_DMA1_2_Configuration();

		//開啓DMA通道的TC中斷:傳輸完成中斷
    DMA_ITConfig(DMA1_Channel2,DMA_IT_TC,ENABLE);
		// 使能DMA
		DMA_Cmd (DMA1_Channel2,ENABLE);
}

/*****************  發送一個字符 **********************/
void Usart_SendByte( USART_TypeDef * pUSARTx, uint8_t ch)
{
	/* 發送一個字節數據到USART */
	USART_SendData(pUSARTx,ch);
		
	/* 等待發送數據寄存器爲空 */
	while (USART_GetFlagStatus(pUSARTx, USART_FLAG_TXE) == RESET);	
}

/*****************  發送字符串 **********************/
void Usart_SendString( USART_TypeDef * pUSARTx, char *str)
{
	unsigned int k=0;
  do 
  {
      Usart_SendByte( pUSARTx, *(str + k) );
      k++;
  } while(*(str + k)!='\0');
  
  /* 等待發送完成 */
  while(USART_GetFlagStatus(pUSARTx,USART_FLAG_TC)==RESET)
  {}
}

/*****************  發送一個16位數 **********************/
void Usart_SendHalfWord( USART_TypeDef * pUSARTx, uint16_t ch)
{
	uint8_t temp_h, temp_l;
	
	/* 取出高八位 */
	temp_h = (ch&0XFF00)>>8;
	/* 取出低八位 */
	temp_l = ch&0XFF;
	
	/* 發送高八位 */
	USART_SendData(pUSARTx,temp_h);	
	while (USART_GetFlagStatus(pUSARTx, USART_FLAG_TXE) == RESET);
	
	/* 發送低八位 */
	USART_SendData(pUSARTx,temp_l);	
	while (USART_GetFlagStatus(pUSARTx, USART_FLAG_TXE) == RESET);	
}


/*
Desc:接收中斷時,將接收到的所有數據用數組保存。
*/

//中斷緩存串口數據
#define UART_BUFF_SIZE      1024
uint16_t uart3_p = 1;
uint16_t     uart3_RXbuff[UART_BUFF_SIZE]; 
uint8_t u3Temp;
uint8_t tempU3;
uint8_t ReceivedUsart3Flag = 0;
uint16_t clr;
uint16_t a=0x00;


void bspU3_RS485_IRQHandler(void)
{
			if (USART_GetITStatus( USART3, USART_IT_RXNE) != RESET) //收到一個字節的數據
			{//保存接收到的數據
				uart3_RXbuff[uart3_p] = USART_ReceiveData(USART3);
				uart3_p++;		
			}	
			if (USART_GetITStatus(USART3, USART_IT_IDLE) != RESET) //收到一幀的數據
			{//將接收到的數據發送到串口調試助手上以便觀察數據是否正確
					u3Temp = uart3_p-1;
					clr = USART3->SR;				
					clr = USART3->DR;
					ReceivedUsart3Flag = 1;
					RS485_TX_EN() ;
//					for(uart3_p= 1; uart3_p <= u3Temp; uart3_p++)//調試通信程序專用,用於將接收到的數據再發送到串口調試助手顯示
//					{
//						Usart_SendByte(USART3,uart3_RXbuff[uart3_p]);				
//					}				
					uart3_p = 1;
				
//				 LED1_OFF;
//				 LED2_OFF;
//				 LED3_OFF;
//				 LED4_OFF;
			 
			 	 LED1_ON;
				 LED2_ON;
				 LED3_ON;
				 LED4_ON;	
				if(uart3_RXbuff[1]==0x01&&uart3_RXbuff[2]==0x03&&uart3_RXbuff[3]==0x00&&uart3_RXbuff[4]==0x00&&
							uart3_RXbuff[5]==0x00&&uart3_RXbuff[6]==0x06&&uart3_RXbuff[7]==0xC5&&uart3_RXbuff[8]==0xC8)
//							uart3_RXbuff[9]==0x00&&uart3_RXbuff[10]==0x01&&uart3_RXbuff[11]==0x03&&uart3_RXbuff[12]==0x9C&&
//							uart3_RXbuff[13]==0x41&&uart3_RXbuff[14]==0x00&&uart3_RXbuff[15]==0x02&&uart3_RXbuff[16]==0x17&&
							
				{								
				/* DMA發送使能 */
				USART3_DMA_Config();
				RS485_TX_EN() ;
				USART_DMACmd(USART3, USART_DMAReq_Tx, ENABLE);//這個放在最後	
				}
				
			}			
}

void bspU3_RS485_DMA_IRQHandler()
{
		if(DMA_GetITStatus(DMA1_IT_TC2))
		 {
			 	 //清TC標誌
				DMA_ClearITPendingBit(DMA1_IT_GL2); //清除全部中斷標誌 //DMA_ClearFLAG(DMA1_FLAG_TC2); //清除全部中斷標誌(這種寫法也可以)
        while(USART_GetFlagStatus(USART3, USART_FLAG_TC) == RESET);    //等待USART1發送完成標誌TC置1
        USART_ClearFlag(USART3, USART_FLAG_TC);     //清除發送完成標誌			 
		}   
   //關閉DMA通道
			DMA_Cmd(DMA1_Channel2, DISABLE);    
			RS485_RX_EN();
}


CRC16.c:

#include "crc16.h" 
unsigned int GetCRC16(unsigned char *ptr,  unsigned char len)
{ 
    uint16_t index;
    uint8_t crcl = 0xFF;  //高CRC字節
    uint8_t crch = 0xFF;  //低CRC字節
    uint8_t  TabH[] = {  //CRC高位字節值表
        0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,  
        0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,  
        0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,  
        0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,  
        0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,  
        0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,  
        0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,  
        0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,  
        0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,  
        0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40,  
        0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,  
        0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,  
        0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,  
        0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40,  
        0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,  
        0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,  
        0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,  
        0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,  
        0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,  
        0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,  
        0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,  
        0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40,  
        0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,  
        0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,  
        0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,  
        0x80, 0x41, 0x00, 0xC1, 0x81, 0x40  
    } ;  
    u8 TabL[] = {  //CRC低位字節值表
        0x00, 0xC0, 0xC1, 0x01, 0xC3, 0x03, 0x02, 0xC2, 0xC6, 0x06,  
        0x07, 0xC7, 0x05, 0xC5, 0xC4, 0x04, 0xCC, 0x0C, 0x0D, 0xCD,  
        0x0F, 0xCF, 0xCE, 0x0E, 0x0A, 0xCA, 0xCB, 0x0B, 0xC9, 0x09,  
        0x08, 0xC8, 0xD8, 0x18, 0x19, 0xD9, 0x1B, 0xDB, 0xDA, 0x1A,  
        0x1E, 0xDE, 0xDF, 0x1F, 0xDD, 0x1D, 0x1C, 0xDC, 0x14, 0xD4,  
        0xD5, 0x15, 0xD7, 0x17, 0x16, 0xD6, 0xD2, 0x12, 0x13, 0xD3,  
        0x11, 0xD1, 0xD0, 0x10, 0xF0, 0x30, 0x31, 0xF1, 0x33, 0xF3,  
        0xF2, 0x32, 0x36, 0xF6, 0xF7, 0x37, 0xF5, 0x35, 0x34, 0xF4,  
        0x3C, 0xFC, 0xFD, 0x3D, 0xFF, 0x3F, 0x3E, 0xFE, 0xFA, 0x3A,  
        0x3B, 0xFB, 0x39, 0xF9, 0xF8, 0x38, 0x28, 0xE8, 0xE9, 0x29,  
        0xEB, 0x2B, 0x2A, 0xEA, 0xEE, 0x2E, 0x2F, 0xEF, 0x2D, 0xED,  
        0xEC, 0x2C, 0xE4, 0x24, 0x25, 0xE5, 0x27, 0xE7, 0xE6, 0x26,  
        0x22, 0xE2, 0xE3, 0x23, 0xE1, 0x21, 0x20, 0xE0, 0xA0, 0x60,  
        0x61, 0xA1, 0x63, 0xA3, 0xA2, 0x62, 0x66, 0xA6, 0xA7, 0x67,  
        0xA5, 0x65, 0x64, 0xA4, 0x6C, 0xAC, 0xAD, 0x6D, 0xAF, 0x6F,  
        0x6E, 0xAE, 0xAA, 0x6A, 0x6B, 0xAB, 0x69, 0xA9, 0xA8, 0x68,  
        0x78, 0xB8, 0xB9, 0x79, 0xBB, 0x7B, 0x7A, 0xBA, 0xBE, 0x7E,  
        0x7F, 0xBF, 0x7D, 0xBD, 0xBC, 0x7C, 0xB4, 0x74, 0x75, 0xB5,  
        0x77, 0xB7, 0xB6, 0x76, 0x72, 0xB2, 0xB3, 0x73, 0xB1, 0x71,  
        0x70, 0xB0, 0x50, 0x90, 0x91, 0x51, 0x93, 0x53, 0x52, 0x92,  
        0x96, 0x56, 0x57, 0x97, 0x55, 0x95, 0x94, 0x54, 0x9C, 0x5C,  
        0x5D, 0x9D, 0x5F, 0x9F, 0x9E, 0x5E, 0x5A, 0x9A, 0x9B, 0x5B,  
        0x99, 0x59, 0x58, 0x98, 0x88, 0x48, 0x49, 0x89, 0x4B, 0x8B,  
        0x8A, 0x4A, 0x4E, 0x8E, 0x8F, 0x4F, 0x8D, 0x4D, 0x4C, 0x8C,  
        0x44, 0x84, 0x85, 0x45, 0x87, 0x47, 0x46, 0x86, 0x82, 0x42,  
        0x43, 0x83, 0x41, 0x81, 0x80, 0x40  
    } ;
 
    while (len--)  //計算指定長度的CRC
    {
        index = crcl ^ *ptr++;
        crcl = crch ^ TabH[index];
        crch = TabL[index];
    }
    
    return ((crch<<8) | crcl);  
} 

嗯。。。我把工程打包了一份。。。鏈接如下。。。

https://download.csdn.net/download/qq_34471646/11240985

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章