Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Проблема с UART
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > MSP430
Zelepuk
Вот код
CODE
#include "msp430x471x7.h"

void main(void)
{
volatile unsigned int i;
P5DIR |= BIT7;

WDTCTL = WDTPW+WDTHOLD; // Stop WDT
FLL_CTL0 |= XCAP14PF; // Configure load caps

do
{
IFG1 &= ~OFIFG; // Clear OSCFault flag
for (i = 0x47FF; i > 0; i--); // Time for flag to set
}
while ((IFG1 & OFIFG)); // OSCFault flag still set?

P1SEL |= BIT6+BIT7; // P2.4,5 = USCI_A0 RXD/TXD
UCA1CTL1 |= UCSSEL_1; // CLK = ACLK
UCA1BR0 = 0x03; // 32k/9600 - 3.41
UCA1BR1 = 0x00; //
UCA1MCTL = 0x06; // Modulation
UCA1CTL1 &= ~UCSWRST; // **Initialize USCI state machine**
// IE2 |= UCA1RXIE; // Enable USCI_A0 RX interrupt
char c = 'A';
// _BIS_SR(LPM3_bits + GIE); // Enter LPM3, interrupts enabled
while(1)
{

while(!(IFG2&UCA1TXIFG));
UCA1TXBUF = c;
P5OUT ^= BIT7;
for(i=2500;i>0;i--);
}

}


Пытаюсь просто выводить в терминал символ 'A' и зажигать светодиод. Светодиод горит, на терминал выводится сами видите что (см. приложенное фото).
В чём может быть дело?
Ещё когда пробую проект "эхо"(посылаем символ с клавиатуры компьютера - MSP430 принимает его и кидает в компорт компьютера), то он работает со сбоями (сначала всё хорошо, потом символы не передаются, потом передаётся чепуха...)

Нужна помощь, всю голову сломал((
rezident
Модуль тактирования проинициализируйте полностью!
Zelepuk
Цитата(rezident @ Jul 13 2011, 16:23) *
Модуль тактирования проинициализируйте полностью!


У меня MSP430F47197 подклюен часовой кварц(32768) и кварцевый резонатор(16 мегагерц).
Если я правильно понял, то можно тактировать USCI модуль от разных источников:
DCO, SMCLK, ACLK. Я предпочёл ACLK (см. код выше).
Я делаю так

CODE
FLL_CTL0 |= XCAP0PF; // Set load capacitance
FLL_CTL1 &= ~XT2OFF; // Turn on XT2
FLL_CTL1 = SELS; // Select SMCLK source as XT2CLK
FLL_CTL2 |= XT2S_2;


По-моему у серии MSP430F47XX несколько сложнее, чем у других, система тактирования (так как есть FLL).

Кто знает поправьте если что-то не так.


MrYuran
Цитата(Zelepuk @ Jul 14 2011, 09:40) *
Кто знает поправьте если что-то не так.

Типовое значение UMCTL для 32768/9600 равно 4А. (таблица в мануале)
Непонятно, из каких соображений у вас 6 торчит. Два бита подряд корректируются, остальные пошли вразнос.
rezident
Цитата(Zelepuk @ Jul 14 2011, 10:40) *
Кто знает поправьте если что-то не так.

Я же вам сказал полностью нужно проинициализировать! Т.е. прописать явными значениями все регистры модуля тактирования, а не накладывать маски на дефолтные (после POR) состояния. То же самое касается в отношении регистров USCI.
Еще возникает вопрос зачем использовать 32768 для UART? Да еще и при неверном значении регистра модуляции, на что вам MrYuran указал. Подстройте DCO по часовому кварцу к какой-либо типизированной частоте, которая нацело делиться для выбранной скорости UART. Например, 1,152МГц (9600*120=115200*10) или 1,8432МГц (9600*192=115200*16). И потом используйте DCO как источник SMCLK, а тот в свою очередь для тактирования USCI. Либо подключите кварц на XT2 с тем же критерием выбора частоты (нацело делится для стандартного ряда скоростей UART).
Zelepuk
Цитата(rezident @ Jul 14 2011, 19:51) *
Я же вам сказал полностью нужно проинициализировать! Т.е. прописать явными значениями все регистры модуля тактирования, а не накладывать маски на дефолтные (после POR) состояния. То же самое касается в отношении регистров USCI.
Еще возникает вопрос зачем использовать 32768 для UART? Да еще и при неверном значении регистра модуляции, на что вам MrYuran указал. Подстройте DCO по часовому кварцу к какой-либо типизированной частоте, которая нацело делиться для выбранной скорости UART. Например, 1,152МГц (9600*120=115200*10) или 1,8432МГц (9600*192=115200*16). И потом используйте DCO как источник SMCLK, а тот в свою очередь для тактирования USCI. Либо подключите кварц на XT2 с тем же критерием выбора частоты (нацело делится для стандартного ряда скоростей UART).


Может я совсем дуб, но как смог понять DCO применяется для умножения частоты часового кварца если нету кварца на XT2 (у меня там стоит кварц на 16 мегагерц).

Тогда наверное нужно в качестве SMCLK указать что используется кварц на XT2?
___________________________________________________________________________

Дабы не плодить темы.
Подскажите как нормально инициализировать систему тактирования, если, у меня есть на плате два кварца (часовой и 16Мгц), не планируется использовать внутренние ёмкости и нужно добится максимальной скорости тактирования ядра, а кроме того от часового кварца работают часы реального времени.
нужен ли тогда вообще DCO или нет?
rezident
Цитата(Zelepuk @ Jul 14 2011, 22:12) *
нужен ли тогда вообще DCO или нет?

DCO нужен всегда! По крайней мере для тактирования MCLK нужен.
Плюсы DCO.
- есть во всех кристаллах MSP430;
- не требует внешних элементов/компонентов;
- весьма широкий диапазон программной перестройки частоты, возможность подстройки от внешнего сигнала;
- это внутренний генератор, поэтому он наименее подвержен воздействию внешних помех;
- быстрый запуск (единицы мкс), удобно использовать в режимах энергосбережения - быстро проснулся, быстро (на высокой частоте) выполнил необходимые операции, снова уснул;
Минусы DCO:
- зависимость от температуры и величины напряжения питания.
При наличии часового кварца минус DCO нивелируется периодической подстройкой его частоты или задействованием FLL для синхронизации его от LFXT. См. структурную блок-схему модуля FLL+ в User's Guide Figure 5−3.MSP430x47x3/4 and MSP430F471xx Frequency-Locked Loop и описание в разделе Chapter 5. FLL+ Clock Module.
Zelepuk
Цитата(rezident @ Jul 14 2011, 19:51) *
Еще возникает вопрос зачем использовать 32768 для UART? Да еще и при неверном значении регистра модуляции, на что вам MrYuran указал. Подстройте DCO по часовому кварцу к какой-либо типизированной частоте, которая нацело делиться для выбранной скорости UART. Например, 1,152МГц (9600*120=115200*10) или 1,8432МГц (9600*192=115200*16). И потом используйте DCO как источник SMCLK, а тот в свою очередь для тактирования USCI. Либо подключите кварц на XT2 с тем же критерием выбора частоты (нацело делится для стандартного ряда скоростей UART).


Я подключаю кварц на XT2 (16000кГц) и делю его частоту на скорость UART(115200) получается 138 целых, а дробную часть просто не учитываю (именно так делают TI в своих примерах).


Цитата(rezident @ Jul 14 2011, 19:51) *
Я же вам сказал полностью нужно проинициализировать! Т.е. прописать явными значениями все регистры модуля тактирования, а не накладывать маски на дефолтные (после POR) состояния. То же самое касается в отношении регистров USCI.


Вы имеете ввиду, что нужно проинициализировать все регистры (см. приложенный рисунок) и каждый бит определить требуемым значением (если даже оно и не особо надо)???

Просто у меня есть большая апликуха от TI и там такой подход не практикуется.



Цитата(rezident @ Jul 14 2011, 22:50) *
DCO нужен всегда! По крайней мере для тактирования MCLK нужен.


MCLK: основное тактирование. Модуль MCLK программно выбирается как LFXT1CLK, XT2CLK (если доступен) или DCOCLK. MCLK делится на 1, 2, 4 или 8. MCLK используется ЦПУ и системой.

Это прочитано из русского руководства. Получается, если есть два кварца на плате, можно вообще без DCO обойтись.
rezident
Цитата(Zelepuk @ Jul 15 2011, 19:10) *
Я подключаю кварц на XT2 (16000кГц) и делю его частоту на скорость UART(115200) получается 138 целых, а дробную часть просто не учитываю (именно так делают TI в своих примерах).

В ваших предыдущих примерах генератор XT2 отключен!
Цитата(Zelepuk @ Jul 15 2011, 19:10) *
Вы имеете ввиду, что нужно проинициализировать все регистры (см. приложенный рисунок) и каждый бит определить требуемым значением (если даже оно и не особо надо)???

Просто у меня есть большая апликуха от TI и там такой подход не практикуется.

Я что-то не пойму, вам "шашечки" или ехать? rolleyes.gif
Цитата(Zelepuk @ Jul 15 2011, 19:17) *
Это прочитано из русского руководства. Получается, если есть два кварца на плате, можно вообще без DCO обойтись.

Я наверное для себя предыдущее сообщение писал, да? Вы либо его не читали, либо смысла не поняли. Перечитайте еще раз.
zltigo
QUOTE (Zelepuk @ Jul 15 2011, 16:17) *
получается 138 целых, а дробную часть просто не учитываю (именно так делают TI в своих примерах).

Неграмотные индусы нанятые TI для написания кучи мусора для еще более неграмотных "программистов" округлять до целого не умеют. Но Вы для себя могли-бы и постараться и НЕ отбрасывать всегда безусловно дробную часть.
QUOTE
Просто у меня есть большая апликуха от TI и там такой подход не практикуется.

См. выше.
Zelepuk
Цитата(rezident @ Jul 14 2011, 19:51) *
Я же вам сказал полностью нужно проинициализировать! Т.е. прописать явными значениями все регистры модуля тактирования, а не накладывать маски на дефолтные (после POR) состояния. То же самое касается в отношении регистров USCI.
Еще возникает вопрос зачем использовать 32768 для UART? Да еще и при неверном значении регистра модуляции, на что вам MrYuran указал. Подстройте DCO по часовому кварцу к какой-либо типизированной частоте, которая нацело делиться для выбранной скорости UART. Например, 1,152МГц (9600*120=115200*10) или 1,8432МГц (9600*192=115200*16). И потом используйте DCO как источник SMCLK, а тот в свою очередь для тактирования USCI. Либо подключите кварц на XT2 с тем же критерием выбора частоты (нацело делится для стандартного ряда скоростей UART).


Читая даташит, я понял что fdcoclk задаётся путём умножения частоты кварца (32768 в моём случае) на константу, а так же возможно деление значения на число из ряда 1, 2, 4 или 8.
Так задавшись частотой 1,152МГц я никак не могу подобрать точное значение множителей, что бы 1152000 делилось без остатка на 115200 или 9600.

fdcoclk = ((x+1)/y)*fcrystal
1152000 = ((x+1)/y)*32768
если y = 2 (задаём в регистре SCFI0 биты FLLDx), то x = 69.3125
принимаю x = 69
Строго целое не получится никогда.
Zelepuk
Теперь пробую инициализировать явно все регистры модуля тактирования и модуля USCI.

CODE
#include "msp430x471x7.h"

void main(void)
{
volatile unsigned int i;

WDTCTL = WDTPW+WDTHOLD; // Stop WDT
P5DIR |= BIT7;

//-----------------------------------------------------------------------------
// Инициализация модуля тактирования (SMCLK = Fdcoclk = 1048576)
//-----------------------------------------------------------------------------
SCFQCTL = 52; // модуляции нет, множитель DCO = 52
SCFI0 = 0; // диапахон DCO 0.65 to 6.1 MHz
// SCFI1 нет трогаю
FLL_CTL0 = 0;
FLL_CTL0 |= (DCOPLUS)|(1<<5)|(1<<4); // не используем предделитель кварц на XT1 на 10пФ
FLL_CTL1 = 0;
FLL_CTL1 |= SELM1; //SMCLK от DCO, MCLK от 16Mhz кварца
FLL_CTL2 |= (XT2S1)|(XT2S0); //диапазон частоты XT2 от 0.4 до 16 Mhz

do
{
IFG1 &= ~OFIFG; // Clear OSCFault flag
for (i = 0x47FF; i > 0; i--); // Time for flag to set
}
while ((IFG1 & OFIFG)); // OSCFault flag still set?


//-----------------------------------------------------------------------------
// Инициализация USCI модуля в режиме UART
//-----------------------------------------------------------------------------
P1SEL |= BIT6+BIT7; // P1.6,7 = USCI_A1 RXD/TXD
UCA1CTL0 = 1; //нет контроля чётности, 8N1 LSB first, Synchronous Mode
UCA1CTL1 = 0;
UCA1CTL1 |= (1<<7); // CLK = SMCLK
UCA1BR0 = 0x6D; // 1146880/9600 = 119.46
UCA1BR1 = 0x00; //
UCA1MCTL = 0x03; // Modulation
UCA1CTL1 &= ~UCSWRST; // **Initialize USCI state machine**
UC1IE |= UCA1RXIE; // Enable USCI_A1 RX interrupt

while(1) // main loop
{
while(!(IFG2&UCA1TXIFG));
UCA1TXBUF = 'A';
P5OUT ^= BIT7;
for(i=2500;i>0;i--);
}
}


Значение Fdcoclk = 1048576 а так же
UCA1BR0 = 0x6D; // 1146880/9600 = 119.46
UCA1BR1 = 0x00; //
UCA1MCTL = 0x03; // Modulation

взяты из даташита (страница 17-16).

Теперь даже не мигает светодиод.... накосячил опять где-то наверное((( laughing.gif
единственное что могло прийти в голову - номиналами конденсаторов программно поиграться - непомогло... (а это может влиять вплоть до неработоспособности?)
rezident
Есть несколько вариантов организации тактирования UART.
Вариант 1.
Код
XT2 → SMCLK → BRCLK → |BRCLK divider| → BITCLK

Вариант 2.
Код
LFXT →
     +  FLL → SMCLK → BRCLK → |BRCLK divider| → BITCLK
DCO →

Вариант 3.
Код
LFXT → ACLK  
(откалиброванный по ACLK) DCO → SMCLK → BRCLK → |BRCLK divider| → BITCLK

Кварцевый генератор служит опорой, поэтому в первую очередь нужно обеспечить его функционирование. И только дождавшись когда колебания стабилизируются, можно использовать его для тактирования внутренних сигналов. Следовательно в первую очередь следует инициализировать регистры FLL_CTL0 и FLL_CTL2 (если собираетесь использовать XT2).
Колебания генератора часового кварца стабилизируются гораздо медленне, чем высокочастотного. А для вариантов 2 и 3 генератор 32768Гц к тому же является опорным. Поэтому сначала ждем именно его готовности. К тому же OFIFG нельзя будет сбросить до тех пор, пока оба кварцевых генератора и FLL не будут функционировать нормально.
Ниже привожу пример программы, которая с периодом около 100мс отсылает через UART символы из буфера и мерцает светодиодом на выводе P5.7 с частотой 1Гц.
В программе используется тактирование по варианту 2: часовой кварц и DCO, синхронизированный от него с помощью FLL. Частота DCO должна получаться 9830400Гц. SMCLK = DCO и вплоть до baudrate = 38400 делится нацело, поэтому регистр модуляции не используется. Но даже и для более высоких значений baudrate (56700, 115200) при такой частоте регистр модуляции можно не использовать. Т.к. ошибка установки baudrate будет составлять менее 0,4% что вполне допустимо. Это же замечание относится к варианту 1, когда используется ВЧ кварцевый генератор частота 16МГц.
Для варианта тактирования 1 нужно раскоментировать закоментированные строки.
Вариант 3 мне реализовывать уже было лень sm.gif Можете попробовать сами его реализовать, учитывая, что имеется возможность внутренне скоммутировать ACLK на вход захвата CCI2B TimerA. Это указано в таблице TIMER_A3 SIGNAL CONNECTIONS в datasheet MSP430F47197. Пример подстройки DCO для такого способоа где-то был в примерах исходников от TI по-моему. Частота DCO программно корректируется до тех пор, пока отношение частот DCO и 32768Гц (полученное с помощью схемы захвата TimerA) не будет равно заданному.
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;
}

uint16_t tick_ms; //счетчик миллисекунд
uint8_t uart_buf[]={'0','1','2','3','4','5','6','7','8','9','\n','\r'};//буфер UART

void main(void)
{ uint16_t tickStamp, idx;
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 = XCAP11PF; //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;
} while ((IFG1&OFIFG) != 0); //ждем готовности всей системы тактирования
//Инициализация 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 &= ~(UCA1TXIE | UCA1RXIE); //запретим прерывания USCI_A1
UC1IFG &= ~UCA1RXIFG; //сбросим флаг готовности буфера приемника
UC1IFG |= UCA1TXIFG; //установим флаг готовность буфера передатчика
//Иницализация TimerA
TACTL = TASSEL_1 | TACLR; //TACLK=ACLK/1
TACCR0=(uint16_t)(FREQACLK/10UL); //период около 100мс
TACCTL0 = CCIE; //разр. прерывание от CCR0
TACCTL1 = 0;
TACCTL2 = 0;
TACTL |= MC_1; //запустить таймер в режиме CountUP
//Инициализация LED
P5DIR |= BIT7;
P5SEL &= ~BIT7;
P5OUT &= ~BIT7;
idx=0;
tickStamp = tick_ms; //зафиксировать временную метку
__enable_interrupt(); //разрешим прерывания
for (;;)
{ if ((tick_ms - tickStamp) >= BLINK_TIME_MS)//полупериод мерцания закончился?
{ tickStamp = tick_ms; //запомним новое значение метки времени
P5OUT ^= BIT7; //инвертируем состояние LED
}
if ((UC1IFG & UCA1TXIFG) != 0) //буфер передатчика готов?
{ UCA1TXBUF=uart_buf[idx]; //вывод текущего символа
if (idx < (sizeof(uart_buf)-1))//увеличение индекса
idx += 1;
else
idx = 0;
}
__bis_SR_register(LPM0_bits + GIE);//переход в режим энергосбережения LPM0
}
}

#pragma vector=TIMERA0_VECTOR
#pragma type_attribute=__interrupt
void TimerA0_ISR (void)
{
tick_ms += TICK_MS_ADDVAL; //инкремент счтечика тиков [мс]
__bic_SR_register_on_exit(LPM0_bits);//выход из режима энергосбережения при выходе из прерывания
}

Программа на железе не проверялась ввиду отсутствия оного.

Update. Исправил форматирование исходника. Изменил команду выхода из режима энергосбережения в прерывании. В принципе код генерился одинаковый, но так корректнее.
Zelepuk
Цитата(rezident @ Jul 17 2011, 04:26) *
Есть несколько вариантов организации тактирования UART.
Вариант 1.
Код
XT2 → SMCLK → BRCLK → |BRCLK divider| → BITCLK

Вариант 2.
Код
LFXT →
     +  FLL → SMCLK → BRCLK → |BRCLK divider| → BITCLK
DCO →

Вариант 3.
Код
LFXT → ACLK  
(откалиброванный по ACLK) DCO → SMCLK → BRCLK → |BRCLK divider| → BITCLK

Кварцевый генератор служит опорой, поэтому в первую очередь нужно обеспечить его функционирование. И только дождавшись когда колебания стабилизируются, можно использовать его для тактирования внутренних сигналов. Следовательно в первую очередь следует инициализировать регистры FLL_CTL0 и FLL_CTL2 (если собираетесь использовать XT2).
Колебания генератора часового кварца стабилизируются гораздо медленне, чем высокочастотного. А для вариантов 2 и 3 генератор 32768Гц к тому же является опорным. Поэтому сначала ждем именно его готовности. К тому же OFIFG нельзя будет сбросить до тех пор, пока оба кварцевых генератора и FLL не будут функционировать нормально.
Ниже привожу пример программы, которая с периодом около 100мс отсылает через UART символы из буфера и мерцает светодиодом на выводе P5.7 с частотой 1Гц.
В программе используется тактирование по варианту 2: часовой кварц и DCO, синхронизированный от него с помощью FLL. Частота DCO должна получаться 9830400Гц. SMCLK = DCO и вплоть до baudrate = 38400 делится нацело, поэтому регистр модуляции не используется. Но даже и для более высоких значений baudrate (56700, 115200) при такой частоте регистр модуляции можно не использовать. Т.к. ошибка установки baudrate будет составлять менее 0,4% что вполне допустимо. Это же замечание относится к варианту 1, когда используется ВЧ кварцевый генератор частота 16МГц.
Для варианта тактирования 1 нужно раскоментировать закоментированные строки.
Вариант 3 мне реализовывать уже было лень sm.gif Можете попробовать сами его реализовать, учитывая, что имеется возможность внутренне скоммутировать ACLK на вход захвата CCI2B TimerA. Это указано в таблице TIMER_A3 SIGNAL CONNECTIONS в datasheet MSP430F47197. Пример подстройки DCO для такого способоа где-то был в примерах исходников от TI по-моему. Частота DCO программно корректируется до тех пор, пока отношение частот DCO и 32768Гц (полученное с помощью схемы захвата TimerA) не будет равно заданному.
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;
}

uint16_t tick_ms; //счетчик миллисекунд
uint8_t uart_buf[]={'0','1','2','3','4','5','6','7','8','9','\n','\r'};//буфер UART

void main(void)
{ uint16_t tickStamp, idx;
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 = XCAP11PF; //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;
} while ((IFG1&OFIFG) != 0); //ждем готовности всей системы тактирования
//Инициализация 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 &= ~(UCA1TXIE | UCA1RXIE); //запретим прерывания USCI_A1
UC1IFG &= ~UCA1RXIFG; //сбросим флаг готовности буфера приемника
UC1IFG |= UCA1TXIFG; //установим флаг готовность буфера передатчика
//Иницализация TimerA
TACTL = TASSEL_1 | TACLR; //TACLK=ACLK/1
TACCR0=(uint16_t)(FREQACLK/10UL); //период около 100мс
TACCTL0 = CCIE; //разр. прерывание от CCR0
TACCTL1 = 0;
TACCTL2 = 0;
TACTL |= MC_1; //запустить таймер в режиме CountUP
//Инициализация LED
P5DIR |= BIT7;
P5SEL &= ~BIT7;
P5OUT &= ~BIT7;
idx=0;
tickStamp = tick_ms; //зафиксировать временную метку
__enable_interrupt(); //разрешим прерывания
for (;;)
{ if ((tick_ms - tickStamp) >= BLINK_TIME_MS)//полупериод мерцания закончился?
{ tickStamp = tick_ms; //запомним новое значение метки времени
P5OUT ^= BIT7; //инвертируем состояние LED
}
if ((UC1IFG & UCA1TXIFG) != 0) //буфер передатчика готов?
{ UCA1TXBUF=uart_buf[idx]; //вывод текущего символа
if (idx < (sizeof(uart_buf)-1))//увеличение индекса
idx += 1;
else
idx = 0;
}
__bis_SR_register(LPM0_bits + GIE);//переход в режим энергосбережения LPM0
}
}

#pragma vector=TIMERA0_VECTOR
#pragma type_attribute=__interrupt
void TimerA0_ISR (void)
{
tick_ms += TICK_MS_ADDVAL; //инкремент счтечика тиков [мс]
__bic_SR_register_on_exit(LPM0_bits);//выход из режима энергосбережения при выходе из прерывания
}

Программа на железе не проверялась ввиду отсутствия оного.

Update. Исправил форматирование исходника. Изменил команду выхода из режима энергосбережения в прерывании. В принципе код генерился одинаковый, но так корректнее.


Спасибо огромное, rezident, за внимание! Но вроде код грамотный и всё разжёвано... но ваш код не запускается вовсе... светодиод не горит, в терминалке ничего не выводится...(((
А может вся эта система не запускаться из-за того, что неправильно кондесаторы на кварцах подобраны?
Разбираюсь дальше smile3046.gif
За код ещё раз спасибо.
rezident
Цитата(Zelepuk @ Jul 18 2011, 00:00) *
А может вся эта система не запускаться из-за того, что неправильно кондесаторы на кварцах подобраны?

А какие конденсаторы у вас стоят? Если часовой кварц типовой (с нагрузочной емкостью 12,5пФ), то в обвязке его должны быть по 12пФ. С учетом предположения именно такой нагрузочной емкости выбраны установки битов XCAP11PF. В обвязке 16МГц-кварца должны быть по 15пФ. И, кстати, какой именно часовой кварц вы используете? Я недавно напоролся на проблемы с запуском LFXT на MSP430F2618TPW. Пробовал все что было под рукой: KX-327NHT, KX-327LT от Geyer и DT-38LT (noname) , но ни с одним из них запустить LF-генератор не получалось. Разбор полетов, чтение документации (включая Errata), запросы на форум выявили особенность этого генератора в серии 2xxx. Там очень жесткие требования к допустимому диапазону ESR кварца. Кое-как удалось запустить лишь на DT-26L неизвестного производителя. Коллеги рекомендовали использовать MS1V-T1K от швейцарской фирмы Micro Crystal. Якобы с ним проблем не бывает. Так что проверьте с помощью отладчика или трассировки с помощью того же светодиода, в каком именно месте циклится программа? Если я правильно догадываюсь, то зацикливание должно происходить на ожидании готовности LFXT - там, где проверяется бит LFOF.
Zelepuk
Цитата(rezident @ Jul 18 2011, 01:16) *
А какие конденсаторы у вас стоят? Если часовой кварц типовой (с нагрузочной емкостью 12,5пФ), то в обвязке его должны быть по 12пФ. С учетом предположения именно такой нагрузочной емкости выбраны установки битов XCAP11PF. В обвязке 16МГц-кварца должны быть по 15пФ. И, кстати, какой именно часовой кварц вы используете? Я недавно напоролся на проблемы с запуском LFXT на MSP430F2618TPW. Пробовал все что было под рукой: KX-327NHT, KX-327LT от Geyer и DT-38LT (noname) , но ни с одним из них запустить LF-генератор не получалось. Разбор полетов, чтение документации (включая Errata), запросы на форум выявили особенность этого генератора в серии 2xxx. Там очень жесткие требования к допустимому диапазону ESR кварца. Кое-как удалось запустить лишь на DT-26L неизвестного производителя. Коллеги рекомендовали использовать MS1V-T1K от швейцарской фирмы Micro Crystal. Якобы с ним проблем не бывает. Так что проверьте с помощью отладчика или трассировки с помощью того же светодиода, в каком именно месте циклится программа? Если я правильно догадываюсь, то зацикливание должно происходить на ожидании готовности LFXT - там, где проверяется бит LFOF.


У меня стоит кварц KX-327S и 12пФ кондёры. На 16Мгц кварце стоят тоже 12пФ. Кстати, XCAP11PF - нету такого дефайна, конденсаторы выбираются из ряда 1, 6, 8, 10 пФ.

И ещё, код из моего первого поста работает (хоть и выдаёт в порт несуразицу). Но если выставляю программно конденсатор 1пф - не работает.
А тут ВООБЩЕ не работает, что примечательно, если закоментить вот это

do
{ IFG1 &= OFIFG;
} while ((IFG1&OFIFG) != 0);

то начинает мигать светодиод, что говорит о работоспособности таймера, но UATR всё равно молчит.
rezident
Блин! В этой строке ошибка. Я забыл проинвертировать. Должно быть так
Код
IFG1 &= ~OFIFG;

или так
Код
IFG1 &= OFIFG ^ 0xFF;
Zelepuk
Да, теперь светодиод мигает с нужным интервалом... но UART молчит crying.gif
пробую такую конструкцию

CODE
while(!(UC1IFG&UCA1TXIFG)); //буфер передатчика готов?
P5OUT ^= BIT7;


Диод не мигает, что говорит о том что флаг готовности передающего буфера не устанавливается...
rezident
Цитата(Zelepuk @ Jul 18 2011, 19:47) *
пробую такую конструкцию

Приводите полный код. Нам ведь не видно, что вы там еще намодифицировали в исходнике?
Zelepuk
Да, простите, в основном цикле вообще не трогаю таймер, а просто пытаюсь что-то вывести через UART.
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;
}

uint16_t tick_ms; //счетчик миллисекунд
uint8_t uart_buf[]={'0','1','2','3','4','5','6','7','8','9','\n','\r'};//буфер UART

void main(void)
{ uint16_t tickStamp, idx;
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 = XCAP6PF; //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;
} 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 &= ~(UCA1TXIE | UCA1RXIE); //запретим прерывания USCI_A1
UC1IFG &= ~UCA1RXIFG; //сбросим флаг готовности буфера приемника
UC1IFG |= UCA1TXIFG; //установим флаг готовность буфера передатчика
//Иницализация TimerA
TACTL = TASSEL_1 | TACLR; //TACLK=ACLK/1
TACCR0=(uint16_t)(FREQACLK/10UL); //период около 100мс
TACCTL0 = CCIE; //разр. прерывание от CCR0
TACCTL1 = 0;
TACCTL2 = 0;
TACTL |= MC_1; //запустить таймер в режиме CountUP
//Инициализация LED
P5DIR |= BIT7;
P5SEL &= ~BIT7;
P5OUT &= ~BIT7;
idx=0;
tickStamp = tick_ms; //зафиксировать временную метку
__enable_interrupt(); //разрешим прерывания
for (;;)
{
while(!(UC1IFG&UCA1TXIFG)); //буфер передатчика готов?
P5OUT ^= BIT7;
UCA1TXBUF= 'Z'; //вывод текущего символа
}
// __bis_SR_register(LPM0_bits + GIE);//переход в режим энергосбережения LPM0

}

#pragma vector=TIMERA0_VECTOR
#pragma type_attribute=__interrupt
void TimerA0_ISR (void)
{
tick_ms += TICK_MS_ADDVAL; //инкремент счтечика тиков [мс]
__bic_SR_register_on_exit(LPM0_bits);//выход из режима энергосбережения при выходе из прерывания
}


Так вот, отсутствие мерцания светодиода даёт мне право полагать, что флаг готовности выходного буфера никогда не устанавливается в данном коде. crying.gif
В вашем коде светодиод мерцает, но UART не выдаёт ничего (стало быть кварц работает и он здесь непричём).... laughing.gif
rezident
Ну вот, так сразу видно где у вас ошибки. Готовность буфера не наступает, потому что вы забыли скобки и пишете в буфер UART постоянно на каждом цикле for(;;). Должно быть так.
Код
if ((UC1IFG&UCA1TXIFG)!=0) //буфер передатчика готов?
{ P5OUT ^= BIT7;
  UCA1TXBUF = uart_buf[idx]; //вывод текущего символа
}

Кроме того, непонятно, вы собирались использовать XT2 или DCO в качестве SMCLK? Потому, что у вас часть строк раскомментирована, что неправильно. Нужно раскомментировать все и поменять дефайн с величиной частоты SMCLK.
Ошибку мою так и не исправили?
Код
do
{ IFG1 &= ~OFIFG;
} while ((IFG1&OFIFG) != 0); //ждем готовности всей системы тактирования


Update. Вот блин, вслед за вами повелся и фигню написал. sad.gif Исправил while на if.
Zelepuk
Вот. исправил код. Светодиод горит всё время. В порт не выводится ничего(
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;
}

uint16_t tick_ms; //счетчик миллисекунд
uint8_t uart_buf[]={'0','1','2','3','4','5','6','7','8','9','\n','\r'};//буфер UART

void main(void)
{ uint16_t tickStamp, idx;
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 = XCAP8PF; //XT1=LF, DCO/D, XCAP=8пФ
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;
} while ((IFG1&OFIFG) != 0); //ждем готовности всей системы тактирования
//Инициализация 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 &= ~(UCA1TXIE | UCA1RXIE); //запретим прерывания USCI_A1
UC1IFG &= ~UCA1RXIFG; //сбросим флаг готовности буфера приемника
UC1IFG |= UCA1TXIFG; //установим флаг готовность буфера передатчика
//Инициализация LED
P5DIR |= BIT7;
P5SEL &= ~BIT7;
P5OUT &= ~BIT7;
idx=0;
tickStamp = tick_ms; //зафиксировать временную метку
__enable_interrupt(); //разрешим прерывания
for (;;)
{
if ((UC1IFG & UCA1TXIFG) != 0) //буфер передатчика готов?
{ UCA1TXBUF='A'; //вывод символа 'A'
P5OUT ^= BIT7;
}
}
}


думаю косяк в железе(может в в разводке). Но ведь первоначальный вариант (первый пост) выводил хоть что-то в порт (чупуху но всё же). Бывает ли такое? laughing.gif
rezident
Как вы определяете, что ничего не выводится? Осциллографом выход смотрели или в программе-терминале ничего не принимается? По свечению светодиода в данном случае вы ничего не поймете, т.к. темп вывода на скорости 9600 будет давать ему подсветку постоянно. В моем первоначальном примере вепеключение светодиода было синхронизирован по времени с таймаутом в 0,5с, что позволяло определить работоспособность. А у вас - нет.
Я нашел еще одну свою ошибку в инициализации FLL. Битом SCFQ_M модуляция выключается. И-за этого частота DCO может отличаться от расчетной. Попробуйте еще раз вот такой пример.
CODE
#include <msp430x471x7.h>
#include <stdint.h>

#define FREQMCLK 9830400UL //MCLK
#define FREQSMCLK 9830400UL //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;
}

uint16_t tick_ms; //счетчик миллисекунд
uint8_t uart_buf[]={'0','1','2','3','4','5','6','7','8','9','\n','\r'};//буфер UART

void main(void)
{ uint16_t tickStamp, idx;
uint32_t lTmp;
//Инициализация системы тактирования
FLL_CTL1 = XT2OFF; //D=2, MCLK=fDCOCLK/D, SMCLK=fDCOCLK/D, ACLK=LFXT/1, XT2=off
FLL_CTL2 = XT2S1; //для работы XT2=16МГц
FLL_CTL0 = XCAP11PF; //XT1=LF, DCO/D, XCAP=11пФ
while ((FLL_CTL0 & LFOF) != 0); //ждем готовности генератора 32768Гц
SCFI0 = FLLD_4 | FN_3; //D=4, fDCOCLK = 2.2-17Mhz
SCFQCTL = (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
do
{ IFG1 &= ~OFIFG;
} while ((IFG1&OFIFG) != 0); //ждем готовности всей системы тактирования
//Инициализация 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 &= ~(UCA1TXIE | UCA1RXIE); //запретим прерывания USCI_A1
UC1IFG &= ~UCA1RXIFG; //сбросим флаг готовности буфера приемника
UC1IFG |= UCA1TXIFG; //установим флаг готовность буфера передатчика
//Иницализация TimerA
TACTL = TASSEL_1 | TACLR; //TACLK=ACLK/1
TACCR0=(uint16_t)(FREQACLK/10UL); //период около 100мс
TACCTL0 = CCIE; //разр. прерывание от CCR0
TACCTL1 = 0;
TACCTL2 = 0;
TACTL |= MC_1; //запустить таймер в режиме CountUP
//Инициализация LED
P5DIR |= BIT7;
P5SEL &= ~BIT7;
P5OUT &= ~BIT7;
idx=0;
tickStamp = tick_ms; //зафиксировать временную метку
__enable_interrupt(); //разрешим прерывания
for (;;)
{ if ((tick_ms - tickStamp) >= BLINK_TIME_MS)//полупериод мерцания закончился?
{ tickStamp = tick_ms; //запомним новое значение метки времени
if ((UC1IFG & UCA1TXIFG) != 0)//буфер передатчика готов?
{ UCA1TXBUF = uart_buf[idx]; //вывод текущего символа
P5OUT |= BIT7; //включаем LED
if (idx < (sizeof(uart_buf)-1))//увеличение индекса
idx += 1;
else
idx = 0;
}
else
P5OUT &= ~BIT7; //выключаем LED
}
}
}

#pragma vector=TIMERA0_VECTOR
#pragma type_attribute=__interrupt
void TimerA0_ISR (void)
{
tick_ms += TICK_MS_ADDVAL; //инкремент счтечика тиков [мс]
}


Кстати, насчет ESR часового кварца. В errata присутствует описание бага XOSC8, про который я упоминал выше.
Цитата
XOSC8 LFXT1 Module
Function ACLK failure when crystal ESR is below 40 kΩ
Description When ACLK is sourced by a low-frequency crystal with an ESR below 40 kΩ, the duty
cycle of ACLK may fall below the specification; the OFIFG may become set or, in some
instances, ACLK may stop completely.
Workaround See the application report XOSC8 Guidance (SLAA423) for information regarding
working with this erratum.
Zelepuk
rezident
Попробовал последний вариант вашего кода (спасибо огромное вам).
Вот результаты: светодиод горит и тут же гаснет навсегда. В порт выводится бяка (очень медленно выводится) - см. фото.
smile3046.gif smile3046.gif smile3046.gif

Про резонатор: у меня резонатор KX-327S. load capacitance CL = 12.5пФ. Резонатор подключен по такой схеме (см. второе фото).
rezident
Я так и не понял, осциллограф у вас есть? Если есть, то посмотрите наличие и частоту сигналов SMCLK и ACLK. В примере который привожу ниже они выведены на P1.4 и P1.5 соответственно.
Очередной пример, использующий XT2=16МГц в качестве частоты тактирования UART. Посредством UART должны непрерывно (без задержек) выводиться строки
"0123456789"
Поведение светодиода: после инициализации он светится. Если передача идет, то он мерцает с частотой 2Гц. Если же передачи нет, то он гаснет. Поскольку я не знаю как именно у вас светодиод подключен (между плюсом питания и P5.7 или между P5.7 и общим?), то переопределите уж сами макросы LED_OFF и LED_ON так, чтобы они соответствовали правильной полярности управляющего сигнала.
CODE
#include <stdint.h>
#include <msp430x471x7.h>

#define FREQMCLK 2097152UL //MCLK
#define FREQSMCLK 16000000UL //SMCLK
#define FREQACLK 32768UL //ACLK
#define BAUDRATE 9600UL //baudrate
#define TICK_MS_ADDVAL 10U //инкремент таймера тиков [мс]
#define BLINK_TM_MS 250U //полупериод мерцания LED [мс]
#define LED_ON P5OUT&=~BIT7//включить LED
#define LED_OFF P5OUT|=BIT7 //выключить LED
#define LED_TOGGLE P5OUT^=BIT7 //переключить LED

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

volatile uint16_t tick_ms; //счетчик миллисекунд
uint8_t uart_buf[]={'0','1','2','3','4','5','6','7','8','9','\n','\r'};//буфер UART

void main(void)
{ uint16_t tickStamp, idx, flag;
uint32_t lTmp;
//Инициализация системы тактирования
FLL_CTL1 = 0; //D=2, MCLK=fDCOCLK/D, SMCLK=fDCOCLK/D, ACLK=LFXT/1, XT2=on
FLL_CTL2 = XT2S1; //для работы XT2=16МГц
FLL_CTL0 = XCAP11PF; //XT1=LF, DCO/D, XCAP=11пФ
while ((FLL_CTL0 & LFOF) != 0); //ждем готовности генератора 32768Гц
SCFI0 = FLLD_2; //D=2, fDCOCLK = 0.65-6.1Mhz
SCFQCTL = (32U-1U); //fDCOCLK=32768*(32)*2=2097152Гц, DCO=fDCOCLK/2
FLL_CTL0 |= DCOPLUS; //MCLK=DCO/1, SMCLK=DCO/1
do
{ IFG1 &= ~OFIFG;
} while ((IFG1&OFIFG) != 0); //ждем готовности всей системы тактирования
FLL_CTL1 |= SELS; //MCLK=fDCOCLK, SMCLK=XT2, ACLK=LFXT/1, XT2=on
//Инициализация 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 &= ~(UCA1TXIE | UCA1RXIE); //запретим прерывания USCI_A1
UC1IFG &= ~UCA1RXIFG; //сбросим флаг готовности буфера приемника
UC1IFG |= UCA1TXIFG; //установим флаг готовность буфера передатчика
//Иницализация TimerA
TACTL = TASSEL_1 | TACLR; //TACLK=ACLK/1
TACCR0=(uint16_t)(FREQACLK*TICK_MS_ADDVAL/1000UL); //период около 10мс
TACCTL0 = CCIE; //разр. прерывание от CCR0
TACCTL1 = 0;
TACCTL2 = 0;
TACTL |= MC_1; //запустить таймер в режиме CountUP
//Инициализация LED
P5DIR |= BIT7;
P5SEL &= ~BIT7;
LED_ON;
//Настройка пинов чтобы посмотреть частоту SMCLK и ACLK
P1DIR |= BIT4 | BIT5;
P1SEL |= BIT4 | BIT5; //P1.4 = SMCLK, P1.5 = ACLK

idx=0;
flag=0;
tickStamp = tick_ms; //зафиксировать временную метку
__enable_interrupt(); //разрешим прерывания
for (;;)
{ if ((UC1IFG & UCA1TXIFG) != 0) //буфер передатчика готов?
{ UCA1TXBUF = uart_buf[idx]; //вывод текущего символа
flag=1; //установим флаг готовности UART
if (idx < (sizeof(uart_buf)-1))//увеличение индекса элемента буфера
idx += 1;
else
idx = 0;
}
if ((tick_ms - tickStamp) >= BLINK_TM_MS)//полупериод мерцания закончился?
{ tickStamp = tick_ms; //запомним новое значение метки времени
if (flag != 0) //проверка флага готовности UART
{ LED_TOGGLE; //включаем LED
flag = 0; //сбросим флаг готовности UART
}
else
LED_OFF; //выключаем LED
}
}
}

#pragma vector=TIMERA0_VECTOR
#pragma type_attribute=__interrupt
void TimerA0_ISR (void)
{
tick_ms += TICK_MS_ADDVAL; //инкремент счтечика тиков [мс]
}

Если и этот пример у вас не будет работать, то я уже теряюсь в догадках о причинах такого поведения вашего устройства. sad.gif На всякий случай попробуйте вместо виндусового Гипертерминала использовать программу Br@y's Terminal.
Zelepuk
Пока осциллографа под рукой нет (завтра планирую получить).
Но на выводы, на которые выводятся сигналы частоты подключены светодиоды, а они не горят. Светодиод, который сигнализирует о передаче данных - горит.
Порт молчит.

И ещё. Может дело и правда в железе? У меня физический уровень реализован на двух оптронах и используется сигнал DTR (около 10В). Когда порт открыт на DTR +10В. (см. фото схемы).

ещё: вы используете XT2 в качестве источника тактирования USCI (последний вариант кода). Но регистры UCA1BR1, UCA1BR0 остаются неизменными (как и при тактировании от DCO) - как я понял скорость везде должна составить 9600. Это правильно?
rezident
Цитата(Zelepuk @ Jul 21 2011, 19:25) *
И ещё. Может дело и правда в железе? У меня физический уровень реализован на двух оптронах и используется сигнал DTR (около 10В). Когда порт открыт на DTR +10В. (см. фото схемы).
Я правильно разглядел, что R47 у вас 220кОм? wacko.gif А V+ это питание MSP430 около 3В? Нда уж. cranky.gif В таком случае понятно почему нет передачи. Номинал резистора нужно уменьшить примерно в 2000 раз. До 100Ом. А лучше вообще изменить схемотехнику этого преобразователя уровней.
Цитата(Zelepuk @ Jul 21 2011, 19:25) *
ещё: вы используете XT2 в качестве источника тактирования USCI (последний вариант кода).
Да, используется частота от XT2=16МГц.
Цитата(Zelepuk @ Jul 21 2011, 19:25) *
Но регистры UCA1BR1, UCA1BR0 остаются неизменными (как и при тактировании от DCO) - как я понял скорость везде должна составить 9600. Это правильно?
Почему неизменными? Там происходит подстановка величин и расчет в препроцессоре при компиляции . Если вам нужно изменять baudrate в программе, то замените в формуле расчета символьные константы переменными типа uint32_t (unsigned long), задав им предварительно требуемые значения.
Zelepuk
Цитата(rezident @ Jul 21 2011, 19:20) *
Я правильно разглядел, что R47 у вас 220кОм? wacko.gif А V+ это питание MSP430 около 3В? Нда уж. cranky.gif В таком случае понятно почему нет передачи. Номинал резистора нужно уменьшить примерно в 2000 раз. До 100Ом. А лучше вообще изменить схемотехнику этого преобразователя уровней.
Да, используется частота от XT2=16МГц.
Почему неизменными? Там происходит подстановка величин и расчет в препроцессоре при компиляции . Если вам нужно изменять baudrate в программе, то замените в формуле расчета символьные константы переменными типа uint32_t (unsigned long), задав им предварительно требуемые значения.


Простите что ввожу в заблуждение (всётаки некоторые вещи никто кроме меня знать не может). Резистор там 220 Ом (на схема ошибка - в железе правильно).
Вообще схема взята с апликухи счётчика от Texas Instruments. Но сама апликуха не работает(хотя должна была). Вот и решил написать программу простую для вывода в порт символов.
laughing.gif laughing.gif laughing.gif laughing.gif
Zelepuk
Цитата(rezident @ Jul 21 2011, 19:20) *
А лучше вообще изменить схемотехнику этого преобразователя уровней.


как бы вы посоветовали это сделать?
Zelepuk
Вот что получаю в окне терминала (см. фото). В терминале что-то появляется только в момент открытия порта... (ложу трубку, поднимаю - появляются цифры и дальше тишина, опять ложу трубку и поднимаю - цифры и тишина....)

Очень странное поведение.... хрень какая-то... smile3046.gif smile3046.gif smile3046.gif
Zelepuk
Что примечательно, заменив преобразователь уровней на max232 я вообще ничего не наблюдаю...(схема заведомо рабочая).

Такое вообще бывает?
rezident
Эх-ма. sad.gif Основная проблема большинства начинающих в том, что они варятся внутри своей проблемы, не умея/на зная, как выйти и взглянуть на нее с другой высоты полета. А с другой высоты проблема выглядит немного иначе и попутно могут выявиться связи с другими объектами, которые незаметны изнутри проблемы. Вдобавок начинающие пренебрегают отвечать (хотя бы для самого себя) на наводящие вопросы, которые они не понимают или считают незначащими.
Вот вы, Zelepuk, пишете сообщения не для публичного форума, а для себя. "Мысли вслух" т.с.. Нет, такой способ тоже бывает полезным! Но только в том случае, когда вы, не пренебрегая мелочами, описываете проблему и ее текущее состояние полностью, а не фрагментарно!
Из последних ваших сообщений лично мне совершенно непонятно какую программу, с какими изменениями/дополнениями вы сейчас проверяете? С какой схемотехникой или на какой Eval Board? Ведь даже кусочек опубликованной вами схемы оказался неточным, а как там дело с остальной схемой? Проверяли вы или нет а) выходные сигналы осциллографом, б) преобразователь уровней отдельно от MSP430, в) работу связи с другой терминальной программой, г) работоспособность самого порта на компьютере, д) настройки COM-порта? Вы вообще используете нормальный аппаратный COM-порт или переходник USB-COM? Ответе хотя бы для себя на эти вопросы, чтобы локализовать место поиска проблемы.
Zelepuk
Схемотехника используется из slaa409 (апликейшн счётчика).
Преобразователь уровней на MAX232 работает (проверялось отдельно).
Используется COM-порт на материнке.
Осцила нет crying.gif
Код (это ваш последний вариант для меня - SMLK от XT2):
CODE
#include <stdint.h>
#include <msp430x471x7.h>

