Zelepuk 0 13 июля, 2011 Опубликовано 13 июля, 2011 · Жалоба Вот код #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 0 13 июля, 2011 Опубликовано 13 июля, 2011 · Жалоба Модуль тактирования проинициализируйте полностью! Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Zelepuk 0 14 июля, 2011 Опубликовано 14 июля, 2011 (изменено) · Жалоба Модуль тактирования проинициализируйте полностью! У меня MSP430F47197 подклюен часовой кварц(32768) и кварцевый резонатор(16 мегагерц). Если я правильно понял, то можно тактировать USCI модуль от разных источников: DCO, SMCLK, ACLK. Я предпочёл ACLK (см. код выше). Я делаю так 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). Кто знает поправьте если что-то не так. Изменено 14 июля, 2011 пользователем Zelepuk Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
MrYuran 29 14 июля, 2011 Опубликовано 14 июля, 2011 · Жалоба Кто знает поправьте если что-то не так. Типовое значение UMCTL для 32768/9600 равно 4А. (таблица в мануале) Непонятно, из каких соображений у вас 6 торчит. Два бита подряд корректируются, остальные пошли вразнос. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
rezident 0 14 июля, 2011 Опубликовано 14 июля, 2011 · Жалоба Кто знает поправьте если что-то не так. Я же вам сказал полностью нужно проинициализировать! Т.е. прописать явными значениями все регистры модуля тактирования, а не накладывать маски на дефолтные (после 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 0 14 июля, 2011 Опубликовано 14 июля, 2011 · Жалоба Я же вам сказал полностью нужно проинициализировать! Т.е. прописать явными значениями все регистры модуля тактирования, а не накладывать маски на дефолтные (после 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 0 14 июля, 2011 Опубликовано 14 июля, 2011 · Жалоба нужен ли тогда вообще 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 0 15 июля, 2011 Опубликовано 15 июля, 2011 (изменено) · Жалоба Еще возникает вопрос зачем использовать 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 в своих примерах). Я же вам сказал полностью нужно проинициализировать! Т.е. прописать явными значениями все регистры модуля тактирования, а не накладывать маски на дефолтные (после POR) состояния. То же самое касается в отношении регистров USCI. Вы имеете ввиду, что нужно проинициализировать все регистры (см. приложенный рисунок) и каждый бит определить требуемым значением (если даже оно и не особо надо)??? Просто у меня есть большая апликуха от TI и там такой подход не практикуется. DCO нужен всегда! По крайней мере для тактирования MCLK нужен. MCLK: основное тактирование. Модуль MCLK программно выбирается как LFXT1CLK, XT2CLK (если доступен) или DCOCLK. MCLK делится на 1, 2, 4 или 8. MCLK используется ЦПУ и системой. Это прочитано из русского руководства. Получается, если есть два кварца на плате, можно вообще без DCO обойтись. Изменено 15 июля, 2011 пользователем Zelepuk Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
rezident 0 15 июля, 2011 Опубликовано 15 июля, 2011 · Жалоба Я подключаю кварц на XT2 (16000кГц) и делю его частоту на скорость UART(115200) получается 138 целых, а дробную часть просто не учитываю (именно так делают TI в своих примерах). В ваших предыдущих примерах генератор XT2 отключен! Вы имеете ввиду, что нужно проинициализировать все регистры (см. приложенный рисунок) и каждый бит определить требуемым значением (если даже оно и не особо надо)??? Просто у меня есть большая апликуха от TI и там такой подход не практикуется. Я что-то не пойму, вам "шашечки" или ехать? :rolleyes: Это прочитано из русского руководства. Получается, если есть два кварца на плате, можно вообще без DCO обойтись. Я наверное для себя предыдущее сообщение писал, да? Вы либо его не читали, либо смысла не поняли. Перечитайте еще раз. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
zltigo 2 15 июля, 2011 Опубликовано 15 июля, 2011 · Жалоба получается 138 целых, а дробную часть просто не учитываю (именно так делают TI в своих примерах). Неграмотные индусы нанятые TI для написания кучи мусора для еще более неграмотных "программистов" округлять до целого не умеют. Но Вы для себя могли-бы и постараться и НЕ отбрасывать всегда безусловно дробную часть. Просто у меня есть большая апликуха от TI и там такой подход не практикуется. См. выше. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Zelepuk 0 16 июля, 2011 Опубликовано 16 июля, 2011 · Жалоба Я же вам сказал полностью нужно проинициализировать! Т.е. прописать явными значениями все регистры модуля тактирования, а не накладывать маски на дефолтные (после 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 0 16 июля, 2011 Опубликовано 16 июля, 2011 (изменено) · Жалоба Теперь пробую инициализировать явно все регистры модуля тактирования и модуля USCI. #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: единственное что могло прийти в голову - номиналами конденсаторов программно поиграться - непомогло... (а это может влиять вплоть до неработоспособности?) Изменено 16 июля, 2011 пользователем Zelepuk Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
rezident 0 17 июля, 2011 Опубликовано 17 июля, 2011 (изменено) · Жалоба Есть несколько вариантов организации тактирования 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) не будет равно заданному. #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. Исправил форматирование исходника. Изменил команду выхода из режима энергосбережения в прерывании. В принципе код генерился одинаковый, но так корректнее. Изменено 17 июля, 2011 пользователем rezident Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Zelepuk 0 17 июля, 2011 Опубликовано 17 июля, 2011 (изменено) · Жалоба Есть несколько вариантов организации тактирования 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) не будет равно заданному. #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: За код ещё раз спасибо. Изменено 17 июля, 2011 пользователем Zelepuk Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
rezident 0 17 июля, 2011 Опубликовано 17 июля, 2011 · Жалоба А может вся эта система не запускаться из-за того, что неправильно кондесаторы на кварцах подобраны? А какие конденсаторы у вас стоят? Если часовой кварц типовой (с нагрузочной емкостью 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. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться