Часы AVR ATMega 8, 7 сегментный индикатор

Модератор: boogyman

Часы AVR ATMega 8, 7 сегментный индикатор

Сообщение:#1  Сообщение ASDFG123 » 25 июл 2012, 13:16

Помогите допилить код часов из примера, на семисегментном индикаторе. Моделирую в протэусе, проблема в том что идут не точно.
Вот код
Код: Выделить всё
#define F_CPU 8000000UL
#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>
#include "display.h"

volatile unsigned char second, minute, hour, level;

ISR(TIMER2_COMP_vect)   // обработчик прерывания по совпадению Т2
{                       
second++;            // увеличиваем секунды
if(second == 60)        // если second = 60, second = 0
{  second = 0;
   minute++;            // увеличиваем минуты
if(minute == 60)        // если minute = 60, minute = 0
{  minute = 0;
   hour++;              // увеличиваем часы
if(hour == 24)          // если hour = 24, hour = 0
   hour = 0;
}
}

set_time(hour,minute,second);

}

int main(void)
{
hour = 12;   // начальная установка времени
minute = 0;
second = 0;

DDRB |= (0 << PB5)|(0 << PB4);
PORTB |= (1 << PB5)|(1 << PB4);
TCNT2=0; 
TCCR2|=(1<<CS20)|(1<<CS21)|(1<<CS22)|(1<<WGM21); // 32768/256 =32hz запуск Т2 (CTC ?)
ASSR|=(1<<AS2); //ассинхронный режим
 
OCR2=25-1; //регистр сравнения (пришлось поставить так, точность ближе)

sei();                 // глобально разрешам прерывания

set_brightness(80);   // начальная установка яркости дисплея
display_init();        // инициализация дисплея

shift_in('t'); // выводим бегущую строку "test display"
_delay_ms(50);
shift_in('E');
_delay_ms(50);
shift_in('s');
_delay_ms(50);
shift_in('t');
_delay_ms(50);
shift_in(' ');
_delay_ms(50);
shift_in('d');
_delay_ms(50);
shift_in('i');
_delay_ms(50);
shift_in('s');
_delay_ms(50);
shift_in('p');
_delay_ms(50);
shift_in('L');
_delay_ms(50);
shift_in('a');
_delay_ms(50);
shift_in('y');
_delay_ms(50);
shift_in(' ');
_delay_ms(50);
shift_in(' ');
_delay_ms(50);
shift_in(' ');
_delay_ms(50);
clear_screen();
_delay_ms(100);

TIMSK |= (1<<OCIE2); // разрешаем прерывание по совпадению Т2


while(1)
{   
unsigned char i, dr;

if((PINB&(1 << PB4))==0 && (PINB&(1 << PB5))==0)// если кнопка Часы+ и Минуты+ нажаты
{
dr=0;
for (i=0;i<10;i++)
  { // программный антидребезг контактов
   _delay_ms(5);
   if((PINB&(1 << PB4))==0 && (PINB&(1 << PB5))==0)
   dr++;
  }
if(dr > 5)
  {
   if(level != 99)
   level++;   // увеличиваем яркость
   else level = 0;
   set_brightness(level);
  }
}

if((PINB&(1 << PB4))==0 && PINB&(1 << PB5)) // если кнопка Часы+ нажата
{
dr=0;
for (i=0;i<10;i++)
  { // программный антидребезг контактов
   _delay_ms(5);
   if((PINB&(1 << PB4))==0)
   dr++;
  }
if(dr > 5)
  {
   if(hour != 23) hour++;   // увеличиваем часы
   else hour = 0;
   set_time(hour,minute,second);
  }
}

if((PINB&(1 << PB5))==0 && PINB&(1 << PB4)) // если кнопка Минуты+ нажата
{
dr=0;
for (i=0;i<10;i++)
  { // программный антидребезг контактов
   _delay_ms(5);
   if((PINB&(1 << PB5))==0)
   dr++;
  }
if (dr > 5)
  {
   if(minute != 59) minute++;   // увеличиваем минуты
   else minute = 0;
   set_time(hour,minute,second);
  }
}

}
}


