Например TDA7294

Форум РадиоКот • Просмотр темы - Нескольно простых вопросов о программировании AVR на Си.
Форум РадиоКот
Здесь можно немножко помяукать :)





Текущее время: Вт апр 23, 2024 14:59:40

Часовой пояс: UTC + 3 часа


ПРЯМО СЕЙЧАС:



Начать новую тему Ответить на тему  [ Сообщений: 1459 ]     ... , , , 33, , , ...  
Автор Сообщение
Не в сети
 Заголовок сообщения: Re: Нескольно простых вопросов о программировании AVR на Си.
СообщениеДобавлено: Пт июн 30, 2017 15:55:02 
Родился

Зарегистрирован: Пт дек 23, 2016 16:43:34
Сообщений: 5
Рейтинг сообщения: 0
Уважаемые знатоки, объясните пожалуйста какая структура кода более "правильная", если так можно выразиться:
(Оба кода работают как надо)

Вариант 1:
Спойлер
Код:
#include <avr/io.h> //Подключаем библиотеку AVR
#include <avr/iotn2313.h> //Подключаем библиотеку ATtiny2313
#include <avr/interrupt.h> //Подключаем библиотеку прерываний
#define F_CPU 1000000UL
#include <util/delay.h>

//Глобальные переменные сюда:
volatile unsigned char reg=0; //Переменная reg - режим

//Обработка прерывания по спаду напряжения на INT0
ISR(INT0_vect)
{
_delay_ms(10);
reg++; //при нажатии на кнопку Увеличиваем значение переменной reg на 1
if (reg==4) reg=0; //Если досчитали до 4, то reg=0
}

void INTinit()
{
GIMSK=(1<<6); //Разрешаем прерывание INT0
MCUCR=(1<<0)|(1<<1); //Прерывыание по ниспадающему форонту (с 1 на 0); ISC01=1, ISC00=1
}

int main (void)
{
DDRB=(1<<0)|(1<<1)|(1<<2)|(1<<3)|(1<<4)|(1<<5)|(1<<6)|(1<<7); //Порт В на ВЫХод

PORTD=(1<<2); //Порт PD2 Подтягивающий резистор ВКлючен

INTinit();   // вызываем функцию инициализации прерываний
sei();   //Глобальное разрешение прерываний

   while (1)
   {
      switch(reg)
         {

            case 1:
               PORTB=(1<<0);
               break;
            case 2:
               PORTB=(1<<1);
               break;
            case 3:
               PORTB=(1<<2);
               break;
            default:
               PORTB=0;
         }
            

   };
}


Вариант 2:
Спойлер
Код:
#include <avr/io.h> //Подключаем библиотеку AVR
#include <avr/iotn2313.h> //Подключаем библиотеку ATtiny2313
#include <avr/interrupt.h> //Подключаем библиотеку прерываний
#define F_CPU 1000000UL
#include <util/delay.h>

//Глобальные переменные сюда:
volatile unsigned char reg=0; //Переменная reg - режим

//Обработка прерывания по спаду напряжения на INT0
ISR(INT0_vect)
{
_delay_ms(10);
reg++; //при нажатии на кнопку Увеличиваем значение переменной reg на 1
if (reg==4) reg=0; //Если досчитали до 4, то reg=0
}

int main (void)
{
DDRB=(1<<0)|(1<<1)|(1<<2)|(1<<3)|(1<<4)|(1<<5)|(1<<6)|(1<<7); //Порт В на ВЫХод

PORTD=(1<<2); //Порт PD2 Подтягивающий резистор ВКлючен

GIMSK=(1<<6); //Разрешаем прерывание INT0
MCUCR=(1<<0)|(1<<1); //Прерывыание по ниспадающему форонту (с 1 на 0); ISC01=1, ISC00=1

sei();   //Глобальное разрешение прерываний

   while (1)
   {
      switch(reg)
         {

            case 1:
               PORTB=(1<<0);
               break;
            case 2:
               PORTB=(1<<1);
               break;
            case 3:
               PORTB=(1<<2);
               break;
            default:
               PORTB=0;
         }
            

   };
}


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: Нескольно простых вопросов о программировании AVR на Си.
СообщениеДобавлено: Пн июл 03, 2017 22:43:35 
Потрогал лапой паяльник
Аватар пользователя

Карма: 3
Рейтинг сообщений: 87
Зарегистрирован: Чт июл 24, 2014 23:09:23
Сообщений: 354
Откуда: Киев
Рейтинг сообщения: 0
Зря вы столько кода лишнего вставили. Тяжело анализировать
Спойлер
Код:
ПЕРВЫЙ ВАРИАНТ

void INTinit()
{
GIMSK=(1<<6); //Разрешаем прерывание INT0
MCUCR=(1<<0)|(1<<1); //Прерывыание по ниспадающему форонту (с 1 на 0); ISC01=1, ISC00=1
}
int main (void)
{
INTinit();   // вызываем функцию инициализации прерываний
sei();   //Глобальное разрешение прерываний
   while (1)
   {
   }
}

ВТОРОЙ ВАРИАНТ

int main (void)
{
GIMSK=(1<<6); //Разрешаем прерывание INT0
MCUCR=(1<<0)|(1<<1); //Прерывыание по ниспадающему форонту (с 1 на 0); ISC01=1, ISC00=1
sei();   //Глобальное разрешение прерываний
   while (1)
   {
   }
}

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


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: Нескольно простых вопросов о программировании AVR на Си.
СообщениеДобавлено: Пн июл 03, 2017 23:22:37 
Это не хвост, это антенна
Аватар пользователя

Карма: 8
Рейтинг сообщений: 193
Зарегистрирован: Чт июн 10, 2010 20:11:19
Сообщений: 1441
Рейтинг сообщения: 0
Цитата:
MCUCR=(1<<0)|(1<<1); //Прерывыание по ниспадающему форонту (с 1 на 0); ISC01=1, ISC00=1
Вот так писать не надо. Специально для наглядности кода существуют константы:
MCUCR = (1<<ISC01 | 1<<ISC00); // прерывание INT0 по спаду
Цитата:
Видел так делают, когда принимают или отправляют значение, так называемые геттеры и сеттеры, но это не тот случай.
Вроде как это делается для большей структуризации кода и некоторого увеличения его безопасности. В контроллерах, где идет прямое обращение к регистрам, это лишнее.


Вернуться наверх
 
PCBWay - всего $5 за 10 печатных плат, первый заказ для новых клиентов БЕСПЛАТЕН

Сборка печатных плат от $30 + БЕСПЛАТНАЯ доставка по всему миру + трафарет

Онлайн просмотровщик Gerber-файлов от PCBWay + Услуги 3D печати
Не в сети
 Заголовок сообщения: Re: Нескольно простых вопросов о программировании AVR на Си.
СообщениеДобавлено: Вт июл 04, 2017 16:17:09 
Открыл глаза
Аватар пользователя

Зарегистрирован: Чт сен 05, 2013 11:01:55
Сообщений: 52
Откуда: MoscowCity
Рейтинг сообщения: 0
небольшой вопрос по языку си (правда на примере регистров stm32). Для чего применяется запись uint32_t? Это какой-то намек на 32-разрядные числа? Вот пример, нужно сбросить бит в регистре:
RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_SW)); Для чего здесь первый раз применяется эта конструкция и для чего второй?


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

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

Подробнее>>
Не в сети
 Заголовок сообщения: Re: Нескольно простых вопросов о программировании AVR на Си.
СообщениеДобавлено: Вт июл 04, 2017 18:38:16 
Модератор
Аватар пользователя

Карма: 90
Рейтинг сообщений: 1289
Зарегистрирован: Чт мар 18, 2010 23:09:57
Сообщений: 4510
Откуда: Планета Земля
Рейтинг сообщения: 0
Медали: 1
Получил миской по аватаре (1)
Цитата:
Для чего применяется запись uint32_t?
uint32_t - unsigned integer 32-битный.
Не трудно догадаться, что этот тип применяется для целочисленных беззнаковых 32-битных переменных.


