Chiriac D Postat Aprilie 21, 2022 Partajează Postat Aprilie 21, 2022 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: Link spre comentariu
Mircea Postat Aprilie 21, 2022 Partajează Postat Aprilie 21, 2022 (editat) 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 Aprilie 21, 2022 de Mircea Link spre comentariu
Postări Recomandate
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 contAutentificare
Ai deja un cont? Autentifică-te aici.
Autentifică-te acum