51单片机usart通信程序(有CRC校验)

合集下载

单片机UART通信实现

单片机UART通信实现

单片机UART通信实现在单片机系统中,UART(通用异步收发器)通信是一种常见的串口通信方式。

通过UART通信,可以实现单片机与外部设备之间的数据传输。

本篇文章将介绍如何使用单片机实现UART通信,并提供相应的代码示例。

一、UART通信原理UART通信是一种串行通信方式,其中数据按照位的形式依次传输。

UART接口包括发送端和接收端,发送端将要传输的数据通过串行方式发送出去,接收端将接收到的数据按位恢复为原始数据。

通信的核心是波特率,即数据传输的速度。

发送端和接收端必须以相同的波特率进行通信,以确保数据的正确传输。

二、单片机UART通信的硬件连接实现单片机UART通信的关键是正确连接相应的硬件。

典型的单片机UART通信硬件连接如下:发送端:- 单片机的TX(发送)引脚连接到外部设备的RX(接收)引脚- 单片机的GND引脚连接到外部设备的GND引脚接收端:- 单片机的RX(接收)引脚连接到外部设备的TX(发送)引脚- 单片机的GND引脚连接到外部设备的GND引脚三、单片机UART通信的软件实现在软件方面,需要编写相应的代码来配置单片机的UART通信模块。

以下是一个示例代码,用于实现基本的UART通信功能。

```c#include <reg51.h>#define BAUDRATE 9600 // 波特率设置为9600bpsvoid uart_init(){TMOD = 0x20; // 设置定时器1为8位自动重装模式TH1 = -(256 - (11059200 / 12 / 32) / BAUDRATE); // 设置波特率TL1 = TH1; // 初始化定时器1的初值TR1 = 1; // 启动定时器1SCON = 0x50; // 标识为8位UART模式EA = 1; // 允许全局中断ES = 1; // 允许串口中断}void uart_send(unsigned char dat)SBUF = dat; // 将数据写入发送寄存器 while (!TI); // 等待发送完毕TI = 0; // 清除发送完成标志}unsigned char uart_receive(){while (!RI); // 等待接收完毕RI = 0; // 清除接收标志return SBUF; // 返回接收到的数据}void main(){unsigned char data;uart_init(); // 初始化UART通信模块 while (1)data = uart_receive(); // 接收数据uart_send(data); // 发送接收到的数据}}```以上代码是基于8051系列单片机的实现示例,具体的单片机型号和编程语言可能有所不同,但基本原理是相同的。

51单片机的串口通信程序(C语言)

51单片机的串口通信程序(C语言)

51单片机的串口通信程序(C语言) 51单片机的串口通信程序(C语言)在嵌入式系统中,串口通信是一种常见的数据传输方式,也是单片机与外部设备进行通信的重要手段之一。

本文将介绍使用C语言编写51单片机的串口通信程序。

1. 硬件准备在开始编写串口通信程序之前,需要准备好相应的硬件设备。

首先,我们需要一块51单片机开发板,内置了串口通信功能。

另外,我们还需要连接一个与单片机通信的外部设备,例如计算机或其他单片机。

2. 引入头文件在C语言中,我们需要引入相应的头文件来使用串口通信相关的函数。

在51单片机中,我们需要引入reg51.h头文件,以便使用单片机的寄存器操作相关函数。

同时,我们还需要引入头文件来定义串口通信的相关寄存器。

3. 配置串口参数在使用串口通信之前,我们需要配置串口的参数,例如波特率、数据位、停止位等。

这些参数的配置需要根据实际需要进行调整。

在51单片机中,我们可以通过写入相应的寄存器来配置串口参数。

4. 初始化串口在配置完串口参数之后,我们需要初始化串口,以便开始进行数据的发送和接收。

初始化串口的过程包括打开串口、设置中断等。

5. 数据发送在串口通信中,数据的发送通常分为两种方式:阻塞发送和非阻塞发送。

阻塞发送是指程序在发送完数据之后才会继续执行下面的代码,而非阻塞发送是指程序在发送数据的同时可以继续执行其他代码。

6. 数据接收数据的接收与数据的发送类似,同样有阻塞接收和非阻塞接收两种方式。

在接收数据时,需要不断地检测是否有数据到达,并及时进行处理。

7. 中断处理在串口通信中,中断是一种常见的处理方式。

通过使用中断,可以及时地响应串口数据的到达或者发送完成等事件,提高程序的处理效率。

8. 串口通信实例下面是一个简单的串口通信实例,用于在51单片机与计算机之间进行数据的传输。

```c#include <reg51.h>#include <stdio.h>#define BAUDRATE 9600#define FOSC 11059200void UART_init(){TMOD = 0x20; // 设置定时器1为模式2SCON = 0x50; // 设置串口为模式1,允许接收TH1 = 256 - FOSC / 12 / 32 / BAUDRATE; // 计算波特率定时器重载值TR1 = 1; // 启动定时器1EA = 1; // 允许中断ES = 1; // 允许串口中断}void UART_send_byte(unsigned char byte){SBUF = byte;while (!TI); // 等待发送完成TI = 0; // 清除发送完成标志位}unsigned char UART_receive_byte(){while (!RI); // 等待接收完成RI = 0; // 清除接收完成标志位return SBUF;}void UART_send_string(char *s){while (*s){UART_send_byte(*s);s++;}}void main(){UART_init();UART_send_string("Hello, World!"); while (1){unsigned char data = UART_receive_byte();// 对接收到的数据进行处理}}```总结:通过以上步骤,我们可以编写出简单的51单片机串口通信程序。

51单片机串口通信实例

51单片机串口通信实例

51单片机串口通信实例一、原理简介51 单片机内部有一个全双工串行接口。

什么叫全双工串口呢?一般来说,只能接受或只能发送的称为单工串行;既可接收又可发送,但不能同时进行的称为半双工;能同时接收和发送的串行口称为全双工串行口。

串行通信是指数据一位一位地按顺序传送的通信方式,其突出优点是只需一根传输线,可大大降低硬件成本,适合远距离通信。

其缺点是传输速度较低。

与之前一样,首先我们来了解单片机串口相关的寄存器。

SBUF 寄存器:它是两个在物理上独立的接收、发送缓冲器,可同时发送、接收数据,可通过指令对SBUF 的读写来区别是对接收缓冲器的操作还是对发送缓冲器的操作。

从而控制外部两条独立的收发信号线RXD(P3.0)、TXD(P3.1),同时发送、接收数据,实现全双工。

串行口控制寄存器SCON(见表1) 。

表1 SCON寄存器表中各位(从左至右为从高位到低位)含义如下。

SM0 和SM1 :串行口工作方式控制位,其定义如表2 所示。

经验分享:学习单片机重要的是实践,所以开发板是很重要,给大家推荐些淘宝上信誉良好并且软硬件及小零件等、售前售后服务良好的皇冠级金钻店铺给大家,在硬件购买上少走弯路。

按住Ctrl键单击即可:慧净电子单片机(一皇冠)【天津商盟】天津锐志(电子)单片机经营部(两皇冠)金沙滩工作室(5钻)深圳育松电子元件,模块,传感器,批发部:淘宝最全最平价(5皇冠)志宏电子(4钻)表2 串行口工作方式控制位其中,fOSC 为单片机的时钟频率;波特率指串行口每秒钟发送(或接收)的位数。

SM2 :多机通信控制位。

该仅用于方式2 和方式3 的多机通信。

其中发送机SM2 = 1(需要程序控制设置)。

接收机的串行口工作于方式2 或3,SM2=1 时,只有当接收到第9 位数据(RB8)为1 时,才把接收到的前8 位数据送入SBUF,且置位RI 发出中断申请引发串行接收中断,否则会将接受到的数据放弃。

当SM2=0 时,就不管第位数据是0 还是1,都将数据送入SBUF,并置位RI 发出中断申请。

51单片机串口通信(相关例程)

51单片机串口通信(相关例程)

51单片机串口通信(相关例程) 51单片机串口通信(相关例程)一、简介51单片机是一种常用的微控制器,它具有体积小、功耗低、易于编程等特点,被广泛应用于各种电子设备和嵌入式系统中。

串口通信是51单片机的常见应用之一,通过串口通信,可以使单片机与其他外部设备进行数据交互和通信。

本文将介绍51单片机串口通信的相关例程,并提供一些实用的编程代码。

二、串口通信基础知识1. 串口通信原理串口通信是通过串行数据传输的方式,在数据传输过程中,将信息分为一个个字节进行传输。

在51单片机中,常用的串口通信标准包括RS232、RS485等。

其中,RS232是一种常用的串口标准,具有常见的DB-9或DB-25连接器。

2. 串口通信参数在进行串口通信时,需要设置一些参数,如波特率、数据位、停止位和校验位等。

波特率表示在单位时间内传输的比特数,常见的波特率有9600、115200等。

数据位表示每个数据字节中的位数,一般为8位。

停止位表示停止数据传输的时间,常用的停止位有1位和2位。

校验位用于数据传输的错误检测和纠正。

三、串口通信例程介绍下面是几个常见的51单片机串口通信的例程,提供给读者参考和学习:1. 串口发送数据```C#include <reg51.h>void UART_Init(){TMOD = 0x20; // 设置计数器1为工作方式2(8位自动重装) TH1 = 0xFD; // 设置波特率为9600SCON = 0x50; // 设置串口工作方式1,允许串行接收TR1 = 1; // 启动计数器1}void UART_SendChar(unsigned char dat){SBUF = dat; // 发送数据while (!TI); // 等待发送完成TI = 0; // 清除发送完成标志}void main(){UART_Init(); // 初始化串口while (1){UART_SendChar('A'); // 发送字母A}}```2. 串口接收数据```C#include <reg51.h>void UART_Init(){TMOD = 0x20; // 设置计数器1为工作方式2(8位自动重装) TH1 = 0xFD; // 设置波特率为9600SCON = 0x50; // 设置串口工作方式1,允许串行接收TR1 = 1; // 启动计数器1}void UART_Recv(){unsigned char dat;if (RI) // 检测是否接收到数据{dat = SBUF; // 读取接收到的数据 RI = 0; // 清除接收中断标志// 处理接收到的数据}}void main(){UART_Init(); // 初始化串口EA = 1; // 允许中断ES = 1; // 允许串口中断while (1)// 主循环处理其他任务}}```3. 串口发送字符串```C#include <reg51.h>void UART_Init(){TMOD = 0x20; // 设置计数器1为工作方式2(8位自动重装) TH1 = 0xFD; // 设置波特率为9600SCON = 0x50; // 设置串口工作方式1,允许串行接收TR1 = 1; // 启动计数器1}void UART_SendString(unsigned char *str){while (*str != '\0')SBUF = *str; // 逐个发送字符while (!TI); // 等待发送完成TI = 0; // 清除发送完成标志str++; // 指针指向下一个字符}}void main(){UART_Init(); // 初始化串口while (1){UART_SendString("Hello, World!"); // 发送字符串}}```四、总结本文介绍了51单片机串口通信的基础知识和相关编程例程,包括串口发送数据、串口接收数据和串口发送字符串。

51单片机串口通信程序。。含详细例子

51单片机串口通信程序。。含详细例子

