roboforum.ru

Технический форум по робототехнике.


CodeVisionAVR - версия 2!

Программирование микроконтроллеров AVR, PIC, ARM.
Разработка и изготовление печатных плат для модулей.

Re: CodeVisionAVR - версия 2!

Сообщение elmot » 24 июн 2013, 03:51

Коллизия будет. Так что аккуратнее со множественным доступом. гуглить "запрет прерываний", "критическая секция", "volatile".
Аватара пользователя
elmot
 
Сообщения: 5691
Зарегистрирован: 10 ноя 2011, 12:02
Откуда: Turku, Finland
Skype: elmot73
прог. языки: Java и все-все=все
ФИО: Илья

Re: CodeVisionAVR - версия 2!

Сообщение RoboHobbyRu » 24 июн 2013, 05:33

Korbofos писал(а):Ещё небольшой вопрос. Что будет если в основном цикле изменяем значение переменной или регистра, и в этот момент попытаемся изменить значение этой переменной в прерывании?
в таких ситуациях нужно использовать следующий подход:
1) если "ширина" переменной не превышает ширину шины данных (для AVR - 8 бит, т.е. один байт), то достаточно при объявлении переменной сказать компилятору, что переменная ненадёжна (может изменить своё состояние незаметно для компилятора), с помощью ключевого свойства volatile:
Код: Выделить всёРазвернуть
char regularVar; // рядовая переменная типа char
volatile char interruptableVar; // переменная типа char, которая "ненадёжна" для компилятора


2) если "ширина" переменной превышает ширину шины данных, то такая переменная читается АЛУ в несколько заходов, сначала одна часть (один байт для AVR), затем вторая часть, ... Такую переменную, кроме пометки по пункту 1 требуется защитить от прерываний запрещая/разрешая их (например глобально):
Код: Выделить всёРазвернуть
volatile int interruptableVar; // переменная типа int

// не защищённый вариант
interruptableVar = 24;

// защищённый вариант
cli(); // запрет прерываний
interruptableVar = 24;
sei(); // разрешение прерываний
RoboHobbyRu
 
Сообщения: 203
Зарегистрирован: 04 май 2013, 10:35
Откуда: Тюмень

Re: CodeVisionAVR - версия 2!

Сообщение Korbofos » 24 июн 2013, 13:29

А если речь идёт о кольцевом буфере достаточно объявить переменную rx_count volatile?
Или надо отменить ещё прерывания? Когда читаю данные из буфера?
Код: Выделить всёРазвернуть
interrupt [USART1_RXC] void usart1_rx_isr(void)
{
if(rx_count < SIZE_BUF)
  {                                 
   rx_buf[rx_in++] = UDR1;       
   if(rx_in == SIZE_BUF)rx_in = 0; 
   rx_count++;                                 
  }
}

unsigned char read (void)
{
unsigned char data;
while(!rx_count);bin
data=rx_buf[rx_out++];
rx_count--;
if(rx_out == SIZE_BUF) rx_out=0;
//------Debag----------
Led(rx,ON);
led_rx_count=1;
//---------------------
return data;
}

Уже замучился, не на все запросы отвечает контроллер по уарту. Вещал диод на переполнение буфера, срабатывания не было.

Добавлено спустя 35 минут 18 секунд:
Вот проект, кому не лень посмотрите пожалуйста, какие косяки в коде есть. Проблема в потере данных по уарту :cry:
Вложения
ADC_Debag.rar
(155.66 КиБ) Скачиваний: 0
РАБОТА, РАБОТА перейди на Федота, с Федота на его брата, а ко мне их зарплата.
Аватара пользователя
Korbofos
 
Сообщения: 317
Зарегистрирован: 15 янв 2011, 11:27
Откуда: Челябинск
прог. языки: C/C++
ФИО: Александр

Re: CodeVisionAVR - версия 2!

Сообщение RoboHobbyRu » 24 июн 2013, 17:54

Korbofos писал(а):Или надо отменить ещё прерывания? Когда читаю данные из буфера?

Да, надо. Т.к. буфер - это массив данных он не может читаться/писаться за один присест

Добавлено спустя 24 минуты 59 секунд:
Я уже давно подобный код не пишу. Я бы сделал так:
в прерывании по приёму байта с UART-а, помещаю байт в приёмный буфер (так же как и ты), но сразу анализируя протокольную часть (детектирование флагового байта, кол-ва байт и т.п.). В прерывании, как только обнаружил конец передачи, выставил флаг завершения (который видно из главного цикла) и запретил прерывания по приёму. А в главном цикле только проверяю этот флаг. Если флаг выставлен, то читаю буфер без необходимости защищать чтение от прерываний (т.к. единственные прерывания, которые изменяют буфер уже запрещены).
А у тебя я вижу, что ты "умертвляешь" главный цикл в функции read() (while(!rx_count);)
RoboHobbyRu
 
