Sari la conținut
ELFORUM - Forumul electronistilor

Proiect cu tub VFD


Chiriac D

Postări Recomandate

Salutare, am un tub vfd de la un Mayak vechi si nu gasesc niciun intregrat in prezent care mai poate lucra cu asa ceva. Am gasit o schema de la un baiat istet care a folosit ca uC un Atmega. Dificultatea intervine atunci cand incerc sa inteleg limbajul, acesta fiind in asamblare nu imi pot da seama unde pot modifica codul astfel incat sa il pot face mai pe placul meu.

Daca ma puteti ajuta, chiar cu un sfat as fii recunoscator, iar intrebarile ar fii urmatoarele:

1. Pot lega la pinii 25/27 un jumper, un pin sa citeasca bar/dot iar celalalt sa fie peak hold on/off ?

2. Pot modifica viteza de afisare la semnal, sa mearga mai repede sau mai incet ?

/*
 * VUMeterMayak.cpp
 *
 * Created: 06.01.2015 14:42:10
 *  Author: Volstr
 */ 

#define F_CPU 1000000L

#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>

typedef unsigned char BYTE;

static BYTE memADCSRA = 0;
static BYTE memADMUX = 0;

// Координаты нахождения точки максимального уровня
static int PointMaxLeft = 0;
static int PointMaxRight = 0;
// Количество тиков таймера
static int PointTickLeft = 0;
static int PointTickRight = 0;

// Солличество сегментов 
#define DISPLAY_BIT_COUNT 15

// Пауза замирания максимального уровня (точки)
#define POINT_TICK_COUNT 15		// Придостижении максимального уровня
#define POINT_TICK_DOWN	 2		// При спадании

// Обозначаем каналы
enum CHANNEL
{
	CHANNEL_LEFT,
	CHANNEL_RIGHT
};

const BYTE DisplayBits[DISPLAY_BIT_COUNT][2] =
{	// Массив отображения
	// PORTB	 PORTD
	{0b00000000, 0b00000000},	// 0
	{0b00000001, 0b00000000},	// 1
	{0b00000011, 0b00000000},	// 2
	{0b00000111, 0b00000000},	// 3
	{0b00001111, 0b00000000},	// 4
	{0b00011111, 0b00000000},	// 5
	{0b00111111, 0b00000000},	// 6
	{0b01111111, 0b00000000},	// 7
	{0b11111111, 0b00000000},	// 8
	{0b11111111, 0b00000001},	// 9
	{0b11111111, 0b00000011},	// 10
	{0b11111111, 0b00000111},	// 11
	{0b11111111, 0b00001111},	// 12
	{0b11111111, 0b00011111},	// 13
	{0b11111111, 0b00111111}	// 14	Для PORTD 6, 7 бит - переключение сетки
};

BYTE GetAdcValue(const BYTE adc);
void DrawValue(int val, CHANNEL chanel);

void timer0_init()
{
	cli();
	// инициализация таймера0 
	TCCR0 = 0b00000100;
					/* режим Normal(бит 6,3 =0) наиболее простой режим счетный регистр(TCNT0) работает как 
					суммируищий регистр по каждому импульсу присходит инкремент TCNT0 
					при переходе 0xFF->0x00 флаг прерывание по переполнению устанавливается  в 1 
					биты 0-2 управление тактовым сигналом
					000	 таймер остановлен 
					001	 частота кварца делится  на 1
					010  частота кварца делится  на 8   (наш случай при кварце 8мГц =1мГц)
					011  частота кварца делится  на 64
					100  частота кварца делится  на 256
					101  частота кварца делится  на 1024
					110  Вывод T0 счет осуществляется по спадаешему фронту
					111  Вывод T0 счет осуществляется по нарастаешему фронту
					   */
	TCNT0=0x00; /*  значение в регистр счетный регистр таймера
				   прерывание вызовется когда он отсчитает 0x80(128) тиков 0x80+0x80=0х100(переполнение)*/  

	/*	настройка прерываний от таймера(TIMSK)
		прерывание от переполнения таймера0 (бит0=1) 
		прерывание от переполнения таймера1 (бит2=1)
	*/
	TIMSK |= (1 << 0); //Разрешить прерывание при переполнении T0
	//TIMSK |= (1 << 1); //Разрешить прерывание при совпадении T0
}

ISR(TIMER0_OVF_vect)
{	// Прерывание таймера Т0 (по переполнению)
	if ((--PointTickLeft) < 0)
		PointTickLeft = POINT_TICK_DOWN;
	if ((--PointTickRight) < 0)
		PointTickRight = POINT_TICK_DOWN;
		
	if ((PointTickLeft == 0) && (PointMaxLeft > 0))
		PointMaxLeft--;
	if ((PointTickRight == 0) && (PointMaxRight > 0))
		PointMaxRight--;
}

