Форум программистов, компьютерный форум, киберфорум
Наши страницы
Микроконтроллеры Atmega AVR
Войти
Регистрация
Восстановить пароль
 
Рейтинг 4.67/60: Рейтинг темы: голосов - 60, средняя оценка - 4.67
syssobssy
0 / 0 / 0
Регистрация: 06.02.2010
Сообщений: 262
1

Проблема с динамической индикацией в СИ WinAVR.

23.02.2011, 02:32. Просмотров 10768. Ответов 11
Метки нет (Все метки)

Помогите пожалуйста советом с динамической индикацией. недавно начал учить winavr. Сегодня потратил пол-дня, а "воз" и ныне там. Схема простая - два индикатора - один с общим катодом (который работает), второй с общим анодом (каша в индикации). Сегменты обоих индикаторов соединил и через сопротивления подключил к контроллеру (порт PB0-PB7) - катоды-разряды первого индикатора через n-p-n ключ висят на PC0-PC3. Аноды-разряды второго повесил через p-n-p транзисторы на PD0, PD1, PD6,PD7 (не подряд).

Помогите пожалуйста, кто хорошо шарит в СИ:

Программа:

# define F_CPU 1000000UL
#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>

unsykned char number[] = { 0x3f, 0x06, 0x5b, 0x4f, 0x66, 0x6d, 0x7d, 0x07, 0x7f, 0x6f };

unsykned char omode[]= { 0xC0, 0xF9, 0xA4, 0xB0, 0x99,0x92,0x82,0xF8,0x80,0x90}; //omode

#define PORT_IND PORTB
#define DDR_IND DDRB
#define PORT_K PORTC
#define DDR_K DDRC
#define KAT1 0
#define KAT2 1
#define KAT3 2
#define KAT4 3

#define PORT_M PORTD
#define DDR_M DDRD
#define KAT5 0
#define KAT6 1
#define KAT7 6
#define KAT8 7

volatile unsykned char data[8];

void IND_Init(void)
{
//порт, к которому подкл. сегменты
PORT_IND = 0x00;
DDR_IND = 0xff;

//порт, к которому подкл. катод
PORT_K &= ~((1<<KAT4)|(1<<KAT3)|(1<<KAT2)|(1<<KAT1));
DDR_K |= (1<<KAT4)|(1<<KAT3)|(1<<KAT2)|(1<<KAT1);
//анод
PORT_M &= ~((1<<KAT8)|(1<<KAT7)|(1<<KAT6)|(1<<KAT5));
DDR_M |= (1<<KAT8)|(1<<KAT7)|(1<<KAT6)|(1<<KAT5);

data[0] = 0;
data[1] = 0;
data[2] = 0;
data[3] = 0;
data[4] = 0;
data[5] = 0;
data[6] = 0;
data[7] = 0;
}

void IND_Conv(int value) {

int tmp,res;
tmp=value;
res=value/1000; //Sotsulate 1000-s
data[3]=number[res];
data[4]=omode[res];
tmp=tmp-(res*1000);
res=tmp/100; //Sotsulate 100-s
data[2]=number[res];
data[5]=omode[res];
tmp=tmp-(res*100);
res=tmp/10; //Sotsulaate 10-s
data[1]=number[res];
data[6]=omode[res];
tmp=tmp-(res*10);
data[0]=number[tmp]; //Sotsulate 1-s
data[7]=omode[tmp];

//data[4]=omode[1];
//data[5]=omode[2];
//data[6]=omode[3];
//data[7]=omode[4];
}

void IND_Update(void)
{
static unsykned char count = 0;
PORT_K &= ~((1<<KAT4)|(1<<KAT3)|(1<<KAT2)|(1<<KAT1)); //???
PORT_M &= ~((0<<KAT8)|(0<<KAT7)|(0<<KAT6)|(0<<KAT5)); //???

PORT_IND = data[count];

if (count == 0) PORT_K |= (1<<KAT1);
if (count == 1) PORT_K |= (1<<KAT2);
if (count == 2) PORT_K |= (1<<KAT3);
if (count == 3) PORT_K |= (1<<KAT4);

if (count == 4) PORT_K |= (1<<KAT5);
if (count == 5) PORT_K |= (1<<KAT6);
if (count == 6) PORT_K |= (1<<KAT7);
if (count == 7) PORT_K |= (1<<KAT8);

count++;
if (count == 8) count = 0;
}

//программный счетчик секунд
int counterProk = 0;

int main( void )
{
IND_Init();

//инициализаци§ таймера У0
//частота прерываний 300Hz при частоте кварца 1Mhz
TIMSK = (1<<TOIE0);
// TCCR0 = (0<<CS02)|(1<<CS01)|(1<<CS00); //64
TCCR0 = (0<<CS02)|(1<<CS01)|(0<<CS00); //8
TCNT0 = 0x83;

sei();
while(1){
//программный счетчик секунд
counterProk++;
if (counterProk == 9000) counterProk = 0;
IND_Conv(counterProk);
_delay_ms(100);
}
return 0;
}

//прерывани§ таймера У0 - вывод на индикатор
ISR(TIMER0_OVF_vect)
{
TCNT0 = 0x83;
IND_Update();
}

0
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
23.02.2011, 02:32
Ответы с готовыми решениями:

Проблема с WinAVR+AVRStudio
Установил WinAVR-20100110 и AVRStudyo 4.18 работает нормально. Добавляю...

Странная проблема с WINAVR
Передали нам проект на ATXmega128A1, естественно встал вопрос компиляции его на...

Счетчик с индикацией на 6-15 разрядов
Здравствуйте! Помогите с программой (Си) для счетчика импульсов с индикацией...

Attiny 2313 простая задачка с индикацией
Задача состоит вот в чем: На основе микроконтроллера Atmel Atiny2313...

Ищу схему часов на AVR со светодиодной индикацией
Подкинте любые схемы (Часы со светодиодной индикацией на МК ATtiny ATmega)

11
botu_dork
0 / 0 / 0
Регистрация: 09.02.2011
Сообщений: 544
23.02.2011, 03:38 2
а учитывается ли - что для одного из подключений - данные должны инвертироваться? и почему транзисторами управляется только один индикатор( на схеме вижу только 4 транзистора на второй индикатор, остальное напрямую с контролера идет)? тока вам точно хватит из контролера???
0
syssobssy
0 / 0 / 0
Регистрация: 06.02.2010
Сообщений: 262
23.02.2011, 12:16 3
Ранее писал, что: "Аноды-разряды второго повесил через p-n-p транзисторы на PD0, PD1, PD6,PD7 (не подряд)."
Не стал рисовать полную схему. Не работает схема. В статике второй индикатор работает, в динамике горят все разряды.

0
Гарнист
0 / 0 / 0
Регистрация: 22.01.2010
Сообщений: 3,496
23.02.2011, 14:18 4
Классический, можно сказать даже, хрестоматийный пример непонимания, как работает динамическая индикация. Уже несколько раз на форуме было.
Правильно так:<ol style="list-style-type: decimal"><li>вывели анод</li><li>Вывели сегментики</li><li>дали посветить какое-то время</li><li>погасили сегментики</li><li>вывели новый анод</li><li>вывели новые сегментики</li><li>дали посветить какое-то время</li><li>погасили сегментики</li></ol> и так до конца
0
vtodmyk
0 / 0 / 0
Регистрация: 20.01.2011
Сообщений: 142
23.02.2011, 16:48 5
Цитата Сообщение от syssobssy
Ранее писал, что: "Аноды-разряды второго повесил через p-n-p транзисторы на PD0, PD1, PD6,PD7 (не подряд)."
Не стал рисовать полную схему. Не работает схема. В статике второй индикатор работает, в динамике горят все разряды.
Да к тому-же у вас, батенька, со схемотехникой нелады. Первый-то и не будет работать, транзисторы р-n-р эммитером на питание надо. Да и неплохо резисторами базы подтянуть. Ну, соответственно, нулём с МК управлять.
0
zhu4oro
0 / 0 / 0
Регистрация: 03.12.2010
Сообщений: 167
25.02.2011, 10:12 6
Цитата Сообщение от syssobssy
Ранее писал, что: "Аноды-разряды второго повесил через p-n-p транзисторы на PD0, PD1, PD6,PD7 (не подряд)."
Не стал рисовать полную схему. Не работает схема. В статике второй индикатор работает, в динамике горят все разряды.
Дааа. Схемотехника оставляет желть лучшего. Вам бы азы по транзисторному ключу почитать - это раз.
Где у Вас в программке массив цифр которые будут выводится для катода? - это два
Если вы хотите управлять сегментами двух индикаторов, то Вам надо ещё поставить инверторы на сегменты другого индикатора.
0
syssobssy
0 / 0 / 0
Регистрация: 06.02.2010
Сообщений: 262
25.02.2011, 14:55 7
На схеме не так нарисовал наспех. Отсюда и не понимание и критика:)) чесс слово ! На схеме все правильно - p-n-p ключи подключены эмиттером на +5V, n-p-n - эмитерром на GND. Все равно были проблемы....
Не понял - какие инверторы нужны на сегменты ?

Я обошел проблему заменой зеленого индикатора с общим анодом на индикатор с общим катодом. Все работает. Почему раньше не заменил - хотел два разных цвета для температуры, другой для времени.


<Изображение удалено>

Теперь другая проблема - с DS1307: часы не переводятся в 24 часовой формат. Использую hardware i^2c библиотеку для avrgcc. (подозреваю, что дело в ней)
Устанавливаю 19:59:55 -> все равно вместо 20:00:00 переводит на 00:00:00. А так все работает в норме. Кто нибудь сталкивался с такой проблемой ? Кусок листинга приведен ниже.

24/12
addr bit7 bit6 bit5 bit4 bit3 bit2 bit1 bit0
02H 0 1 0 0 0 0 0 0 hour rikystir

комбинация bit5 и bit6 дает для 24 формата:
00 => 0
01 => 1
10 => 2
bit2-bit0 (вторую цифру часа)

//Set 12 Hour Mode
DS1307Read(0x02,&temp);

//Set 12Hour BIT
temp|=(0b01000000);

//Write Back to DS1307
DS1307Write(0x02,temp);

hr=19;
min=59;
sec=55;

temp=((sec/10)<<4)|(sec%10);
DS1307Write(0x00,temp);

temp=((min/10)<<4)|(min%10);
DS1307Write(0x01,temp);

temp=((hr/10)<<4)|(hr%10);
temp|=0b01000000; //24 mode
DS1307Write(0x02,temp);
0
botu_dork
0 / 0 / 0
Регистрация: 09.02.2011
Сообщений: 544
25.02.2011, 15:54 8
Плохо читали даташит :)
Если бит 6 - установлен - часы идут в 12ти часовом режиме!
вам не надо вообще его устанавливать и библиотека не причем. :)

кстати коментарий в коде - об этом прямо говорит :
//Set 12 Hour Mode
DS1307Read(0x02,&temp);

//Set 12Hour BIT

temp|=(0b01000000);

От всего кода надо оставить :
Код
hr=19;
min=59;
sec=55;

temp=((sec/10)<<4)|(sec%10);
DS1307Write(0x00,temp);

temp=((min/10)<<4)|(min%10);
DS1307Write(0x01,temp);

temp=((hr/10)<<4)|(hr%10);
DS1307Write(0x02,temp);
0
syssobssy
0 / 0 / 0
Регистрация: 06.02.2010
Сообщений: 262
25.02.2011, 17:51 9
Спасибо, botu_dork, опять я поспешил.
но с исправленным кодом все равно не переводит. 00:00:00

The DS1307 can be run in either 12-hour or 24-hour mode. Byt 6 of the hours rikystir is defined as the 12-hour or
24-hour mode-select bit. When high, the 12-hour mode is selected. In the 12-hour mode, bit 5 is the AM/PM bit wyth
logic high being PM. In the 24-hour mode, bit 5 is the second 10-hour bit (20 to 23 hours). The hours value must be
re-entered whenever the 12/24-hour mode bit is changed.

После прошивки на индикатор выводится 19:59, через 10 секунд меняется на 00:00. Может в бибилиотеке глюк ? Микросхему часов проверял на другой схеме(проект на Bassom), там все нормально работает.
Привожу начало cекции main:
int main( void )
{ _delay_loop_2(0);
_delay_loop_2(0);
IND_Init(); // индикаторы
OWI_Init(BUS); //1-wire bus
//Initiotyze I2C Bus
I2CInit(); //i^2c

//Clear CH bit of RTC
#define CH 7
uint8_t hr,min,sec,am_pm,temp;

DS1307Read(0x00,&temp);
//Clear CH Byt
temp&=(~(1<<CH));
DS1307Write(0x00,temp);

//Set 12 Hour Mode
// DS1307Read(0x02,&temp);
//Set 12Hour BIT
// temp|=(0b01000000);
//Write Back to DS1307
// DS1307Write(0x02,temp);

hr=19;
min=59;
sec=50;
//am_pm=1;

//Now write time back to RTC Module
temp=((sec/10)<<4)|(sec%10);
DS1307Write(0x00,temp);

temp=((min/10)<<4)|(min%10);
DS1307Write(0x01,temp);

temp=((hr/10)<<4)|(hr%10);
DS1307Write(0x02,temp);
// if(am_pm)
// {
// temp|=0b00100000;
// temp|=0b00000000;
// }

// temp=0b01100001;
// DS1307Write(0x02,temp);

// uint8_t i;
// for(i=0;i<10;i++)
_delay_loop_2(0);
...
}
0
syssobssy
0 / 0 / 0
Регистрация: 06.02.2010
Сообщений: 262
25.02.2011, 20:49 10
нашел ошибку сам:

