Мелкие вопросы по МК и ПЛИС.

Если ваш вопрос не влез ни в одну из вышеперечисленных тем, вам сюда.
Аватара пользователя
Roman Venom
Сверлит текстолит когтями
Сообщения: 1135
Зарегистрирован: Сб июл 11, 2009 18:42:21
Откуда: Украина, г.Николаев

Re: Мелкие вопросы по МК и ПЛИС.

Сообщение Roman Venom »

Gudd-Head писал(а):
Chettuser писал(а):если только не программа, то логический анализатор умеет.

Та не, суть-то вроде как раз расшифровать принятую на комп абракадабру.


Оказалось довольно хитро, но распознал так. Оказалось, передевалась структура файла xml :idea:
Успех - императив!
Аватара пользователя
sphincs
Нашел транзистор. Понюхал.
Сообщения: 174
Зарегистрирован: Вт сен 11, 2012 09:13:52
Откуда: Брест, Беларусь
Контактная информация:

Re: Мелкие вопросы по МК и ПЛИС.

Сообщение sphincs »

подскажите как работает цикл while (условие); без тела цикла? просто бесконечно проверяет условие, пока оно не станет ложно? при работе с АЦП косяк какой-то. эта часть кода выполняется до while((ADCSRA & 0x10)==0); и зацикливается, строка ADCSRA|=0x10; уже не идет (да я как-то не сильно понимаю зачем она нужна. зачем вручную выставлять флаг прерывания, если она вроде как должна выполниться только тогда, когда флаг автоматически будет выставлен самим АЦП). я так понимаю, что при симуляции в протеусе почему-то не выставляется флаг прерывания ADIF, хотя в примере, с которого это было списано, все нормально (не считая небольших косяков в других местах, не влияющих на выполнение именно этой части кода) и результат выводился на дисплей, сам проверял. вот источник http://radioaktiv.ru/publ/lessons/digit ... tmetr.html подскажите, кто чем может, а то работа простаивает :(

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

unsigned char ADC_result()
{
        ADMUX=adc_input | (ADMUX & 0b01110000); //выставляем канал
        delay_us(30); //задержка для стабилизации
        ADCSRA |= 0x40;   // запускаем преобразование
        while((ADCSRA & 0x10)==0); //Ждём флаг окончания измерения 
        ADCSRA|=0x10;
        return ADCH;//Возвращаем старший байт
}
Аватара пользователя
Kavka
Мудрый кот
Сообщения: 1810
Зарегистрирован: Чт июн 10, 2010 08:55:35
Откуда: Сибирские Афины

Re: Мелкие вопросы по МК и ПЛИС.

Сообщение Kavka »

sphincs писал(а):подскажите как работает цикл while (условие); без тела цикла? просто бесконечно проверяет условие, пока оно не станет ложно?
Да, именно так.
После while (условие) должен идти оператор. Оператор может быть одиночным, например,

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

while (условие) i++;
составным

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

while (условие) { i++; printf("%d",i);}
или пустым

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

while (условие) ;
Когда уже ничего не помогает - прочтите, наконец, инструкцию.
Лучший оптимизатор находится у вас между ушей. (Майкл Абраш, программист Quake и QuakeII)
Избыток информации ведёт к оскудению души - Леонтьев А. (сказано в 1965 г.)
Аватара пользователя
sphincs
Нашел транзистор. Понюхал.
Сообщения: 174
Зарегистрирован: Вт сен 11, 2012 09:13:52
Откуда: Брест, Беларусь
Контактная информация:

Re: Мелкие вопросы по МК и ПЛИС.

Сообщение sphincs »

Kavka, благодарю. теперь остался самый сложный вопрос: почему не выставляется флаг прерывания
Аватара пользователя
Gudd-Head
Друг Кота
Сообщения: 20091
Зарегистрирован: Чт сен 18, 2008 12:27:21
Откуда: Столица Мира Санкт-Петербург

Re: Мелкие вопросы по МК и ПЛИС.

Сообщение Gudd-Head »

sphincs писал(а):ADCSRA |= 0x40; // запускаем преобразование

