• N76E003之串口


    N76E003包含两个具备增强的自动地址识别和帧错误检测功能的全双工串口。由于两个串口的控制位是一样的,为了区分两个串口控制位,串口1的控制位以“_1”结尾(例如SCON_1)。下述详例以串口0为例。
    每个串口都有一种同步工作模式:模式0。三种全双工异步模式:模式1,2,和3,这意味着收发可以同时连续进行。串口接收带有接收缓存,意味着在接收的前一个数据在被读取之前,串口就能接收第二个数据。接收和发送都是对SBUF进行操作访问,写入SBUF数据将直接传到发送寄存器,而读取SBUF是访问一个具有独立物理地址的接收寄存器。串口共有4种操作模式,任何一种模式,任何以操作SBUF的指令都将开始一次传输。注意,在使用串口功能前,串口所用管脚P0.7及 P0.6 (RXD 及 TXD引脚) 或者 P0.2及 P1.6 (RXD_1 及 TXD_1)必须先置1。N76E003提供更灵活的管脚配置,可将串口0的TXD及RXD通过UART0PX (AUXR1.2)更改位置。

     

     

    13.1 模式 0
    模式0是与外部设备进行同步通信的方式。在该模式下,串行数据由RXD脚进行收发,而TXD 脚用于产生移位时钟。这种方式下是以半双工的形式进行通信,每帧接收或发送8位数据。数据的最低位被最先发送或接收,波特率设置为FSYS/12(SM2 (SCON.5) 为 0) 或 FSYS/2 (SM2 为 1)。无论发送或接收数据,串行时钟将一直由MCU产生,因此串口模式 0 为主机模式。图13‑1 显示串口模式0传输时序图

     

    如图所示,数据由双向RXD引脚进行收发,TXD引脚用来输出移位时钟。串口用移位时钟来一位位接收/发送数据与其他串口通讯。数据移入移出由最低位开始,波特率等于TXD的移位时钟频率。

    向SBUF的写入数据将会开启发送,此时移位时钟启动数据从RXD脚串行移出,直至8位数据传输完成。传输标志位TI (SCON.1) 置 1表示 1 个字节数据传输完成。
    当REN (SCON.4)=1 且 RI(SCON.0)=0 时串口开始接收数据。该条件告诉串口控制器有数据要移位进入。这个过程将持续到8位数据接收完毕,然后接收标志RI将置1。用户可以清零RI,以触发接收下一字节数据。

    13.2 模式 1
    模式1为异步全双工的工作方式。异步通讯模式通常用于PC间,调制解调器和其它类似接口间通讯。模式1下,10位数据通过TXD发送,通过RXD接收。10位数据组成如下:起始位(逻辑0),8位数据(最低位在前),停止位(逻辑1)。波特率由定时器1决定, SMOD (PCON.7) 设置为1可使波特率加倍.图13‑2为串口模式1发送和接收的时序图.

    向SBUF写入数据开始传输,传输发生在TXD引脚上。首先是开始位,随后是8位数据位,最后是停止位。停止位出现后,TI(SCON.1)将置1 表示一个字节传输完成,所有位的传输速度取决于波特率。
    当波特率发生器激活且REN(SCON.4) =1时,系统可以随时开始接收操作,当RXD脚上侦测到1到0的跳变时,数据将开始被采样并根据波特率的时钟频率接收,停止位必须符合一定的条件,接收到数据才能装载到SBUF:

    1. RI (SCON.0) = 0

    2. 要么SM2 (SCON.5) = 0, 要么接收到停止位STOP= 1,同时SM2 = 1且被寻址“Given”或符合广播地址(Broadcast address)匹配时。详见 13.7 多机通讯 和 13.8 自动地址识别。
    如果上述条件满足,SBUF将加载到接收数据,RB8(SCON.2)为停止位,和RI将被置1,如果条件不满足,RI保持为0,没有数据加载。完成接收过程后,串口控制器将等待RXD脚上出现另一个1-0传输以开始新的数据接收。

    13.3 模式 2
    模式2为全双工异步通信, 与模式1不同的是,模式2是11位收发。数据由起始位(逻辑0),8位数据(最低位在前),第9位数据(TB8或RB8)和停止位(逻辑1)组成。第9位做奇偶校验位或多机通信时用来区分数据和地址。波特率是系统时钟频率的1/32 或1/64,由 SMOD位(PCON.7)来配置。图13‑3 指示串口模式2的传输时序。

     

    向SBUF中写入数据启动TXD引脚发送,首先是开始位,然后是8位数据和TB8(SCON.3),最后是停止位,停止位发送后,TI将置位标志传输完成。
    当REN=1时,串口可进行接收操作。RXD上的下降沿表示接收过程开始,数据根据所配置波特率进行采样和接收。停止位必须符合一定的条件,接收到数据才能装载到SBUF:

    1. RI (SCON.0) = 0,

    2. 要么SM2(SCON.5) = 0, 要么9th位 = 1同时 SM2 = 1且被寻址“Given”或符合广播地址(Broadcast address)匹配。详见 13.7 多机通讯 和 13.8 自动地址识别。
    如果上述条件满足,则第9位数据进入RB8(SCON.2),8位数据进入SBUF,且RI置位。否则数据将不会装载,且RI保持为0。完成接收过程后,串口控制器等待RXD脚上的另一个1-0跳变以开始新的数据接收。
    13.4 模式 3
    除波特率外模式 3与模式 2相同。模式3采用定时器1的溢出率作为波特率时钟。图13‑3 模式3的传输时序,与模式2没有不同。

    13.5 波特率
    串口的不同模式的波特率时钟源和速度是完全不同的。详见表 13–3. 用于设定不同的波特率。
    在模式1或模式3,串口0的波特率时钟源可通过BRCK (T3CON.5)选择定时器1或定时器3。对于串口1,只有采用定时器3作为唯一的时钟源。

    当采用定时器1作为波特率发生器,需要关闭定时器1中断。定时器1可配置为计数器或是定时器,三种工作模式都可以。典型应用中,会配置为定时器工作在自动重装载模式(定时器模式2)。如果采用定时器3作为波特率发生器,同样也需要关闭定时器3中断。

    模式1和模式3的波特率是可变的,取决于定时器1或2(003芯片)的溢出速率,就是说定时器1每溢出一次,串口发送一次数据。那么我们怎么去计算这两个模式的波特率设置时相关的寄存器的值呢?可以用公式去计算。  

    13.6 帧错误检测
    帧错误检测用于异步模式 (模式 1, 2 和 3)。当由于总线干扰或争夺,导致没有检测到有效的停止位时,将发生帧错误。串口可以检测帧错误,并通过软件提示出错。
    FE为帧错误标志,位于SCON第7位,这个位正常被用作为SM0 。当SMOD0 (PCON.6)置1时,帧错误检测功能打开,它作为FE标志。SM0和FE其实是相互独立的标志位。
    当帧错误发生时,FE标志由硬件置位。如果必要,FE可在串口中断程序中检测。注意在对FE标志位进行读写时,同时SMOD0必须为1。如果FE被置位,那么下次即使接收到的正确数据帧也不会将其清除。对该位的清除必须由软件来完成。

    13.7 多机通讯
    N76E003串口支持多机通讯,可让一个主机(master device)向多个从机(slave device)发送多帧序列信息。在同一串行线上使用该功能过程中不需要中断其它从机设备工作。该功能只能在模式2或模式3下进行。用户设置SM2(SCON.5)为1打开这个功能,以便当一个数据帧接收后,当第9位为1时,串口中断将产生(模式2下,第9位为停止位)。当SM2为1时,如果第9位为0,不会发生中断。在该情况下,第9位能简单的把从机地址和数据分开。
    当主机需要向多个从机中的一个发送数据时,首先需要发送目标从机的地址。注,地址字节与数据字节是不同的:在地址字节中,第9位为1。而数据字节中第9位为0。地址字节会触发所有从机,而每台从机检查接收到的

    地址是否与自身匹配。地址匹配的从机,清除SM2,准备接收数据;未被寻址到的从机的SM2 必须保持,从而系统会持续工作,同时忽略接收数据。.
    配置多机通信步骤如下:
    1. 设置所有设备(主机与从机)为串口模式2或3;
    2. 所有从机 SM2 位置为1;
    3. 主机传输协议:
    – 第一个字节:地址,目标从机地址 (第9位 = 1)
    – 下一个字节:数据, (第9位 = 0)。
    4. 当目标从机接收到第一个字节, 因为第9位数据为1所有从机将中断。目标从机比较自身地址并且清SM2 位等待接收后面的数据。其它从机则继续正常运行。

    5. 接收到所有数据后,置 SM2 为 1 等待下一地址。
    SM2 在模式 0 下无效。若 SM2 置 1,模式1可用于检测有效的停止位。同时将不会产生中断除非有效停止位已经接收。
    13.8 自动地址识别
    自动地址识别功能提高了多机通讯功能,允许UART通过硬件比较,来识别特别的地址信息在接收的比特流中。该功能可以节省软件识别地址而所占用的程序空间,仅当串口识别到自身地址时,接收器置位RI位并请求中断。当多机通信特征使能时(SM2置位),就使能自动地址识别。
    如果需要,用户可以在模式1下使能自动地址识别功能。在这种配置下,停止位取代第九位的数据位。仅当接收命令的帧地址与器件地址匹配和有效的停止位时,RI置位。

    使用自动地址识别功能,允许一个主机通过从机地址选择性与一个或几个从机通信。所有从机可以通过“广播”地址联系。有两个特殊功能寄存器用于定义从机地址 SADDR和从机地址掩码SADEN。 SADEN 用于定义SADDR的哪些位被用,哪些位不必关心. SADEN掩码可以与SADDR以“逻辑与”的方式以创建每个从机的“Given” 地址。使用 “Given”地址允许多从机被识别。

     

    下列范例用以说明该功能的灵活应用
    范例 1, 从机 0:
    SADDR = 11000000b
    SADEN = 11111101b
    Given = 110000X0b
    范例 2, 从机 1:
    SADDR = 11000000b
    SADEN = 11111110b
    Given = 1100000Xb
    在上面的例子中SADDR是相同的,SADEN的数据用于区分两个从机。从机0要求位0为” ”而忽略位1,从机1要求位1为” ”而位0被忽略。一个从机0唯一的地址11000010B,由于从机1要求位1为0。一个从机1唯一的地址将自1位11000001b将排除从机0。这两个从机可以选择在同一时间,地址位0 = 0(从机0)和第1位= 0(从机1)。因此,使用广播地址(Boadcast address) 11000000b就可以同时寻址。
    更复杂应用可用于排除从机0之后,选择从机1或2:

    范例 1, 从机 0:
    SADDR = 11000000b
    SADEN = 11111001b
    Given = 11000XX0b
    范例 2, 从机 1:
    SADDR = 11100000b
    SADEN = 11111010b
    Given = 11100X0Xb
    范例 3, 从机 2:
    SADDR = 11000000b
    SADEN = 11111100b
    Given = 110000XXb
    在上面的例子中,3个从机的分别是在地址的低3位。从机0要求位0 = 0,它可用11100110b解决。从机1要求位1= 0,它可用11100101b识别。从机2要求位2= 0,其独立的地址是11100011b。要选择从机0和1,去除从机2,可使用地址11100100b,因为它是必要的第2位= 1来排除从机2。
    每个从机的“广播”地址的计算是通过逻辑或SADDR和SADEN。结果中的零位被视为“无关”位。例如:

    SADDR = 01010110b
    SADEN = 11111100b
    Broadcast = 1111111Xb
    使用“无关”位可在广播模式下,提供更灵活的应用。不过在大部分应用条件下,广播地址全部使用FFH。
    复位后,SADDR和SADEN初始化为00H。这将对于所有“无关”地址产生一个“Given”地址,以及一个“广播”地址对应所有XXXXXXXXb地址(所有“无关”位)。这样有效地禁止了自动寻址模式,允许微控制器保持标准串口模式而不使用这个功能。

    N76E003属于增强型51内核单片机,一般这种都是提供简单的串口UART使用的。
    那么我们先看这个单片机一共几个串口。
    手册中提到:N76E003包含两个具备增强的自动地址识别和帧错误检测功能的全双工串口。也就是2个串口。分别叫串口0和串口1.
    我们也可以从手册发现每个串口具备4种模式,见下表

    官方有提供的例程来操作这两个串口,全部是最常用的模式1
    串口0可以使用定时器1或者定时器3产生波特率,并提供了对应的收发函数
    串口1可以使用定时器3产生波特率,并提供了对应的收发函数。
    基本上大家也用不上其他模式的。常规的应用足够了,我至今还没有用过串口的其他模式。
    如果需要,可以参考这个库函数进行对应的寄存器修改。

    关于波特率,我在定时器的博客上有描述

    #include "N76E003.h"
    #include "Common.h"
    #include "Delay.h"
    #include "SFR_Macro.h"
    #include "Function_define.h"
    
    /******************************************************************************
     * FUNCTION_PURPOSE: Serial interrupt, echo received data.
     * FUNCTION_INPUTS : P0.7(RXD) serial input
     * FUNCTION_OUTPUTS: P0.6(TXD) serial output
     * Following setting in Common.c
     ******************************************************************************/
    #if 0
    //void InitialUART0_Timer1(UINT32 u32Baudrate)    //T1M = 1, SMOD = 1
    //{
    //        P06_Quasi_Mode;        
    //        P07_Quasi_Mode;
    //    
    //    SCON = 0x52;     //UART0 Mode1,REN=1,TI=1
    //    TMOD |= 0x20;    //Timer1 Mode1
    //    
    //    set_SMOD;        //UART0 Double Rate Enable
    //    set_T1M;
    //    clr_BRCK;        //Serial port 0 baud rate clock source = Timer1
    
    // 
    //#ifdef FOSC_160000
    //    TH1 = 256 - (1000000/u32Baudrate+1);               /*16 MHz */
    //#endif        
    //    set_TR1;
    //}
    ////---------------------------------------------------------------
    //void InitialUART0_Timer3(UINT32 u32Baudrate) //use timer3 as Baudrate generator
    //{
    //        P06_Quasi_Mode;
    //        P07_Quasi_Mode;    
    //    
    //    SCON = 0x52;     //UART0 Mode1,REN=1,TI=1
    //    set_SMOD;        //UART0 Double Rate Enable
    //    T3CON &= 0xF8;   //T3PS2=0,T3PS1=0,T3PS0=0(Prescale=1)
    //    set_BRCK;        //UART0 baud rate clock source = Timer3
    
    //#ifdef FOSC_160000
    //    RH3    = HIBYTE(65536 - (1000000/u32Baudrate)-1);          /*16 MHz */
    //  RL3    = LOBYTE(65536 - (1000000/u32Baudrate)-1);            /*16 MHz */
    //#endif
    //    set_TR3;         //Trigger Timer3
    //}
    #endif
    
    /*******************************************************************************
     * FUNCTION_PURPOSE: Main function 
     ******************************************************************************/
    void main (void)
    {
    
    #if 0    
        InitialUART0_Timer1(9600);           //UART0 Baudrate initial,T1M=0,SMOD=0
        while(1)
        Send_Data_To_UART0(0x55);
    #else
            InitialUART0_Timer3(115200);
        while(1)
        Send_Data_To_UART0(0x55);
    #endif
                
        
            
    }
      
    //void InitialUART0_Timer1(UINT32 u32Baudrate)    //T1M = 1, SMOD = 1
    //{
    //        P06_Quasi_Mode;        
    //        P07_Quasi_Mode;
    //    
    //    SCON = 0x52;     //UART0 Mode1,REN=1,TI=1
    //    TMOD |= 0x20;    //Timer1 Mode1
    //    
    //    set_SMOD;        //UART0 Double Rate Enable
    //    set_T1M;
    //    clr_BRCK;        //Serial port 0 baud rate clock source = Timer1
    
    // 
    //#ifdef FOSC_160000
    //    TH1 = 256 - (1000000/u32Baudrate+1);               /*16 MHz */
    //#endif        
    //    set_TR1;
    //}

     

    SCON = 0x52; //01010010 SM0=0,SM1=1即为模式一,REN=1,打开串口0在模式1,2或3模式下的接收功能。TI=1串口发送中断标志位,在发送到数据最后一位后由硬件置位。当串口0中断使能,将执行中断服务程序。该位必须由软件来清除。

    
    
     TMOD |= 0x20;    //Timer1 Mode2

    set_SMOD;

    #define set_SMOD PCON |= SET_BIT7

    #define SET_BIT7        0x80

    #define set_T1M     CKCON   |= SET_BIT4

    #define set_BRCK T3CON |= SET_BIT5

    #ifdef FOSC_160000
    TH1 = 256 - (1000000/u32Baudrate+1); /*16 MHz */
    #endif
    #ifdef FOSC_166000
    TH1 = 256 - (1037500/u32Baudrate); /*16.6 MHz */
    #endif
    set_TR1;
    set_TI; //For printf function must setting TI = 1
    }

    方式1的波特率=      即   (2^smod /32)*T1的溢出率,即  ((2^smod /32)*16000000)/(256-x)

    通常都是固定的,一般都是根据所使用的波特率来求定时器初值。

    TH1 = 256 - (1000000/u32Baudrate+1); 
    256-TH1-1=1000000/u32Baudrate

    u32Baudrate=1000000/(256-TH1-1)

    set_TR1;


    set_TI; //For printf function must setting TI = 1

    void Send_Data_To_UART0 (UINT8 c)
    {
        TI = 0;
        SBUF = c;
        while(TI==0);
    }

     下面这个是一个串口零模式1的小案例

    #include <stdio.h>
    #include "N76E003.h"
    #include "Common.h"
    #include "Delay.h"
    #include "SFR_Macro.h"
    #include "Function_Define.h"
    
    /******************************************************************************
     * FUNCTION_PURPOSE: Serial interrupt, echo received data.
     * FUNCTION_INPUTS : P0.7(RXD) serial input
     * FUNCTION_OUTPUTS: P0.6(TXD) serial output
     * Following setting in Common.c
     ******************************************************************************/
    #if 0
    //void InitialUART0_Timer1(UINT32 u32Baudrate)    //T1M = 1, SMOD = 1
    //{
    //        P06_Quasi_Mode;        
    //        P07_Quasi_Mode;
    //    
    //    SCON = 0x52;     //UART0 Mode1,REN=1,TI=1
    //    TMOD |= 0x20;    //Timer1 Mode1
    //    
    //    set_SMOD;        //UART0 Double Rate Enable
    //    set_T1M;
    //    clr_BRCK;        //Serial port 0 baud rate clock source = Timer1
    
    // 
    //#ifdef FOSC_160000
    //    TH1 = 256 - (1000000/u32Baudrate+1);               /*16 MHz */
    //#endif        
    //    set_TR1;
    //}
    ////---------------------------------------------------------------
    //void InitialUART0_Timer3(UINT32 u32Baudrate) //use timer3 as Baudrate generator
    //{
    //        P06_Quasi_Mode;
    //        P07_Quasi_Mode;    
    //    
    //    SCON = 0x52;     //UART0 Mode1,REN=1,TI=1
    //    set_SMOD;        //UART0 Double Rate Enable
    //    T3CON &= 0xF8;   //T3PS2=0,T3PS1=0,T3PS0=0(Prescale=1)
    //    set_BRCK;        //UART0 baud rate clock source = Timer3
    
    //#ifdef FOSC_160000
    //    RH3    = HIBYTE(65536 - (1000000/u32Baudrate)-1);          /*16 MHz */
    //  RL3    = LOBYTE(65536 - (1000000/u32Baudrate)-1);            /*16 MHz */
    //#endif
    //    set_TR3;         //Trigger Timer3
    //}
    #endif
    
    void DelayTime(UINT32 u32CNT)
    {
        UINT32 i;
        i=u32CNT;
        while(i--);
        
        
    }
    
    
    /*******************************************************************************
     * FUNCTION_PURPOSE: Main function 
     ******************************************************************************/
    void main (void)
    {
    
    #if 1    
        InitialUART0_Timer1(9600);                        //UART0 Baudrate from Timer1
        while(1)
            {
          Send_Data_To_UART0(0x33);
             
                Timer0_Delay1ms(500);//ÑÓʱ500mS
            
            }
    #else
            InitialUART0_Timer3(115200);                    //UART0 Baudrate from Timer3
        while(1)
            {
                Send_Data_To_UART0(0x55);
                Timer0_Delay1ms(500);   //ÑÓʱ500mS
            }
    #endif
                
    
            
            
    }

     串口0可选定时器3或定时器1,我们再看一下,串口零 模式三

    模式2为全双工异步通信, 模式2是11位收发。数据由起始位(逻辑0),8位数据(最低位在前),第9位数据(TB8或RB8)和停止位(逻辑1)组成。第9位做奇偶校验位或多机通信时用来区分数据和地址。波特率是系统时钟频率的1/32 或1/64,由 SMOD位(PCON.7)来配置。图13‑3 指示串口模式2的传输时序。

    串口零模式三 要采用定时器1做时钟。

    #include "N76E003.h"
    #include "SFR_Macro.h"
    #include "Common.h"
    #include "Delay.h"
    #include "Function_define.h"
    
    #define BUFFER_SIZE        16
    UINT8  UART_BUFFER[BUFFER_SIZE],temp;
    UINT16 u16CNT=0,u16CNT1=0;
    bit riflag;
    
    
    /**
     * FUNCTION_PURPOSE: serial interrupt, echo received data.
     * FUNCTION_INPUTS: P0.7(RXD) serial input
     * FUNCTION_OUTPUTS: P0.6(TXD) serial output
     */
    void SerialPort0_ISR(void) interrupt 4 
    {
        if (RI==1) 
        {                                       /* if reception occur */
            clr_RI;                             /* clear reception flag for next reception */
            UART_BUFFER[u16CNT] = SBUF;
            u16CNT ++;
                    riflag =1;
        }
        if(TI==1)
        {
            clr_TI;                             /* if emission occur */
        }
    }
    
    /************************************************************************************************************
    *    Main function 
    ************************************************************************************************************/
    void main (void)
    {
            P12_PushPull_Mode;
            P06_Quasi_Mode;
            P07_Quasi_Mode;
        
            SCON = 0xD0;            // Special setting the mode 3 and 
            TMOD |= 0x20;        //Timer1 Mode1
        
        set_SMOD;            //UART0 Double Rate Enable
        set_T1M;             //sys clk
        clr_BRCK;            //Serial port 0 baud rate clock source = Timer1
            TH1 = 256 - (1000000/115200+1);               /*16 MHz */
            set_TR1;
        
            set_RB8;                    //This bit is for setting the stop bit 2 high/low status, 
        
            clr_TI; 
        set_ES;           //enable UART interrupt
        set_EA;           //enable global interrupt
    
        while(1)
            {
                if (riflag)
                {
                    P12 = ~P12;        //In debug mode check UART_BUFFER[u16CNT] to check receive data
                    riflag = 0;
                }
            }
        
    }

    接下来,是串口一,对于串口1,只有采用定时器3作为唯一的时钟源。

    #include "N76E003.h"
    #include "Common.h"
    #include "Delay.h"
    #include "SFR_Macro.h"
    #include "Function_define.h"
    
    #define BUFFER_SIZE        16
    UINT8  UART_BUFFER[BUFFER_SIZE],temp;
    UINT16 u16CNT=0,u16CNT1=0;
    bit riflag;
    
    /******************************************************************************
     * FUNCTION_PURPOSE: Serial port 1 interrupt, echo received data.
     * FUNCTION_INPUTS : P0.2(RXD) serial input
     * FUNCTION_OUTPUTS: P1.6(TXD) serial output
     * Following setting in Common.c
     ******************************************************************************/
    #if 0
    //void InitialUART1_Timer3(UINT32 u32Baudrate) //use timer3 as Baudrate generator
    //{
    //        P02_Quasi_Mode;        //Setting UART pin as Quasi mode for transmit
    //        P16_Quasi_Mode;        //Setting UART pin as Quasi mode for transmit
    //    
    //      SCON_1 = 0x50;       //UART1 Mode1,REN_1=1,TI_1=1
    //    T3CON = 0x08;       //T3PS2=0,T3PS1=0,T3PS0=0(Prescale=1), UART1 in MODE 1
    //        clr_BRCK;
    //    
    //#ifdef FOSC_160000
    //        RH3    = HIBYTE(65536 - (1000000/u32Baudrate)-1);          /*16 MHz */
    //        RL3    = LOBYTE(65536 - (1000000/u32Baudrate)-1);            /*16 MHz */
    //#endif
    //#ifdef FOSC_166000
    //        RH3    = HIBYTE(65536 - (1037500/u32Baudrate));              /*16.6 MHz */
    //        RL3    = LOBYTE(65536 - (1037500/u32Baudrate));                /*16.6 MHz */
    //#endif
    //    set_TR3;         //Trigger Timer3
    //}
    #endif
    
    void SerialPort1_ISR(void) interrupt 15 
    {
        if (RI_1==1) 
        {                                       /* if reception occur */
            clr_RI_1;                             /* clear reception flag for next reception */
            UART_BUFFER[u16CNT] = SBUF_1;
            u16CNT ++;
                    riflag =1;
        }
        if(TI_1==1)
        {
            clr_TI_1;                             /* if emission occur */
        }
    }
    
    
    /****************************************************************************************************************
     * FUNCTION_PURPOSE: Main function 
      
     !!! N76E003 UART1 pin also occupied by debug pin, 
     please remove Nu-link or not in debug mode to test UART1 function.
    
     External UART1 connect also disturb debug download
    
     ***************************************************************************************************************/
    void main (void)
    {
        P12_PushPull_Mode;        // For I/O toggle display
        
    #if 0    
    //for Simple use UART1 transmit out
            InitialUART1_Timer3(115200);        
        while(1)
        Send_Data_To_UART1(0x55);
            
    #else            
    // For interrupt setting check receive 
            InitialUART1_Timer3(115200);
            set_ES_1;                    //For interrupt enable
            set_EA;
            
            while(1)
            {
                if (riflag)
                {
                        P12 = ~ P12;            //Receive each byte P12 toggle, never work under debug mode
                        riflag = 0;
                }
            }
    
    #endif
              
            
    }
    void InitialUART1_Timer3(UINT32 u32Baudrate) //use timer3 as Baudrate generator
    {
            P02_Quasi_Mode;        //Setting UART pin as Quasi mode for transmit
            P16_Quasi_Mode;        //Setting UART pin as Quasi mode for transmit
        
          SCON_1 = 0x50;       //UART1 Mode1,REN_1=1,TI_1=1
        T3CON = 0x08;       //T3PS2=0,T3PS1=0,T3PS0=0(Prescale=1), UART1 in MODE 1
            clr_BRCK;
        
    #ifdef FOSC_160000
            RH3    = HIBYTE(65536 - (1000000/u32Baudrate)-1);          /*16 MHz */
            RL3    = LOBYTE(65536 - (1000000/u32Baudrate)-1);            /*16 MHz */
    #endif
    #ifdef FOSC_166000
            RH3    = HIBYTE(65536 - (1037500/u32Baudrate));              /*16.6 MHz */
            RL3    = LOBYTE(65536 - (1037500/u32Baudrate));                /*16.6 MHz */
    #endif
        set_TR3;         //Trigger Timer3
    }

    SCON_1 = 0x50; //UART1 Mode1,REN_1=1,TI_1=1

    
    
     T3CON = 0x08;       //T3PS2=0,T3PS1=0,T3PS0=0(Prescale=1), UART1 in MODE 1

     

    #ifdef FOSC_160000
            RH3    = HIBYTE(65536 - (1000000/u32Baudrate)-1);          /*16 MHz */
            RL3    = LOBYTE(65536 - (1000000/u32Baudrate)-1);            /*16 MHz */
    #endif
    #ifdef FOSC_166000
            RH3    = HIBYTE(65536 - (1037500/u32Baudrate));              /*16.6 MHz */
            RL3    = LOBYTE(65536 - (1037500/u32Baudrate));              /*16.6 MHz */
    #endif
      set_TR3;         //Trigger Timer3

     

     set_ES_1;                    //For interrupt enable
            set_EA;

    串口1只能用定时器3,串口0只能做定时器1或3,但是串口0模式三只能用定时器1,串口零其他模式正常

    还有一个比较重要的问题,由于ICP烧录的时候,与串口一是重合的,由于是引脚复用的关系,所以串口功能发生作用时,就会出现烧录不进去的情况,这时只需要让串口收发不了数据就能烧录程序了。

    
    
  • 相关阅读:
    CentOS 6找不到partprobe命令的解决方法
    RTL源码归类与路径
    拓扑排序
    Char、AnsiChar、WideChar、PChar、PAnsiChar、PWideChar 的区别
    Delphi Byte与数据类型之间的转换
    Delphi byte[]转换为int
    Delphi Byte数组与Int String之间的相互转换
    delphi TTcpClient TTcpServer分析
    Delph7中TcpClient和TcpServer用法分析
    动态数组的使用
  • 原文地址:https://www.cnblogs.com/zhugeanran/p/9255167.html
Copyright © 2020-2023  润新知