#define FREQMCLK 2097152UL //MCLK
#define FREQSMCLK 16000000UL //SMCLK
#define FREQACLK 32768UL //ACLK
#define BAUDRATE 9600UL //baudrate
#define TICK_MS_ADDVAL 10U //инкремент таймера тиков [мс]
#define BLINK_TM_MS 250U //полупериод мерцания LED [мс]
#define LED_ON P5OUT&=~BIT7//включить LED
#define LED_OFF P5OUT|=BIT7 //выключить LED
#define LED_TOGGLE P5OUT^=BIT7 //переключить LED

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

volatile uint16_t tick_ms; //счетчик миллисекунд
uint8_t uart_buf[]={'0','1','2','3','4','5','6','7','8','9','\n','\r'};//буфер UART

void main(void)
{ uint16_t tickStamp, idx, flag;
uint32_t lTmp;
//Инициализация системы тактирования
FLL_CTL1 = 0; //D=2, MCLK=fDCOCLK/D, SMCLK=fDCOCLK/D, ACLK=LFXT/1, XT2=on
FLL_CTL2 = XT2S1; //для работы XT2=16МГц
FLL_CTL0 = XCAP11PF; //XT1=LF, DCO/D, XCAP=11пФ
while ((FLL_CTL0 & LFOF) != 0); //ждем готовности генератора 32768Гц
SCFI0 = FLLD_2; //D=2, fDCOCLK = 0.65-6.1Mhz
SCFQCTL = (32U-1U); //fDCOCLK=32768*(32)*2=2097152Гц, DCO=fDCOCLK/2
FLL_CTL0 |= DCOPLUS; //MCLK=DCO/1, SMCLK=DCO/1
do
{ IFG1 &= ~OFIFG;
} while ((IFG1&OFIFG) != 0); //ждем готовности всей системы тактирования
FLL_CTL1 |= SELS; //MCLK=fDCOCLK, SMCLK=XT2, ACLK=LFXT/1, XT2=on
//Инициализация 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 &= ~(UCA1TXIE | UCA1RXIE); //запретим прерывания USCI_A1
UC1IFG &= ~UCA1RXIFG; //сбросим флаг готовности буфера приемника
UC1IFG |= UCA1TXIFG; //установим флаг готовность буфера передатчика
//Иницализация TimerA
TACTL = TASSEL_1 | TACLR; //TACLK=ACLK/1
TACCR0=(uint16_t)(FREQACLK*TICK_MS_ADDVAL/1000UL); //период около 10мс
TACCTL0 = CCIE; //разр. прерывание от CCR0
TACCTL1 = 0;
TACCTL2 = 0;
TACTL |= MC_1; //запустить таймер в режиме CountUP
//Инициализация LED
P5DIR |= BIT7;
P5SEL &= ~BIT7;
LED_ON;
//Настройка пинов чтобы посмотреть частоту SMCLK и ACLK
P1DIR |= BIT4 | BIT5;
P1SEL |= BIT4 | BIT5; //P1.4 = SMCLK, P1.5 = ACLK

idx=0;
flag=0;
tickStamp = tick_ms; //зафиксировать временную метку
__enable_interrupt(); //разрешим прерывания
for (;;)
{ if ((UC1IFG & UCA1TXIFG) != 0) //буфер передатчика готов?
{ UCA1TXBUF = uart_buf[idx]; //вывод текущего символа
flag=1; //установим флаг готовности UART
if (idx < (sizeof(uart_buf)-1))//увеличение индекса элемента буфера
idx += 1;
else
idx = 0;
}
if ((tick_ms - tickStamp) >= BLINK_TM_MS)//полупериод мерцания закончился?
{ tickStamp = tick_ms; //запомним новое значение метки времени
if (flag != 0) //проверка флага готовности UART
{ LED_TOGGLE; //включаем LED
flag = 0; //сбросим флаг готовности UART
}
else
LED_OFF; //выключаем LED
}
}
}

