msp430g2553通过定时器A和软件代码配合可以形成串口,即软件串口。当然msp430g2553也有硬件串口,内部有自己完整的uart模块。
内部的uart参考:msp430g2533USCI_A0功能模块硬件串口
一、代码与仿真
在官方例程的基础上,编写了串口通信程序,并硬件测试通过 😉。
硬件测试用板(TI的MSP-EXP430G2ET)
串口测试助手的收发情况
打开板子,电脑端收到
MADE BY PengChengIT.
G2xx2 TimerA UART
READY.
通过电脑端向芯片发字符,发啥收啥。测试成功!
代码说明:
接收:
1、接收啥发啥,通过for循环,持续进行
for(;; )
{
__bis_SR_register(LPM0_bits);
TimerA_UART_tx(rxBuffer);
}
}
2、接收的值存放在rxBuffer缓冲区内。
发送:
1、代码中有发送函数,可以根据需要发送特定的字符;
①TimerA_UART_tx(unsigned char byte),直接向函数输入要发送的字节
②TimerA_UART_print(char *string),可以直接向函数输入要发送的一串文字、数字。
TimerA_UART_print(“MADE BY PengChengIT.\r\n”);
也可以发送字符串
char a_a[]=“pengchengIT”;
TimerA_UART_print(a_a);
引脚
1、P1.1TXD , P1.2RXD
中断
1、用2个中断函数,分别在接收和发送时触发。
#include <msp430.h>
//------------------------------------------------------------------------------
// Hardware-related definitions
//------------------------------------------------------------------------------
#define UART_TXD 0x02 // TXD on P1.1 (Timer0_A.OUT0)
#define UART_RXD 0x04 // RXD on P1.2 (Timer0_A.CCI1A)
//------------------------------------------------------------------------------
// Conditions for 9600 Baud SW UART, SMCLK = 1MHz
//------------------------------------------------------------------------------
#define UART_TBIT_DIV_2 (1000000 / (9600 * 2))
#define UART_TBIT (1000000 / 9600)
//------------------------------------------------------------------------------
// Global variables used for full-duplex UART communication
//------------------------------------------------------------------------------
unsigned int txData; // UART internal variable for TX
unsigned char rxBuffer; // Received UART character
//------------------------------------------------------------------------------
// Function prototypes
//------------------------------------------------------------------------------
void TimerA_UART_init(void);
void TimerA_UART_tx(unsigned char byte);
void TimerA_UART_print(char *string);
//------------------------------------------------------------------------------
// main()
//------------------------------------------------------------------------------
int main(void)
{
WDTCTL = WDTPW + WDTHOLD; // Stop watchdog timer
if (CALBC1_1MHZ==0xFF) // If calibration constant erased
{
while(1); // do not load, trap CPU!!
}
DCOCTL = 0; // Select lowest DCOx and MODx settings
BCSCTL1 = CALBC1_1MHZ; // Set DCOCLK to 1MHz
DCOCTL = CALDCO_1MHZ;
P1SEL = UART_TXD + UART_RXD; // Timer function for TXD/RXD pins
P1DIR = 0xFF & ~UART_RXD; // Set all pins but RXD to output
__enable_interrupt();
TimerA_UART_init(); // Start Timer_A UART
TimerA_UART_print("MADE BY PengChengIT.\r\n");
TimerA_UART_print("G2xx2 TimerA UART\r\n");
TimerA_UART_print("READY.\r\n");
for (;;)
{
// Wait for incoming character
__bis_SR_register(LPM0_bits);
TimerA_UART_tx(rxBuffer);
}
}
//------------------------------------------------------------------------------
// Function configures Timer_A for full-duplex UART operation
//------------------------------------------------------------------------------
void TimerA_UART_init(void)
{
TACCTL0 = OUT; // Set TXD Idle as Mark = '1'
TACCTL1 = SCS + CM1 + CAP + CCIE; // Sync, Neg Edge, Capture, Int
TACTL = TASSEL_2 + MC_2; // SMCLK, start in continuous mode
}
//------------------------------------------------------------------------------
// Outputs one byte using the Timer_A UART
//------------------------------------------------------------------------------
void TimerA_UART_tx(unsigned char byte)
{
while (TACCTL0 & CCIE); // Ensure last char got TX'd
TACCR0 = TAR; // Current state of TA counter
TACCR0 += UART_TBIT; // One bit time till first bit
TACCTL0 = OUTMOD0 + CCIE; // Set TXD on EQU0, Int
txData = byte; // Load global variable
txData |= 0x100; // Add mark stop bit to TXData
txData <<= 1; // Add space start bit
}
//------------------------------------------------------------------------------
// Prints a string over using the Timer_A UART
//------------------------------------------------------------------------------
void TimerA_UART_print(char *string)
{
while (*string) {
TimerA_UART_tx(*string++);
}
}
//------------------------------------------------------------------------------
// Timer_A UART - Transmit Interrupt Handler
//------------------------------------------------------------------------------
#if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__)
#pragma vector = TIMER0_A0_VECTOR
__interrupt void Timer_A0_ISR(void)
#elif defined(__GNUC__)
void __attribute__ ((interrupt(TIMER0_A0_VECTOR))) Timer_A0_ISR (void)
#else
#error Compiler not supported!
#endif
{
static unsigned char txBitCnt = 10;
TACCR0 += UART_TBIT; // Add Offset to CCRx
if (txBitCnt == 0) { // All bits TXed?
TACCTL0 &= ~CCIE; // All bits TXed, disable interrupt
txBitCnt = 10; // Re-load bit counter
}
else {
if (txData & 0x01) {
TACCTL0 &= ~OUTMOD2; // TX Mark '1'
}
else {
TACCTL0 |= OUTMOD2; // TX Space '0'
}
txData >>= 1;
txBitCnt--;
}
}
//------------------------------------------------------------------------------
// Timer_A UART - Receive Interrupt Handler
//------------------------------------------------------------------------------
#if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__)
#pragma vector = TIMER0_A1_VECTOR
__interrupt void Timer_A1_ISR(void)
#elif defined(__GNUC__)
void __attribute__ ((interrupt(TIMER0_A1_VECTOR))) Timer_A1_ISR (void)
#else
#error Compiler not supported!
#endif
{
static unsigned char rxBitCnt = 8;
static unsigned char rxData = 0;
switch (__even_in_range(TA0IV, TA0IV_TAIFG)) { // Use calculated branching
case TA0IV_TACCR1: // TACCR1 CCIFG - UART RX
TACCR1 += UART_TBIT; // Add Offset to CCRx
if (TACCTL1 & CAP) { // Capture mode = start bit edge
TACCTL1 &= ~CAP; // Switch capture to compare mode
TACCR1 += UART_TBIT_DIV_2; // Point CCRx to middle of D0
}
else {
rxData >>= 1;
if (TACCTL1 & SCCI) { // Get bit waiting in receive latch
rxData |= 0x80;
}
rxBitCnt--;
if (rxBitCnt == 0) { // All bits RXed?
rxBuffer = rxData; // Store in global variable
rxBitCnt = 8; // Re-load bit counter
TACCTL1 |= CAP; // Switch compare to capture mode
__bic_SR_register_on_exit(LPM0_bits); // Clear LPM0 bits from 0(SR)
}
}
break;
}
}
二、代码寄存器分析分析
配置软件串口,涉及了时钟的配置,IO的配置,定时器A的配置以及中断函数,发送接收函数的编写。
初始化
初始化的过程用到了多个寄存器,具体如下
寄存器名称 | 涉及执行模式及说明 |
---|---|
DCOCTL | 时钟寄存器 |
BCSCTL1 | 时钟寄存器 |
TACCTL0 | Timer_A寄存器、捕获比较控制寄存器 |
TACCTL1 | Timer_A寄存器、捕获比较控制寄存器 |
TACTL | Timer_A寄存器、控制寄存器 |
PXSEL | IO口寄存器、功能选择寄存器 |
PXDIR | IO口寄存器、设定输入输出方向 |
中断函数
用到两个中断向量
TIMER0_A1_VECTOR
TIMER0_A0_VECTOR
发送函数
发送函数[ TimerA_UART_tx(unsigned char byte) ]用到的寄存器和参数整理如下
寄存器名称/参数 | 执行模式及说明 |
---|---|
TACCTL0 | Timer_A寄存器、捕获比较控制寄存器 |
TACCR0 | Timer_A寄存器、捕获比较寄存器 |
UART_TBIT/参数 | 波特率 |