Страница 1 из 1
Семисегментник + Atmega8
Добавлено: Вт июн 09, 2015 13:11:18
binarick
Рыл на форуме долго и упорно и не нашёл по моему вопросу.
В общем задача банальная: засветить 3х символьный 7сегментник
Но ! Беда в том, что во всех примерах на форуме он занимает целый порт.
У меня атмега8 + кварц(заняты PB6 и PB7) + кнопки на прерываниях(int0 занят), отсюда я не могу использовать порт весь целиком
а во всех программах используют чтото подобное:
Код: Выделить всё
while (1)
{
switch (cur_dig)
{
case 0:{digit3=0; digit1=1; break;}; //подаём питание на разряд 3
case 1:{digit1=0; digit2=1; break;}; //подаём питание на разряд 2
case 2:{digit2=0; digit3=1; break;}; //подаём питание на разряд 1
}
PORTB=digits[digit_out[cur_dig]]; //выводим с каждым срабатыванием таймера число с масива в порт В, но не для всех разрядов сразу
cur_dig++; //с каждым срабатыванием таймера, увеличиваем переменную cur_dig на 1
if(cur_dig==3) cur_dig=0; //если cur_dig = 3 обнуляем
а именно PORTB=digits[digit_out[cur_dig]]; что не возможно для меня.
так вот прошу подсказки или примера кода (если возможно) как можно это обойти.
здорово бы было если порты задать через #define, но как их потом перебирать и присваивать ума не приложу
Спасибо за ваше время и ответы
Re: Семисегментник + Atmega8
Добавлено: Вт июн 09, 2015 13:54:10
Gudd-Head
Ну так если у вас порт будет раскидан по разным ногам, тогда надо всё делать побитово.
Намного проще будет, если вы наскребёте две тетрады (пины 0...3 и/или 4...7 одного порта).
Re: Семисегментник + Atmega8
Добавлено: Вт июн 09, 2015 13:57:01
B@R5uk
Решение без модификации схемы заключается в том, чтобы выводить данные на свободные пины нескольких портов.
Решение с добавлением внешнего элемента заключается в том, чтобы выводить данные через два пина ( ! ) с помощью SPI на сдвиговый регистр. Это решение так же хорошо тем, что с тремя сдвиговыми регистрами можно сделать статическую, а не динамическую индикацию, а модуль индикации будет внешним, к которому будут вести всего 4 провода (2 питания, клок и данные).
Re: Семисегментник + Atmega8
Добавлено: Вт июн 09, 2015 13:58:54
binarick
могу освободить любые порты кроме тех которые я перечислил это кварц и любое прерывание int0 либо int1
я понимаю что побитно. но как написать красивый алгоритм типа как в примере, а не городить повторяющиеся и почти аналогичные куски кода. и желательно с дефайнами
Решение с добавлением внешнего элемента заключается в том, чтобы выводить данные через два пина с помощью SPI на сдвиговый регистр.
пока не хотелось бы так делать, свободных портов много
Re: Семисегментник + Atmega8
Добавлено: Вт июн 09, 2015 14:03:18
B@R5uk
Ну, перекиньте тогда два старших бита порта B на порт D.
Re: Семисегментник + Atmega8
Добавлено: Вт июн 09, 2015 14:04:29
binarick
B@R5uk писал(а):Ну, перекиньте тогда два старших бита порта B на порт D.
вобщем вопрос в том и заключается как это сделать наименее громоздко ?
Re: Семисегментник + Atmega8
Добавлено: Вт июн 09, 2015 14:05:06
Gudd-Head
B@R5uk писал(а):Это решение так же хорошо тем, что с тремя сдвиговыми регистрами можно сделать статическую, а не динамическую индикацию
Особенно это решение "хорошо" если сегментник заточен под динамическую индикацию, и у него просто не выведены все ноги

Re: Семисегментник + Atmega8
Добавлено: Вт июн 09, 2015 14:13:24
B@R5uk
Gudd-Head писал(а):если сегментник заточен под динамическую индикацию
Вы имели в виду под статическую? А это и не важно. В регистр можно писать все данные: и сигналы на аноды, и сигналы на катоды. Разница будет только в программном коде, а коммутация останется прежней.
binarick писал(а):вопрос в том и заключается как это сделать наименее громоздко ?
Вообще так можно делать. Вместо
написать
Код: Выделить всё
uint8_t tmpB = digits [ digit_out [cur_dig] ];
uint8_t tmpD = digits [ digit_out [cur_dig] ];
tmpB >>= 2;
tmpD <<= 6;
uint8_t PDov = PORTD;
PDov &= 0x3F;
tmpD |= PDov;
PORTB = tmpB;
PORTD = tmpD;
На ассемблере это бы красивее выглядело. Данные, которые планировалось разместить в PB0...PB7 теперь выводятся в PD6,PD7,PB0...PB5 соответственно.
Re: Семисегментник + Atmega8
Добавлено: Вт июн 09, 2015 14:17:31
binarick
спасибо буду пробовать. Нет ассемблер мне не подходит

не грамотен я в нём совсем
Re: Семисегментник + Atmega8
Добавлено: Вт июн 09, 2015 14:20:18
B@R5uk
А у меня си в АВР-студии на работает, поэтому я грамотен.

Вы в какой среде кодите?
Re: Семисегментник + Atmega8
Добавлено: Вт июн 09, 2015 14:21:43
binarick
B@R5uk писал(а):А у меня си в АВР-студии на работает, поэтому я грамотен.

Вы в какой среде кодите?
CodeVision 3.12
Re: Семисегментник + Atmega8
Добавлено: Вт июн 09, 2015 14:27:11
B@R5uk
Если просто два старших бита с порта B на порт D перекинуть, то будет ещё проще:
Код: Выделить всё
uint8_t tmp = digits [ digit_out [cur_dig] ];
uint8_t PDov = PORTD;
PDov &= 0x3F;
PORTB = tmp;
tmp &= 0xC0;
tmp |= PDov;
PORTD = tmp;
Тут, как и в предыдущем случае есть маленькая неприятность: модификация портов не является атомарной, поэтому, если в где-то в прерывании модифицируется порт D, и эта модификация попадёт между чтением порта D и его записью предложенным мною кодом, то модификация будет перезаписана старым значением. Так что тут либо следить надо, либо отключить прерывания на время вывода данных.
Re: Семисегментник + Atmega8
Добавлено: Вт июн 09, 2015 14:49:43
binarick
B@R5uk писал(а):
Тут, как и в предыдущем случае есть маленькая неприятность: модификация портов не является атомарной, поэтому, если в где-то в прерывании модифицируется порт D, и эта модификация попадёт между чтением порта D и его записью предложенным мною кодом, то модификация будет перезаписана старым значением. Так что тут либо следить надо, либо отключить прерывания на время вывода данных.
сейчас не уверен но порт D используется, попробую, что получится
схемку переделал теперь как-то так будет:

Re: Семисегментник + Atmega8
Добавлено: Вт июн 09, 2015 16:20:11
B@R5uk
Я так понимаю, на выход порт D используется всё для того же индикатора и в той же процедуре. А пины-входы порта D без подтяжки. Есть смысл заранее подготовить и реализовать вывод всех выходных пинов одним махом.
Чтобы индикатор светился на входа ABCDEFG должен быть высокий уровень, а на входах 1234 — низкий, или наоборот? Кстати, можно модель индикатора, а то меня цифровое отображение данных тоже интересует.
Re: Семисегментник + Atmega8
Добавлено: Ср июн 10, 2015 05:52:31
binarick
второй алгоритм работает!
Спасибо огромное
осталось мне понять как он работает
С подтяжками не разбирался ещё только в протеусе собрал. Сейчас буду схемку приводить в рабочее состояние
например такой будет C-563G-12
http://www.paralight.us/uploads/pdf/C-563G%20A1.pdf
Re: Семисегментник + Atmega8
Добавлено: Ср июл 01, 2015 12:51:10
binarick
Ребят помогите ошибку найти
Код: Выделить всё
//------------------
void recoding(int indication) { //функция для перекодировки из hex в dec
digit_out[0]=indication%10; //Делим на 10 остаток в масив 1-разряд
indication=indication/10; //Оставляем 2 разряда
digit_out[1]=indication%10; //Делим на 10 остаток в масив 2-разряд
digit_out[2]=indication/10; //Делим на 10 целое число в масив 3-разряд
}
//-----------------
while (1)
{
TimeData= 123;
recoding(TimeData);
//PORTB=0b000000; //убираем тень
//PORTD=0b00000000;
for (cur_dig=0; cur_dig<2 ;cur_dig++)
{
if (cur_dig ==0) {digit3= 1; digit1=0;}
else if (cur_dig ==1) {digit1= 1; digit2=0;}
else if (cur_dig ==2) {digit2= 1; digit3=0;}
tmp = digits [ digit_out [cur_dig] ];
PDov = PORTD;
PDov &= 0b111111; //0x3F;
PORTB = tmp;
tmp &= 0b11000000; //0xC0;
tmp |= PDov;
PORTD = tmp;
}
}
на экране имею:
а должно быть "123"
и можно как-то убрать цикл типа for (cur_dig=0; cur_dig<2 ;cur_dig++) и за раз выводить 3,2 и 1 разряды.... думаю с ним связана ошибка но додумать не могу
на нравится мне digit3= 1; не понимаю зачем их гасить но если не гасить то вообще ерунда какаято
Спасибо
Re: Семисегментник + Atmega8
Добавлено: Ср июл 01, 2015 17:35:32
dr.doc
if (cur_dig ==0) {digit3= 1; digit1=0;}
else if (cur_dig ==1) {digit1= 1; digit2=0;}
else if (cur_dig ==2) {digit2= 1; digit3=0;}
Сам пишу на ассемблере, но, сдается мне, что в данном коде выводится цифра на 2 общих катода (анода) при любом значении cur_dig...