CH559L单片机常用外设功能-串口介绍

Posted perseverance52

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了CH559L单片机常用外设功能-串口介绍相关的知识,希望对你有一定的参考价值。

【CH559L单片机】常用外设功能-串口介绍


  • ✨说明:这里不做串口原理实现的底层协议解析,仅对串口的使用相关内容进行介绍。
  • 📍外设示例资源WCH官方:https://www.wch.cn/products/CH559.html

📖CH559-通用异步收发器(UART)

  • 🔖CH559 芯片提供 2 个全双工的异步串口:UART0UART1

📑UART0 是标准 MCS51 串口,其数据接收和发送是通过 SBUF 访问物理上分开的收/发寄存器实现的。写入 SBUF 的数据装入发送寄存器,对 SBUF 的读操作则对应于接收缓冲寄存器。

  • ⛳不管是串口1还是串口0,通常情况下,我们只需掌握在工作模式1(8 位异步通信方式,波特率可变。)的情况下使用即可。

🌼UART0 应用:

(1)、🌿选择 UART0 的波特率发生器,可以选择来自定时器 T1 或者 T2,并配置相应计数器。
(2)、🌿开启定时器。
(3)、🌿设置 SCON 的 SM0、SM1、SM2 选择串口 0 的工作模式。设置 REN 为 1,使能 UART0 接收。
(4)、🌿可以设置串口中断或者查询 RI 和 TI 中断状态。
(5)、🌿读写 SBUF 实现串口数据收发,串口接收信号的允许波特率误差不大于 2%。

🌻UART1 应用:

(1)、🌿设置 SER1_LCR 的位 bLCR_DLAB 为 1,写 UART1 预分频寄存器 SER1_DIV,根据波特率计算波特率除数,除数=Fsys/8/SER1_DIV/波特率,除数高低字节分别写入 SER1_DLM 和 SER1_DLL。
(2)、🌿设置 SER1_LCR,选择合适的串口数据格式,数据字节和奇偶校验模式等。
(3)、🌿可选设置 SER1_IER,选择 UART1 中断状态触发。
(4)、🌿如果使用中断方式那么需要将 SER1_MCR 的位 bMCR_OUT2 置 1,使能中断输出;否则需要主动查询中断状态位。
(5)、🌿读写 SER1_FIFO 实现串口数据收发,串口接收信号的允许波特率误差不大于 2%。

📋UART 相关寄存器

  • 🌿UART0 控制寄存器(SCON):

🌷UART0 工作模式选择

📑在模式 1 和 3 下,当 RCLK=0 并且 TCLK=0 时,UART0 波特率由定时器 T1 产生。应该设置 T1 为
模式 2 自动重载 8 位定时器模式,bT1_CT 和 bT1_GATE 必须都为 0,分为以下几类时钟情况。

📑在模式 1 和 3 下,当 RCLK=1 或者 TCLK=1 时,UART0 波特率由定时器 T2 产生。应该设置 T2 为
16 位自动重载波特率发生器模式,C_T2 和 CP_RL2 必须都为 0,分为以下几类时钟情况。


UART0 数据寄存器(SBUF):

  • 📝USART0 初始化代码
/*******************************************************************************
* Function Name  : mInitSTDIO()
* Description    : CH559串口0初始化,默认使用T1作UART0的波特率发生器,也可以使用T2
                   作为波特率发生器
* Input          : None
* Output         : None
* Return         : None
*******************************************************************************/
void	mInitSTDIO( )

    UINT32 x;
    UINT8 x2; 
    SM0 = 0;//UART0 工作方式选择位 0,该位为 0 选择 8 位数据异步通信;该位为
1 选择 9 位数据异步通信
    SM1 = 1;//UART0 工作方式选择位 1,该位为 0 设置固定波特率;该位为 1 设置
可变波特率,由定时器 T1 或者 T2 产生
    SM2 = 0; //串口0使用模式1
