IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 嵌入式 -> 【CH559L单片机】常用外设功能-串口介绍 -> 正文阅读

[嵌入式]【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;
  嵌入式 最新文章
基于高精度单片机开发红外测温仪方案
89C51单片机与DAC0832
基于51单片机宠物自动投料喂食器控制系统仿
《痞子衡嵌入式半月刊》 第 68 期
多思计组实验实验七 简单模型机实验
CSC7720
启明智显分享| ESP32学习笔记参考--PWM(脉冲
STM32初探
STM32 总结
【STM32】CubeMX例程四---定时器中断(附工
上一篇文章      下一篇文章      查看所有文章
加:2022-10-17 12:50:48  更:2022-10-17 12:53:28 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/25 20:26:51-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码