Сообщения: 203
Зарегистрирован: 04 май 2013, 10:35
Откуда: Тюмень

Re: CodeVisionAVR - версия 2!

Сообщение Duhas » 25 июн 2013, 10:23

а два буфера с поочередным использованием не круче ?
«Как сердцу выразить себя? … Мысль изреченная есть ложь!»
В этом мире меня подводит доброта и порядочность...
"двое смотрят в лужу, один видит лужу, другой отраженные в ней звезды"
Аватара пользователя
Duhas
 
Сообщения: 6338
Зарегистрирован: 15 сен 2007, 13:03
Откуда: Красноярск
прог. языки: ASM(МК), C(PC)
ФИО: Гагарский Андрей Александрович

Re: CodeVisionAVR - версия 2!

Сообщение Korbofos » 25 июн 2013, 21:23

Извиняюсь за навязчивость :( Стоит ли отключать прерывания, когда присваивается значение переменной wait в основном цикле?
Код: Выделить всёРазвернуть
volatile unsigned char wait=0;

interrupt [TIM0_OVF] void timer0_ovf_isr(void)
{
if(wait)wait--;       // таймер ожидания прихода байта
if(!wait)TCCR0=0x00;     
}

bool read_byte(unsigned char byte)
{
unsigned char i=0;
if(!TCCR0)TCCR0=0x04;
wait = wait_time * byte;  //Добавить сюда запрет прерывания?
while(rx_count < byte)       // ожидание прихода нужного количества байт
     {
      if(!wait)
        {
         Led(lost_byte,ON);
         led_wait_count=250;
         #asm("cli")
         rx_count=0;  //очищаем буфер если пришло нужное количество байт
         #asm("sei")
         return 0;
        }
     }
for(;byte>1;byte--)data[i++]=read();
wait=0;     
if(read()==checksum)return 1;   //проверка контрольной суммы в конце пакета
return 0;         
}
РАБОТА, РАБОТА перейди на Федота, с Федота на его брата, а ко мне их зарплата.
Аватара пользователя
Korbofos
 
Сообщения: 317
Зарегистрирован: 15 янв 2011, 11:27
Откуда: Челябинск
прог. языки: C/C++
ФИО: Александр

Re: CodeVisionAVR - версия 2!

Сообщение RoboHobbyRu » 25 июн 2013, 23:09

Korbofos писал(а):Стоит ли отключать прерывания, когда присваивается значение переменной wait в основном цикле?
Код: Выделить всёРазвернуть
volatile unsigned char wait=0;

interrupt [TIM0_OVF] void timer0_ovf_isr(void)
{
if(wait)wait--;       // таймер ожидания прихода байта
if(!wait)TCCR0=0x00;     
}
...
Нет, т.к. char - один байт, доступ в AVR-ке к одному байту происходит "за один присест".
RoboHobbyRu
 
Сообщения: 203
Зарегистрирован: 04 май 2013, 10:35
Откуда: Тюмень

Re: CodeVisionAVR - версия 2!

Сообщение Korbofos » 26 июн 2013, 01:37

RoboHobbyRu Спасибо вам :)

Добавлено спустя 21 минуту 7 секунд:
Сейчас залил прошивку в мк. стоило добавить volatile и все глюки ушли :)

Добавлено спустя 7 минут 54 секунды:
Я над этим косяком столько тупил жесть, поменял несколько передатчиков, поменял мк на плате. Ладно заканчиваю свой монолог.
РАБОТА, РАБОТА перейди на Федота, с Федота на его брата, а ко мне их зарплата.
Аватара пользователя
Korbofos
 
Сообщения: 317
Зарегистрирован: 15 янв 2011, 11:27
Откуда: Челябинск
прог. языки: C/C++
ФИО: Александр

Re: CodeVisionAVR - версия 2!

Сообщение RoboHobbyRu » 26 июн 2013, 01:42

Для начального ознакомления с языком Си можно купить книгу Герберта Шилдта - Полный справочник по С (она сравнительно легко читается)
RoboHobbyRu
 
Сообщения: 203
Зарегистрирован: 04 май 2013, 10:35
Откуда: Тюмень

Пред.

Вернуться в Микроконтроллеры

Кто сейчас на конференции

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