Так.Не думал что вернусь в тему,но увы проблемы все такие есть.
После длительной паузы опять сел дорабаывать прогу.
И так что я имею.
Таймер - 40кГц
АЦП по прерыванию счиывает данные.
В обработчике эти данные я забираю. И с меньше частотой вывожу на Индикатор.
Программа работает.
CODE
#include <msp430g2553.h>
unsigned int digit; /// переменная для значения 1 разряда
unsigned int pos = 1; /// номер разряда
unsigned int value; // переменная для значения выводимого числа
unsigned int buffer; // переменная для значения ADC
unsigned int buffer_2; // переменная для значения ADC
unsigned int i; // счетчик
unsigned int x1[3]=0;
unsigned int y1[3]=0,y2[3]=0,y3[3]=0,y4[3]=0,y5[3]=0;
void init_led(void) // инициализация индикатора (описание смотрите в даташите)
{
P1REN &= ~(BIT1+BIT2+BIT3+BIT4+BIT5+BIT6);
P2REN &= ~(BIT0+BIT1+BIT2+BIT3+BIT4+BIT5);
P2REN &= ~(BIT3+BIT4+BIT5);
P1REN &= ~BIT6;
P2DIR |= (BIT0+BIT1+BIT2);
P1DIR |= (BIT1+BIT2+BIT3+BIT4+BIT5);
P2OUT |= (BIT0+BIT1+BIT2);
P1OUT |= (BIT1+BIT2+BIT3+BIT4+BIT5);
P2DIR |=(BIT3+BIT4+BIT5);
P1DIR |=BIT6;
P2OUT |=(BIT3+BIT4+BIT5);
P1OUT |=BIT6;
}
void clear_led(void) { // обнуление. выключаем все регистры и цифры.
P2OUT |= (BIT0+BIT1+BIT2);
P1OUT |= (BIT1+BIT2+BIT3+BIT4+BIT5);
P2OUT |= (BIT3+BIT4+BIT5);
P1OUT |= BIT6;
}
void show_number(number) { // сопоставление ножек установки числа
switch (number) {
case 0 :
P1OUT &=~(BIT1+BIT2+BIT3+BIT5);
P2OUT &=~(BIT0+BIT2);
break;
case 1:
P1OUT &=~(BIT3+BIT5);
break;
case 2:
P1OUT &=~(BIT1+BIT3+BIT4);
P2OUT &=~(BIT0+BIT2);
break;
case 3:
P1OUT &=~(BIT1+BIT3+BIT4+BIT5);
P2OUT &=~(BIT0);
break;
case 4:
P1OUT &=~(BIT2+BIT3+BIT4+BIT5);
break;
case 5:
P1OUT &=~(BIT1+BIT2+BIT4+BIT5);
P2OUT &=~(BIT0);
break;
case 6:
P1OUT &=~(BIT1+BIT2+BIT4+BIT5);
P2OUT &=~(BIT0+BIT2);
break;
case 7:
P1OUT &=~(BIT1+BIT3+BIT5);
break;
case 8:
P1OUT &=~(BIT1+BIT2+BIT3+BIT4+BIT5);
P2OUT &=~(BIT0+BIT2);
break;
case 9:
P1OUT &=~(BIT1+BIT2+BIT3+BIT4+BIT5);
P2OUT &=~(BIT0);
break;
}
}
void show_registr(registr) { // сопоставление ножек управления регистра
switch (registr) {
case 4:
P1OUT &=~BIT6;
break;
case 3:
P2OUT &=~BIT5;
break;
case 2:
P2OUT &=~BIT4;
break;
case 1:
P2OUT &=~BIT3;
break;
}
}
void init_ADC(void) {
ADC10CTL1 |= CONSEQ_2; // Циклический,одноканальный
ADC10CTL1 |= INCH_0 //A0
+ SHS_2; // Модуль вывода 0 Таймера А
ADC10CTL0 |= SREF_0 // Опорные Vcc Vss
+ ADC10SHT_3 // 64 такта ADC10CLK
+ ADC10ON //Модуль ADC10 включён
+ ENC //Работа ADC10 разрешена
+ ADC10IE; //Прерывание разрешено
ADC10AE0 = BIT0; // Разрешаем вход АЦП на порту P1.0
}
void ConfigClocks(void)
{
BCSCTL1 = CALBC1_16MHZ; // Set range
DCOCTL = CALDCO_16MHZ; // Set DCO step + modulation
}
void ConfigTimerA(void)
{
TA0CCR0 = 400; // Обеспечиваем обращение к прерыванию 16MHZ/ 400 = 40000 Hz
TA0CCTL0 = OUTMOD_2; // Режим работы модуля вывода. "Переключение"
TA0CTL = TASSEL_2 //SMCLK
+ MC_1 //Прямой счёт (таймер считает от 0000h до TACCR0)
+ ID_0; // и Делитель 1
}
int main(void) {
WDTCTL = WDTPW | WDTHOLD; // Stop watchdog timer
ConfigClocks();
ConfigTimerA();
init_led();
init_ADC();
_BIS_SR(GIE); // Разрешаем прерывание
while (1)
{
//ТУТ ПОКА ПУСТО
}
}
#pragma vector=ADC10_VECTOR
__interrupt void ADC10_ISR(void)
{
buffer=ADC10MEM; // с частотой 40000 гц берем значение с ацп
//C с частотой 200Гц выводим на экран каждую цифру
i++;
if (i==40000/200) {
i=0;
if (value == 0) {
value=buffer; // присваиваем результат к АЦП
pos = 1;
}
digit = value % 10; /// взятие остатка от деления
clear_led();
show_number(digit); // выбор числа
show_registr(pos); // выбор сегмента
value /= 10; // деление без остатка. отбпрасываем число которое показали
pos++;
}
}
Но вот куда добавить математику фильтрации?
Запихнул ее в While(1) в основную прогу с флагом.Если все правильно понял - как только данные считались - выполняется то что в цикле флага.
CODE
#include <msp430g2553.h>
unsigned int digit; /// переменная для значения 1 разряда
unsigned int pos = 1; /// номер разряда
unsigned int value; // переменная для значения выводимого числа
unsigned int buffer; // переменная для значения ADC
unsigned int buffer_2; // переменная для значения ADC
unsigned int i; // счетчик
unsigned int x1[3]=0;
unsigned int y1[3]=0,y2[3]=0,y3[3]=0,y4[3]=0,y5[3]=0;
void init_led(void) // инициализация индикатора (описание смотрите в даташите)
{
P1REN &= ~(BIT1+BIT2+BIT3+BIT4+BIT5+BIT6);
P2REN &= ~(BIT0+BIT1+BIT2+BIT3+BIT4+BIT5);
P2REN &= ~(BIT3+BIT4+BIT5);
P1REN &= ~BIT6;
P2DIR |= (BIT0+BIT1+BIT2);
P1DIR |= (BIT1+BIT2+BIT3+BIT4+BIT5);
P2OUT |= (BIT0+BIT1+BIT2);
P1OUT |= (BIT1+BIT2+BIT3+BIT4+BIT5);
P2DIR |=(BIT3+BIT4+BIT5);
P1DIR |=BIT6;
P2OUT |=(BIT3+BIT4+BIT5);
P1OUT |=BIT6;
}
void clear_led(void) { // обнуление. выключаем все регистры и цифры.
P2OUT |= (BIT0+BIT1+BIT2);
P1OUT |= (BIT1+BIT2+BIT3+BIT4+BIT5);
P2OUT |= (BIT3+BIT4+BIT5);
P1OUT |= BIT6;
}
void show_number(number) { // сопоставление ножек установки числа
switch (number) {
case 0 :
P1OUT &=~(BIT1+BIT2+BIT3+BIT5);
P2OUT &=~(BIT0+BIT2);
break;
case 1:
P1OUT &=~(BIT3+BIT5);
break;
case 2:
P1OUT &=~(BIT1+BIT3+BIT4);
P2OUT &=~(BIT0+BIT2);
break;
case 3:
P1OUT &=~(BIT1+BIT3+BIT4+BIT5);
P2OUT &=~(BIT0);
break;
case 4:
P1OUT &=~(BIT2+BIT3+BIT4+BIT5);
break;
case 5:
P1OUT &=~(BIT1+BIT2+BIT4+BIT5);
P2OUT &=~(BIT0);
break;
case 6:
P1OUT &=~(BIT1+BIT2+BIT4+BIT5);
P2OUT &=~(BIT0+BIT2);
break;
case 7:
P1OUT &=~(BIT1+BIT3+BIT5);
break;
case 8:
P1OUT &=~(BIT1+BIT2+BIT3+BIT4+BIT5);
P2OUT &=~(BIT0+BIT2);
break;
case 9:
P1OUT &=~(BIT1+BIT2+BIT3+BIT4+BIT5);
P2OUT &=~(BIT0);
break;
}
}
void show_registr(registr) { // сопоставление ножек управления регистра
switch (registr) {
case 4:
P1OUT &=~BIT6;
break;
case 3:
P2OUT &=~BIT5;
break;
case 2:
P2OUT &=~BIT4;
break;
case 1:
P2OUT &=~BIT3;
break;
}
}
void init_ADC(void) {
ADC10CTL1 |= CONSEQ_2; // Циклический,одноканальный
ADC10CTL1 |= INCH_0 //A0
+ SHS_2; // Модуль вывода 0 Таймера А
ADC10CTL0 |= SREF_0 // Опорные Vcc Vss
+ ADC10SHT_3 // 64 такта ADC10CLK
+ ADC10ON //Модуль ADC10 включён
+ ENC //Работа ADC10 разрешена
+ ADC10IE; //Прерывание разрешено
ADC10AE0 = BIT0; // Разрешаем вход АЦП на порту P1.0
}
void ConfigClocks(void)
{
BCSCTL1 = CALBC1_16MHZ; // Set range
DCOCTL = CALDCO_16MHZ; // Set DCO step + modulation
}
void ConfigTimerA(void)
{
TA0CCR0 = 400; // Обеспечиваем обращение к прерыванию 16MHZ/ 400 = 40000 Hz
TA0CCTL0 = OUTMOD_2; // Режим работы модуля вывода. "Переключение"
TA0CTL = TASSEL_2 //SMCLK
+ MC_1 //Прямой счёт (таймер считает от 0000h до TACCR0)
+ ID_0; // и Делитель 1
}
int main(void) {
WDTCTL = WDTPW | WDTHOLD; // Stop watchdog timer
ConfigClocks();
ConfigTimerA();
init_led();
init_ADC();
_BIS_SR(GIE); // Разрешаем прерывание
while (1)
{
while ((ADC10CTL0 & ADC10IFG))
{
x1[0]=buffer; // входные данные с АЦП
y1[0]=(9*x1[0]+13*x1[1]+9*x1[2]-20*y1[1]-15*y1[2])/16;
y2[0]=(9*y1[0]+8*y1[1]+9*y1[2]-15*y2[1]-15*y2[2])/16;
y3[0]=(6*y2[0]+9*y2[1]+6*y2[2]-18*y3[1]-14*y3[2])/16;
y4[0]=(6*y3[0]+4*y3[1]+6*y3[2]-15*y4[1]-14*y4[2])/16;
y5[0]=(2*y4[0]+0*y4[1]-2*y4[2]-16*y5[1]-13*y5[2])/16;
buffer_2=y5[0];//
x1[2]=x1[1];
x1[1]=x1[0];
y1[2]=y1[1];
y1[1]=y1[0];
y2[2]=y2[1];
y2[1]=y2[0];
y3[2]=y3[1];
y3[1]=y3[0];
y4[2]=y4[1];
y4[1]=y4[0];
y5[2]=y5[1];
y5[1]=y5[0];
}
}
}
#pragma vector=ADC10_VECTOR
__interrupt void ADC10_ISR(void)
{
buffer=ADC10MEM; // с частотой 40000 гц берем значение с ацп
//C с частотой 200Гц выводим на экран каждую цифру
i++;
if (i==40000/200) {
i=0;
if (value == 0) {
value=buffer_2; // присваиваем результат к АЦП
pos = 1;
}
digit = value % 10; /// взятие остатка от деления
clear_led();
show_number(digit); // выбор числа
show_registr(pos); // выбор сегмента
value /= 10; // деление без остатка. отбпрасываем число которое показали
pos++;
}
}
Но вот загвостка.
Я подаю на АЦП постоянный сигнал. АЧХ постоянного сигнала очевидна.Если я фильтрую частоту 13700 - то мне на выходе должен падать 0.
А вместо этого я получаю число 1456 +- небольшие помехи из за того что АЦП сам снимает с небольшими флуктуациями...
Фильтр в МАТЛАБЕ проектировал и там все тип топ.
Может с типами проблема. Или с тем что беззнаковые переменные использую....
А то мне кажется у меня в минус значения уходят....или нет....
Если меня с UNSIGNET INT на INT - то вроде похоже на правду , но проходит цикла 5-6 и больше в цикл математики не заходит...
В дебагере вижу что ацп считывает, но в математику не заходит.
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
Короче решил математику в обработчик запихнуть.вроде успевает считать.все тип топ.
ВОПРОС - Когда выполняется код из обоаботчика - таймер пересает считать ? нет ли из за этого сбивки по частоте ?
CODE
#include <msp430g2553.h>
int digit; /// переменная для значения 1 разряда
unsigned int pos = 1; /// номер разряда
int value; // переменная для значения выводимого числа
int buffer; // переменная для значения ADC
int buffer_2; // переменная для значения ADC
unsigned int i; // счетчик
int x1[3]=0;
int y1[3]=0,y2[3]=0,y3[3]=0,y4[3]=0,y5[3]=0;
void init_led(void) // инициализация индикатора (описание смотрите в даташите)
{
P1REN &= ~(BIT1+BIT2+BIT3+BIT4+BIT5+BIT6);
P2REN &= ~(BIT0+BIT1+BIT2+BIT3+BIT4+BIT5);
P2REN &= ~(BIT3+BIT4+BIT5);
P1REN &= ~BIT6;
P2DIR |= (BIT0+BIT1+BIT2);
P1DIR |= (BIT1+BIT2+BIT3+BIT4+BIT5);
P2OUT |= (BIT0+BIT1+BIT2);
P1OUT |= (BIT1+BIT2+BIT3+BIT4+BIT5);
P2DIR |=(BIT3+BIT4+BIT5);
P1DIR |=BIT6;
P2OUT |=(BIT3+BIT4+BIT5);
P1OUT |=BIT6;
}
void clear_led(void) { // обнуление. выключаем все регистры и цифры.
P2OUT |= (BIT0+BIT1+BIT2);
P1OUT |= (BIT1+BIT2+BIT3+BIT4+BIT5);
P2OUT |= (BIT3+BIT4+BIT5);
P1OUT |= BIT6;
}
void show_number(number) { // сопоставление ножек установки числа
switch (number) {
case 0 :
P1OUT &=~(BIT1+BIT2+BIT3+BIT5);
P2OUT &=~(BIT0+BIT2);
break;
case 1:
P1OUT &=~(BIT3+BIT5);
break;
case 2:
P1OUT &=~(BIT1+BIT3+BIT4);
P2OUT &=~(BIT0+BIT2);
break;
case 3:
P1OUT &=~(BIT1+BIT3+BIT4+BIT5);
P2OUT &=~(BIT0);
break;
case 4:
P1OUT &=~(BIT2+BIT3+BIT4+BIT5);
break;
case 5:
P1OUT &=~(BIT1+BIT2+BIT4+BIT5);
P2OUT &=~(BIT0);
break;
case 6:
P1OUT &=~(BIT1+BIT2+BIT4+BIT5);
P2OUT &=~(BIT0+BIT2);
break;
case 7:
P1OUT &=~(BIT1+BIT3+BIT5);
break;
case 8:
P1OUT &=~(BIT1+BIT2+BIT3+BIT4+BIT5);
P2OUT &=~(BIT0+BIT2);
break;
case 9:
P1OUT &=~(BIT1+BIT2+BIT3+BIT4+BIT5);
P2OUT &=~(BIT0);
break;
}
}
void show_registr(registr) { // сопоставление ножек управления регистра
switch (registr) {
case 4:
P1OUT &=~BIT6;
break;
case 3:
P2OUT &=~BIT5;
break;
case 2:
P2OUT &=~BIT4;
break;
case 1:
P2OUT &=~BIT3;
break;
}
}
void init_ADC(void) {
ADC10CTL1 |= CONSEQ_2; // Циклический,одноканальный
ADC10CTL1 |= INCH_0 //A0
+ SHS_2; // Модуль вывода 0 Таймера А
ADC10CTL0 |= SREF_0 // Опорные Vcc Vss
+ ADC10SHT_0 // 64 такта ADC10CLK
+ ADC10ON //Модуль ADC10 включён
+ ENC //Работа ADC10 разрешена
+ ADC10IE; //Прерывание разрешено
ADC10AE0 = BIT0; // Разрешаем вход АЦП на порту P1.0
}
void ConfigClocks(void)
{
BCSCTL1 = CALBC1_16MHZ; // Set range
DCOCTL = CALDCO_16MHZ; // Set DCO step + modulation
}
void ConfigTimerA(void)
{
TA0CCR0 = 400; // Обеспечиваем обращение к прерыванию 16MHZ/ 400 = 40000 Hz
TA0CCTL0 = OUTMOD_2; // Режим работы модуля вывода. "Переключение"
TA0CTL = TASSEL_2 //SMCLK
+ MC_1 //Прямой счёт (таймер считает от 0000h до TACCR0)
+ ID_0; // и Делитель 1
}
int main(void) {
WDTCTL = WDTPW | WDTHOLD; // Stop watchdog timer
ConfigClocks();
ConfigTimerA();
init_led();
init_ADC();
_BIS_SR(GIE); // Разрешаем прерывание
while (1)
{
//while (!(ADC10CTL0 & ADC10IFG));
}
}
#pragma vector=ADC10_VECTOR
__interrupt void ADC10_ISR(void)
{
buffer=ADC10MEM; // с частотой 40000 гц берем значение с ацп
x1[0]=buffer; // входные данные с АЦП
y1[0]=(5*x1[0]+6*x1[1]+5*x1[2]-10*y1[1]-8*y1[2])/8;
y2[0]=(5*y1[0]+4*y1[1]+5*y1[2]-7*y2[1]-8*y2[2])/8;
y3[0]=(3*y2[0]+5*y2[1]+3*y2[2]-9*y3[1]-7*y3[2])/8;
y4[0]=(3*y3[0]+2*y3[1]+3*y3[2]-7*y4[1]-7*y4[2])/8;
y5[0]=(1*y4[0]+0*y4[1]-1*y4[2]-8*y5[1]-6*y5[2])/8;
buffer_2=y5[0];//
x1[2]=x1[1];
x1[1]=x1[0];
y1[2]=y1[1];
y1[1]=y1[0];
y2[2]=y2[1];
y2[1]=y2[0];
y3[2]=y3[1];
y3[1]=y3[0];
y4[2]=y4[1];
y4[1]=y4[0];
y5[2]=y5[1];
y5[1]=y5[0];
//C с частотой 200Гц выводим на экран каждую цифру
i++;
if (i==40000/200) {
i=0;
if (value == 0) {
value=abs(buffer_2); // присваиваем результат к АЦП
pos = 1;
}
digit = value % 10; /// взятие остатка от деления
clear_led();
show_number(digit); // выбор числа
show_registr(pos); // выбор сегмента
value /= 10; // деление без остатка. отбпрасываем число которое показали
pos++;
}
}