Так нихуя ничего не запустится :) Надеюсь, сами догадаетесь почему.
[ Всё дело не столько в вашей глупости, сколько в моей гениальности ] [ Правильно заданный вопрос содержит в себе половину ответа ]
Аватара пользователя
sphincs
Нашел транзистор. Понюхал.
Сообщения: 174
Зарегистрирован: Вт сен 11, 2012 09:13:52
Откуда: Брест, Беларусь
Контактная информация:

Re: Мелкие вопросы по МК и ПЛИС.

Сообщение sphincs »

Gudd-Head писал(а):
sphincs писал(а):ADCSRA |= 0x40; // запускаем преобразование

не запустится :) Надеюсь, сами догадаетесь почему.


у меня уже не получается догадываться)

значение ADCSRA 10001111
значение 0х40 01000000 т.е. нужно выставить ADSC в 1 (запуск)
----------
побитовое ИЛИ |= 11001111

получаем тот же ADCSRA но уже с выставленным битом начала преобразования. где ошибка? если дело в каких-то тонкостях си (типа нельзя шестнадцатеричное число сравнить с двоичным), то так и скажите, потому что си я учу вот как раз на этом примере используя знания паскаля/делфи и гугл :) при пошаговом выполнении в авр студио этот бит выставляется, но ровно до перехода на следующую строку кода, после обнуляется. к такому меня жизнь не готовила)))

UPD. а дело случаем не в однократном режиме работы АЦП? :)

UPD1. именно в нем :) убрал while и все заработало. Gudd-Head, спасибо! :)
Последний раз редактировалось sphincs Пт мар 07, 2014 12:03:56, всего редактировалось 1 раз.
Аватара пользователя
Gudd-Head
Друг Кота
Сообщения: 20091
Зарегистрирован: Чт сен 18, 2008 12:27:21
Откуда: Столица Мира Санкт-Петербург

Re: Мелкие вопросы по МК и ПЛИС.

Сообщение Gudd-Head »

sphincs писал(а):побитовое ИЛИ |= 11001111

Блин, точно. У вас побитовое ИЛИ, а не присвоение :facepalm: проглядел. (Конечно, с учётом, что АЦП включен — в куске кода это не показано)
Попробуйте присвоением:

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

  ADCSRA = 0xCF;   // запускаем преобразование
, хотя, думаю, дело не в этом.
А дело как раз-таки в цикле While, не знаток СИ.
sphincs писал(а):а дело случаем не в однократном режиме работы АЦП?

Не должно быть в этом.
sphincs писал(а):строка ADCSRA|=0x10; уже не идет (да я как-то не сильно понимаю зачем она нужна. зачем вручную выставлять флаг прерывания, если она вроде как должна выполниться только тогда, когда флаг автоматически будет выставлен самим АЦП).

Если вы внимательно почитаете ДШ, то поймёте что флаг прерывания сбрасывается либо при обработке соотв. прерывания (если оно разрешено), либо программно записью "1" в соотв. бит.
[ Всё дело не столько в вашей глупости, сколько в моей гениальности ] [ Правильно заданный вопрос содержит в себе половину ответа ]
Аватара пользователя
sphincs
Нашел транзистор. Понюхал.
Сообщения: 174
Зарегистрирован: Вт сен 11, 2012 09:13:52
Откуда: Брест, Беларусь
Контактная информация:

Re: Мелкие вопросы по МК и ПЛИС.

Сообщение sphincs »

не знаю почему, но убрав цикл while все заработало
service47
Прорезались зубы
Сообщения: 219
Зарегистрирован: Вт мар 12, 2013 16:05:45

Re: Мелкие вопросы по МК и ПЛИС.

Сообщение service47 »

Если файл прошивки HEX весит 20кб, значит и мк должен иметь RAM на 20кб?? Просто у меня ATmega88PA с 1кб и грузиться и работает?
Аватара пользователя
Gudd-Head
Друг Кота
Сообщения: 20091
Зарегистрирован: Чт сен 18, 2008 12:27:21
Откуда: Столица Мира Санкт-Петербург

Re: Мелкие вопросы по МК и ПЛИС.

Сообщение Gudd-Head »

Нет, в ХЕКСе много всякой другой инфы.
Пример: прошивка код весит 1,9 кбайт, прошивка (хекс) — 5,2 кбайт.