#pragma vector=TIMERA0_VECTOR
#pragma type_attribute=__interrupt
void TimerA0_ISR (void)
{
tick_ms += TICK_MS_ADDVAL; //инкремент счтечика тиков [мс]
}


Код, судя по всему, верный и рабочий.
Суть проблемы:
Когда открываю порт в HyperTerminal то по экрану бегут иероглифы. Стоит только "закрыть-открыть" порт тут же всё идёт как надо (бегут цифры "0123456789" столбиком). Иногда "закрыть-открыть" нужно несколько раз тобы получить нужную картину.
Сие чудо наблюдается в ЛЮБОЙ терминальной программе.

Если бы просто не выводилось ничего я бы больше не стал писать (сколько можно уж). Но тут непонятное вовсе явление.
rezident
"Дьявол кроется в мелочах". laughing.gif Не ссылайтесь на slaa409, опубликуйте свою схему. Если она на базе slaa409, то ничего секретного там нет, не так ли? Например, в схеме из slaa409 используется часовой кварц со встроенными нагрузочными конденсаторами, а у вас другой кварц с внешними конденсаторами. Притом, что имеются нюансы применения такого кварца, о чем отмечено в Errata.
Преобразователь вы проверяли как? Пробовали проверить на "эхо" при подключенной плате? Т.е. все подключено штатно к ПК, но только в самом преобразователе TTL выход преобразователя подключен к TTL входу, который в свою очередь отключен от выхода MSP430. Отключив в программе-терминале локальное эхо, нужно получить такую же строку символов, которую вы вводите с клавиатуры в окне терминала. Handshake (аппаратное управление потоком) в настройках терминальной программы точно отключено? Br@y's Terminal ведет себя также как и Гипертерминал?
Питание своей платы откуда получаете? Гальваническая изоляция от сети у этого БП имеется? Ваш ПК заземлен? Не могут ли токи от сетевого фильтра и/или от вашего БП мешать передаче (синфазная помеха)?
Dog Pawlowa
Цитата(Zelepuk @ Jul 25 2011, 22:08) *
Код, судя по всему, верный и рабочий.
Суть проблемы:
Когда открываю порт в HyperTerminal то по экрану бегут иероглифы. Стоит только "закрыть-открыть" порт тут же всё идёт как надо (бегут цифры "0123456789" столбиком). Иногда "закрыть-открыть" нужно несколько раз тобы получить нужную картину.
Сие чудо наблюдается в ЛЮБОЙ терминальной программе.

