当前位置:文档之家› 手把手教你学51单片机之十八RS485通信与Modbus协议

手把手教你学51单片机之十八RS485通信与Modbus协议

在工业控制、电力通讯、智能仪表等领域,通常情况下是采用串口通信的方式

进行数据交换。最初采用的方式是 RS232 接口,由于工业现场比较复杂,各

种电气设备会在环境中产生比较多的电磁干扰,会导致信号传输错误。除此之外,

RS232 接口只能实现点对点通信,不具备联网功能,最大传输距离也只能达到

几十米,不能满足远距离通信要求。而 RS485 则解决了这些问题,数据信号采用

差分传输方式,可以有效的解决共模干扰问题,最大距离可以到1200 米,并且

允许多个收发设备接到同一条总线上。随着工业应用通信越来越多, 1979 年施耐

德电气制定了一个用于工业现场的总线协议 Modbus 协议,现在工业中使用

RS485 通信场合很多都采用 Modbus 协议,本节课我们要讲解一下 RS485 通信和Modbus 协议。

单单使用一块KST-51 开发板是不能够进行RS485 实验的,应很多同学的要求,把这节课作为扩展课程讲一下,如果要做本课相关实验,需要自行购买USB 转 485 通信模块。

18.1 RS485通信

实际上在 RS485 之前 RS232 就已经诞生,但是RS232 有几处不足的地方:

1、接口的信号电平值较高,达到十几V ,容易损坏接口电路的芯片,而且和TTL 电平不兼容,因此和单片机电路接起来的话必须加转换电路。

2、传输速率有局限,不可以过高,一般到几十Kb/s 就到极限了。

3、接口使用信号线和GND 与其他设备形成共地模式的通信,这种共地模式传输容易产生

干扰,并且抗干扰性能也比较弱。

4、传输距离有限,最多只能通信几十米。

5、通信的时候只能两点之间进行通信,不能够实现多机联网通信。

针对 RS232 接口的不足,就不断出现了一些新的接口标准,RS485 就是其中之一,他具备

以下的特点:

1、我们在讲A/D 的时候,讲过差分信号输入的概念,同时也介绍了差分输入的好处,最大

的优势是可以抑制共模干扰。尤其工业现场的环境比较复杂,干扰比较多,所以通信如果采用的是差分方式,就可以有效的抑制共模干扰。而RS485 就是一种差分通信方式,它的通

信线路是两根,通常用 A 和B 或者D+ 和 D- 来表示。逻辑“ 1”以两线之间的电压差为+(0.2~6)V 表示,逻辑“0”以两线间的电压差为-(0.2~6)V来表示,是一种典型的差分通信。

2、 RS485通信速度快,最大传输速度可以达到10Mb/s以上。

3、RS485 内部的物理结构,采用的是平衡驱动器和差分接收器的组合,抗干扰能力也大大

增加。

4、传输距离最远可以达到1200 米左右,但是他的传输速率和传输距离是成反比的,只有

在100Kb/s 以下的传输速度,才能达到最大的通信距离,如果需要传输更远距离可以使用中继。

5、可以在总线上进行联网实现多机通信,总线上允许挂多个收发器,从现有的RS485 芯片来看,有可以挂32、 64、 128、 256 等不同个设备的驱动器。

RS485 的接口非常简单,和RS232 所使用的MAX232是类似的,只需要一个RS485 转换器,就可以直接和我们单片机的UART 串行接口连接起来,并且完全使用的是和UART 一致的异步串行通信协议。但是由于RS485 是差分通信,因此接收数据和发送数据是不能同

时进行的,也就是说它是一种半双工通信。那我们如何判断什么时候发送,什么时候接收呢?

RS485 类的芯片很多,这节课我们以 MAX485 为例讲解 RS485 通信,如图 18-1 所示。

图18-1 MAX485 硬件接口

MAX485 是美信 (Maxim) 推出的一款常用 RS485 转换器。其中 5 脚和 8 脚是电源引脚, 6 脚和 7 脚就是 485 通信中的 A 和 B 两个引脚,而 1 脚和 4 脚分别接到我们单片机的RXD 和TXD 引脚上,直接使用单片机UART 进行数据接收和发送。而 2 脚和 3 脚就是方向引脚了,

其中 2 脚是低电平使能接收器, 3 脚是高电平使能输出驱动器。我们把这两个引脚连到一起,平时不发送数据的时候,保持这两个引脚是低电平,让MAX485 处于接收状态,当需要发送数据的时候,把这个引脚拉高,发送数据,发送完毕后再拉低这个引脚就可以了。为了提

高 RS485 的抗干扰性能,需要在靠近 MAX485的 A 和 B 引脚之间并接一个电阻,这个电阻阻值从 100 欧到 1K 都可以。

在这里我们还要介绍一下如何使用KST-51 单片机开发板进行外围扩展实验。我们的开发板只能把基本的功能给同学们做出来提供实验练习,但是同学们学习的脚步不应该停留在这个

实验板上。如果想进行更多的实验,就可以通过单片机开发板的扩展接口进行扩展实验。大家可以看到蓝绿色的单片机座周围有32 个插针,这32 个插针就是把单片机的32个IO 引

脚全部都引出来了。在原理图上体现出来的就是我们的J4、J5、J6、 J7 这 4 个器件,如图18-2 所示。

图18-2 单片机扩展接口

这32 个 IO 口不是所有的 IO 口都可以用来对外扩展,其中既作为数据输出,又可以作为数

据输入的引脚是不可以用的,比如P3.2、 P3.4、P3.6 引脚,这三个引脚是不可用的。比如

P3.2 这个引脚,如果我们用来扩展,发送的信号如果和DS18B20 的时序吻合,会导致

DS18B20 拉低引脚,影响通信。除这 3 个 IO 口以外的其他 29 个 IO 口,都可以使用杜邦线

接上插针,扩展出来使用。当然了,如果把当前的IO 口应用于扩展功能了,板子上的相应

的功能就实现不了了,也就是说需要扩展功能和板载功能二选一。

在进行 RS485 实验中,我们通信用的引脚必须是P3.0 和 P3.1,此外还有一个方向控制引脚,我们使用杜邦线将其连接到P1.7 上去。 RS485 的另外一端,大家可以使用一个USB 转 485模块,用双绞线把开发板和模块上的 A 和 B 分别对应连起来, USB 那头插入电脑,然后就

可以进行通信了。

学习了第 13 章的实用串口通信的方法和程序后,做这种串口通信的方法就很简单了,基本

是一致的。我们使用实用串口通信的思路,做了一个简单的程序,通过串口调试助手下发任意个字符,单片机接收到后在末尾添加“回车+换行”符后再送回,在调试助手上重新显示

出来,先把程序贴出来。

程序中需要注意的一点是:因为平常都是将485 设置为接收状态,只有在发送数据的时候才将485 改为发送状态,所以在 UartWrite() 函数开头将 485 方向引脚拉高,函数退出前再拉低。但是这里有一个细节,就是单片机的发送和接收中断产生的时刻都是在停止位的一半上,也

就是说每当停止位传送了一半的时候,RI或TI就已经置位并且马上进入中断(如果中断使

能的话)函数了,接收的时候自然不会存在问题,但发送的时候就不一样了:当紧接这向

SBUF写入一个字节数据时,UART硬件会在完成上一个停止位的发送后,再开始新字节的

发送,但如果此时不是继续发送下一个字节,而是已经发送完毕了,要停止发送并将485方向引脚拉低以使485 重新处于接收状态时就有问题了,因为这时候最后的这个停止位实际

只发送了一半,还没有完全完成,所以就有了UartWrite() 函数内 DelayX10us(5)这个操作,这是人为的增加了延时50us ,这 50us 的时间正好让剩下的一半停止位完成,那么这个时

间自然就是由通信波特率决定的了,为波特率周期的一半。

/***********************RS485.c文件程序源代码*************************/

#include

#include

sbit RS485_DIR = P1^7; //RS485方向选择引脚

bit flagOnceTxd = 0; //单次发送完成标志,即发送完一个字节

bit cmdArrived = 0;// 命令到达标志,即接收到上位机下发的命令

unsigned char cntRxd = 0;

unsigned char pdata bufRxd[40]; //串口接收缓冲区

void ConfigUART(unsigned int baud) //串口配置函数,baud 为波特率

{

RS485_DIR = 0; //RS485设置为接收方向

SCON = 0x50;//配置串口为模式1

TMOD &= 0x0F; //清零T1的控制位

TMOD |= 0x20; //配置T1为模式2

TH1 = 256 - (11059200/12/32) / baud; //

计算 T1 重载值

TL1 = TH1;// 初值等于重载值

ET1 = 0;// 禁止 T1 中断

ES = 1;//使能串口中断

TR1 = 1;//启动 T1

}

unsigned char UartRead(unsigned char *buf, unsigned char len) //

串口数据读取函数,数

据接收指针buf ,读取数据长度len ,返回值为实际读取到的数据长度

