Jump to content

    

niketa

Участник
  • Content Count

    30
  • Joined

  • Last visited

Community Reputation

0 Обычный

About niketa

  • Rank
    Участник
  1. /////////////////////////////////////////////////////////// еще как сюда уарт прикрутить ? чтоб на комп еще слать значения В уже существующее прерывание от АЦП засунуть ? или новое прерывание написать для уарта ? Есть хоть один урок или пример нормальный ?
  2. Так.Не думал что вернусь в тему,но увы проблемы все такие есть. После длительной паузы опять сел дорабаывать прогу. И так что я имею. Таймер - 40кГц АЦП по прерыванию счиывает данные. В обработчике эти данные я забираю. И с меньше частотой вывожу на Индикатор. Программа работает. #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) в основную прогу с флагом.Если все правильно понял - как только данные считались - выполняется то что в цикле флага. #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 и больше в цикл математики не заходит... В дебагере вижу что ацп считывает, но в математику не заходит. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// Короче решил математику в обработчик запихнуть.вроде успевает считать.все тип топ. ВОПРОС - Когда выполняется код из обоаботчика - таймер пересает считать ? нет ли из за этого сбивки по частоте ? #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++; } }
  3. АЦП считывает с частотой 40кГц по таймеру Так же замутил фильтр полосо пропускающий на частоте 13.5кГц +-500Гц Запрогал алгоритм (предварительно смоделировал его в Матлабе) Но как оказалось слабый очень msp430g2553 У меня из обработчика прерывания не выходит. Только в нем крутится и поэтому данные на Индикатор не выводятся. Вроде 16МГц.Я думал успеет посчитать. Всего то 40кГц таймер.... #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 x1[3],x2[3],x3[3],x4[3],x5[3]; unsigned int y1[3],y2[3],y3[3],y4[3],y5[3]; unsigned int i; // счетчик 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_0; // single channel, single conversion ADC10CTL1 |= INCH_0 + SHS_0 // use ADC10SC bit to trigger sampling + ADC10DIV_3 // clock divider = 4 + ADC10SSEL_3; // clock source = SMCLK ADC10CTL0 |= SREF_0 // reference voltages are Vss and Vcc + ADC10SHT_3 // 64 ADC10 clocks for sample and hold time (slowest) + ADC10ON + ENC; ADC10AE0 = BIT0; // Разрешаем вход АЦП на порту P1.0 } void ConfigClocks(void) { BCSCTL1 = CALBC1_16MHZ; // Set range DCOCTL = CALDCO_16MHZ; // Set DCO step + modulation } void ConfigTimerA(void) { TACCR0 = 50; // Обеспечиваем обращение к прерыванию 16MHZ/ 8 / 50 = 40kHz TACCTL0 = CCIE; // Разрешаем прерывание таймера по достижению значения CCR0. TACTL = TASSEL_2 + ID_3 + MC_1; } int main(void) { WDTCTL = WDTPW | WDTHOLD; // Stop watchdog timer ConfigClocks(); ConfigTimerA(); init_led(); init_ADC(); _BIS_SR(GIE); while (1) { if (value == 0) { value=buffer_2; // присваиваем результат к АЦП pos = 1; } digit = value % 10; /// взятие остатка от деления clear_led(); show_number(digit); // выбор числа show_registr(pos); // выбор сегмента value /= 10; // деление без остатка. отбпрасываем число которое показали pos++; } } #pragma vector=TIMER0_A0_VECTOR __interrupt void Timer_CC0 (void) { /////////////////////////////////////C Частотой 40кГц работает ADC/////////////////////// ADC10CTL0 |= ADC10SC; // включаем считвание с ацп while (ADC10CTL1 & ADC10BUSY); // ждем пока все считает ///////////////////////////////////////////////////////////////////////////////////////// x1[2]=x1[1]; x1[1]=x1[0]; x1[0]=ADC10MEM; y1[0]=(5*x1[0]+6*x1[1]+5*x1[2]-10*y1[1]-8*y1[2])/8; x2[0]=y1[0]; x2[1]=y1[1]; x2[2]=y1[2]; y1[2]=y1[1]; y1[1]=y1[0]; y2[0]=(5*x2[0]+4*x2[1]+5*x2[2]-7*y2[1]-8*y2[2])/8; x3[0]=y2[0]; x3[1]=y2[1]; x3[2]=y2[2]; y2[2]=y2[1]; y2[1]=y2[0]; y3[0]=(3*x3[0]+5*x3[1]+3*x3[2]-9*y3[1]-7*y3[2])/8; x4[0]=y3[0]; x4[1]=y3[1]; x4[2]=y3[2]; y3[2]=y3[1]; y3[1]=y3[0]; y4[0]=(3*x4[0]+2*x4[1]+3*x4[2]-7*y4[1]-7*y4[2])/8; x5[0]=y4[0]; x5[1]=y4[1]; x5[2]=y4[2]; y4[2]=y4[1]; y4[1]=y4[0]; y5[0]=(1*x5[0]+0*x5[1]-1*x5[2]-8*y5[1]-6*y5[2])/8; y5[2]=y5[1]; y5[1]=y5[0]; buffer=y5[0]; if (i==40000/10) { i=0; buffer_2=buffer; } i++; }
  4. 1. Я знаю что что неправильно АЦП включать в прерывании. Но это сделано для того чтоб я в нем мог математические операции по фильтрации сделать Вот тут сразу вопрос. Как посчитать правильно сколько тактов работы проца у меня между прерываниями и сколько тактов работы проца занимает один проход мигания 2. ясно 3. Частота маловата. в комплекте есть такой генератор. 4. Огромное спасибо.
  5. Вот я написал Код. С частотой 40кГц считывается АЦП. На Индикатор выводится в основной программе под циклом While. Вывод на индикатор в данном случае не так важно. #include <msp430g2553.h> unsigned int digit; /// переменная для значения 1 разряда unsigned int pos = 1; /// номер разряда unsigned int value; // переменная для значения выводимого числа unsigned int buffer; // переменная для значения ADC unsigned int i; // счетчик 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_0; // single channel, single conversion ADC10CTL1 |= INCH_0 + SHS_0 // use ADC10SC bit to trigger sampling + ADC10DIV_3 // clock divider = 4 + ADC10SSEL_3; // clock source = SMCLK ADC10CTL0 |= SREF_0 // reference voltages are Vss and Vcc + ADC10SHT_3 // 64 ADC10 clocks for sample and hold time (slowest) + ADC10ON + ENC; ADC10AE0 = BIT0; // Разрешаем вход АЦП на порту P1.0 } void ConfigClocks(void) { BCSCTL1 = CALBC1_16MHZ; // Set range DCOCTL = CALDCO_16MHZ; // Set DCO step + modulation } void ConfigTimerA(void) { TACCR0 = 50; // Обеспечиваем обращение к прерыванию 16MHZ/ 8 / 50 = 40kHz TACCTL0 = CCIE; // Разрешаем прерывание таймера по достижению значения CCR0. TACTL = TASSEL_2 + ID_3 + MC_1; } int main(void) { WDTCTL = WDTPW | WDTHOLD; // Stop watchdog timer ConfigClocks(); ConfigTimerA(); init_led(); init_ADC(); _BIS_SR(GIE); while (1) { if (value == 0) { value=buffer; // присваиваем результат к АЦП pos = 1; } digit = value % 10; /// взятие остатка от деления clear_led(); show_number(digit); // выбор числа show_registr(pos); // выбор сегмента value /= 10; // деление без остатка. отбпрасываем число которое показали pos++; } } #pragma vector=TIMER0_A0_VECTOR __interrupt void Timer_CC0 (void) { /////////////////////////////////////C Частотой 40кГц работает ADC/////////////////////// ADC10CTL0 |= ADC10SC; // включаем считвание с ацп while (ADC10CTL1 & ADC10BUSY); // ждем пока все считает buffer = ADC10MEM; ///////////////////////////////////////////////////////////////////////////////////////// } Вопросы: 1.Что делаю неправильно ? 2.В дальнейшем я планирую сделать фильтрацию частоты 15кГц. Т.е. счиитывается с частотой 40кГц а я ППФ спроектирую которsй будет вырезать где то 15кГц +-300Гц. И собственно вопрос. Сколько у меня запас по отсчетам есть микропроконтроллера до следующего считывания АЦП и так чтоб мигание вело себя корректно. 3. Не совсем понял что это за резонатор. Исходя из мануала я вычитал что это какой то генератор. Но в чем он лучше ? 4.Как настроить второе прерывание с другой частотой ? По CC1 сравнивал чтоб в другом прерывании код выполнял. В описании g2553h есть такой пункт. Но что то он не работает.А в мануале не написано как настроить сравнение с CC1. Сейчас while(1) выводит информацию на индикатор(с прерыванием на АЦП). НО! Я хочу и не спрашивайте почему (для практики) сделать так чтоб : -buffer - Значение АЦП меняется с частотой 40кГЦ -value - то значение что выводится на индкатор (=buffer_2) -buffer_2 - с частотой 20Гц(примерно) = buffer пока реализовано это в том же прерывании if (i==40000/10) { i=0; buffer_2=buffer; } i++; Но хочу чтоб было в отдельном прерыании, просто для практики
  6. Читаю Student Guide and Lab Manual и Family User's Guide и стали мне непонятны некоторые строки из кода лабораторной. В лабораторной 4 нашел пример кода. Детально с ним разобрался,но некоторые вещи мне непонятны. #include <msp430g2553.h> volatile unsigned int i; void ConfigWDT(void); void ConfigClocks(void); void ConfigLEDs(void); void ConfigTimerA2(void); void main(void) { ConfigWDT(); ConfigClocks(); ConfigLEDs(); ConfigTimerA2(); _BIS_SR(GIE); // РАЗРЕШАЕМ ПРЕРЫВАНИЕ - ЭТО ПОНЯТНО while(1) { P1OUT |= BIT0; for (i = 100; i > 0; i--); P1OUT &= ~BIT0; for (i = 5000; i > 0; i--); } } void ConfigWDT(void) { WDTCTL = WDTPW + WDTHOLD; // Stop watchdog timer } void ConfigClocks(void) // НЕПОНЯТНАЯ ЧАСТЬ,НО ОНА У ВСЕХ ПРИСУТСТВУЕТ,Я РЕШИЛ ОСТАВИТЬ { BCSCTL1 = CALBC1_1MHZ; // Set range DCOCTL = CALDCO_1MHZ; // Set DCO step + modulation } void ConfigLEDs(void) { P1DIR = BIT6 + BIT0; // P1.6 and P1.0 outputs P1OUT = 0; // LEDs off } void ConfigTimerA2(void) { TACCR0 = 62500 - 1; // Период в 62,500 цикла, от 0 до 62,499. /// ПОЧЕМУ 62500 ОТСТЧЕТОВ ВСЕГО ???????? TACCTL0 = CCIE; // Разрешаем прерывание таймера по достижению значения CCR0. // ЭТО ПОНЯТНО TACTL = TASSEL_2 // ПОНЯЛ ЧТО ЭТО ВЫБОР ИСТОЧНИКА ТАКТОВОГО СИГНАЛА, НО В ЧЕМ МЕЖДУ НИМИ РАЗНИЦА ? ГДЕ ПРОЧЕСТЬ ? + ID_3 // ЭТО ПОНЯТНО. НО КАКАЯ ИЗНАЧАЛЬНАЯ ЧАСТОТА КОТОРУЮ МЫ ДЕЛИМ ? + MC_1; // ПОНЯТНО } #pragma vector=TIMER0_A0_VECTOR // НИ В ОДНОЙ ИЗ ВЫШЕ ОПИСАННЫХ КНИЖЕК НЕ НАПИСАНО ПОЧЕМУ ТАКОЙ СИНТАКСИС __interrupt void Timer_A (void) // ПОЧЕМУ ТАКОЙ СИНТАКСИС ? { P1OUT ^=BIT6; } 1. Если выше описано что в таймере 62500 отсчетов. А так же включен делитель частоты /8 - то изначальная частота была 8 *62500 = 500кГц ??? Т.е. SMCLK что в коде включен имеет такую частоту ? 2. Как мне реализовать 2 таймера ? Мне нужно чтоб один обращался к прерыванию с частотой 48кГц , а второй 200 Гц. Идея в том что 48кГц будет забираться данные с АЦП , потом еще и фильтроваться будет. А 200гц - вывод на индикатор
  7. Ошибку в коде нашел. Предыдущий пост исправил. Я там забыл скобки две поставить. Паузу уберу нафиг,она ненужна. Спасибо.Исправлю.
  8. Полный код программы на вывод числа. #include <msp430.h> //unsigned int digit; /// переменная для значения 1 разряда //unsigned int value; // переменная для значения выводимого числа //unsigned char pos; /// номер разряда 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; //Маленькая пауза после очистки volatile unsigned int i; i = 10; do i--; while(i != 0); } void show_number(number) { // сопоставление ножек установки числа if (number == 0) { P1OUT &=~(BIT1+BIT2+BIT3+BIT5); P2OUT &=~(BIT0+BIT2); } if (number == 1) { P1OUT &=~BIT3+BIT5; } if (number == 2) { P1OUT &=~(BIT1+BIT3+BIT4); P2OUT &=~(BIT0+BIT2); } if (number == 3) { P1OUT &=~(BIT1+BIT3+BIT4+BIT5); P2OUT &=~(BIT0); } if (number == 4) { P1OUT &=~(BIT2+BIT3+BIT4+BIT5); } if (number == 5) { P1OUT &=~(BIT1+BIT2+BIT4+BIT5); P2OUT &=~(BIT0); } if (number == 6) { P1OUT &=~(BIT1+BIT2+BIT4+BIT5); P2OUT &=~(BIT0+BIT2); } if (number == 7) { P1OUT &=~(BIT1+BIT3+BIT5); } if (number == 8) { P1OUT &=~(BIT1+BIT2+BIT3+BIT4+BIT5); P2OUT &=~(BIT0+BIT2); } if (number == 9) { P1OUT &=~(BIT1+BIT2+BIT3+BIT4+BIT5); P2OUT &=~(BIT0); } } void show_registr(registr) { // сопоставление ножек управления регистра if (registr == 4) { P1OUT &=~BIT6; } if (registr == 3) { P2OUT &=~BIT5; } if (registr == 2) { P2OUT &=~BIT4; } if (registr == 1) { P2OUT &=~BIT3; } } int main(void) { WDTCTL = WDTPW | WDTHOLD; // Stop watchdog timer init_led(); // инициализация ножек индикатора for(;;) { volatile unsigned int digit; /// переменная для значения 1 разряда volatile unsigned int value; // переменная для значения выводимого числа volatile unsigned int pos; /// номер разряда value = 634; // ЧИСЛО ДЛЯ ВЫВОДА pos = 1; while (value) { // цикл показа числа digit = value % 10; /// взятие остатка от деления //clear_led(); // выключаем все show_registr(pos); // выбор сегмента show_number(digit); // выбор числа value /= 10; // деление без остатка. отбпрасываем число которое показали pos++; clear_led(); // счетчик позиции if (pos > 4) break; } } } Видео демонстрация. Далее я дописав пару строк для того чтоб брать значение с АЦП. Между ногой ацп,vcc и землей поставил переменный резистор для того чтоб можно было заметить разницу , да и в целом работу. Код Вот тут видео как все работает Надо пооптимизировать программу,добавить таймеры. С таймерами пока не разобрался как пользоваться.
  9. Спасибо. Все просто оказалось. В случае проблем подключения - думаю эта тема поможет многим.
  10. Вопрос 1. uint32_t -что это ? uint16_t -что это ? Вопрос 2. Как после получения числа разбить его на разряды ? т.е. допустим число 1020 разбить на 1 , 0, 2, и 0 а дальше уже не так сложно вывести будет
  11. ////////////////////////////////////////////////////////////////////////////////////////////////////////// Дополнительный вопрос Как спроектировать функцию показала числа с АЦП на Сегментный индикатор. Т.е. Я получаю с АЦП в его регситре ADC10MEM число от 0x0000 (это 0) до 0х03FF (это 1023) Как мне из него вытащить цифры в 10теричной системе чтоб я показал его на индиктаор ?
  12. Все предельно понятно.Премного вам благодарен. Тут ачепятка - для тех кто будет по этой теме как я подключать индикатор я подправлю ///////////НАСТРОЙКА ВСЕХ ДИОДОВ НА "НЕ ГОРИТ"////// //Настройка пинов управления сегментов 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; ////////////////////////////////////////////////////// Как зажечь сегмент ? Пример P2OUT &=~ BIT0; //P2.0 управление сегментом P2OUT &=~ BIT3: //P2.3 управление разрядом Очень благодарю за то что разжевали как подключать этот индикатор.
  13. ////////////////////// Еще один косяк. Со всем остальным вроде разобрался. Либо у меня где то пробой или же я не пойму в чем косяк...Номиналы наверно другие надо. Весь КОД МИГАНИЯ #include <msp430.h> int main(void) { WDTCTL = WDTPW | WDTHOLD; // Stop watchdog timer ///////////НАСТРОЙКА ВСЕХ ДИОДОВ НА "НЕ ГОРИТ"////// //Пины управления сегментов ставим на вход P2DIR &=~(BIT0+BIT1+BIT2); P1DIR &=~(BIT1+BIT2+BIT3+BIT4+BIT5); //0 на пины управления сегментов P2OUT &=~(BIT0+BIT1+BIT2); P1OUT &=~(BIT1+BIT2+BIT3+BIT4+BIT5); //Пины выбора разряда на выход P2DIR |=(BIT3+BIT4+BIT5); P1DIR |=BIT6; //Подтягивающ резистор включаем P2REN |=(BIT3+BIT4+BIT5); P1REN |= BIT6; //Подтягиваем Vcc к пинам P2OUT |=(BIT3+BIT4+BIT5); P1OUT |=BIT6; ////////////////////////////////////////////////////// ////ОЧЕНЬ ПРОСТОЙ ЦИКЛ МИГАНИЯ//////////////////////// for(;;) { volatile unsigned int i; // volatile to prevent optimization //////////////////////////////////////// //Обнуляем все в "НЕ ГОРИТ" P2DIR &=~(BIT0+BIT1+BIT2); P1DIR &=~(BIT1+BIT2+BIT3+BIT4+BIT5); P2OUT |=(BIT3+BIT4+BIT5); P1OUT |=BIT6; //ВКЛ P2DIR |=BIT2; P2DIR |=BIT1; //Первый регистр P2OUT &=~BIT3; i = 100000; do i--; while(i != 0); ////////////////////////////////////////// //Обнуляем все в "НЕ ГОРИТ" P2DIR &=~(BIT0+BIT1+BIT2); P1DIR &=~(BIT1+BIT2+BIT3+BIT4+BIT5); P2OUT |=(BIT3+BIT4+BIT5); P1OUT |=BIT6; P2DIR |=BIT2; P2DIR |=BIT1; //Второй регистр P2OUT &=~BIT4; i = 100000; do i--; while(i != 0); ////////////////////////////////////////// //Обнуляем все в "НЕ ГОРИТ" P2DIR &=~(BIT0+BIT1+BIT2); P1DIR &=~(BIT1+BIT2+BIT3+BIT4+BIT5); P2OUT |=(BIT3+BIT4+BIT5); P1OUT |=BIT6; P2DIR |=BIT2; P2DIR |=BIT1; //Третий регистр P2OUT &=~BIT5; i = 100000; do i--; while(i != 0); ////////////////////////////////////////// //Обнуляем все в "НЕ ГОРИТ" P2DIR &=~(BIT0+BIT1+BIT2); P1DIR &=~(BIT1+BIT2+BIT3+BIT4+BIT5); P2OUT |=(BIT3+BIT4+BIT5); P1OUT |=BIT6; P2DIR |=BIT2; P2DIR |=BIT1; //Четвертый регистр P1OUT &=~BIT6; i = 100000; do i--; while(i != 0); ////////////////////////////////////////// } return 0; } ВИДЕО - Демонстрация проблемы ПЕрвое видео Второе видео Почему не гаснут разряды ?
  14. ///// Хотя вот переписал цикл так чтоб на одном регистре горела одна палка а на втором друга. Так же вписал пердварительное обнуление перед показаном нового разряда и все вроде норм. for(;;) { volatile unsigned int i; // volatile to prevent optimization P2OUT |= (BIT1+BIT2); P2OUT &=~BIT1; P2OUT |=BIT2; P2OUT |=BIT5; P2OUT &=~BIT3; i = 100; do i--; while(i != 0); P2OUT |= (BIT1+BIT2); P2OUT |=BIT1; P2OUT &=~BIT2; P2OUT &=~BIT5; P2OUT |=BIT3; i = 100; do i--; while(i != 0); } Теперь только с яркостью разобраться надо Исходя из моей логики программы - во время того как загорается диод P2.1 равносильна земле. Но я попробовал ножку с индикатора что идет к 2.1 проводкном коснуться земли(быстренько чтоб не спалить ничего) - все просто засверкало ярче яркого! Все таки подтягивается резистор к земле хреного.... как быть ? где знающие люди ? /////////////////////////////////////////////////////////////////////////////////////////////// Я во всем разорался,но мне непонятно почему. Схема у меня с общим анодом. И сегмент горит в том случе - если Непонятно P2DIR |=BIT1; - Ножка выбора сегмента на ВЫХОД - почему ? P2OUT &=~BIT1 - 0 на ножке понятно P2DIR |=BIT3; Ножка выбора разряда на ВЫХОД P2REN |= BIT3; ВКЛ подтягивающий резистор P2OUT &=~BIT5; Подвели к земпле базу тразистора
  15. Да вроде нет. Судя из расчета элементов должно хватать. Замечу вот что. Запрогал контроллер. И что я вижу Стало заметно что это не мигание. 1 разряд загорается. А когда загорается четвертый - первый просто тускнеет. Отключил от ЮСБ,включил обратно и все хорошо мигает. Через пол часа опять залили прогу и уже не мигает нормально. (так как через строчку выше) Я запутался и не могу разобраться что делать. А ни на форуме ни в инете нету обзоров похожих подключений индикатора. Очень надеюсь на грамотных людей в помощи.