简体   繁体   English

我使用ATmega164的CodeVisionAVR中的吉他调谐器代码无法处理4个以上的样本

[英]My guitar tuner code in CodeVisionAVR using an ATmega164 can't handle more than 4 samples

I'm designing a guitar tuner through CodeVisionAVR and using an ATmega164 microchip for my university project. 我正在通过CodeVisionAVR设计吉他调音器,并为我的大学项目使用ATmega164芯片。 If i set the number of samples any higher than 4, the chip LEDs will just flash continuously and the code won't get past the pin reading phase of the process (tested with lighting up LEDs after each line of code to see where it stops). 如果我将样本数量设置为大于4,则芯片LED只会连续闪烁,并且代码不会超过该过程的引脚读取阶段(在每行代码之后测试LED发光以查看其停止位置) )。

I'm forced by the university to design the code through CVAVR, using a DFT. 大学逼迫我使用DFT通过CVAVR设计代码。 I have made (with the great help of an answer to a recent question) the code almost 18 times smaller than it was originally. 我已经(在最近一个问题的答案的大力帮助下)将代码比原来的小了近18倍。 I don't know how i can make it any easier to run so that it can tolerate more than 4 samples ( #define N 4 ) 我不知道如何使它运行起来更容易,使其可以承受4个以上的样本( #define N 4

#define M_PI 3.1415926f
#define N 4

unsigned char read_adc(void)
{
ADCSRA |= 0b01000000;  //start conversion;
while (ADCSRA&(0b01000000)); //wait conversion end
return ADCH;
}

float computeDft()
{      
    unsigned char x[N] = {0};
    float max = 0;   
    float maxi = 0;
    float magnitude = 0; 
    int k = 0;
    int n = 0;
    float re = 0;
    float im = 0;          
    for (k = 0; k < N; k++)
    {       
        x[k] = read_adc();            
    }
    for (n = 0; n < N; n++)
    {
        for (k = 0; k < N; k++)
        {       
            re += x[k] * cos(n * k * M_PI / N);
            im -= x[k] * sin(n * k * M_PI / N);
        }
        magnitude = sqrt(re * re +  im * im);
        if (magnitude > maxi) 
        {
            maxi = magnitude;
            max = k;   
        }
    }                                     
    return max;   
}


/*
 * main function of program
 */
void main (void)
{          
float F = 0;
Init_initController();  // this must be the first "init" action/call!
#asm("sei")             // enable interrupts
// Crystal Oscillator division factor: 1
#pragma optsize-
CLKPR=0x80;
CLKPR=0x00;
#ifdef OPTIMIZE_SIZE
#pragma optsize+
#endif

TWCR=0x00;
//adc init
ADMUX = 0b10100111; // set ADC0
ADCSRA = 0b10000111; //set ADEN, precale by 128
while(TRUE)
{
    wdogtrig();         // call often else processor will reset
    F = computeDft();    
    L2 = 1;
    if(F > 20 && F < 100)
    {
        L3 = 1;
    }
}  


}// end main loop 

A tuner in general should be able to use at least 800 samples because of the Nyquist–Shannon sampling theorem, and the high E guitar string being somewhere around 380 Hz (can't remember exactly). 由于Nyquist–Shannon采样定理,以及高E吉他弦大约在380 Hz左右(记不清),因此,调谐器通常应能够使用至少800个采样。

/* initialization file */

#include <mega164a.h>
#include "defs.h"


/*
 * most intialization values are generated using Code Wizard and depend on clock value
 */
void Init_initController(void)
{
// Crystal Oscillator division factor: 1
#pragma optsize-
CLKPR=0x80;
CLKPR=0x00;
#ifdef _OPTIMIZE_SIZE_
#pragma optsize+
#endif

// Input/Output Ports initialization
// Port A initialization
// Func7=In Func6=In Func5=In Func4=In Func3=In Func2=In Func1=In Func0=In 
// State7=T State6=T State5=T State4=T State3=T State2=T State1=T State0=T 
PORTA=0x00;
DDRA=0x00;

// Port B initialization
PORTB=0x00;
DDRB=0x00;

// Port C initialization
PORTC=0x00;
DDRC=0x00;

// Port D initialization
PORTD=0b00100000; // D.5 needs pull-up resistor
DDRD= 0b01010000; // D.6 is LED, D.4 is test output

// Timer/Counter 0 initialization
// Clock source: System Clock
// Clock value: Timer 0 Stopped
// Mode: Normal top=FFh
// OC0 output: Disconnected
TCCR0A=0x00;
TCCR0B=0x00;
TCNT0=0x00;
OCR0A=0x00;
OCR0B=0x00;

// Timer/Counter 1 initialization
// Clock source: System Clock
// Clock value: 19.531 kHz = CLOCK/256
// Mode: CTC top=OCR1A
// OC1A output: Discon.
// OC1B output: Discon.
// Noise Canceler: Off
// Input Capture on Falling Edge
// Timer 1 Overflow Interrupt: Off
// Input Capture Interrupt: Off
// Compare A Match Interrupt: On
// Compare B Match Interrupt: Off

TCCR1A=0x00;
TCCR1B=0x0D;
TCNT1H=0x00;
TCNT1L=0x00;
ICR1H=0x00;
ICR1L=0x00;

// 1 sec = 19531 counts = 4C41H counts, from 0 to 4C40 
// 4C40H = 4CH (MSB) and 40H (LSB)
OCR1AH=0x4C;
OCR1AL=0x40;

OCR1BH=0x00;
OCR1BL=0x00;

// Timer/Counter 2 initialization
// Clock source: System Clock
// Clock value: Timer2 Stopped
// Mode: Normal top=0xFF
// OC2A output: Disconnected
// OC2B output: Disconnected
ASSR=0x00;
TCCR2A=0x00;
TCCR2B=0x00;
TCNT2=0x00;
OCR2A=0x00;
OCR2B=0x00;

// External Interrupt(s) initialization
// INT0: Off
// INT1: Off
// INT2: Off
// Interrupt on any change on pins PCINT0-7: Off
// Interrupt on any change on pins PCINT8-15: Off
// Interrupt on any change on pins PCINT16-23: Off
// Interrupt on any change on pins PCINT24-31: Off
EICRA=0x00;
EIMSK=0x00;
PCICR=0x00;

// Timer/Counter 0,1,2 Interrupt(s) initialization
TIMSK0=0x00;
TIMSK1=0x02;
TIMSK2=0x00;

// USART0 initialization
// Communication Parameters: 8 Data, 1 Stop, No Parity
// USART0 Receiver: On
// USART0 Transmitter: On
// USART0 Mode: Asynchronous
// USART0 Baud rate: 9600
UCSR0A=0x00;
UCSR0B=0xD8;
UCSR0C=0x06;
UBRR0H=0x00;
UBRR0L=0x81;

// USART1 initialization
// USART1 disabled
UCSR1B=0x00;


// Analog Comparator initialization
// Analog Comparator: Off
// Analog Comparator Input Capture by Timer/Counter 1: Off
ACSR=0x80;
ADCSRB=0x00;
DIDR1=0x00;

// Watchdog Timer initialization
// Watchdog Timer Prescaler: OSC/2048  
#pragma optsize-
#asm("wdr")
// Write 2 consecutive values to enable watchdog
// this is NOT a mistake !
WDTCSR=0x18;
WDTCSR=0x08;
#ifdef _OPTIMIZE_SIZE_
#pragma optsize+
#endif

}

1. 1。

float re = 0;
float im = 0;  

move the declaration, or do not forget to reset those values to zero inside the loop before the nested loop. 移动声明,或者不要忘记在嵌套循环之前在循环内部将这些值重置为零。

2. Nyquist–Shannon theorem (also known as Kotelnikov's theorem) says about sampling rate. 2. Nyquist–Shannon定理(也称为Kotelnikov定理)说的是采样率。 To transfer frequencies up to F you have to have at least 2*F sampling rate. 要传输高达F的频率,您必须至少具有2 * F的采样率。 It is nothing to do with number of samples. 这与样本数量无关。 If your MCU is running at 16MHz, i can assume you have the sampling rate about 9kHz = 16MHz / 128 (prescaler of the ADC) / 14 (ADC clock cycles per one sample) 如果您的MCU以16MHz运行,我可以假设您的采样率约为9kHz = 16MHz / 128(ADC的预分频器)/ 14(每一个采样的ADC时钟周期)

3. What is Init_initController(); 3.什么是Init_initController(); ? There is no such function in your code. 您的代码中没有此类功能。 What it is doing? 它在做什么? Why it must be the first "init" action/call! 为什么它must be the first "init" action/call! ? Probably there is an issue. 可能有问题。 Looking at wdogtrig(); wdogtrig(); I can assume somewhere watchdog timer is initialized. 我可以假设看门狗计时器已初始化。 Since float math takes too much long time, The watchdog expires before the loop finished. 由于浮点运算需要花费很长时间,因此看门狗会在循环结束之前到期。

Either disable the watchdog, or put wdogtrig(); 要么禁用看门狗,要么放置wdogtrig(); inside the loop in computeDft(); computeDft();的循环内computeDft(); , for watchdog timer reset more often. ,用于看门狗定时器更频繁地重置。

4. You can make the declaration 4.您可以进行声明

unsigned char x[N] = {0};

global, moving it outside the function, the memory will be allocated once and do not refill the stack on each function call 全局,将其移到函数外部,内存将分配一次,并且不会在每次函数调用时重新填充堆栈

5. Please, if you asking a question, provide all the information inside the question: what you were expecting, what you got, all custom functions and exact code which does not work. 5.如果您提出问题,请提供问题内的所有信息:您的期望,所得到的东西,所有自定义函数和不起作用的确切代码。

What is the stack size? 堆栈大小是多少? Your x[N] is instantiated on the stack and there is probably insufficient space for an array of sufficient size. 您的x[N]实例化在堆栈上,可能没有足够的空间来放置足够大小的数组。

Allocate it statically to avoid the stack-overflow: 静态分配它以避免堆栈溢出:

static unsigned char x[N] = {0};

Even then the ATmega164 has only 1K RAM in total. 即使这样,ATmega164总共也只有1K RAM。 You may be able to create an 800 sample buffer, but your stack will have to be no more than around 200 bytes in that case. 您可能可以创建800个样本缓冲区,但是在这种情况下,堆栈的大小不得超过200个字节。 However you don't need a buffer that size; 但是,您不需要该大小的缓冲区。 you are confusing number of samples with number of samples per second. 您将样本数量与每秒样本数量混淆了。 What you need for the DFT is only a reasonable number of cycles to achieve your required precision. DFT只需要一个合理的周期数即可达到所需的精度。 The resolution in Hz will be equal to F s /N, so a 256 sample buffer will yield a precision of around 3Hz which may be accurate enough. 以Hz为单位的分辨率将等于F s / N,因此256个采样缓冲区将产生约3Hz的精度,这可能足够准确。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 我正在尝试在 atmega164 上制作一个简单的吉他调谐器,但我无法在 CodeVisionAVR 上编写读取频率的代码 - I am trying to make a simple guitar tuner on a atmega164 and i cannot make the code for reading a frequency on CodeVisionAVR 我正在通过ATmega16p和CodeVisionAVR设计吉他调音器,但我无法运行我的代码 - I'm designing a guitar tuner through ATmega16p and CodeVisionAVR and i just can't get my code to run Mbed吉他调谐器代码有问题吗? - Mbed Guitar Tuner Code Problems? 带ATMega164PA的PWM - PWM with ATMega164PA ds_list不能处理3个以上的元素 - ds_list can't handle more than 3 elements 为什么我的代码不能生成超过999个文本文件? - Why can't my code generate more than 999 text files? 从atmega128 C代码中找不到错误 - Can't find error from atmega128 C code 使用 CodevisionAVR for ATmega16a 构建后 Linker 警告 - Linker warning after builds with CodevisionAVR for ATmega16a 为什么我不能在我的代码中关闭 window 句柄? - Why can't I close the window handle in my code? 使用我的代码,我得到了不止一个“最小为”行或“最大为”行……我的错误在哪里? - Using my code I am returned more than one “smallest is” line or “largest is” line…where are my errors?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM