TI中文支持网
TI专业的中文技术问题搜集分享网站

MSP430g2553如何实现位操作,需要用普通口发送串行数据

msp430怎么实现位操作?现在想用一个普通I/O口往外围芯片发送串行数据,不带标准串行接口,我觉得是编程问题,怎么写啊

Ling Zhu2:

 你好,MSP430 可以利用定时器来实现软件串口,如下程序供参考:

//******************************************************************************// MSP430G2xx2 Demo – Timer_A, Ultra-Low Pwr UART 9600 Echo, 32kHz ACLK//// Description: Use Timer_A CCR0 hardware output modes and SCCI data latch// to implement UART function @ 9600 baud. Software does not directly read and// write to RX and TX pins, instead proper use of output modes and SCCI data// latch are demonstrated. Use of these hardware features eliminates ISR// latency effects as hardware insures that output and input bit latching and// timing are perfectly synchronised with Timer_A regardless of other// software activity. In the Mainloop the UART function readies the UART to// receive one character and waits in LPM3 with all activity interrupt driven.// After a character has been received, the UART receive function forces exit// from LPM3 in the Mainloop which configures the port pins (P1 & P2) based// on the value of the received byte (i.e., if BIT0 is set, turn on P1.0).

// ACLK = TACLK = LFXT1 = 32768Hz, MCLK = SMCLK = default DCO// //* An external watch crystal is required on XIN XOUT for ACLK *// //// MSP430G2xx2// —————–// /|\| XIN|-// | | | 32kHz// –|RST XOUT|-// | |// | CCI0B/TXD/P1.1|——–>// | | 9600 8N1// | CCI0A/RXD/P1.2|<——–//// D. Dang// Texas Instruments Inc.// December 2010// Built with CCS Version 4.2.0 and IAR Embedded Workbench Version: 5.10//******************************************************************************

#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 TXunsigned 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("G2xx2 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 = TIMER0_A0_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 = TIMER0_A1_VECTOR__interrupt void Timer_A1_ISR(void){ 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; }}//——————————————————————————

Tommy Aaron:

回复 Ling Zhu2:

用得了这么复杂吗,只是想用一个端口发送八位数据(如0x55),没有程序实现位操作么?

Ling Zhu2:

回复 Tommy Aaron:

 你好,

1. 除非你是单线制操作(像DS18B20那样),否则一般发送数据至少需要一根数据线和一根时钟线,没有节拍,数据会传乱的。。。

2. MSP430的位操作可以通过 |= 和 &=~ 来实现。比如:

P1OUT |= BIT0; //P1.0置高

P1OUT &=~ BIT0; //P1.0置低

Tommy Aaron:

回复 Ling Zhu2:

对,是单线制,比如是把0x55这个数据发送出去,用

DATA=0XFE;

DS=DATA&0X80;  

DATA=DATA<<1;

DS为定义的发送端口,

类似这样的,要发送变量,不可能每发送一个0或1都写一个P1OUT|=BIT0。

赞(0)
未经允许不得转载:TI中文支持网 » MSP430g2553如何实现位操作,需要用普通口发送串行数据
分享到: 更多 (0)