Перейти к содержанию

Видеокурс по AVR-микроконтроллерам для начинающих


Рекомендуемые сообщения

3 часа назад, COKPOWEHEU сказал:

С другой стороны, эта тема предназначена только для обсуждения конкретного видеокурса. Лучше создайте новую.

Да, вы правы. Развел тут беспредел. Наверно таки нужно создать новую тему, ибо вопросов будет много...

Скрытый текст

void set7RG_C(int in, int clk, int data, int enable)//up to 1ms - 0.001s
{
	//			 0  1  2  3--4  5  6  7
	//			 0  1  2  3--1  2  3  4
	//		 	    yunior----elder
	bool arr[] = {0, 0, 0, 0, 0, 0, 0, 0};
	
	if (in <100)
	{
		int elder =in/10;
		int yunior =in%10;
		int tmp =0;
		
		while (yunior >0)
		{
			arr[tmp] +=yunior%2;
			yunior /=2;
			tmp++;
		}
		tmp =4;
		while (elder >0)
		{
			arr[tmp] +=elder%2;
			elder /=2;
			tmp++;
		}
	}
	for (int i =7; i >=0; i--)
	{
		if (arr[i])
			PORTC |=(1<<clk)|(1<<data);
		else
			PORTC |=(1<<clk);
      
		_delay_us(1);
		PORTC &=~((1<<clk)|(1<<data));
		_delay_us(1);
	}
      
	PORTC |=(1<<enable);
	_delay_us(1);
	PORTC &=~(1<<enable);
	_delay_us(1);
}

 

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

Изменено пользователем chotke
Ссылка на комментарий
Поделиться на другие сайты

Реклама: ООО ТД Промэлектроника, ИНН: 6659197470, Тел: 8 (800) 1000-321

Передачу по SPI лучше вынести в отдельную функцию, причем я бы ее оформил так

//Software SPI transmit
void SSPI_transmit(uint8_t data){
  uint8_t i;
  for(i=0;i<8;i++){
    if( data & (1<<7) )PORTC |= (1<<1); else PORTC &=~(1<<1); //допустим, PC1 - MOSI, выход данных
    PORTC |= (1<<5); //допустим, PC5 - SCK, тактовый сигнал
    //_delay_us(1); //на 1 МГц частоты должно хватить и без искусственных задержек, но если надо можно раскомментировать
    data <<= 1;
    PORTC &=~(1<<5);
    //_delay_us(1);
  }
}

Отличие в том, что в AVR есть команды установки/очистки отдельного бита порта. А для изменения нескольких битов приходится либо вызывать эти одиночные, либо чтение-модификация-запись. Так что в данном случае удобнее дергать MOSI и SCK по отдельности. Но лучше всего использовать аппаратный SPI.

Преобразование перед передачей как по мне несколько неочевидно, но может это я с такими регистрами дела не имел и так и должно быть. Зачем нужны отдельные дешифраторы если тоже самое может сделать и контроллер?

Ругался на отсутствие форматирования исходного кода (включая отсутствие осмысленных комментариев и наличие неубранного после конфигуратора мусора) не менее 15 раз.

Часть моих наработок.

Ссылка на комментарий
Поделиться на другие сайты

20% скидка на весь каталог электронных компонентов в ТМ Электроникс!

Акция "Лето ближе - цены ниже", успей сделать выгодные покупки!

Плюс весь апрель действует скидка 10% по промокоду APREL24 + 15% кэшбэк и бесплатная доставка!

Перейти на страницу акции

Реклама: ООО ТМ ЭЛЕКТРОНИКС, ИНН: 7806548420, info@tmelectronics.ru, +7(812)4094849

57 минут назад, COKPOWEHEU сказал:

Передачу по SPI лучше вынести в отдельную функцию, причем я бы ее оформил так


//Software SPI transmit
void SSPI_transmit(uint8_t data){
  uint8_t i;
  for(i=0;i<8;i++){
    if( data & (1<<7) )PORTC |= (1<<1); else PORTC &=~(1<<1); //допустим, PC1 - MOSI, выход данных
    PORTC |= (1<<5); //допустим, PC5 - SCK, тактовый сигнал
    //_delay_us(1); //на 1 МГц частоты должно хватить и без искусственных задержек, но если надо можно раскомментировать
    data <<= 1;
    PORTC &=~(1<<5);
    //_delay_us(1);
  }
}

