Серега 0 17 ноября, 2005 Опубликовано 17 ноября, 2005 · Жалоба Помогите пожалуйста. Проблема с софт УАПП. Взял пример. Работает. //****************************************************************************** // MSP-FET430x110 Demo - Timer_A UART 115k, 16MHz DCO SMCLK // // Description: This program demonstrates a full-duplex 115k-baud UART using // Timer_A3 and a the DCO. A character is echoed on the Hyperterminal of a // a PC. The DCO frequency settings are stored in INFOA flash segment. // ACLK = LFXT1 = 32768, MCLK = SMCLK = saved DCO 16MHz // //* External watch crystal installed on XIN XOUT is required for ACLK *// // // MSP430F21x1 // ----------------- // /|\| XIN|- // | | | 32kHz // --|RST XOUT|- // | | // | P1.3|--------> Power for MAX3221 // | CCI0A/TXD/P1.1|--------> // | | 115200 8N1 // | CCI0B/RXD/P2.2|<-------- // // H. Grewal / A. Dannenberg // Texas Instruments, Inc // July 2005 // Built with IAR Embedded Workbench Version: 3.30A //***************************************************************************** #include <msp430x21x1.h> #define RXD 0x04 // RXD on P2.2 #define TXD 0x02 // TXD on P1.1 // Conditions for 115200 Baud SW UART, DCO = 16000000Hz #define Bitime_5 69 // ~ 0.5 bit length #define Bitime 138 // ~ 115942 baud unsigned int RXTXData; unsigned char BitCnt; void TX_Byte(void); void RX_Ready(void); void main (void) { WDTCTL = WDTPW + WDTHOLD; // Stop WDT BCSCTL1 = CALBC1_16MHZ; // Set DCO DCOCTL = CALDCO_16MHZ; TACTL = TASSEL_2 + MC_2 + TACLR; // SMCLK, cont-mode, clear CCTL0 = OUT; // TXD Idle as Mark P1SEL = TXD; // P1.1/TA0 for TXD function P1DIR = TXD; // TXD output on P1 P2SEL = RXD; // P2.2/TA0 as RXD input P1DIR |= 0x08; // Power MAX3221 P1OUT |= 0x08; // // Mainloop for (;;) { RX_Ready(); // UART ready to RX one Byte _BIS_SR(LPM3_bits + GIE); // Enter LPM3 w/ interr until char RXed TX_Byte(); // TX Back RXed Byte Received } } // Function Transmits Character from RXTXData Buffer void TX_Byte (void) { BitCnt = 0xA; // Load Bit counter, 8data + ST/SP CCR0 = TAR; // Current state of TA counter CCR0 += Bitime; // Some time till first bit RXTXData |= 0x100; // Add mark stop bit to RXTXData RXTXData = RXTXData << 1; // Add space start bit CCTL0 = OUTMOD0 + CCIE; // TXD = mark = idle while ( CCTL0 & CCIE ); // Wait for TX completion } // Function Readies UART to Receive Character into RXTXData Buffer // Sync capture not possible as DCO=TACLK=SMCLK can be off !! void RX_Ready (void) { BitCnt = 0x8; // Load Bit counter CCTL0 = CM1 + CCIS0 + OUTMOD0 + CAP + CCIE; // Neg Edge, Cap } // Timer A0 interrupt service routine #pragma vector=TIMERA0_VECTOR __interrupt void Timer_A (void) { CCR0 += Bitime; // Add Offset to CCR0 // RX if (CCTL0 & CCIS0) // RX on CCI0B? { if( CCTL0 & CAP ) // Capture mode = start bit edge { CCTL0 &= ~ CAP; // Switch from capture to compare mode CCR0 += Bitime_5; _BIC_SR_IRQ(SCG1 + SCG0); // DCO reamins on after reti } else { RXTXData = RXTXData >> 1; if (CCTL0 & SCCI) // Get bit waiting in receive latch RXTXData |= 0x80; BitCnt --; // All bits RXed? if ( BitCnt == 0) //>>>>>>>>>> Decode of Received Byte Here <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< { CCTL0 &= ~ CCIE; // All bits RXed, disable interrupt _BIC_SR_IRQ(LPM3_bits); // Clear LPM3 bits from 0(SR) } //>>>>>>>>>> Decode of Received Byte Here <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< } } // TX else { if ( BitCnt == 0) CCTL0 &= ~ CCIE; // All bits TXed, disable interrupt else { CCTL0 |= OUTMOD2; // TX Space if (RXTXData & 0x01) CCTL0 &= ~ OUTMOD2; // TX Mark RXTXData = RXTXData >> 1; BitCnt --; } } } Далее переделал для работы от кварца и на другую скорость. Выше скорости 2800 бод/с посылает нули вместо данных. Скорость же нужна 115200 бод/с. #include <msp430x21x1.h> #define TXD 0x02 // 2800 бод #define Bitime_5 1786 #define Bitime 3571 unsigned int RXTXData, i; unsigned char BitCnt; void TX_Byte(void); void main (void) { WDTCTL = WDTPW + WDTHOLD; // Stop WDT BCSCTL1 = XTS; BCSCTL2 = SELM_3 + SELS; BCSCTL3 = LFXT1S_2; TACTL = TASSEL_2 + MC_2; // SMCLK, cont-mode, clear CCTL0 = OUT; // TXD Idle as Mark P1SEL = TXD; // P1.1/TA0 for TXD function P1DIR = TXD; // TXD output on P1 _EINT(); for (;;) { RXTXData = 0x71; TX_Byte(); for (i = 0xFFF; i > 0; i--); // Delay } } // Function Transmits Character from RXTXData Buffer void TX_Byte (void) { BitCnt = 0xA; // Load Bit counter, 8data + ST/SP CCR0 = TAR; // Current state of TA counter CCR0 += Bitime; // Some time till first bit RXTXData |= 0x100; // Add mark stop bit to RXTXData RXTXData = RXTXData << 1; // Add space start bit CCTL0 = OUTMOD0 + CCIE; // TXD = mark = idle while ( CCTL0 & CCIE ); // Wait for TX completion } // Timer A0 interrupt service routine #pragma vector=TIMERA0_VECTOR __interrupt void Timer_A (void) { CCR0 += Bitime; // Add Offset to CCR0 // TX if ( BitCnt == 0) CCTL0 &= ~ CCIE; // All bits TXed, disable interrupt else { CCTL0 |= OUTMOD2; // TX Space if (RXTXData & 0x01) CCTL0 &= ~ OUTMOD2; // TX Mark RXTXData = RXTXData >> 1; BitCnt --; } } Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
rezident 0 17 ноября, 2005 Опубликовано 17 ноября, 2005 · Жалоба Дык а что вы хотели при частоте тактирования 32768 Гц? Или все-таки кварц другой стоит? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Antony Ugolev 0 17 ноября, 2005 Опубликовано 17 ноября, 2005 · Жалоба Software UART 115200? Это очень жестоко. Особенно приём. Вам придётся задержки вручную вымерять. И для надёжной работы на время приёма блокировать работу программы и выключать все прерывания. Иначе будут ошибки. Я отказался от 115200. У меня была возможность. 9600 -- в самый раз. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Серега 0 17 ноября, 2005 Опубликовано 17 ноября, 2005 (изменено) · Жалоба Сорри, кварц на 16 МГц. "Это очень жестоко. Особенно приём." Идет в основном передача данных, пока можно и без приема обойтись. Проблема в том что при внешнем кварце скорость выше 2800 бод/с достигнуть не удается. Изменено 17 ноября, 2005 пользователем Серега Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Antony Ugolev 0 17 ноября, 2005 Опубликовано 17 ноября, 2005 (изменено) · Жалоба Проверенный код для кварца 7.3728 МГц. Только это совсем другой микроконтроллер, ATmega128. #define SET_TX OCR2 = TX_115200 #define SET_RX OCR2 = RX_115200 #define TX_115200 64-3 #define RX_115200 64-4 void set_115200(void) { OCR2 = RX_115200; TCCR2 = 1 | (1<<WGM21); // prescaler=1, CTC } inline void Send_Bit(bool bit) { if(bit) PORT_TXD |= BIT_TXD; else PORT_TXD &= ~BIT_TXD; } inline void Delay_Bit(void) { while (!(TIFR & _BV(OCF2))) ; TIFR = _BV(OCF2); } void SoftwareUSART_Write(char data) { unsigned char i; SET_TX; cli(); // Start bit TCNT2 = 0; TIFR = _BV(OCF2); Send_Bit(0); Delay_Bit(); for(i = 0; i < 8; i++) { Send_Bit(data & 0b00000001); data >>= 1; Delay_Bit(); } Send_Bit(1); Delay_Bit(); sei(); } Изменено 17 ноября, 2005 пользователем Antony Ugolev Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
rezident 0 18 ноября, 2005 Опубликовано 18 ноября, 2005 · Жалоба Сорри, кварц на 16 МГц. Проблема в том что при внешнем кварце скорость выше 2800 бод/с достигнуть не удается. У вас в исходном коде некорректная процедура выбора источника тактирования. Нужно вставить задержку и опрос флага OFIFG. По этой причине, скорее всего, МК работает на DCO. DCO вы не инициализируете, поэтому по-умолчанию его частота около 1МГц. Исходя из этих предположений, делаем вывод почему у вас не получается работать на на более высокой скорости - малая частота тактирования CPU. Для MSP430F1101 и кварца 8МГц у меня, например, такой код инициализации. #pragma vector = NMI_VECTOR #pragma type_attribute=__interrupt void OSC_Fault_ISR(void) { BCSCTL2 = SELM_0+DIVM_0+DIVS_0; // MCLK=DCO/1=1МГц, SMCLK=DCO/1=1МГц DCOCTL = DCO2 + DCO1 + DCO0; // установка DCO BCSCTL1 = XTS+DIVA_1+RSEL2+RSEL1+RSEL0; // ACLK=XT2/2=4MHz, бит XTS установлен while ((IFG1 & OFIFG) != 0) IFG1 &=~ OFIFG; // Ожидаем пока стабилизируются колебания кварца BCSCTL2 = SELM_2 + DIVM_0 + SELS + DIVS_3; // MCLK=XT2/1=8МГц, SMCLK=XT2/8=1МГц IE1 |= OFIE; // разрешим прерывание от детектора ошибки резонатора } P.S. Для вашего МК код видимо немного отличаться будет, т.к. у него есть доп. биты и регистр источника тактирования, если я не ошибаюсь. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Серега 0 19 ноября, 2005 Опубликовано 19 ноября, 2005 · Жалоба Большое спасибо, в понедельник буду пробовать. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться