0%

MSP430单片机(五)——USCI-UART模式

前言

USCI模块不仅支持UART模式,还支持SPI模式,在单片机的应用中十分重要。

USCI-UART概述

先简要翻译一下官方手册对USCI-UART模式的描述:

USCI概述

USCI模块支持多种串行通信模式。 不同的USCI模块支持不同的模式。 每个不同的USCI模块均以不同的字母命名。 例如,USCI_A与USCI_B不同,等等。如果在一个设备上实现了多个相同的USCI模块,则这些模块将以递增编号命名。 例如,如果一个设备具有两个USCI_A模块,则它们分别命名为USCI_A0和USCI_A1。

USCI_Ax模块支持:

  • UART模式
  • IrDA通信的脉冲整形
  • LIN通信的自动波特率检测
  • SPI模式

USCI_Bx模块支持:

  • I2C模式
  • SPI模式

UART模式

在异步模式下,USCI_Ax模块通过两个外部引脚UCAxRXD和UCAxTXD将设备连接到外部系统。UCSYNC位清零时,选择UART模式。
UART模式的功能包括:

  • 具有奇校验,偶校验或非奇偶校验的7位或8位数据
  • 独立的发送和接收移位寄存器
  • 单独的发送和接收缓冲寄存器
  • LSB优先或MSB优先数据发送和接收
  • 内置 用于多处理器系统的空闲线路和地址位通信协议
  • 用于从LPMx模式自动唤醒的接收器起始沿检测
  • 带有调制的可编程波特率,支持分数波特率
  • 用于错误检测和抑制的状态标志
  • 状态标志 用于地址检测
  • 具有独立的中断接收和发送功能

UART模式操作

在串口模式下,USCI以一个比特的速率和其他谁被之间进行异步的传输和接收数据。发送每一个字符的时间都是由USCI选择的波特率决定的。发送和接收的功能使用相同的波特率。

操作步骤

初始化:

  • 设置波特率
  • 选择USCI时钟源
  • 设置UART状态机
  • 设置预分频器UCBRx
  • 设置调制器
  • 打开 USCI RX 中断

寄存器说明

USCI_Ax控制寄存器1 USCI_Ax Control Register 1 (UCAxCTL1)
7 6 5 4 3 2 1 0
UCSSELx UCRXEIE UCBRKIE UCDORM UCTXADDR UCTXBRK UCSWRST
rw-0 rw-0 rw-0 rw-0 rw-0 rw-0 rw-0 rw-1

UCSSELx 位7-6 USCI时钟源选择。 这些位选择BRCLK源时钟。
00 UCLK
​ 01 ACLK
​ 10 SMCLK
​ 11 SMCLK
UCRXEIE 位5 接收错误字符中断使能
​ 0-拒绝错误字符且未设置UCRXIFG。
1-收到的错误字符设置为UCRXIFG。
UCBRKIE 位4 接收中断字符中断使能
​ 0-接收到的中断字符未设置UCRXIFG。
1-接收到的断字符设置为UCRXIFG。
UCDORM 位3 休眠。 使USCI进入睡眠模式。
0-不休眠。所有收到的字符都设置为UCRXIFG。
1-休眠。UCRXIFG只设置了空行或地址位之后的字符。 在具有自动波特率检测的UART模式下,只有中断和同步字段的组合才会设置UCRXIFG。
UCTXADDR 位2 发送地址。根据所选的多处理器模式,将要发送的下一帧标记为地址。
0-传输的下一帧是数据。
1-下一个发送的帧是一个地址。
UCTXBRK 位1 发送中断。 下一次写入传输缓冲区时发送中断。 在具有自动波特率检测的UART模式下,必须将055h写入UCAxTXBUF,以生成所需的间隔/同步字段。否则,必须将0h写入发送缓冲区。
0-传输的下一帧不是间断。
1-传输的下一帧是中断或中断/同步。
UCSWRST 位0 软件复位使能
​ 0-禁用。USCI复位已释放以进行操作。
1-启用。USCI逻辑保持在复位状态。