Отличие в том, что в AVR есть команды установки/очистки отдельного бита порта. А для изменения нескольких битов приходится либо вызывать эти одиночные, либо чтение-модификация-запись. Так что в данном случае удобнее дергать MOSI и SCK по отдельности. Но лучше всего использовать аппаратный SPI.

Преобразование перед передачей как по мне несколько неочевидно, но может это я с такими регистрами дела не имел и так и должно быть. Зачем нужны отдельные дешифраторы если тоже самое может сделать и контроллер?

Да, реально через сдвиг все работает на ура. Сам сразу не догадался как это сделать, потому написал "как обычно". Функция предполагалась быть универсальной, то есть настроить выходы на нужные пины для несколько семисегментов. Только не придумал как в параметрах функции указывать какой порт мы используем без постоянных проверок типо: if() PORTA else if() PORTB else PORTC.

Задержки вроде тоже лишние, постоянный сигнал для выходных микросхем нужен порядком 100ns. Зачем дешифратор? Думалось сделать небольшой термометр на АТтини13, с двумя цифровыми датчиками температуры и кнопкой для переключения между ними. Итого 6 ножек. Теперь то сам задумался, может реально все сделать программно на АТмега8? По сути и меньше места вся схема будет занимать. Как я говорил, знаком с мк совсем недавно, потому на очереди прерывания, счетчики, таймера, компараторы и другие прелести... На днях будет тема, ох замучаю вас вопросами)

Ссылка на комментарий
Поделиться на другие сайты

Выбираем схему BMS для корректной работы литий-железофосфатных (LiFePO4) аккумуляторов

 Обязательным условием долгой и стабильной работы Li-FePO4-аккумуляторов, в том числе и производства EVE Energy, является применение специализированных BMS-микросхем. Литий-железофосфатные АКБ отличаются такими характеристиками, как высокая многократность циклов заряда-разряда, безопасность, возможность быстрой зарядки, устойчивость к буферному режиму работы и приемлемая стоимость. Но для этих АКБ, также как и для других, очень важен контроль процесса заряда и разряда, а специализированных микросхем для этого вида аккумуляторов не так много. Инженеры КОМПЭЛ подготовили список имеющихся микросхем и возможных решений от разных производителей. Подробнее>>

Реклама: АО КОМПЭЛ, ИНН: 7713005406, ОГРН: 1027700032161

Цитата

Только не придумал как в параметрах функции указывать какой порт мы используем без постоянных проверок типо: if() PORTA else if() PORTB else PORTC.

Зависит от задачи. Чаще всего выбор порта известен на этапе компиляции, тогда выбирается макросом. Если же выбор делается на этапе выполнения - можно передавать адрес регистра.

#define SPI_PORT PORTA
#define SPI_DDR DDRA
#define SPI_SCK 5
#define SPI_MOSI 1

Но еще раз повторю, удобнее использовать аппаратный SPI, а его ножки уж точно известны заранее.

Цитата

Зачем дешифратор?

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

Цитата

На днях будет тема, ох замучаю вас вопросами)

ждем-с :) Одно дело когда на форум прискакивает неопознанное тело "пАмАгИтЕ нАпИсАтЬ пРоГрАмМу" и другое - человек интересующийся.

Ругался на отсутствие форматирования исходного кода (включая отсутствие осмысленных комментариев и наличие неубранного после конфигуратора мусора) не менее 15 раз.

Часть моих наработок.

Ссылка на комментарий
Поделиться на другие сайты

  • 3 недели спустя...

Здравствуйте , вот хочу доделать прошивку (вело спидометра) под себя ,не знаю получится или нет я только учусь,посмотрите и подскажите пожалуйста можно в ней сделать чтобы показания спидометра после выключения питания не сбрасывались по нулям , а оставались в памяти те же после включения ,и если можно то как ? СПАСИБО   

ВЕЛОС.rar

Ссылка на комментарий
Поделиться на другие сайты

4 минуты назад, Djen55 сказал:

сделать чтобы показания спидометра после выключения питания не сбрасывались по нулям , а оставались в памяти те же после включения

Интересно, а для чего это ? Спидометр измеряет значения в реальном времени, для чего эти значения сохранять ?
 

Ссылка на комментарий
Поделиться на другие сайты