{ P3_4=0; P3_3=1;
} void RstPro()//编程器复位 {
pw.fpProOver();//直接编程结束 SendData();//通知上位机,表示编程器就绪,可以直接用此函数因为协议号(ComBuf[0])还没被修改,下同 }
void ReadSign()//读特征字 {
} void serial () interrupt 4 using 3 //串口接收中断函数 {
if (RI) { RI = 0 ; ch=SBUF; read_flag= 1 ; //就置位取数标志 }
} main()
{ init_serialcom(); //初始化串口 while ( 1 ) { if (read_flag) //如果取数标志已置位,就将读到的数从串口发出 { read_flag= 0 ; //取数标志清 0 send_char_com(ch); } }
while(RI == 0); RI = 0; c = SBUF; // 从缓冲区中把接收的字符放入 c 中 SBUF = c; // 要发送的字符放入缓冲区 while(TI == 0); TI = 0; } }
4.//////////////// /////////////////////////////////////////////////////////
SendData(); } else break;//等待回应失败 } pw.fpProOver();//操作结束设置为运行状态 ComBuf[0]=0;//通知上位机编程器进入就绪状态 SendData(); }
void Lock()//写锁定位
{
pw.fpLock();
SendData();

51单片机与串口通信代码

51单片机与串口通信代码

51单片机与串口通信代码串口调试1. 发送:向总线上发命令2. 接收:从总线接收命令,并分析是地址还是数据。

3. 定时发送:从内存中取数并向主机发送.经过调试,以上功能基本实现,目前可以通过上位机对单片机进行实时控制。

程序如下://这是一个单片机C51串口接收(中断)和发送例程,可以用来测试51单片机的中断接收//和查询发送,另外我觉得发送没有必要用中断,因为程序的开销是一样的#i nclude <reg51.h>#i nclude<stdio.h>#i nclude <string.h>#define INBUF_LEN 4 //数据长度unsigned char inbuf1[INBUF_LEN];unsigned char checksum,count3 , flag,temp,ch;bit read_flag=0;sbit cp=P1^1;sbit DIR=P1^2;int i;unsigned int xdata *RAMDATA; /*定义RAM地址指针*/unsigned char a[6] ={0x11,0x22,0x33,0x44,0x55,0x66} ;void init_serialcomm(void){SCON=0x50; //在11.0592MHz下,设置串行口波特率为9600,方式1,并允许接收PCON=0x00;ES=1;TMOD=0x21; //定时器工作于方式2,自动装载方式 TH0=(65536-1000)%256;TL0=(65536-1000)/256;TL1=0xfd;TH1=0xfd;ET0=1;TR0=1;TR1=1;// TI=0;EA=1;// TI=1;RAMDATA=0x1F45;}void serial () interrupt 4 using 3{if(RI){ RI=0;ch=SBUF;TI=1; //置SBUF空switch(ch){case 0x01 :printf("A"); TI=0;break;case 0x02 :printf("B"); TI=0;break;case 0x03 :printf("C"); TI=0;break;case 0x04 :printf("D"); TI=0;break; default :printf("fg"); TI=0;break; }}}//向串口发送一个字符void timer0() interrupt 1 using 3{// char i;flag++;TH0=0x00;TL0=0x00;if(flag==10){// cp=!cp;// for(i=0;i<6;i++)P2=0x25;TI=1;temp=*RAMDATA;printf("%c",temp); TI=0;// RAMDATA--;flag=0;}}//主程序main(){init_serialcomm(); //初始化串口//向6264中送数据{*RAMDATA=0x33;}while(1){*RAMDATA=0x33;;}}调试过程中遇到的问题:1. 发送过程:在发送时必须保证TI=1:即发送缓冲器为空,否则将导致数据发不出去,如果想强制发送可以用:TI=1.具体发送数据:利用printf(“akjdfaklfj”);函数直接发送即可。

stc c51 串口通信协议常用校验计算以及一些常用方法

stc c51 串口通信协议常用校验计算以及一些常用方法

stc c51 串口通信协议常用校验计算以及一些常用方法一、引言随着现代通信技术的快速发展,串口通信在各领域得到了广泛应用。

STC C51 作为一种高性能、低功耗的单片机,其串口通信协议在实际工程中具有很高的实用价值。

本文将详细介绍STC C51 串口通信协议的常用校验计算方法及其实现,以期为相关领域的研究和应用提供参考。

二、STC C51 串口通信协议简介1.串口通信的基本原理串口通信是通过传输线将数据位按照位顺序依次传输的一种通信方式。

在数据传输过程中,通常采用异步串行通信和同步串行通信两种方式。

2.STC C51 串口通信的特点STC C51 单片机内部集成了异步串行通信模块,具有以下特点:(1)高速率:最高可达1Mbps;(2)低功耗:待机模式下电流小于1uA;(3)丰富的波特率选择:支持0-115200bps等多种波特率;(4)灵活的通信模式:支持多机通信、广播通信等;(5)内置硬件滤波器:可滤除噪声干扰,提高通信可靠性。

三、常用校验计算方法1.奇偶校验奇偶校验是一种简单而有效的校验方法。

在数据传输过程中,根据数据位中1的个数是否为奇数来判断数据是否正确。

若数据位中1的个数为奇数,则为奇校验;若为偶数,则为偶校验。

2.循环冗余校验(CRC)循环冗余校验是一种基于二进制多项式的校验方法。

发送方和接收方使用相同的生成多项式,对数据位进行异或操作,得到校验位。

接收方在接收到数据后,同样对数据位进行异或操作,若结果与接收到的校验位相同,则数据正确;否则,数据错误。

3.异或校验异或校验是一种基于异或运算的校验方法。

在数据传输过程中,发送方和接收方约定一个校验位,并对数据位进行异或操作。

接收方在接收到数据后,对数据位进行异或操作,若结果与接收到的校验位相同,则数据正确;否则,数据错误。

四、STC C51 串口通信协议的实现1.硬件配置为实现STC C51 串口通信,需要配置以下硬件:(1)串口通信模块:UART0、UART1 或UART2;(2)波特率发生器:用于产生不同的波特率;(3)电平转换器:用于匹配发送和接收端的电平;(4)滤波器:用于滤除噪声干扰。

51单片机模拟串口通讯

51单片机模拟串口通讯

论坛新老朋友们。

祝大家新年快乐。

在新的一年开始的时候,给大家一点小小的玩意。

工程师经常碰到需要多个串口通信的时候,而低端单片机大多只有一个串行口,甚至没有串口。

这时候无论是选择高端芯片,还是更改系统设计都是比较麻烦的事。

我把以前搞的用普通I/O口模拟串行口通讯的程序拿出来,供大家参考,希望各位兄弟轻点拍砖。

基本原理:我们模拟的是串行口方式1.就是最普通的方式。

一个起始位、8个数据位、一个停止位。

模拟串行口最关键的就是要计算出每个位的时间。

以波特率9600为例,每秒发9 600个位,每个位就是1/9600秒,约104个微秒。

我们需要做一个精确的延时,延时时间+对IO口置位的时间=104微秒。

起始位是低状态,再延时一个位的时间。

停止位是高状态,也是一个位的时间。

数据位是8个位,发送时低位先发出去,接收时先接低位。

了解这些以后,做个IO模拟串口的程序,就是很容易的事。

我们开始。

先上简单原理图:就一个MAX232芯片,没什么好说的,一看就明白。

使用单片机普通I/ O口,232数据输入端使用51单片机P3.2口(外部中断1口,接到普通口上也可以,模拟中断方式的串行口会有用。

呵呵)。

数据输出为P0.4(随便哪个口都行)。

下面这个程序,您只需吧P0.4 和P3.2 当成串口直接使用即可,经过测试完全没有问题.2、底层函数代码如下:sbit TXD1 = P0^4; //定义模拟输出脚sbit RXD1 = P3^2; //定义模拟输入脚bdata unsigned char SBUF1; //定义一个位操作变量sbit SBUF1_bit0 = SBUF1^0;sbit SBUF1_bit1 = SBUF1^1;sbit SBUF1_bit2 = SBUF1^2;sbit SBUF1_bit3 = SBUF1^3;sbit SBUF1_bit4 = SBUF1^4;sbit SBUF1_bit5 = SBUF1^5;sbit SBUF1_bit6 = SBUF1^6;sbit SBUF1_bit7 = SBUF1^7;void delay_bps() {unsigned char i; for (i = 0; i < 29; i++); _nop_(); _nop_();} //波特率9600 模拟一个9600波特率unsigned char getchar2() //模拟接收一个字节数据{while (RXD1);_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_(); delay_bps();SBUF1_bit0 = RXD1; //0delay_bps();SBUF1_bit1 = RXD1; //1delay_bps();SBUF1_bit2 = RXD1; //2delay_bps();SBUF1_bit3 = RXD1; //3delay_bps();SBUF1_bit4 = RXD1; //4delay_bps();SBUF1_bit5 = RXD1; //5delay_bps();SBUF1_bit6 = RXD1; //6delay_bps();SBUF1_bit7 = RXD1; //7delay_bps();return(SBUF1) ; //返回读取的数据}void putchar2(unsigned char input) //模拟发送一个字节数据{SBUF1 = input;TXD1 = 0; //起始位delay_bps();TXD1 = SBUF1_bit0; //0delay_bps();TXD1 = SBUF1_bit1; //1delay_bps();TXD1 = SBUF1_bit2; //2delay_bps();TXD1 = SBUF1_bit3; //3delay_bps();TXD1 = SBUF1_bit4; //4delay_bps();TXD1 = SBUF1_bit5; //5delay_bps();TXD1 = SBUF1_bit6; //6delay_bps();TXD1 = SBUF1_bit7; //7delay_bps();TXD1 = 1; //停止位delay_bps();}3、实现串行通讯。

51单片机串口通信及波特率设置

51单片机串口通信及波特率设置

51单片机串口通信及波特率设置MCS-51单片机具有一个全双工的串行通信接口,能同时进行发送和接收。

它可以作为UART(通用异步接收和发送器)使用,也可以作为同步的移位寄存器使用。

1. 数据缓冲寄存器SBUFSBUF是可以直接寻址的专用寄存器。

物理上,它对应着两个寄存器,即一个发送寄存器一个接收寄存器,CPU写SBUF就是修改发送寄存器;读SBUF就是读接收寄存器。

接收器是双缓冲的,以避免在接收下一帧数据之前,CPU未能及时的响应接收器的中断,没有把上一帧的数据读走而产生两帧数据重叠的问题。

对于发送器,为了保持最大的传输速率,一般不需要双缓冲,因为发送时CPU是主动的,不会产生重叠问题。

2. 状态控制寄存器SCONSCON是一个逐位定义的8位寄存器,用于控制串行通信的方式选择、接收和发送,指示串口的状态,SCON即可以字节寻址也可以位寻址,字节地址98H,地址位为98H~9FH。

它的各个位定义如下:MSB LSBSM0 SM1 SM2 REN TB8 RB8 TI RI SM0和SM1是串口的工作方式选择位,2个选择位对应4种工作方式,如下表,其中Fosc是振荡器的频率。

SM0 SM1 工作方式功能波特率0 0 0 8位同步移位寄存器Fosc/120 1 1 10位UART 可变1 02 11位UART Fosc/64或Fosc/321 1 3 11位UART 可变SM2在工作方式2和3中是多机通信的使能位。

在工作方式0中,SM2必须为0。

在工作方式1中,若SM2=1且没有接收到有效的停止位,则接收中断标志位RI不会被激活。

在工作方式2和3中若SM2=1且接收到的第9位数据(RB8)为0,则接收中断标志RB8不会被激活,若接收到的第9位数据(RB8)为1,则RI置位。

此功能可用于多处理机通信。

REN为允许串行接收位,由软件置位或清除。

置位时允许串行接收,清除时禁止串行接收。

TB8是工作方式2和3要发送的第9位数据。

简单有效的单片机CRC快速算法

简单有效的单片机CRC快速算法

简单实用的单片机CRC快速算法1 引言CRC(循环冗余码)检验技术广泛应用于测控及通信领域。

在很多情况下,CRC计算是靠专用的硬件来实现的,但是对于小型低成本的单片机系统来说,若要在没有这些硬件的支持下实现CRC检验,首先要解决的就是如何通过软件高效快速地完成CRC计算的问题,也就是CRC算法的问题。

这里将提供两种算法,它们稍有不同,一种适用于程序空间大一些的51系列等单片机,另一种适用于程序空间的使用条件十分苛刻的PIC单片机。

这些算法按字节进行计算,仅使用查表和简单的异或运算等操作,所以,计算过程相当简捷,而计算速度却很快。

下面先简述一下CRC原理,然后再以CRC-CCITT标准生成多项式为例对算法进行说明,并给出一个51系列单片机子程序和一个PIC单片机子程序。

2 CRC原理CRC检验原理实际上就是在一个p位二进制数据序列之后附加一个r位二进制检验码(序列),从而构成一个总长为n=p +r位的二进制序列,例如,p位二进制数据序列D=[dp-1dp-2 ......d1d0],r位二进制检验码R=[rr-1 rr-2....r1 r0],所得到的这个n位二进制序列就是M=[dp-1dp-2 ......d1d0 rr-1 rr-2....r1 r0];附加在数据序列之后的这个检验码与数据序列的内容之间存在着某种特定的关系。

如果因干扰等原因使数据序列中的某一位或某些位发生错误,这种特定关系就会被破坏,因此,通过检查这一关系, 就可以实现对数据正确性的检验。

校验码R是通过对数据序列D进行二进制除法取余式运算得到的,它被一个称为生成多项式的(r+1)位二进制序列G =[gr gr-1 .... g1 g0]来除,用多项式形式表示为其中,xrD(x)表示将数据序列D左移r位(即在D的末尾再增加r个0位),Q(x)代表这一除法所得的商,R(x)就是所需的余式。

这一运算关系还可以用式(2)来表达其中,Re[ ]表示对括号内的式子进行取余式运算。

51单片机 Modbus协议RTU模式校验CRC计算方法

51单片机 Modbus协议RTU模式校验CRC计算方法
如:接收数据放在数组 rsbuf[],length 为接收到数据的总长度。 判断 CRC_L 是否等于 rsbuf[length-2];CRC_H 是否等于 rsbuf[length-1]
注意:在传送 CRC 的时候确保低字节数据线传送,然后在传送高字节。 下面是 C 代码: Void CRC_Check(unsigned char *gets,unsigned char length) {
Unsigned int I; Unsigned int j; Unsigned int CRC; Unsigned char CRC_L; Unsigned char CRC_H; CRC=0xFFFF; CRC_L=CRC; CRC_H=CRC>>8; for(i=0;i<length-2;i++) {
CRC 的低字节(确保是 CRC 的低字节,而不是 CRC) 3. CRC 右移一位,CRC 最高位补 0,并判断移出位。 4. 如果移出位是 0:重复 3 步骤,如果移出位是 1:则 CRC 与 A001H 做 XOR(异或)
运算将运算结果传回 CRC(这次是 CRC)。 5. 重复步骤 3 和 Байду номын сангаас 直到已经右移了 8 位为止。 6. 对信息的下一个字节重复 2 到 5 的步骤,直到信息中的数据字节都处理完。 7. 此时得到的 CRC 就是校验 CRC
CRC_L=CRC_L^gets[i]; CRC=CRC_L+(CRC_H<<8); for(j=0;j<8;j++) {
if(CRC&1) {
CRC>>=1; CRC = CRC^0xA001; } else {CRC=CRC/2;} CRC_H=CRC>>8; CRC_L=CRC; }

简述usart程序编程步骤

简述usart程序编程步骤

简述usart程序编程步骤摘要:USART程序编程步骤概述1.硬件配置2.初始化USART模块3.配置波特率和其他通信参数4.编写发送和接收函数5.编写主循环6.错误处理和调试正文:USART(通用串行异步接收发送器)是一种广泛应用于嵌入式系统的通信接口。

以下是将USART应用于程序编程的步骤概述:1.硬件配置:首先,根据项目需求选择合适的USART硬件。

这包括USART芯片、电平转换器(如有必要)、晶振等。

同时,确保所选硬件与MCU(微控制器)相匹配。

2.初始化USART模块:在程序开始时,对USART模块进行初始化。

这包括启用相应的时钟,配置波特率、数据位、停止位、奇偶校验等参数。

3.配置波特率和其他通信参数:根据通信需求,设置合适的波特率和其他通信参数。

常用的波特率计算方法有公式法和查表法。

此外,还需配置其他参数,如数据位、停止位、奇偶校验等。

4.编写发送和接收函数:为实现USART的数据发送和接收,需要编写相应的发送和接收函数。

发送函数将待发送数据包装成合适的格式,并通过USART 模块发送。

接收函数则从USART模块读取接收到的数据,并进行必要的处理。

5.编写主循环:在主循环中,根据实际需求调用发送和接收函数,实现数据的传输。

同时,可以添加错误检测和处理机制,以确保通信的稳定性和可靠性。

6.错误处理和调试:USART通信过程中可能出现各种错误,如波特率不匹配、数据位错误等。

为保证程序的鲁棒性,需要对可能出现的错误进行处理。

此外,充分利用调试工具(如串口调试助手)进行调试,以确保程序的正确性。

通过以上步骤,可以完成一个基本的USART程序。

在实际应用中,根据具体需求,还可以扩展其他功能,如多机通信、硬件流控制等。

C51的CRC校验程序(Keil C51)

C51的CRC校验程序(Keil C51)
{
CRC = CrcCal((*p),CRC);
p++;
}
*p++ = CRC; //CrcL 将结果放到缓冲区中低字节在前,高字节在后。
*p = CRC / 256; // CrcH
}//准备RTU数据
main (void) // main program
}
//计算Buf1中的8个字节CRC=0x0000,想想看Buf与Buf1的数据,为什么?
CRC = 0xffff;
for(i = 0;i < 8;i++) //Buf1做8次循环计算
{
CRC = CrcCal(Buf1[i],CRC); //改过的调用方式,将0xa001固定在子程序中
date : 2013.03.06
design : Shi Jian Min
version : 1.0.0
Modify : 2013.03.06 V1.0.0
Modifier : Shi Jian Min
}
} //Test_CRC(void)
/*************************************************
(准备数据)
数据放在缓冲区中,计算缓冲区中所有数据的CRC结果,
并将结果放在缓冲区后面。
(计算好数据后就可以通过串口等将数据发送出去)
***************************************************/
/*************************************************
CRC校验程序 Keil-C51

CRC校验码在单片机中的程序实现的求取

CRC校验码在单片机中的程序实现的求取

CRC校验码在单片机中的程序实现的求取由单片机嵌入式系统与微机组成的工业检测和数据采集系统中,计算机与单片机之间经常需要进行数据通信。

在数字通信过程中,干扰有可能使接收到的二进制数和发送的不一致,造成'0'和'1'互变的差错。

一个实用的通信系统必需能发现这种差错,并加以纠正或给出重新发送信息。

CRC(CyclICRedundancy Code循环冗余码),也称多项式编码。

是一种检错效率高、原理简单、易于实现的通信编码,是目前在数字通信领域应用最为广泛的一种检验方式。

如16位的CRC-CCITT标准可以检测出所有的单位错、双位错、奇位数错及小于等于16位的突发错,大于17位的突发错检错率为99.9984%[1]。

可见,CRC码的检错率要大大高于一般的奇偶校验。

因此CRC校验可以应用于重要数据的通信场合,如下位机运行状态的检测、运行模式或参数的在线重设置等。

对于8位的单片机系统,要实现CRC通信就必须编写生成CRC码的指令程序,且由于单片机的程序存储器很少、运算速度也比较低,因此要求程序代码尽量少,算法必须简单。

下面将以CRC-CCITT标准为例来介绍CRC通信码的单片机实现过程。

1 CRC校验码的构成求得余式R(x),使等式左端的代数式恰为CRC校验式G(x)的整数倍。

则将其与待发送的数据多项式xr·M(x)相加得到的r+k次多项式的各个系数(mk-1,mk-2,…,m1,m0,rr-1,rr-2,…,r1,r0)作为编码一起发送,其中高k位是信息位,低r位是附加校验位。

在数据接收端,再对接收到的信息码进行校验,如能被同一个G(x)整除,则表明通信正确;若余数不为0,表示数据传输有误,从而达到检错的目的。

CRC校验虽然不能100%检测出错误,但它的漏检率相当低。

漏检概率和所选取的校验标准相关,国际上已有多种CRC校验式标准。

其中8位的CRC码标准有CDT约定,其校验式为G(x)=x8+x2+x+1;16位的标准有CCITT(国际电报电话咨询委员会推荐)标准G(x)=x16+x12+x5+1,和IBM公司提出的CRC-16标准G(x)=x16+x12+x2+1;校验错误效率最高的是具有32位CRC校验码的2 多字节信息序列CRC码的快速算法假设需要传送的一组信息码N为k个字节二进制序列:Nk=[n1 n2……nk]其中的ni为信息码中的各个字节。

51单片机与PC串口间通讯设计与分析

51单片机与PC串口间通讯设计与分析

51单片机与PC串口间通讯设计与分析一、串口通讯原理串口通讯是指通过串口来进行数据的收发传输的一种通讯方式。

串口通讯分为同步串行通讯和异步串行通讯两种方式,而51单片机与PC之间的串口通讯采用的是异步串行通讯方式。

异步串行通信是指每个数据字节之间可以有可变长度的停止位和起始位。

串口通讯一般由以下几个部分组成:1.传输数据线:用于传输数据的信号线,包括发送数据线(TXD)和接收数据线(RXD)。

2.时钟线:用于提供通讯双方的时钟信号。

3.控制线:用于控制串口通讯的流程,包括数据准备好(DSR)、数据就绪(DTR)等。

二、串口通讯协议串口通讯协议是约定通讯双方数据传输的格式和规则,常见的串口通讯协议有RS-232、RS-485等。

在51单片机与PC之间的串口通讯中,一般使用的是RS-232协议。

RS-232协议规定了数据的起始位、数据位数、校验位和停止位等。

起始位用于标识数据的传输开始,通常为一个逻辑低电平;数据位数指定了每个数据字节的位数,常见的值有5位、6位、7位和8位等;校验位用于校验数据的正确性,一般有无校验、奇校验和偶校验等选项;停止位用于表示数据的传输结束,通常为一个逻辑高电平。

三、51单片机串口的程序设计#include <reg52.h>#define UART_BAUDRATE 9600 // 波特率设置#define UART_DIV 256- UART_BAUDRATE/300void UART_Init( //串口初始化TMOD=0x20;SCON=0x50;PCON=0x00;TH1=UART_DIV;TL1=UART_DIV;TR1=1;EA=1;ES=1;void UART_SendByte(unsigned char ch) //串口发送字节TI=0;SBUF = ch;while(TI == 0);TI=0;void UART_Interrupt( interrupt 4 //串口中断处理if(RI)unsigned char ch;ch = SBUF;RI=0;//处理接收到的数据}if(TI)TI=0;//发送下一个字节}void mainUART_Init(;while(1)//主循环}在上述程序中,首先通过UART_Init(函数进行串口初始化,其中设置了波特率为9600;然后使用UART_SendByte(函数发送数据,调用该函数时会把数据放入SBUF寄存器,并等待TI标志位变为1;最后,在UART_Interrupt(函数中,使用RI标志位判断是否收到数据,然后对数据进行处理,TI标志位判断是否发送完当前字节。

C51单片机串口通讯通用模块代码(可用于操作系统串口通讯)

C51单片机串口通讯通用模块代码(可用于操作系统串口通讯)

C51单片机串口通讯通用模块代码(可用于操作系统串口通讯)#include#include "UART1.h"#include "commdriver.h"//当前适用于C51//可以根据具体CPU型号,修改宏定义和串口初始化代码就可以#define CPU_XTAL 22118400 //CPU频率#define FUNCTION_NULL 0 //没有定义函数#define COM_TI TI //发送中断寄存器#define COM_TI0() {TI = 0;} //发送中断寄存器清零#define COM_TI1() {TI = 1;} //发送中断寄存器置一( 强行置一触发发送中断)#define COM_TI_SBUF(dat) {SBUF = dat;} //发送数据到硬件缓冲区#define COM_TI_End() {return;} //发送结束处理函数#define COM_RI RI //接收中断寄存器#define COM_RI0() {RI = 0;} //接收中断寄存器清零#define COM_RI1() {RI = 1;} //接收中断寄存器置一#define COM_RI_SBUF(dat) {dat = SBUF;} //提取接收硬件缓冲区数据#define COM_TI_FLAG COM_TI //发送中断标志寄存器(非中断发送方式使用)#define COM_TI_FLAG0() COM_TI0() //发送中断标志寄存器清零(非中断发送方式使用)void (*COM1RevEvent)(unsigned char dat); //数据接收事件#define LenTxBuf 30 //发送缓冲区长度#define LenRxBuf 1 //接收缓冲区长度volatile unsigned char TxBuf1[LenTxBuf],RxBuf1[LenRxBuf]; //收发缓冲区实体volatile unsigned char *inTxBuf1,*outTxBuf1,*inRxBuf1,*outRxBuf1; //收发缓冲区读写指针volatile unsigned char TIflag1=1;//Note:It must be 1. //发送缓冲区为空标志//*********************#define _TxBuf TxBuf1#define _RxBuf RxBuf1#define _inTxBuf inTxBuf1#define _outTxBuf outTxBuf1#define _inRxBuf inRxBuf1#define _outRxBuf outRxBuf1#define _TIflag TIflag1/*************函数声明****************/#define _COMRevEvent COM1RevEvent //串口接收事件#define _USART_IRQ void USART1_IRQHandler(void) interrupt 4 //串口中断服务程序#define _COM_Buffer_Init void COM1_Buffer_Init(void) //串口缓冲区初始化#define _COM_Open void COM1_Open(unsigned int baudrate,void (*revevent)(unsigned char dat)) // 串口初始化#define _COM_Close void COM1_Close(void) //关闭串口#define _COM_GetOneByte unsigned charCOM1_GetOneByte(unsigned char *ch) //获取一个字节#define _COM_GetPChar unsigned char COM1_GetPChar(unsigned char *ch,unsigned char len) //获取指定长度字节数组#define _COM_RxByte unsigned char COM1_RxByte(void) //获取接收字节个数//********缓冲区中断方式发送(安全性高)#define _COM_SendOneByte unsigned char COM1_SendOneByte(unsigned char one_byte) // 发送一个字节#define _COM_SendPChar void COM1_SendPChar(unsigned char *P,unsigned char Len) //发送定长字节数组#define _COM_SendString void COM1_SendString(unsigned char *P) //发送字符串//********非缓冲区中断方式发送#define _COM_PrintOneByte void COM1_PrintOneByte(unsigned char c) // 发送一个字节#define _COM_PrintPChar void COM1_PrintPChar(unsigned char *buf,unsigned int len) //发送定长字节数组#define _COM_PrintString void COM1_PrintString(unsigned char *P) //发送字符串//*************内部引用模型函数(外部不关心,移植时修改后面函数名,要与上面对应的外部声明的函数名一致)*******************#define COM_GetOneByte_(ptr) COM1_GetOneByte(ptr) //与上面获取一个字节的函数对应#define COM_SendOneByte_(dat) COM1_SendOneByte(dat) //与上面发送一个字节的函数对应#define COM_PrintOneByte_(dat) COM1_PrintOneByte(dat) //与上面发送一个字节的函数对应//*********************函数模型定义区(不需要修改)*****************/****************************函数模型:void USART_IRQHandler(void)函数功能:串口中断服务程序入口参数:无返回值:无修改者:修改时间:修改内容简要:***************************/_USART_IRQ //串口1中断{volatile unsigned char *t;if(COM_RI){COM_RI0(); //清接收标记if(_COMRevEvent != FUNCTION_NULL) //自定义接收事件{COM_RI_SBUF(*_inRxBuf);_COMRevEvent(*_inRxBuf);}else{t = _inRxBuf;t++;if(t == (_RxBuf + LenRxBuf)) t = _RxBuf;if(t != _outRxBuf) //RxBuf No Full{COM_RI_SBUF(*_inRxBuf);_inRxBuf = t;}}}if(COM_TI){COM_TI0();if(_inTxBuf == _outTxBuf) {_TIflag = 1;COM_TI_End();};//TxBuf1 EmptyCOM_TI_SBUF(*_outTxBuf); _outTxBuf++;if(_outTxBuf == (_TxBuf+LenTxBuf)) _outTxBuf = _TxBuf;}}/****************************函数模型:void COM1_Buffer_Init(void)函数功能:串口1缓冲区初始化入口参数:无返回值:无修改者:修改时间:修改内容简要:***************************/_COM_Buffer_Init{_inTxBuf = _TxBuf;_outTxBuf = _TxBuf;_inRxBuf = _RxBuf;_outRxBuf = _RxBuf;}/****************************函数模型:void COM_Open(unsigned int baudrate,void (*revevent)(unsigned char dat))函数功能:系统串口初始化入口参数: unsigned int baudrate:串口波特率返回值:无修改者:修改时间:修改内容简要:***************************/_COM_Open{//定时器1做波特率发生器TI = 0; /* clear transmit interrupt */TR1 = 0; /* stop timer 1 */ET1 = 0; /* disable timer 1 interrupt */PCON |= 0x80; /* 0x80=SMOD: set serial baudrate doubler */ TMOD &= ~0xF0; /* clear timer 1 mode bits */TMOD |= 0x20; /* put timer 1 into MODE 2 */TH1 = (unsigned char) (256 - (CPU_XTAL / (16L * 12L * baudrate)));TR1 = 1; /* start timer 1 *///设置串口1模式SM0 = 0; SM1 = 1; /* serial port MODE 1 */SM2 = 0;REN = 1; /* enable serial receiver */RI = 0; /* clear receiver interrupt */TI = 0; /* clear transmit interrupt */ES = 1; /* enable serial interrupts */PS = 1; /* set serial interrupts to low priority */_COMRevEvent = revevent;}/****************************函数模型:void COM1_Close(void)函数功能:关闭系统串口入口参数:无返回值:无修改者:修改时间:修改内容简要:***************************/_COM_Close{}/****************************函数模型:unsigned char COM1_GetOneByte(unsigned char *ch)函数功能:获取一个字节入口参数:unsigned char *ch:接收字节指针返回值: unsigned char *ch:接收字节指针unsigned char :获取状态;0:成功,1:失败(缓冲区为空)修改者:修改时间:修改内容简要:***************************/_COM_GetOneByte{if(_inRxBuf == _outRxBuf) {return 0;}; //RxBuf Empty*ch = *_outRxBuf; _outRxBuf++;if(_outRxBuf==_RxBuf+LenRxBuf) _outRxBuf = _RxBuf;return 1;}/****************************函数模型:unsigned char COM_GetPChar(unsigned char *ch,unsigned char len)函数功能:获取指定长度字节数组入口参数: unsigned char *ch:接收字节数组指针unsigned char len:接收字节个数返回值: unsigned char *ch:接收字节数组指针unsigned char:实际接收字节个数修改者:修改时间:修改内容简要:***************************/_COM_GetPChar{unsigned char i = 0;do{len--;if(!COM_GetOneByte_(ch)) break;i++;ch++;}while(len);return i;}/****************************函数模型:unsigned char COM_RxByte(void)函数功能:获取接收缓冲区有效字节个数入口参数:无返回值: unsigned char:接收缓冲区有效字节个数修改者:修改时间:修改内容简要:***************************/_COM_RxByte{if(_inRxBuf>=_outRxBuf) return (_inRxBuf-_outRxBuf);else return LenRxBuf-(_outRxBuf-_inRxBuf);}/****************************函数模型:unsigned char COM_SendOneByte(unsigned char one_byte)函数功能:发送一个字节入口参数: unsigned char one_byte:发送的字节返回值:unsigned char:发送状态,0:成功,1:失败(缓冲区满)修改者:修改时间:修改内容简要:***************************/_COM_SendOneByte{volatile unsigned char *t;if(_TIflag){_TIflag = 0;COM_TI1();}t = _inTxBuf;t++;if(t == _TxBuf + LenTxBuf) t = _TxBuf;if(t == _outTxBuf) {return 1;};//TxBuf Full*_inTxBuf = one_byte;_inTxBuf = t;return 0;}/****************************函数模型:void COM_SendPChar(unsigned char *P,unsigned char Len)函数功能:发送定长字节数组入口参数: unsigned char *P:字节数组指针unsigned char Len:发送长度返回值:无修改者:修改时间:修改内容简要:***************************/_COM_SendPChar{while(Len){//while(COM1_SendOneByte(*P)); //发送失败,继续发送,知道发送成功COM_SendOneByte_(*P);P++;Len--;}}/****************************函数模型:void COM_SendString(unsigned char *P)函数功能:发送字符串入口参数: unsigned char *P:字符串指针返回值:无修改者:修改时间:修改内容简要:***************************/_COM_SendString{while(*P){COM_SendOneByte_(*P);P++;}}//**************** 非缓冲区中断方式发送/****************************函数模型:void COM_PrintOneByte(unsigned char c)函数功能:发送一个字节入口参数: unsigned char one_byte:发送的字节返回值:无修改者:修改时间:修改内容简要:***************************/_COM_PrintOneByte{COM_TI_FLAG0();COM_TI_SBUF(c); //发送数据while(!COM_TI_FLAG) ; //等待发送结束}/****************************函数模型:void COM_PrintPChar(unsigned char *buf,unsigned int len)函数功能:发送定长字节数组入口参数: unsigned char *P:字节数组指针unsigned char Len:发送长度返回值:无修改者:修改时间:修改内容简要:***************************/_COM_PrintPChar{while(len){COM_PrintOneByte_(*buf);buf ++;len--;}}/****************************函数模型:void COM_PrintString(unsigned char *P) 函数功能:发送字符串入口参数: unsigned char *P:字符串指针返回值:无修改者:修改时间:修改内容简要:***************************/_COM_PrintString{while(*P){COM_PrintOneByte_(*P);P++;}}。