Если бы просто не выводилось ничего я бы больше не стал писать (сколько можно уж). Но тут непонятное вовсе явление.

Код неверный и нерабочий, поскольку он постоянно, без интервалов больше стопового передает что-то.
Принять такое, подключившись в произвольный момент времени, невозможно.
Вы вообще про байтовую синхронизацию слышали? wink.gif
Сделайте так: запустите терминал, откройте порт, ПОТОМ запустите устройство и отпишитесь о результатах.
Zelepuk
Цитата(Dog Pawlowa @ Jul 26 2011, 06:33) *
Код неверный и нерабочий, поскольку он постоянно, без интервалов больше стопового передает что-то.
Принять такое, подключившись в произвольный момент времени, невозможно.
Вы вообще про байтовую синхронизацию слышали? wink.gif
Сделайте так: запустите терминал, откройте порт, ПОТОМ запустите устройство и отпишитесь о результатах.


Да, так всё работает нормально. Выходит нужно задержку поставить в коде?

Цитата(rezident @ Jul 26 2011, 00:42) *
"Дьявол кроется в мелочах". laughing.gif Не ссылайтесь на slaa409, опубликуйте свою схему. Если она на базе slaa409, то ничего секретного там нет, не так ли? Например, в схеме из slaa409 используется часовой кварц со встроенными нагрузочными конденсаторами, а у вас другой кварц с внешними конденсаторами. Притом, что имеются нюансы применения такого кварца, о чем отмечено в Errata.
Преобразователь вы проверяли как? Пробовали проверить на "эхо" при подключенной плате? Т.е. все подключено штатно к ПК, но только в самом преобразователе TTL выход преобразователя подключен к TTL входу, который в свою очередь отключен от выхода MSP430. Отключив в программе-терминале локальное эхо, нужно получить такую же строку символов, которую вы вводите с клавиатуры в окне терминала. Handshake (аппаратное управление потоком) в настройках терминальной программы точно отключено? Br@y's Terminal ведет себя также как и Гипертерминал?
Питание своей платы откуда получаете? Гальваническая изоляция от сети у этого БП имеется? Ваш ПК заземлен? Не могут ли токи от сетевого фильтра и/или от вашего БП мешать передаче (синфазная помеха)?