Прогу я чуть поменял, запустил асинхроный режим Т2, обратите внимание на регистр сравнения при таком значении через 2-3 часа прогона в протэусе часы начинают спешить на 1-2 минуты. (если ставить больше то отстают, если поставить как положено (32-1) то отстают очень сильно.
Часы хочу сделать в железе, но нужно чтоб они шли точно, возможно постараюсь еще чем нб их функционал повысить. Всем спасибо
Аватара пользователя
ASDFG123
Любитель
 
Сообщения: 16
Зарегистрирован: 26 фев 2012, 08:30

Re: Часы AVR ATMega 8, 7 сегментный индикатор

Сообщение:#2  Сообщение boogyman » 25 июл 2012, 17:27

Асинхронный режим таймера это правильно. Попробуй поставь часовой кварц. Девайс лучше налаживать в железе.
Аватара пользователя
boogyman
Модератор
 
Сообщения: 183
Зарегистрирован: 25 дек 2011, 21:48
Откуда: Москва

Re: Часы AVR ATMega 8, 7 сегментный индикатор

Сообщение:#3  Сообщение ASDFG123 » 25 июл 2012, 18:16

Если собрать в железе будет ли свобода маневра? для модификации и т.д (меги 8 я уже заказал терь жду)
На микрах в железе ничего не делал еще :(
Как можно сделать чтоб контроллер сидел в плате впаян, и его можно было перепрошивать и т.д может выводы какие в разьем ввести ?
п.с что значит часовой кварц ? в протэусе в настройках поставил 32768 Гц
Аватара пользователя
ASDFG123
Любитель
 
Сообщения: 16
Зарегистрирован: 26 фев 2012, 08:30

Re: Часы AVR ATMega 8, 7 сегментный индикатор

Сообщение:#4  Сообщение boogyman » 25 июл 2012, 18:26

ASDFG123 писал(а):п.с что значит часовой кварц ? в протэусе в настройках поставил 32768 Гц

Ставишь кварц на 32768 Гц, настраиваешь предделитель таймера на 128 и у тебя таймер будет прерываться точно раз в секунду, это как вариант.
ASDFG123 писал(а):Как можно сделать чтоб контроллер сидел в плате впаян, и его можно было перепрошивать и т.д может выводы какие в разьем ввести ?
программатор подключаешь к выводам Reset, Mosi, Miso, SCK, подключаешь питание вот тебе и внутрисхемное программирование
Аватара пользователя
boogyman
Модератор
 
Сообщения: 183
Зарегистрирован: 25 дек 2011, 21:48
Откуда: Москва

Re: Часы AVR ATMega 8, 7 сегментный индикатор

Сообщение:#5  Сообщение ASDFG123 » 31 авг 2012, 18:22

Уже купил большую часть деталей, индикатор не брал еще но скорее всего ОА. Еще купил DS18b20, хотелось бы, приделать термометр и будильник, конечно не ущерб в точности часов. Попытался к готовой проге часов с библиотекой для 7сегментиков, приделать прогу для DS18b20 не заработало ничего, хотел сделать так, по нажатию кнопки на дисплей выводится темпа которая уже была расчитана заранее, а часы продолжали тикать, и через секунд 5 обратно выводились часы. А еще ключ в протэусе хотел проверить на Р-Н-Р для ОА, в симуляторе показывает крякозябы, в библиотеке порты инвертировал не помогло
Аватара пользователя
ASDFG123
Любитель
 
Сообщения: 16
Зарегистрирован: 26 фев 2012, 08:30

Re: Часы AVR ATMega 8, 7 сегментный индикатор

Сообщение:#6  Сообщение AntonChip » 31 авг 2012, 20:57

Хочешь точные часы используй DS1307.
Аватара пользователя
AntonChip
Администратор
 
Сообщения: 200
Зарегистрирован: 24 дек 2011, 21:11
Откуда: Киров

Re: Часы AVR ATMega 8, 7 сегментный индикатор

Сообщение:#7  Сообщение ASDFG123 » 31 авг 2012, 21:58

их я тоже рассматривал но у нас они дорого стоят раза в 2 больше чем мега8, да и всех функций ее реализовать не смогу.
а точности я думаю можно добится если на пример каждые 10 часов прибавлять 1 сек,(эмпирически высчитать) это ведь можно реализовать?

В библиотеке что надо поправить для запуска индикации через ключи, р-н-р и н-р-н транзы в наличии, sbi cbi в самом начале библиотекики менял не помогло.
вот код
Код: Выделить всё
#define F_CPU 8000000UL
#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>
#include "display.h"

 
#include "OWIPolled.h"
#include "OWIHighLevelFunctions.h"
#include "OWIBitFunctions.h"
#include "OWIcrc.h"

#define DS18B20_CONVERT_T                0x44
#define DS18B20_READ_SCRATCHPAD          0xbe
#define BUS   OWI_PIN_0

unsigned char scratchpad[9];
volatile unsigned char second, minute, hour, level;
 
ISR(TIMER2_COMP_vect)   // обработчик прерывания по совпадению Т2
{                       
second++;            // увеличиваем секунды
if(second == 60)        // если second = 60, second = 0
{  second = 0;
   minute++;            // увеличиваем минуты
if(minute == 60)        // если minute = 60, minute = 0
{  minute = 0;
   hour++;              // увеличиваем часы
if(hour == 24)          // если hour = 24, hour = 0
   hour = 0;
}
}
 
set_time(hour,minute,second);
 
}
 
int main(void)
{
hour = 12;   // начальная установка времени
minute = 0;
second = 0;
 
unsigned int tmp = 0;
  unsigned char temperature;
unsigned int tempint = 0,tempint1,tempint2,tempint3;
unsigned int temppoint = 0,temppoint1;
OWI_Init(BUS);
 
DDRB |= (0 << PB5)|(0 << PB4);
PORTB |= (1 << PB5)|(1 << PB4);
DDRC |= (0<<PC1);
PORTC |= (1 << PC1);
TCNT2=0; 
TCCR2|=(1<<CS20)|(0<<CS21)|(1<<CS22)|(1<<WGM21); // 32768/128 =256hz запуск Т2 (CTC ?)
ASSR|=(1<<AS2); //ассинхронный режим
 
OCR2=(203); //регистр сравнения (пришлось поставить так, точность ближе)
 
sei();                 // глобально разрешам прерывания
 
set_brightness(80);   // начальная установка яркости дисплея
display_init();        // инициализация дисплея
 
shift_in('t'); // выводим бегущую строку "test display"
_delay_ms(50);
shift_in('E');
_delay_ms(50);
shift_in('s');
_delay_ms(50);
shift_in('t');
_delay_ms(50);
shift_in(' ');
_delay_ms(50);
shift_in('d');
_delay_ms(50);
shift_in('i');
_delay_ms(50);
shift_in('s');
_delay_ms(50);
shift_in('p');
_delay_ms(50);
shift_in('L');
_delay_ms(50);
shift_in('a');
_delay_ms(50);
shift_in('y');
_delay_ms(50);
shift_in(' ');
_delay_ms(50);
shift_in(' ');
_delay_ms(50);
shift_in(' ');
_delay_ms(50);
clear_screen();
_delay_ms(100);
 
TIMSK |= (1<<OCIE2); // разрешаем прерывание по совпадению Т2
while(1)
{   
 
 
 
unsigned char i, dr;
 
 
 
if((PINB&(1 << PB4))==0 && (PINB&(1 << PB5))==0)// если кнопка Часы+ и Минуты+ нажаты
{
dr=0;
for (i=0;i<10;i++)
  { // программный антидребезг контактов
   _delay_ms(10);
   if((PINB&(1 << PB4))==0 && (PINB&(1 << PB5))==0)
   dr++;
  }
if(dr > 5)
  {
   if(level != 99)
   level++;   // увеличиваем яркость
   else level = 0;
   set_brightness(level);
  }
}
 
if((PINB&(1 << PB4))==0 && PINB&(1 << PB5)) // если кнопка Часы+ нажата
{
dr=0;
for (i=0;i<10;i++)
  { // программный антидребезг контактов
   _delay_ms(10);
   if((PINB&(1 << PB4))==0)
   dr++;
  }
if(dr > 5)
  {
     second = 0;
   if(hour != 23) hour++;   // увеличиваем часы
   else hour = 0;
   set_time(hour,minute,second);
  }
}
 
if((PINB&(1 << PB5))==0 && PINB&(1 << PB4)) // если кнопка Минуты+ нажата
{
dr=0;
for (i=0;i<10;i++)
  { // программный антидребезг контактов
   _delay_ms(10);
   if((PINB&(1 << PB5))==0)
   dr++;
  }
if (dr > 5)
  {
     second = 0;
   if(minute != 59) minute++;   // увеличиваем минуты
   else minute = 0;
   set_time(hour,minute,second);
  }
  }
 
 
 
 
 
 
if((PINC&(1 << PC1))==0) // если кнопка темп нажата
{
dr=0;
for (i=0;i<10;i++)
  { // программный антидребезг контактов
   _delay_ms(10);
   if((PINC&(1 << PC1))==0)
   dr++;
  }
if (dr > 5)
  {
   OWI_DetectPresence(BUS); //а тут программа термодатчика
    OWI_SkipRom(BUS);
    OWI_SendByte(DS18B20_CONVERT_T ,BUS);
   /*ждем, когда датчик завершит преобразование*/
    while (!OWI_ReadBit(BUS));
 
    /*подаем сигнал сброса
    команду для адресации всех устройств на шине
    команду - чтение внутренней памяти
    затем считываем внутреннюю память датчика в массив
    */
    OWI_DetectPresence(BUS);
    OWI_SkipRom(BUS);
    OWI_SendByte(DS18B20_READ_SCRATCHPAD, BUS);
    scratchpad[0] = OWI_ReceiveByte(BUS);
    scratchpad[1] = OWI_ReceiveByte(BUS);
 
   if ((scratchpad[1]&128) == 0){ }
    else{
      tmp = ((unsigned int)scratchpad[1]<<8)|scratchpad[0];
      tmp = ~tmp + 1;
      scratchpad[0] = tmp;
      scratchpad[1] = tmp>>8; 
    }
 
temperature = (scratchpad[0]<< 4)& 0x70|((scratchpad[1])>> 4); // тут пытался разделить по сегментам
tempint1 = temperature % 1000 / 100;
tempint2 = temperature % 100 / 10;
tempint3 = temperature % 10;
 
set_char_at(tempint1, 0);
set_char_at(tempint2, 1);
set_char_at(tempint3, 2);
set_char_at('t', 3);
  }
  }
}
 
}
Аватара пользователя
ASDFG123
Любитель
 
Сообщения: 16
Зарегистрирован: 26 фев 2012, 08:30

Re: Часы AVR ATMega 8, 7 сегментный индикатор

Сообщение:#8  Сообщение ASDFG123 » 30 сен 2012, 18:24

//#define SET_DIGIT cbi
//#define CLEAR_DIGIT sbi
//#define SET_SEGMENT sbi
//#define CLEAR_SEGMENT cbi
как переделать под ключи на pnp транзах ? индикатор ОА
Аватара пользователя
ASDFG123
Любитель
 
Сообщения: 16
Зарегистрирован: 26 фев 2012, 08:30

Re: Часы AVR ATMega 8, 7 сегментный индикатор

Сообщение:#9  Сообщение boogyman » 01 окт 2012, 14:15

Где, в какой библиотеке править? Не вижу?
Аватара пользователя
boogyman
Модератор
 
Сообщения: 183
Зарегистрирован: 25 дек 2011, 21:48
Откуда: Москва

Re: Часы AVR ATMega 8, 7 сегментный индикатор

Сообщение:#10  Сообщение ASDFG123 » 01 окт 2012, 17:29

Код: Выделить всё
#include <avr/io.h>
#include <avr/interrupt.h>
#include "display.h"

// Выбираем тип подключения дисплея OA или OK
// common anode
#define SET_DIGIT sbi
#define CLEAR_DIGIT cbi
#define SET_SEGMENT cbi
#define CLEAR_SEGMENT sbi

// common cathode
//#define SET_DIGIT cbi
//#define CLEAR_DIGIT sbi
//#define SET_SEGMENT sbi
//#define CLEAR_SEGMENT cbi

#define sbi(var, mask)   ((var) |= (uint8_t)(1 << mask))
#define cbi(var, mask)   ((var) &= (uint8_t)~(1 << mask))

char data[4]; // Digit data
char segment_data[4]; // Segment data

// dots [bit 0~3]
uint8_t dots = 0;

uint16_t brightness = 80;   // Read from EEPROM on startup

void display(uint8_t pos, uint8_t digit);
void clearDisplay(void);

void display_init(void)
{
   // set digits as output
   sbi(DIGIT1_DDR, DIGIT1_BIT);
   sbi(DIGIT2_DDR, DIGIT2_BIT);
   sbi(DIGIT3_DDR, DIGIT3_BIT);
   sbi(DIGIT4_DDR, DIGIT4_BIT);
   
   // set segments as output
   sbi(A_DDR,  A_BIT);
   sbi(B_DDR,  B_BIT);
   sbi(C_DDR,  C_BIT);
   sbi(D_DDR,  D_BIT);
   sbi(E_DDR,  E_BIT);
   sbi(F_DDR,  F_BIT);
   sbi(G_DDR,  G_BIT);
   sbi(DP_DDR, DP_BIT);

   // clear screen
   clear_screen();

   sei();   // Enable interrupts

   // Inititalize timer for multiplexing
   TCCR0 = (1<<CS01); // Set Prescaler to clk/8 : 1 click = 1us. CS01=1
   TIMSK |= (1<<TOIE0); // Enable Overflow Interrupt Enable
   TCNT0 = 0; // Initialize counter
}

uint8_t set_brightness(uint8_t b)
{
   if (b > 100) b = 100;
   b = 100 - b;

   brightness = b + 5;
   return b;
}

void shift_in(char c)
{
   data[0] = data[1];
   data[1] = data[2];
   data[2] = data[3];
   data[3] = c;

   segment_data[0] = segment_data[1];
   segment_data[1] = segment_data[2];
   segment_data[2] = segment_data[3];
   segment_data[3] = 0;
}

void set_char_at(char c, uint8_t offset)
{
   data[offset] = c;
}

void set_segments_at(uint8_t segments, uint8_t offset)
{
   segment_data[offset] = segments;
   data[offset] = 0b10000000; // set upper bit to indicate that segment data should be used for display
}

void shift_in_segments(uint8_t segments)
{
   data[0] = data[1];
   data[1] = data[2];
   data[2] = data[3];
   data[3] = 0b10000000; // set upper bit to indicate that segment data should be used for display

   segment_data[0] = segment_data[1];
   segment_data[1] = segment_data[2];
   segment_data[2] = segment_data[3];
   segment_data[3] = segments;
}

// show number on screen
void set_number(uint16_t num)
{
   data[3] = num % 10;
   num /= 10;
   data[2] = num % 10;
   num /= 10;
   data[1] = num % 10;
   num /= 10;
   data[0] = num % 10;
   dots = 0;
}

void clear_screen(void)
{
   data[0] = ' '; data[1] = ' '; data[2] = ' '; data[3] = ' ';
   cbi(dots, 2);
}

void set_time(uint8_t hour, uint8_t min, uint8_t sec)
{
   set_number(hour * 100 + min);
   if (sec % 2) sbi(dots, 2); // set dot 1 on
   else cbi(dots, 2); // set dot 1 off
}

void set_dots(void)
{
   sbi(dots, 3); // set dot 1 on
}

uint8_t multiplex_counter = 0;

// display multiplexing routine: run once every 5us
void display_multiplex(void)
{
   if (multiplex_counter == 0)
      display(0, 1);
   else if (multiplex_counter == 1)
      display(1, 2);
   else if (multiplex_counter == 2)
      display(2, 3);
   else if (multiplex_counter == 3)
      display(3, 4);
   else if (multiplex_counter == 4)
      clearDisplay();

   multiplex_counter++;

   // brightness setting: 5~100
   if (multiplex_counter == brightness) multiplex_counter = 0;
}

// run once every 1 us
ISR(TIMER0_OVF_vect)
{
   display_multiplex();   
   TCNT0 = 0xFF - 12; // Overflow again after 10 ticks = 10 us
}

uint8_t calculate_segments(uint8_t character)
{
   uint8_t segments = 0;

   switch (character)
   {
      case 0:
      case '0':
      case 'O':
         segments = (1<<A)|(1<<B)|(1<<C)|(1<<D)|(1<<E)|(1<<F);
         break;
      case 1:
      case '1':
      case 'l':
         segments = (1<<B)|(1<<C);
         break;
      case 2:
      case '2':
         segments = (1<<A)|(1<<B)|(1<<D)|(1<<E)|(1<<G);
         break;
      case 3:
      case '3':
         segments = (1<<A)|(1<<B)|(1<<C)|(1<<D)|(1<<G);
         break;
      case 4:
      case '4':
         segments = (1<<B)|(1<<C)|(1<<F)|(1<<G);
         break;
      case 5:
      case '5':
      case 'S':
      case 's':
         segments = (1<<A)|(1<<C)|(1<<D)|(1<<F)|(1<<G);
         break;
      case 6:
      case '6':
         segments = (1<<A)|(1<<C)|(1<<D)|(1<<E)|(1<<F)|(1<<G);
         break;
      case 7:
      case '7':
         segments = (1<<A)|(1<<B)|(1<<C);
         break;
      case 8:
      case '8':
         segments = (1<<A)|(1<<B)|(1<<C)|(1<<D)|(1<<E)|(1<<F)|(1<<G);
         break;
      case 9:
      case '9':
      case 'g':
         segments = (1<<A)|(1<<B)|(1<<C)|(1<<D)|(1<<F)|(1<<G);
         break;
      case 10:
      case 'A':
      case 'a':
         segments = (1<<A)|(1<<B)|(1<<C)|(1<<E)|(1<<F)|(1<<G);
         break;
      case 11:
      case 'B':
      case 'b':
         segments = (1<<C)|(1<<D)|(1<<E)|(1<<F)|(1<<G);
         break;
      case 12:
      case 'C':
         segments = (1<<A)|(1<<D)|(1<<E)|(1<<F);
         break;
      case 'c':
         segments = (1<<D)|(1<<E)|(1<<G);
         break;
      case 13:
      case 'D':
      case 'd':
         segments = (1<<B)|(1<<C)|(1<<D)|(1<<E)|(1<<G);
         break;
      case 14:
      case 'E':
         segments = (1<<A)|(1<<D)|(1<<E)|(1<<F)|(1<<G);
         break;
      case 'e':
         segments = (1<<A)|(1<<B)|(1<<D)|(1<<E)|(1<<F)|(1<<G);
         break;
      case 15:
      case 'F':
      case 'f':
         segments = (1<<A)|(1<<E)|(1<<F)|(1<<G);
         break;
      case 'G':
         segments = (1<<A)|(1<<C)|(1<<D)|(1<<E)|(1<<F);
         break;
      case 'H':
         segments = (1<<B)|(1<<C)|(1<<E)|(1<<F)|(1<<G);
         break;
      case 'h':
         segments = (1<<C)|(1<<E)|(1<<F)|(1<<G);
         break;
      case 'I':
      case 'i':
         segments = (1<<B)|(1<<C);
         break;
      case 'J':
      case 'j':
         segments = (1<<B)|(1<<C)|(1<<D)|(1<<E);
         break;
      case 'L':
         segments = (1<<D)|(1<<E)|(1<<F);
         break;
      case 'M':
      case 'm':
         segments = (1<<A)|(1<<C)|(1<<E)|(1<<G);
         break;
      case 'N':
      case 'n':
         segments = (1<<C)|(1<<E)|(1<<G);
         break;
      case 'o':
         segments = (1<<C)|(1<<D)|(1<<E)|(1<<G);
         break;
      case 'P':
      case 'p':
         segments = (1<<A)|(1<<B)|(1<<E)|(1<<F)|(1<<G);
         break;
      case 'Q':
      case 'q':
         segments = (1<<A)|(1<<B)|(1<<C)|(1<<F)|(1<<G);
         break;
      case 'R':
      case 'r':
         segments = (1<<E)|(1<<G);
         break;
      case 'T':
      case 't':
         segments = (1<<D)|(1<<E)|(1<<F)|(1<<G);
         break;
      case 'U':
         segments = (1<<B)|(1<<C)|(1<<D)|(1<<E)|(1<<F);
         break;
      case 'u':
         segments = (1<<C)|(1<<D)|(1<<E);
         break;
      case 'V':
      case 'v':
         segments = (1<<C)|(1<<D)|(1<<E);
         break;
      case 'W':
      case 'w':
         segments = (1<<A)|(1<<C)|(1<<D)|(1<<E);
         break;
      case 'Y':
      case 'y':
         segments = (1<<B)|(1<<C)|(1<<D)|(1<<F)|(1<<G);
         break;
      case '-':
         segments = (1<<G);
         break;
      case '"':
         segments = (1<<B)|(1<<F);
         break;
      case 0x27:   // "'"
         segments = (1<<B);
         break;
      case '_':
         segments = (1<<D);
         break;
      case ' ':
      default:
         segments = 0;
         break;
   }

   return segments;
}

// Output number to digit 0, 1, 2 or 3
void display(uint8_t pos, uint8_t digit)
{   
   clearDisplay();

   //  Turn on selected digit
   switch (digit)
   {
      case 1:
         SET_DIGIT(DIGIT1_PORT, DIGIT1_BIT);
         break;
      case 2:
         SET_DIGIT(DIGIT2_PORT, DIGIT2_BIT);
         break;
      case 3:
         SET_DIGIT(DIGIT3_PORT, DIGIT3_BIT);
         break;   
      case 4:
         SET_DIGIT(DIGIT4_PORT, DIGIT4_BIT);
         break;
   }

   uint8_t segments = 0;

   if (data[pos] & 0b10000000)
      segments = segment_data[pos];
   else
      segments = calculate_segments(data[pos]);
   
   // set dot
   if (dots & (1<<digit))
      segments |= (1<<DP);

   // This allows segments do be on different ports
   if (segments & _BV(7)) SET_SEGMENT(DP_PORT, DP_BIT);
   else CLEAR_SEGMENT(DP_PORT, DP_BIT);

   if (segments & _BV(6)) SET_SEGMENT(G_PORT, G_BIT);
   else CLEAR_SEGMENT(G_PORT, G_BIT);

   if (segments & _BV(5)) SET_SEGMENT(F_PORT, F_BIT);
   else CLEAR_SEGMENT(F_PORT, F_BIT);

   if (segments & _BV(4)) SET_SEGMENT(E_PORT, E_BIT);
   else CLEAR_SEGMENT(E_PORT, E_BIT);

   if (segments & _BV(3)) SET_SEGMENT(D_PORT, D_BIT);
   else CLEAR_SEGMENT(D_PORT, D_BIT);

   if (segments & _BV(2)) SET_SEGMENT(C_PORT, C_BIT);
   else CLEAR_SEGMENT(C_PORT, C_BIT);
         
   if (segments & _BV(1)) SET_SEGMENT(B_PORT, B_BIT);
   else CLEAR_SEGMENT(B_PORT, B_BIT);

   if (segments & _BV(0)) SET_SEGMENT(A_PORT, A_BIT);
   else CLEAR_SEGMENT(A_PORT, A_BIT);
}

void clearDisplay(void)
{
   // all digits low
   CLEAR_DIGIT(DIGIT1_PORT, DIGIT1_BIT);
   CLEAR_DIGIT(DIGIT2_PORT, DIGIT2_BIT);
   CLEAR_DIGIT(DIGIT3_PORT, DIGIT3_BIT);
   CLEAR_DIGIT(DIGIT4_PORT, DIGIT4_BIT);
   
   // all segments high
   CLEAR_SEGMENT(A_PORT,  A_BIT);
   CLEAR_SEGMENT(B_PORT,  B_BIT);
   CLEAR_SEGMENT(C_PORT,  C_BIT);
   CLEAR_SEGMENT(D_PORT,  D_BIT);
   CLEAR_SEGMENT(E_PORT,  E_BIT);
   CLEAR_SEGMENT(F_PORT,  F_BIT);
   CLEAR_SEGMENT(G_PORT,  G_BIT);
   CLEAR_SEGMENT(DP_PORT, DP_BIT);
}
В этой библиотеке
Аватара пользователя
ASDFG123
Любитель
 
Сообщения: 16
Зарегистрирован: 26 фев 2012, 08:30

Re: Часы AVR ATMega 8, 7 сегментный индикатор

Сообщение:#11  Сообщение boogyman » 01 окт 2012, 18:38

Какой тип подключения нужен, надо раскомментировать его дефайны, другой тип комментируем и наоборот. Сейчас выбрано с общим анодом
Аватара пользователя
boogyman
Модератор
 
Сообщения: 183
Зарегистрирован: 25 дек 2011, 21:48
Откуда: Москва

Re: Часы AVR ATMega 8, 7 сегментный индикатор

Сообщение:#12  Сообщение ASDFG123 » 01 окт 2012, 19:12

так мне тоже нужен ОА, но с ключами на ПНП транзах. У них наскоко я знаю лог 1 выставляется при 0 на базах (без ключей горят при 1), а 8 катодов (7 сег и точка) не меняются
п.с протеус как мне кажется оч сильно гонит, пытаюсь просимулировать с ключами и показывает абракадабру на всех сегментах, скоро разведу норм плату под дисплей.
Аватара пользователя
ASDFG123
Любитель
 
Сообщения: 16
Зарегистрирован: 26 фев 2012, 08:30


Вернуться в Микроконтроллеры AVR

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 1

cron
Rambler's Top100