//使用Timer1作为波特率发生器
    RCLK = 0;//UART0接收时钟
    TCLK = 0; //UART0发送时钟
    PCON |= SMOD;//电源控制寄存器
    x = 10 * FREQ_SYS / BUAD / 16;//如果更改主频,注意x的值不要溢出                            
    x2 = x % 10;
    x /= 10;
    if ( x2 >= 5 ) x ++;  //四舍五入

    TMOD = TMOD & ~ bT1_GATE & ~ bT1_CT & ~ MASK_T1_MOD | bT1_M1; //0X20,Timer1作为8位自动重载定时器
    T2MOD = T2MOD | bTMR_CLK | bT1_CLK;   //Timer1时钟选择
    TH1 = 0-x;  //12MHz晶振,buad/12为实际需设置波特率
    TR1 = 1; //启动定时器1
    TI = 1;//发送使能
    REN = 1; //串口0接收使能

📝串口0中断服务函数

/*******************************************************************************
* Function Name  : CH559UART0Interrupt()
* Description    : CH559UART0中断处理函数
*******************************************************************************/
void CH559UART0Interrupt( )  interrupt INT_NO_UART0 using 1  //看门狗中断服务程序,使用寄存器组1

    if(TI)
    
        TI = 0; //清空发送中断                        
    
    if(RI)
    
        FLAG = 1;
        RI = 0;  //清空接收中断
        DAT = SBUF;
    

📝串口0映射

/*******************************************************************************
* Function Name  : CH559UART0Alter()
* Description    : CH559串口0引脚映射,串口映射到P0.2和P0.3
* Input          : None
* Output         : None
* Return         : None
*******************************************************************************/
void CH559UART0Alter()

    PORT_CFG |= bP0_OC;
    P0_DIR |= bTXD_;//输入输出方向设置
    P0_PU |= bTXD_ | bRXD_;//IO口模式设置
    PIN_FUNC |= bUART0_PIN_X; //串口映射到P0.2和P0.3

✨UART1 配置相对于串口0要复杂一些,里面涉及到有关RS485通讯功能的部分,相关寄存器不做过多介绍了。

  • 串口1初始函数代码
/*******************************************************************************
* Function Name  : CH559UART1Init(UINT8 DIV,UINT8 mode,UINT8 pin)
* Description    : CH559 UART1初始化设置
* Input          : 
                   UINT8 DIV设置分频系数,时钟频率=Fsys/DIV,DIV不能为0
                   UINT8 mode,模式选择,1:普通串口模式;0:485模式
                   UINT8 pin,串口引脚选择;
                   当mode=1时
                   0:RXD1=P4.0,TXD1关闭;
                   1:RXD1&TXD1=P4.0&P4.4;
                   2:RXD1&TXD1=P2.6&P2.7;
                   3:RXD1&TXD1&TNOW=P2.6&P2.7&P2.5;
                   当mode=0时
                   0:无意义
                   1:P5.4&P5.5连接485,TNOW=P4.4;
                   2:P5.4&P5.5连接485;
                   3:P5.4&P5.5连接485,TNOW=P2.5;
* Output         : None
* Return         : None
*******************************************************************************/
void CH559UART1Init(UINT8 DIV,UINT8 mode,UINT8 pin)

    UINT32 x;
    UINT8 x2; 

    SER1_LCR |= bLCR_DLAB;                                                    // DLAB位置1,写DLL、DLM和DIV寄存器
    SER1_DIV = DIV;                                                           // 预分频
    x = 10 * FREQ_SYS *2 / DIV / 16 / CH559UART1_BPS;                             
    x2 = x % 10;
    x /= 10;
    if ( x2 >= 5 ) x ++;                                                      //四舍五入
    SER1_DLM = x>>8;
    SER1_DLL = x&0xff;
    SER1_LCR &= ~bLCR_DLAB;                                                   //DLAB位置0,防止修改UART1波特率和时钟
    if(mode == 1)                                                             //关闭RS485模式 RS485_EN = 0,不能省略
    
	      XBUS_AUX |=  bALE_CLK_EN;                                     
    
    else if(mode == 0)                                                        //开启RS485模式 RS485_EN = 1;
    
        UHUB1_CTRL |= bUH1_DISABLE;                                   
        PIN_FUNC &= ~bXBUS_CS_OE;
        PIN_FUNC |= bXBUS_AL_OE;
        XBUS_AUX &= ~bALE_CLK_EN;	
        SER1_MCR |= bMCR_HALF; //485模式只能使用半双工模式	    
    
    SER1_LCR |= MASK_U1_WORD_SZ;//线路控制
    SER1_LCR &= ~(bLCR_PAR_EN | bLCR_STOP_BIT);  //无线路间隔,无校验,1位停止位,8位数据位

    SER1_IER |= ((pin << 4) & MASK_U1_PIN_MOD); //串口模式配置
    SER1_IER |= bIER_MODEM_CHG | bIER_LINE_STAT | bIER_THR_EMPTY | bIER_RECV_RDY;//中断使能配置
 
    SER1_FCR |= MASK_U1_FIFO_TRIG | bFCR_T_FIFO_CLR | bFCR_R_FIFO_CLR | bFCR_FIFO_EN;//FIFO控制器
 //清空接收、发送FIFO,7字节接收触发,FIFO使能
    SER1_MCR |= bMCR_OUT2;  //MODEM控制寄存器
