Страница 1 из 1
AVR + DFPlayer. Анализ обратной связи с модулем
Добавлено: Вс окт 04, 2020 21:41:55
Prosperous
Здравствуйте! Как вы знаете, AVR и DFPlayer общаются по UART. Команды обратной связи отсылаются и принимаются тут вопросов нет. Не могу реализовать следующий алгоритм:
1. Нажали кнопку - послали модулю команду воспроизведения
2. От модуля пришел ответ - провели анализ
3. Если ответ положительный - отправили команду зациклить трек, если отрицательный - зажгли светодиод
4. От модуля пришел ответ о зацикливании - провели анализ
5. и т.д.
6 Нажали на ту же кнопку - отправили команду прекратить воспроизведение
7. От модуля пришел ответ - провели анализ
8. и т.д.
Все работает, кроме анализа. Вроде несложно, но не могу понять как МК заставить ждать ответа, точнее накопления буфера.
Есть код, но явно неверный (могу выложить, чтобы носом меня ткнуть в ошибки).
Подскажите алгоритм. Спасибо.
Re: AVR + DFPlayer. Анализ обратной связи с модулем
Добавлено: Вс окт 04, 2020 21:49:19
ARV
делал подобное - гемор еще тот, ибо модуль плейера имеет обыкновение то не отвечать на часть команд, то отвечать не одним ответом, а двумя разными, то задержка ответа непредсказуемая может быть - гадай потом, на какую команду он ответил... после долгих мучений отказался от анализа ответов, оставив тодлько анализ "уведомлений" о том, что карта вставлена-вынута, прошел сброс и инициализация. начало/конец воспроизведения отслеживаю по уровню на пине.
возможно, у меня руки кривые, но без анализа все получилось гораздо проще.
Re: AVR + DFPlayer. Анализ обратной связи с модулем
Добавлено: Вс окт 04, 2020 22:01:02
Oxford
Привет. В каком плане вы имеете ввиду анализ ? Вы имеете ввиду не знаете какой длины пакет будет?
Re: AVR + DFPlayer. Анализ обратной связи с модулем
Добавлено: Вт окт 06, 2020 14:13:15
Prosperous
2ARV
На самом деле не получается сделать анализ даже если карта воткнута/вынута. Например, я послал команду "плей".пришел ответ, что карта вынута, я поcлал еще раз "плей", чтобы убедится, что она действительно вынута (т.е. должно прийти еще одно подтверждение). Т.е. надо проанализировать ответ и в зависимости от него послать ту или другую команду по UART. Ошибка в коде явно в ожидании ответа. Прикладываю код, все лишнее удалил. Посмотрите где косяк, пжлст. Спасибо.
P.S. Пользуясь случаем спрошу. В этой программе есть анализ данных по АЦП. Когда опрос АЦП закомментирован - вывод данных на дисплей от UART мгновенный. Когда раскомментирован - секунд 5. Как можно оптимизировать?
Спойлер
Код: Выделить всё
#define F_CPU 16000000UL
#define StartConvAdc() ADCSRA |= (1<<ADSC)
#define MODULE_OK 0x41
#define MODULE_ONLINE 0x3F
#define MODULE_ERROR 0x40
#define MODULE_BUSY 0x01
#define SD_IN 0x3A
#define SD_OUT 0x3B
#define MODULE_PLAY 0x0D
#define MODULE_STOP 0x16
#define MODULE_REPEAT 0x19
unsigned char RX_Buffer[8];
unsigned char RX_Counter = 0;
unsigned char RX_Bait = 0;
unsigned char key=1;
unsigned char key1=1;
unsigned char key_on = 0;
unsigned char module_OK = 0;
unsigned char TX_OK = 0;
unsigned char USART_Receive(void)
{
while (!(UCSR0A & (1 << RXC0)))
;
return UDR0;
}
ISR(USART_RX_vect)
{
if (RX_Bait<10){
RX_Buffer[RX_Counter] = USART_Receive();
RX_Counter++;
if (RX_Counter == 10)
RX_Counter = 0;
RX_Bait++;
}
}
void Packet_Analyze()
{
unsigned char code;
unsigned char databyte;
if (RX_Bait == 10)
{
code = RX_Buffer[3];
databyte = RX_Buffer[6];
switch (code)
{
case MODULE_OK:
{
TX_OK = 1;
break;
}
case MODULE_ERROR:
{
TX_OK = 0;
break;
}
case SD_IN:
{
module_OK = 1;
break;
}
case SD_OUT:
{
module_OK = 0;
break;
}
case MODULE_ONLINE:
{
module_OK = 1;
break;
}
}
USART_FlushRxBuf();
}
}
void USART_FlushRxBuf(void)
{
cli();
RX_Counter = 0;
RX_Bait = 0;
sei();
}
void main(void)
{
usart_init();
sei();
PORTD = 0b00000100;
DDRD = 0x01;
mp3_status(MODULE_ONLINE);
while(1) {
key = ~(PIND & _BV(2));
_delay_ms(20);
key1 = ~(PIND & _BV(2));
if (key == 0xff && key1 == 0xff){
flag_EN = 1;
if (flag_EN!=flag_EN_old)
{
flag_EN_old = flag_EN;
flag = !flag;
key_on = 1;
}
}
else{
flag_EN = 0;
flag_EN_old = 0;
}
if (key_on==1){
if (flag)
{
mp3_play(MODULE_PLAY);
if (TX_OK) //анализ ответа от модуля
{
TX_OK = 0;
mp3_repeat(0x19);
//здесь также должен быть анализ ответа
key_on=0;
}
else
{
key_on=0;
}
}
else{
mp3_stop(MODULE_STOP);
//здесь также должен быть анализ ответа
key_on=0;
}
}
Packet_Analyze();
}
}
2Oxford
Тупо не выставляется флаг TX_OK (например) по завершении приема. Точнее он выставляется позже чем надо и поэтому программа работает неверно .
Re: AVR + DFPlayer. Анализ обратной связи с модулем
Добавлено: Вт окт 06, 2020 15:22:47
Dimon456
Prosperous, у вас есть формат ответа от модуля (можно все возможные комбинации ответа от модуля)?
Re: AVR + DFPlayer. Анализ обратной связи с модулем
Добавлено: Вт окт 06, 2020 16:25:40
ARV
посмотрите на мои старания:
Код: Выделить всё
// прием данных от модуля и их разбор по прерываниям
ISR(RX_VECTOR){
static uint8_t cur;
static mp3_buf_t buf;
static uint8_t old = 0xFF;
uint8_t d = _UDR;
// ждем стартовый байт - синхронизация
if(cur == 0){
if(d != MP3_START_BYTE) return;
}
// накапливаем пакет
buf.bytes[cur++] = d;
if(d == MP3_STOP_BYTE){
// готов пакет
cur = 0;
switch(buf.command){
case MP3_ERROR: // ошибка
if(status == P_PLAY) status = P_READY;
break;
case MP3_STAY_USB:// конец воспроизведения
case MP3_STAY_SD:
// STAY приходит дважды, один раз надо игнорировать
if(old != buf.param_lo)
status = P_READY;
old = buf.param_lo;
break;
case MP3_DEV_STATUS: // инициализация закончена
if((status == P_NOT_READY) && (buf.param_lo == DEV_SD))
status = P_READY;
break;
case MP3_PLUG_IN: // подключение источника
status = P_READY;
break;
case MP3_PULL_OUT: // отключение источника
status = P_NOT_READY;
break;
default: // все прочие пакеты
break;
}
}
}
в основном цикле смотрю уже на status и принимаю решения.
Добавлено after 2 minutes 6 seconds:
вот заголовочник с константами и типами:
Спойлер
Код: Выделить всё
/** \file mp3_tf_16p.h
* \brief определения для общенияс модулем MP3-плейера
*
* все константы, макросы, структуры данных и т.п. сделаны на основе документации
* на модуль.
* \author ARV
* \date 10 дек. 2018 г.
* \copyright 2015 © ARV. All rights reserved.
*
*/
#ifndef MP3_TF_16P_H_
#define MP3_TF_16P_H_
/// максимальное значение громкости
#define MP3_MAX_VOL 30
/// размер пакета обмена с модулем
#define MP3_PACKET_SZ 10
/// формат пакета обмена данными с MP3-плейером
typedef union{
uint8_t bytes[MP3_PACKET_SZ]; //!< представление пакета в виде массива байтов
struct{
uint8_t start; //!< стартовый байт
uint8_t ver; //!< версия
uint8_t number; //!< количество байт в пакете
uint8_t command; //!< команда
uint8_t feedback; //!< запрос подтверждения
union{
struct{
uint8_t param_hi; //!< старший байт параметра команды
uint8_t param_lo; //!< младший байт параметра команды
};
uint16_t param_ui; //!< параметр команды, как двухбайтное слово
};
uint8_t crc_hi; //!< старший байт контрольной суммы
uint8_t crc_lo; //!< младший байт контрольной суммы
uint8_t end; //!< стоповый байт
};
} mp3_buf_t;
/// стартовый байт пакета
#define MP3_START_BYTE 0x7E
/// стоповый байт пакета
#define MP3_STOP_BYTE 0xEF
#define MP3_IS_PLAYING 0x01
#define MP3_IS_PAUSED 0x02
#define MP3_IS_STOPPED 0x00
/// воспроизведение следующего трека
#define MP3_CMD_PLAY_NEXT 0x01
/// воспроизведение предыдущего трека
#define MP3_CMD_PLAY_PREV 0x02
/// воспроизведение трека из корня устройства
#define MP3_CMD_PLAY_ONE 0x03
/// увеличить громкость
#define MP3_CMD_INC_VOL 0x04
/// уменьшить громкость
#define MP3_CMD_DEC_VOL 0x05
/// установить громкость
#define MP3_CMD_SET_VOL 0x06
/// установить эквалайзер
#define MP3_CMD_SET_EQ 0x07
/// варианты настроек эквалайзера
typedef enum{
EQ_NORMAL = 0, //!< нет эквалайзера
EQ_POP = 1, //!< поп
EQ_ROCK = 2, //!< рок
EQ_JAZZ = 3, //!< джаз
EQ_CLASSIC = 4, //!< классика
EQ_BASS = 5 //!< басы
} equalizer_t;
/// повтор выбранного трека
#define MP3_CMD_REP_TRK 0x08
/// выбор устройства
#define MP3_CMD_SET_DEV 0x09
/// режим сна
#define MP3_CMD_SLEEP 0x0A
/// сброс плейера
#define MP3_CMD_RESET 0x0C
/// продолжение воспроизведения
#define MP3_CMD_PLAY 0x0D
/// пауза
#define MP3_CMD_PAUSE 0x0E
/// воспроизведение трека из папки, содержащей не более 255 треков
#define MP3_CMD_PLAY_FOLDER 0x0F
/// дополнительное усиление
#define MP3_CMD_SET_AMP 0x10
/// циклическое воспроизведение всего
#define MP3_CMD_REPEAT_ALL 0x11
/// выбор папки MP3 для воспроизведения
#define MP3_CMD_SELECT_MP3 0x12
/// врезка рекламы
#define MP3_CMD_START_ADV 0x13
/// воспроизведение трека из папки, содержащей не более 3000 треков
#define MP3_CMD_PLAY_3000 0x14
/// останока рекламы и продолжение прерванного трека
#define MP3_CMD_STOP_ADV 0x15
/// остановить воспроизведение
#define MP3_CMD_STOP 0x16
/// циклическое воспроизведение папки
#define MP3_CMD_REPEAT_FOLDER 0x17
/// слуяайный порядок воспроизведения
#define MP3_CMD_RANDOM_PLAY 0x18
/// зацикливание текущего трека
#define MP3_CMD_REPEAT_CUR 0x19
/// включение ЦАП
#define MP3_CMD_SET_DAC 0x1A
/// инфо о подключении источника
#define MP3_PLUG_IN 0x3A
/// инфо об отключении источника
#define MP3_PULL_OUT 0x3B
/// инфо об окончани трека на USB
#define MP3_STAY_USB 0x3C
/// инфо об окончании трека на SD
#define MP3_STAY_SD 0x3D
/// инфо о текущем активном устройстве
#define MP3_DEV_STATUS 0x3F
/// инфо об ошибке
#define MP3_ERROR 0x40
/// подтверждение приема команды от плейера
#define MP3_ACK 0x41
/// инфо о статусе плейера
#define MP3_GET_STATUS 0x42
/// инфо об уровне громкости
#define MP3_GET_VOL 0x43
/// инфо о текущем эквалайзере
#define MP3_GET_EQ 0x44
/// инфо об общем количестве файлов на USB-устройстве
#define MP3_USB_FCOUNT 0x47
/// инфо об общем количестве файлов на SD-карте
#define MP3_SD_FCOUNT 0x47
/// инфо о текущем треке на USB
#define MP3_USB_CUR_TRACK 0x4B
/// инфо о текущем треке на SD
#define MP3_SD_CUR_TRACK 0x4C
/// инфо о количестве файлов в папке
#define MP3_FOLDER_FCOUNT 0x4E
/// инфо о количестве папок на устройстве
#define MP3_FOLDER_COUNT 0x4F
/// устройства (для команды #MP3_DEV_STATUS)
typedef enum{
DEV_USB = 1, //!< USB-флешка
DEV_SD = 2, //!< SD-карта
DEV_USB_SD = 3, //!< И флешка и карта
DEV_PC = 4 //!< компьютер ?
} mp3_device_t;
/// коды ошибок
typedef enum{
ERR_BUSY = 1, //!< модуль занят (не инициализирован)
ERR_SLEEP = 2, //!< модуль в режиме сна
ERR_SERIAL = 3, //!< ошибочный фрейм последовательного порта
ERR_CRC = 4, //!< неверная контрольная сумма
ERR_TRACKOUT= 5, //!< трек поврежден (?)
ERR_NOTFOUND= 6, //!< трек не найден
ERR_INTERCUT= 7, //!< врезка рекламы возможна тоько во время воспроизведения трека
ERR_SD = 8 //!< ошибка чтения SD-карты (или карта вынута неожиданно)
} mp3_error_t;
#endif /* MP3_TF_16P_H_ */
Re: AVR + DFPlayer. Анализ обратной связи с модулем
Добавлено: Вт окт 06, 2020 17:58:27
Prosperous
2Dimon456
7E FF 06 41 00 00 00 xx xx EF - команда принята удачно
7E FF 06 40 00 00 01 xx xx EF - модуль не инициализирован/занят
7E FF 06 40 00 00 03 xx xx EF - ошибка приема
7E FF 06 40 00 00 08 xx xx EF - SD карта повреждена
7E FF 06 3A 00 00 02 xx xx EF - SD карта установлена
7E FF 06 3B 00 00 02 xx xx EF - SD карта извлечена
7E FF 06 3F 00 00 02 xx xx EF - модуль инициализирован
где xx - CRC пакета
Как можно видеть, нам фактически интересны только 3 и 6 байт
2ARV
Спасибо. Буду смотреть