【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):
void mInitSTDIO( )
{
UINT32 x;
UINT8 x2;
SM0 = 0;
1 选择 9 位数据异步通信
SM1 = 1;
可变波特率,由定时器 T1 或者 T2 产生
SM2 = 0;
RCLK = 0;
TCLK = 0;
PCON |= SMOD;
x = 10 * FREQ_SYS / BUAD / 16;
x2 = x % 10;
x /= 10;
if ( x2 >= 5 ) x ++;
TMOD = TMOD & ~ bT1_GATE & ~ bT1_CT & ~ MASK_T1_MOD | bT1_M1;
T2MOD = T2MOD | bTMR_CLK | bT1_CLK;
TH1 = 0-x;
TR1 = 1;
TI = 1;
REN = 1;
}
📝串口0中断服务函数
void CH559UART0Interrupt( ) interrupt INT_NO_UART0 using 1
{
if(TI)
{
TI = 0;
}
if(RI)
{
FLAG = 1;
RI = 0;
DAT = SBUF;
}
}
📝串口0映射
void CH559UART0Alter()
{
PORT_CFG |= bP0_OC;
P0_DIR |= bTXD_;
P0_PU |= bTXD_ | bRXD_;
PIN_FUNC |= bUART0_PIN_X;
}
?UART1 配置相对于串口0要复杂一些,里面涉及到有关RS485通讯功能的部分,相关寄存器不做过多介绍了。
void CH559UART1Init(UINT8 DIV,UINT8 mode,UINT8 pin)
{
UINT32 x;
UINT8 x2;
SER1_LCR |= bLCR_DLAB;
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;
if(mode == 1)
{
XBUS_AUX |= bALE_CLK_EN;
}
else if(mode == 0)
{
UHUB1_CTRL |= bUH1_DISABLE;
PIN_FUNC &= ~bXBUS_CS_OE;
PIN_FUNC |= bXBUS_AL_OE;
XBUS_AUX &= ~bALE_CLK_EN;
SER1_MCR |= bMCR_HALF;
}
SER1_LCR |= MASK_U1_WORD_SZ;
SER1_LCR &= ~(bLCR_PAR_EN | bLCR_STOP_BIT);
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;
SER1_MCR |= bMCR_OUT2;
SER1_ADDR |= 0xff;
}
📑串口1中断服务函数
void UART1Interrupt( void ) interrupt INT_NO_UART1 using 1
{
UINT8 InterruptStatus,i,tmp;
InterruptStatus = SER1_IIR & 0x0f;
switch(InterruptStatus)
{
case U1_INT_RECV_RDY:
Num = CH559UART1Rcv(buffer);
tmp = Num;
for(i = 0;i < tmp;i++)
{
CH559UART1SendByte(buffer[i]);
}
break;
case U1_INT_RECV_TOUT:
Num = CH559UART1Rcv(buffer);
tmp = Num;
for(i = 0;i < tmp;i++)
{
CH559UART1SendByte(buffer[i]);
}
break;
case U1_INT_LINE_STAT:
break;
case U1_INT_SLV_ADDR:
break;
case U1_INT_NO_INTER:
break;
case U1_INT_MODEM_CHG:
i = SER1_MSR;
break;
case U1_INT_THR_EMPTY:
break;
default:
break;
}
}
🔖串口1引脚选择位配置介绍
CH559UART1Init(1,1,2);
CH559UART1Init(1,1,1);
|