Нескольно простых вопросов о программировании AVR на Си.

Обсуждаем контроллеры компании Atmel.
REQW84
Родился
Сообщения: 5
Зарегистрирован: Пт дек 23, 2016 16:43:34

Re: Нескольно простых вопросов о программировании AVR на Си.

Сообщение REQW84 »

Уважаемые знатоки, объясните пожалуйста какая структура кода более "правильная", если так можно выразиться:
(Оба кода работают как надо)

Вариант 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;
			}
				

	};
}
Реклама
Аватара пользователя
hosturik
Потрогал лапой паяльник
Сообщения: 354
Зарегистрирован: Чт июл 24, 2014 23:09:23
Откуда: Киев

Re: Нескольно простых вопросов о программировании AVR на Си.

Сообщение hosturik »

Зря вы столько кода лишнего вставили. Тяжело анализировать
Спойлер

Код: Выделить всё

ПЕРВЫЙ ВАРИАНТ

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)
   { 
   }
}
Чисто мое мнение, не вижу никакого смысла использовать лишнюю функцию. Видел так делают, когда принимают или отправляют значение, так называемые геттеры и сеттеры, но это не тот случай.
Реклама
Аватара пользователя
COKPOWEHEU
Говорящий с текстолитом
Сообщения: 1525
Зарегистрирован: Чт июн 10, 2010 20:11:19

Re: Нескольно простых вопросов о программировании AVR на Си.

Сообщение COKPOWEHEU »

MCUCR=(1<<0)|(1<<1); //Прерывыание по ниспадающему форонту (с 1 на 0); ISC01=1, ISC00=1
Вот так писать не надо. Специально для наглядности кода существуют константы:
MCUCR = (1<<ISC01 | 1<<ISC00); // прерывание INT0 по спаду
Видел так делают, когда принимают или отправляют значение, так называемые геттеры и сеттеры, но это не тот случай.
Вроде как это делается для большей структуризации кода и некоторого увеличения его безопасности. В контроллерах, где идет прямое обращение к регистрам, это лишнее.
Аватара пользователя
*BoyKot*
Открыл глаза
Сообщения: 52
Зарегистрирован: Чт сен 05, 2013 11:01:55
Откуда: MoscowCity

Re: Нескольно простых вопросов о программировании AVR на Си.

Сообщение *BoyKot* »

небольшой вопрос по языку си (правда на примере регистров stm32). Для чего применяется запись uint32_t? Это какой-то намек на 32-разрядные числа? Вот пример, нужно сбросить бит в регистре:
RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_SW)); Для чего здесь первый раз применяется эта конструкция и для чего второй?
Реклама
Эиком - электронные компоненты и радиодетали
Аватара пользователя
Аlex
Модератор
Сообщения: 4614
Зарегистрирован: Чт мар 18, 2010 23:09:57
Откуда: Планета Земля
Контактная информация:

Re: Нескольно простых вопросов о программировании AVR на Си.

Сообщение Аlex »

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

Re: Нескольно простых вопросов о программировании AVR на Си.

Сообщение *BoyKot* »

[uquote="Аlex",url="/forum/viewtopic.php?p=3138500#p3138500"]uint32_t - unsigned integer 32-битный.
Не трудно догадаться, что этот тип применяется для целочисленных беззнаковых 32-битных переменных.[/uquote]
Т.е. uint_32t это тоже самое для программы, что unsigned int в объявлении переменных? Я всегда это подозревал. Но тогда как понять запись вида ((uint32_t)~(RCC_CFGR_SW))?
Реклама
Аватара пользователя
WiseLord
Друг Кота
Сообщения: 4905
Зарегистрирован: Чт апр 11, 2013 11:19:59
Откуда: Минск
Контактная информация:

Re: Нескольно простых вопросов о программировании AVR на Си.

Сообщение WiseLord »

Не совсем. unsigned int не везде 32-битный (в тех же AVR - 16-битный, например). Использование типов вроде uint32_t избавляет от необходимости помнить эти размеры в разных архитектурах, упрощает код и обеспечивает лучшую переносимость кода между разными платформами.

Собственно, то же и с приведением типов. Если имеем, к примеру, #define SOME 4, то (uint32_t)(~((uint32_t)SOME) гарантировано даст 32-битную инверсию 32-битной четвёрки, т.е., 0xFFFFFFFB. Тогда как, например, просто (uint32_t)(~SOME) вполне может дать результат 0x0000FFFB на некоторых архитектурах.
Аватара пользователя
*BoyKot*
Открыл глаза
Сообщения: 52
Зарегистрирован: Чт сен 05, 2013 11:01:55
Откуда: MoscowCity

