几乎所有的单片机都会集成UART外设,但是调试MSP430的UART功能比想象的要有挑战性也更有乐趣。MSP430的UART外设提供了更丰富的硬件可定制性,允许用户使用更简洁的代码和更少的外围器件,实现非常实用的功能,比如address选择、break信号、baudrate自动检测等等。当然,UART外设有丰富的时钟选项,32.768KHZ的ACLK时钟源也可以被使用,CPU可以最大限度的处于未唤醒状态,这是为低功耗而考虑的设计。
(USI外设:Universal Serial Interface,提供这一功能的MSP430型号并不多,在调试它之前得先确认是否具备它,MSP430F2616不提供USI外设,所以直接从USCI开始。)
USCI外设:Universal Serial Communication Interface,大部分单片机会将UART、SPI、I2C外设功能分开,它们通常会使用不一样的IO引脚,不共用寄存器和中断向量;MSP430将这些外设功能集成到USCI中,它支持不同的(UART、SPI、I2C)模式,不同模式之间虽然不共用IO引脚,但是却共用寄存器和中断向量。USCI之间以不同的字母后缀来命名,比如USCI_A和USCI_B;如果有两个USCI_A,则命名为USCI_A0和USCI_A1。
其中,USCI_Ax支持UART、SPI、IrDA模式。如果需要使用UART功能,就需要设置USCI_Ax对应的IO引脚、寄存器和中断服务程序。相应的,USCI包含的SPI功能也就无法再使用。
这里UART使用的时钟是SMCLK(MCLK不能作为UART的时钟,而只能从UCLK(?)、ACLK、SMCLK中选择),默认的SMCLK来自DCOCLK,也就是MSP430自带的Digitally Controlled Oscillator时钟,IO引脚使用的是P3.4/P3.5,从数据手册可以看到它们是UART外设的专用引脚。将波特率设置为9600,分频值在数据手册中有表可查。
由于UART的接受通常使用中断,所以这里还要使能全局中断和UART接收中断。
/**********************************************************************/
uint32_t uart_rx_count = 0;
#pragma vector=USCIAB0RX_VECTOR
__interrupt void USCI0RX_ISR(void)
{
dma_temp_A[0] = UCA0RXBUF;
uart_rx_count++;
HC595_disdata_4bytes(uart_rx_count);
}
int main (void)
{
uint16_t i = 0;
WDTCTL = WDTPW + WDTHOLD;
// 等待DCOCLK稳定,并且将它调整为1MHz,而系统启动时的默认值是1.1MHz
if (CALBC1_1MHZ == 0xFF || CALDCO_1MHZ == 0xFF)
while(1);
BCSCTL1 = CALBC1_1MHZ;
DCOCTL = CALDCO_1MHZ;
// 开启全局中断
__bis_SR_register(GIE);
led_init();
HC595_init();
// 首先关断UART
// 选择时钟为SMCLK
// UCA0BR0、UCA0BR、UCA0MCTL的值在9600波特率,可查询技术手册提供的表格
UCA0CTL1 |= UCSWRST;
UCA0CTL1 |= UCSSEL_2;
UCA0BR0 = 104;
UCA0BR1 = 0;
UCA0MCTL = (0 << 4) + (1 << 1);
// 设置IO口的外设功能
// 启动UART
// 使能UART的接收中断
P3SEL = 0x30;
UCA0CTL1 &= ~UCSWRST;
IE2 |= UCA0RXIE;
while (1) {
for (i = 'A'; i <= 'Z'; i++) {
while (!(IFG2 & UCA0TXIFG));
UCA0TXBUF = i;
}
while (!(IFG2 & UCA0TXIFG));
UCA0TXBUF = '\r';
while (!(IFG2 & UCA0TXIFG));
UCA0TXBUF = '\n';
}
return 0;
}
/********************************************************************/
MSP430的技术手册提供了不同波特率对应的寄存器表格,观察这个表格就会发现,以1MHz的SMCLK作为时钟源时,115200波特率实际上会有一个不可忽视的误差值,在实际应用中可能要注意它带来的影响。
当使用串口调试软件发送数据时,中断服务程序就会将当前接收到的个数显示在74HC595驱动的4位数码管上面。串口和液晶由于显示事件比较长,并不适合放进中断服务程序,实际上,显示4位8段数码管也需要不短的时间,因此在中断函数中写标志位、在主函数中显示,还是更加合理的选择。