51单片机串口通信

51单片机串口通信

51单片机串口通信串行口通信是一种在计算机和外部设备之间进行数据传输的通信方式,其中包括了并行通信、RS-232通信、USB通信等。

而在嵌入式系统中,最常见、最重要的通信方式就是单片机串口通信。

本文将详细介绍51单片机串口通信的原理、使用方法以及一些常见问题与解决方法。

一、串口通信的原理串口通信是以字节为单位进行数据传输的。

在串口通信中,数据传输分为两个方向:发送方向和接收方向。

发送方将待发送的数据通过串行转并行电路转换为一组相对应的并行信号,然后通过串口发送给接收方。

接收方在接收到并行信号后,通过串行转并行电路将数据转换为与发送方发送时相对应的数据。

在51单片机中,通过两个寄存器来实现串口通信功能:SBUF寄存器和SCON寄存器。

其中,SBUF寄存器用于存储要发送或接收的数据,而SCON寄存器用于配置串口通信的工作模式。

二、51单片机串口通信的使用方法1. 串口的初始化在使用51单片机进行串口通信之前,需要进行串口的初始化设置。

具体的步骤如下:a. 设置波特率:使用波特率发生器,通过设定计算器的初值和重装值来实现特定的波特率。

b. 串口工作模式选择:设置SCON寄存器,选择串行模式和波特率。