Вернуться наверх
 
Новый аккумулятор EVE серии PLM для GSM-трекеров, работающих в жёстких условиях (до -40°С)

Компания EVE выпустила новый аккумулятор серии PLM, сочетающий в себе высокую безопасность, длительный срок службы, широкий температурный диапазон и высокую токоотдачу даже при отрицательной температуре. Эти аккумуляторы поддерживают заряд при температуре от -40/-20°С (сниженным значением тока), безопасны (не воспламеняются и не взрываются) при механическом повреждении (протыкание и сдавливание), устойчивы к вибрации. Они могут применяться как для автотранспорта (трекеры, маячки, сигнализация), так и для промышленных устройств мониторинга, IoT-устройств.

Подробнее>>
Не в сети
 Заголовок сообщения: Re: Нескольно простых вопросов о программировании AVR на Си.
СообщениеДобавлено: Ср июл 05, 2017 09:49:30 
Открыл глаза
Аватар пользователя

Зарегистрирован: Чт сен 05, 2013 11:01:55
Сообщений: 52
Откуда: MoscowCity
Рейтинг сообщения: 0
uint32_t - unsigned integer 32-битный.
Не трудно догадаться, что этот тип применяется для целочисленных беззнаковых 32-битных переменных.

Т.е. uint_32t это тоже самое для программы, что unsigned int в объявлении переменных? Я всегда это подозревал. Но тогда как понять запись вида ((uint32_t)~(RCC_CFGR_SW))?


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: Нескольно простых вопросов о программировании AVR на Си.
СообщениеДобавлено: Ср июл 05, 2017 10:27:48 
Друг Кота
Аватар пользователя

Карма: 86
Рейтинг сообщений: 1018
Зарегистрирован: Чт апр 11, 2013 11:19:59
Сообщений: 4875
Откуда: Минск
Рейтинг сообщения: 1
Не совсем. unsigned int не везде 32-битный (в тех же AVR - 16-битный, например). Использование типов вроде uint32_t избавляет от необходимости помнить эти размеры в разных архитектурах, упрощает код и обеспечивает лучшую переносимость кода между разными платформами.

Собственно, то же и с приведением типов. Если имеем, к примеру, #define SOME 4, то (uint32_t)(~((uint32_t)SOME) гарантировано даст 32-битную инверсию 32-битной четвёрки, т.е., 0xFFFFFFFB. Тогда как, например, просто (uint32_t)(~SOME) вполне может дать результат 0x0000FFFB на некоторых архитектурах.


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: Нескольно простых вопросов о программировании AVR на Си.
СообщениеДобавлено: Ср июл 05, 2017 11:12:06 
Открыл глаза
Аватар пользователя

Зарегистрирован: Чт сен 05, 2013 11:01:55
Сообщений: 52
Откуда: MoscowCity
Рейтинг сообщения: 0
Не совсем. unsigned int не везде 32-битный (в тех же AVR - 16-битный, например). Использование типов вроде uint32_t избавляет от необходимости помнить эти размеры в разных архитектурах, упрощает код и обеспечивает лучшую переносимость кода между разными платформами.

Собственно, то же и с приведением типов. Если имеем, к примеру, #define SOME 4, то (uint32_t)(~((uint32_t)SOME) гарантировано даст 32-битную инверсию 32-битной четвёрки, т.е., 0xFFFFFFFB. Тогда как, например, просто (uint32_t)(~SOME) вполне может дать результат 0x0000FFFB на некоторых архитектурах.

Разобрался, спасибо.


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: Нескольно простых вопросов о программировании AVR на Си.
СообщениеДобавлено: Ср июл 12, 2017 10:00:34 
Грызет канифоль
Аватар пользователя

