Что нового

[C++]Объявление переменной

_Lexa98_

Осваивающий
Сообщения
551
Репутация
25
Есть код:
Код:
#include "PCM.h"

const unsigned char data = {0};

void setup()
{
  Serial.begin(9600);
}

void loop()
{
  const unsigned char data = {Serial.read()};
  startPlayback(data, sizeof(data));
}

При попытке компиляции через Arduino IDE выдает ошибку:
Код:
serial.ino: In function 'void loop()':
serial:13: error: invalid conversion from 'const unsigned char' to 'const unsigned char*'
serial:13: error: initializing argument 1 of 'void startPlayback(const unsigned char*, int)'

Не могу понять как исправить, пробовал менять типы переменных, ничего не получалось.
Помогите исправить, а то я в C++ не силен.

Две библиотеки к коду:

Код:
/*
 * speaker_pcm
 *
 * Plays 8-bit PCM audio on pin 11 using pulse-width modulation (PWM).
 * For Arduino with Atmega168 at 16 MHz.
 *
 * Uses two timers. The first changes the sample value 8000 times a second.
 * The second holds pin 11 high for 0-255 ticks out of a 256-tick cycle,
 * depending on sample value. The second timer repeats 62500 times per second
 * (16000000 / 256), much faster than the playback rate (8000 Hz), so
 * it almost sounds halfway decent, just really quiet on a PC speaker.
 *
 * Takes over Timer 1 (16-bit) for the 8000 Hz timer. This breaks PWM
 * (analogWrite()) for Arduino pins 9 and 10. Takes Timer 2 (8-bit)
 * for the pulse width modulation, breaking PWM for pins 11 & 3.
 *
 * References:
 *     http://www.uchobby.com/index.php/2007/11/11/arduino-sound-part-1/
 *     http://www.atmel.com/dyn/resources/prod_documents/doc2542.pdf
 *     http://www.evilmadscientist.com/article.php/avrdac
 *     http://gonium.net/md/2006/12/27/i-will-think-before-i-code/
 *     http://fly.cc.fer.hr/GDM/articles/sndmus/speaker2.html
 *     http://www.gamedev.net/reference/articles/article442.asp
 *
 * Michael Smith <[email protected]>
 */

/*
 * The audio data needs to be unsigned, 8-bit, 8000 Hz, and small enough
 * to fit in flash. 10000-13000 samples is about the limit.
 *
 * sounddata.h should look like this:
 *     const int sounddata_length=10000;
 *     const unsigned char sounddata_data[] PROGMEM = { ..... };
 *
 * You can use wav2c from GBA CSS:
 *     http://thieumsweb.free.fr/english/gbacss.html
 * Then add "PROGMEM" in the right place. I hacked it up to dump the samples
 * as unsigned rather than signed, but it shouldn't matter.
 *
 * http://musicthing.blogspot.com/2005/05/tiny-music-makers-pt-4-mac-startup.html
 * mplayer -ao pcm macstartup.mp3
 * sox audiodump.wav -v 1.32 -c 1 -r 8000 -u -1 macstartup-8000.wav
 * sox macstartup-8000.wav macstartup-cut.wav trim 0 10000s
 * wav2c macstartup-cut.wav sounddata.h sounddata
 *
 * (starfox) nb. under sox 12.18 (distributed in CentOS 5), i needed to run
 * the following command to convert my wav file to the appropriate format:
 * sox audiodump.wav -c 1 -r 8000 -u -b macstartup-8000.wav
 */

#include <avr/pgmspace.h>

#ifdef __cplusplus
extern "C" {
#endif

void startPlayback(unsigned char const *data, int length);
void stopPlayback();

#ifdef __cplusplus
}
#endif

Код:
/*
 * speaker_pcm
 *
 * Plays 8-bit PCM audio on pin 11 using pulse-width modulation (PWM).
 * For Arduino with Atmega168 at 16 MHz.
 *
 * Uses two timers. The first changes the sample value 8000 times a second.
 * The second holds pin 11 high for 0-255 ticks out of a 256-tick cycle,
 * depending on sample value. The second timer repeats 62500 times per second
 * (16000000 / 256), much faster than the playback rate (8000 Hz), so
 * it almost sounds halfway decent, just really quiet on a PC speaker.
 *
 * Takes over Timer 1 (16-bit) for the 8000 Hz timer. This breaks PWM
 * (analogWrite()) for Arduino pins 9 and 10. Takes Timer 2 (8-bit)
 * for the pulse width modulation, breaking PWM for pins 11 & 3.
 *
 * References:
 *     http://www.uchobby.com/index.php/2007/11/11/arduino-sound-part-1/
 *     http://www.atmel.com/dyn/resources/prod_documents/doc2542.pdf
 *     http://www.evilmadscientist.com/article.php/avrdac
 *     http://gonium.net/md/2006/12/27/i-will-think-before-i-code/
 *     http://fly.cc.fer.hr/GDM/articles/sndmus/speaker2.html
 *     http://www.gamedev.net/reference/articles/article442.asp
 *
 * Michael Smith <[email protected]>
 */

#include <stdint.h>
#include <avr/interrupt.h>
#include <avr/io.h>
#include <avr/pgmspace.h>

#define SAMPLE_RATE 8000

#if defined(ARDUINO) && ARDUINO >= 100
#include "Arduino.h"
#else
#include "WProgram.h"
#endif

#include "PCM.h"

/*
 * The audio data needs to be unsigned, 8-bit, 8000 Hz, and small enough
 * to fit in flash. 10000-13000 samples is about the limit.
 *
 * sounddata.h should look like this:
 *     const int sounddata_length=10000;
 *     const unsigned char sounddata_data[] PROGMEM = { ..... };
 *
 * You can use wav2c from GBA CSS:
 *     http://thieumsweb.free.fr/english/gbacss.html
 * Then add "PROGMEM" in the right place. I hacked it up to dump the samples
 * as unsigned rather than signed, but it shouldn't matter.
 *
 * http://musicthing.blogspot.com/2005/05/tiny-music-makers-pt-4-mac-startup.html
 * mplayer -ao pcm macstartup.mp3
 * sox audiodump.wav -v 1.32 -c 1 -r 8000 -u -1 macstartup-8000.wav
 * sox macstartup-8000.wav macstartup-cut.wav trim 0 10000s
 * wav2c macstartup-cut.wav sounddata.h sounddata
 *
 * (starfox) nb. under sox 12.18 (distributed in CentOS 5), i needed to run
 * the following command to convert my wav file to the appropriate format:
 * sox audiodump.wav -c 1 -r 8000 -u -b macstartup-8000.wav
 */

int speakerPin = 11;
unsigned char const *sounddata_data=0;
int sounddata_length=0;
volatile uint16_t sample;
byte lastSample;

// This is called at 8000 Hz to load the next sample.
ISR(TIMER1_COMPA_vect) {
  if (sample >= sounddata_length) {
    if (sample == sounddata_length + lastSample) {
      stopPlayback();
    }
    else {
      // Ramp down to zero to reduce the click at the end of playback.
      OCR2A = sounddata_length + lastSample - sample;
    }
  }
  else {
    OCR2A = pgm_read_byte(&sounddata_data[sample]);
  }
  
  ++sample;
}

void startPlayback(unsigned char const *data, int length)
{
  sounddata_data = data;
  sounddata_length = length;

  pinMode(speakerPin, OUTPUT);
  
  // Set up Timer 2 to do pulse width modulation on the speaker
  // pin.
  
  // Use internal clock (datasheet p.160)
  ASSR &= ~(_BV(EXCLK) | _BV(AS2));
  
  // Set fast PWM mode  (p.157)
  TCCR2A |= _BV(WGM21) | _BV(WGM20);
  TCCR2B &= ~_BV(WGM22);
  
  // Do non-inverting PWM on pin OC2A (p.155)
  // On the Arduino this is pin 11.
  TCCR2A = (TCCR2A | _BV(COM2A1)) & ~_BV(COM2A0);
  TCCR2A &= ~(_BV(COM2B1) | _BV(COM2B0));
  
  // No prescaler (p.158)
  TCCR2B = (TCCR2B & ~(_BV(CS12) | _BV(CS11))) | _BV(CS10);
  
  // Set initial pulse width to the first sample.
  OCR2A = pgm_read_byte(&sounddata_data[0]);
  
  
  // Set up Timer 1 to send a sample every interrupt.
  
  cli();
  
  // Set CTC mode (Clear Timer on Compare Match) (p.133)
  // Have to set OCR1A *after*, otherwise it gets reset to 0!
  TCCR1B = (TCCR1B & ~_BV(WGM13)) | _BV(WGM12);
  TCCR1A = TCCR1A & ~(_BV(WGM11) | _BV(WGM10));
  
  // No prescaler (p.134)
  TCCR1B = (TCCR1B & ~(_BV(CS12) | _BV(CS11))) | _BV(CS10);
  
  // Set the compare register (OCR1A).
  // OCR1A is a 16-bit register, so we have to do this with
  // interrupts disabled to be safe.
  OCR1A = F_CPU / SAMPLE_RATE;    // 16e6 / 8000 = 2000
  
  // Enable interrupt when TCNT1 == OCR1A (p.136)
  TIMSK1 |= _BV(OCIE1A);
  
  lastSample = pgm_read_byte(&sounddata_data[sounddata_length-1]);
  sample = 0;
  sei();
}

void stopPlayback()
{
  // Disable playback per-sample interrupt.
  TIMSK1 &= ~_BV(OCIE1A);
  
  // Disable the per-sample timer completely.
  TCCR1B &= ~_BV(CS10);
  
  // Disable the PWM timer.
  TCCR2B &= ~_BV(CS10);
  
  digitalWrite(speakerPin, LOW);
}
 

sss

Продвинутый
Сообщения
332
Репутация
96
Попробуй так
Код:
const unsigned char data[] = {Serial.read()};
startPlayback(&data, sizeof(data));

Или так:
Код:
const unsigned char data = Serial.read();
startPlayback(&data, 1);
 

AZJIO

Меценат
Меценат
Сообщения
2,879
Репутация
1,194
Строковый массив можно объявить так:
Код:
const unsigned char data[] = "0";
В таком способе каждый символ строки является элементом массива, а количество определяется автоматически при компиляции.

А функция main() отсутствует что ли?

Почему в loop() пытаешься изменить константу? Если ты объявил её как глобальную, вне функций, то внутри функций должен быть extern, если ты её хочешь изменить. А вообще если массив содержит один символ и он при компиляции определён, то вписать туда больше чем один символ не удастся не повредив программу записью выйдя за пределы своих данных.
 

sss

Продвинутый
Сообщения
332
Репутация
96
AZJIO
Это Arduino - она потом код преобразует примерно к такому виду:
Код:
int main(){
    init(); // инициализация ардуины
    setup();
    while (1){
        loop();
    }
    return 0;
}
Насколько я помню, extern не нужно писать - это вроде необходимо только если объявление находится в другом файле (поправьте меня если ошибаюсь). По крайнем мере я с этим словом столкнулся только когда писал библиотеки из 2 файлов - .h и .cpp

И кстати да, либо глобально объявляй переменную (за функцией), либо в функции.

И еще вспомнил кое-что: в этом случае const можно опустить. Это сделано, чтобы функция не могла изменить значение переменной. Только что проверил на похожей ситуации в чистых C++ (не адруине) - вот так работает:

Код:
unsigned char data = Serial.read();
startPlayback(&data, 1);
 
Автор
_Lexa98_

_Lexa98_

Осваивающий
Сообщения
551
Репутация
25
Sky-WaLkeR
Sky-WaLkeR сказал(а):
const unsigned char data[] = {Serial.read()};
startPlayback(&data, sizeof(data));
Выдает ошибку:
Код:
serial.ino: In function 'void loop()':
serial:13: error: cannot convert 'const unsigned char (*)[1]' to 'const unsigned char*' for argument '1' to 'void startPlayback(const unsigned char*, int)'
А это:
Код:
unsigned char data = Serial.read();
startPlayback(&data, 1);
Компилируется, но не хочет воспроизводиться. Наверно там библиотека воспроизволит только массив, а не строку.
 
Верх