int main(void)
{
	//Настраиваем порты на ввод/вывод
	DDRC = 0x00;
	DDRB = DDRD = 0xFF;
	
	PORTB = PORTD = 0x00;
	
	_delay_ms(100);
	
	// Настраиваем встроенный АЦП:
	// напряжение питания, выравнивание влево, входной канал ADC0
	ADMUX = (0<<REFS1)|(1<<REFS0)|(1<<ADLAR)|(0<<MUX3)|(0<<MUX2)|(0<<MUX1)|(0<<MUX0);
	// вкл. ацп, режим одиночного преобр., разрешение прерывания,частота преобр. = FCPU/8
	ADCSRA = (1<<ADEN)|(1<<ADSC)|(1<<ADFR)|(1<<ADIF)|(0<<ADIE)|(0<<ADPS2)|(1<<ADPS1)|(1<<ADPS0);
	
	memADCSRA = ADCSRA;
	memADMUX = ADMUX;
	
	float resistor_value = 0;
	int left_value = 0;
	int right_value = 0;

	//Инициализация таймера T0
	timer0_init();

	sei();

    while(1)
    {
		// Обрабатываем значения АЦП
		// Читаем значение резистора (ADC2) - 0010
		resistor_value = GetAdcValue(0b0010) / 255.0f;	// Возвращаемое значение будет от 0 до 1
		resistor_value = 1 + (resistor_value * 20);		// На сколько будем умножать входной сигнал
	
		PORTB = PORTD = 0x00;

		// Читаем значение Левого канала (ADC0) - 0000
		left_value = GetAdcValue(0b0000) * resistor_value;
		DrawValue(left_value, CHANNEL_LEFT);
		_delay_ms(5);
		
		PORTB = PORTD = 0x00;

		// Читаем значение Правого канала (ADC1) - 0001
		right_value = GetAdcValue(0b0001) * resistor_value;
		DrawValue(right_value, CHANNEL_RIGHT);
		_delay_ms(5);
    }
}

BYTE GetAdcValue(const BYTE adc)
{
	// Обязательно в инициализации АЦП вход должен быть 0. Происходит тупое сложение. (0<<MUX2)|(0<<MUX1)|(0<<MUX0)
	ADCSRA = memADCSRA;
	ADCSRA |= (1 << ADIF);
	ADMUX = memADMUX + adc;
	ADCSR |= (1 << ADSC);				//Start ADC
	while (!(ADCSRA & (1 << ADIF)));	//ждем, пока АЦП закончит преобразование (ADIF = 0)
	ADCSRA = memADCSRA;
	ADCSRA |= (1 << ADIF);
	while (!(ADCSRA & (1 << ADIF)));	//ждем, пока АЦП закончит преобразование (ADIF = 0)

	return ADCH;
}

void DrawValue(int val, CHANNEL chanel)
{
	static const BYTE delitel = 255 / (DISPLAY_BIT_COUNT - 1);
	BYTE index = val / delitel;
	
	if (index >= DISPLAY_BIT_COUNT)
		index = DISPLAY_BIT_COUNT - 1;
	
	BYTE pb = DisplayBits[index][0];
	BYTE pd = DisplayBits[index][1];
	
	// Записываем максимальный уровень
	if ((chanel == CHANNEL_LEFT) && (index >= PointMaxLeft))
	{
		PointMaxLeft = index;
		PointTickLeft = POINT_TICK_COUNT;
	}
	else if ((chanel == CHANNEL_RIGHT) && (index >= PointMaxRight))
	{
		PointMaxRight = index;
		PointTickRight = POINT_TICK_COUNT;
	}

	// Делаем различие между каналами	
	if (chanel == CHANNEL_LEFT)
	{
		pd |= (1 << 6);
		pd &= ~(1 << 7);
		
		// Дорисовываем точки максимального уровня
		if (PointMaxLeft > 0)
		{
			if (PointMaxLeft <= 8)
				pb |= (1 << (PointMaxLeft - 1));
			else
				pd |= (1 << (PointMaxLeft - 9));
		}
	}
	else //if (chanel == CHANNEL_RIGHT)
	{
		pd &= ~(1 << 6);
		pd |= (1 << 7);

		// Дорисовываем точки максимального уровня
		if (PointMaxRight > 0)
		{
			if (PointMaxRight <= 8)
				pb |= (1 << (PointMaxRight - 1));
			else
				pd |= (1 << (PointMaxRight - 9));
		}
	}

	// Выводим результат
	PORTB = pb;
	PORTD = pd;
}

Iar schema ar fii aceasta:

image.jpg

Link spre comentariu
  • Răspunsuri 1
  • Creat
  • Ultimul Răspuns

Top autori în acest subiect

  • Mircea

    1

  • Chiriac D

    1

Zile populare

Top autori în acest subiect

Daca nu poti diferentia intre C (ca asta e limbajul folosit) si asamblare, e greu spre imposibil ca tu sa modifici ceva la codul prezentat. 

 

Codul e comentat in rusa, si destul de mult. Macar tradu si vezi ce zice acolo.

Editat de Mircea
Link spre comentariu

Creează un cont sau autentifică-te pentru a adăuga comentariu

Trebuie să fi un membru pentru a putea lăsa un comentariu.

Creează un cont

Înregistrează-te pentru un nou cont în comunitatea nostră. Este simplu!

Înregistrează un nou cont

Autentificare

Ai deja un cont? Autentifică-te aici.

Autentifică-te acum



×
×
  • Creează nouă...

Informații Importante

Am plasat cookie-uri pe dispozitivul tău pentru a îmbunătății navigarea pe acest site. Poți modifica setările cookie, altfel considerăm că ești de acord să continui.Termeni de Utilizare si Ghidări