Re: Нескольно простых вопросов о программировании AVR на Си.

Сообщение *BoyKot* »

[uquote="WiseLord",url="/forum/viewtopic.php?p=3138868#p3138868"]Не совсем. unsigned int не везде 32-битный (в тех же AVR - 16-битный, например). Использование типов вроде uint32_t избавляет от необходимости помнить эти размеры в разных архитектурах, упрощает код и обеспечивает лучшую переносимость кода между разными платформами.

Собственно, то же и с приведением типов. Если имеем, к примеру, #define SOME 4, то (uint32_t)(~((uint32_t)SOME) гарантировано даст 32-битную инверсию 32-битной четвёрки, т.е., 0xFFFFFFFB. Тогда как, например, просто (uint32_t)(~SOME) вполне может дать результат 0x0000FFFB на некоторых архитектурах.[/uquote]
Разобрался, спасибо.
Аватара пользователя
Vergilium
Грызет канифоль
Сообщения: 260
Зарегистрирован: Ср фев 13, 2008 14:41:32
Откуда: Украина, Николаев

Re: Нескольно простых вопросов о программировании AVR на Си.

Сообщение Vergilium »

Здравствуйте. Подскажите по поводу использования таймера в atmega8. Есть таймер 16 бит. Сконфигурирован таким образом чтобы на выход OCR1B в режиме fast PWM 9bit был меандр со скважностью 50%. Это для пищалки. Хочу использовать этот же таймер для прерывания по совпадению с OCR1A. Но МК не входит в прерывание. Я так понимаю не до тикивает до нужного значения TCNT1.
Можно ли вообще использовать часть таймера для генерации ШИМ и отсчета времени в прерывании?
Спасибо.
Немного нервов и девайс готов
Аватара пользователя
COKPOWEHEU
Говорящий с текстолитом
Сообщения: 1525
Зарегистрирован: Чт июн 10, 2010 20:11:19

Re: Нескольно простых вопросов о программировании AVR на Си.

Сообщение COKPOWEHEU »

Можно. Чтобы определить где в вашем коде ошибка, нужно его видеть.
Аватара пользователя
Vergilium
Грызет канифоль
Сообщения: 260
Зарегистрирован: Ср фев 13, 2008 14:41:32
Откуда: Украина, Николаев

Re: Нескольно простых вопросов о программировании AVR на Си.

Сообщение Vergilium »

