CH559L单片机常用外设功能-串口介绍
Posted perseverance52
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了CH559L单片机常用外设功能-串口介绍相关的知识,希望对你有一定的参考价值。
【CH559L单片机】常用外设功能-串口介绍
- ✨说明:这里不做串口原理实现的底层协议解析,仅对串口的使用相关内容进行介绍。
- 📍外设示例资源WCH官方:
https://www.wch.cn/products/CH559.html
📖CH559-通用异步收发器(UART)
- 🔖CH559 芯片提供 2 个全双工的异步串口:
UART0
和UART1
。
📑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单片机常用外设功能-串口介绍的主要内容,如果未能解决你的问题,请参考以下文章