реклама на сайте
подробности

 
 
3 страниц V   1 2 3 >  
Reply to this topicStart new topic
> Проблема с UART, выводит несуразицу
Zelepuk
сообщение Jul 13 2011, 05:34
Сообщение #1


Знающий
****

Группа: Участник
Сообщений: 634
Регистрация: 27-10-10
Пользователь №: 60 464



Вот код
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 принимает его и кидает в компорт компьютера), то он работает со сбоями (сначала всё хорошо, потом символы не передаются, потом передаётся чепуха...)

Нужна помощь, всю голову сломал((
Эскизы прикрепленных изображений
Прикрепленное изображение
 
Go to the top of the page
 
+Quote Post
rezident
сообщение Jul 13 2011, 12:23
Сообщение #2


Гуру
******

Группа: Свой
Сообщений: 10 920
Регистрация: 5-04-05
Пользователь №: 3 882



Модуль тактирования проинициализируйте полностью!
Go to the top of the page
 
+Quote Post
Zelepuk
сообщение Jul 14 2011, 05:40
Сообщение #3


Знающий
****

Группа: Участник
Сообщений: 634
Регистрация: 27-10-10
Пользователь №: 60 464



Цитата(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).

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




Сообщение отредактировал Zelepuk - Jul 14 2011, 05:57
Go to the top of the page
 
+Quote Post
MrYuran
сообщение Jul 14 2011, 07:40
Сообщение #4


Беспросветный оптимист
******

Группа: Свой
Сообщений: 4 640
Регистрация: 26-12-07
Из: Н.Новгород
Пользователь №: 33 646



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

Типовое значение UMCTL для 32768/9600 равно 4А. (таблица в мануале)
Непонятно, из каких соображений у вас 6 торчит. Два бита подряд корректируются, остальные пошли вразнос.


--------------------
Программирование делится на системное и бессистемное. ©Моё :)
— а для кого-то БГ — это Bill Gilbert =)
Go to the top of the page
 
+Quote Post
rezident
сообщение Jul 14 2011, 15:51
Сообщение #5


Гуру
******

Группа: Свой
Сообщений: 10 920
Регистрация: 5-04-05
Пользователь №: 3 882



Цитата(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).
Go to the top of the page
 
+Quote Post
Zelepuk
сообщение Jul 14 2011, 17:12
Сообщение #6


Знающий
****

Группа: Участник
Сообщений: 634
Регистрация: 27-10-10
Пользователь №: 60 464



Цитата(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 или нет?
Go to the top of the page
 
+Quote Post
rezident
сообщение Jul 14 2011, 18:50
Сообщение #7


Гуру
******

Группа: Свой
Сообщений: 10 920
Регистрация: 5-04-05
Пользователь №: 3 882



Цитата(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.
Эскизы прикрепленных изображений
Прикрепленное изображение
 
Go to the top of the page
 
+Quote Post
Zelepuk
сообщение Jul 15 2011, 14:17
Сообщение #8


Знающий
****

Группа: Участник
Сообщений: 634
Регистрация: 27-10-10
Пользователь №: 60 464



Цитата(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 обойтись.

Сообщение отредактировал Zelepuk - Jul 15 2011, 14:26
Go to the top of the page
 
+Quote Post
rezident
сообщение Jul 15 2011, 14:20
Сообщение #9


Гуру
******

Группа: Свой
Сообщений: 10 920
Регистрация: 5-04-05
Пользователь №: 3 882



Цитата(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 обойтись.

Я наверное для себя предыдущее сообщение писал, да? Вы либо его не читали, либо смысла не поняли. Перечитайте еще раз.
Go to the top of the page
 
+Quote Post
zltigo
сообщение Jul 15 2011, 17:34
Сообщение #10


Гуру
******

Группа: Свой
Сообщений: 13 372
Регистрация: 27-11-04
Из: Riga, Latvia
Пользователь №: 1 244



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

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

См. выше.


--------------------
Feci, quod potui, faciant meliora potentes
Go to the top of the page
 
+Quote Post
Zelepuk
сообщение Jul 16 2011, 12:22
Сообщение #11


Знающий
****

Группа: Участник
Сообщений: 634
Регистрация: 27-10-10
Пользователь №: 60 464



Цитата(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
Строго целое не получится никогда.
Go to the top of the page
 
+Quote Post
Zelepuk
сообщение Jul 16 2011, 13:36
Сообщение #12


Знающий
****

Группа: Участник
Сообщений: 634
Регистрация: 27-10-10
Пользователь №: 60 464



Теперь пробую инициализировать явно все регистры модуля тактирования и модуля 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
единственное что могло прийти в голову - номиналами конденсаторов программно поиграться - непомогло... (а это может влиять вплоть до неработоспособности?)

Сообщение отредактировал Zelepuk - Jul 16 2011, 13:47
Go to the top of the page
 
+Quote Post
rezident
сообщение Jul 17 2011, 00:26
Сообщение #13


Гуру
******

Группа: Свой
Сообщений: 10 920
Регистрация: 5-04-05
Пользователь №: 3 882



Есть несколько вариантов организации тактирования 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 - Jul 17 2011, 10:43
Go to the top of the page
 
+Quote Post
Zelepuk
сообщение Jul 17 2011, 19:00
Сообщение #14


Знающий
****

Группа: Участник
Сообщений: 634
Регистрация: 27-10-10
Пользователь №: 60 464



Цитата(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
За код ещё раз спасибо.

Сообщение отредактировал Zelepuk - Jul 17 2011, 19:11
Go to the top of the page
 
+Quote Post
rezident
сообщение Jul 17 2011, 21:16
Сообщение #15


Гуру
******

Группа: Свой
Сообщений: 10 920
Регистрация: 5-04-05
Пользователь №: 3 882



Цитата(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.
Go to the top of the page
 
+Quote Post

3 страниц V   1 2 3 >
Reply to this topicStart new topic
2 чел. читают эту тему (гостей: 2, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 17th June 2025 - 22:50
Рейтинг@Mail.ru


Страница сгенерированна за 0.01557 секунд с 7
ELECTRONIX ©2004-2016