AVR Раздел по микроконтроллерам компании Atmel - AVR / ATtiny / ATmega / ATMega128 / ATxmega, вопросы по программированию в AVR studio и все, относящееся к AVR... |
17.07.2015, 06:09
|
|
Временная регистрация
Регистрация: 24.03.2015
Адрес: Россия. г.Новосибирск
Сообщений: 69
Сказал спасибо: 12
Сказали Спасибо 0 раз(а) в 0 сообщении(ях)
|
Re: Помогите советом ATmega8535
Сообщение от NewWriter
|
Я бы сделал так. Значения таймеров загружаются в ОЗУ и если их нужно изменить, то они меняются прямо в ОЗУ. А когда изменения будут закончены (по нажатию кнопки), то значения переписываются из ОЗУ в EEPROM и там хранятся до следующих изменений начальных значений.
Для счета в принципе то нужна только одна двухбайтная переменная. В нее читается из EEPROM первый таймер при запуске, и счет таймера идет в этой переменной. Далее, когда первый таймер досчитает до 0, в эту же переменную загружается из EEPROM значение второго таймера и счет повторяется. Далее третий и четвертый таймеры запускаются аналогично. А потом после окончания счета в эту же переменную читаются с накопительным суммированием значения таймеров из EEPROM.
Если нужно изменить значения конкретного таймера, читаются из EEPROM в ОЗУ и там изменяются, затем перезаписываются обратно.
|
Вот про это я и пытался спросить. Только просто не совсем точно свои мысли передал.
|
|
|
|
17.07.2015, 06:20
|
|
Временная регистрация
Регистрация: 24.03.2015
Адрес: Россия. г.Новосибирск
Сообщений: 69
Сказал спасибо: 12
Сказали Спасибо 0 раз(а) в 0 сообщении(ях)
|
Re: Помогите советом ATmega8535
Сообщение от alvadep
|
ТС бросай работать с десятичной системой исчисления. В цифровой технике принята двоичная.
На кой ляд хранить каждую цифру отдельно. Для каждого таймера достаточно всего два байта для задания значения в двоичной системе. Для суммы кстати тоже.
При программировании к значению для каждого таймера прибавлять/отнимать константу (1, 10, 100, 1000). Вот вам и будет коррекция определенного знакоместа.
В общем, как-то так.
|
Вот это пока ,что не понял...
|
|
|
|
17.07.2015, 06:54
|
|
Временная регистрация
Регистрация: 24.03.2015
Адрес: Россия. г.Новосибирск
Сообщений: 69
Сказал спасибо: 12
Сказали Спасибо 0 раз(а) в 0 сообщении(ях)
|
Re: Помогите советом ATmega8535
Может вот так будет правильнее показать свою писанину...
volatile unsigned char Segm1=0,Segm2=0,Segm3=0,Segm4=0,Segm5;
volatile unsigned char SEGMENT[]={0x3F, 0x06, 0x5B, 0x4F, 0x66, 0x6D, 0x7D, 0x07, 0x7F, 0x6F};
ISR (TIMER0_COMP_vect){
static unsigned char segcounter=0;
PORTD=0xFF; // гасим перед выводом на индикацию
PORTB = ((PORTB|(0x1f‹‹PB3))& ~(1 ‹‹ (segcounter + PB3))); двигаем бит который зажигает индикатор
switch (segcounter) {
case 0:
PORTD = ~(SEGMENT[Segm1]);
break;
case 1:
PORTD = ~(SEGMENT[Segm2]);
break;
case 2:
PORTD = ~((SEGMENT[Segm3])|0x80); //здесь |0x80 выводит точку
break;
case 3:
PORTD = ~(SEGMENT[Segm4];
case 4:
PORTD = ~(SEGMENT[Segm5]);
break;
}
if ((segcounter++) › 4) {segcounter = 0;}
}
}
Прерывание по сравнению настроено на раз в три миллисекунды. Мне так удобно. Segm1 ,Segm2, Segm3, Segm4,Segm5 глобальные переменные.
и в них можно ложить любое число и оно мгновенно отобразится на экране.
если есть какой то еще интересный алгоритм вывода числа индикатор прошу поделиться.
Если каждый индикатор выводится у меня отдельно то и напросилось хранить значение таймеров тоже в отдельной переменной для каждого значения.
Но после общения с вами ,форумчане , у меня появились новые мысли попробую обкатать и напишу....
|
|
|
|
17.07.2015, 08:27
|
|
Заблокирован
Регистрация: 07.09.2014
Адрес: В Кремле!
Сообщений: 4,486
Сказал спасибо: 396
Сказали Спасибо 2,220 раз(а) в 1,319 сообщении(ях)
|
Re: Помогите советом ATmega8535
Сообщение от ARTEM277
|
Вот это пока ,что не понял...
|
А что там не понять то - двоичная система счисления. В одном байте может содержаться до 2^8=256 значений числа. Два байта - это 2^16=65536 значений. А если представить число в двоично-десятичной системе, когда под каждую цифру отводится один байт, то для хранения числа 65536 понадобится не 2, а 5 байт. Для индикации хорошо, а для хранения и вычислений - плохо.
Сообщение от ARTEM277
|
то и напросилось хранить значение таймеров тоже в отдельной переменной для каждого значения
|
Так тоже можно (это двоично-десятичная система), но занимает больше места. Да и операции суммирования сложнее выполняются, чем просто в двоичной системе.
Сообщение от ARTEM277
|
у меня появились новые мысли
|
Конкретно в этой задаче с этим МК - вообще без разницы, как считать и как отображать. Но на будущее, учесть, что есть что. В двоичной системе считать проще и быстрее, но BCD-преобразование перед индикацией отнимает какое-то время. Зато экономятся байты ОЗУ
Последний раз редактировалось NewWriter; 17.07.2015 в 09:47.
|
|
|
|
17.07.2015, 16:23
|
|
Заблокирован
Регистрация: 21.01.2014
Сообщений: 589
Сказал спасибо: 7
Сказали Спасибо 267 раз(а) в 206 сообщении(ях)
|
Re: Помогите советом ATmega8535
Я бы так сделал. Переменных получается немного.
Код:
|
unsigned int EEMEM Timer1_EE, Timer2_EE, Timer3_EE, Timer4_EE;
unsigned char Segm1, Segm2, Segm3, Segm4, Segm5;
void ConvertBinToSegment(unsigned int i)
{
Segm1 = 0;
Segm2 = 0;
Segm3 = 0;
Segm4 = 0;
Segm5 = 0;
while(i›10000)
{
i -=10000;
Segm5++;
}
while(i›1000)
{
i -=1000;
Segm4++;
}
while(i›100)
{
i -=100;
Segm3++;
}
while(i›10)
{
i -=10;
Segm2++;
}
while(i›0)
{
i -=1;
Segm1++;
}
}
unsigned int ConvertSegmentToBin()
{
unsigned int i = 0;
unsigned char c;
c = Segm1;
while(c-- › 0) i++;
c = Segm2;
while(c-- › 0) i += 10;
c = Segm3;
while(c-- › 0) i += 100;
c = Segm4;
while(c-- › 0) i += 1000;
c = Segm5;
while(c-- › 0) i += 10000;
return i;
}
void main()
{
//
//
// Читаем из EEPROM сохранённое значение таймера1 и устанавливаем на индикатор
ConvertBinToSegment(eeprom_read_word(&Timer1_EE));
//
//
// Сохраняем значение индикатора для таймера1 в EEPROM
eeprom_write_word(&Timer1_EE, ConvertSegmentToBin());
} |
При обратном счёте уменьшаем Segm1 на 1. Если Segm1==0, то Segm1=9 и уменьшаем Segm2 на 1. И так далее.
Последний раз редактировалось Yurkin2014; 17.07.2015 в 16:31.
|
|
|
|
19.07.2015, 22:34
|
|
Временная регистрация
Регистрация: 24.03.2015
Адрес: Россия. г.Новосибирск
Сообщений: 69
Сказал спасибо: 12
Сказали Спасибо 0 раз(а) в 0 сообщении(ях)
|
Re: Помогите советом ATmega8535
Извините ,что так на долго выпал из темы.Бытовые дела на выходных решал.
Очень рад ,что тут так новичков встречают и делятся своим опытом.
Пока ,что вникаю в то ,что написано.
|
|
|
|
19.07.2015, 22:58
|
|
Временная регистрация
Регистрация: 24.03.2015
Адрес: Россия. г.Новосибирск
Сообщений: 69
Сказал спасибо: 12
Сказали Спасибо 0 раз(а) в 0 сообщении(ях)
|
Re: Помогите советом ATmega8535
Сообщение от Yurkin2014
|
Я бы так сделал. Переменных получается немного.
Код:
|
unsigned int EEMEM Timer1_EE, Timer2_EE, Timer3_EE, Timer4_EE;
unsigned char Segm1, Segm2, Segm3, Segm4, Segm5;
void ConvertBinToSegment(unsigned int i)
{
Segm1 = 0;
Segm2 = 0;
Segm3 = 0;
Segm4 = 0;
Segm5 = 0;
while(i›10000)
{
i -=10000;
Segm5++;
}
while(i›1000)
{
i -=1000;
Segm4++;
}
while(i›100)
{
i -=100;
Segm3++;
}
while(i›10)
{
i -=10;
Segm2++;
}
while(i›0)
{
i -=1;
Segm1++;
}
}
unsigned int ConvertSegmentToBin()
{
unsigned int i = 0;
unsigned char c;
c = Segm1;
while(c-- › 0) i++;
c = Segm2;
while(c-- › 0) i += 10;
c = Segm3;
while(c-- › 0) i += 100;
c = Segm4;
while(c-- › 0) i += 1000;
c = Segm5;
while(c-- › 0) i += 10000;
return i;
}
void main()
{
//
//
// Читаем из EEPROM сохранённое значение таймера1 и устанавливаем на индикатор
ConvertBinToSegment(eeprom_read_word(&Timer1_EE));
//
//
// Сохраняем значение индикатора для таймера1 в EEPROM
eeprom_write_word(&Timer1_EE, ConvertSegmentToBin());
} |
При обратном счёте уменьшаем Segm1 на 1. Если Segm1==0, то Segm1=9 и уменьшаем Segm2 на 1. И так далее.
|
За пример очень благодарен. Я похожий алгоритм нашёл только на ассемблере. Но мне на асме сейчас не интересно .... Смысл программы мне понятен. Но я загружу ее в отладчик и разберусь досконально. Так как увидел для себя новые строки.Например вот i -=10000; и вот i += 10000; Не совсем понимаю,что + и - перед равно делает...
Пытался такой алгоритм сам реализовать. Но кривоватенько получается.
Если я правильно понимаю алгоритм этой программки ,то получается ,что берем число например 34567 и начинаем отнимать от него 10000 при этом считая сколько раз можно его отнять и эти разы и будут мой самый старшый разряд.То есть 34567-10000=24567(Segm5 увеличился на 1),24567-10000=14567(Segm5=2),14567-10000=4567(Segm5=3), вот мой первый старший сегмент равен 3 И так до первого разряда.И в Bin можно сказать обратная процедура.
Я думаю автор этих строк мне позволит использовать их в моей программе ?
|
|
|
|
19.07.2015, 23:03
|
|
Почётный гражданин KAZUS.RU
Регистрация: 10.12.2007
Адрес: Екатеринбург
Сообщений: 2,727
Сказал спасибо: 2,428
Сказали Спасибо 893 раз(а) в 580 сообщении(ях)
|
Re: Помогите советом ATmega8535
i-=1000 это сокращенная запись i=i-1000.
Не надо повторять все сообщение.
Последний раз редактировалось baiderin; 19.07.2015 в 23:07.
|
|
|
|
19.07.2015, 23:35
|
|
Временная регистрация
Регистрация: 24.03.2015
Адрес: Россия. г.Новосибирск
Сообщений: 69
Сказал спасибо: 12
Сказали Спасибо 0 раз(а) в 0 сообщении(ях)
|
Re: Помогите советом ATmega8535
Сообщение от NewWriter
|
А что там не понять то - двоичная система счисления. В одном байте может содержаться до 2^8=256 значений числа. Два байта - это 2^16=65536 значений. А если представить число в двоично-десятичной системе, когда под каждую цифру отводится один байт, то для хранения числа 65536 понадобится не 2, а 5 байт. Для индикации хорошо, а для хранения и вычислений - плохо.
Так тоже можно (это двоично-десятичная система), но занимает больше места. Да и операции суммирования сложнее выполняются, чем просто в двоичной системе.
Конкретно в этой задаче с этим МК - вообще без разницы, как считать и как отображать. Но на будущее, учесть, что есть что. В двоичной системе считать проще и быстрее, но BCD-преобразование перед индикацией отнимает какое-то время. Зато экономятся байты ОЗУ
|
С этим совсем вроде разобрался. Даже пробовал взять два байта (int) и работал с тетрадами. то есть число например 9999 туда поместилось свободно .Потом двигал эти тетрады с лево на право.И выводил их на индикацию.Но как-то все громоздко получилось. Может просто пока опыта очень мало.... Это просто пробовал один из вариантов обкатать...тренировался так сказать...
Не сразу понял по поводу такого числа как 65536.Я понимаю,что оно занимает в памяти МК всего два байта.Но после перевода его в десятичный вид на основе такой формулы ,0xABC = 10 * 16 ^ 2 + 11 * 16 ^ 1 + 12 * 16 ^ 0 = 2748, оно у меня сохранялось опять как шестнадцатиричное. Т.е занимало так же два байта.Но потом включил внимательность и понял ,что ты имел в виду,про то что считать удобно
в двоичной а выводить на индикацию десятичное. Действительно правильно будет внутри программы считать в двоичной системе,так как компилятор мне выводит для удобства все в десятичном виде ,но на уровне МК остается все в двоичном виде(точнее в HEX),в этом моменте я и заблудился. И не мог понять как декодер забацать. Сейчас вроде дошло.
|
|
|
|
19.07.2015, 23:38
|
|
Временная регистрация
Регистрация: 24.03.2015
Адрес: Россия. г.Новосибирск
Сообщений: 69
Сказал спасибо: 12
Сказали Спасибо 0 раз(а) в 0 сообщении(ях)
|
Re: Помогите советом ATmega8535
Спасибо baiderin ! На счет сообщений ...понял... больше не буду
|
|
|
|
Ваши права в разделе
|
Вы не можете создавать новые темы
Вы не можете отвечать в темах
Вы не можете прикреплять вложения
Вы не можете редактировать свои сообщения
HTML код Выкл.
|
|
|
Часовой пояс GMT +4, время: 16:49.
|
|