我正在尝试在 atmega164 上制作一个简单的吉他调谐器,但我无法制作用于在 CodeVisionAVR 上读取频率的代码

问题描述

我正在为我的代码寻找一些指导。

#include <mega164a.h>

// Declare your global variables here
#define BUTTON1 PINC7
#define Freq_e 0xEF
#define Freq_B 0x9F
#define Freq_G 0xDE
#define Freq_D 0xBD
#define Freq_A 0xF7
#define Freq_E 0xCF

// Standard Input/Output functions
#include <stdio.h>
#include <delay.h>
#include <stdbool.h>
void USARtinit()
{
    // 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;

    #asm("sei")
}
 bool button_state()
{
  if (!((PINC & (1 << BUTTON1)) >> BUTTON1))
  {
    delay_ms(30);
   if (!((PINC & (1 << BUTTON1)) >> BUTTON1))
     return true;
  }
  return false;
}
  unsigned char SelectedFreq=0;
/*unsigned char readanalog()
{
    unsigned short val=0;
    while(ADCSRA&(1<<ADSC));
    val=ADCL;
    val+=(ADCH<<8);
    return ADCL;
}
*/
float val1=0.0;
float desirefreqe=329.63;
float desirefreqB=246.94;
float desirefreqG=196;
float desirefreqD=146.83;
float desirefreqA=110;
float desirefreqEs=82.41;
void compfreq(unsigned char SelectedFreq)
{
    float tempfreq=0;
  if(SelectedFreq==0){
     tempfreq=desirefreqe;
  }
  else if(SelectedFreq==1){
     tempfreq=desirefreqB;
  }
   else if(SelectedFreq==2){
     tempfreq=desirefreqG;
  }
   else if(SelectedFreq==3){
     tempfreq=desirefreqD;
  }
   else if(SelectedFreq==4){
     tempfreq=desirefreqA;
  }
   else if(SelectedFreq==5){
     tempfreq=desirefreqEs;
  }
  if(val1>(tempfreq+2)){
   PORTB=0x9c;
  }
  else if(val1<(tempfreq-2)){
   PORTB=0xE2;
  }
  else{
  PORTB=0x81;
  }
}
void closefreq(){
    if(val1>=(desirefreqe-((desirefreqe-desirefreqB)/2))){
       PORTD=Freq_e;
    }
    else if(val1>=(desirefreqB-((desirefreqB-desirefreqG)/2))){
        PORTD=Freq_B;
    }
    else if(val1>=(desirefreqG-((desirefreqG-desirefreqD)/2))){
        PORTD=Freq_G;
    }
     else if(val1>=(desirefreqD-((desirefreqD-desirefreqA)/2))){
        PORTD=Freq_D;
    }
     else if(val1>(desirefreqA-((desirefreqA-desirefreqEs)/2))){
        PORTD=Freq_A;
    }
     else {
        PORTD=Freq_E;
    }
}
/*unsigned char read_adc(unsigned char adc_input) {
    ADMUX = adc_input | ADC_VREF_TYPE;
    // Delay needed for the stabilization of the ADC input voltage
    delay_us(10);
    // Start the AD conversion
    ADCSRA |= (1 << ADSC);
    // Wait for the AD conversion to complete
    while ((ADCSRA & (1 << ADIF)) == 0);

    ADCSRA |= (1 << ADIF);
    return ADCH;
}
*/
unsigned char read_adc1(void)
{
    ADCSRA |= 0b01000000;  //start conversion;
    while (ADCSRA&(0b01000000)); //wait conversion end
    return ADCH;
}
void main(void)
{
// Declare your local variables here

// Crystal Oscillator division factor: 1
#pragma optsize-
CLKPR=(1<<CLKPCE);
CLKPR=(0<<CLKPCE) | (0<<CLKps3) | (0<<CLKPS2) | (0<<CLKPS1) | (0<<CLKPS0);
#ifdef _OPTIMIZE_SIZE_
#pragma optsize+
#endif

// Input/Output Ports initialization
// Port A initialization
// Function: Bit7=In Bit6=In Bit5=In Bit4=In Bit3=In Bit2=In Bit1=In Bit0=In
DDRA=(0<<DDA7) | (0<<DDA6) | (0<<DDA5) | (0<<DDA4) | (0<<DDA3) | (0<<DDA2) | (0<<DDA1) | (0<<DDA0);
PRR &= ~(1 << PRADC);
//ADMUX=ADC_VREF_TYPE;
ADMUX = 0b10100111; // set ADC0
ADCSRA = 0b10000111; //set ADEN,precale by 128
// State: Bit7=T Bit6=T Bit5=T Bit4=T Bit3=T Bit2=T Bit1=T Bit0=T
PORTA=(0<<PORTA7) | (0<<PORTA6) | (0<<PORTA5) | (0<<PORTA4) | (0<<PORTA3) | (0<<PORTA2) | (0<<PORTA1) | (0<<PORTA0);

// Port B initialization
// Function: Bit7=In Bit6=Out Bit5=Out Bit4=Out Bit3=Out Bit2=Out Bit1=Out Bit0=Out
DDRB=(0<<DDB7) | (1<<DDB6) | (1<<DDB5) | (1<<DDB4) | (1<<DDB3) | (1<<DDB2) | (1<<DDB1) | (1<<DDB0);
// State: Bit7=T Bit6=0 Bit5=0 Bit4=0 Bit3=0 Bit2=0 Bit1=0 Bit0=0
PORTB=(0<<PORTB7) | (0<<PORTB6) | (0<<PORTB5) | (0<<PORTB4) | (0<<PORTB3) | (0<<PORTB2) | (0<<PORTB1) | (0<<PORTB0);

// Port C initialization
// Function: Bit7=In Bit6=Out Bit5=Out Bit4=Out Bit3=Out Bit2=Out Bit1=Out Bit0=Out
DDRC=(0<<DDC7) | (1<<DDC6) | (1<<DDC5) | (1<<DDC4) | (1<<DDC3) | (1<<DDC2) | (1<<DDC1) | (1<<DDC0);
// State: Bit7=T Bit6=0 Bit5=0 Bit4=0 Bit3=0 Bit2=0 Bit1=0 Bit0=0
PORTC=(1<<PORTC7) | (0<<PORTC6) | (0<<PORTC5) | (0<<PORTC4) | (0<<PORTC3) | (0<<PORTC2) | (0<<PORTC1) | (0<<PORTC0);

// Port D initialization
// Function: Bit7=In Bit6=Out Bit5=Out Bit4=Out Bit3=Out Bit2=Out Bit1=Out Bit0=Out
DDRD=(0<<DDD7) | (1<<DDD6) | (1<<DDD5) | (1<<DDD4) | (1<<DDD3) | (1<<DDD2) | (1<<DDD1) | (1<<DDD0);
// State: Bit7=T Bit6=0 Bit5=0 Bit4=0 Bit3=0 Bit2=0 Bit1=0 Bit0=0
PORTD=(0<<PORTD7) | (0<<PORTD6) | (0<<PORTD5) | (0<<PORTD4) | (0<<PORTD3) | (0<<PORTD2) | (0<<PORTD1) | (0<<PORTD0);

// Timer/Counter 0 initialization
// Clock source: System Clock
// Clock value: Timer 0 Stopped
// Mode: normal top=0xFF
// OC0A output: disconnected
// OC0B output: disconnected
TCCR0A=(0<<COM0A1) | (0<<COM0A0) | (0<<COM0B1) | (0<<COM0B0) | (0<<WGM01) | (0<<WGM00);
TCCR0B=(0<<WGM02) | (0<<CS02) | (0<<CS01) | (0<<CS00);
TCNT0=0x00;
OCR0A=0x00;
OCR0B=0x00;

// Timer/Counter 1 initialization
// Clock source: System Clock
// Clock value: Timer1 Stopped
// Mode: normal top=0xFFFF
// OC1A output: disconnected
// OC1B output: disconnected
// Noise Canceler: Off
// Input Capture on Falling Edge
// Timer1 Overflow Interrupt: Off
// Input Capture Interrupt: Off
// Compare A Match Interrupt: Off
// Compare B Match Interrupt: Off
TCCR1A=(0<<COM1A1) | (0<<COM1A0) | (0<<COM1B1) | (0<<COM1B0) | (0<<WGM11) | (0<<WGM10);
TCCR1B=(0<<ICNC1) | (0<<ICES1) | (0<<WGM13) | (0<<WGM12) | (0<<CS12) | (0<<CS11) | (0<<CS10);
TCNT1H=0x00;
TCNT1L=0x00;
ICR1H=0x00;
ICR1L=0x00;
OCR1AH=0x00;
OCR1AL=0x00;
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=(0<<EXCLK) | (0<<AS2);
TCCR2A=(0<<COM2A1) | (0<<COM2A0) | (0<<COM2B1) | (0<<COM2B0) | (0<<WGM21) | (0<<WGM20);
TCCR2B=(0<<WGM22) | (0<<CS22) | (0<<CS21) | (0<<CS20);
TCNT2=0x00;
OCR2A=0x00;
OCR2B=0x00;

// Timer/Counter 0 Interrupt(s) initialization
TimsK0=(0<<OCIE0B) | (0<<OCIE0A) | (0<<TOIE0);

// Timer/Counter 1 Interrupt(s) initialization
TimsK1=(0<<ICIE1) | (0<<OCIE1B) | (0<<OCIE1A) | (0<<TOIE1);

// Timer/Counter 2 Interrupt(s) initialization
TimsK2=(0<<OCIE2B) | (0<<OCIE2A) | (0<<TOIE2);


// 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=(0<<ISC21) | (0<<ISC20) | (0<<ISC11) | (0<<ISC10) | (0<<ISC01) | (0<<ISC00);
EimsK=(0<<INT2) | (0<<INT1) | (0<<INT0);
PCICR=(0<<PCIE3) | (0<<PCIE2) | (0<<PCIE1) | (0<<PCIE0);


// USART1 initialization
// USART1 disabled
UCSR1B=(0<<RXCIE1) | (0<<TXCIE1) | (0<<UDRIE1) | (0<<RXEN1) | (0<<TXEN1) | (0<<UCSZ12) | (0<<RXB81) | (0<<TXB81);

// Analog Comparator initialization
// Analog Comparator: Off
// The Analog Comparator's positive input is
// connected to the AIN0 pin
// The Analog Comparator's negative input is
// connected to the AIN1 pin
ACSR=(1<<ACD) | (0<<ACBG) | (0<<ACO) | (0<<ACI) | (0<<ACIE) | (0<<ACIC) | (0<<ACIS1) | (0<<ACIS0);
ADCSRB=(0<<Acme);
// Digital input buffer on AIN0: On
// Digital input buffer on AIN1: On
DIDR1=(0<<AIN0D) | (0<<AIN1D);

// ADC initialization
// ADC disabled
ADCSRA=(0<<ADEN) | (0<<ADSC) | (0<<ADATE) | (0<<ADIF) | (0<<ADIE) | (0<<ADPS2) | (0<<ADPS1) | (0<<ADPS0);

// SPI initialization
// SPI disabled
SPCR=(0<<SPIE) | (0<<SPE) | (0<<DORD) | (0<<MSTR) | (0<<CPOL) | (0<<CPHA) | (0<<SPR1) | (0<<SPR0);

// TWI initialization
// TWI disabled
TWCR=(0<<TWEA) | (0<<TWSTA) | (0<<TWSTO) | (0<<TWEN) | (0<<TWIE);
USARtinit();


while (1)
      {
     // readanalog();
      val1 = read_adc1();
      if( button_state())
      {
        SelectedFreq++;
        SelectedFreq=SelectedFreq%6;
        delay_ms(60);
      }
      if(SelectedFreq==0)
      {
        PORTC=Freq_e;
      }
      else if (SelectedFreq==1)
          {
            PORTC=Freq_B;
          }
      else if (SelectedFreq==2)
          {
            PORTC=Freq_G;
          }
      else if (SelectedFreq==3)
          {
            PORTC=Freq_D;
          }
      else if (SelectedFreq==4)
          {
            PORTC=Freq_A;
          }
       else if (SelectedFreq==5)
          {
            PORTC=Freq_E;
          }
       compfreq(SelectedFreq);
       closefreq();
      }
}

