Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: пример работы UART
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > MSP430
Dubov
Прошу поделится примером рабочего кода инициализирующего UART, и принимающего/передающего символы через UART.

Code Examples от TI - полное барахло.


rezident
Вначале следует утончить: режим UART для модуля USART или для модуля USCI?
Примеры использования периферийных модулей (и USART и USCI) есть на сайте производителя - см. MSP430 Code Examples.
Dubov
Цитата(rezident @ Mar 6 2014, 19:34) *
Вначале следует утончить: режим UART для модуля USART или для модуля USCI?
Примеры использования периферийных модулей (и USART и USCI) есть на сайте производителя - см. MSP430 Code Examples.


а вы этот Code Example сами пробовали? код нерабочий там. Нужен пример для USCI
rezident
Цитата(Dubov @ Mar 7 2014, 13:07) *
а вы этот Code Example сами пробовали? код нерабочий там. Нужен пример для USCI

Который именно? Вы же не указали конкретный тип МК. К тому же прием/передачу данных через UART можно организовать двумя способами: 1) по прерываниям от USCI и 2) без использования прерываний, по опросу флагов готовности USCI. Вам какой способ больше подходит? Вы бы конкретизировали свою задачу, а то "инициализация и прием/передача символов через UART" это слишком общо.
Да и честно говоря, при самостоятельном изучении документации (User's Manual) эта задача занимает максимум один рабочий день вместе с обедом, послеобеденным сном и семью перекурами biggrin.gif Там регистров-то USCI кот наплакал. Загвоздка может возникнуть лишь с использованием модулятора - дык, можно просто оценив ошибку baudrate, пока и не использовать его. laughing.gif
Dubov
Цитата(rezident @ Mar 7 2014, 13:39) *
Который именно? Вы же не указали конкретный тип МК. К тому же прием/передачу данных через UART можно организовать двумя способами: 1) по прерываниям от USCI и 2) без использования прерываний, по опросу флагов готовности USCI. Вам какой способ больше подходит? Вы бы конкретизировали свою задачу, а то "инициализация и прием/передача символов через UART" это слишком общо.
Да и честно говоря, при самостоятельном изучении документации (User's Manual) эта задача занимает максимум один рабочий день вместе с обедом, послеобеденным сном и семью перекурами biggrin.gif Там регистров-то USCI кот наплакал. Загвоздка может возникнуть лишь с использованием модулятора - дык, можно просто оценив ошибку baudrate, пока и не использовать его. laughing.gif

пример любой. Они все одинаковово корявые.
Я подумал что кто-то может выложить сюда кусок кода работы USCI по прерываниям.
vzelenuk
Цитата(Dubov @ Mar 7 2014, 13:53) *
пример любой. Они все одинаковово корявые.
Я подумал что кто-то может выложить сюда кусок кода работы USCI по прерываниям.


Что значит "корявые" конкретизируйте пожалуйста в чем проявляется "кривизна", а то возникают нехорошие подозрения, что Вам нужен просто оригинальный код, отличный от примеров, потому что лень писать самому.
Если нужен оригинальный код, так и скажите. Я при использовании примеров от TI не встречал значительных косяков...
Dubov
Цитата(vzelenuk @ Mar 7 2014, 14:03) *
Что значит "корявые" конкретизируйте пожалуйста в чем проявляется "кривизна", а то возникают нехорошие подозрения, что Вам нужен просто оригинальный код, отличный от примеров, потому что лень писать самому.
Если нужен оригинальный код, так и скажите. Я при использовании примеров от TI не встречал значительных косяков...

всем спасибо. нашёл интереснутему с примерами http://electronix.ru/forum/index.php?showt...=UART&st=15

там, кстати, тоже не жалуют примеры от TI
Dubov
переделал код. Теперь работает по прерываниям.

CODE

#include <msp430x471x7.h>
#include <stdint.h>

#define FREQMCLK 9830400UL //MCLK
#define FREQSMCLK 9830400UL //SMCLK
//#define FREQSMCLK 16000000UL //SMCLK
#define FREQACLK 32768UL //ACLK
#define BAUDRATE 9600UL //baudrate
#define TICK_MS_ADDVAL 100U //инкремент таймера тиков [мс]
#define BLINK_TIME_MS 500U //полупериод мерцания LED [мс]


int __low_level_init(void)
{ WDTCTL = WDTPW | WDTHOLD; //останов WDTimer
return 1;
}



void main(void)
{
uint32_t lTmp;
//Инициализация системы тактирования
// FLL_CTL1 = XT2OFF; //D=2, MCLK=fDCOCLK/D, SMCLK=fDCOCLK/D, ACLK=LFXT/1, XT2=off
FLL_CTL1 = 0; //D=2, MCLK=fDCOCLK/D, SMCLK=fDCOCLK/D, ACLK=LFXT/1
FLL_CTL2 = XT2S1; //для работы XT2=16МГц
FLL_CTL0 = XCAP0PF; //XT1=LF, DCO/D, XCAP=11пФ
while ((FLL_CTL0 & LFOF) != 0); //ждем готовности генератора 32768Гц
// while ((FLL_CTL0 & XT2OF) != 0); //ждем готовности генератора 16МГц
SCFI0 = FLLD_4 | FN_2; //D=4, fDCOCLK = 1.4-12MHz
SCFQCTL = SCFQ_M + (75U-1U); //fDCOCLK=32768*(75)*4=9830400Гц, DCO=fDCOCLK/4
while ((FLL_CTL0 & DCOF) != 0); //ждем готовности FLL
// FLL_CTL0 |= DCOPLUS; //MCLK=DCO/1, SMCLK=DCO/1
FLL_CTL1 |= SELS; //MCLK=DCO, SMCLK=XT2, ACLK=LFXT/1
do
{ IFG1 &= OFIFG ^ 0xFF;
} while ((IFG1&OFIFG) != 0); //ждем готовности всей системы тактирования
P5OUT ^= BIT7;

//Инициализация UART
UCA1CTL1 |= UCSWRST; //Reset USCI
UCA1CTL0 = 0; //Parity=disable, 8bit, 1stop-bit
UCA1CTL1 = UCSSEL_2 | UCSWRST; //BRCLK=SMCLK
lTmp=FREQSMCLK/BAUDRATE;
UCA1BR1 = (uint8_t)(lTmp>>8UL); //
UCA1BR0 = (uint8_t)(lTmp); //BITCLK=BRCLK/(UCAxBR1*256+UCAxBR0)
UCA1MCTL = 0; //регистр модуляции
UCA1STAT = 0; //сброс всех битов ощибок
UCA1IRTCTL = 0; //IRDA disable
UCA1CTL1 &= ~UCSWRST;
P1SEL |= BIT6 | BIT7; //P1.6 = USCI TXD, P1.7 = USCI RXD
UC1IE |= UCA1RXIE; //разрешить прерывания от приёмника USCI_A1
UC1IFG |= UCA1RXIFG; //сбросим флаг готовности буфера приемника
// UC1IFG |= UCA1TXIFG; //установим флаг готовность буфера передатчика
//Инициализация LED
P5DIR |= BIT7;
P5SEL &= ~BIT7;
P5OUT &= ~BIT7;
__enable_interrupt(); //разрешим прерывания
}

// Echo back RXed character, confirm TX buffer is ready first
#pragma vector=USCIAB1RX_VECTOR
__interrupt void USCIA1RX_ISR (void)
{

if ((UC1IFG&UCA1TXIFG)!=0);
UCA1TXBUF = UCA1RXBUF; // TX -> RXed character
P5OUT ^= BIT7;
}


Но наблюдается очень странное поведение. Некоторые символы отлично проходят в "эхо", другие возвращаются с ошибками(непонятные символы приходят). Например символ "a" не возвращается как положено, а символ "z" всегда возвращается как надо.
При каждом прерывании светодиод должен менять своё состояние, но, для случая с "a" состояние меняется, а для случая отправки "z" состояние не меняется. То есть со светодиодом ситуация наоборот... КАК ТАК?
mcheb
Цитата(Dubov @ Mar 15 2014, 17:47) *
переделал код. Теперь работает по прерываниям.

КАК ТАК?

Правильный код такой
// MOdemRX interrupt
#pragma vector = USCI_A0_VECTOR
__interrupt void USCI_A0_ISR(void)
{
uint8_t u;
if(UCA0IV & (UCRXIFG<<1))
{
u = UCA0RXBUF; // RXed character rxBuf[0]
if(!ModemFlags.Uart)
{
if(u=='\n' || u=='\r') ModemFlags.Uart=1;
uartRxBuf[uartRxCnt++] = u;
};
};
// if(UCA0IV & (UCTXIFG<<1))
// {
// uartCommand = UCA0RXBUF; // TXed character txBuf[0]
// };
}
И прочитайте всё-таки даташит
Dubov
Цитата(mcheb @ Mar 16 2014, 05:06) *
Правильный код такой
// MOdemRX interrupt
#pragma vector = USCI_A0_VECTOR
__interrupt void USCI_A0_ISR(void)
{
uint8_t u;
if(UCA0IV & (UCRXIFG<<1))
{
u = UCA0RXBUF; // RXed character rxBuf[0]
if(!ModemFlags.Uart)
{
if(u=='\n' || u=='\r') ModemFlags.Uart=1;
uartRxBuf[uartRxCnt++] = u;
};
};
// if(UCA0IV & (UCTXIFG<<1))
// {
// uartCommand = UCA0RXBUF; // TXed character txBuf[0]
// };
}
И прочитайте всё-таки даташит


извините, не могли бы вы рассказать про смысл ModemFlags.Uart ?
в вашем коде не видно когда обнуляетсяэтот флаг
mcheb
Цитата(Dubov @ Mar 16 2014, 08:48) *
извините, не могли бы вы рассказать про смысл ModemFlags.Uart ?
в вашем коде не видно когда обнуляетсяэтот флаг

Это флаг прихода Новой команды по Уарту. После обработки команды он сбрасывается.
Dubov
Цитата(mcheb @ Mar 16 2014, 11:15) *
Это флаг прихода Новой команды по Уарту. После обработки команды он сбрасывается.

позвольте узнать, что в вашем примере примечательного? мне не нужно принимать последовательность байтов, я реализую простейшее эхо. Так вот некоторые символы передается а некоторые нет. Зависит от символа, не могу понять почему.
rezident
Цитата(Dubov @ Mar 15 2014, 19:47) *
Но наблюдается очень странное поведение. Некоторые символы отлично проходят в "эхо", другие возвращаются с ошибками(непонятные символы приходят). Например символ "a" не возвращается как положено, а символ "z" всегда возвращается как надо.

У вас скорее всего не передача глючит, а прием символов по причине неверной настройки baudrate. Кварц подключенный к XT2 у вас точно 9830,4кГц?
К тому же, думаю, стоит зациклить вашу программу, чтобы "эхо" передавалось каждый раз при приеме нового символа. Для этого в конце main следует добавить строку for(;;);
Ну и неплохо бы уже указать конкретный тип кристалла. А то мы можем лишь догадываться по заголовочному файлу, что у вас что-то из серии MSP430F471x7.
Dubov
Цитата(rezident @ Mar 17 2014, 06:07) *
У вас скорее всего не передача глючит, а прием символов по причине неверной настройки baudrate. Кварц подключенный к XT2 у вас точно 9830,4кГц?
К тому же, думаю, стоит зациклить вашу программу, чтобы "эхо" передавалось каждый раз при приеме нового символа. Для этого в конце main следует добавить строку for(;;);
Ну и неплохо бы уже указать конкретный тип кристалла. А то мы можем лишь догадываться по заголовочному файлу, что у вас что-то из серии MSP430F471x7.

кристалл MSP430F47197.
Два кварца: 32768Гц и 16Мгц

Код взял здесь http://electronix.ru/forum/index.php?showt...l=UART&st=0 и переписал, чтобы задействовать прерывания.
У автора топика по ссылке тоже такая же конфигурация кварцев
rezident
Цитата(Dubov @ Mar 17 2014, 07:41) *
кристалл MSP430F47197.
Два кварца: 32768Гц и 16Мгц

Код взял здесь http://electronix.ru/forum/index.php?showt...l=UART&st=0 и переписал, чтобы задействовать прерывания.
У автора топика по ссылке тоже такая же конфигурация кварцев

Гм. А как вы думаете, какой результат вы получаете в результате выполнения вот этой операции?
Код
lTmp=FREQSMCLK/BAUDRATE;

Таки реальная частота SMCLK у вас вовсе не 9830400Гц, а в 4 раза меньше. Даже могу подсказать отчего она меньше
Код
#define FREQSMCLK 9830400UL //SMCLK
//#define FREQSMCLK 16000000UL //SMCLK

Код
// FLL_CTL0 |= DCOPLUS; //MCLK=DCO/1, SMCLK=DCO/1
FLL_CTL1 |= SELS; //MCLK=DCO, SMCLK=XT2, ACLK=LFXT/1

Вы уж разберитесь от какого генератора хотите тактировать SMCLK и правильно раскомментарьте/закомментарьте указанные строки sm.gif
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.