|
Подключение 7-сегментного индикатора к msp430g24523, программирование |
|
|
|
Jun 18 2013, 12:12
|

Познающий...
     
Группа: Свой
Сообщений: 2 963
Регистрация: 1-09-05
Из: г. Иркутск
Пользователь №: 8 125

|
QUOTE (Cruz21 @ Jun 18 2013, 01:11)  Кто может указанные здесь AVRсоком коде, порты переименовать на наш msp430cкий Совсем запутался с портами, как с ними работать  Может быть я занудствую, но - учитесь читать мануалы и даташиты. Читая, Вы попутно впитываете сопутствующую полезную информацию, и с каждой итерацией чтения, находить ответы на вопросы будет легче. Естественно, что чтение не избавит от недоразумений и новых вопросов, но это будут вопросы рода "сделал как указано в этом толстющем мануале, всё проверил на не раз, а оно не работает. Помогите"  Чувствуете разницу?  ну тогда успехов
--------------------
Выбор.
|
|
|
|
|
Jun 18 2013, 19:42
|
Гуру
     
Группа: Свой
Сообщений: 10 920
Регистрация: 5-04-05
Пользователь №: 3 882

|
Цитата(Cruz21 @ Jun 17 2013, 13:49)  Исправил схему Плохо исправили. Нумерацию выводов нужно внести так, как она изображена у оригинального индикатора. Транзисторы заменить на NPN, оставив их включенными по изначальной схеме с общим эмиттером. Цитата(Cruz21 @ Jun 17 2013, 21:11)  Совсем запутался с портами, как с ними работать  Читайте User's Manual (по ссылке), в нем описано в разделе 8 Digital I/O. http://www.ti.com/product/msp430g2453Я не работал с AVR, чтобы давать аналогии. В MSP430 PxDIR регистр, определяющий функцию входа/выхода для режима GPIO (и для некоторых альтернативных): 0 - вход, 1 - выход. Вам нужна функция "выход", поэтому биты в PxDIR нужно установить в 1. В регистре PxOUT задается состояние выхода для GPIO. Вот этими PxOUT и нужно манипулировать, зажигая и выключая сегменты индикатора. PxSEL определяет подключение дополнительных функции к пину, отличающейся от GPIO. Поскольку вам этого не нужно, то в PxSEL биты должны быть сброшены в 0.
|
|
|
|
|
Jun 18 2013, 19:52
|
Участник

Группа: Участник
Сообщений: 43
Регистрация: 23-01-13
Пользователь №: 75 313

|
Цитата(rezident @ Jun 18 2013, 23:42)  Плохо исправили. Нумерацию выводов нужно внести так, как она изображена у оригинального индикатора. Транзисторы заменить на NPN, оставив их включенными по изначальной схеме с общим эмиттером. Я перепаял транзисторы NPN, но с общим коллектором, а не эмиттером. Почему мне нужно перепаять с ОЭ? Сейчас собираюсь заново собрать, как раз учту нумерацию в этот раз.
|
|
|
|
|
Jun 18 2013, 19:58
|
Гуру
     
Группа: Свой
Сообщений: 10 920
Регистрация: 5-04-05
Пользователь №: 3 882

|
Цитата(Cruz21 @ Jun 19 2013, 00:52)  Я перепаял транзисторы NPN, но с общим коллектором, а не эмиттером. Почему мне нужно перепаять с ОЭ? Я же не вижу, чего и куда вы перепаяли. На вашей схеме в сообщении №14 изображены транзисторы PNP, включенные по схеме с ОК. В то время как для работы в ключевом режиме вам нужны NPN, включенные по схеме с ОЭ. Может вам ТОЭ для начала почитать? Хотя бы даже в Википедии http://ru.wikipedia.org/wiki/%D0%9A%D0%B0%...%80%D0%BE%D0%BCP.S. в исходном сообщении на схеме у вас было правильное включение: PNP, с ОЭ относительно плюса питания. Но эта схема годилась бы для индикатора с общим анодом. А у вас индикатор с общим(и) катодом(ами), поэтому включать нужно NPN по схеме с ОЭ относительно общего провода ( минуса питания).
|
|
|
|
|
Jun 18 2013, 20:06
|
Участник

Группа: Участник
Сообщений: 43
Регистрация: 23-01-13
Пользователь №: 75 313

|
Цитата(rezident @ Jun 18 2013, 23:58)  Я же не вижу, чего и куда вы перепаяли. На вашей схеме в сообщении №14 изображены транзисторы PNP, включенные по схеме с ОК. В то время как для работы в ключевом режиме вам нужны NPN, включенные по схеме с ОЭ. Может вам ТОЭ для начала почитать? Хотя бы даже в Википедии http://ru.wikipedia.org/wiki/%D0%9A%D0%B0%...%80%D0%BE%D0%BCP.S. в исходной схему у вас было правильное включение: PNP, с ОЭ относительно плюса питания. Но эта схема годилась бы для индикатора с общим анодом. А у вас индикатор с общим(и) катодом(ами), поэтому включать нужно NPN по схеме с ОЭ относительно общего провода (минуса питания). Спасибо за помощь. Сейчас попробую сделать с ОЭ. Транзисторы я новые купил NPN КТ3102Б, а раньше были ВС327-25(аналог КТ3107Б) На схеме да, я не правильно указал транзисторы.
|
|
|
|
|
Jun 19 2013, 18:43
|
Участник

Группа: Участник
Сообщений: 43
Регистрация: 23-01-13
Пользователь №: 75 313

|
Наконец то собрал схему правильно, программно тоже начал работать индикатор, спасибо всем кто помог. Немного теперь и у меня мозгов прибавилось  Теперь осталось реализовать программную начинку, так сказать залить душу в тело. Особую благодарность хочу выразить rezident, kovigor  вам
|
|
|
|
|
Jun 23 2013, 12:29
|
Участник

Группа: Участник
Сообщений: 43
Регистрация: 23-01-13
Пользователь №: 75 313

|
Код #include <msp430g2452.h>
#define IND1 BIT5 //управление разрядами индикатора #define IND2 BIT4 #define IND3 BIT3 #define IND4 BIT2
unsigned char NUM;//отвечает какой разряд горит unsigned char BCD;//значение частоты unsigned char BC_H1,BC_L1,BC_H2,BC_L2; //разделение по BCD по знаково int t2ms=0;
unsigned char digits[]= { 0xBE, //0 0x84, //1 0xAB, //2 0xA7, //3 0x95, //4 0x37, //5 0x3F, //6 0xA4, //7 0xBF, //8 0xB7, //9 };
void main( void ) { WDTCTL = WDTPW + WDTHOLD;// Stop watchdog timer to prevent time out reset BCSCTL1 = CALBC1_16MHZ;//Проц тактируем от встроенного DCOCTL = CALDCO_16MHZ;//генератора с калибровкой последнего на 16 мгц P1DIR |= 0x3C; // P1 output P2DIR |= 0xFF; // P2 output //конфиг первого таймера TA0CCR0 = 32000;//?anoioa TA0CCTL0 = CCIE;// TACTL = TASSEL_2 + MC_1; // SMCLK, upmode
__enable_interrupt();
_BIS_SR(LPM0_bits + GIE); // Enter LPM0 w/ interrupt }
#pragma vector=TIMER0_A0_VECTOR __interrupt void Timer0_A0 (void) { P1OUT &= ~(IND1|IND2|IND3|IND4); switch (NUM) { case 0 : P2OUT = digits[1]; P1OUT |= IND1; break; case 1 : P2OUT = digits[2]; P1OUT |= IND2; break; case 2 : P2OUT = digits[3]; P1OUT |= IND3; break; case 3 : P2OUT = digits[4]; P1OUT |= IND4; break; } NUM++; if (NUM == 4) NUM = 0; } в чем может быть проблема? я хочу чтоб у меня светилось 1 2 3 4, а получается 1 1 1 1, 2 2 2 2, 3 3 3 3, 4 4 4 4??
Сообщение отредактировал Cruz21 - Jun 23 2013, 12:29
|
|
|
|
|
Jun 23 2013, 18:32
|
Гуру
     
Группа: Свой
Сообщений: 10 920
Регистрация: 5-04-05
Пользователь №: 3 882

|
Рискну предложить свой "перелопаченный" вариант вашей тестовой программы. CODE #include <msp430g2452.h>
unsigned char digits[]= { 0xBE, //0 0x84, //1 0xAB, //2 0xA7, //3 0x95, //4 0x37, //5 0x3F, //6 0xA4, //7 0xBF, //8 0xB7, //9 };
#define SYS_VALMCLKL 16000000UL //частота MCLK #define SYS_VALSMCLK 2000000UL //частота SMCLK #define SYS_VALACLK 12000UL //частота ACLK
/* биты управления разрядами индикатора */ #define SEG7_DIG1 (1U<<5) #define SEG7_DIG2 (1U<<4) #define SEG7_DIG3 (1U<<3) #define SEG7_DIG4 (1U<<2) /* маска битов управления разрядами */ #define SEG7_MASKDIG (SEG7_DIG1|SEG7_DIG2|SEG7_DIG3|SEG7_DIG4)
#define SEG7_MAXNUM 4 //количество разрядов индикатора #define SEG7_REFRESH_MS 5UL //период динамической индикации [мс]
#define SYSTICKMS_ADD 1UL //приращение счетчика системных тиков [мс]
volatile unsigned int sysTickMS; //счетчик мс
unsigned char seg7_buf[4]; //буфер индикатора unsigned int seg7_num; //номер разряда для текущего отображения
void main( void ) { unsigned int sysTickMSStamp, time;
WDTCTL = WDTPW + WDTHOLD; // Stop watchdog timer to prevent time out reset BCSCTL3 = LFXT1S_2; //ACLK = VLOCLK BCSCTL1 = CALBC1_16MHZ; //Проц тактируем от встроенного DCOCTL = CALDCO_16MHZ; //генератора с калибровкой последнего на 16 мгц BCSCTL2 = DIVM_0 | DIVS_3;//MCLK = DCOCLK, SMCLK = DCOCLK/8
P1DIR |= 0x3C; // P1 output P2DIR |= 0xFF; // P2 output
//конфиг первого таймера /* период: ccr0 = SYSTICKMS_ADD * (16МГц/8 / 1000мс) - 1 */ unsigned long tmp = SYS_VALSMCLK; tmp /= 1000UL; tmp *= SYSTICKMS_ADD; TA0CCR0 = (unsigned int)tmp - 1; TA0CCTL0 = CCIE; // TACTL = TASSEL_2 | MC_1; // SMCLK, upmode
/* заполним буфер индикатора символами 1, 2, 3, 4 вообще говоря, по-уму нужна отдельная функция, которая будет выводить строку символов в буфер индикатора */ seg7_buf[0] = digits[1]; seg7_buf[1] = digits[2]; seg7_buf[2] = digits[3]; seg7_buf[3] = digits[4];
sysTickMSStamp = sysTickMS; //сделаем отметку времени
__enable_interrupt();
/* main loop - большой цикл */ for(;;) { time = sysTickMS; if ((time - sysTickMSStamp) >= SEG7_REFRESH_MS) { /* здесь делаем все, что нужно делать при динамичесй индикации */ seg7_num += 1; if (seg7_num >= SEG7_MAXNUM) seg7_num = 0;
P1OUT &= ~(SEG7_MASKDIG); //гасим все разряды P2OUT = seg7_buf[seg7_num]; //выводим значение символа switch(seg7_num) //зажигаем соответствующий символ индикатора { case 0: P1OUT |= SEG7_DIG1; break; case 1: P1OUT |= SEG7_DIG2; break; case 2: P1OUT |= SEG7_DIG3; break; case 3: P1OUT |= SEG7_DIG4; break; } sysTickMSStamp = sysTickMS; //обновляем значение временной отметки }
/* не знаю, зачем вам это нужно в тестовой программе, но засыпаем */ __bis_SR_register(LPM0_bits | GIE); // Enter LPM0 w/ interrupt
}/* end main loop - конец большого цикла */ } /* end main */
#pragma vector=TIMER0_A0_VECTOR __interrupt void Timer0_A0 (void) { sysTickMS += SYSTICKMS_ADD; //увеличиваем счетчик мс
/* поскольку в основном цикле есть переход в режим энергосбережения, то для того, чтобы большой цикл выполнялся нужно временно выйти из этого режима */ __bic_SR_register_on_exit(LPM4_bits); }
Основные недостатки вашей программы а) отсутствует big loop, т.е. программа не зацикливается, а перезапускается после одного-единственного прохода б) в прерывании нужно делать минимум операций и только самые необходимые. Вызов функции обработки динамической индикации можно спокойно перенести в основной цикл. А в прерывании от таймера только увеличивать счетчик времени, который в моей версии считает миллисекунды. в) судя по именам переменных, замысел такой был, но по факту не реализована буферизация вывода на индикатор. Я бы на вашем месте написал отдельную функцию для вывода в буфер индикатора (отметил это в комментариях). г) старайтесь избегать "магических" чисел в исходниках. Пользуйтесь именованными константами, определенными с помощью макросов (define) и enum. Будет проще и вам самому и другим людям, которые будут разбираться с вашей программой. д) рекомендуется поддерживать общепринятый стиль написания программ на Си. Только одними ЗАГЛАВНЫМИ символами принято обозначать макросы. Не стоит такие имена давать переменным. Имена переменным нужно давать осмысленно. Я сначала вообще хотел отдельную структуру для переменных индикатора создать, но потом подумал и ограничился лишь префиксом seg7_.
|
|
|
|
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|