{

unsigned char i;

if (len > cntRxd) //读取长度大于接收到的数据长度时,

{

len = cntRxd; //读取长度设置为实际接收到的数据长度

}

for (i=0; i

{

*buf = bufRxd[ i];

buf++;

}

cntRxd = 0; // 清零接收计数器

return len; // 返回实际读取长度

}

void DelayX10us(unsigned char t) //软件延时函数,延时时间(t*10)us

{

do {

_nop_();

_nop_();

_nop_();

_nop_();

_nop_();

_nop_();

_nop_();

_nop_();

} while (--t);

}

void UartWrite(unsigned char *buf, unsigned char len) // 串口数据写入函数,即串口发送函数,待发送数据指针 buf ,数据长度 len

{

RS485_DIR = 1; //RS485设置为发送

while (len--)//发送数据

{

flagOnceTxd = 0;

SBUF = *buf;

buf++;

while (!flagOnceTxd);

}

DelayX10us(5); // 等待最后的停止位完成,延时时间由波特率决定

RS485_DIR = 0; //RS485 设置为接收

}

void UartDriver() //串口驱动函数,检测接收到的命令并执行相应动作

{

unsigned char len;

unsigned char buf[30];

if (cmdArrived) //有命令到达时,读取处理该命令

{

cmdArrived = 0;

len = UartRead(buf, sizeof(buf)-2); //将接收到的命令读取到缓冲区中

buf[len++] = '\r';//在接收到的数据帧后添加换车换行符后发回

buf[len++] = '\n';

UartWrite(buf, len);

}

}

void UartRxMonitor(unsigned char ms) //串口接收监控函数

{

static unsigned char cntbkp = 0;

static unsigned char idletmr = 0;

if (cntRxd > 0) //接收计数器大于零时,监控总线空闲时间

{

if (cntbkp != cntRxd) //接收计数器改变,即刚接收到数据时,清零空闲计时{

cntbkp = cntRxd;

idletmr = 0;

}

else

{

if (idletmr < 30) //接收计数器未改变,即总线空闲时,累积空闲时间

{

idletmr += ms;

if (idletmr >= 30) //空闲时间超过30ms 即认为一帧命令接收完毕

{

cmdArrived = 1; //设置命令到达标志

}

}

}

}

else

{

cntbkp = 0;

}

}

void InterruptUART() interrupt 4 //UART中断服务函数

{

if (RI) // 接收到字节

{

RI = 0;//手动清零接收中断标志位

if (cntRxd < sizeof(bufRxd)) //接收缓冲区尚未用完时,

{

bufRxd[cntRxd++] = SBUF; //保存接收字节,并递增计数器}

}

if (TI) // 字节发送完毕

{

TI = 0;//手动清零发送中断标志位

flagOnceTxd = 1; //设置单次发送完成标志

}

}

/***********************main.c文件程序源代码*************************/ #include

unsigned char T0RH = 0; //T0重载值的高字节

unsigned char T0RL = 0; //T0重载值的低字节

void ConfigTimer0(unsigned int ms);

extern void ConfigUART(unsigned int baud);

extern void UartRxMonitor(unsigned char ms);

extern void UartDriver();

void main ()

{

EA = 1;// 开总中断

ConfigTimer0(1); //配置T0定时1ms

ConfigUART(9600); //配置波特率为9600

while(1)

{

UartDriver();

}

}

void ConfigTimer0(unsigned int ms) //T0配置函数

{

unsigned long tmp;

tmp = 11059200 / 12;//定时器计数频率

tmp = (tmp * ms) / 1000; //计算所需的计数值

tmp = 65536 - tmp;//计算定时器重载值

tmp = tmp + 34;// 修正中断响应延时造成的误差

T0RH = (unsigned char)(tmp >> 8); //定时器重载值拆分为高低字节

T0RL = (unsigned char)tmp;

TMOD &= 0xF0;// 清零 T0 的控制位

TMOD |= 0x01;//配置T0为模式1

TH0 = T0RH;// 加载T0 重载值

TL0 = T0RL;

ET0 = 1;// 使能T0 中断

TR0 = 1;//启动T0

}

void InterruptTimer0() interrupt 1 //T0中断服务函数

{

TH0 = T0RH; //定时器重新加载重载值

TL0 = T0RL;

UartRxMonitor(1); //串口接收监控

}

现在看这种串口程序,是不是感觉很简单了呢?串口通信程序我们反反复复的使用,加

上随着我们学习的模块越来越多,实践的越来越多,原先感觉很复杂的东西,现在就会感到

简单了。我们的下载程序模块用的是COM4,而 USB转 485 虚拟的是COM5,通信的时候我

们用的是COM5口,如图18-3所示。

图18-3 RS485 串行通信

18.2 Modbus通信协议介绍

我们前边学习UART、I 2C 、SPI 这些通信协议,都是最底层的协议,是“位”级别的协议。

而我们在学习13 章实用串口通信程序的时候,我们通过串口发给单片机三条指令,让单片

机做了三件不同的事情,分别是"buzz on" 、 "buzz off" 、和 "showstr" 。随着我们系统复杂性

的增加,我们希望可以实现更多的指令。而指令越来越多,带来的后果就是非常杂乱无章,

尤其是这个人喜欢写成 "buzz on" 、"buzz off" ,而另外一个人喜欢写成"on buzz" 、"off buzz" 。导致不同开发人员写出来的代码指令不兼容,不同厂家的产品不能挂到一条总线上通信。

随着这种矛盾的日益严重,就会有聪明人提出更合理的解决方案,提出一些标准来,今后我们的编程必须按照这个标准来,这种标准也是一种通信协议,但是和UART 、I 2C、SPI 通信协议不同的是,这种通信协议是字节级别的,叫做应用层通信协议。在1979 年由Modicon(现为施耐德电气公司的一个品牌) 提出了全球第一个真正用于工业现场总线的协

议,就是Modbus 协议。

18.2.1 Modbus协议特点

Modbus协议是应用于电子控制器上的一种通用语言。通过此协议,控制器相互之间、控制

器经由网络 ( 例如以太网 ) 和其他设备之间可以通信,已经成为一种工业标准。有了它,不

同厂商生产的控制设备可以连成工业网络,进行集中监控。这种协议定义了一种控制器能够

认识使用的数据结构,而不管它们是经过何种网络进行通信的。它描述了控制器请求访问其

他设备的过程,如何回应来自其他设备的请求,以及怎样侦测错误记录,它制定了通信数据

的格局和内容的公共格式。

在进行多机通信的时候,Modbus 协议规定每个控制器必须要知道他们的设备地址,识别按

照地址发送过来的数据,决定是否要产生动作,产生何种动作,如果要回应,控制器将生成

的反馈信息用Modbus 协议发出。

Modbus协议允许在各种网络体系结构内进行简单通信,每种设备(PLC、人机界面、控制面板、驱动程序、输入输出设备) 都能使用Modbus 协议来启动远程操作,一些网关允许在几

种使用 Modbus 协议的总线或网络之间的通信,如图18-4 所示。

图18-4 Modbus 网络体系结构实例

Modbus 协议的整体架构和格式比较复杂和庞大,在我们的课程里,我们重点介绍数据帧结构和数据通信控制方式,作为一个入门级别的了解。如果大家要详细了解,或者使用 Modbus 开发相关设备,可以查阅相关的国标文件再进行深入学习。

1.2.2 RTU协议帧数据

Modbus 有两种通信传输方式,一种是 ASCII 模式,一种是 RTU 模式。由于 ASCII 模式的数据字节是7bit 数据位,51 单片机无法实现,而且应用也相对较少,所以这里我们只用RTU 模式。两种模式相似,会用一种另外一种也就会了。一条典型的 RTU 数据帧如图 18-5 所示。

图18-5 RTU 数据帧

和我们实用串口通信程序类似,我们一次发送的数据帧必须是作为一个连续的数据流进行传

输。我们在实用串口通信程序中采用的方法是定义30ms,如果接收到的数据超过了30ms 还没有接收到下一个字节,我们就认为这次的数据结束。而Modbus 的 RTU 模式规定不同数据帧之间的间隔是 3.5 个字节通信时间以上。如果在一帧数据完成之前有超过 3.5个字节时间的停顿,接收设备将刷新当前的消息并假定下一个字节是一个新的数据帧的开始。同样的,如果一个新消息在小于 3.5 个字节时间内接着前边一个数据开始的,接收的设备将会认

为它是前一帧数据的延续。这将会导致一个错误,因此大家看RTU 数据帧最后还有16bit 的 CRC 校验。

起始位和结束符:图 18-5 上代表的是一个数据帧,前后都至少有3.5个字节的时间间隔,起始位和结束符实际上没有任何数据,T1-T2-T3-T4 代表的是时间间隔 3.5个字节以上的时间,而真正有意义的第一个字节是设备地址。

设备地址:很多同学不理解,在多机通信的时候,数据那么多,我们依靠什么判断这个数据

帧是哪个设备的呢?没错,就是依靠这个设备地址字节。每个设备都有一个自己的地址,当设备接收到一帧数据后,程序首先对设备地址字节进行判断比较,如果与自己的地址不同,

则对这帧数据直接不予理会,如果如果与自己的地址相同,就要对这帧数据进行解析,按照之后的功能码执行相应的功能。如果地址是0x00,则认为是一个广播命令,就是所有的从

机设备都要执行的指令。

功能代码:在第二个字节功能代码字节中,Modbus 规定了部分功能代码,此外也保留了一

部分功能代码作为备用或者用户自定义,这些功能码大家不需要去记忆,甚至都不用去看,

直到你有用到的那天再过来查这个表格即可,如表18-1 所示。

表18-1 Modbus 功能码

功能码名称作用

01读取线圈状态

取得一组逻辑线圈的当前状态(ON/OFF)

02

03

04

05

06

07

08

09

10

11

12

13

14

15

16

17

18

19

20

21

读取输入状态取得一组开关输入的当前状态(ON/OFF)

读取保持寄存器在一个或多个保持寄存器中取得当前的二进制值

读取输入寄存器在一个或多个输入寄存器中取得当前的二进制值

强置单线圈强置一个逻辑线圈的通断状态

预置单寄存器把具体二进值装入一个保持寄存器

读取异常状态

取得 8 个内部线圈的通断状态,这8 个线圈的地址由控制器决定,

可以将这些线圈定义,以说明从机状态,短报文适宜于迅速读取状回送诊断校验把诊断校验报文送从机,以对通信处理进行评鉴

编程 ( 只用于 484)使主机模拟编程器作用,修改PC 从机逻辑

控询 ( 只用于 484)

可使主机与一台正在执行长程序任务从机通信,探询该从机是否已

任务,仅在含有功能码9 的报文发送后,本功能码才发送读取事件计数

可使主机发出单询问,并随即判定操作是否成功,尤其是该命令或

生通信错误时

读取通信事件记录

可是主机检索每台从机的ModBus 事务处理通信事件记录。如果某

完成,记录会给出有关错误

编程 (184/384 484 584 )可使主机模拟编程器功能修改PC 从机逻辑

探询 (184/384 484 584)

可使主机与正在执行任务的从机通信,定期控询该从机是否已完成其

仅在含有功能 13 的报文发送后,本功能码才得发送

强置多线圈强置一串连续逻辑线圈的通断

预置多寄存器把具体的二进制值装入一串连续的保持寄存器

报告从机标识可使主机判断编址从机的类型及该从机运行指示灯的状态

884 和 MICRO 84可使主机模拟编程功能,修改PC 状态逻辑

重置通信链路发生非可修改错误后,是从机复位于已知状态,可重置顺序字节读取通用参数 (584L)显示扩展存储器文件中的数据信息

写入通用参数 (584L)把通用参数写入扩展存储文件,或修改

22~64保留作扩展功能备用

65~72保留以备用户功能所用留作用户功能的扩展编码

73~119非法功能

120~127保留留作内部作用

128~255保留用于异常应答

我们程序对功能码的处理,就是程序来检测这个字节的数值,然后根据其数值来做相应

的功能处理。

数据:跟在功能代码后边的是n 个 8bit 的数据。这个n 值的到底是多少,是功能代码来确

定的,不同的功能代码后边跟的数据数量不同。举个例子,如果功能码是0x03,也就是读保持寄存器,那么主机发送数据n 的组成部分就是: 2 个字节的寄存器起始地址,加 2 个字节的寄存器数量N*。从机数据n 的组成部分是: 1 个字节的字节数,因为我们回复的寄存

器的值是 2 个字节,所以这个字节数也就是2N*个,再加上2N*个寄存器的值,如图18-6所示。

图 18-6 读保持寄存器数据结构

CRC 校验: CRC 校验是一种数据算法,是用来校验数据对错的。CRC 校验函数把一帧数据除最后两个字节外,前边所有的字节进行特定的算法计算,计算完后生成了一个16bit 的数据,作为 CRC 校验码,添加在一帧数据的最后。接收方接收到数据后,同样会把前边的字

节进行 CRC 计算,计算完了再和发过来的CRC 的 16bit 的数据进行比较,如果相同则认为

数据正常,没有出错,如果比较不相同,则说明数据在传输中发生了错误,这帧数据将被丢弃,就像没收到一样,而发送方会在得不到回应后做相应的处理错误处理。

RTU 模式的每个字节的位是这样分布的: 1 个起始位、 8 个数据位,最小有效位先发送、1个奇偶校验位 (如果无校验则没有这一位)、 1 位停止位 (有校验位时 )或者 2 个停止位 (无校验

位时 )。

18.3 Modbus多机通信例程

给从机下发不同的指令,从机去执行不同的操作,这个就是判断一下功能码即可,和我们前边学的实用串口例程是类似的。多机通信,无非就是添加了一个设备地址判断而已,难度也不是很大。我们找了一个Modbus 调试精灵,通过设置设备地址,读写寄存器的地址以及数

值数量等参数,可以直接替代串口调试助手,比较方便的下发多个字节的数据,如图18-7所示。我们先来就图中的设置和数据来对Modbus 做进一步的分析,图中的数据来自于调试

精灵与我们接下来要讲的例程之间的交互。

图18-7 Modbus 调试精灵

如图:我们的 USB 转 485 模块虚拟出的是COM5 ,波特率 9600,无校验位,数据位是 8 位,1 位停止位,设备地址假设为1。

写寄存器的时候,如果我们要把01 写到一个地址是0000 的寄存器地址里,点一下“写入” ,就会出现发送指令: 01 06 00 00 00 01 48 0A 。我们来分析一下这帧数据,其中01 是设备地址, 06 是功能码,代表写寄存器这个功能,后边跟00 00 表示的是要写入的寄存器的地址,00 01 就是要写入的数据, 48 0A 就是 CRC 校验码,这是软件自动算出来了。而根据 Modbus 协议,当写寄存器的时候,从机成功完成该指令的操作后,会把主机发送的指令直接返回,

我们的调试精灵会接收到这样一帧数据:010600000001480A。

假如我们现在要从寄存器地址0002 开始读取寄存器,并且读取的数量是 2 个。点一下“读出”,就会出现发送指令:01 03 00 02 00 02 65 CB 。其中 01 是设备地址, 03 是功能码,代

表写寄存器这个功能,00 02就是读寄存器的起始地址,后一个00 02就是要读取 2 个寄存器的数值,65 CB就是CRC校验。而接收到的数据是:01 03 04 00 00 00 00 FA 33。其中01是设备地址,03 是功能码,04 代表的是后边读到的数据字节数是4个,00000000分别是地址为00 02和00 03的寄存器内部的数据,而FA 33就是CRC 校验了。

似乎越来越明朗了,所谓的Modbus 这种通信协议,无非就是主机下发了不同的指令,从机

根据指令的判断来执行不同的操作而已。由于我们的开发板没有Modbus 功能码那么多相应

的功能,我们在程序中定义了一个数组regGroup[5] ,相当于 5 个寄存器,此外又定义了第

6个寄存器,控制蜂鸣器,通过下发不同的指令我们改变寄存器组的数据或者改变蜂鸣器的

开关状态。在Modbus 协议里寄存器的地址和数值都是16 位的,即 2 个字节,我们默认高

字节是0x00,低字节就是数组 regGroup 对应的值。其中地址 0x0000 到 0x0004 对应的就

是 regGroup 数组中的元素,我们写入的同时把数字又显示到我们的LCD1602 液晶上,而0x0005这个地址,写入 0x00,蜂鸣器就不响,写入任何其他数字,蜂鸣器就报警。我们单

片机的主要工作也就是解析串口接收的数据执行不同操作,也就是主要在RS485.C 这个文件中了

/***********************RS485.c文件程序源代码*************************/

#include

#include

sbit RS485_DIR = P1^7; //RS485方向选择引脚

bit flagOnceTxd = 0; //单次发送完成标志,即发送完一个字节

bit cmdArrived = 0;// 命令到达标志,即接收到上位机下发的命令

unsigned char cntRxd = 0;

unsigned char pdata bufRxd[40]; //串口接收缓冲区

unsigned char regGroup[5]; //Modbus寄存器组,地址为0x00 ~0x04

extern bit flagBuzzOn;

extern void LcdShowStr(unsigned char x, unsigned char y, const unsigned char *str);

extern unsigned int GetCRC16(unsigned char *ptr, unsigned char len);

void ConfigUART(unsigned int baud) //串口配置函数,baud 为波特率

{

RS485_DIR = 0; //RS485设置为接收方向

SCON = 0x50;//配置串口为模式1

TMOD &= 0x0F; //清零T1的控制位

TMOD |= 0x20; //配置T1为模式2

TH1 = 256 - (11059200/12/32) / baud; //

计算T1重载值

TL1 = TH1;// 初值等于重载值

ET1 = 0;// 禁止 T1 中断

ES =1; TR1 = 1;//使能串口中断//启动 T1

}

unsigned char UartRead(unsigned char *buf, unsigned char len) //

据接收指针buf ,读取数据长度len ,返回值为实际读取到的数据长度

{

串口数据读取函数,数unsigned char i;

if (len > cntRxd) //读取长度大于接收到的数据长度时,

{

len = cntRxd; //读取长度设置为实际接收到的数据长度

}

for (i=0; i

{

*buf = bufRxd[ i];

buf++;

}

cntRxd = 0; // 清零接收计数器

return len; // 返回实际读取长度

}

void DelayX10us(unsigned char t) //软件延时函数,延时时间(t*10)us

{

do {

_nop_();

_nop_();

_nop_();

_nop_();

_nop_();

_nop_();

_nop_();

_nop_();

} while (--t);

}

void UartWrite(unsigned char *buf, unsigned char len) // 串口数据写入函数,即串口发送函数,待发送数据指针 buf ,数据长度 len

{

RS485_DIR = 1; //RS485设置为发送

while (len--)//发送数据

{

flagOnceTxd = 0;

SBUF = *buf;

buf++;

while (!flagOnceTxd);

}

DelayX10us(5); //等待最后的停止位完成,延时时间由波特率决定

RS485_DIR = 0; //RS485设置为接收

}

void UartDriver() //串口驱动函数,检测接收到的命令并执行相应动作

{

unsigned char i;

unsigned char cnt;

unsigned char len;

unsigned char buf[30];

unsigned char str[4];

unsigned int crc;

unsigned char crch, crcl;

if (cmdArrived) //有命令到达时,读取处理该命令

{

cmdArrived = 0;

len = UartRead(buf, sizeof(buf)); //将接收到的命令读取到缓冲区中

if (buf[0] == 0x01) //核对地址以决定是否响应命令,本例本机地址为0x01

{

crc = GetCRC16(buf, len-2); //计算CRC校验值

crch = crc >> 8;

crcl = crc & 0xFF;

if ((buf[len-2] == crch) && (buf[len-1] == crcl)) //判断CRC校验是否正确

{

switch (buf[1]) //按功能码执行操作

{

case 0x03: //读取一个或连续的寄存器

if ((buf[2] == 0x00) && (buf[3] <= 0x05)) //寄存器地址支持0x0000 ~0x0005

{

if (buf[3] <= 0x04)

{

i = buf[3];// 提取寄存器地址

cnt = buf[5];//提取待读取的寄存器数量

buf[2] = cnt*2; //读取数据的字节数,为寄存器数*2,因Modbus 定义的寄存器为16 位

len = 3;

while (cnt--)

{

buf[len++] = 0x00;// 寄存器高字节补0

buf[len++] = regGroup[ i++]; //低字节

}

}

else // 地址 0x05 为蜂鸣器状态

{

buf[2] = 2; //读取数据的字节数

buf[3] = 0x00;

buf[4] = flagBuzzOn;

len = 5;

}

break;

}

else // 寄存器地址不被支持时,返回错误码

{

buf[1] = 0x83; //功能码最高位置1

buf[2] = 0x02; //设置异常码为02-无效地址

len = 3;

break;

}

case 0x06: //写入单个寄存器

if ((buf[2] == 0x00) && (buf[3] <= 0x05)) //寄存器地址支持0x0000 ~0x0005

{

if (buf[3] <= 0x04)

{

i = buf[3];// 提取寄存器地址

regGroup[ i] = buf[5];//保存寄存器数据

cnt = regGroup[ i] >> 4; //显示到液晶上

if (cnt >= 0xA)

str[0] = cnt - 0xA + 'A';

else

str[0] = cnt + '0';

cnt = regGroup[ i] & 0x0F;

if (cnt >= 0xA)

str[1] = cnt - 0xA + 'A';

else

str[1] = cnt + '0';

str[2] = '\0';

LcdShowStr(i*3, 0, str);

}

else // 地址 0x05 为蜂鸣器状态

{

flagBuzzOn = (bit)buf[5]; //寄存器值转换为蜂鸣器的开关

}

len -= 2; // 长度 -2 以重新计算CRC并返回原帧

break;

}

else // 寄存器地址不被支持时,返回错误码

{

buf[1] = 0x86;//功能码最高位置1

buf[2] = 0x02;//设置异常码为02-无效地址

len = 3;

break;

}

default: // 其它不支持的功能码

buf[1] |= 0x80; //功能码最高位置buf[2] = 0x01;//设置异常码为len = 3;

break;

1

01-无效功能

}

crc = GetCRC16(buf, len); //计算CRC校验值

buf[len++] = crc >> 8;//CRC 高字节

buf[len++] = crc & 0xFF; //CRC低字节

UartWrite(buf, len);// 发送响应帧

}

}

}

}

void UartRxMonitor(unsigned char ms) //串口接收监控函数

{

static unsigned char cntbkp = 0;

static unsigned char idletmr = 0;

if (cntRxd > 0) //接收计数器大于零时,监控总线空闲时间

{

if (cntbkp != cntRxd) //接收计数器改变,即刚接收到数据时,清零空闲计时

{

cntbkp = cntRxd;

idletmr = 0;

}

else

{

if (idletmr < 5) //接收计数器未改变,即总线空闲时,累积空闲时间

{

idletmr += ms;

if (idletmr >= 5) //空闲时间超过 4 个字节传输时间即认为一帧命令接收完毕

{

cmdArrived = 1; //设置命令到达标志

}

多机通信协议规范

通信协议 来自中国工控网 所谓通信协议是指通信双方的一种约定。约定包括对数据格式、同步方式、传送速度、传送步骤、 检纠错方式以及控制字符定义等问题做出统一规定,通信双方必须共同遵守。因此,也叫做通信控制规程,或称传输控制规程,它属于ISO'S OSI七层参考模型中的数据链路层。 目前,采用的通信协议有两类:异步协议和同步协议。同步协议又有面向字符和面向比特以及面向 字节计数三种。其中,面向字节计数的同步协议主要用于DEC公司的网络体系结构中。 串行通讯简单认识 串行通讯的基本概念:与外界的信息交换称为通讯。基本的通讯方式有并行通讯和串行通讯两种。 一条信息的各位数据被同时传送的通讯方式称为并行通讯。并行通讯的特点是:各数据位同时传送,传送速度快、效率高,但有多少数据位就需多少根数据线,因此传送成本高,且只适用于近距离(相距 数米)的通讯。 一条信息的各位数据被逐位按顺序传送的通讯方式称为串行通讯。串行通讯的特点是:数据位传送,传按位顺序进行,最少只需一根传输线即可完成,成本低但送速度慢。串行通讯的距离可以从几米到几 千米。 根据信息的传送方向,串行通讯可以进一步分为单工、半双工和全双工三种。信息只能单向传送为 单工;信息能双向传送但不能同时双向传送称为半双工;信息能够同时双向传送则称为全双工。 串行通讯又分为异步通讯和同步通讯两种方式。在单片机中,主要使用异步通讯方式。 MCS_51单片机有一个全双工串行口。全双工的串行通讯只需要一根输出线和一根输入线。数据的输 出又称发送数据(TXD),数据的输入又称接收数据(RXD)。串行通讯中主要有两个技术问题,一个是数 据传送、另一个是数据转换。数据传送主要解决传送中的标准、格式及工作方式等问题。数据转换是指 数据的串并行转换。具体说,在发送端,要把并行数据转换为串行数据;而在接收端,却要把接收到的 串行数据转换为并行数据。 单工、半双工和全双工的定义 如果在通信过程的任意时刻,信息只能由一方A传到另一方B,则称为单工。 如果在任意时刻,信息既可由A传到B,又能由B传A,但只能由一个方向上的传输存在,称为半双工传输如果在任意时刻,线路上存在A到B和B到A的双向信号传输,则称为全双工。 电话线就是二线全双工信道。由于采用了回波抵消技术,双向的传输信号不致混淆不清。双工信道有时也发信道分开,采用分离的线路或频带传输相反方向的信号,如回线传输。 --------> <--------> --------> A---------B A----------B A---------B <-------- 单工半双工全双工

手把手教你STC51的ISP下载线

手把手教你STC51的ISP下载线 说起我从认识学习使用C51单片机到现在有两年多,时间不长,菜鸟一只。从用TOP151烧写AT89C51,到用easy51pro在线编程AT89S51,再到用STC-ISP 软件在线编程STC89C51,最后现在变得越来越懒,干脆用protues仿真单片机外围电路。 现在简单的总结一下,入门级的C51学习在没有昂贵的单片机仿真器情况下,怎样算是方便调试又花费少吧。 先说说AT89C51,噢,差点忘了,这型号的单片机不知何年被停产了,现在就靠它的库存仍在这个历史的舞台上挣扎。 缺点:对入土为安的芯片没什么好说了。 那就说AT89S51,这可是一个令人振奋的产物,最大的特点莫过于它的ISP(在线编程)功能,就是使用者每编译好程序,就可以立即通过ISP下载线写到单片机上去。而且ISP下载线的制作简单令单片机和我们的距离更加接近了。它的ISP原理图如下:

其中ISP下载程序可以用easy 51pro v2.0。相比昂贵的仿真器,做上图的元器件总共也就十块钱左右吧。 缺点:一、并口连接电脑,1.可能占用打印机口;2.是笔记本是没有并口的。 二、下载线制作一次成功率不大,不是漏接了这个脚就是那个口,对于新手而言尤其这样。 三、下载线寿命不长,一两次不知明的原因(通常静电),就可以把里面的那块芯片(74LS244)烧坏。并且,实际你都不知道到底哪里出毛病了。 也许,世界上真的没有最好,只要更好,自从好友张JL和陈Y介绍了STC的51系列单片机给我之后,发现竟然有这么方便好用功能强大的单片机。

STC51单片机的型号跟ATMEL的大致一样,有STC89C51,C52等,对应于AT89C51,C52等对应它们的内部RAM内部ROM中断口等,是完全一样的。 当然,STC系列单片机是改进型的单片机,它的热重启,串口ISP等功能确实为我准备介绍给大家提供了理由。 先说说ISP功能,它跟电脑连接就只有三根线,就是通过RS-232传输。它ISP 过程是这样的:冷重启(上电)-单片机运行系统ISP监控程序(出厂时已烧到里面)-检测P3.0/RXD有没有合法下载命令流,有的话,就下载用户程序进户程序区;没有的话,就跳到用户程序区,运行用户程序。所以,第一次下载程序,用户需要先点ISP下载软件的“download”,再把单片机通电。如图: 到了这里,大家不禁会说,下载线虽然简单,但每次都要断电上电,烦不烦?答:我都觉得烦。不过眼睛锐利的读者发现了上图右下片有一段文字。说什么的呢?哦,原来是自定义下载。什么是自定义下载?首先我先说个高兴的事儿——用自定义下载,从此告别断电上电的冷重启ISP下载。 所谓自定义下载,就是我从上面软件的自定义下载命令文本框中打入十六进制数字(如:FEH)然后点击发送,程序自动下载到用户单片机里。神奇吧。究其不用断电上电冷重启的原因,就是上面我所说的STC单片机具有热重启功能。用户只需简单控制ISP_CONTOR特殊功能寄存器即可实现系统复位了。汇编语

设计单片机通讯协议论文(非常经典)

如何设计单片机常用通信 协议论文

目录 1.自定义数据通信协议 (3) 2.上位机和下位机中的数据发送 (3) 3.下位机中的数据接收和协议解析 (4) 4.上位机中的数据接收和命令处理 (8) 5.总结 (9)

单片机通信协议现在大部分的仪器设备都要求能过通过上位机软件来操作,这样方便调试,利于操作。其中就涉及到通信的过程。在实际制作的几个设备中,笔者总结出了通信程序的通用写法,包括上位机端和下位机端等。 1.自定义数据通信协议 这里所说的数据协议是建立在物理层之上的通信数据包格式。所谓通信的物理层就是指我们通常所用到的RS232、RS485、红外、光纤、无线等等通信方式。在这个层面上, 底层软件提供两个基本的操作函数:发送一个字节数据、接收一个字节数据。所有的数据协议全部建立在这两个操作方法之上。通信中的数据往往以数据包的形式进行传送的,我们把这样的一个数据包称作为一帧数据。类似于网络通信中的TCPIP协议一般,比较可靠的通信协议往往包含有以下几个组成部分:帧头、地址信息、数据类型、数据长度、数据块、校验码、帧尾。 帧头和帧尾用于数据包完整性的判别,通常选择一定长度的固定字节组成,要求是在整个数据链中判别数据包的误码率越低越好。减小固定字节数据的匹配机会,也就是说使帧头和帧尾的特征字节在整个数据链中能够匹配的机会最小。通常有两种做法,一、减小特征字节的匹配几率。二、增加特征字节的长度。通常选取第一种方法的情况是整个数据链路中的数据不具有随即性,数据可预测,可以通过人为选择帧头和帧尾的特征字来避开,从而减小特征字节的匹配几率。使用第二种方法的情况更加通用,适合于数据随即的场合。通过增加特征字节的长度减小匹配几率,虽然不能够完全的避免匹配的情况,但可以使匹配几率大大减小,如果碰到匹配的情况也可以由校验码来进行检测,因此这种情况在绝大多说情况下比较可靠。 地址信息主要用于多机通信中,通过地址信息的不同来识别不同的通信终端。在一对多的通信系统中,可以只包含目的地址信息。同时包含源地址和目的地址则适用于多对多的通信系统。 数据类型、数据长度和数据块是主要的数据部分。数据类型可以标识后面紧接着的是命令还是数据。数据长度用于指示有效数据的个数。 校验码则用来检验数据的完整性和正确性。通常对数据类型、数据长度和数据块三个部分进行相关的运算得到。最简单的做法可是对数据段作累加和,复杂的也可以对数据进行CR C运算等等,可以根据运算速度、容错度等要求来选取。 2.上位机和下位机中的数据发送 物理通信层中提供了两个基本的操作函数,发送一个字节数据则为数据发送的基础。数据 包的发送即把数据包中的左右字节按照顺序一个一个的发送数据而已。当然发送的方

51单片机实例程100讲全集

目录 目录 (1) 函数的使用和熟悉 (4) 实例3:用单片机控制第一个灯亮 (4) 实例4:用单片机控制一个灯闪烁:认识单片机的工作频率 (4) 实例5:将P1口状态分别送入P0、P2、P3口:认识I/O口的引脚功能 (5) 实例6:使用P3口流水点亮8位LED (5) 实例7:通过对P3口地址的操作流水点亮8位LED (6) 实例8:用不同数据类型控制灯闪烁时间 (7) 实例9:用P0口、P1 口分别显示加法和减法运算结果 (8) 实例10:用P0、P1口显示乘法运算结果 (9) 实例11:用P1、P0口显示除法运算结果 (9) 实例12:用自增运算控制P0口8位LED流水花样 (10) 实例13:用P0口显示逻辑"与"运算结果 (10) 实例14:用P0口显示条件运算结果 (11) 实例15:用P0口显示按位"异或"运算结果 (11) 实例16:用P0显示左移运算结果 (11) 实例17:"万能逻辑电路"实验 (11) 实例18:用右移运算流水点亮P1口8位LED (12) 实例19:用if语句控制P0口8位LED的流水方向 (13) 实例20:用swtich语句的控制P0口8位LED的点亮状态 (13) 实例21:用for语句控制蜂鸣器鸣笛次数 (14) 实例22:用while语句控制LED (15) 实例23:用do-while语句控制P0口8位LED流水点亮 (16) 实例24:用字符型数组控制P0口8位LED流水点亮 (17) 实例25:用P0口显示字符串常量 (18) 实例26:用P0 口显示指针运算结果 (19) 实例27:用指针数组控制P0口8位LED流水点亮 (19) 实例28:用数组的指针控制P0 口8 位LED流水点亮 (20) 实例29:用P0 、P1口显示整型函数返回值 (21) 实例30:用有参函数控制P0口8位LED流水速度 (22) 实例31:用数组作函数参数控制流水花样 (22) 实例32:用指针作函数参数控制P0口8位LED流水点亮 (23) 实例33:用函数型指针控制P1口灯花样 (25) 实例34:用指针数组作为函数的参数显示多个字符串 (26) 实例35:字符函数ctype.h应用举例 (27) 实例36:内部函数intrins.h应用举例 (27) 实例37:标准函数stdlib.h应用举例 (28) 实例38:字符串函数string.h应用举例 (29) 实例39:宏定义应用举例2 (29) 实例40:宏定义应用举例2 (29) 实例41:宏定义应用举例3 (30)

51单片机通信协议

单片机通信协议 现在大部分的仪器设备都要求能过通过上位机软件来操作,这样方便调试,利于操作。其中就涉及到通信的过程。在实际制作的几个设备中,笔者总结出了通信程序的通用写法,包括上位机端和下位机端等。 1.自定义数据通信协议 这里所说的数据协议是建立在物理层之上的通信数据包格式。所谓通信的物理层就是指我们通常所用到的RS232、RS485、红外、光纤、无线等等通信方式。在这个层面上,底层软件提供两个基本的操作函数:发送一个字节数据、接收一个字节数据。所有的数据协议全部建立在这两个操作方法之上。 通信中的数据往往以数据包的形式进行传送的,我们把这样的一个数据包称作为一帧数据。类似于网络通信中的TCPIP协议一般,比较可靠的通信协议往往包含有以下几个组成部分:帧头、地址信息、数据类型、数据长度、数据块、校验码、帧尾。 帧头和帧尾用于数据包完整性的判别,通常选择一定长度的固定字节组成,要求是在整个数据链中判别数据包的误码率越低越好。减小固定字节数据的匹配机会,也就是说使帧头和帧尾的特征字节在整个数据链中能够匹配的机会最小。通常有两种做法,一、减小特征字节的匹配几率。二、增加特征字节的长度。通常选取第一种方法的情况是整个数据链路中的数据不具有随即性,数据可预测,可以通过人为选择帧头和帧尾的特征字来避开,从而减小特征字节的匹配几率。使用第二种方法的情况更加通用,适合于数据随即的场合。通过增加特征字节的长度减小匹配几率,虽然不能够完全的避免匹配的情况,但可以使匹配几率大大减小,如果碰到匹配的情况也可以由校验码来进行检测,因此这种情况在绝大多说情况下比较可靠。 地址信息主要用于多机通信中,通过地址信息的不同来识别不同的通信终端。在一对多的通信系统中,可以只包含目的地址信息。同时包含源地址和目的地址则适用于多对多的通信系统。 数据类型、数据长度和数据块是主要的数据部分。数据类型可以标识后面紧接着的是命令还是数据。数据长度用于指示有效数据的个数。 校验码则用来检验数据的完整性和正确性。通常对数据类型、数据长度和数据块三个部分进行相关的运算得到。最简单的做法可是对数据段作累加和,复杂的也可以对数据进行CRC运算等等,可以根据运算速度、容错度等要求来选取。 2.上位机和下位机中的数据发送 物理通信层中提供了两个基本的操作函数,发送一个字节数据则为数据发送的基础。数据包的发送即把数据包中的左右字节按照顺序一个一个的发送数据而已。当然发送的方法也有不同。 在单片机系统中,比较常用的方法是直接调用串口发送单个字节数据的函数。这种方法的缺点是需要处理器在发送过程中全程参与,优点是所要发送的数据能够立即的出现在通信线路上,能够立即被接收端接收到。另外一种方法是采用中断发送的方式,所有需要发送的数据被送入一个缓冲区,利用发送中断将缓冲区中的数据发送出去。这种方法的优点是占用处理器资源小,但是可能出现需要发送的数据不能立即被发送的情况,不过这种时延相当的小。对于51系列单片机,比较倾向于采用直接发送的方式,采用中断发送的方式比较占用RAM资源,而且对比直接发送来说也没有太多的优点。以下是51系列单片机中发送单个字节的函数。 v oid SendBy te(unsigned char ch) { SBUF = ch; while(TI == 0); TI = 0; }

云龙51单片机视频教程大全

云龙51单片机视频教程简介 本视频教程是针对YL-51单片机开发板讲的配套DVD视频教程目录: 讲次内容细节 第一课如何学好单片机单片机能做什么,学习单片机需要什么,如何学好单片机技术。 第二课预备知识点亮一个发光管认识单片机由来及内部结构,单片机最小工作单元组成;单片机开发软件操作:KEIL软件开发环境认识、单片机烧录软件使用。 第三课预备知识 C51基础知识及流水灯设计简单延时程序、子程序调用、、流水灯同时蜂鸣器响、如何驱动蜂鸣器,及如何驱动继电器,集电极开路的概念及应用。 第四课数码管显示的原理,数码管的静态显示共阳、共阴数码管显示原理、带参数子程序设计。 第五课中断和定时器原理定时器工作方式介绍、重点讲述工作方式2、中断概念及中断函数写法、定时器中断应用 第六课数码管的动态显示原理及应用实现动态扫描概念及定时器、中断加深 第七课按键学习:独立按键和矩阵按键键盘检测、消抖、键盘编码、带返回值函数写法及应用 第八课数模转换(DA)工作原理及应用数字电压与模拟电压的关系、如何使用DAC0832的实成DA转换 第九课模数转换(AD)工作原理及应用模拟电压与数字电压的关系,如何使用ADC0804的实成AD转换 第十课1602液晶显示原理及实现最简单液晶工作原理、如何开始对一个没有任何概念的芯片开始单片机的操作 第十一课串口原理及应用串口通讯工作方式、重点讲述最常用的10位数据通讯、波特率概念及如何根据波特率计算定时器初值 第十二课IIC总线原理和模块化编程方法 IIC总线工作原理、目前非常通用的一种通信机制; 项目开发模块化编程方法。 第十三课红外通信原理及应用红外通信是目前应用最为广泛的通信和遥控手段。在本课程中以红外遥控为代表,具体讲解红外通信的具体过程。

51串口通信协议(新型篇)

51串口通信协议(新型篇) C51编程:这是网友牛毅编的一个C51串口通讯程序! //PC读MCU指令结构:(中断方式,ASCII码表示) //帧:帧头标志|帧类型|器件地址|启始地址|长度n|效验和|帧尾标志 //值: 'n' 'y'| 'r' | 0x01 | x | x | x |0x13 0x10 //字节数: 2 | 1 | 1 | 1 | 1 | 1 | 2 //求和: ///////////////////////////////////////////////////////////////////// //公司名称:*** //模块名:protocol.c //创建者:牛毅 //修改者: //功能描述:中断方式:本程序为mcu的串口通讯提供(贞结构)函数接口,包括具体协议部分 //其他说明:只提供对A T89c51具体硬件的可靠访问接口 //版本:1.0 //信息:QQ 75011221 ///////////////////////////////////////////////////////////////////// #include #include //预定义 //帧 #define F_ST1 0x6e //帧头标志n #define F_ST2 0x79 //帧头标志y #define F_R 0x72 //帧类型读r #define F_W 0x77 //帧类型写w #define F_D 0x64 //帧类型数据帧d #define F_B 0x62 //帧类型写回应帧b #define F_C 0x63 //帧类型重发命令帧c #define F_Q 0x71 //帧类型放弃帧q #define F_ADDR 0x31 //器件地址0-9 #define F_END 0x7a //帧尾标志z #define F_SPACE 0x30 //空标志0 #define F_ERR1 0x31 //错误标志1,flagerr 1 #define F_ERR2 0x32 //错误标志2 2 //常数 #define S_MAXBUF 16 //接收/发送数据的最大缓存量 #define FIELD_MAXBUF 48 //最小场缓存,可以大于48字节,因为协议是以20字节为

STC15W系列单片机初学者教程

目录 因为网站限制原因,其他链接都不予显示,还有联系方式都不予显示,带来不便非常抱歉 1.开始学习了 2.15W4K32S4单片机简介资料 3.单片机可以用来做什么呢? 4.单片机示例!写一个串口通讯程序,您也可以直接先从这 步开始学习 5.相关资料链接(数据手册,其他进阶例子,开拓眼界) 6.售后持续支持 7.所有下载链接汇总 一. 开始学习了 这个宝贝包含的硬件,也就是给您发货的内容包含以下东西:

1.15W4K32S4最小系统板 1块 2.转串口下载器一个2303转串口 1块用来下载程序和串口 通讯 3.白色面包板一个 1块适合搭建各种电路 4.一个霍尔传感器,制作一个霍尔电路做一个磁控开关 5.若干杜邦针;连接电路 6.彩灯3 颗若干电阻学习彩色灯控制彩色灯 7.三极管若干个电位计 1个灯亮度控制 8.提供上面所有元器件手把手教程手把手教程

这篇教程能够让您学会什么呢? 1.怎么使用 4软件编写的程序,并且使用下载程序到单片机 上面; 2.串口通讯程序,另外在电脑端使用软件进行图形化显示 程序; 如果您有兴趣的话,希望下面对您学习工作有帮助,资料有点多,但是还是值得花一些时间实际操作演示,只有自己动手了,才能体会到更多的内容。

二. 15W4K32S4单片机简介 15W4K32S4单片机是一款非常优秀的51系列单片机,很适合用来作为初学者入门单片机世界。当然单片机的世界没有最强大,只有最适合的单片机。如果你有了解过什么是51单片机和一点C语言。就可以尝试进入这款单片机。边玩边搭建更多的电路,在玩中学习。 继续往下看,将会一步一步演示给您看具体怎么是使用这款单片机。请有耐心的看下去哦,不过如果一次看不完的话,可以分多几天来操作,关键是要坚持! 那么单片机可以用来做什么呢? 目前单片机渗透到我们生活的各个领域,小到电话,玩具,手机,刷卡机,电脑键盘,彩电,冰箱,空调,电磁炉,大到汽车,工业自动控制,机器人,导弹导航装置,甚至是美国的火星车,这些设备里面都含有一个或者多个单片机。单片机的数量不仅远超过机,甚至比人类的数量还要多。可见数量之庞大,用途之广泛啊。 三. 我们掌握单片机有什么用呢?

51单片机实用汇编程序库(word)

51 单片机实用程序库 4.1 流水灯 程序介绍:利用P1 口通过一定延时轮流产生低电平 输出,以达到发光二极管轮流亮的效果。实际应用中例如:广告灯箱彩灯、霓虹灯闪烁。 程序实例(LAMP.ASM) ORG 0000H AJMP MAIN ORG 0030H MAIN: 9 MOV A,#00H MOV P1,A ;灭所有的灯 MOV A,#11111110B MAIN1: MOV P1,A ;开最左边的灯 ACALL DELAY ;延时 RL A ;将开的灯向右边移 AJMP MAIN ;循环 DELAY: MOV 30H,#0FFH D1: MOV 31H,#0FFH D2: DJNZ 31H,D2 DJNZ 30H,D1 RET END 4.2 方波输出 程序介绍:P1.0 口输出高电平,延时后再输出低电 平,循环输出产生方波。实际应用中例如:波形发生器。 程序实例(FAN.ASM): ORG 0000H MAIN: ;直接利用P1.0 口产生高低电平地形成方波////////////// ACALL DELAY SETB P1.0 ACALL DELAY 10 CLR P1.0 AJMP MAIN ;////////////////////////////////////////////////// DELAY: MOV R1,#0FFH DJNZ R1,$ RET

五、定时器功能实例 5.1 定时1 秒报警 程序介绍:定时器1 每隔1 秒钟将p1.o 的输出状态改变1 次,以达到定时报警的目的。实际应用例如:定时报警器。程序实例(DIN1.ASM): ORG 0000H AJMP MAIN ORG 000BH AJMP DIN0 ;定时器0 入口 MAIN: TFLA G EQU 34H ;时间秒标志,判是否到50 个 0.2 秒,即50*0.2=1 秒 MOV TMOD,#00000001B;定时器0 工作于方式 1 MOV TL0,#0AFH MOV TH0,#3CH ;设定时时间为0.05 秒,定时 20 次则一秒 11 SETB EA ;开总中断 SETB ET0 ;开定时器0 中断允许 SETB TR0 ;开定时0 运行 SETB P1.0 LOOP: AJMP LOOP DIN0: ;是否到一秒//////////////////////////////////////// INCC: INC TFLAG MOV A,TFLAG CJNE A,#20,RE MOV TFLAG,#00H CPL P1.0 ;////////////////////////////////////////////////// RE: MOV TL0,#0AFH MOV TH0,#3CH ;设定时时间为0.05 秒,定时 20 次则一秒 RETI END 5.2 频率输出公式 介绍:f=1/t s51 使用12M 晶振,一个周期是1 微秒使用定时器1 工作于方式0,最大值为65535,以产生200HZ 的频率为例: 200=1/t:推出t=0.005 秒,即5000 微秒,即一个高电

单片机通信协议处理解析

单片机通信协议处理 现在大部分的仪器设备都要求能过通过上位机软件来操作,这样方便调试,利于操作。其中就涉及到通信的过程。在实际制作的几个设备中,笔者总结出了通信程序的通用写法,包括上位机端和下位机端等 1. 自定义数据通信协议 这里所说的数据协议是建立在物理层之上的通信数据包格式。所谓通信的物理层就是指我们通常所用到的 RS232、 RS485、红外、光纤、无线等等通信方式。在这个层面上,底层软件提供两个基本的操作函数:发送一个字节数据、接收一个字节数据。所有的数据协议全部建立在这两个操作方法之上。 通信中的数据往往以数据包的形式进行传送的,我们把这样的一个数据包称作为一帧数据。类似于网络通信中的 TCPIP 协议一般,比较可靠的通信协议往往包含有以下几个组成部分:帧头、地址信息、数据类型、数据长度、数据块、校验码、帧尾。 帧头和帧尾用于数据包完整性的判别,通常选择一定长度的固定字节组成,要求是在整个数据链中判别数据包的误码率越低越好。减小固定字节数据的匹配机会,也就是说使帧头和帧尾的特征字节在整个数据链中能够匹配的机会最小。通常有两种做法,一、减小特征字节的匹配几率。二、增加特征字节的长度。通常选取第一种方法的情况是整个数据链路中的数据不具有随即性,数据可预测,可以通过人为选择帧头和帧尾的特征字来避开,从而减小特征字节的匹配几率。使用第二种方法的情况更加通用,适合于数据随即的场合。通过增加特征字节的长度减小匹配几率,虽然不能够完全的避免匹配的情况,但可以使匹配几率大大减小,如果碰到匹配的情况也可以由校验码来进行检测,因此这种情况在绝大多说情况下比较可靠。 地址信息主要用于多机通信中,通过地址信息的不同来识别不同的通信终端。在一对多的通信系统中,可以只包含目的地址信息。同时包含源地址和目的地址则适用于多对多的通信系统。

单片机百度盘资料

一、51单片机 1、祥云51单片机学习光盘(视频教程、例程、操作系统)适合初学者 资料下载链接:https://https://www.doczj.com/doc/da13522790.html,/cJzLQdrBfp2KD 访问密码8f77 2、普中51单片机学习光盘 https://www.doczj.com/doc/da13522790.html,/s/1pK0c4BL 3、郭天祥----十天征服单片机 https://www.doczj.com/doc/da13522790.html,/s/1i4N2Hrn 4、新概念51单片机C语言教程.入门、提高、开发(500页,郭天祥著) https://https://www.doczj.com/doc/da13522790.html,/cYAYJtgFJNUup 访问密码9eb1 5、力天电子51单片机视频教程 https://www.doczj.com/doc/da13522790.html,/s/1hrulifU 6、天狼星51单片机视频教程 链接:https://www.doczj.com/doc/da13522790.html,/s/1pKsD3b9 密码:scy4 8、STC12C5A60S2例程 https://https://www.doczj.com/doc/da13522790.html,/cjPpH7uBBbIr8 访问密码a471 二、AVR单片机 1、郭天祥--十天学会AVR单片机视频教程 https://https://www.doczj.com/doc/da13522790.html,/cwVbV5mWw9pxk 访问密码34ba 1、锐志电子AVR单片机视频教程

https://https://www.doczj.com/doc/da13522790.html,/cweRHU4JUSypY 访问密码64b2 2、手把手AVR单片机视频教程 https://https://www.doczj.com/doc/da13522790.html,/cm926G3YrWKhG 访问密码dccb 3、DY_miniAVR单片机光盘资料 https://https://www.doczj.com/doc/da13522790.html,/c3fIFUrWu4LEG 访问密码0036 4、AVR代码生成器 https://https://www.doczj.com/doc/da13522790.html,/c3fILqj5h3aT9 访问密码2061 5、AVR开发工具 https://https://www.doczj.com/doc/da13522790.html,/c3fI3satMGmSh 访问密码d356 6、AVR例程 https://https://www.doczj.com/doc/da13522790.html,/c3fIFfSgCzhWE 访问密码48c1 三、msp430单片机 1、郭天祥---十天学会msp430单片机 https://https://www.doczj.com/doc/da13522790.html,/cYAYvyxDBaHgr 访问密码4dca 2、力天msp430单片机视频教程 https://https://www.doczj.com/doc/da13522790.html,/cYAY83HwRumTn 访问密码d66c 3、msp430 c语言.pdf https://https://www.doczj.com/doc/da13522790.html,/cYAY577Ucc7b2 访问密码86b3 4、msp430教程.pdf https://https://www.doczj.com/doc/da13522790.html,/cYAYtXwXYesgC 访问密码ccbf 5、IAR C 430标准库函数.pdf https://https://www.doczj.com/doc/da13522790.html,/cYAYnInwURHZx 访问密码52ef

03 第三讲 数字电路基础知识--力天手把手教你学单片机之入门篇

手把手教你学51单片机 ——之MCS-51入门篇 主讲: 尹延辉 策划:张勇 开发板:LT-Super51 QQ群:31646346 网址:https://www.doczj.com/doc/da13522790.html, E-Mail:litianmcu@https://www.doczj.com/doc/da13522790.html, litianmcu@https://www.doczj.com/doc/da13522790.html,

入门篇第三讲——数字电路基础知识?本讲内容提要 数字量和模拟量 数制和码制 算术运算和逻辑运算 数字芯片 常用数字芯片简介 可编程逻辑器件 存储器 学习板上扩展IO口 的实现

——数字量和模拟量 ?数字量和模拟量定义 模拟量:随时间连续变化的电压或电流信号称之为模拟量 数字量:随时间离散变化的量称之为数字量 ?数字量的实质为加入判决门限的模拟量

——数字电路’0’与’1’的定义?数字电路’0’与’1’的定义 TTL电平:电压+5V代表’1’,电压0代表’0’ LVTTL:+3.3V~’1’,0~’0’ RS232:-15V~’1’,+15V~’0’ LVDS:2根线上电压差的正负表示’1’或’0’

——数制和码制 ?数制的定义 计数过程中一位数字通常是不够用的,多位数码中每一位的构成方法及从低位向高位进位规则称为数制。 N进制数的通俗定义:逢N进1 ?十进制:逢十进一 ?十六进制:逢十六进一 ?二进制:逢二进一 ?常用数制 十进制、二进制、十六进制 ?人类有十个指头,所以习惯采用十进制 ?计算机只能识别0和1,采用二进制 ?为了计算机学中的数据书写方便,采用十六进制

——数制转换详解 ?数制间的转换 二-十转换 十-二转换 二-十六转换 十六-二转换 ?位与字节的概念: 位(bit):简写为b,表示二进制数的一位。 字节(Byte):简写为B,8位为一字节。 ?数制转换工具: Windows自带的计算器

51单片机实例(含详细代码说明)

1.闪烁灯 1.实验任务 如图4.1.1所示:在P1.0端口上接一个发光二极管L1,使L1在不停地一亮一灭,一亮一灭的时间间隔为0.2秒。 2.电路原理图 图4.1.1 3.系统板上硬件连线 把“单片机系统”区域中的P1.0端口用导线连接到“八路发光二极管指示模块”区域中的L1端口上。 4.程序设计内容 (1).延时程序的设计方法 作为单片机的指令的执行的时间是很短,数量大微秒级,因此,我们要 求的闪烁时间间隔为0.2秒,相对于微秒来说,相差太大,所以我们在 执行某一指令时,插入延时程序,来达到我们的要求,但这样的延时程 序是如何设计呢?下面具体介绍其原理:

如图4.1.1所示的石英晶体为12MHz,因此,1个机器周期为1微秒机器周期微秒 MOV R6,#20 2个 2 D1: MOV R7,#248 2个 2 2+2×248=498 20× DJNZ R7,$ 2个2×248 (498 DJNZ R6,D1 2个2×20=40 10002 因此,上面的延时程序时间为10.002ms。 由以上可知,当R6=10、R7=248时,延时5ms,R6=20、R7=248时, 延时10ms,以此为基本的计时单位。如本实验要求0.2秒=200ms, 10ms×R5=200ms,则R5=20,延时子程序如下: DELAY: MOV R5,#20 D1: MOV R6,#20 D2: MOV R7,#248 DJNZ R7,$ DJNZ R6,D2 DJNZ R5,D1 RET (2).输出控制 如图1所示,当P1.0端口输出高电平,即P1.0=1时,根据发光二极管 的单向导电性可知,这时发光二极管L1熄灭;当P1.0端口输出低电平, 即P1.0=0时,发光二极管L1亮;我们可以使用SETB P1.0指令使P1.0 端口输出高电平,使用CLR P1.0指令使P1.0端口输出低电平。 5.程序框图 如图4.1.2所示

c51单片机实例下载大全

单片机资料教程下载,省去找资料的麻烦,只供学习参考用,下载24内删掉,祝大家学习进步 单片机点阵学习资料 https://www.doczj.com/doc/da13522790.html,/thread-1703-1-1.html 手把手教你学单片机--教程视频 https://www.doczj.com/doc/da13522790.html,/thread-1688-1-1.html 力天把手教你学单片机视频教程 https://www.doczj.com/doc/da13522790.html,/thread-1689-1-1.html 谱中单片机开发板例程 https://www.doczj.com/doc/da13522790.html,/thread-1683-1-2.html 初学单片机的30,硬件简单对初学者有帮助 https://www.doczj.com/doc/da13522790.html,/thread-1962-1-1.html 用单片机制作的MP3 https://www.doczj.com/doc/da13522790.html,/thread-1701-1-2.html 51单片机应用开发大全所含100个范例代码及电路图 https://www.doczj.com/doc/da13522790.html,/thread-1820-1-1.html 【含28个单片机实例流程图】 https://www.doczj.com/doc/da13522790.html,/thread-1959-1-2.html 谱中单片机程序烧录工具STC https://www.doczj.com/doc/da13522790.html,/thread-1682-1-2.html 《单片机技术》32讲

https://www.doczj.com/doc/da13522790.html,/thread-1693-1-1.html 51单片机c语言100例教程 https://www.doczj.com/doc/da13522790.html,/thread-1700-1-1.html 单片机超级精华包 https://www.doczj.com/doc/da13522790.html,/thread-1687-1-1.html 新手学的多功能电子钟 https://www.doczj.com/doc/da13522790.html,/thread-1679-1-1.html 十天学会单片机和c语言视频教程 https://www.doczj.com/doc/da13522790.html,/thread-1692-1-1.html C语言函数库速查手册 https://www.doczj.com/doc/da13522790.html,/thread-1696-1-1.html 历史上最全的KEIL中文学习资料 https://www.doczj.com/doc/da13522790.html,/thread-1729-1-2.html 单片机c语言程序设计实训100例--基于AVR+PROTUES https://www.doczj.com/doc/da13522790.html,/thread-1695-1-2.html (有电路图和程序) https://www.doczj.com/doc/da13522790.html,/thread-1965-1-1.html 关于单片机抗干扰的资料 https://www.doczj.com/doc/da13522790.html,/thread-1961-1-1.html 单片机矩阵扫描键盘程序 https://www.doczj.com/doc/da13522790.html,/thread-1723-1-1.html 共享通过串口在线调试51单片机的专业版培训资料

手把手教你学单片机进阶-框架篇(上)

手把手教你学单片机进阶教程 框架篇(上) 本篇里我们聊一聊软件框架,那么什么是框架呢?它又有什么用处呢? 软件框架,说简单一点就是我们组织软件的方式,没有框架的代码,模块是乱添的,写程序的人也不知道要添在哪里,只知道加在这里可以用,放在这里就行。有框架的代码,模块应该添加到哪里是清楚的。曾经看过一句话说的挺有道理,“一个好的程序架构,是一个有经验的工程师和一个初学者的分水岭”,我们在单片机软件中用的最多的结构莫过于下面这样的: 1While(1) 2{ 3Led_on(); 4i = 1000; 5While(i--); 6Led_off(); 7} 当我们刚开始学习的时个,程序比较简单,这样单纯的结构还是可以应付的。但是如果当我们真的要做一个系统级的工程的时候,有很多功能要处理,这样的结构显然就不能适应了,只那一个“while(i--)”就不知道耽误了多少事儿。 到这里有人要说了,工程复杂的时候我可以跑个OS。可以说RTOS对于功能复杂的嵌入式系统来说是个非常好的解决方案,如比较出名的RT-Thread (我们以后会推出这个的专题),uc/os-ii。不过,可惜的是,操作系统对于51来说有点太,系统的开销有可能比应用占用的资源的还要多。 那么我们就自己动手来打造一个小资源单片机适用的框架吧。我们将实现两个版本,其内在思想都是一样的,一个简单点,占用资源更小。一个稍复杂些, pzq@https://www.doczj.com/doc/da13522790.html,/csh@sparkcn

但更灵活。大家可以根据情况选用。 easy_framework 我们把这个框架暂时命名为easy_framework,这里我们仅提供思想和基本的代码。完整的代码可以在我们提供代码包(下载地址见文章最后)里找到。 这里测试和实验的硬件环境是Spark51学习板。大家如果有需要,可以到我们工作室店铺购买https://www.doczj.com/doc/da13522790.html,或直接通过QQ联系我们首先使用一个Timer来产生一个1m的定时中断。在51单片机上,这里选用Timer0 1init_sys_timer() 2{ 3/*T0 1方式*/ 4TMOD |= 0x01; 5/*设定1m的计时*/ 6TL0 = (u8)SYS_TIMER_INIT_VALUE; 7TH0= (u8)(SYS_TIMER_INIT_VALUE >> 8); 8/*允许中断*/ 9ET0 = 1; 10TR0 = 1; 11} 通过上面这个函数产生一个1m的中断,在其“中断服务函数”里我们对一些时间标志量进行记数 1/*Timer 0中断服务程序*/ 2void proc_sys_tick() interrupt 1 3{ 4TR0 = 0; 5Cnt5ms++; pzq@https://www.doczj.com/doc/da13522790.html,/csh@sparkcn

手把手教你学51单片机之十八RS485通信与Modbus协议

在工业控制、电力通讯、智能仪表等领域,通常情况下是采用串口通信的方式 进行数据交换。最初采用的方式是 RS232 接口,由于工业现场比较复杂,各 种电气设备会在环境中产生比较多的电磁干扰,会导致信号传输错误。除此之外, RS232 接口只能实现点对点通信,不具备联网功能,最大传输距离也只能达到 几十米,不能满足远距离通信要求。而 RS485 则解决了这些问题,数据信号采用 差分传输方式,可以有效的解决共模干扰问题,最大距离可以到1200 米,并且 允许多个收发设备接到同一条总线上。随着工业应用通信越来越多, 1979 年施耐 德电气制定了一个用于工业现场的总线协议 Modbus 协议,现在工业中使用 RS485 通信场合很多都采用 Modbus 协议,本节课我们要讲解一下 RS485 通信和Modbus 协议。 单单使用一块KST-51 开发板是不能够进行RS485 实验的,应很多同学的要求,把这节课作为扩展课程讲一下,如果要做本课相关实验,需要自行购买USB 转 485 通信模块。 18.1 RS485通信 实际上在 RS485 之前 RS232 就已经诞生,但是RS232 有几处不足的地方: 1、接口的信号电平值较高,达到十几V ,容易损坏接口电路的芯片,而且和TTL 电平不兼容,因此和单片机电路接起来的话必须加转换电路。 2、传输速率有局限,不可以过高,一般到几十Kb/s 就到极限了。 3、接口使用信号线和GND 与其他设备形成共地模式的通信,这种共地模式传输容易产生 干扰,并且抗干扰性能也比较弱。 4、传输距离有限,最多只能通信几十米。 5、通信的时候只能两点之间进行通信,不能够实现多机联网通信。 针对 RS232 接口的不足,就不断出现了一些新的接口标准,RS485 就是其中之一,他具备 以下的特点: 1、我们在讲A/D 的时候,讲过差分信号输入的概念,同时也介绍了差分输入的好处,最大 的优势是可以抑制共模干扰。尤其工业现场的环境比较复杂,干扰比较多,所以通信如果采用的是差分方式,就可以有效的抑制共模干扰。而RS485 就是一种差分通信方式,它的通 信线路是两根,通常用 A 和B 或者D+ 和 D- 来表示。逻辑“ 1”以两线之间的电压差为+(0.2~6)V 表示,逻辑“0”以两线间的电压差为-(0.2~6)V来表示,是一种典型的差分通信。 2、 RS485通信速度快,最大传输速度可以达到10Mb/s以上。 3、RS485 内部的物理结构,采用的是平衡驱动器和差分接收器的组合,抗干扰能力也大大 增加。 4、传输距离最远可以达到1200 米左右,但是他的传输速率和传输距离是成反比的,只有 在100Kb/s 以下的传输速度,才能达到最大的通信距离,如果需要传输更远距离可以使用中继。

[用微课学51单片机][白炽贵][电子教案和教学指南] 《用微课学51单片机》教学指南0513

《用微课学51单片机》教学指南 教学模式 本书与电子工业出版社出版的《用微课学电子CAD》教材对接,即以学生电子CAD 课程所完成制作的51单片机电路板为编程验证平台,进行51单片机编程实操实训。因此,需在本课程开课前,先进行本书所需的51单片机实验板CAD设计及安装焊接。这既提高了电子CAD课程的教学目标和教学档次,又为单片机课程创建了学生得心应手功能强劲的编程开发平台,从而满足学生单片机技术高档次的研发平台之需,能让职业院校学生在电子CAD和单片机技术两课程对接上实现“1+1>2”的效果。 教学目标 借助学生亲手完成的单片机实验板平台,在单片机程序实训案例的数量上和质量上有所突破和创新,引用蓝牙技术和WIFI技术,让学生充分享受单片机程序设计的乐趣和成功,为学生胜任单片机技术职业岗位打下必须的技能基础。 教学内容 1.数码管显示编程实操; 2.单片机中断编程实操; 3.单总线双总线三总线器件编程实操; 4.LED16乘16点阵汉字显示编程实操; 5.串行通信编程实操; 6.存储器编程实操; 7.使用蓝牙模块和WIFI模块编程实操; 8.ADC0804和DAC0832编程实操; 9.LCD液晶屏编程实操; 10.红外解码超声测距步进电机编程实操; 11.程序综合编程实操。 12. 教学重点 每个单片机程序设计项目的实操步骤和代码输入过程是教学的重点 。 教学难点 理解单片机程序的执行逻辑分析是教学难点。 教学时数 全书实操视频约540分钟,学生实操以4倍计算,计2160分钟,以40分钟为1课时,约54课时,加14课时机动,合计68课时。 教学建议 1.本书以任务驱动展开教学和实操,为方便教师的教和学生的学,全书的每个任务实操都配有一个不差一秒的实操全程录屏视频,可手把手指导学生正确完成编程任务。学生实操时应两人一组进行合作学习,即学生甲用一台电脑进行单片机程序设计,学生乙用另一台电脑放实操视频,学生甲要参照学生乙所放视频进行代码输入,学生乙要对照检查学生甲屏幕上的代码输入是否正确,两学生的角色定时轮换。两学生这样合作实操,就能保证编程实操的正确性。 1

相关主题
文本预览
相关文档 最新文档