Спойлер/*

#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); //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 раз.
Немного нервов и девайс готов
Аватара пользователя
Z_h_e
Собутыльник Кота
Сообщения: 2708
Зарегистрирован: Сб май 14, 2011 21:16:04
Откуда: г. Чайковский

Re: Нескольно простых вопросов о программировании AVR на Си.

Сообщение Z_h_e »

Код: Выделить всё

TIFR = 0; 
Бесполезная операция, флаги сбрасываются записью 1.

Код: Выделить всё

OCR1A = 0xEFFF; //Значение перегрузки таймера (30гц)
В ДШ, буружуйским по белому написано, что счетчик будет считать до 0x01FF в 9битном режиме, что логично, а не до регистра OCR.
Или уменьшайте OCR1A или используйте прерывание по переполнению таймера.
Изображение
Добро всегда побеждает зло. Поэтому кто победил - тот и добрый.
Аватара пользователя
hosturik
Потрогал лапой паяльник
Сообщения: 354
Зарегистрирован: Чт июл 24, 2014 23:09:23
Откуда: Киев

Re: Нескольно простых вопросов о программировании AVR на Си.

Сообщение hosturik »

Подскажите по передаче 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
Аватара пользователя
Siarzhuk
Потрогал лапой паяльник
Сообщения: 353
Зарегистрирован: Вс янв 19, 2014 22:41:55

Re: Нескольно простых вопросов о программировании AVR на Си.

Сообщение Siarzhuk »

[uquote="hosturik",url="/forum/viewtopic.php?p=3144731#p3144731"]Но дело в том, что там же нужно задавать размер этого самого буфера. Это хорошо если заранее знаешь размер передаваемых данных, а если нет, то как быть?[/uquote]
Выбрать его больше [либо равным] длины максимально возможной посылки, и перед помещением в него новой порции данных отслеживать состояние передатчика. Но в этом случае кольцевой буфер и не нужен. Либо перед помещением новой порции данных проверять наличие там места - буфер ведь кольцевой и передатчик его "обмолачивает" пока в нём что-то есть. А дело программы - подкидывать новые данные в хвост.

[uquote="hosturik",url="/forum/viewtopic.php?p=3144731#p3144731"]Можно как то заранее узнать количество передаваемых байт и потом задать нужный буфер?[/uquote]
буфера разного размера -> работа с динамическим выделением памяти -> передатчик должен отслеживать работу со списком буферов - кмк, заморочно получается.

[uquote="hosturik",url="/forum/viewtopic.php?p=3144731#p3144731"]Еще вычитал что есть функция sizeof() для массивов[/uquote]
Это не функция - а оператор определяющий размер содержимого в момент компиляции - т.е. во время работы программы это уже будет константа.

Это теория :) была, а по коду: добавьте в USART_PutChar и USART_SendStr возвращаемое значение bool для успеха попытки помещения в буффер и проверяйте его в своей программе - если "отослалось" успешно - забыли, если нет - повторите попытку послать попозже.
Одновременным нажатием LIGHT и POWER, РП Sangean ATS-909X (ver 1.29) превращается в ATS-909XR! ;-)
Аватара пользователя
hosturik
Потрогал лапой паяльник
Сообщения: 354
Зарегистрирован: Чт июл 24, 2014 23:09:23
Откуда: Киев

Re: Нескольно простых вопросов о программировании AVR на Си.

Сообщение hosturik »

[uquote="Siarzhuk",url="/forum/viewtopic.php?p=3144864#p3144864"]Выбрать его больше [либо равным] длины максимально возможной посылки, и перед помещением в него новой порции данных отслеживать состояние передатчика. Но в этом случае кольцевой буфер и не нужен. Либо перед помещением новой порции данных проверять наличие там места - буфер ведь кольцевой и передатчик его "обмолачивает" пока в нём что-то есть. А дело программы - подкидывать новые данные в хвост.[/uquote]
У меня видимо где-то в коде ошибка, буфер должен идеально соответствовать размеру передаваемых данных, ни больше ни меньше.
Если он больше, то получается фигня, данные дублируются, теряются.
Вот такое происходит (первая строка правильная)
СпойлерИзображение
Если было бы возможным задать размер буфера с запасом, то это для меня был бы отличный вариант. У меня задача для которой понадобилось два UART, нужно через определенные промежутки времени слать команды двум разным датчикам, а от одного еще и получать. Хотелось отказаться от программной реализации UART, которая довольно ресурсозатратна, вот и было решено оставить аппаратный и коммутировать одно или другое устройство . Команды разные размер их тоже разный и скорости передачи отличаются (57600 и 9600), вот в этом и сложность.
Аватара пользователя
Siarzhuk
Потрогал лапой паяльник
Сообщения: 353
Зарегистрирован: Вс янв 19, 2014 22:41:55

Re: Нескольно простых вопросов о программировании AVR на Си.

Сообщение Siarzhuk »

[uquote="hosturik",url="/forum/viewtopic.php?p=3145168#p3145168"]У меня видимо где-то в коде ошибка, буфер должен идеально соответствовать размеру передаваемых данных, ни больше ни меньше. Если он больше, то получается фигня, данные дублируются, теряются.[/uquote]
У вас буффер "хвостом" вперёд ползёт (что, впрочем, для МК безразлично). ;) А txCount - дублирующая сущность - высчитывайте количество неотправленых из разницы головы к хвосту (с учётом "заворота", конечно-же). Тем более что меняется txCount как в основном "потоке" так и в прерывании - начните с причисления его к Ордену Волатайла Приснопамятного. ;-)

[uquote="hosturik",url="/forum/viewtopic.php?p=3145168#p3145168"]У меня задача для которой понадобилось два UART, нужно через определенные промежутки времени слать команды двум разным датчикам, а от одного еще и получать. [....] вот и было решено оставить аппаратный и коммутировать одно или другое устройство.[/uquote]
Фишка кольцевого буфера в его асинхронной автономности - кидаем мясо в мясорубку, а котлеты с другой стороны аккуратно выпадают. Коммутация предполагает синхронизацию с тем фактом, что вся посылка к текущему адресату ушла (включая замыкающий байт!) - и не проще ли будет переключиться на обычный буффер - заряжать всегда его с нуля и не позволять преключаться пока передатчик в busy?
И да, "от одного ещё и получать" - синхронные ответы на команды? В противном случае - сами понимаете что будет. ;)
Одновременным нажатием LIGHT и POWER, РП Sangean ATS-909X (ver 1.29) превращается в ATS-909XR! ;-)
Аватара пользователя
hosturik
Потрогал лапой паяльник
Сообщения: 354
Зарегистрирован: Чт июл 24, 2014 23:09:23
Откуда: Киев

Re: Нескольно простых вопросов о программировании AVR на Си.

Сообщение hosturik »

[uquote="Siarzhuk",url="/forum/viewtopic.php?p=3145343#p3145343"]и не проще ли будет переключиться на обычный буффер[/uquote]
Обычный в смысле не кольцевой? А скорость будет такая же быстрая как с кольцевым?
Я просто всего пару месяцев изучаю МК так что особо не понимаю разницы.
Мне главное чтобы работало быстро. А то я сравнивал UART без прерываний (ожидание флага готовности), так отправка 60 байт занимала время МК на 8 миллисекунд, с прерываниями максимум 150 микросекунд, разница колоссальная.

А задумка такая подключаем первый датчик, отправляем ему команду получаем ответ, выводим эти данные на дисплей после обработки. Затем, через несколько секунд отключаем первый и подключаем второй датчик, отправляем ему данные, ответа от него не будет.
Затем через несколько секунд отключаем второй подключаем первый, шлем команду и т. д.
Аватара пользователя
Siarzhuk
Потрогал лапой паяльник
Сообщения: 353
Зарегистрирован: Вс янв 19, 2014 22:41:55

Re: Нескольно простых вопросов о программировании AVR на Си.

Сообщение Siarzhuk »

[uquote="hosturik",url="/forum/viewtopic.php?p=3145392#p3145392"]Обычный в смысле не кольцевой? А скорость будет такая же быстрая как с кольцевым?[/uquote]
Если теоретизировать - то зависит от задачи. Представьте себе, что лежите вы с пулемётом на огневом рубеже и лента у пулемёта закольцована. Подполз второй номер с цинком - набил в это кольцо десяток-другой патронов, разбудил вас сапогом в бок - нажали вы на спуск и пошла стрельба пока есть чем. Это кольцевой буфер. А линейный буфер - это если у пулемёта питание магазинное - то второй номер вам боеприпасы в виде этих самых магазинов подаёт, смена которых гарантировано ведёт к задержкам в стрельбе. В кольцевом-же - набивание патронов может производиться параллельно основному процессу и не задерживать процесс истребления басурманов. Но моментальная "скорострельность" в обоих случаях одинакова. А общая "скорострельность" да - для линейного будет слегка пониже. Но задача у вас ведь не непрерывное подавление огнём, при котором такие задержки критичны, а попеременное "отоваривание" двух целей фиксированным количеством пуль - где зарядка нового "магазина" во время переноса огня с одной цели на другую, не мешает выполнению основной задачи.
А UART что из кольцевого буфера, что из линейного будет данные кушать одинаково быстро. Кольцевой - лишь способ организации безостановочной отсылки данных. А линейный проще - зарядили, запустили и ждём пока всё не уйдёт.
Я бы убрал из программы head, tail, count, заведя вместо них один index, загружал каждую посылку в буффер с нулевого индекса и с того-же нулевого индекса и начинал отсылку. Буффер размером с максимально возможную посылку. Окончание передачи - index на байте, следующем за концом отсылаемых данных && состояние передатчика не BUSY.
Одновременным нажатием LIGHT и POWER, РП Sangean ATS-909X (ver 1.29) превращается в ATS-909XR! ;-)
Аватара пользователя
hosturik
Потрогал лапой паяльник
Сообщения: 354
Зарегистрирован: Чт июл 24, 2014 23:09:23
Откуда: Киев

Re: Нескольно простых вопросов о программировании AVR на Си.

Сообщение hosturik »

Спасибо большое. После такого объяснения с приведением аналогии я наконец-то понял как все работает.
Да пожалуй линейный буфер как раз для моего случая.
Аватара пользователя
ra9ust
Потрогал лапой паяльник
Сообщения: 375
Зарегистрирован: Чт июн 24, 2010 20:58:59

Re: Нескольно простых вопросов о программировании AVR на Си.

Сообщение ra9ust »

Да кодвижн самый лучший! Что тут говорить, по крайней мере для начинания.
Ответить

Вернуться в «AVR»