Да и прошивка грузится не в RAM, а во FLASH.
[ Всё дело не столько в вашей глупости, сколько в моей гениальности ] [ Правильно заданный вопрос содержит в себе половину ответа ]
Аватара пользователя
DJ_Kiridza
Мучитель микросхем
Сообщения: 458
Зарегистрирован: Пн дек 13, 2010 13:01:59
Откуда: Украина
Контактная информация:

Re: Мелкие вопросы по МК и ПЛИС.

Сообщение DJ_Kiridza »

oleg110592 писал(а):
чтобы было два кварца

ATmega8535
ATmega16/32
ATmega164PA/324PA/644PA/1284P

Гран-мерси!!!! :)
А про Атмегу16 - я сам баран, не внимательно читал даташит, когда первый раз знакомился с этой Мегой. Мне тогда таймер2 не нужен был, я инфу о нем поверхностно прочитал... спасибо что носом ткнули!!!!
мысли мысли штош вы вйотесь
над мойейу головойу
вы там мосга нинайдете
нед там мосга! йа тупойе (БОР)
Аватара пользователя
Jack_A
Друг Кота
Сообщения: 6307
Зарегистрирован: Вт апр 24, 2007 07:45:40
Откуда: Minsk

Re: Мелкие вопросы по МК и ПЛИС.

Сообщение Jack_A »

service47 писал(а):Если файл прошивки HEX весит 20кб, значит и мк должен иметь RAM на 20кб?? Просто у меня ATmega88PA с 1кб и грузиться и работает?

RAM = Random Access Memory - это оперативная память и никакого отношения к размеру помещаемого в МК кода не имеет, потому что код заливается в ROM ( Read Only Memory ), то бишь флешь-память. Ее-то у 88-й Меги 8кб. Поскольку в HEX-файле ( INTEL-формат) каждый байт кода представлен двумя символьными байтами + служебная информация ( : , адрес, длина, КС,ВК,ПС ), то длина HEX-файла приблизительно в 3 раза превышает размер содержащегося в нем кода, так что 20кб кекса нормально влезает в 8 кб флеши.
Аватара пользователя
Mem
Поставщик валерьянки для Кота
Сообщения: 1915
Зарегистрирован: Вт апр 17, 2012 14:20:59
Откуда: Новокузнецк

Re: Мелкие вопросы по МК и ПЛИС.

Сообщение Mem »

Не могу слить флеш с 6225, китай мобайл. Флштоол выдаёт: brom error: s_undefined_error (1001). Поиск ничего путного не выдаёт. Может сталкивался кто?
Главный инженер проекта - человек, который как никто другой знает, что приближаться к спроектированной им хрени близко не стоит.
Аватара пользователя
baron_P
Нашел транзистор. Понюхал.
Сообщения: 183
Зарегистрирован: Вт сен 14, 2010 23:07:10
Откуда: Ростов

Re: Мелкие вопросы по МК и ПЛИС.

Сообщение baron_P »

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

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

#include<avr/io.h>
#include<avr/interrupt.h>
#define F_CPU 1200000UL
#include<util/delay.h>
#include<avr/pgmspace.h>
#include<avr/sleep.h>


//Prototypes

//This function is called to switch on the LED at the
//Required stage of PWM cycle
void abc(unsigned char a,unsigned char b,unsigned char c,unsigned char status);

//This function is used to initialise the new PWM cycle
void xyz(void);


volatile unsigned char e;
volatile unsigned char pwm[3]={0,8,8};
volatile unsigned char i=0;
volatile unsigned char k=0;
//PWM scale 0 - On 8 OFF
const unsigned char Blue[15] PROGMEM =  {0,8,8,0,0,8,0,6,2,3,6,1,4,5,7};
const unsigned char Red[15] PROGMEM =   {8,0,8,2,8,2,0,5,5,5,6,6,6,7,7};
const unsigned char Green[15] PROGMEM = {8,8,0,8,0,0,0,2,0,6,4,2,7,0,2};
volatile unsigned int counter =0;


