• AT89S52之串行异步通信笔记


    SRF

    中断入口地址

    • 中断源
      • 外中断
        • 外部中断0 INT0(P3.2)
        • 外部中断1 INT1(P3.3)
        • 电平方式触发
          • 低电平
        • 脉冲方式触发
          • 脉冲后延的负跳
      • 内中断
      • 定时中断
      • 串行中断

    中断允许控制寄存器

    • EA中断允许总控制位
    • ES串行中断允许控制位
    • ET2、ET1、ET0、EX1、EX0

    C51

    • 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. 查看芯片的晶振,检查配置的波特率是否误差较大(>1%),利用单片机小精灵查看

    1. 查看自己使用的串口调试助手的跳线帽,STC89C52单片机输出的串口信号是0-3.3V电平,跳线帽应短接3.3端而不是5V端。
    2. 当下载完程序后应先进行复位操作再进行串口调试,查看数据。

    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编程

  • 相关阅读:
    Git忽略提交规则
    vue-echarts, vue 图表数据处理; axios 跨域代理
    css 画图
    span 空标签 width 设置无效 解决办法
    css 属性备忘录
    js 操作数组的方法 split()
    js 取整,四舍五入 Math.ceil()
    js 强制类型转换 parseInt,parseFloat,number
    dom级别和对应事件级别;事件流
    mac 使用命令行向 github 提交代码
  • 原文地址:https://www.cnblogs.com/scrazy/p/10035248.html
Copyright © 2020-2023  润新知