Делаем светодиодный индикатор напряжения

Модератор: boogyman

Ответить
Аватара пользователя
StyleWarrior
Новичок
Сообщения: 5
Зарегистрирован: 23 янв 2012, 09:46

Делаем светодиодный индикатор напряжения

#1

Сообщение StyleWarrior »

Сделал 8 разрядный все прекрасно работает, захотелось 10 разрядный, подключил еще 2 светодиода к порту С на РС7 и РС6 мк atmega64 резистор на PF0 остальные светодиоды на PA0-PA7
При прокрутки резистора и при достижении порта РС7 светодиод загорается но при уменьшении он не гаснет в чем может быть проблема?

код программы:

Код: Выделить всё

/***Использование АЦП. Светодиодная шкала***/

#define F_CPU 8000000UL  // 8 MHz
#include <avr/io.h>
#include <avr/delay.h>

/***Главная функция***/
int main (void) 
{
	DDRA = 0xFF;
    PORTA = 0x00;
	DDRC = 0xFF;
    PORTC = 0x00;


/***Настройка АЦП***/ 
    ADCSRA |= (1 << ADEN) //Включение АЦП
	|(1 << ADPS1)|(1 << ADPS0);	// предделитель преобразователя на 8
    ADMUX |= (0 << REFS1)|(0 << REFS0) // внешний ИОН
	|(0 << MUX0)|(0 << MUX1)|(0 << MUX2)|(0 << MUX3); // вход PF0

while(1)
	{ 
    unsigned int u;
    ADCSRA |= (1 << ADSC);	//Начинаем преобразование
    while ((ADCSRA&(1 << ADIF))== 0); //Ждем флага окончания преобразования    
 
     u = (ADCL|ADCH << 8);  // Считываем  ADC
	 	 
if (u > 102)                 //0.5V
	 {PORTA = (1 << PA0);}          
else {PORTA &= ~(1 << PA0);}
	 
if (u > 204)                  //1.0V
	 PORTA = (1 << PA0)|(1 << PA1);     
if (u > 306)                  //1.5V  
	 PORTA = (1 << PA0)|(1 << PA1)
	                   |(1 << PA2);
if (u > 408)                  //2V
	 PORTA = (1 << PA0)|(1 << PA1)
	        |(1 << PA2)|(1 << PA3);
if (u > 510)                  //2.5V
	 PORTA = (1 << PA0)|(1 << PA1)
	        |(1 << PA2)|(1 << PA3)
			           |(1 << PA4);
if (u > 612)                  //3V
	 PORTA = (1 << PA0)|(1 << PA1)
	        |(1 << PA2)|(1 << PA3)
			|(1 << PA4)|(1 << PA5);
if (u > 714)                  //3.5V
	 PORTA = (1 << PA0)|(1 << PA1)
	        |(1 << PA2)|(1 << PA3)
			|(1 << PA4)|(1 << PA5)
			           |(1 << PA6);
if (u > 816)                 //4V
	 PORTA = (1 << PA0)|(1 << PA1)
	        |(1 << PA2)|(1 << PA3)
			|(1 << PA4)|(1 << PA5)
			|(1 << PA6)|(1 << PA7);
	 
if (u > 918) {                //4.5V
	 PORTA = (1 << PA0)|(1 << PA1)
	        |(1 << PA2)|(1 << PA3)
			|(1 << PA4)|(1 << PA5)
			|(1 << PA6)|(1 << PA7);			
	 PORTC = (1 << PC7);
	 }
if (u > 1020) {                 //5V
	 PORTA = (1 << PA0)|(1 << PA1)
	        |(1 << PA2)|(1 << PA3)
			|(1 << PA4)|(1 << PA5)
			|(1 << PA6)|(1 << PA7);			
	 PORTC = (1 << PC7)|(1 << PC6);
	 }
	 _delay_ms(30);
	 }
}
Аватара пользователя
boogyman
Модератор
Сообщения: 183
Зарегистрирован: 25 дек 2011, 22:48
Откуда: Москва

Re: Делаем светодиодный индикатор напряжения

#2

Сообщение boogyman »