USCI_Ax波特率控制寄存器0 USCI_Ax Baud Rate Control Register 0 (UCAxBR0)
7 6 5 4 3 2 1 0
- - - UCBRx - low byte - - - -
rw rw rw rw rw rw rw rw
USCI_Ax波特率控制寄存器1 USCI_Ax Baud Rate Control Register 1 (UCAxBR1)
7 6 5 4 3 2 1 0
- - - UCBRx - high byte - - - -
rw rw rw rw rw rw rw rw

UCBRx 波特率发生器的时钟预分频器设置。(UCAxBR0 + UCAxBR1×256)的16位值构成了预分频器值UCBRx

USCI_Ax调制控制寄存器 USCI_Ax Modulation Control Register (UCAxMCTL)
7 6 5 4 3 2 1 0
UCBRFx - - - UCBRSx - - UCOS16
rw-0 rw-0 rw-0 rw-0 rw-0 rw-0 rw-0 rw-0

UCBRFx 位7-4 第一个调制级选择。 当UCOS16 = 1时,这些位确定BITCLK16的调制模式。
如果UCOS16 =0,则忽略。表16-3给出了调制模式。
UCBRSx 位3-1 第二调制级选择。 这些位确定BITCLK的调制模式。 表16-2给出了调制模式。
UCOS16 位0 启用过采样模式
​ 0禁用
​ 1启用

USCI_Ax中断允许寄存器 USCI_Ax Interrupt Enable Register (UCAxIE)
7 6 5 4 3 2 1 0
Reserved - - - - - UCTXIE UXRXIE
rw-0 rw-0 rw-0 rw-0 rw-0 rw-0 rw-0 rw-0

保留 位7-2 保留

UCTXIE 位1 发送中断使能 0禁止中断 1允许中断

UCRXIE 位0 接收中断使能 0禁止中断 1允许中断

波特率的计算方法

usart模块的波特率值设定是通过以下三个寄存器决定的: UxBR0, UxBR1, UxMCTL
波特率= BRCLK / N ,主要是计算出N

BRCLK: 时钟源,可以通过寄存器设定何为时钟源; 通过寄存器UCAxCTL1的SSEL两位选择,01:ACLK, 02:SMCLK

N:波特率产生的分频因子。 N=UxBR1+UxBR0+UxMCTL, 其中 UxBR1+UxBR0为整数部分, UxMCTL为设定小数部分,其中 UxBR1为高位, UxBR0为低位,两者结合起来为一个16位的字。

波特率 = 115200 ,时钟源 = 8MHz,为外部晶振,N = 8000000 / 115200 = 69.44。所以 UxBR1+UxBR0=69, 69为十进制数,转换为十六进制为 0x45,所以 UxBR1=0UxBR0=0x45 ,小数部分 0.44 x 8 = 3.52,取4(一般取偶数),则需要四个脉冲插补位(需要几个插补位八位上就需要几个1),因为这里设置 UCOS16=0,所以查看表16-2 ,看到四个插补位的是 UCBRSx = 4 ,01010101的那一组 ,所以 UCAxMCTL 寄存器中的 UCBRSx 设置为 0x04, UCAxMCTL 也就是 0000 1000(0x08)。

再算一组,波特率 = 9600,时钟源 = 16MHz,外部晶振。N = 16000000 / 9600 = 1666.66666. 所以 UxBR1+UxBR0=1666,1666转十六进制0x682(0000 0110 1000 0010),所以 UxBR1=0x06UxBR0=0x82 ,小数部分 0.666666 x 8 = 5.33333,近似取正偶数6,UCBRSx = 6 ,所以 UCAxMCTL = 0x0c(0000 1100).

参数表

UCAxMCTL 7-4位控制BITCLK调制模式:

image-20210124182449137

UCAxMCTL 3-1位控制BITCLK16调制模式:

image-20210124182730186

代码实现

​ 分频器参数:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#if (HAL_BOARD_SYS_FREQ==HAL_BOARD_SYS_FREQ_8M)
/*fDCOCLK=8M , uart para */
/***********baud rate********
BP--- S_1200, S_2400, S_4800, S_9600, S_19200, S_38400, S_57600, S_115200*/
uint16 arUCBRx[8] = { 27, 13, 6, 833, 416, 208, 138, 69 }; // 8MHz/S_Baud ~ _______(十进制数)
/* 0x04; 0x0c; 0x0E; 0x04; 0x0c; 0x06; 0x0E; 0x08 */
uint16 arUCBRSx[8]= { UCBRS_2, UCBRS_6, UCBRS_7, UCBRS_2, UCBRS_6, UCBRS_3, UCBRS_7, UCBRS_4 }; //见调制器参数表 Table16-2
#endif

#if (HAL_BOARD_SYS_FREQ==HAL_BOARD_SYS_FREQ_16M)
/*fDCOCLK=16M , uart para */
/***********baud rate********
BP--- S_1200, S_2400, S_4800, S_9600, S_19200, S_38400, S_57600, S_115200*/
uint16 arUCBRx[8] = { 27, 13, 6, 1666, 833, 416, 208, 138 };
uint16 arUCBRSx[8]= { UCBRS_2, UCBRS_6, UCBRS_7, UCBRS_6, UCBRS_2, UCBRS_6, UCBRS_3, UCBRS_7 };
#endif

​ 初始化程序:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
int InitHalUart(unsigned int uart , unsigned int baud)
{
uint8 unUartClk;
if( baud >= UART_BAUD_DEF_END )
return EP_FAILED;
InitHalUartBuf();
//选择UCSI时钟源
//BAUD <= 4800, UCAxCTL1 置 01,选择ACLK为时钟源
//BAUD > 4800,UCAxCTL1 置 11/10,选择SMCLK为时钟源
switch(baud)
{
case UART_BAUD_1200:
case UART_BAUD_2400:
case UART_BAUD_4800:
unUartClk=UCSSEL__ACLK; // CLK = ACLK
break;
default:
unUartClk=UCSSEL_2; // CLK = SMCLK
break;
}

switch(uart)
{
case HAL_UART_UCA0:
P3SEL |= BIT4 + BIT5;
UCA0CTL1 |= UCSWRST; // **Put state machine in reset**
UCA0CTL1 |= unUartClk; // 选择BRCLK的时钟源
UCA0BR0 = (arUCBRx[baud] & 0xFF); // 低八位赋值BR0
UCA0BR1 = (arUCBRx[baud]>>8)&0xFF; // 高八位赋值BR1
UCA0MCTL = arUCBRSx[baud]; //
UCA0CTL1 &= ~UCSWRST; // **Initialize USCI state machine**
UCA0IE |= UCRXIE; // Enable USCI RX interrupt
break;
case HAL_UART_UCA1:
P5SEL |= BIT6 + BIT7;
UCA1CTL1 |= UCSWRST; // **Put state machine in reset**
UCA1CTL1 |= unUartClk;
UCA1BR0 = (arUCBRx[baud] & 0xFF);
UCA1BR1 = (arUCBRx[baud]>>8)&0xFF;
UCA1MCTL = arUCBRSx[baud];
UCA1CTL1 &= ~UCSWRST; // **Initialize USCI state machine**
UCA1IE |= UCRXIE; // Enable USCI RX interrupt
break;
case HAL_UART_UCA2:
P9SEL |= BIT4 + BIT5;
UCA2CTL1 |= UCSWRST; // **Put state machine in reset**
UCA2CTL1 |= unUartClk;
UCA2BR0 = (arUCBRx[baud] & 0xFF);
UCA2BR1 = (arUCBRx[baud]>>8)&0xFF;
UCA2MCTL = arUCBRSx[baud];
UCA2CTL1 &= ~UCSWRST; // **Initialize USCI state machine**
UCA2IE |= UCRXIE; // Enable USCI RX interrupt
break;
case HAL_UART_UCA3:
//P10DIR |= BIT3;
//P10OUT &= ~BIT3;
P10SEL |= BIT4 + BIT5;
UCA3CTL1 |= UCSWRST; // **Put state machine in reset**
UCA3CTL1 |= unUartClk;
UCA3BR0 = (arUCBRx[baud] & 0xFF);
UCA3BR1 = (arUCBRx[baud]>>8)&0xFF;
UCA3MCTL = arUCBRSx[baud];
UCA3CTL1 &= ~UCSWRST; // **Initialize USCI state machine**
UCA3IE |= UCRXIE; // Enable USCI RX interrupt
break;
}
return EP_SUCCESS;
}
两种颜色的功德箱(逃