【IoT】TI MSP430 如何实现模拟串口通信

简介: 模拟串口

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 <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 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;
}

}
//---

卫朋

人人都是产品经理受邀专栏作家,CSDN 嵌入式领域新星创作者、资深技术博主。2020 年 8 月开始写产品相关内容,截至目前,人人都是产品经理单渠道阅读 56 万+,鸟哥笔记单渠道阅读200 万+,CSDN 单渠道阅读 210 万+,51CTO单渠道阅读 180 万+。

卫朋入围2021/2022年人人都是产品经理平台年度作者,光环国际学习社区首批原创者、知识合作伙伴,商业新知 2021 年度产品十佳创作者,腾讯调研云2022年达人榜第三名。

文章被人人都是产品经理、CSDN、华为云、运营派、产品壹佰、鸟哥笔记、光环国际、商业新知、腾讯调研云等头部垂直类媒体转载。文章见仁见智,各位看官可策略性选择对于自己有用的部分。

相关文章
|
网络协议 物联网 开发者
NB-IoT 通信之 TCP 收发数据 | 学习笔记
快速学习 NB-IoT 通信之 TCP 收发数据
1082 0
NB-IoT 通信之 TCP 收发数据 | 学习笔记
|
4月前
|
传感器 物联网 5G
物联网的通信技术以及Wi-Fi、一键配网技术、BLE、GPRS(2G)、LTE-Cat1 、NB-IoT简介
物联网的一个重要的特点是接入了网络,因此这些设备才能将传感器采集的数据上传到云平台,然后根据平台对数据的分析做出反应。而这种接入网络的技术,就是通信技术,是物联网的基础之一。通信的方式可以分为有线和无线两种方式,因为有线通信的成本较高,无线通信技术在物联网中应用比较广泛。
197 1
|
物联网 网络性能优化
IoT平台业务通信Topic设计最佳实践(共享场景为例)
以共享充电宝业务场景为例,讲解业务中topic和payload的规划设计
5547 0
|
4天前
|
传感器 监控 安全
物联网通信的基石:LoRa、Sigfox与NB-IoT详解
物联网通信的基石:LoRa、Sigfox与NB-IoT详解
44 0
|
2月前
|
网络协议 物联网 定位技术
毕设(二)——NB-IOT通信模块(nb卡通信测试)+gps定位
毕设(二)——NB-IOT通信模块(nb卡通信测试)+gps定位
|
安全 物联网 数据安全/隐私保护
|
存储 网络协议 物联网
NB-IoT 通信之 MQTT 发布订阅 | 学习笔记
快速学习 NB-IoT 通信之 MQTT 发布订阅
765 0
NB-IoT 通信之 MQTT 发布订阅 | 学习笔记
|
存储 数据采集 网络协议
NB-IoT 通信流程 | 学习笔记
快速学习 NB-IoT 通信流程
977 0
NB-IoT 通信流程 | 学习笔记
|
传感器 物联网 智能硬件
IoT设备与手机App之间实时消息通信解决方案
PLC 工控机和管理人员 App 的联动
1399 0
IoT设备与手机App之间实时消息通信解决方案
|
传感器 物联网
【阿里云IoT+YF3300】11.物联网多设备快速通信级联
我们见到的很多物联网设备,大都是“一跳”上网,所谓的“一跳”就是设备直接上网,内嵌物联网模块或者通过DTU直接上网。其实稍微复杂的物联网现场,往往网关下面连接若干物联网设备(如下图),并且这些物联网设备的距离有可能还有些远,连接的传感器也可能有些多,如何合理,且快速的连接这些设备,并把这些传感器数据上传的云端,如果是传统的做法,还是比较麻烦的,下面讲讲我们是如何快速进行多级物联网设备互联的。
1176 0
【阿里云IoT+YF3300】11.物联网多设备快速通信级联