Проверял в Proteuse или собирал на макетке? Я просимулировал в Proteuse, тоже самое показывает.
Аватара пользователя
boogyman
Модератор
Сообщения: 183
Зарегистрирован: 25 дек 2011, 22:48
Откуда: Москва

Re: Делаем светодиодный индикатор напряжения

#3

Сообщение boogyman »

Для полного выключения порта С добавить else, также как для порта А
Аватара пользователя
StyleWarrior
Новичок
Сообщения: 5
Зарегистрирован: 23 янв 2012, 09:46

Re: Делаем светодиодный индикатор напряжения

#4

Сообщение StyleWarrior »

на макетке собрал.
Да уже сам разобрался...
надо было погасить сигмент последний в 28 стоке else {PORTD &= ~(1 << PD0);} это и делается только для другова порта, я пошел немного другим путем:

Код: Выделить всё

/***Использование АЦП. Светодиодная шкала***/

#define F_CPU 8000000UL  // 8 MHz
#include <avr/io.h>
#include <avr/delay.h>


/***Главная функция***/
int main (void) 
{
	DDRA = 0xFF;
    PORTA = 0x00;
	DDRC = 0xFF;
    PORTC = 0x00;
	DDRD = 0xFF;
    PORTD = 0x00;


/***Настройка АЦП***/ 
    ADCSRA |= (1 << ADEN)|(1 << ADPS1)|(1 << ADPS0);	// предделитель преобразователя на 8 //Включение АЦП
	
    ADMUX |= (0 << REFS1)|(0 << REFS0)|(0 << MUX0)|(0 << MUX1)|(0 << MUX2)|(0 << MUX3); // вход PF0 // Частота АЦП = такту микроконтроллера / 64

while(1)
	{ 
    unsigned int u;
    ADCSRA |= (1 << ADSC);	//Начинаем преобразование
    
	while ((ADCSRA&(1 << ADIF))== 0); //Ждем флага окончания преобразования    
 
     u = (ADCL|ADCH << 8);  // Считываем  ADC
	 	 
if (u > 102)                 //0.5V
	 {PORTA = 0x01;}          
else {PORTA &= ~(1 << PA0);}
	 
if (u > 204) {                 //1.0V
	 PORTA = 0x03;
	 PORTC = 0x00;
	 PORTD = 0x00;
}     
if (u > 306) {                 //1.5V  
	 PORTA = 0x07;
	 PORTC = 0x00;
	 PORTD = 0x00;
}  
if (u > 408) {                 //2V
	 PORTA = 0x0F;
	 PORTC = 0x00;
	 PORTD = 0x00;
}  
if (u > 510) {                 //2.5V
	 PORTA = 0x1F;
	 PORTC = 0x00;
	 PORTD = 0x00;
}  
if (u > 612) {                 //3V
	 PORTA = 0x3F;
	 PORTC = 0x00;
	 PORTD = 0x00;
}  
if (u > 714) {                 //3.5V
	 PORTA = 0x7F;
	 PORTC = 0x00;
	 PORTD = 0x00;
}  
if (u > 816) {                //4V
	 PORTA = 0xFF;
	 PORTC = 0x00;
	 PORTD = 0x01;
}  
	 
if (u > 918) {               //4.5V
	 PORTA = 0xFF;
	 PORTC = 0x80;
	 PORTD = 0x01;
}  		
	
if (u > 1020) {                 //5V
	 PORTA = 0xFF;
	 PORTC = 0xC0;
	 PORTD = 0x01;
}  			
	 
	 _delay_ms(1);
	 }
}
гасил сегменты в других условиях.
Аватара пользователя
StyleWarrior
Новичок
Сообщения: 5
Зарегистрирован: 23 янв 2012, 09:46

Re: Делаем светодиодный индикатор напряжения

#5

Сообщение StyleWarrior »

В продолжение к теме Занятие №2. Переключение светодиода
Она не рабочая, почему не знаю...
На ноге где светодиод почему то постоянно присутствует +2,5 вольта, соответственно он светится в пол накала, а при нажатии на кнопку, он иногда включается на полную (повторяюсь иногда раза с 3-4)
я предполагаю это из за входа AREF он посажен на +5, хотя врятле скорее всего из за резюка на кнопке...
притом +2.5 вольт появятся только после прошивки контроллера.