2. 发送数据发送数据的过程可以分为以下几个步骤:a. 将要发送的数据存储在SBUF寄存器中。

b. 等待发送完成,即判断TI(发送中断标志位)是否为1,如果为1,则表示发送完成。

c. 清除TI标志位。

3. 接收数据接收数据的过程可以分为以下几个步骤:a. 等待数据接收完成,即判断RI(接收中断标志位)是否为1,如果为1,则表示接收完成。

b. 将接收到的数据从SBUF寄存器中读取出来。

c. 清除RI标志位。

三、51单片机串口通信的常见问题与解决方法1. 波特率不匹配当发送方和接收方的波特率不一致时,会导致数据传输错误。

解决方法是在初始化时确保两端的波特率设置一致。

2. 数据丢失当发送方连续发送数据时,接收方可能会出现数据丢失的情况。

51单片机串口通信试验汇编程序

51单片机串口通信试验汇编程序

51单片机串口通信试验汇编程序(今天是硬生生的把它给抠出来了):PC 通过串口助手向单片机系统传递命令和数据:以A5开始,以5A结束;中间是数据,长度不一,要求把数据部分用led灯显示出来;并且要求循环显示;//This is my x_Ed program code//we use it as the pc communicated with the mcu//At the same time,we want to see the result by LCD;STFLAG BIT 00H //收到起始码标志,1为收到起始码EDFLAG BIT 01H //到结束码标志,1为收到结束码TMFLAG BIT 02H //定时时间到标志,1为定时时间到ORG 0000HSJMP Initialize//主程序入口(初始化程序)ORG 000BH //定时器0入口LJMP TIMER0 //定时器0中断ORG 0023H //串口中断程序的入口地址LJMP Transfer //跳转到接受中断入口///////////////////////////////////////////////////////////////ORG 0050HInitialize:MOV SP,#70H //设置堆栈MOV TMOD,#21H //T1工作方式2 T0工作MOV TH1,#0FDH //波特率9600MOV TL1,#0FDH //波特率9600 自动重装载MOV TH0,#3CH //定时50msMOV TL0,#0BH //定时50msMOV SCON,#50H //串口工作方式1MOV R6,#00H //定时次数计数器20一秒MOV R5,#00H //接收数据长度计数器MOV R4,#00H //控制输出控制寄存器MOV R0,#30H //数据存储地址MOV R1,#30H //控制输出的数据缓存CLR STFLAG //清起始标志位CLR EDFLAG //清结束标志位CLR TMFLAG //清时钟标志位SETB PS //提高串口中断的优先级SETB TR1 //打开定时器1;SETB ES //打开串口中断允许位SETB ET0 //定时器0中断允许位SETB EA //打开全局中断允许位/////////////////等待接受命令//////////////////////// Main: JB STFLAG,NODE3 //已经收到起始位SJMP Main //未起始继续等待NODE3: JB EDFLAG,NODE4 //已经收到结束位SJMP Main //未结束继续等待NODE4: SETB TR0 //打开定时器0;NODE5: JB TMFLAG,OUTPUTSJMP NODE5///////////////////等待上位机传送数据并记录//////// Transfer: CLR ESMOV A,SBUFCJNE A,#0A5H,NODE0 //检测到起始位SETB STFLAGSJMP JIEDIANNODE0: CJNE A,#05AH,NODE1 //检测到结束位SETB EDFLAGMOV DPH,R5MOV R4,DPHclr ES //打开串口中断允许位SJMP ret00NODE1: MOV @R0,A //既非起始码,又非结束码,则为数据INC R0INC R5MOV SBUF,#055HJIEDIAN: CLR TICLR RISETB ESret00: RETITIMER0: CLR TR0MOV TH0,#3CHMOV TL0,#0B0HINC R6CJNE R6,#20,RTNSETB TMFLAGMOV R6,#00HRTN: SETB TR0RETIOUTPUT: CLR TR0clr TMFLAGMOV A,@R1MOV P1,AINC R1DJNZ R4,NODE4MOV R1,#30HCLR TMFLAGMOV DPH,R5MOV R4,DPHSJMP NODE4RETIEND。