Пересмотрел я все эти сайты , пытаюсь разобраться вообще как эта прошивка работает и какую часть кода нужно запомнить еепрому , если не сложно гляньте пожалуйста вообще реально туда сделать еепром чтобы он запоминал последние показания спидометра,а то я уже за сомневался,в голове уже каша  ,недели 3 уже ковыряю ее .Спасибо.  

ВЕЛОС.rar

Изменено пользователем Djen55
Ссылка на комментарий
Поделиться на другие сайты

Добрый день.

Помогите с уроком №7. Не получается собрать вольтметр.

Ошибки в своем коде не нашел. Перечитал всю ветку форума, ответа не нашел.

Суть проблемы в том, что при подаче напряжения без делителя 2.56 В на вход АЦП , на экран выводит значение 200.

И со вторым входом тоже проблема, в независимости от подаваемого напряжения с источника, на экране всегда выдается 5,8.

Может проблема с Протеусом?. Стоит Proteus 7.10 SP0

Протеус.PNG

Код.txt

Ссылка на комментарий
Поделиться на другие сайты

а ежели так

...

for (int i=0;i<16;i++)

...

return tmp>>4;

--------------------------------------------------------------

2.56v - 1024

1024 * 32 = 32768

https://im2-tub-ru.yandex.net/i?id=a0d29535a0c8c38ecdcbd91039c39619-l&n=13

Изменено пользователем Berg
Ссылка на комментарий
Поделиться на другие сайты

хотя не., все верно., это я тупанул

скопипастил ваш код, все напряжения по схеме такие же, на экране 1023.0 и 12.3

протеус такой же.., чудеса прям

позвонил на "Битву экстрасенсов", сказали пусть проверит та ли программа залита в камень

Изменено пользователем Berg
Ссылка на комментарий
Поделиться на другие сайты

В 26.02.2017 в 10:31, Berg сказал:

 

позвонил на "Битву экстрасенсов", сказали пусть проверит та ли программа залита в камень

Да та программа в камень залита, текст на экран вывожу параллельно

Ссылка на комментарий
Поделиться на другие сайты

Гость Чупачупс

Добрый день! не получается вывести градусы. прошу помогите. вроде сделал все как говорится. но градусы не правильные.

Где моя ошибка?

Спасибо заранее

//Atmega32

#define F_CPU 8000000        //Укажем частоту
#include <avr/io.h>
#include <util/delay.h>        //Инициализация библиотеки для использования дисплея
#include <stdlib.h>            //библиотек ***** работы с itoa
#include "n5110.h"

void preset(){                //Предварительные настройки функции
    Lcd_init();                //Инициализация дисплея
    //Настройка АЦП
    //ADCSRA
    ADCSRA |= (1<<ADEN)        //Задеиствовать АЦП
    | (1<<ADPS2) | (1<<ADPS1) | (1<<ADPS0);    //Делитель 128=64кГц
    
    ADMUX |= (1<<REFS1)|(1<<REFS0);        //Опорное напряжение 2,56В
}

int readADC (unsigned int ch){    //целочисленное, положительное число
    unsigned char set_admux = ADMUX;
    set_admux &= ~((1<<MUX3) | (1<<MUX2) | (1<<MUX1) | (1<<MUX0));    //Записать в регистры все 0
    switch (ch)                    //позволяет сделать выбор
    {
        case 1: set_admux |= (0<<MUX3) | (0<<MUX2) | (0<<MUX1) | (1<<MUX0); break;
        case 2: set_admux |= (0<<MUX3) | (0<<MUX2) | (1<<MUX1) | (0<<MUX0); break;
        default:break;
    }
    ADMUX=set_admux;
    _delay_ms(10);
    int tmp = 0;
    for(int i=0; i<=40; i++){
        ADCSRA |= (1<<ADSC);        //Запуск преобразования
        while(ADCSRA&(1<<ADSC));            //Ожидвание окончания преоброзавания
        tmp +=ADC;                    // tmp = tmp+ADC
    }
    return tmp/40;
}

int main(void)
{
    preset();
    while (1)
    {
        Lcd_clear();            //Очистка дисплея
        Lcd_printf(0,0,FONT_1X,((readADC(0)*2.56*(30/2.56))/1023),1);        //Вольт
        Lcd_printf(0,1,FONT_1X,((readADC(1)*2.56*(3/2.56))/1023),1);        //Ампер/ максимум 3 ампера поддерживает
        Lcd_printf(0,2,FONT_1X,(((readADC(2)*2.56*100*(3.73/2.56))/1023)-273.15), 0);        //Градус
        Lcd_update();
        _delay_ms(200);
    }
}


 