Еще встал вопрос о многозадачности контроллеров, как ее реализовать ведь, если в предыдущий вариант скрестить с переключением светодиода ничего не получится так как в обоех случаях используется бесконечный цыкл соответственно как реализовать например вольтметр и амперметр или все в один цикл записать
еще вопрос про мигание светодиодов ведь если делать delay то цикл останавливается и соответственно все измерения тоже.
Аватара пользователя
StyleWarrior
Новичок
Сообщения: 5
Зарегистрирован: 23 янв 2012, 09:46

Re: Делаем светодиодный индикатор напряжения

#6

Сообщение StyleWarrior »

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

Re: Делаем светодиодный индикатор напряжения

#7

Сообщение boogyman »

StyleWarrior писал(а):Да уж форум гиблый нечего тут оставаться...
Форуму 2 месяца, а ты что хотел?
Аватара пользователя
uuu000
Любитель
Сообщения: 17
Зарегистрирован: 08 апр 2019, 00:15

Re: Делаем светодиодный индикатор напряжения

#8

Сообщение uuu000 »

Схема radioparty.ru/programming/avr/c/285-lesson-adc-avr работает прекрасно,собрал на ее основе индикатор разряда аккумулятора.
Но возникла необходимость в замене Atmega 8 на Attiny44 , вроде все делал согласно datasheet -но отказывается работать.
Пробовал выход на порт А(кроме ножки РА0-вход АЦП) или на три ноги порта В.Фьюзы ваставлены по умолчанию из datasheet.
К сожалению слишком малый опыт в программировании не позволил самостоятельно найти проблему.
Прошу помощи.
Спасибо.
КОД:

Код: Выделить всё

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

int main (void)
{
	DDRA|=(1<<PA1)|(1<<PA2)|(1<<PA3)|(1<<PA4)|(1<<PA5)|(1<<PA6)|(1<<PA7);
	PORTA&=~((1<<PA1)|(1<<PA2)|(1<<PA3)|(1<<PA4)|(1<<PA5)|(1<<PA6)|(1<<PA7));
	//DDRB|=(1<<PB0)|(1<<PB1)|(1<<PB2);
	//PORTB&=~((1<<PB0)|(1<<PB1)|(1<<PB2));
	/*** Настройка АЦП ***/
	ADCSRA |= (1 << ADEN) // Включение АЦП
	|(1 << ADPS1)|(1 << ADPS0);    // предделитель преобразователя на 8
	ADMUX |= (0 << REFS1)|(0 << REFS0) // внешний ИОН
	|(0 << MUX0)|(0 << MUX1)|(0 << MUX2)|(0 << MUX3)|(0 << MUX4)|(0 << MUX5); // вход PA0
	ADCSRB|=(1<<ADLAR);
	while(1)
	{
		unsigned int u;
		ADCSRA |= (1 << ADSC)
		|(1<<ADIE)
		|(1 << ADATE);    // Начинаем преобразование
		while ((ADCSRA&(1 << ADIF))== 0); // Ждем флага окончания преобразования
		
		u = (ADCL|ADCH << 8); // Считываем  ADC
		
		if (u > 128) // 0.625V
		//PORTB |= (1<<PB0);
		//else
		//PORTA &= ~((1<<PB0));
		
		//if (u > 256) // 1.25V
		//PORTB |=(1<<PB0)| (1<<PB1);
		//if (u > 384) // 1.875V
		//PORTB |= (1<<PB0)|(1<<PB1)|(1<<PB2);
	    PORTA |= (1<<PA1);
		else
		PORTA &= ~((1<<PA1)|(1<<PA2)|(1<<PA3)|(1<<PA4)|(1<<PA5)|(1<<PA6)|(1<<PA7));
		
		if (u > 256) // 1.25V
		PORTA |=(1<<PA1)| (1<<PA2);
		if (u > 384) // 1.875V
		PORTA |= (1<<PA1)|(1<<PA2)|(1<<PA3);
		if (u > 512) // 2.5V
		PORTA |= (1<<PA1)|(1<<PA2)|(1<<PA3)|(1<<PA4);
		if (u > 640) // 3.125V
		PORTA |=(1<<PA1)|(1<<PA2)|(1<<PA3)|(1<<PA4)|(1<<PA5);
		if (u > 768) // 3.75V
		PORTA |=(1<<PA1)|(1<<PA2)|(1<<PA3)|(1<<PA4)|(1<<PA5)|(1<<PA6);
		if (u > 896) // 4.375V
		PORTA |=(1<<PA1)|(1<<PA2)|(1<<PA3)|(1<<PA4)|(1<<PA5)|(1<<PA6)|(1<<PA7);
		
		_delay_ms(30);
	}
}
Аватара пользователя
microsystems
Любитель
Сообщения: 12
Зарегистрирован: 11 дек 2019, 19:40