//中断请求输出,不产生实际中断
    SER1_ADDR |= 0xff;//关闭多机通信

📑串口1中断服务函数

/*******************************************************************************
* Function Name  : UART1Interrupt(void)
* Description    : UART1中断服务程序 
*******************************************************************************/
void	UART1Interrupt( void ) interrupt INT_NO_UART1 using 1                 //UART1中断服务程序,使用寄存器组1

    UINT8 InterruptStatus,i,tmp; 
    InterruptStatus = SER1_IIR & 0x0f;                                        //获取中断状态 
//	printf("InterruptStatus %02X\\n",(UINT16)InterruptStatus);
    switch(InterruptStatus)
    
        case U1_INT_RECV_RDY: //接收数据可用中断,可以先读取指定字节数触发中断的数据个数
           Num = CH559UART1Rcv(buffer);
           tmp = Num;
//           while(Num--)
//           
//               printf("%02X  ",(UINT16)buffer[Num]);
//           
			     for(i = 0;i < tmp;i++)
			     
				       CH559UART1SendByte(buffer[i]);//将接受到的数据,转发出去
			     
			   break;				
        case U1_INT_RECV_TOUT://接收超时中断
             Num = CH559UART1Rcv(buffer);
           tmp = Num;
//             while(Num--)
//             
//                 printf("%02X  ",(UINT16)buffer[Num]);
//             
			     for(i = 0;i < tmp;i++)
			     
				       CH559UART1SendByte(buffer[i]);
			     
			    break;		
        case U1_INT_LINE_STAT:                                                //线路状态中断
			   break;		
        case U1_INT_SLV_ADDR:                                                 //设备地址match中断
			   break;			
        case U1_INT_NO_INTER:                                                 //无中断
          break;		
        case U1_INT_MODEM_CHG:                                                //MODEM中断
		         i = SER1_MSR;
         break;	
        case U1_INT_THR_EMPTY:                                                //发送空中断,可以启动下次发送或者等待接收
			   break;
        default:
         break;
	                                                                    

🔖串口1引脚选择位配置介绍

CH559UART1Init(1,1,2);//RXD1&TXD1=P2.6&P2.7
CH559UART1Init(1,1,1);//RXD1&TXD1=P4.0&P4.4;

以上是关于CH559L单片机常用外设功能-串口介绍的主要内容,如果未能解决你的问题,请参考以下文章

CH559L单片机DMA方式在手工选择通道模式下AD采样数据串口输出

CH559L单片机串口下载程序说明

CH559l单片机入门篇通过串口打印内部ID信息

CH559L单片机PWM功能和示例介绍

CH559L单片机PWM功能和示例介绍

CH559L单片机基于Arduino框架下实现USB CDC虚拟串口打印ADC数据