【TI MSP430】如何实现模拟串口通信
2018-05-05 来源:eefocus
1、背景:
很多时候由于硬件资源有限,但又需要使用串口通信,此时可以考虑使用模拟串口;
2、前提:
要实现特定bps的串口速率,需要相应频率的定时器,保证误码率在可以接受的范围内;
例如:
1MHz的时钟最高可模拟9600bps的通信速率:1M/9600 = 104 误码率<1%
3、参考代码:
//******************************************************************************
// ACLK = TACLK = LFXT1 = 32768Hz, MCLK = SMCLK = default DCO
// //* An external watch crystal is required on XIN XOUT for ACLK *//
//
// MSP430G2xx1
// -----------------
// /|\| XIN|-
// | | | 32kHz
// --|RST XOUT|-
// | |
// | CCI0B/TXD/P1.1|-------->
// | | 9600 8N1
// | CCI0A/RXD/P1.2|<--------
//
//******************************************************************************
#include
//------------------------------------------------------------------------------
// 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 constants erased
{
while(1); // do not load, trap CPU!!
}
DCOCTL = 0; // Select lowest DCOx and MODx settings
BCSCTL1 = CALBC1_1MHZ;
DCOCTL = CALDCO_1MHZ;
P1OUT = 0x00; // Initialize all GPIO
P1SEL = UART_TXD + UART_RXD; // Timer function for TXD/RXD pins
P1DIR = 0xFF & ~UART_RXD; // Set all pins but RXD to output
P2OUT = 0x00;
P2SEL = 0x00;
P2DIR = 0xFF;
__enable_interrupt();
TimerA_UART_init(); // Start Timer_A UART
TimerA_UART_print('G2xx1 TimerA UART\r\n');
TimerA_UART_print('READY.\r\n');
for (;;)
{
// Wait for incoming character
__bis_SR_register(LPM0_bits);
// Update board outputs according to received byte
if (rxBuffer & 0x01) P1OUT |= 0x01; else P1OUT &= ~0x01; // P1.0
if (rxBuffer & 0x02) P1OUT |= 0x08; else P1OUT &= ~0x08; // P1.3
if (rxBuffer & 0x04) P1OUT |= 0x10; else P1OUT &= ~0x10; // P1.4
if (rxBuffer & 0x08) P1OUT |= 0x20; else P1OUT &= ~0x20; // P1.5
if (rxBuffer & 0x10) P1OUT |= 0x40; else P1OUT &= ~0x40; // P1.6
if (rxBuffer & 0x20) P1OUT |= 0x80; else P1OUT &= ~0x80; // P1.7
if (rxBuffer & 0x40) P2OUT |= 0x40; else P2OUT &= ~0x40; // P2.6
if (rxBuffer & 0x80) P2OUT |= 0x80; else P2OUT &= ~0x80; // P2.7
// Echo received character
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
//------------------------------------------------------------------------------
#pragma vector = TIMERA0_VECTOR
__interrupt void Timer_A0_ISR(void)
{
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
//------------------------------------------------------------------------------
#pragma vector = TIMERA1_VECTOR
__interrupt void Timer_A1_ISR(void)
{
static unsigned char rxBitCnt = 8;
static unsigned char rxData = 0;
switch (__even_in_range(TAIV, TAIV_TAIFG)) { // Use calculated branching
case TAIV_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;
}
}
//------------------------------------------------------------------------------
- MCU今年的重点:NPU和64位
- 实时控制技术如何实现可靠且可扩展的高压设计
- PLD入门其实不难!TI带你解锁无代码逻辑设计新体验
- 德州仪器扩大氮化镓(GaN)半导体自有制造规模, 产能提升至原来的四倍
- TI研讨会正在进行中,米尔诚邀您参与
- 德州仪器业绩正在逐步好转
- 德州仪器 (TI) 全新可编程逻辑产品系列助力工程师在数分钟内完成从概念到原型设计的整个
- 利用德州仪器MSPM0系列微控制器实现高效电机控制
- 共模半导体推出可替代TI的TPS7A11型号的700mA低功耗高精度LDO稳压器 GM1500
- 贸泽开售适用于汽车和EV应用的 Texas Instruments DLP2021-Q1 DLP数字微镜器件