wuzhengmin 发表于 2026-1-20 19:15:55

注意,接收方的波特率必须和发送方的波特率相同!

接受放REN=1

中断服务程序请中断肯定是请RI

wuzhengmin 发表于 2026-1-21 20:37:53

我手头没有陈老师的课程资料,程序要自己慢慢输入:


//$include (../comm/AI8051U.INC)

           $INCLUDE (AI8051U.INC) ;包含AI8051U单片机的寄存器定义文件
           ADDRT EQU 1000H
       ORG0000H

LJMP                   MAINT   ;跳至主程序入口
                        ORG0023H
                        LJMP UART1_ISR   ;转至串行中断服务程序
       
MAINT:                 MOV SP, #80H       ;设置堆栈指针
                        MOV SCON, #50H   ;8位数据,可变波特率
                        ANL AUXR, #0FEH    ;串口1选择定时器1为波特率发生器
                        ANL TMOD, #0FH   ;设定定时器1为16位自动重装方式
                        MOV TL1, #0E8H   ;设定定时初值
                        MOV TH1, #0FFH   ;设定定时初值
                        CLR ET1            ;禁止定时器1中断
                        SETB TR1         ;启动定时器1
                        SETB ES            ;串行口开中断
                        SETB EA            ;开总中断

                        MOV DPTR,#ADDRT    ;ADDRT是首址,可以使用EQU定义
                        MOV R0,#00H      ;传送字节数初值
                        MOVX A,@DPTR       ;取第一个发送字节
                        MOV SBUF,A         ;启动串行口发送
                        SJMP $             ;等待中断

                        ;中断服务程序
UART1_ISR:CLR TI             ;将中断标志清零
                        CJNE R0,#7FH,LOOPT ;判断128B是否发送完,若没完,则转LOOPT
                        CLR ES             ;全部发送完毕,禁止串行口中断
                        LJMP ENDT          ;转中断返回
                       
LOOPT:      INC R0             ;修改字节数指针                       
                        INC DPTR         ;修改地址指针,继续取下一发送数据
                        MOVX A,@DPTR       ;取发送数据
                       
                        MOV SBUF,A         ;启动串行口
                       
ENDT:       RETI               ;中断返回
                        END

wuzhengmin 发表于 2026-1-21 20:39:00

下面是C语言对应的程序:

#include <AI8051U.H>
unsigned char xdata ADDRT; //在外部RAM区定义128个单元

unsigned char num=0;    //声明计数变量
unsigned char xdata *psend;   //指向发送数据区的指针


void main(void)       //主程序,在C语言的主程序中可以不设置堆栈指针
{

        SCON=0x40;      //8位数据,可变波特率
        AUXR &= 0xFE;   //串口1选择定时器1为波特率发生器
        TMOD &= 0x0F;   //设定定时器1为16位自动重装方式

        TL1 = 0xE8;       //设定定时初值
        TH1 = 0xFF;       //设定定时初值
        TR1 = 1;          //启动定时器1
       
        ES=1;             //串行口开中断
        psend = ADDRT;      //设置发送数据缓冲区指针
        EA=1;             //开中断
        psend=ADDRT;      //设置发送数据缓冲区指针
        SBUF = *psend;    //发送第一个数据
        while(1);         //等待中断
}

void UART1_ISR(void) interruptUART1_VECTOR//串口1中断服务函数
{

        TI = 0;         //清发送中断标志
        num++;          //修改计数变量值
        if(num==0x7F)
                ES=0;       //判断是否发送完,若已完,则关中断
        else
        {
                psend++;      //否则,修改指针,发送下一个数据
                SBUF= *psend;
        }
}

wuzhengmin 发表于 2026-1-21 20:56:17

接收方的汇编源程序:

wuzhengmin 发表于 2026-1-21 21:18:53

我们也只能慢慢输入:

//$include (../comm/AI8051U.INC)

           $INCLUDE (AI8051U.INC) ;包含AI8051U单片机的寄存器定义文件
           ADDRT EQU 1000H
       ORG0000H

