STM32F103使用USART串口中断收取带CRC校验的数据,上位机发送数据CRC和串口中断接收数据计算的CRC判断一致则转发接收的数据

crc.h

#ifndef __CRC_H
#define __CRC_H


#include "stm32f10x.h"



uint16_t GetCRC16(uint8_t *ptr,  uint8_t len);









#endif

crc.c

#include "crc.h"

#include <stdio.h>




uint16_t GetCRC16(uint8_t *ptr,  uint8_t len)
{
    uint16_t index;
    uint8_t crch = 0xFF;  //高CRC字节
    uint8_t crcl = 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,  
    };  
    uint8_t 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 = crch ^ *ptr++;
        crch = crcl ^ TabH[index];
        crcl = TabL[index];
    }
   
    return ((crcl<<8) | crch); //低字节先发 
}                           

 

usart.h

#ifndef __USART_H
#define __USART_H


#include "stm32f10x.h"
#include "stdio.h"

#define USART1PERIPH 0x40013804

void USART_GPIO_Init(void);
int fputc(int ch, FILE *f);





















#endif

usart.c

#include "usart.h"

extern uint8_t DATA_RECEIVE_BUFF[136];

int fputc(int ch, FILE *f)
{
    while(USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET);
    USART_SendData(USART1, (uint8_t)ch);
    
    USART_ClearFlag(USART1, USART_FLAG_TC);

    return ch;

}

void USART_GPIO_Init(void)
{
    GPIO_InitTypeDef   GPIO_InitStruct;
    USART_InitTypeDef    USART_InitStruct;
    
//    DMA_InitTypeDef   DMA_InitStruct;
    NVIC_InitTypeDef    NVIC_InitStruct;
    
//    RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);
//    DMA_InitStruct.DMA_BufferSize = 9; //猜测是要缓存的字节数
//    DMA_InitStruct.DMA_DIR = DMA_DIR_PeripheralSRC;//用 变量 接收数据
//    DMA_InitStruct.DMA_M2M = DMA_M2M_Disable; //非存储器到存储器
//    DMA_InitStruct.DMA_MemoryBaseAddr = (uint32_t)&DATA_RECEIVE_BUFF;//数据需要存储到哪个变量里
//    DMA_InitStruct.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;//数据字节数大小
//    DMA_InitStruct.DMA_MemoryInc = DMA_MemoryInc_Enable;
//    DMA_InitStruct.DMA_Mode = DMA_Mode_Circular;
//    DMA_InitStruct.DMA_PeripheralBaseAddr = USART1PERIPH;
//    DMA_InitStruct.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
//    DMA_InitStruct.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
//    DMA_InitStruct.DMA_Priority = DMA_Priority_Low;
//
//    DMA_Init(DMA1_Channel5, &DMA_InitStruct);
//    DMA_Cmd(DMA1_Channel5, ENABLE); 

    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
    NVIC_InitStruct.NVIC_IRQChannel = USART1_IRQn;
    NVIC_InitStruct.NVIC_IRQChannelCmd =  ENABLE;
    NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 2;
    NVIC_InitStruct.NVIC_IRQChannelSubPriority = 2;
    NVIC_Init(&NVIC_InitStruct);


    RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1 | RCC_APB2Periph_GPIOA, ENABLE);

    GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF_PP;//GPIO_Mode_Out_PP
    GPIO_InitStruct.GPIO_Pin = GPIO_Pin_9;
    GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;

    GPIO_Init(GPIOA, &GPIO_InitStruct);

    GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IN_FLOATING;
    GPIO_InitStruct.GPIO_Pin = GPIO_Pin_10;

    GPIO_Init(GPIOA, &GPIO_InitStruct);


    USART_InitStruct.USART_BaudRate = 9600;
    USART_InitStruct.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
    USART_InitStruct.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
    USART_InitStruct.USART_Parity = USART_Parity_No;
    USART_InitStruct.USART_StopBits = USART_StopBits_1;
    USART_InitStruct.USART_WordLength = USART_WordLength_8b;



    USART_Init(USART1, &USART_InitStruct);

    USART_Cmd(USART1, ENABLE);


//    USART_DMACmd(USART1, USART_DMAReq_Rx, ENABLE);
//    DMA_ITConfig(DMA1_Channel5, DMA_IT_TC, ENABLE);
    USART_ITConfig(USART1, USART_IT_RXNE | USART_IT_IDLE, ENABLE);


}
#include "stm32f10x_it.h"

extern uint8_t DATA_FLAG;
extern uint8_t DATA_NUM;
extern uint8_t DATA_RECEIVE_BUFF[136];

void USART1_IRQHandler(void)
{
    DATA_FLAG = 1;
    if(USART_GetITStatus(USART1, USART_IT_RXNE))
    {
        
        DATA_RECEIVE_BUFF[DATA_NUM] = (uint8_t)USART_ReceiveData(USART1);
        DATA_NUM ++;
        USART_ClearITPendingBit(USART1, USART_IT_RXNE);
    }
//    if(USART_GetITStatus(USART1, USART_IT_IDLE) == SET)
//    {
//            
//    }
}

main.c

//将串口工具发出的数据通过串口助手添加CRC后发送出去
//MCU的串口中断收到该数据后校验收到的数据的CRC,并和发送附加的CRC比较是否一致,一致的话会打印发送的数据

#include "stm32f10x.h"
#include "usart.h"
#include "crc.h"

//#define DATA_LENGTH 136
uint8_t DATA_RECEIVE_BUFF[136] = {0};
uint8_t DATA_FLAG = 0;
uint8_t DATA_NUM = 0;
uint8_t i = 0;
uint16_t crcval = 0;
int main(void)
{
    
    USART_GPIO_Init();
    printf("hello, world");
    printf("----------------\r\n");
    while(1)
    {
    
            
               if(DATA_FLAG&&USART_GetFlagStatus(USART1, USART_FLAG_IDLE))
               {
                    crcval = GetCRC16(DATA_RECEIVE_BUFF, DATA_NUM-2);//CRC低字节先发,高字节后发
                    printf("crcval = %X, datanum = %d\r\n",crcval,DATA_NUM); //打印计算出来的CRC
                    if(((uint8_t)(crcval&0x00FF) == DATA_RECEIVE_BUFF[DATA_NUM-2]) &&((uint8_t)((crcval>>8)&0x00FF) == DATA_RECEIVE_BUFF[DATA_NUM-1]))//判断发送数据里的CRC和收到计算出来的CRC是否一致
                    {
                        for(i = 0; i < DATA_NUM; i ++)
                        {
                            printf("%02X ",DATA_RECEIVE_BUFF[i]);
                        }
                    }

                    DATA_FLAG = 0;
                    DATA_NUM = 0;
                }
                
                 
                
            
            
        
        
    }
}

 

posted @ 2025-12-20 13:39  了解2号  阅读(4)  评论(0)    收藏  举报