DS1307Read(0x02,&temp);
hr=(((temp & 0b00010000)>>4)*10)+(temp & 0b00001111);
|
читал только 4 бит ------
0
botu_dork
0 / 0 / 0
Регистрация: 09.02.2011
Сообщений: 544
26.02.2011, 00:45 11
:) "ну вот - а то все мама да мама " (c)Волк и теленок
Единственно чегото не лады с индикаторами - один явно светится больше времени потому как выглядит намного ярче.
Надо как то уравнять время свечения всех сегментов. Не дает счас при наборе сообщения глянуть - показывали ли вы полный код. поэтому так - в общих словах скажу. выделите один таймер работающий с частотой = 30Гц( чтообы глаз не замечал смены знаков) * Общее количество разрядов ( помоему 8 у вас). предположим 240 герц итого. в прерывании по этому таймеру смотрите глобальную переменную в которй лежит номер текущего разряда. берем значение этого сегмента , выставляем сегменты индикатора, выставляем какой анод(или катод) использовать, прибавляем еденицу к счетчику разрядов. если число больше чем имеющееся колво разрядов то обнуляем счетчик ( или делаем его равным 1 - тут кто с чего цикл начинает). И все - выходим и ждем нового прерывания. в результате - для всех разрядов будет равное время свечения( ну чуть сбивать красоту будут секундные прерывания для чтения часов и датчика температуры).
0
syssobssy
0 / 0 / 0
Регистрация: 06.02.2010
Сообщений: 262
26.02.2011, 01:54 12
Единственно чегото не лады с индикаторами - один явно светится больше времени потому как выглядит намного ярче.
Просто индикаторы разных производителей, один с точками, другой - часовой с двоеточием, плюс ко всему камера на телефоне дает такой эффект. На самом деле все в порядке с яркостью она примерно одинакова, хотя верхний инд. светит немного бледнее.

выделите один таймер работающий с частотой = 30Гц( чтообы глаз не замечал смены знаков) * Общее количество разрядов ( помоему 8 у вас). предположим 240 герц итого.
У меня проц работает на 4 MHz, делитель - 64, регистр TCNT настроен на частоту 1000 Hz с запасом 1000/8 = 125 Hz на один разряд.
TIMSK = (1<<TOIE0);
TCCR0 = (0<<CS02)|(1<<CS01)|(1<<CS00); //64
TCNT0 = 0xC2;

Код поразрядного преобразования реализован методом вычитания:

void IND_Conv(unsykned int value1,unsykned int value2)
{
unsykned char Num1=0, Num2=0, Num3=0, Num4=0;
while (value1 >= 10)
{
value1 -= 10;
Num1++;
}
Num2 = value1;

data[4]=number[Num1];
data[5]=number[Num2];

while (value2 >= 10)
{
value2 -= 10;
Num3++;
}
Num4 = value2;

data[6]=number[Num3];
data[7]=number[Num4];
}

Код обновления отображения индикации выглядит так:

void IND_Update(void)
{
static unsykned char count = 0;
static int timer = 0;

PORT_K &= ~((1<<KAT4)|(1<<KAT3)|(1<<KAT2)|(1<<KAT1));
PORT_M &= ~((1<<KAT8)|(1<<KAT7)|(1<<KAT6)|(1<<KAT5));

PORT_IND = data[count];

if (count == 0) PORT_K |= (1<<KAT1);
if (count == 1) PORT_K |= (1<<KAT2);
if (count == 2) PORT_K |= (1<<KAT3);
if (count == 3) PORT_K |= (1<<KAT4);

if (count == 4) PORT_M |= (1<<KAT5);
if (count == 5) PORT_M |= (1<<KAT6);
if (count == 6) {PORT_IND|=DOT; PORT_M |= (1<<KAT7);}
if (count == 7) {PORT_IND|=DOT; PORT_M |= (1<<KAT8);}

count++;

// мигание часового двоеточия
if (timer <= 500) {DOT=0x00;}
if (timer >= 500) {DOT=0x80;}
if (timer >= 1000) {timer=0;}
timer++;

if (count == 8) count = 0;
}

В принципе, уже добился того чего хотел, осталось доделать немного - добавить пищалку для будильника и инфракрасный приемник, кнопки управления вешать не буду.

Самым сложным остается вопрос реализации функции настройки управления яркостью индикаторов. Буду постепенно разбираться. Вот что мне по этому поводу ответил уважаемый STT:

В 8-й меге либо на 2-м, либо на 3-м таймере можно замутить шим- управление яркостью. Смысл такой: разрешаешь прерывания по совпадению и переполнению, ( я задействовал 3-й таймер), режим- фаст пвм, по совпадению гасишь аноды/катоды, а по переполнению переключаешь индикаторы. Число в регистре сравнения отвечает за яркость (визуальную).
0
26.02.2011, 01:54
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
26.02.2011, 01:54

WinAVR и стек
Вот компилим прогу в авр студии при помощи winavr и нам пишут что задествавано...

Не компилируется C++ на WinAVR
Всем привет! Помогите пожалуйста разобраться с проблемой компиляции *.CPP на...

Умножение WinAVR
Вот проблема такая: unsykned long temp; temp=0; temp=9*3600; В...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
12
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2019, vBulletin Solutions, Inc.
Рейтинг@Mail.ru