Динамическая индикация на ATTiny13

Обсуждаем контроллеры компании Atmel.
Ответить
Друг Кота
Аватара пользователя
Сообщения: 4732
Зарегистрирован: Ср сен 18, 2013 10:08:26
Откуда: Санкт-Петербург

Сообщение Gisteresis »

Мяяяяу!
Бьюсь значит вот с каким шайтаном.
Сделал милливольтиметр на ATTiny13A. Частота 9.4МГц. Хочу вывести на 4значный семисегментный индикатор. Вывод динамический по прерыванию таймера, работает прекрасно. В прерывании АЦП происходит преобразование условных единиц АЦП в число и разбивка на декады, чтобы их потом выводило прерывание таймера. Все рабоает. Проверял выводом регистра АЦП. Выводит значение от 0 до 1023.

Первый вопрос.
Настроил преобразование АЦП на минимум, 73.438кГц. Значения на дисплее дергаются. Как сделать еще меньше? Например 2..3 преобразования в секунду.

Второй вопрос.
Преобразование кода сделал так

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

iVolts = 5*adc_data[0]-(24*adc_data[0]/1024)*5;
cDigit[0][0] = ~cSeg[((iVolts/1000)%10)];
cDigit[1][0] = ~cSeg[((iVolts/100 )%10)];
cDigit[2][0] = ~cSeg[((iVolts/10  )%10)];
cDigit[3][0] = ~cSeg[((iVolts/1   )%10)];
Понимаю, что изобрел протез. Как сделать нормально?
Если я просто делаю так

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

iVolts = 5000*adc_data[0]/1024
то преобразование упирается в 16ти битовое умножение. Операция 5000*adc_data[0] требует больше чем 16 бит.
Есть ли какой то аналог функции MulDiv?
Как это нормально сделать на ATTiny?

Расшифровывать эту писанину думаю не нужно?
cDigit[0][0] - это массив на 4 декады для того чтобы потом прерывание таймера брало оттуда и выводило.
cSeg - это массив с кодами семисегментного индикатора.

Просьба отослать к существующей ветке, если такая есть.
Реклама
ARV
Ум, честь и совесть. И скромность.
Аватара пользователя
Сообщения: 18786
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск

Сообщение ARV »

во-первых: извиняюсь, вы применили какие-то схемные решения для подключения 7-сегментного 4-разрядного индикатора к МК с 6-ю доступными ножками? или ошибка и МК у вас другого типа?

во-вторых, преобразование значения АЦП в выводимые символы не надо делать в прерывании! это задача для главного цикла, где можно делать любые задержки, усреднения и т.п. штуки
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

Мой уютный бложик... заходите!
Контактная информация:
Реклама
Опытный кот
Аватара пользователя
Сообщения: 882
Зарегистрирован: Ср фев 22, 2012 01:25:21

Сообщение shads »

Gisteresis писал(а):Первый вопрос.
Настроил преобразование АЦП на минимум, 73.438кГц. Значения на дисплее дергаются. Как сделать еще меньше? Например 2..3 преобразования в секунду.
Сделать усреднение... или просто поставь между обновлениями буфера дисплея _delay_ms (300);
(естественно - при этом динамическая обработка дисплея должна быть реализована в прерывании...)
Gisteresis писал(а):Второй вопрос.
Как сделать нормально?
Просто приведи любое из значений к 32-м разрядам...
Например так: iVolts = (uint32_t)5000*adc_data[0]/1024;
или так: iVolts = 5000UL*adc_data[0]/1024;
или так: iVolts = 5000*(uint32_t)adc_data[0]/1024
Последний раз редактировалось shads Пн сен 29, 2014 21:05:30, всего редактировалось 1 раз.
Мучитель микросхем
Сообщения: 410
Зарегистрирован: Чт ноя 13, 2008 16:33:42

Сообщение vdavid »

shads писал(а): или так: iVolts = 5000*(uint8_t)adc_data[0]/1024
Ну только не так :) .
Реклама
Эиком - электронные компоненты и радиодетали
Опытный кот
Аватара пользователя
Сообщения: 882
Зарегистрирован: Ср фев 22, 2012 01:25:21

Сообщение shads »

