AT89S52之串行异步通信笔记

SRF

中断入口地址

- 中断源
- 外中断
- 外部中断0 INT0(P3.2)
- 外部中断1 INT1(P3.3)
- 电平方式触发
- 低电平
- 脉冲方式触发
- 脉冲后延的负跳
- 内中断
- 定时中断
- 串行中断
- 外中断
中断允许控制寄存器
- EA中断允许总控制位
- ES串行中断允许控制位
- ET2、ET1、ET0、EX1、EX0

- AT89S52有两个定时/计数器T1,T2
- T1,T2各有四种工作方式
定时器/计数器工作方式寄存器TMOD
- 工作方式



顾 12M的晶振对于一个正道周期为1/12us ,一个机器周期为1us
方式1位16位寄存器,顾最大65536个数 从0-65535-0变化
所以,你要想定时1us,因为它溢出中断,所以FF FF 执行完+1 后溢出 置位TF0 并 触发中断 定时器恢复为0
定时器/计数器控制寄存器TCON
溢出TF:查询方式,软件清零;中断方式,硬件自动清零。
允许TR:启动停止

串行控制口寄存器SCON
- 串行口工作方式
- REN控制是否允许接受。当REN=1时,允许接收,当REN=0
- 方式0,8位移位寄存器方式,典型应用串口驱动数码管
- 方式1,10位异步通信方式,通信的帧格式为1个起始位0,8个数据位,最后是停止位1
- 方式2,11位方式,通信的帧格式为1个起始位0,9个数据位,第九位作为奇偶校验位或者多机通讯是的地址数据标识位,最后是停止位1,共11个二进制位。

串行口工作方式选择:

电源控制寄存器PCON
- 波特率加倍

定时器T1的溢出率:

定时器T1的波特率的计算公式:
- 串行口传输方式为方式0和方式2的波特率不灵活:
- 串行口传输方式为方式1或者方式3时的波特率灵活,其计算公式:



常用波特率:

汇编使用定时器1工作在方式1【10位数据帧格式】(无奇偶校验位)发送接受(双向,允许接受,REN=1),配置波特率为9600bit/s,
①设置定时器1工作方式2:
MOV TMOD, #20H ;M1,M2为10,T1为定时方式2
②设置定时器1的初始值:
MOV TL1, #0FDH ;TL1为8位定时/计数
MOV TH1, #0FDH ;TH1为自动装载的初值,波特率为9600bit/s
②启动定时器1工作(TCON):
SETB TR1 ;启动定时器
④设置串行口工作方式:
MOV SCON, #50H ;串行口工作在方式1
⑥设置波特串加倍位为不加倍
SMOD:MOV PCON,#00H
⑥开中断开关IE:
SETB ES;
SETB EA;

实验现象
未发送完SBUF里的数据时,SCON 寄存器里TI位为0

当发送完SBUF里的数据时,SCON 寄存器里TI位由硬件自动置1,并进入中断


注意事项:
当确认程序配置的波特率无误,但是利用串口调试助手接受到数据和实际单片机发送的数据不吻合时可按下面检查
- 查看芯片的晶振,检查配置的波特率是否误差较大(>1%),利用单片机小精灵查看