Re: Делаем светодиодный индикатор напряжения

#9

Сообщение microsystems »

Не надо было делать левое выравнивание результата АЦП: ADCSRB|=(1<<ADLAR);

Код: Выделить всё

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

int main (void)
{
	DDRA|=(1<<PA1)|(1<<PA2)|(1<<PA3)|(1<<PA4)|(1<<PA5)|(1<<PA6)|(1<<PA7);
	PORTA&=~((1<<PA1)|(1<<PA2)|(1<<PA3)|(1<<PA4)|(1<<PA5)|(1<<PA6)|(1<<PA7));
	//DDRB|=(1<<PB0)|(1<<PB1)|(1<<PB2);
	//PORTB&=~((1<<PB0)|(1<<PB1)|(1<<PB2));

	/*** Настройка АЦП ***/
	ADCSRA |= (1 << ADEN) // Включение АЦП
	|(1 << ADPS1)|(1 << ADPS0);    // предделитель преобразователя на 8
	ADMUX |= (0 << REFS1)|(0 << REFS0) // внешний ИОН
	|(0 << MUX0)|(0 << MUX1)|(0 << MUX2)|(0 << MUX3)|(0 << MUX4)|(0 << MUX5); // вход PA0
	//ADCSRB|=(1<<ADLAR);
	while(1)
	{
		unsigned int u;
		ADCSRA |= (1 << ADSC);	// Начинаем преобразование
		while ((ADCSRA&(1 << ADIF))== 0); // Ждем флага окончания преобразования
		
		u = (ADCL|ADCH << 8); // Считываем  ADC
		
		if (u > 128){ // 0.625V
			PORTA |= (1<<PA1);
			if (u > 256){ // 1.25V
				PORTA |=(1<<PA2);
				if (u > 384){ // 1.875V
					PORTA |= (1<<PA3);
					if (u > 512){ // 2.5V
						PORTA |= (1<<PA4);
						if (u > 640){ // 3.125V
							PORTA |=(1<<PA5);
							if (u > 768){ // 3.75V
								PORTA |=(1<<PA6);
								if (u > 896){ // 4.375V
									PORTA |=(1<<PA7);
								}
								else PORTA &= ~(1<<PA7);
							}
							else PORTA &= ~((1<<PA6)|(1<<PA7));
						}
						else PORTA &= ~((1<<PA5)|(1<<PA6)|(1<<PA7));
					}
					else PORTA &= ~((1<<PA4)|(1<<PA5)|(1<<PA6)|(1<<PA7));
				}
				else PORTA &= ~((1<<PA3)|(1<<PA4)|(1<<PA5)|(1<<PA6)|(1<<PA7));
			}
			else PORTA &= ~((1<<PA2)|(1<<PA3)|(1<<PA4)|(1<<PA5)|(1<<PA6)|(1<<PA7));
		}
		else PORTA &= ~((1<<PA1)|(1<<PA2)|(1<<PA3)|(1<<PA4)|(1<<PA5)|(1<<PA6)|(1<<PA7));

		_delay_ms(30);
	}
}
Аватара пользователя
uuu000
Любитель
Сообщения: 17
Зарегистрирован: 08 апр 2019, 00:15

Re: Делаем светодиодный индикатор напряжения

#10

Сообщение uuu000 »

Cпасибо,все понял.
Ответить