kK30ZBKm_400x400.jpeg

Ссылка на комментарий
Поделиться на другие сайты

Уже обсуждалось в этой теме - библиотека глючная.
Ищите другие варианты в теме.
 

В 1 марта 2017 г. в 19:41, Гость Чупачупс сказал:

((readADC(2)*2.56*100*(3.73/2.56))/1023)-273.15)

Пипец, бедные контроллеры :) 
 

Ссылка на комментарий
Поделиться на другие сайты

В ‎01‎.‎03‎.‎2017 в 19:41, Гость Чупачупс сказал:

Где моя ошибка?

переполняете переменную tmp и не правильно вычисляете среднее значение

вот так попробуйте:

...

for(int i=0; i<32; i++){

...

return tmp/32;

Ссылка на комментарий
Поделиться на другие сайты

  • 1 месяц спустя...

Можно немного пояснить запись PINC&(1<<PC0),а именно какое значение приобретает PINC и PC0  до и после нажатия кнопки,единица рассматривается как 0b00000001 и PC0 тоже как 0b00000001 или как.Поясните пожалуйста.

Ссылка на комментарий
Поделиться на другие сайты

Ругался на отсутствие форматирования исходного кода (включая отсутствие осмысленных комментариев и наличие неубранного после конфигуратора мусора) не менее 15 раз.

Часть моих наработок.

Ссылка на комментарий
Поделиться на другие сайты

1 час назад, COKPOWEHEU сказал:

Жестоко :)

Если забанить всех, кто набрался смелости думать независимо, здорово будет на форуме - как на кладбище: тишина, птички поют...

Ссылка на комментарий
Поделиться на другие сайты

битовые операции понятны,не понятно значение PINC до и после размыкания. PINC опрашивает вроде как весь порт С,это значит что до замыкания там  1111110,а мы сравниваем его с просто нулем,а после нажатия на кнопку PINC = 1111111 и PC0 = 1,но единица в двоичной это то 00000001 и когда мы делаем операцию & как мы получаем то что получаем

Ссылка на комментарий
Поделиться на другие сайты

PC0 это константа. запись 1<<PC0 означает "сдвинуть единичку на PC0 разрядов вправо", т.е. получить число, в котором единичка будет на месте, указанном PC0. Ну, в данном контексте, это будет просто единичка :) а потом мы берем содержимое PINC и делаем битовое И с этой самой единичкой. В итоге если нулевой бит в обоих числах будет равен 1, то результат тоже будет равен 1, а если хотя бы в одном числе будет ноль - результат тоже будет ноль... то есть при помощи конструкции PINC & (1<<PC0) мы просто проверяем, равен нулю или нет младший бит PINC

Изменено пользователем ARV

Если забанить всех, кто набрался смелости думать независимо, здорово будет на форуме - как на кладбище: тишина, птички поют...

Ссылка на комментарий
Поделиться на другие сайты

PC0 и до, и после остается равным 0. Хоть в двоичной, хоть в троичной, хоть в восьмеричной, хоть в какой угодно системе.

PINC меняется, но как - я не в курсе, ибо не знаю, где там кнопка и как она замыкается. Но предполагаю, что одно из состояний сожержит 1 в младшем бите, а другое - содержит 0.

Нас не интересует, что содержится в остальных битах, т.к. при помощи битового И мы выделяем только интересующий нас 0-й бит. даже если до нажатия кнопки PINC был 00000001, а после нажатия стал 10101010, важно лишь то, что младший бит сменил свое состояние.

Изменено пользователем ARV

Если забанить всех, кто набрался смелости думать независимо, здорово будет на форуме - как на кладбище: тишина, птички поют...

Ссылка на комментарий
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы публикуете как гость. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.
Примечание: Ваш пост будет проверен модератором, прежде чем станет видимым.

Гость
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
Ответить в этой теме...

×   Вставлено с форматированием.   Восстановить форматирование

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

Загрузка...
  • Последние посетители   0 пользователей онлайн

    • Ни одного зарегистрированного пользователя не просматривает данную страницу

×
×
  • Создать...