vdavid писал(а):
shads писал(а): или так: iVolts = 5000*(uint8_t)adc_data[0]/1024
Ну только не так :) .
Хе... по привычке написал... естественно - (uint32_t)... поправлю :)...
Реклама
Друг Кота
Аватара пользователя
Сообщения: 3832
Зарегистрирован: Сб сен 10, 2011 17:46:25

Сообщение oleg110592 »

расчет можно подсократить, 4 разряд думаю не нужен - разрешение 1мВ вряд ли нормально получится

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

//V=(ADC*VAREF)/1024     
//V=ADC*500/1024 
//V=ADC*125/256       
Voltage = (unsigned int)(((unsigned long)read_adc(3)*125)>>8);
binary to bcd:

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

void Bin2bcd(unsigned int Value)
{
  unsigned char n=0;
  while (Value >= 100)
  {
    Value -= 100;
    n++;
  }
  Led0 = seg7[n];
  n = 0;
  while (Value >= 10)
  {
    Value -= 10;
    n++;
  }
  Led1 = seg7[n];
  Led2 = seg7[Value];
}
СпойлерИзображение
Реклама
Друг Кота
Аватара пользователя
Сообщения: 4732
Зарегистрирован: Ср сен 18, 2013 10:08:26
Откуда: Санкт-Петербург

Сообщение Gisteresis »

ARV писал(а):какие-то схемные решения для подключения 7-сегментного 4-разрядного индикатора
Извиняюсь что не написал, но вроде это и ненужно было. Эта часть работает хорошо. Стоят 2 регистра 595х в первый пишется код цифры, второй зажигает нужную декаду через транзистор. В прерывании таймера зажигается одна декада, следующее прерывание зажигает следующую декаду. И так по кругу прерывание обновляет декады. Тут собственно проблем нет.
ARV писал(а):преобразование значения АЦП в выводимые символы не надо делать в прерывании!
Те в главном цикле ждать завершения прерывания?
А чем плохо если я это сделаю сразу в прерывании АЦП? Там код небольшой.
shads писал(а):Сделать усреднение...
Да, начал догадываться до этого. Спасибо.
shads писал(а):Просто приведи любое из значений к 32-м разрядам...
А вот просто привести к 32битам не получается. Вначале компилер говорит что РАМ не хватает. Ну ладно, расширил. Потом он говорит что это действие невозможно так как в ATTiny13 MUL 16ти битный. Там хоть к long long приводи, он все равно результат отрежет значением 65535. Вот в том то и вопрос был. Как с этим ограничением преобразовать данные с АЦП в миливольты и разбить на декады. Я поэтому и вспомнил MULDIV но не знаю какой ее аналог есть в CV. Код искал, пока безрезультатно.
oleg110592 писал(а):расчет можно подсократить, 4 разряд думаю не нужен - разрешение 1мВ вряд ли нормально получится
Ну оно собственно и не получается, там скорее шум какой то. Вопрос был скорее по математике преобразования.
Насчет подсократить подумаю, хорошее решение, сам не догадался.
....

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

read_adc(3)*125
Эта операция не пройдет. Максимальное значение АЦП 1024 его максимум можно умножить на 64, получится максимум 65536.

Всем спасибо за подсказки.
Последний раз редактировалось Gisteresis Вт сен 30, 2014 08:11:54, всего редактировалось 1 раз.
Это не хвост, это антенна
Аватара пользователя
Сообщения: 1438
Зарегистрирован: Вт окт 28, 2008 09:00:18
Откуда: Украина, Харьков

Сообщение Dr. Alex »

Gisteresis писал(а):... Частота 9.4МГц...
КАК???? :shock: Частота Тини13 9.6!!!!!
Порой мне кажется, что я делаю какое-то дерьмо, но когда я вижу, что делают другие, то я чувствую себя гением...
Контактная информация:
Друг Кота
Аватара пользователя
Сообщения: 4732
Зарегистрирован: Ср сен 18, 2013 10:08:26
Откуда: Санкт-Петербург

Сообщение Gisteresis »

Dr. Alex писал(а):Частота Тини13 9.6!!!!!
Да, 9.6мГц, вы правы.
Друг Кота
Аватара пользователя
Сообщения: 3832
Зарегистрирован: Сб сен 10, 2011 17:46:25

Сообщение oleg110592 »