Техасовцы вообще народ интересный. Выдают схему, а потом на фото платы у них же виден обычный кварц часовой и два кондёра.
Преобразователь проверял путём подключения к другой плате (на другом микроконтроллере).
ВСЕ терминалы ведут себя одинаково.
Гальваническая развязка у БП есть.
ПК не заземлён (обычный пк как у всех).
Dog Pawlowa
Цитата(Zelepuk @ Jul 26 2011, 11:25) *
Да, так всё работает нормально. Выходит нужно задержку поставить в коде?

Я же не знаю, какая цель этого проекта.
Если убедиться в работоспособности преобразователя уровней RS232, то цель достигнута.
Если передавать осмысленные данные, то одной задержки мало, обычно предпринимают какие-нибудь меры для контроля правильности приема.
Правила, установленные для организации передачи данных, зовутся протоколом, и Вы должны его сформулировать, предусмотрев поведение для любой из сторон.
Сейчас Вы не предусмотрели поведение приемника.
Включившись в середине посылки, даже при наличии задержки, приемник получит неправильные данные и запустит стратегическую ракету, начав III WW.
rezident
Цитата(Dog Pawlowa @ Jul 26 2011, 07:33) *
Код неверный и нерабочий, поскольку он постоянно, без интервалов больше стопового передает что-то.
Принять такое, подключившись в произвольный момент времени, невозможно.