51单片机STC89C52RC上生成CRC16校验码的C语言程序

51单片机STC89C52RC上生成CRC16校验码的C语言程序

/*一段简单的51单片机CRC16校验码生成代码,上机测试通过,给那些想拿来主义的朋友们使用或许有用@Email:***********//*本代码在Keil中测试通过,在STC89C52RC单片机上测试通过*/#include <STC89C5xRC.H>#define uint unsigned int#define uchar unsigned char#define ushort unsigned shortuchar test_DATA[6]={0x01,0x06,0x00,0x01,0x00,0x17}; /////待校验数据,一组6字节的数据ushort CRC16num; ///////////CRC16校验码存储变量/////////////标准CRC16校验查询表,不要问我怎么得来的,就是这么用////////////////////////////////// CRC 高位字节值表*/////////////////////////////////////////// static uchar code auchCRCHi[] = {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} ;////////////////////////////////// CRC 低位字节值表/////////////////////////////////////static uchar code auchCRCLo[] = {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};////////////////////////////////////////////////////////////////////////////////////////////////////// ///CRC16校验函数,使用函数需输入待校验数组指针(数组名字咯)与数组字节数,返回值为ushort型16位CRC校验码///ushort CRC16(uchar *puchMsg , ushort usDataLen ){uchar uchCRCHi = 0xFF ; /* 高CRC字节初始化*/uchar uchCRCLo = 0xFF ; /* 低CRC字节初始化*/uint uIndex ; /* CRC循环中的索引*/while (usDataLen--) /* 传输消息缓冲区*/ {uIndex = uchCRCHi ^ *puchMsg++ ; /* */uchCRCHi = uchCRCLo ^ auchCRCHi[uIndex]; /* 计算CRC */uchCRCLo = auchCRCLo[uIndex] ; /* */}return (uchCRCHi << 8 | uchCRCLo) ;}////////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////主函数////////////////////////////////////////////////////////void main(){///////////////串口通讯相关设定://******************///////////////////////////////////// PCON &= 0x7F; //波特率不倍速SCON = 0x50; //8位数据,可变波特率AUXR &= 0xBF; //定时器1时钟为Fosc/12,即12TAUXR &= 0xFE; //串口1选择定时器1为波特率发生器TMOD &= 0x0F; //清除定时器1模式位TMOD |= 0x20; //设定定时器1为8位自动重装方式TL1 = 0xFD; //设定定时初值TH1 = 0xFD; //设定定时器重装值ET1 = 0; //禁止定时器1中断TR1 = 1; //启动定时器1////////////////////////////////////////////////////////////////////////////////////////////////////////计算出CRC16校验码后通过串口发送,可用串口通讯助手等软件察看CRC16校验码////本例计算出的正确的CRC16校验码数值为:0x9804//while(1){CRC16num=CRC16(test_DATA,6);SBUF=CRC16num>>8;while (!TI);TI=0;SBUF=CRC16num;while (!TI);TI=0;}}//////////////////////////////////////////////////////////////////////////////////////////////////////。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
相关文档
最新文档