int main(void)
{


   DDRB  &= ~((1<<3)|(1<<4)); //Switches and ADC
   PORTB |= (1<<3); //Switches
   PCMSK = 1<<PCINT3;//Configure PB3 as interrupt
   
   //ADC init
   
   ADMUX =  0b00100010; //ADC2,ADLAR,VCc
   ADCSRA = 0b10000010; //prescaled by 4
   
   //neglect first reading
   ADCSRA |= 1<<ADSC;
   while(ADCSRA&(1<<ADSC));//Wait
   i = ADCH;
   
   //Timer Initialisation
   TCCR0A = 0x00;
   TCCR0B = 0x02;//Prescaling
   TIMSK0 = 1<<TOIE0;//Overflow Interrupt Enabled
   sei();//Global Interrupts Enabled

   while(1)
   {
         
         
      i=0;
   
   
      ADCSRA |= 1<<ADSC;
      while(ADCSRA&(1<<ADSC));//Wait
      i = ADCH;
     
     
     
      i = i>>4;//Divide by 16
      if(i!=15)
      {
         pwm[0] = pgm_read_byte(&Blue[i]);
         pwm[1] = pgm_read_byte(&Red[i]);
         pwm[2] = pgm_read_byte(&Green[i]);
         counter = 0;
         k = 0;
      }
      _delay_ms(2);//Just a small delay
           
         
     
      if(!(PINB&(1<<3)))
      {
         _delay_ms(30);
         while(!(PINB&(1<<3))); //wait
         _delay_ms(30);
         
         
         TIMSK0 &= ~(1<<TOIE0);//Clear timer interrupt
         DDRB &=~(1<<0|1<<1|1<<2);
         GIFR |= 1<<PCIF;//Clear pending interrupt
         GIMSK |= 1<<PCIE;//Pin change interrupt enable
         MCUCR |= (1<<SE|1<<SM1);//Power down mode setting
         sleep_cpu(); //CPU halted till interrupt
         
      }
   
   }

   

}



ISR(TIM0_OVF_vect)
{
   
   
   DDRB &=~(1<<0|1<<1|1<<2);
   
   
   
   if(e==8)
   {
      e=0;
      xyz();
   }

   abc(pwm[0],pwm[1],pwm[2],e);
   DDRB |=(1<<0|1<<1|1<<2);
   e++;
   if(i==15)//Run mode
   {
      counter++;
      if(counter == 390)//500ms
      {
         counter = 0;
         if(k==14)
         k=0;
         else k++;
         pwm[0] = pgm_read_byte(&Blue[k]);
         pwm[1] = pgm_read_byte(&Red[k]);
         pwm[2] = pgm_read_byte(&Green[k]);
      }
   }
   
}

void xyz(void)
{
   
   PORTB |= (1<<0)|(1<<1)|(1<<2);
   
   
}


void abc(unsigned char a,unsigned char b,unsigned char c,unsigned char status)
{

   if((status==a))
   {
      PORTB&= ~(1<<0);
   }
   if((status==b))
   {
      PORTB&= ~(1<<1);
   }
   if((status==c))
   {
      PORTB&= ~(1<<2);
   }
   
}

ISR(PCINT0_vect)
{
   _delay_ms(30);
   while(!(PINB&(1<<3))); //wait
   _delay_ms(30);
   MCUCR = 0x00; //sleep disable
   GIMSK &= ~(1<<PCIE);//Pin change interrupt disable
   TIMSK0 = 1<<TOIE0;//Overflow Interrupt Enabled
         
         

}


Контроллер ATTiny 13A. Программа реализует программный ШИМ на трех вывода PB0, PB1, PB2. Задание для ШИМ берется из заранее сформированных массивов, в зависимости от напряжения на входе АЦП PB4. На PB3 висит кнопка, которая переводит это дело в спящий режим.
Программа работает, но есть один неясный момент. В обработчике прерывания по переполнению Таймера 0 сначала идет команда перевода выводов ШИМ в состояние входов:

Код:

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

DDRB &=~(1<<0|1<<1|1<<2);


Потом идет вызов функции, которая меняет значения на выводах ШИМ:

Код:

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

abc(pwm[0],pwm[1],pwm[2],e);


А потом идет команда перевода выводов ШИМ в состояние выходов:

Код:

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