LJMP                   MAINT   ;跳至主程序入口
                        ORG0023H
                        LJMP UART1_ISR   ;转至串行中断服务程序
                       
                        ORG0200H
       
MAINT:                 MOV SP, #80H       ;设置堆栈指针
                        MOV SCON, #50H   ;8位数据,可变波特率
                        ANL AUXR, #0FEH    ;串口1选择定时器1为波特率发生器
                        ANL TMOD, #0FH   ;设定定时器1为16位自动重装方式
                        MOV TL1, #0E8H   ;设定定时初值
                        MOV TH1, #0FFH   ;设定定时初值
                        CLR ET1            ;禁止定时器1中断
                        SETB TR1         ;启动定时器1
                        SETB ES            ;串行口开中断
                        SETB EA            ;开总中断

                        MOV DPTR,#ADDRT    ;ADDRT是首址,可以使用EQU定义
                        MOV R0,#00H      ;传送字节数初值
                        MOVX A,@DPTR       ;取第一个发送字节
                        MOV SBUF,A         ;启动串行口发送
                        SJMP $             ;等待中断

                        ;中断服务程序
UART1_ISR:CLR RI             ;接收中断标志清零

                        MOV A,SBUF         ;取接收的数据
                        MOVX @DPTR,A      ;接收的数据送缓冲区
                        CJNE R0,#7FH,LOOPR ;判断128B是否接收完,若没完,则转LOOPR
                       
                        CLR ES             ;全部接收完毕,禁止串行口中断
                        LJMP ENDR          ;转中断返回
                       
LOOPR:      INC R0             ;修改字节数指针                       
                        INC DPTR         ;修改地址指针,继续取下一发送数据
                       
                                               
ENDR:       RETI               ;中断返回
                        END

wuzhengmin 发表于 2026-1-21 21:45:16

对应的C语言接收源程序:

#include <AI8051U.H>
unsigned char xdata ADDRT; //在外部RAM区定义128个单元

unsigned char num=0;    //声明计数变量
unsigned char xdata *prcc;   //指向接收数据区的指针


void main(void)       //主程序,在C语言的主程序中可以不设置堆栈指针
{

        SCON=0x50;      //8位数据,可变波特率
        AUXR &= 0xFE;   //串口1选择定时器1为波特率发生器
        TMOD &= 0x0F;   //设定定时器1为16位自动重装方式

        TL1 = 0xE8;       //设定定时初值
        TH1 = 0xFF;       //设定定时初值
        ET1 = 0;         //禁止定时器1中断
        TR1 = 1;          //启动定时器1
        ES=1;             //串行口开中断
        EA=1;             //开中断
       
        prcc = ADDRT;      //设置发送数据缓冲区指针
               
        while(1);         //等待中断
}

void UART1_ISR(void) interruptUART1_VECTOR//串口1中断服务函数
{

        RI = 0;         //清接收中断标志
        num++;          //修改计数变量值
        if(num==0x7F)
                ES=0;       //判断是否接收完,若已完,则关中断
        else
        {
               
                *prcc = SBUF ;
                prcc++;      //修改指针,接收下一个数据
        }
}

wuzhengmin 发表于 2026-1-21 21:52:54

接下来我们看看下一个内容:

wuzhengmin 发表于 2026-1-21 21:54:03

串口2 的使用实际例子:

wuzhengmin 发表于 2026-1-21 21:55:10

还有多机通信的问题:

wuzhengmin 发表于 2026-1-21 22:03:17

多机通信的时候,主机发送地址后,要等待从机的回应

回应之后,再发送数据............

从机:接收主机发来的地址帧信息,并与本机的地址号相比较,若不符合,仍保持SM2=1不变;若相等,则使SM2清零,准备接收后续的数据信息,直至接收完10个数据信息。

页: 72 73 74 75 76 77 78 79 80 81 [82] 83 84 85 86 87 88 89
查看完整版本: 有关DMA,山东大学陈桂友教授