приведение типов - (unsigned long)read_adc(3) теперь можно умножать на 125
Друг Кота
Аватара пользователя
Сообщения: 4732
Зарегистрирован: Ср сен 18, 2013 10:08:26
Откуда: Санкт-Петербург

Сообщение Gisteresis »

В ATTiny13 сама операция умножения 16ти битная. Привести к 32м битам можно, но само умножение не получается. Все, что выше 16го бита отрезается. Фирштейн. Тоесть максимальное число, которым может манипулировать тини 65535.
АЦП = 1024
1024*125=128000 что больше 65535.
Друг Кота
Аватара пользователя
Сообщения: 3832
Зарегистрирован: Сб сен 10, 2011 17:46:25

Сообщение oleg110592 »

все нормально работает (картинку приводил), причем тут тини - компилятор сделает всю работу
Друг Кота
Аватара пользователя
Сообщения: 4732
Зарегистрирован: Ср сен 18, 2013 10:08:26
Откуда: Санкт-Петербург

Сообщение Gisteresis »

Попробую ваш код вечером.
Но у меня уже было написано 5000*adc_data[0], и тут мне компилятор заявлял что команда MUL 16 битная, повторяю уже 4й раз. То есть числа подаем 32х битные, но в 16битные регистры с отрезанием всего лишнего. И результат выходит 16ти битный.
Оно собирается в исполняемый файл и после прошивки я вижу что работает только 2 последних разряда и там шлак. Что собственно и ожидалось от такого умножения.

ПС: Чтобы не устраивать пустой холивар, ждем до вечера. Опробую, скажу результат.
Друг Кота
Аватара пользователя
Сообщения: 3832
Зарегистрирован: Сб сен 10, 2011 17:46:25

Сообщение oleg110592 »

уже было написано 5000*adc_data[0]
если так, как выше товарищ shads говорил:

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

unsigned long V; 
V=5000UL*(unsigned long)adc_data[0];
компилятор не заявлял бы
Изображение
ARV
Ум, честь и совесть. И скромность.
Аватара пользователя
Сообщения: 18786
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск

Сообщение ARV »

Gisteresis писал(а):
ARV писал(а):преобразование значения АЦП в выводимые символы не надо делать в прерывании!
Те в главном цикле ждать завершения прерывания?А чем плохо если я это сделаю сразу в прерывании АЦП? Там код небольшой.
не надо ничего ждать. если вам так ужасно хочется, молотите прерываниями АЦП, и в обработчике прерываний помещайте результат в переменную, которую затем в главном цикле по мере необходимости обсчитывайте и выводите изредка. только учтите, что для работы с 2-байтной переменной нужно обеспечить атомарность доступа, т.е. как минимум делайте так:

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

volatile int result_adc; // сюда в прерывании помещается результат

int main(void){
   // где-то в главном цикле делаете так
   int tmp;
   cli(); // запрет прерываний
   tmp = result_adc;
   sei(); // разрешение прерываний
   // дальше обрабатываете переменную tmp
}
только все это бессмысленно. я бы делал именно так, как вы сказали мне в ответ: в главном цикле ждал бы окончания преобразования и дальше его обрабатывал бы...
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

Мой уютный бложик... заходите!
Контактная информация:
Прорезались зубы
Аватара пользователя
Сообщения: 202
Зарегистрирован: Пн сен 26, 2011 13:48:25
Откуда: Харьков

Сообщение slavokhire5 »

Dr. Alex писал(а):
Gisteresis писал(а):... Частота 9.4МГц...
КАК???? :shock: Частота Тини13 9.6!!!!!
В тини13 можно калибровать частоту =) так что 9.4 от внутреннего сделать не проблема
Осилит дорогу идущий
--------------------------
Пишу на Си за еду
Друг Кота
Аватара пользователя
Сообщения: 4732
Зарегистрирован: Ср сен 18, 2013 10:08:26
Откуда: Санкт-Петербург

Сообщение Gisteresis »

Модификатор UL решил проблему. Остальные множители не пришлось приводить к этому типу.

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

V=5000UL*adc_data[0]/1024;
Сделал усреднение. В общем все заработало как надо. Даже пытается что то вроде 4го разряда показывать, очень грубо.
Всем спасибо.
Ответить

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