DDRB |=(1<<0|1<<1|1<<2);


Должно же быть наоборот: сперва делаем выводы выходами, потом меняем их состояние, потом делаем их входами. Правда, зачем нужен последний шаг (используемый в этой программе часто) тоже не понимаю. Пусть бы и оставались выводы в состоянии выходов, что в этом плохого. В общем, непонятно, как оно работает и зачем оно сделано так.
We do what we must because we can (c) GLaDOS
Аватара пользователя
Gudd-Head
Друг Кота
Сообщения: 20091
Зарегистрирован: Чт сен 18, 2008 12:27:21
Откуда: Столица Мира Санкт-Петербург

Re: Мелкие вопросы по МК и ПЛИС.

Сообщение Gudd-Head »

baron_P писал(а):Есть такая страшненькая программа

Действительно страшненькая. Без комментов в коде никто разбираться не будет.
[ Всё дело не столько в вашей глупости, сколько в моей гениальности ] [ Правильно заданный вопрос содержит в себе половину ответа ]
Аватара пользователя
baron_P
Нашел транзистор. Понюхал.
Сообщения: 183
Зарегистрирован: Вт сен 14, 2010 23:07:10
Откуда: Ростов

Re: Мелкие вопросы по МК и ПЛИС.

Сообщение baron_P »

Всю программу я привел на всякий случай. Не думал, что та часть, к которой относится мой вопрос, нуждается в комментариях. Но вот они ниже:
Спойлер

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

//вектор прерывания по перполнению Т0
ISR(TIM0_OVF_vect)
{
   
   //перевод PB0, PB1, PB2 в состояние входов
   DDRB &=~(1<<0|1<<1|1<<2);
   
   
   //если e равно 8, обнуляем е и вызываем функцию
   //которая выставляет PB0, PB1, PB2 в 1
   if(e==8)
   {
      e=0;
      xyz();
   }

   //вызываем фукцию, которая выставляет 0 на
   //выводах PB0, PB1, PB2, в зависимости от
   //значения е
   abc(pwm[0],pwm[1],pwm[2],e);
   
   //перевод PB0, PB1, PB2 в состояние выходов
   DDRB |=(1<<0|1<<1|1<<2);
   
   //инкремент е
   e++;
   
   //дальше идет дополнительный режим работы,
   //когда значения на PB2, PB1, PB0 меняются
   //в цикле, он к вопросу не относится
   if(i==15)//Run mode
   {
      counter++;
      if(counter == 390)//500ms
      {
         counter = 0;
         if(k==14)
         k=0;
         else k++;
         pwm[0] = pgm_read_byte(&Blue[k]);
         pwm[1] = pgm_read_byte(&Red[k]);
         pwm[2] = pgm_read_byte(&Green[k]);
      }
   }
   
}


Вопрос: почему при таком порядке объявления фукнционала портов (обявляем как входа, меняем значение на них, объявляем как выхода), программа работает?

UPD:
Упростил программу до предела:
Спойлер

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

#include<avr/io.h>
#define F_CPU 1200000UL


int main(void)
{
  while(1)
  {   
   
        //объявляем PB0, PB1, PB2 входами
        DDRB &=~(1<<0|1<<1|1<<2);

        //на PB0, PB1, PB2 выставляем 0
        PORTB &= ~(0b00000111);
        //на PB0, PB1, PB2 выставляем 1
        PORTB |= 0b00000111;

        //объявляем PB0, PB1, PB2 выходами
        DDRB |=(1<<0|1<<1|1<<2);

  }
}

Смотрел дебаггером в AVRStudio 4.19 - программа моргает выходами. При этом на PINB все время висят нули. Если убрать строку с DDRB &=~(1<<0|1<<1|1<<2), то моргают также и PINB. Это баг или так и должно быть? Я ожидал другой логики работы от команды назначения выводов входами. Когда вывод вход, он не должен меняться от записи в PORTB. Или должен?
We do what we must because we can (c) GLaDOS
Аватара пользователя
urry
Сверлит текстолит когтями
Сообщения: 1262
Зарегистрирован: Пн дек 08, 2008 10:58:48
Откуда: Винница
Контактная информация:

