Перейти к содержанию

BT201 схема подключения и управление из под ATMEGA8


Рекомендуемые сообщения

#define F_CPU 7372800UL
#define BAUND 9600L
#define UBRRL_value (F_CPU/(BAUND*16))-1

#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>
  
#define C_PC0 (~PINC&(1<<PC0))
#define C_PC1 (~PINC&(1<<PC1))
#define LED_1_ON() PORTD|=(1<<PD2)
#define LED_1_OFF() PORTD&=~(1<<PD2)
#define LED_2_ON() PORTD|=(1<<PD3)
#define LED_2_OFF() PORTD&=~(1<<PD3)
  
#define FLAG_END_RX (1<<3)
#define FLAG_ERR_RX (1<<4)
#define BUF_SIZE 20
char rx_buf[BUF_SIZE];
char buf_index = 0;

volatile start=1, flags;

char b;

ISR(USART_RXC_vect)
{	
    if (!(flags & FLAG_END_RX)){
        rx_buf[buf_index] = UDR;
        if (rx_buf[buf_index] == 0x0D){
          flags |= FLAG_END_RX;
          return;
        }
      	buf_index++;
        if (buf_index >= BUF_SIZE){
          buf_index = 0;
          flags |= FLAG_ERR_RX;
        }
    }
}

 

flags при инициализации не забудьте в 0 "обратить".

Изменено пользователем korsaj
Ссылка на комментарий
Поделиться на другие сайты

Реклама: ООО ТД Промэлектроника, ИНН: 6659197470, Тел: 8 (800) 1000-321

20% скидка на весь каталог электронных компонентов в ТМ Электроникс!

Акция "Лето ближе - цены ниже", успей сделать выгодные покупки!

Плюс весь апрель действует скидка 10% по промокоду APREL24 + 15% кэшбэк и бесплатная доставка!

Перейти на страницу акции

Реклама: ООО ТМ ЭЛЕКТРОНИКС, ИНН: 7806548420, info@tmelectronics.ru, +7(812)4094849

Особенности хранения литиевых аккумуляторов и батареек

Потеря емкости аккумулятора напрямую зависит от условий хранения и эксплуатации. При неправильном хранении даже самый лучший литиевый источник тока с превосходными характеристиками может не оправдать ожиданий. Технология, основанная на рекомендациях таких известных производителей литиевых источников тока, как компании FANSO и EVE Energy, поможет организовать правильный процесс хранения батареек и аккумуляторов. Подробнее>>

Реклама: АО КОМПЭЛ, ИНН: 7713005406, ОГРН: 1027700032161

@korsaj Сегодня попробовал сделать как ты посоветовал. Получился следующий код.

#define F_CPU 7372800UL
#define BAUND 9600L
#define UBRRL_value (F_CPU/(BAUND*16))-1

#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>
#include <stdlib.h>

void init_pin(void);

#define C_PC0 (~PINC&(1<<PC0))
#define C_PC1 (~PINC&(1<<PC1))
#define LED_1_ON() PORTD|=(1<<PD2)
#define LED_1_OFF() PORTD&=~(1<<PD2)
#define LED_2_ON() PORTD|=(1<<PD3)
#define LED_2_OFF() PORTD&=~(1<<PD3)

#define FLAG_END_RX (1<<3)
#define FLAG_ERR_RX (1<<4)
#define BUF_SIZE 20

char rx_buf[BUF_SIZE];
char buf_index = 0;

volatile start=1, flags;

char b;

ISR(USART_RXC_vect)
{
	b=UDR;
	if(!(flags & FLAG_END_RX))
	{
		rx_buf[buf_index]=UDR;
		if(rx_buf[buf_index] == 0x0D)
		{
			flags |= FLAG_END_RX;
			return;
		}
		buf_index++;
		if(buf_index >= BUF_SIZE)
		{
			buf_index = 0;
			flags |= FLAG_ERR_RX;
		}
	}
}

void init_UART()
{
	UBRRL = UBRRL_value;
	UBRRH = UBRRL_value>>8;
	UCSRB|=(1<<TXEN);
	UCSRB|=(1<<RXEN);
	UCSRC|=((1<<URSEL)|(1<<UCSZ0)|(1<<UCSZ1));
	UCSRB|=(1<<RXCIE);
	sei();
	flags = 0;
}

void send_UART(char value)
{
	while(!(UCSRA&(1<<UDRE)));
	UDR=value;
}

int main(void)
{
	init_pin();
	init_UART();
	
	while(1)
	{
		if (start==1)
		{
			_delay_ms(500);
			send_UART('O');
        	send_UART('K');
	        send_UART('!');
        	send_UART(0x0D);
        	send_UART(0x0A);
			_delay_ms(10);
			start=0;
		}
		if (b == '0')
		{
			LED_1_ON();
			LED_2_OFF();
			send_UART('N');
			send_UART('+');
			send_UART('0');
			send_UART('0');
			send_UART(0x0D);
			send_UART(0x0A);
			_delay_ms(10);
			b=4;
		}
		
		if (b == '1')
		{
			LED_1_OFF();
			LED_2_ON();
			send_UART('N');
			send_UART('+');
			send_UART('0');
			send_UART('1');
			send_UART(0x0D);
			send_UART(0x0A);
			_delay_ms(10);
			b=4;
		}
		
		if (b == '2')
		{
			LED_1_ON();
			LED_2_ON();
			send_UART('N');
			send_UART('+');
			send_UART('0');
			send_UART('2');
			send_UART(0x0D);
			send_UART(0x0A);
			_delay_ms(10);
			b=4;
		}
		
		if (b == '3')
		{
			LED_1_OFF();
			LED_2_OFF();
			send_UART('N');
			send_UART('+');
			send_UART('0');
			send_UART('3');
			send_UART(0x0D);
			send_UART(0x0A);
			_delay_ms(10);
			b=4;
		}
		if (C_PC0)
		{
			send_UART('P');
			send_UART('C');
			send_UART('0');
			send_UART(0x0D);
			send_UART(0x0A);
			_delay_ms(250);
		}
		
		if (C_PC1)
		{
			send_UART('P');
			send_UART('C');
			send_UART('1');
			send_UART(0x0D);
			send_UART(0x0A);
			_delay_ms(250);
		}
	}
}

void init_pin(void)
{
	DDRC = 0b00000000;
	PORTC = 0b11111111;
	DDRD |= ((1<<2)|(1<<3));
	PORTD &=~ ((1<<2)|(1<<3));
}

Ну как сказать всё работает, но вот меня очень интересует приём команд на саму ATMEGA16. Он так и работает только с цифрами. Более ничего корректно принять не получается даже используя таблицу ascii. А мне нужно будет принимать команды и посложней чем просто буквенно - цифровые. Потому как возвращаясь к командам самого плеера там в этих командах хранятся различные данные.

Вот примерно так это всё выглядит.

AT+QM \ r \ n Запрос режима работы [0: Bluetooth], [1: MP3]
AT+M1 \ r \ n Номер текущего файла
AT+M2 \ r \ n Общее количество звуковых файлов
AT+MD \ r \ n Источник музыки USB или SD Card
AT+MT \ r \ n Общее время воспроизведения текущего файла
AT+MK \ r \ n Время воспроизведения текущего файла
AT+MP \ r \ n Текущее состояние плеера [0]Стоп, [1]Воспроизведение, [2]Пауза

К примеру при отправке команды AT+M1 \ r \ n в ответ мы получим M1 + 000002 \ r \ n при этом здесь может быть любое число в hex формате. Мне же нужно каким то образом принять эти данные и обработать их соответствующим образом. Но при этом и нужно учитывать так же что плеер может сам отправить эти данные по началу воспроизведения трека. Вот в этом сейчас и стоит основная задача. Чего я и пытаюсь получить в итоге.

Ссылка на комментарий
Поделиться на другие сайты

Выбираем схему BMS для корректной работы литий-железофосфатных (LiFePO4) аккумуляторов

 Обязательным условием долгой и стабильной работы Li-FePO4-аккумуляторов, в том числе и производства EVE Energy, является применение специализированных BMS-микросхем. Литий-железофосфатные АКБ отличаются такими характеристиками, как высокая многократность циклов заряда-разряда, безопасность, возможность быстрой зарядки, устойчивость к буферному режиму работы и приемлемая стоимость. Но для этих АКБ, также как и для других, очень важен контроль процесса заряда и разряда, а специализированных микросхем для этого вида аккумуляторов не так много. Инженеры КОМПЭЛ подготовили список имеющихся микросхем и возможных решений от разных производителей. Подробнее>>

Реклама: АО КОМПЭЛ, ИНН: 7713005406, ОГРН: 1027700032161

Все верно, вы почти все что нужно сделали. 
Только не нужно было добавлять это b=UDR;
Сразу после старта сбросить флаг flags = 0;
А в основном цикле ждать установки флага FLAG_END_RX. И если он установлен, проверять на совпадение строки в буфере (rx_buf) с вашей строкой (AT+QM \ r \ n .....   .....  AT+MP \ r \ n) При совпадении вызывать выполнение нужного алгоритма.

Ссылка на комментарий
Поделиться на другие сайты

5 minutes ago, korsaj said:

не нужно было добавлять

Если не добавлять: при чтении регистра UDR сбрасывается флаг прерывания RXC. После приёма  "\r" и установки флага FLAG_END_RX обработчик больше не читает UDR.

Но затем приходит "\n" от плеера, снова устанавливается флаг RXC, и программа зависает в бесконечном прерывании.

Ссылка на комментарий
Поделиться на другие сайты

Согласен, для большей стабильности нужно всегда вычитывать  UDR.

ISR(USART_RXC_vect)
{	
    char rxb = UDR;
    if (!(flags & FLAG_END_RX)){
        rx_buf[buf_index] = rxb;
        if (rxb == 0x0D){
          flags |= FLAG_END_RX;
          buf_index = 0;
          return;
        }
      	buf_index++;
        if (buf_index >= BUF_SIZE){
          buf_index = 0;
          flags |= FLAG_ERR_RX;
        }
    }
}

 

9 минут назад, Yurkin2015 сказал:

Но затем приходит "\n" от плеера

Признак окончания приема на усмотрение @tifaso

Изменено пользователем korsaj
Ссылка на комментарий
Поделиться на другие сайты

@korsaj Поправил у себя в коде как ты написал.

Так вроде бы всё нормально, но как теперь проверять эти строки? То есть мне нужен пример самого условия на проверку строки буквенно цифровую как в плеере приём команды, а то как я не пытаюсь у меня кроме цифр от 0 до 9 ничего не принимает.

Изменено пользователем tifaso
Ссылка на комментарий
Поделиться на другие сайты

Да, все верно. Нужно теперь как-то сравнивать строки. Есть два варианта: библиотечной функцией; своей функцией. Для библиотечной - конец строки это нулевой байт. Для своей - на ваше усмотрение.

Ссылка на комментарий
Поделиться на другие сайты

33 минуты назад, korsaj сказал:
38 минут назад, Yurkin2015 сказал:

Но затем приходит "\n" от плеера

Признак окончания приема на усмотрение @tifaso

Как вариант вполне так можно использовать. И ещё я так понимаю полученную инфу нужно будет как то обрезать от всяких префиксов в начале и конце передачи при этом для каждого типа информации нужно делать это индивидуально.

Ссылка на комментарий
Поделиться на другие сайты

Если есть необходимость можно обрезать. Возможно даже сделать ветвление на основании префиксов.

Можно сделать функцию (она же есть и библиотечная) которая будет искать подстроку в строке. 

Давайте больше информации, тогда можно будет более конкретно советовать.

Ссылка на комментарий
Поделиться на другие сайты

4 минуты назад, korsaj сказал:

Нужно теперь как-то сравнивать строки. Есть два варианта: библиотечной функцией; своей функцией.

Вот здесь надеюсь поможешь. Вот из за чего и поднимался весь этот вопрос с UART что какой то приём тут не полноценный получился вначале. Это для меня очень сложно с функциями, а тем более библиотеками ещё сложней. Далеко не каждая библиотека встаёт в программу и начинаются ошибки в следствии этого.

Поэтому я конечно выберу вариант с функцией и без библиотек. Весь код в одном файле. Когда несколько файлов тоже какие то ошибки часто вылетают.

Ссылка на комментарий
Поделиться на другие сайты

Ну понятно, вам так проще, да и понимание что и как будет менее абстрактным.

У вас после приема есть массив символов rx_buf, представляющий собой строку, например: "AT+M2\r\n". Вам нужно эту строку сравнить с другой. Следовательно у вас будет функция, получающая два аргумента (массива строк). Один массив полученная строка, второй строка с которой нужно сравнить. Внутри функции вам нужно сравнивать байт за байтом, перебирая весь массив rx_buf и если все символы совпали вернуть из функции 1, если хоть один из символов не совпал, можно прерывать выполнение функции и возвращать 0.

Попробуйте реализовать этот алгоритм.

Ссылка на комментарий
Поделиться на другие сайты

48 минут назад, korsaj сказал:

Внутри функции вам нужно сравнивать байт за байтом, перебирая весь массив rx_buf и если все символы совпали вернуть из функции 1

Все сделали до нас - strcmp(str1,str2);

Ссылка на комментарий
Поделиться на другие сайты

2 hours ago, tifaso said:

К примеру при отправке команды AT+M1 \ r \ n

Ну, вот, посылаете команду номер трека в плеер:

send_UART('A');
send_UART('T');
send_UART('+');
send_UART('M');
send_UART('1');
send_UART(0x0D);
send_UART(0x0A);

Затем в while(1) ждёте ответа от плеера, проверяя флаг FLAG_END_RX.

Когда пришёл ответ, и флаг установился, в буфере rx_buf лежит нужная информация: в ячейках буфера с 3 по 8 лежит номер трека. Гасите флаг, проверяете, что ответ на команду "М1" и отправляете номер трека на индикаторы, например так:

if (flags & FLAG_END_RX)
{
    flags &= ~FLAG_END_RX;

    if((rx_buf[0] == 'M') && (rx_buf[1] == '1'))
    {
        rx_buf[6]    ->  индикатор сотен
        rx_buf[7]    ->  индикатор десятков
        rx_buf[8]    ->  индикатор единиц
    }
}

 

Изменено пользователем Yurkin2015
Ссылка на комментарий
Поделиться на другие сайты

9 минут назад, donec сказал:

Все сделали до нас - strcmp(str1,str2);

1 час назад, tifaso сказал:

Это для меня очень сложно с функциями, а тем более библиотеками ещё сложней.

 

Ссылка на комментарий
Поделиться на другие сайты

@Yurkin2015 Этот код по какой то причине не отрабатывает.

52 минуты назад, Yurkin2015 сказал:
if (flags & FLAG_END_RX)
{
    flags &= ~FLAG_END_RX;

    if((rx_buf[0] == 'M') && (rx_buf[1] == '1'))
    {
        rx_buf[6]    ->  индикатор сотен
        rx_buf[7]    ->  индикатор десятков
        rx_buf[8]    ->  индикатор единиц
    }
}

Хотя конечно логика данного кода мне вполне понятна.

Ссылка на комментарий
Поделиться на другие сайты

19 минут назад, tifaso сказал:

@Yurkin2015 Этот код по какой то причине не отрабатывает.

Это условно упрощенный

А вы ченить навояли?

Изменено пользователем korsaj
Ссылка на комментарий
Поделиться на другие сайты

@korsaj Ну согласно твоих слов и этот код примерно тоже самое и получается. Я и не вижу особых отличий. Но нужно только как то доработать чтоб оно работало. В том то всё и дело что оно не работает. А учитывая как раз таки что мне нужны будут определённые фрагменты где хранятся данные, то это очень хорошее решение, но нужно его доработать до рабочего состояния.

Изменено пользователем tifaso
Ссылка на комментарий
Поделиться на другие сайты

Мои слова ни как не относятся к тому куску кода

2 часа назад, korsaj сказал:

У вас после приема есть массив символов rx_buf, представляющий собой строку, например: "AT+M2\r\n". Вам нужно эту строку сравнить с другой. Следовательно у вас будет функция, получающая два аргумента (массива строк). Один массив полученная строка, второй строка с которой нужно сравнить. Внутри функции вам нужно сравнивать байт за байтом, перебирая весь массив rx_buf и если все символы совпали вернуть из функции 1, если хоть один из символов не совпал, можно прерывать выполнение функции и возвращать 0.

Знаете что такое функция, аргумент, результат?

Изменено пользователем korsaj
Ссылка на комментарий
Поделиться на другие сайты

@korsaj Так сейчас вчитывался ещё раз и ничего как то на ум так и не идёт. Сложновато получается. Данную функцию да тем более с массивами на сравнение я точно не осилю.

Ссылка на комментарий
Поделиться на другие сайты

rx_buf[0] == 'M'  - сравнение первого байта массива с константой (символ 'M')
rx_buf[0] == str[0]  - сравнение первого байта массива с первым байтом второго массива
rx_buf[i] == str[i]  - сравнение i-того байта массива с i-тым байтом второго массива

Ссылка на комментарий
Поделиться на другие сайты

Функция, например назовем ее cmpcmd сокращение comparison of commands. На вход данной функции передадим два аргумента (массива) str1, str2, а возвращать она нам будет 0 или 1, тогда имеем функцию:
char cmpcmd(char[] str1, char[] str2)

Теперь нужно внутри функции сравнивать два массива (в цикле), если хоть один элемент не совпал - возвращаем 0. Если перебрали все элементы (до появления символа перевода каретки) то возвращаем 1.  Попробуете написать? 

Ссылка на комментарий
Поделиться на другие сайты

9 минут назад, bulat943 сказал:

скорость самого модуля вы поставили 9600?

Да скорость в модуле я сразу переключил на 9600 при помощи терминала из компа.

 

Ссылка на комментарий
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.
Примечание: Ваш пост будет проверен модератором, прежде чем станет видимым.

Гость
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
Ответить в этой теме...

×   Вставлено с форматированием.   Восстановить форматирование

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

Загрузка...

×
×
  • Создать...