Зарегистрирован: Ср фев 13, 2008 14:41:32
Сообщений: 260
Откуда: Украина, Николаев
Рейтинг сообщения: 0
Здравствуйте. Подскажите по поводу использования таймера в atmega8. Есть таймер 16 бит. Сконфигурирован таким образом чтобы на выход OCR1B в режиме fast PWM 9bit был меандр со скважностью 50%. Это для пищалки. Хочу использовать этот же таймер для прерывания по совпадению с OCR1A. Но МК не входит в прерывание. Я так понимаю не до тикивает до нужного значения TCNT1.
Можно ли вообще использовать часть таймера для генерации ШИМ и отсчета времени в прерывании?
Спасибо.

_________________
Немного нервов и девайс готов


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: Нескольно простых вопросов о программировании AVR на Си.
СообщениеДобавлено: Ср июл 12, 2017 10:16:21 
Это не хвост, это антенна
Аватар пользователя

Карма: 8
Рейтинг сообщений: 193
Зарегистрирован: Чт июн 10, 2010 20:11:19
Сообщений: 1441
Рейтинг сообщения: 0
Можно. Чтобы определить где в вашем коде ошибка, нужно его видеть.


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: Нескольно простых вопросов о программировании AVR на Си.
СообщениеДобавлено: Ср июл 12, 2017 10:26:17 
Грызет канифоль
Аватар пользователя