我需要的只是一个可以从 atmega164 的 PINA1 读取频率的函数,仅此而已,但我不知道如何构建它。非常感谢所有的帮助。在这里发帖之前,我已经尝试了两个多星期来找到使我的代码正常工作的答案,但我无法做到。 代码无法从 PINA1 读取值,这是一个频率

代码现在可以比较作为输入频率的值,并将其与 6 个不同节点(e、B、G、D、A、E)的 6 个频率进行比较。程序无法做的是从 PINA1 读取输入频率。

解决方法

一个简单(粗略,但可能可行)的解决方案是随着时间的推移计算过零。我不确定 CodeVision 库提供什么计时器支持,但我假设您有 1 毫秒的分辨率滴答计数和 1 毫秒的分辨率延迟。如果没有,您将不得不使用计时器外设提供自己的外设。

int measureFrequency( int dc_offset )
{
    int zero_x_count = 0 ;
    
    delayms(1) ;  // align to the tick boundary
    int start = tickms() ;
    int previous_sign  = read_adc1() = dc_offset < 0 ? -1 : 1 ;
    
    // Count zero x for 1 second
    while( tickms() - start < 1000 )
    {
        delayms(1) ;
        int sign  = read_adc1() = dc_offset < 0 ? -1 : 1 ;

        if( sign != previous_sign )
        {
            zero_x_count++ ;
        }
    }
    
    // Frequency = zero-x / 2
    return zero_x_count >> 1 ;
}

dc_offset 参数是对应于无信号(静音)的静态 ADC 读数。您可以通过在不拔弦的情况下随时间取平均值来单独测量。一种更复杂的方法是使用截止频率非常低的高通 IIR 滤波器(隔直滤波器)来实时去除信号中的偏移。

读数之间的 1 毫秒延迟有望足以防止由于读数中的高频谐波和噪声引起的错误计数,但您必须进行实验。弹拨弦的波形很复杂,可能会破坏这种简单的方法。 理想情况下,您在输入端有一个模拟抗混叠滤波器,截止频率约为 500Hz;通过去除这些高频分量,这将使其更可靠。

更复杂的数字信号处理 (DSP) 方法包括:

  • 快速傅立叶变换 (FFT) 并找到峰值频率。
  • 为每个弦频率创建一个数字带通滤波器并测量每个频率的响应。

第二种方法的优点是您实际上可以通过弹奏一个开放的和弦同时对所有弦进行调音。在这种情况下,虽然您测量的不是频率,而是该频率的信号电平。您需要一个非常窄的频带和良好的抑制,坦率地说,ATMega 可能达不到它的要求。

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...