- 查看自己使用的串口调试助手的跳线帽,STC89C52单片机输出的串口信号是0-3.3V电平,跳线帽应短接3.3端而不是5V端。
- 当下载完程序后应先进行复位操作再进行串口调试,查看数据。
AT89S52之汇编实现串行通信-只发送数据
;中断方式,硬件自动清除定时器1中断,即清除TF1标志位
;数据从TXD端输出,当数据写入发送缓冲器SBUF后,启动发送器发送。当发送完一帧数据后,置中断标志TI为1。T1为串行控制寄存器里的
/**
**AT89S52之汇编实现串行通信-只发送数据
**备注:波特率为4800bit/s,波特率误差为0.16%,采用定时器1工作在方式2(自动装载初值),采用串口传输方式1(10位数据帧格式)
*/
ORG 0000H
LJMP MAIN
ORG 001BH;定时器1中断
LJMP IT1P
ORG 0023H;串行传输中断
LJMP SEND
ORG 0100H
MAIN:
MOV TMOD, #20H ;M1,M2为10,T1为定时方式2
MOV TL1, #0F3H ;TL1为8位定时/计数
MOV TH1, #0F3H ;TH1为自动装载的初值,波特率为4800bit/s
MOV SCON,#50H ;串口工作方式1 10位数据格式
;SETB ET1 ;允许定时器1中断,有病吧,你开TM定时器1中断干哈????
SETB EA ;允许总中断
SETB ES ;允许串行传输中断ES,传输完成触发中断
MOV PCON,#80H;波特率加倍,减小波特率误差 0.16%
SETB TR1 ;启动定时器
LOOP:MOV A,#99H
MOV SBUF,A
CONT:
INC DPTR
LJMP $
//WAIT:JBC TI,CONT ;判断发送结束否,必须要有个等待发送完毕的过程,发送完毕才能进行下一次的发送
//SJMP WAIT
IT1P:
INC DPTR
RETI ;中断服务程序的返回必须用RETI,用RET则CPU不会清除中断,造成下次无法进入中断
SEND:
CLR TI;TI的位地址是99H,存在于字节地址为98H的SCON第二位里
MOV A,#66H
MOV SBUF,A
RETI
END
2018-12-2日更新 汇编实现数据收发
;中断方式,硬件自动清除定时器1中断,即清除TF1标志位
;数据从TXD端输出,当数据写入发送缓冲器SBUF后,启动发送器发送。当发送完一帧数据后,置中断标志TI为1。T1为串行控制寄存器里的
/**
**AT89S52之汇编实现串行通信-只发送数据
**备注:波特率为4800bit/s,波特率误差为0.16%,采用定时器1工作在方式2(自动装载初值),采用串口传输方式1(10位数据帧格式)
*/
//定时延迟之类的必须大于一个机器周期
;=================================================================================================================
ORG 0000H
LJMP MAIN
ORG 000BH ;定时器0中断
LJMP Timer0Interrupt
ORG 001BH ;定时器1中断
LJMP Timer1Interrupt
ORG 0023H ;串行传输中断
LJMP UARTInterrupt
ORG 0100H
MOV SP,#60H
;=================================================================================================================
;=================================================================================================================
MAIN:
LCALL InitTimer0 ;定时器0初始化
LCALL InitUART ;串口初始化
MOV A,#99H
MOV SBUF,A
CONT:
INC DPTR
LJMP $
;=================================================================================================================
;定时器0中断服务函数
Timer0Interrupt:;定时器中断里赋定时初值,其定时是时间不能小于本中断里所以程序语句执行时间,否则定时器会一直中断????;或者最后清除中断,但是一定要清除,否则会一直进入中断,无法执行其他程序和进入其他中断
PUSH DPH
PUSH DPL
PUSH ACC
MOV TH0,#00H ;
MOV TL0,#01H
;========================
CPL P2.7
//延迟1s
MOV R2,#01H
LCALL DELAY1S
;========================
POP ACC
POP DPL
POP DPH
CLR TF0
RETI
;=================================================================================================================
;定时器1中断服务函数
Timer1Interrupt:
PUSH DPH
PUSH DPL
PUSH ACC
MOV TH0,#0FFH
MOV TL0,#0FFH
;========================
;add your code here!
;========================
POP ACC
POP DPL
POP DPH
CLR TF1
RETI
UARTInterrupt:
JB RI,IsUART_Receive ;RI为1则转移
CLR TI ;TI的位地址是99H,存在于字节地址为98H的SCON第二位里
CPL P2.6
MOV R2,#01H
LCALL DELAY1S
MOV A,#99H
MOV SBUF,A
RETI ;中断服务程序的返回必须用RETI,用RET则CPU不会清除中断,造成下次无法进入中断
;=================================================================================================================
InitTimer0:
MOV TMOD,#01H ;工作方式1,16位计数器
MOV TH0,#00H
MOV TL0,#01H
SETB ET0 ;开定时器T0中断
SETB EA ;开总中断
SETB TR0 ;启动定时器
RET
;=================================================================================================================
/*
InitTimer1:
MOV TMOD,#20H ;M1,M2为10,T1为定时方式2
MOV TL1, #0F3H ;TL1为8位定时/计数
MOV TH1, #0F3H ;TH1为自动装载的初值,波特率为4800bit/s
MOV SCON,#50H ;串口工作方式1 10位数据格式
MOV TMOD,#01H
MOV TH0,#0FFH
MOV TL0,#0FFH
SETB EA ;开总中断
SETB ET0 ;开定时器T0中断
SETB TR0 ;启动定时器
RET
*/
;=================================================================================================================
InitUART:
MOV TMOD,#20H ;M1,M2为10,T1为定时方式2
MOV TL1, #0F3H ;TL1为8位定时/计数
MOV TH1, #0F3H ;TH1为自动装载的初值,波特率为4800bit/s
MOV SCON,#50H ;串口工作方式1 10位数据格式
;SETB ET1 ;关定时器1中断,定时器1会自动装载初值,无需中断
SETB EA ;开总中断
SETB ES ;开串行传输中断ES,传输完成触发中断
MOV PCON,#80H ;波特率加倍,波特率误差为 0.16%
SETB TR1 ;启动定时器
RET
;=================================================================================================================
IsUART_Receive: ;发送中断里先查询是否接受
CLR RI
PUSH ACC
MOV A,SBUF
;========================
CPL P2.0
MOV R2,#01H
LCALL DELAY1S
;========================
POP ACC
RETI
DELAY1S: ;误差 0us
START:
MOV R7,#38H
DL1:
MOV R6,#0E2H
DL0:
MOV R5,#26H
DJNZ R5,$
DJNZ R6,DL0
DJNZ R7,DL1
NOP
DJNZ R2,START
RET
END
C51编程