Да, этот момент я прохлопал, увлекшись проблемой ТС с тактированием UART. laughing.gif Хотя в посте 23 у меня был пример в котором выдача байта в UART была синхронизирована с мерцанием светодиода и значительно превышала период его передачи.
Цитата(Zelepuk @ Jul 26 2011, 13:25) *
Да, так всё работает нормально. Выходит нужно задержку поставить в коде?
Вам нужен какой-либо протокол передачи данных, который включает в себя контроль целостности данных. Кроме того, устройства чаще всего подразделяются на ведущие и ведомые. Соответственно передача данных строится как запрос (ведущего) - ответ (ведомого). Ваш электросчетчик будет ведомым, так что он должен "слушать" линию связи и по запросу выдавать требуемый ведущим блок данных.
Цитата(Zelepuk @ Jul 26 2011, 13:25) *
Техасовцы вообще народ интересный. Выдают схему, а потом на фото платы у них же виден обычный кварц часовой и два кондёра.
Evalutation Board это не догма, а пример/образец, руководство к действию. Этот пример не для слепого клонирования, а как образец для разработки на его основе своего устройства. Разработка это работа инженера, который должен понимать нюансы применения компонентов.
Zelepuk
Цитата(Dog Pawlowa @ Jul 26 2011, 13:28) *
Я же не знаю, какая цель этого проекта.
Если убедиться в работоспособности преобразователя уровней RS232, то цель достигнута.
Если передавать осмысленные данные, то одной задержки мало, обычно предпринимают какие-нибудь меры для контроля правильности приема.
Правила, установленные для организации передачи данных, зовутся протоколом, и Вы должны его сформулировать, предусмотрев поведение для любой из сторон.
Сейчас Вы не предусмотрели поведение приемника.
Включившись в середине посылки, даже при наличии задержки, приемник получит неправильные данные и запустит стратегическую ракету, начав III WW.


Цель? Напсиать свой putchar.
Вот например когда я работал с ARM9, то в компиляторе был printf, который выводил данные в терминалку через DBGU (UART). Так вот там было всё просто и диалого между пользователем и камнем осуществлялся очень хорошо (и протоколов там небыло никаких).
Dog Pawlowa
Цитата(Zelepuk @ Jul 26 2011, 15:52) *
Цель? Напсиать свой putchar.

Ну дык и писали бы putchar!
А так получился тест непонятно чего.
Zelepuk
Теперь можно и putchar писать, теперь видно что связь есть и связь нормальная
Zelepuk
Всем спасибо! Тема закрыта!
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.