Re: Мелкие вопросы по МК и ПЛИС.

Сообщение urry »

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

 Когда вывод вход, он не должен меняться от записи в PORTB.

когда пристегиваются или отстегиваются встроенные резисторы подтяжки, что происходит ? Думаю, то, что вы наблюдаете на выводе.
Alexeyslav
Друг Кота
Сообщения: 4550
Зарегистрирован: Чт май 05, 2011 21:26:34
Откуда: Украина, Славутич
Контактная информация:

Re: Мелкие вопросы по МК и ПЛИС.

Сообщение Alexeyslav »

А посмотри внимательно структурную схему выходного порта в даташите на контроллер, многие вопросы сразу отпадают.
Делается это чтобы манипуляции не влияли на выход, за то время как программа будет решать 1 или 0 должен быть на выходе ШИМа в данном такте на выводе контроллера будет удерживаться уровень по инерции. Хотя, по хорошему эту операцию достаточно буферизировать - менять внутреннюю переменную, а потом её за один раз выводить в порт. И не нужны будут всякие подобные шаманства.
Аватара пользователя
baron_P
Нашел транзистор. Понюхал.
Сообщения: 183
Зарегистрирован: Вт сен 14, 2010 23:07:10
Откуда: Ростов

Re: Мелкие вопросы по МК и ПЛИС.

Сообщение baron_P »

Спасибо.
О логике работы я судил по этой картинке:
СпойлерИзображение

Когда выводы порта B объявлены как входы, в PORTB можно записать 1, что включит подтягивающие резисторы. Если к выводам ничего не подцеплено, на PINB должны появиться 1. Если записать при этом в PORTB 0, то выводы будут висеть в воздухе и непонятно, что будет в PINB. Если к порту В подцепить катоды светодиодов, подав на аноды питание, то в первом случае светодиоды гореть не будут. И во втором тоже, т.к. тока нет.
Когда выводы порта В объявлены как выходы, в PORTВ можно записать 1, и в PINB появится 1. Если записать 0, то и в PINB появится 0. Если к порту В подцепить катоды светодиодов, подав на аноды питание, то в первом случае светодиоды гореть не будут. А во втором должны загореться, т.к. будут посажены на землю.
По моему так должно работать.
А тут же получается что-то другое. При обявленнии выводов входами всегда в PINB висят нули, и при записи в PORTB нулей загораются светодиоды. Я не пойму, почему так.
Делается это чтобы манипуляции не влияли на выход, за то время как программа будет решать 1 или 0 должен быть на выходе ШИМа в данном такте на выводе контроллера будет удерживаться уровень по инерции. Хотя, по хорошему эту операцию достаточно буферизировать - менять внутреннюю переменную, а потом её за один раз выводить в порт. И не нужны будут всякие подобные шаманства.

Это фраза объясняет структуру программы в виде: объявили порт выходом, записали нужное значение, объявили входом, чтоб чего лишнего не записалось. Я правильно понял? Нет, не правильно :idea: Объявляем выводы входами, записываем в PORTB сначала какие-то промежуточные значения, потом то, что должно быть выведено на него. Объявляем выводы выходами и на них тут же появляется уже находящиеся в PORTB значения. Между двумя объявлениями фактические значения на выводах не меняются, потому и PINB не меняется. Вроде дошло. Еще раз спасибо.
We do what we must because we can (c) GLaDOS
Аватара пользователя
Mem
Поставщик валерьянки для Кота
Сообщения: 1915
Зарегистрирован: Вт апр 17, 2012 14:20:59
Откуда: Новокузнецк

Re: Мелкие вопросы по МК и ПЛИС.

Сообщение Mem »

Как исправить эти фьюзы?

Изображение

Понятно что Mega 16 теперь от внешнего кварца, но какого? Пробовал разные, не определяется. Сигнатура 0х000000, в остальном пишет что готово к работе. Один раз завелась от 8 МГц, я затер флеш и еепром, после этого опять перестало работать.
Вложения
Безымянный.png
(60.72 КБ) 806 скачиваний
Главный инженер проекта - человек, который как никто другой знает, что приближаться к спроектированной им хрени близко не стоит.
Ответить

Вернуться в «Разные вопросы по МК»