AT89S52之串行异步通信笔记的更多相关文章
- Verilog学习笔记简单功能实现(七)...............接口设计(并行输入串行输出)
利用状态机实现比较复杂的接口设计: 这是一个将并行数据转换为串行输出的变换器,利用双向总线输出.这是由EEPROM读写器的缩减得到的,首先对I2C总线特征介绍: I2C总线(inter integra ...
- STM32学习笔记(五) USART异步串行口输入输出(轮询模式)
学习是一个简单的过程,只要有善于发掘的眼睛,总能学到新知识,然而如何坚持不懈的学习却很困难,对我亦如此,生活中有太多的诱惑,最后只想说一句勿忘初心.闲话不多扯,本篇讲诉的是异步串行口的输入输出,串口在 ...
- STM32学习笔记——SPI串行通讯(向原子哥学习)
一.SPI 简介 SPI是 Serial Peripheral interface 的缩写,就是串行外围设备接口.SPI 接口主要应用在 EEPROM, FLASH,实时时钟,AD 转换器,还有数 ...
- JVM_垃圾回收串行、并行、并发算法(总结)
一.串行 JDK1.5前的默认算法 缺点是只有一个线程,执行垃圾回收时程序停止的时间比较长 语法 -XX:+UseSerialGC 新生代.老年代使用串行回收 新生代复制算法 老年代标记-压缩 示例图 ...
- 【Arduino】使用C#实现Arduino与电脑进行串行通讯
在给Arduino编程的时候,因为没有调试工具,经常要通过使用串口通讯的方式调用Serial.print和Serial.println输出Arduino运行过程中的相关信息,然后在电脑上用Arduin ...
- 十天学会单片机Day4串行口通信
并行与串行基本通信方式 1.并行通信方式 通常是将数据字节的各位用多条数据线同时进行传送. 并行通信控制简单.传输速度快:由于传输线较多,长距离传送时成本高且接收方的各位同时接收存在困难. 2.串行通 ...
- IOS多线程知识总结/队列概念/GCD/主队列/并行队列/全局队列/主队列/串行队列/同步任务/异步任务区别(附代码)
进程:正在进行中的程序被称为进程,负责程序运行的内存分配;每一个进程都有自己独立的虚拟内存空间 线程:线程是进程中一个独立的执行路径(控制单元);一个进程中至少包含一条线程,即主线程 队列 dispa ...
- 单片微机原理P4:80C51串口与串行总线拓展
0. 串口通讯 0. 串口通讯的数据传输方式:单工(单向传输数据),半双工(非同时双向传输),全双工(同时,双向传输) 1. 根据通信方式的不同又分为同步通讯和异步通讯. 同步通讯:所有设备都使用同一 ...
- PHP中的抽象类与抽象方法/静态属性和静态方法/PHP中的单利模式(单态模式)/串行化与反串行化(序列化与反序列化)/约束类型/魔术方法小结
前 言 OOP 学习了好久的PHP,今天来总结一下PHP中的抽象类与抽象方法/静态属性和静态方法/PHP中的单利模式(单态模式)/串行化与反串行化(序列化与反序列化). 1 PHP中的抽象 ...
随机推荐
- rails中params[:id]与params["id"]分析
写这个帖子的缘由是因为在页面参数传到rails的controller时用params[:]和params[""]都可以取到值: [1] pry(#<BooksControll ...
- Vue中实现token验证
前后端流程分析 前端页面进行登录操作,将用户名和密码发给服务器 服务器进行校验,通过后生成token,包含信息有密匙.uid.过期时间等,然后返回给前端 前端将token保存在本地(建议在localS ...
- 解决vuejs应用在nginx非根目录下部署时访问404的问题
以往部署vuejs应用都是直接在nginx的location为/下直接部署,这次遇到要将vue应用部署在/vuejs-admin的非根下,使用以往部署方案直接访问就会404,这时修改步骤如下: 1.修 ...
- 【转】JUC下面线程池介绍
介绍new Thread的弊端及Java四种线程池的使用,对Android同样适用.本文是基础篇,后面会分享下线程池一些高级功能. 1.new Thread的弊端执行一个异步任务你还只是如下new T ...
- 使用dom4j处理xml操作xml数据
使用dom4j处理xml操作xml数据 示例代码: public class TestDom4j { public static void main(String[] args) { String x ...
- 针对多类型数据库,集群数据库的有序GUID
一.背景 常见的一种数据库设计是使用连续的整数为做主键,当新的数据插入到数据库时,由数据库自动生成.但这种设计不一定适合所有场景. 随着越来越多的使用Nhibernate.EntityFramewor ...
- Zookeeper学习文章目录1
目录:参考文章如下 1.ZooKeeper学习第一期---Zookeeper简单介绍 2. ZooKeeper学习第二期--ZooKeeper安装配置 3. ZooKeeper学习第三期---Zook ...
- CSS页面重构“鑫三无准则”之“无图片”准则——张鑫旭
一.再说关于“鑫三无准则” “鑫三无准则”这个概念貌似最早是在去年的去年一篇名叫“关于Google圆角高光高宽自适应按钮及其拓展”的文章中提过.这是自己在页面重构的经验中总结出来的一套约束自己CSS的 ...
- 传统javabean与spring中的bean的区别
javabean已经没人用了 springbean可以说是javabean的发展, 但已经完全不是一回事儿了 用处不同:传统javabean更多地作为值传递参数,而spring中的bean用处几乎无处 ...
- Vue如何使用动态刷新Echarts组件
这次给大家带来Vue如何使用动态刷新Echarts组件,Vue使用动态刷新Echarts组件的注意事项有哪些,下面就是实战案例,一起来看一下. 需求背景:dashboard作为目前企业中后台产品的“门 ...