Пойду я тоже спать.Ser60 писал(а):У меня есть таком МК на работе. Я завтра принесу домой, тогда продолжим.
Цифровая шкала с LED линейкой на MSP430
Re: Цифровая шкала с LED линейкой на MSP430
- Реклама
Re: Цифровая шкала с LED линейкой на MSP430
Проверил МК, ближайший нашел только MSP430G2452. Вот работающий код. Будет работать и на Вашем МК, поменяйте его название в первой строке. АЦП начинает преобразование по таймеру TimerA, канал 0. По завершении преобразования происходит прерывание и в нем поджигаются нужные светики. Я поменял 2 последних порога, по-моему в них были опечатки.
Советую зашунтировать вход АЦП (вывод 2) керамикой 0.1 мкф на землю.
Советую зашунтировать вход АЦП (вывод 2) керамикой 0.1 мкф на землю.
Спойлер
Код: Выделить всё
#include <msp430g2452.h>
//1 BIT2 1DIR
//2 BIT3 1DIR
//3 BIT4 1DIR
//4 BIT5 1DIR
//5 BIT0 2DIR
//6 BIT1 2DIR
//7 BIT2 2DIR
//8 BIT3 2DIR
//9 BIT4 2DIR
//10 BIT5 2DIR
//11 BIT6 1DIR
//12 BIT7 1DIR
//13 BIT7 2DIR
//14 BIT6 2DIR
void ADC_init(void); // function prototypes
void Ports_init(void);
void TimerA_init(void);
void main( void )
{
WDTCTL = WDTPW + WDTHOLD; // disable watchdog
Ports_init(); // init P1 and P2
ADC_init(); // init ADC
TimerA_init(); // init TimerA
for (;;)
__low_power_mode_0(); // enter sleep mode
}//main
void TimerA_init(void)
{
TACCR0 = 3125; // ADC trigger period ~22 мсек
TACCTL0 = OUTMOD_4; // toggle OUT0 to trigger ADC
TACTL = TASSEL_2 + ID_3 + MC_1 + TACLR; // SMCLK/8, up mode, start
}
void Ports_init(void)
{
P1DIR = 0xFF; // configure port for output
P1OUT = 0; // init port
P2DIR = 0xFF; // configure port for output
P2SEL = 0; // I/O on XTAL pins
P2OUT = 0; // init port
}
void ADC_init(void)
{
ADC10CTL0 = ADC10SHT_2 + ADC10ON + ADC10IE; // 16 clocks sample-and-hold
ADC10CTL1 = SHS_2 + CONSEQ_2; // trigger by TA0
ADC10AE0 = BIT0; // set ADC channel 0
ADC10CTL0 |= ENC; // enable conversion
}
#pragma vector = ADC10_VECTOR
__interrupt void ADC10_ISR (void) // ADC10 ISR
{
float volts = ADC10MEM * 0.0032258; // convert ADC into volts
char led1 = 0; // PORT1 leds stati
char led2 = 0; // PORT2 leds stati
if (volts >= 1.2) led1 |= BIT2; // new led states
if (volts >= 1.36) led1 |= BIT3;
if (volts >= 1.52) led1 |= BIT4;
if (volts >= 1.69) led1 |= BIT5;
if (volts >= 1.85) led2 |= BIT0;
if (volts >= 2.01) led2 |= BIT1;
if (volts >= 2.17) led2 |= BIT2;
if (volts >= 2.33) led2 |= BIT3;
if (volts >= 2.5) led2 |= BIT4;
if (volts >= 2.67) led2 |= BIT5;
if (volts >= 2.82) led1 |= BIT6;
if (volts >= 2.99) led1 |= BIT7;
if (volts >= 3.15) led2 |= BIT7;
if (volts >= 3.25) led2 |= BIT6;
P1OUT = led1; // copy led states to ports
P2OUT = led2;
}
Re: Цифровая шкала с LED линейкой на MSP430
Спойлер
Код: Выделить всё
#include <msp430g2452.h>
//1 BIT2 1DIR
//2 BIT3 1DIR
//3 BIT4 1DIR
//4 BIT5 1DIR
//5 BIT0 2DIR
//6 BIT1 2DIR
//7 BIT2 2DIR
//8 BIT3 2DIR
//9 BIT4 2DIR
//10 BIT5 2DIR
//11 BIT6 1DIR
//12 BIT7 1DIR
//13 BIT7 2DIR
//14 BIT6 2DIR
void ADC_init(void); // function prototypes
void Ports_init(void);
void TimerA_init(void);
int volts =0;
void main( void )
{
WDTCTL = WDTPW + WDTHOLD; // disable watchdog
Ports_init(); // init P1 and P2
ADC_init(); // init ADC
TimerA_init(); // init TimerA
for (;;)
__low_power_mode_0(); // enter sleep mode
}//main
void TimerA_init(void)
{
TACCR0 = 3125; // ADC trigger period ~22 мсек
TACCTL0 = OUTMOD_4; // toggle OUT0 to trigger ADC
TACTL = TASSEL_2 + ID_3 + MC_1 + TACLR; // SMCLK/8, up mode, start
}
void Ports_init(void)
{
P1DIR = 0xFF; // configure port for output
P1OUT = 0; // init port
P2DIR = 0xFF; // configure port for output
P2SEL = 0; // I/O on XTAL pins
P2OUT = 0; // init port
}
void ADC_init(void)
{
ADC10CTL0 = SREF_0 + ADC10SHT_2 + ADC10ON + ADC10IE; // 16 clocks sample-and-hold
ADC10CTL1 = SHS_2 + CONSEQ_2; // trigger by TA0
ADC10AE0 = BIT0; // set ADC channel 0
ADC10CTL0 |= ENC; // enable conversion
}
#pragma vector = ADC10_VECTOR
__interrupt void ADC10_ISR (void) // ADC10 ISR
{
int volts = ADC10MEM; // convert ADC into volts
char led1 = 0; // PORT1 leds stati
char led2 = 0; // PORT2 leds stati
if (volts >= 60) led1 |= BIT2; // new led states
if (volts >= 132) led1 |= BIT3;
if (volts >= 204) led1 |= BIT4;
if (volts >= 276) led1 |= BIT5;
if (volts >= 348) led2 |= BIT0;
if (volts >= 420) led2 |= BIT1;
if (volts >= 492) led2 |= BIT2;
if (volts >= 564) led2 |= BIT3;
if (volts >= 636) led2 |= BIT4;
if (volts >= 708) led2 |= BIT5;
if (volts >= 280) led1 |= BIT6;
if (volts >= 852) led1 |= BIT7;
if (volts >= 924) led2 |= BIT7;
if (volts >= 996) led2 |= BIT6;
P1OUT = led1; // copy led states to ports
P2OUT = led2;
}
Вроде работает. Сейчас спаяю линейку на 14 светиков, попробую поточней откалибровать. Пора разводить плату
Re: Цифровая шкала с LED линейкой на MSP430
Снял коротенькое видео о работе девайса, выкладываю поправленную прошивку.
Если кому-то нужно, выложу чертёж печатки и конечную схему.
http://www.youtube.com/watch?v=-ThdujIcHWI
Если кому-то нужно, выложу чертёж печатки и конечную схему.
http://www.youtube.com/watch?v=-ThdujIcHWI
Спойлер
Код: Выделить всё
#include <msp430g2452.h>
//1 BIT2 1DIR
//2 BIT3 1DIR
//3 BIT4 1DIR
//4 BIT5 1DIR
//5 BIT0 2DIR
//6 BIT1 2DIR
//7 BIT2 2DIR
//8 BIT3 2DIR
//9 BIT4 2DIR
//10 BIT5 2DIR
//11 BIT6 1DIR
//12 BIT7 1DIR
//13 BIT7 2DIR
//14 BIT6 2DIR
void ADC_init(void); // function prototypes
void Ports_init(void);
void TimerA_init(void);
int volts =0;
void main( void )
{
WDTCTL = WDTPW + WDTHOLD; // disable watchdog
Ports_init(); // init P1 and P2
ADC_init(); // init ADC
TimerA_init(); // init TimerA
for (;;)
__low_power_mode_0(); // enter sleep mode
}//main
void TimerA_init(void)
{
TACCR0 = 3125; // ADC trigger period ~22 мсек
TACCTL0 = OUTMOD_4; // toggle OUT0 to trigger ADC
TACTL = TASSEL_2 + ID_3 + MC_1 + TACLR; // SMCLK/8, up mode, start
}
void Ports_init(void)
{
P1DIR = 0xFF; // configure port for output
P1OUT = 0; // init port
P2DIR = 0xFF; // configure port for output
P2SEL = 0; // I/O on XTAL pins
P2OUT = 0; // init port
}
void ADC_init(void)
{
ADC10CTL0 = SREF_0 + ADC10SHT_2 + ADC10ON + ADC10IE; // 16 clocks sample-and-hold
ADC10CTL1 = SHS_2 + CONSEQ_2; // trigger by TA0
ADC10AE0 = BIT0; // set ADC channel 0
ADC10CTL0 |= ENC; // enable conversion
}
#pragma vector = ADC10_VECTOR
__interrupt void ADC10_ISR (void) // ADC10 ISR
{
int volts = ADC10MEM; // convert ADC into volts
char led1 = 0; // PORT1 leds stati
char led2 = 0; // PORT2 leds stati
if (volts >= 60) led1 |= BIT2; // new led states
if (volts >= 132) led1 |= BIT3;
if (volts >= 204) led1 |= BIT4;
if (volts >= 276) led1 |= BIT5;
if (volts >= 348) led2 |= BIT0;
if (volts >= 420) led2 |= BIT1;
if (volts >= 492) led2 |= BIT2;
if (volts >= 564) led2 |= BIT3;
if (volts >= 636) led2 |= BIT4;
if (volts >= 708) led2 |= BIT5;
if (volts >= 780) led1 |= BIT6;
if (volts >= 852) led1 |= BIT7;
if (volts >= 924) led2 |= BIT6;
if (volts >= 996) led2 |= BIT7;
P1OUT = led1; // copy led states to ports
P2OUT = led2;
}
Re: Цифровая шкала с LED линейкой на MSP430
Поздравляю! А как Вы хотели задействовать ногу 3 МК?
- Реклама
Re: Цифровая шкала с LED линейкой на MSP430
Собирался снять напряжение с батареи или второго настроечного потенца для SPLIT. Но думаю откажусь и повешу 15 светик. К тому же, нужно уменьшать потребление - при всех горящих светиках плата кушает 72 ма, что много. Буду переделывать на индикацию горящей точкой.Ser60 писал(а):Поздравляю! А как Вы хотели задействовать ногу 3 МК?
Re: Цифровая шкала с LED линейкой на MSP430
Если это для (переносной) рации, почему просто не индицировать частоту на ЖКИ?
Re: Цифровая шкала с LED линейкой на MSP430
Не интересно. Частотомеры на PICe и AVRe уже есть и делал.Ser60 писал(а):Если это для (переносной) рации, почему просто не индицировать частоту на ЖКИ?
Возникла проблема - мигания светодиодов при переходе через пороги АЦП (при медленом вращении потенца). Нужно организовывать гистерезис (только как)?
Re: Цифровая шкала с LED линейкой на MSP430
В простейшем случае можно усреднять показания АЦП в кольцевом буфере. Скажем, 4 последних показания. Это существенно уменьшит дребезг. Погуглите на алгоритмы скользящего среднего.
Re: Цифровая шкала с LED линейкой на MSP430
Что=то я не могу додуматься как организовать съём и хранение нескольких показаний с АЦП.Ser60 писал(а):В простейшем случае можно усреднять показания АЦП в кольцевом буфере. Скажем, 4 последних показания. Это существенно уменьшит дребезг. Погуглите на алгоритмы скользящего среднего.
Re: Цифровая шкала с LED линейкой на MSP430
Надо завести буфер для хранения показаний и переменную где будет храниться индех самого старого элемента (в начале 0). При получении нового значения от АЦП помещать его в буфер по этому индексу и увеличивать индех в
циклическом порядке. Считать сумму элементов в буфере и делить ее на длину буфера.
циклическом порядке. Считать сумму элементов в буфере и делить ее на длину буфера.
Re: Цифровая шкала с LED линейкой на MSP430
Ser60 писал(а):Надо завести буфер для хранения показаний и переменную где будет храниться индех самого старого элемента (в начале 0). При получении нового значения от АЦП помещать его в буфер по этому индексу и увеличивать индех в
циклическом порядке. Считать сумму элементов в буфере и делить ее на длину буфера.
Код: Выделить всё
int i= 0 ;
int summa = 0;
int A[10];
{
for (i = 0; i < 10; i++)
{
A[i] = ADC10MEM;
summa += A[i];
}
volts = summa / 10;
Вопросы:
1. Как организовать 10 измерений подряд АЦП?
2. Как организовать изменение i по результату измерения АЦП? Это нужно использовать таймер?
Прошу прошения за нубские вопросы, это мой первый опыт работы с МК MSP430.
До этого писал только для промышленных мотороловских контроллеров на асме и Фортране техпроцессы холодной штамповки, и то уже всё позабыл.
Последний раз редактировалось Unrealee Вт дек 04, 2012 00:08:14, всего редактировалось 1 раз.
Re: Цифровая шкала с LED линейкой на MSP430
Код после горизонтальной черты поставьте туда где раньше было получение кода АЦП. Никаких многократных исмерений делать не надо. Длину буфера лучше выбирать равной степени 2, в этом случае деление просто реализовать сдвигом.
Спойлер
Код: Выделить всё
int i= 0 ;
int summa = 0;
int A[8];
----------------------------------------
summa = summa - A[i] + ADC10MEM;
A[i] = ADC10MEM;
i++;
if (i == 9) i=0;
int adcAverage = summa >> 3;
Re: Цифровая шкала с LED линейкой на MSP430
Можно ещё парочку дурацких вопросов?
1. Получается, что
Непрерывно сканирует напряжение на 2 ножке? Период сканирования задаётся TimerA_init?
2. Нифига не понял как этот код работает
1. Получается, что
Код: Выделить всё
{
ADC10CTL0 = SREF_0 + ADC10SHT_2 + ADC10ON + ADC10IE; // 16 clocks sample-and-hold
ADC10CTL1 = SHS_2 + CONSEQ_2; // trigger by TA0
ADC10AE0 = BIT0; // set ADC channel 0
ADC10CTL0 |= ENC; // enable conversion
}2. Нифига не понял как этот код работает
Код: Выделить всё
summa = summa - A[i] + ADC10MEM;
A[i] = ADC10MEM;
i++;
if (i == 9) i=0;
int adcAverage = summa >> 3;
volts = adcAverage;
Re: Цифровая шкала с LED линейкой на MSP430
1. Да, именно так. Точнее, как только Таймер досчитает до своего верхнего значения (в программе 3125) он инвертирует напряжение на своем (внутреннем) выходе и каждый нарастающий фронт на нем заставляет АЦП начинать новое преобразование, заметьте, что без участия процессора, который все это время спит. Он проснется прерыванием по окончании работы АЦП. Таким образом, период измерений в 2 раза больше периода переполнения таймера.
2. В переменной summa хранится сумма последних 8-ми кодов АЦП. Для подсчета новой суммы после очередного измерения можно добавить это измерение к сумме и вычесть из нее самое старое измерение. Последнее находится под индексом i в массиве. После этого i увеличивается на 1 и указывает на самое старое значение для следующей итерации. Индекс i увеличивается по модулю 8 для реализации кольцевого буфера, т.е. по кругу 0,1,...,7,0,1,...,7. Кстати, я там опечатался и в инструкции
if (i == 9) i=0;
следует производить проверку i на 8. Или еще лучше для эффективности вместо нее написать
i = i & 7;
2. В переменной summa хранится сумма последних 8-ми кодов АЦП. Для подсчета новой суммы после очередного измерения можно добавить это измерение к сумме и вычесть из нее самое старое измерение. Последнее находится под индексом i в массиве. После этого i увеличивается на 1 и указывает на самое старое значение для следующей итерации. Индекс i увеличивается по модулю 8 для реализации кольцевого буфера, т.е. по кругу 0,1,...,7,0,1,...,7. Кстати, я там опечатался и в инструкции
if (i == 9) i=0;
следует производить проверку i на 8. Или еще лучше для эффективности вместо нее написать
i = i & 7;