Зарегистрирован: Ср фев 13, 2008 14:41:32
Сообщений: 260
Откуда: Украина, Николаев
Рейтинг сообщения: 0
Спойлер/*

#include <avr/io.h>
#include <util/delay.h>
#include <stdio.h>
#include <avr/interrupt.h>
#include "uart.h"

#include "MFRC522.h"


#define RX_ENABLE PORTD |= _BV(PD2); _delay_ms(1)
#define TX_ENABLE PORTD &= ~(_BV(PD2)); _delay_ms(1)
#define GREENLED_OFF PORTC |= _BV(PC3)
#define GREENLED_ON PORTC &= ~(_BV(PC3))
#define REDLED_OFF PORTC |= _BV(PC2)
#define REDLED_ON PORTC &= ~(_BV(PC2))

#define STARTDEV 1
#define REEDOK 2

#define BEEP_ON cli(); OCR1B = 0x00FF; sei()
#define BEEP_OFF cli(); OCR1B = 0x01FF; sei()

#define RXUBRR (F_CPU/16/9600)-1
#define BUFFER_SIZE 2
//#define UART_RX0_BUFFER_SIZE 3

char buffer[BUFFER_SIZE];
volatile uint8_t delay_count = 0; //задержка для таймера 1, для бипера (30 = 1сек)

void indicate (uint8_t event){
switch(event){
case STARTDEV : BEEP_ON;
GREENLED_ON;
delay_count = 15; break;
// REEDOK :
default: break;
}


}

ISR(TIMER1_COMPA_vect){ // Прерывание отсчета времени
TCNT1 = 0;
if (delay_count > 1){
delay_count--;
} else if (delay_count) {
GREENLED_OFF;
BEEP_OFF;
delay_count = 0;
}
}

int main(void)
{
uchar card_num[5];
uchar i;
//== Init============
DDRD = 0b00000100;
PORTD = 0b11111100;
DDRC = 0b00001100;
PORTC = 0b00101100;
DDRB = 0b00000100;
PORTB = 0b00000111;
//== Init===========
TIMSK = (1<<OCIE1A); //Прерывание по пререполнению таймера 1 (30Гц)
//== 1 16bit Init====
TCCR1A = (1<<COM1B1)|(1<<COM1B0)|(1<<WGM12)|(1<<WGM11); //Fast PWM 9bit на выводе OC1B (частота 3600Гц)
OCR1B = 0x00FF; //Устанавливаем скважность 50%
OCR1A = 0xEFFF; //Значение перегрузки таймера (30гц)
TIFR = 0;
TCCR1B = (1<<CS11); //Делитель частоты на 8, запуск таймера
//======
sei();
uart_init(RXUBRR); //UART Init
MFRC522_Init(); //NFC Init
indicate(STARTDEV);

while (1)
{
_delay_ms(500);
if ( MFRC522_Request( PICC_REQIDL, card_num ) == MI_OK ) {
if ( MFRC522_Anticoll( card_num ) == MI_OK ) {
TX_ENABLE;
GREENLED_ON;
uart_puts("CN"); //Последовательность о передаче номера карты
for (i = 0; i < 5; i++ ) {
uart_putc(card_num[i]); //5 байт номера кары
}
uart_puts("\r"); //Символ конца строки
RX_ENABLE;
GREENLED_OFF;
}
}
}
}

Заметил ошибку в инициализации таймера TCCR1A = (1<<COM1B1)|(1<<COM1B0)|(1<<WGM12)|(1<<WGM11);
WGM12 находится в другом регистре. Исправил на TCCR1A = (1<<COM1B1)|(1<<COM1B0)|(1<<WGM11); TCCR1B = (1<<WGM12);
Проблема остается

ШИМ работает в 9ти битном режиме, т.е. максимальное число это 0х01FF (511). Таймер дотикивает до 511ти и сбрасывается?

_________________
Немного нервов и девайс готов


Последний раз редактировалось Vergilium Ср июл 12, 2017 11:38:50, всего редактировалось 1 раз.

Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: Нескольно простых вопросов о программировании AVR на Си.
СообщениеДобавлено: Ср июл 12, 2017 11:38:13 
Собутыльник Кота
Аватар пользователя

Карма: 29
Рейтинг сообщений: 645
Зарегистрирован: Сб май 14, 2011 21:16:04
Сообщений: 2694
Откуда: г. Чайковский
Рейтинг сообщения: 0
Медали: 1
Получил миской по аватаре (1)
Код:
TIFR = 0;
Бесполезная операция, флаги сбрасываются записью 1.
Код:
OCR1A = 0xEFFF; //Значение перегрузки таймера (30гц)
В ДШ, буружуйским по белому написано, что счетчик будет считать до 0x01FF в 9битном режиме, что логично, а не до регистра OCR.
Или уменьшайте OCR1A или используйте прерывание по переполнению таймера.

_________________
Изображение
Добро всегда побеждает зло. Поэтому кто победил - тот и добрый.


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: Нескольно простых вопросов о программировании AVR на Си.
СообщениеДобавлено: Пт июл 14, 2017 09:19:32 
Потрогал лапой паяльник
Аватар пользователя

Карма: 3
Рейтинг сообщений: 87
Зарегистрирован: Чт июл 24, 2014 23:09:23
Сообщений: 354
Откуда: Киев
Рейтинг сообщения: 0
Подскажите по передаче UART с помощью кольцевого буфера и на прерываниях. В принципе все работает хорошо и очень быстро. Но дело в том, что там же нужно задавать размер этого самого буфера. Это хорошо если заранее знаешь размер передаваемых данных, а если нет, то как быть? Можно как то заранее узнать количество передаваемых байт и потом задать нужный буфер?
Есть только одна мысль, сначала поместить эту строку во временный массив, пройтись циклом, пока не закончаться значения в массиве, инкрементируя при этом счетчик, вот он и будет размером буфера. Не знаю насколько это правильно.
Еще вычитал что есть функция sizeof() для массивов
Спойлер
Код:
//         UART.c

#include "usart.h"

//передающий буфер
unsigned char usartTxBuf[SIZE_BUF];
unsigned char txBufTail = 0;
unsigned char txBufHead = 0;
unsigned char txCount = 0;

void uart_init( void )            //функция инициализации UART
{
  //настройка скорости обмена
  UBRR0H = 0;
  UBRR0L = 15;  // скорость 57600 для 14 745 600
  //разрешить прием и передачу данных
  UCSR0B = (1<<TXCIE0)|(1<<TXEN0); //включаем прерывание по передаче и саму передачу
  //8 бит данных, 1 стоп бит, без контроля четности
  UCSR0C = (1<<UCSZ01) | (1<<UCSZ00);
 
}
//передача
//возвращает колличество символов передающего буфера
unsigned char USART_GetTxCount(void)
{
  return txCount; 
}

//"очищает" передающий буфер
void USART_FlushTxBuf(void)
{
  txBufTail = 0;
  txCount = 0;
  txBufHead = 0;
}

//помещает символ в буфер, инициирует начало передачи
void USART_PutChar(unsigned char sym)
{
  //если модуль usart свободен и это первый символ
  //пишем его прямо в регистр UDR
  if(((UCSR0A & (1<<UDRE0)) != 0) && (!txCount))
  {
   UDR0 = sym;
  }
  else
  {
    if (txCount < SIZE_BUF) //если в буфере еще есть место
   {   
      usartTxBuf[txBufTail] = sym; //помещаем в него символ
      txCount++;                   //инкрементируем счетчик символов
      txBufTail++;                 //и индекс хвоста буфера
      if (txBufTail == SIZE_BUF)
     {
      txBufTail = 0;
     }
    }
  }
}
 
//функция отправки строки
void USART_SendStr(char * data)
{
  unsigned char sym;
  while(*data){
    sym = *data++;
    USART_PutChar(sym);
  }
}

//обработчик прерывания по завершению передачи
ISR(USART_TX_vect)
{
  if (txCount > 0) //если буфер не пустой
  {             
    UDR0 = usartTxBuf[txBufHead]; //записываем в UDR символ из буфера
    txCount--;                   //уменьшаем счетчик символов
    txBufHead++;                 //инкрементируем индекс головы буфера
    if (txBufHead == SIZE_BUF)
   {
    USART_FlushTxBuf();
   }   
  }
}


//         USART.H


#ifndef USART_H
#define USART_H

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

//размер буфера
#define SIZE_BUF 65

void uart_init( void );
unsigned char USART_GetTxCount(void); //взять число символов передающего буфера
void USART_FlushTxBuf(void); //очистить передающий буфер
void USART_PutChar(unsigned char sym); //положить символ в буфер
void USART_SendStr(char * data); //послать строку по usart`у


#endif //USART_H


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: Нескольно простых вопросов о программировании AVR на Си.
СообщениеДобавлено: Пт июл 14, 2017 12:58:17 
Потрогал лапой паяльник
Аватар пользователя

Карма: 20
Рейтинг сообщений: 121
Зарегистрирован: Вс янв 19, 2014 22:41:55
Сообщений: 353
Рейтинг сообщения: 5
Но дело в том, что там же нужно задавать размер этого самого буфера. Это хорошо если заранее знаешь размер передаваемых данных, а если нет, то как быть?

Выбрать его больше [либо равным] длины максимально возможной посылки, и перед помещением в него новой порции данных отслеживать состояние передатчика. Но в этом случае кольцевой буфер и не нужен. Либо перед помещением новой порции данных проверять наличие там места - буфер ведь кольцевой и передатчик его "обмолачивает" пока в нём что-то есть. А дело программы - подкидывать новые данные в хвост.

Можно как то заранее узнать количество передаваемых байт и потом задать нужный буфер?

буфера разного размера -> работа с динамическим выделением памяти -> передатчик должен отслеживать работу со списком буферов - кмк, заморочно получается.

Еще вычитал что есть функция sizeof() для массивов

Это не функция - а оператор определяющий размер содержимого в момент компиляции - т.е. во время работы программы это уже будет константа.

Это теория :) была, а по коду: добавьте в USART_PutChar и USART_SendStr возвращаемое значение bool для успеха попытки помещения в буффер и проверяйте его в своей программе - если "отослалось" успешно - забыли, если нет - повторите попытку послать попозже.

_________________
Одновременным нажатием LIGHT и POWER, РП Sangean ATS-909X (ver 1.29) превращается в ATS-909XR! ;-)


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: Нескольно простых вопросов о программировании AVR на Си.
СообщениеДобавлено: Пт июл 14, 2017 22:13:55 
Потрогал лапой паяльник
Аватар пользователя

Карма: 3
Рейтинг сообщений: 87
Зарегистрирован: Чт июл 24, 2014 23:09:23
Сообщений: 354
Откуда: Киев
Рейтинг сообщения: 0
Выбрать его больше [либо равным] длины максимально возможной посылки, и перед помещением в него новой порции данных отслеживать состояние передатчика. Но в этом случае кольцевой буфер и не нужен. Либо перед помещением новой порции данных проверять наличие там места - буфер ведь кольцевой и передатчик его "обмолачивает" пока в нём что-то есть. А дело программы - подкидывать новые данные в хвост.

У меня видимо где-то в коде ошибка, буфер должен идеально соответствовать размеру передаваемых данных, ни больше ни меньше.
Если он больше, то получается фигня, данные дублируются, теряются.
Вот такое происходит (первая строка правильная)
СпойлерИзображение

Если было бы возможным задать размер буфера с запасом, то это для меня был бы отличный вариант. У меня задача для которой понадобилось два UART, нужно через определенные промежутки времени слать команды двум разным датчикам, а от одного еще и получать. Хотелось отказаться от программной реализации UART, которая довольно ресурсозатратна, вот и было решено оставить аппаратный и коммутировать одно или другое устройство . Команды разные размер их тоже разный и скорости передачи отличаются (57600 и 9600), вот в этом и сложность.


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: Нескольно простых вопросов о программировании AVR на Си.
СообщениеДобавлено: Сб июл 15, 2017 11:42:19 
Потрогал лапой паяльник
Аватар пользователя

Карма: 20
Рейтинг сообщений: 121
Зарегистрирован: Вс янв 19, 2014 22:41:55
Сообщений: 353
Рейтинг сообщения: 2
У меня видимо где-то в коде ошибка, буфер должен идеально соответствовать размеру передаваемых данных, ни больше ни меньше. Если он больше, то получается фигня, данные дублируются, теряются.

У вас буффер "хвостом" вперёд ползёт (что, впрочем, для МК безразлично). ;) А txCount - дублирующая сущность - высчитывайте количество неотправленых из разницы головы к хвосту (с учётом "заворота", конечно-же). Тем более что меняется txCount как в основном "потоке" так и в прерывании - начните с причисления его к Ордену Волатайла Приснопамятного. ;-)

У меня задача для которой понадобилось два UART, нужно через определенные промежутки времени слать команды двум разным датчикам, а от одного еще и получать. [....] вот и было решено оставить аппаратный и коммутировать одно или другое устройство.

Фишка кольцевого буфера в его асинхронной автономности - кидаем мясо в мясорубку, а котлеты с другой стороны аккуратно выпадают. Коммутация предполагает синхронизацию с тем фактом, что вся посылка к текущему адресату ушла (включая замыкающий байт!) - и не проще ли будет переключиться на обычный буффер - заряжать всегда его с нуля и не позволять преключаться пока передатчик в busy?
И да, "от одного ещё и получать" - синхронные ответы на команды? В противном случае - сами понимаете что будет. ;)

_________________
Одновременным нажатием LIGHT и POWER, РП Sangean ATS-909X (ver 1.29) превращается в ATS-909XR! ;-)


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: Нескольно простых вопросов о программировании AVR на Си.
СообщениеДобавлено: Сб июл 15, 2017 13:33:07 
Потрогал лапой паяльник
Аватар пользователя

Карма: 3
Рейтинг сообщений: 87
Зарегистрирован: Чт июл 24, 2014 23:09:23
Сообщений: 354
Откуда: Киев
Рейтинг сообщения: 0
и не проще ли будет переключиться на обычный буффер

Обычный в смысле не кольцевой? А скорость будет такая же быстрая как с кольцевым?
Я просто всего пару месяцев изучаю МК так что особо не понимаю разницы.
Мне главное чтобы работало быстро. А то я сравнивал UART без прерываний (ожидание флага готовности), так отправка 60 байт занимала время МК на 8 миллисекунд, с прерываниями максимум 150 микросекунд, разница колоссальная.

А задумка такая подключаем первый датчик, отправляем ему команду получаем ответ, выводим эти данные на дисплей после обработки. Затем, через несколько секунд отключаем первый и подключаем второй датчик, отправляем ему данные, ответа от него не будет.
Затем через несколько секунд отключаем второй подключаем первый, шлем команду и т. д.


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: Нескольно простых вопросов о программировании AVR на Си.
СообщениеДобавлено: Сб июл 15, 2017 14:38:30 
Потрогал лапой паяльник
Аватар пользователя

Карма: 20
Рейтинг сообщений: 121
Зарегистрирован: Вс янв 19, 2014 22:41:55
Сообщений: 353
Рейтинг сообщения: 2
Обычный в смысле не кольцевой? А скорость будет такая же быстрая как с кольцевым?

Если теоретизировать - то зависит от задачи. Представьте себе, что лежите вы с пулемётом на огневом рубеже и лента у пулемёта закольцована. Подполз второй номер с цинком - набил в это кольцо десяток-другой патронов, разбудил вас сапогом в бок - нажали вы на спуск и пошла стрельба пока есть чем. Это кольцевой буфер. А линейный буфер - это если у пулемёта питание магазинное - то второй номер вам боеприпасы в виде этих самых магазинов подаёт, смена которых гарантировано ведёт к задержкам в стрельбе. В кольцевом-же - набивание патронов может производиться параллельно основному процессу и не задерживать процесс истребления басурманов. Но моментальная "скорострельность" в обоих случаях одинакова. А общая "скорострельность" да - для линейного будет слегка пониже. Но задача у вас ведь не непрерывное подавление огнём, при котором такие задержки критичны, а попеременное "отоваривание" двух целей фиксированным количеством пуль - где зарядка нового "магазина" во время переноса огня с одной цели на другую, не мешает выполнению основной задачи.
А UART что из кольцевого буфера, что из линейного будет данные кушать одинаково быстро. Кольцевой - лишь способ организации безостановочной отсылки данных. А линейный проще - зарядили, запустили и ждём пока всё не уйдёт.
Я бы убрал из программы head, tail, count, заведя вместо них один index, загружал каждую посылку в буффер с нулевого индекса и с того-же нулевого индекса и начинал отсылку. Буффер размером с максимально возможную посылку. Окончание передачи - index на байте, следующем за концом отсылаемых данных && состояние передатчика не BUSY.

_________________
Одновременным нажатием LIGHT и POWER, РП Sangean ATS-909X (ver 1.29) превращается в ATS-909XR! ;-)


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: Нескольно простых вопросов о программировании AVR на Си.
СообщениеДобавлено: Сб июл 15, 2017 17:12:32 
Потрогал лапой паяльник
Аватар пользователя

Карма: 3
Рейтинг сообщений: 87
Зарегистрирован: Чт июл 24, 2014 23:09:23
Сообщений: 354
Откуда: Киев
Рейтинг сообщения: 0
Спасибо большое. После такого объяснения с приведением аналогии я наконец-то понял как все работает.
Да пожалуй линейный буфер как раз для моего случая.


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: Нескольно простых вопросов о программировании AVR на Си.
СообщениеДобавлено: Ср авг 02, 2017 19:45:45 
Потрогал лапой паяльник
Аватар пользователя

Зарегистрирован: Чт июн 24, 2010 20:58:59
Сообщений: 375
Рейтинг сообщения: 0
Да кодвижн самый лучший! Что тут говорить, по крайней мере для начинания.


Вернуться наверх
 
Показать сообщения за:  Сортировать по:  Вернуться наверх
Начать новую тему Ответить на тему  [ Сообщений: 1459 ]     ... , , , 33, , , ...  

Часовой пояс: UTC + 3 часа


Кто сейчас на форуме

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 51


Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете добавлять вложения

Найти:
Перейти:  


Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group
Русская поддержка phpBB
Extended by Karma MOD © 2007—2012 m157y
Extended by Topic Tags MOD © 2012 m157y