|
Проблема с UART, выводит несуразицу |
|
|
|
Jul 13 2011, 05:34
|
Знающий
   
Группа: Участник
Сообщений: 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 принимает его и кидает в компорт компьютера), то он работает со сбоями (сначала всё хорошо, потом символы не передаются, потом передаётся чепуха...) Нужна помощь, всю голову сломал((
Эскизы прикрепленных изображений
|
|
|
|
|
Jul 14 2011, 05:40
|
Знающий
   
Группа: Участник
Сообщений: 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
|
|
|
|
|
Jul 14 2011, 15:51
|
Гуру
     
Группа: Свой
Сообщений: 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).
|
|
|
|
|
Jul 14 2011, 17:12
|
Знающий
   
Группа: Участник
Сообщений: 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 или нет?
|
|
|
|
|
Jul 14 2011, 18:50
|
Гуру
     
Группа: Свой
Сообщений: 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.
Эскизы прикрепленных изображений
|
|
|
|
|
Jul 15 2011, 14:17
|
Знающий
   
Группа: Участник
Сообщений: 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
|
|
|
|
|
Jul 15 2011, 14:20
|
Гуру
     
Группа: Свой
Сообщений: 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 и там такой подход не практикуется. Я что-то не пойму, вам "шашечки" или ехать? Цитата(Zelepuk @ Jul 15 2011, 19:17)  Это прочитано из русского руководства. Получается, если есть два кварца на плате, можно вообще без DCO обойтись. Я наверное для себя предыдущее сообщение писал, да? Вы либо его не читали, либо смысла не поняли. Перечитайте еще раз.
|
|
|
|
|
Jul 15 2011, 17:34
|

Гуру
     
Группа: Свой
Сообщений: 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
|
|
|
|
|
Jul 16 2011, 12:22
|
Знающий
   
Группа: Участник
Сообщений: 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 Строго целое не получится никогда.
|
|
|
|
|
Jul 16 2011, 13:36
|
Знающий
   
Группа: Участник
Сообщений: 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). Теперь даже не мигает светодиод.... накосячил опять где-то наверное(((  единственное что могло прийти в голову - номиналами конденсаторов программно поиграться - непомогло... (а это может влиять вплоть до неработоспособности?)
Сообщение отредактировал Zelepuk - Jul 16 2011, 13:47
|
|
|
|
|
Jul 17 2011, 00:26
|
Гуру
     
Группа: Свой
Сообщений: 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 мне реализовывать уже было лень  Можете попробовать сами его реализовать, учитывая, что имеется возможность внутренне скоммутировать 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
|
|
|
|
|
Jul 17 2011, 19:00
|
Знающий
   
Группа: Участник
Сообщений: 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 мне реализовывать уже было лень  Можете попробовать сами его реализовать, учитывая, что имеется возможность внутренне скоммутировать 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, за внимание! Но вроде код грамотный и всё разжёвано... но ваш код не запускается вовсе... светодиод не горит, в терминалке ничего не выводится...((( А может вся эта система не запускаться из-за того, что неправильно кондесаторы на кварцах подобраны? Разбираюсь дальше За код ещё раз спасибо.
Сообщение отредактировал Zelepuk - Jul 17 2011, 19:11
|
|
|
|
|
Jul 17 2011, 21:16
|
Гуру
     
Группа: Свой
Сообщений: 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.
|
|
|
|
2 чел. читают эту тему (гостей: 2, скрытых пользователей: 0)
Пользователей: 0
|
|
|