Библиотека для AtmelStudio 6.x а-ля CodeVisionAVR


• О проекте
• Обратная связь
• Полезные ссылки
• Полезные программы
• Друзья сайта


Последние комментарии

Аби: Подключение микроконтроллеров к шине RS-485
написано просто о...

Анатолий: Джойстик для денди на stm32
Автору 100500 рес...




           

Библиотека для AVR





AXLIB Генератор





Помощь сайту


				

Библиотека для AtmelStudio 6.x а-ля CodeVisionAVR

	
	
	


	
	
Всем привет!
Многие новички решившие начать программирование AVR микроконтроллеров фирмы Atmel чаще всего идут по двум путям. Самый простой - это Arduino, ничего паять не надо и полно готовых прошивок. Кто по серьезней, паяет сам и использует чаще всего CodeVisionAVR, так как там много готовых библиотек для МК. Но мне часто задают один и тот же вопрос "А есть ли такиеже библиотеки для AtmelStudio?". Нет. Почему-то Атмеловцы решили забить на пользователей и открестились лишь тем что последняя версия может хватать код сгенерированный CodeVisionAVR. Вроде бы ничего, но... Но, заключается в том что CodeVisionAVR является платной программой и стоит денег. Для бесплатного использования слишком мало ресурсов, а хочется большего. Вот и я решил выйти из этого положения и начал потихоньку писать свою библиотеку для AtmelStudio. Со временем накопилось куча разных вариантов и я собравшись с силами решил потихоньку все это систематизировать и собрать в одну кучу. И так родилась библиотека под названием AXLIB. Почему такое название, а хрен его знает. Просто так захотелось. Короче выкладываю первую версию на ваш суд. Если кому интересно можете пользоваться, она абсолютно бесплатна. Я надеюсь что не забью на это и найду силы для ее пополнения. И так приступим.

Первое что надо сделать так это скачать архив с библиотекой axlib 1.1

Или скачать генератор кода тут и он сделает все за вас.

После того как скачали на диск ее нужно распаковать в папку по адресу
Program Files (x86) -> Atmel -> Atmel Toolchain -> AVR8 GCC -> Native ->
3.4.1056 -> avr8-gnu-toolchain -> avr->include
Вот это вот 3.4.1056 у вас может называться по другому из-за версии, но суть остается та же. После переноса папки axlib можно приступать к использованию.

Расположение папки библиотек

Буду расписывать с самого начала. Запускаем программу AtmelStudio 6.2 и создаем новый проект нажав на ссылку слева вверху New Project...

Создание нового проекта

В появившемся окне, выбираем GCC C Executable Project, а в нижних трех строчках Name: - это имя главного файла и имя бинарного файла который нужно загрузить в МК. Location: - это адрес где будет создан проект со всеми файлами. Solution name: - это название которое появится слева при старте программы в поле Recent Projects. Если по нему потом щелкнуть, то загрузится проект.

Создание нового проекта

Жмем ОК и видим новое окно. В нем выбираем МК с которым будем работать. В данный момент у меня это ATmega8A.

Выбор МК

Жмем ОК и ждем пока не будет создан проект. Немного подумав программа родит окно в котором будет вот такая запись.

Окно проекта

Нажимаем F7 и видим в нижнем поле процесс компиляции, а в конце сообщение что все прошло отлично. То есть мы скомпилировали пустой проект. А вот теперь давайте начнем работать с библиотекой axlib


Библиотека сделана таким образом, что вносить какие-либо поправки нужно только в одном файле. (Изночально данный файл находился в той же директории что и все остальные файлы. В связи с частым переносом проектов было принято решение данный файл переместить в корень проекта. Теперь расположения файла main_init.h должно быть там же где и основной файл программы. Дле тех кто использует старый вариант ничего не меняется. Лишь скачайте новую версию библиотеки и при создании нового проекта перенесите файл main_init.h в корень проекта. Теперь для каждого проекта будет свой файл main_init.h) Он называется main_init.h. Как ни странно, но для подключения тех или иных функций необходимо первым делом подключить именно этот файл. Делается это так.
После строки #include <avr/io.h>
пишем #include "main_init.h"
(Старый вариант #include <axlib/main_init.h>)


#include <avr/io.h> #include "main_init.h" int main(void) { while(1) { } }
Теперь снова жмем F7. После компиляции справа в окне появится наш файл. Жмем на него двойным щелчком.

main_init.h

Появится тело файла. Что собственно здесь написано и что здесь нужно править.

main_init.h

Самым первым делом нужно указать на какой частоте будет работать МК. Поэтому после сборки железа, первым делом вписываем эту частоту в герцах. На данный момент я тестировал библиотеку на МК с частотой 7,3728 МГц, поэтому сейчас там записана такая частота. Обязательно поменяйте ее на свою, так как это важно для расчетов некоторых значений регистров периферии. Далее идет определение типов данных. Их трогать не нужно. За ними следует настройка подключения ЖК знакосинтезирующего дисплея по 4-х битной шине. Если использование ЖК не планируется, то можно ничего не трогать. Если же ЖК будет подключатся, то необходимо прописать на каких портах и каких пинах будут подключены ножки МК и ЖК. Сложного ничего нет, просто меняем на ту букву порта на которой подключен ЖК, а в конце прописываем номера пинов. Вот и вся настройка. (Пока)

По вопросам и замечаниям, а так же предложениям, можно обратится на форум.
Генератор кода для AtmelStudio 6.x с поддержкой библиотеки AXLIB

Содержание:

1. Порты ввода/вывода
2. Таймеры
3. ЖК дисплей с максимальным разрешением 4х40
4. АЦП Аналогово-цифровой преобразователь
5. UART
6. 1WIRE
7. I2C
8. Датчик давления от ВАЗ-2103 на прибор
9. Датчик температуры DS1820
10. SPI
11. Цветной TFT дисплей с управляющим контроллером ST7735
12. Функции для работы с часами DS1307
13. Функции для работы с часами DS3231
14. Функции для работы со сдвиговым регистром 74HC595
15. Функции для чтения/записи микросхемы EEPROM серии AT24Cx
16. Функции для управления микросхемой MAX7219
17. Функции для реализации протокола MH-BUS



SPI

Эта часть библиотеки предназначена для связи устройств между собой по шине SPI. Для подключения файла библиотеки нужно написать строку: #include <axlib/spi.h>.

Функции:

void SPI_init(SPI_InitTypeDef *spi); Данная функция принимает в качестве аргумента указатель на структуру которую необходимо заполнить перед вызовом данной функции с требуемыми параметрами.

UBYTE SPI_M_byte_io(BYTE data); Данная функция предназначена для передачи и приема байта по шине SPI. Получаемый аргумент, есть передаваемый байт. Возвращаемое значение, есть полученный байт. Данная функция работает только в режиме Master.

UBYTE SPI_S_byte_io(BYTE data, BYTE timeout); Данная функция предназначена для передачи и приема байта по шине SPI. Получаемые аргументы функции это передаваемый байт мастеру и время действия функции в миллисекундах (таймаут). Если данные не пришли до истечения заданного времени, то функция возвращает значение FULL. В случае удачного получения/передачи данных, функция возвращает полученный байт. Данная функция работает только в режиме Slave.

Значение структуры SPI_InitTypeDef


typedef struct
{
	BYTE SPI_set;			// Включить/выключить SPI
	BYTE SPI_Mode;		// Выбор Мастер или Слейв
	BYTE SPI_Direct;		// Выбор направления передачи байта
	BYTE SPI_Prescaler;	// Выбор претделителя
	BYTE SPI_Polaric;		// Выбор полярности тактового сигнала
	BYTE SPI_Phase;		// Выбор фазы тактового сигнала
	
}SPI_InitTypeDef;


Пример для Master



#include <avr/io.h>

#include "main_init.h";
#include <axlib/spi.h>

BYTE data_in = 0x00;
BYTE data_out = 0x00;

int main(void)
{

// Инициализация SPI
SPI_InitTypeDef SPI_InitType;

  // Включить SPI
  SPI_InitType.SPI_set = SPI_ON;
  // Выбрать режим Master
  SPI_InitType.SPI_Mode = SPI_MASTER;
  // Выбрать претделитель (F_CPU/2)
  SPI_InitType.SPI_Prescaler = SPI_PRESCALER_2;
  // Задание полярности тактового сигнала
  SPI_InitType.SPI_Polaric = SPI_CPOL_LOW;
  // Задание фазы тактового сигнала
  SPI_InitType.SPI_Phase = SPI_CPHA_1EDGE;
  // Выбор направления передачи данных
  SPI_InitType.SPI_Direct = SPI_DIRECT_MSB;

SPI_init(&SPI_InitType); // Инициализация SPI

  while(1)
  {
     data_in = SPI_M_byte_io(data_out); // Значение data отправлено в порт
     data_out = data_in;
  }
}




Пример для Slave



#include <avr/io.h>
#include <stdio.h>

#include "main_init.h"
#include <axlib/spi.h>
#include <axlib/lcd.h>

BYTE data = 0;
BYTE data_old = 0;
BYTE str[20];

int main(void)
{

// Инициализация SPI
SPI_InitTypeDef SPI_InitType;

  // Включить SPI
  SPI_InitType.SPI_set = SPI_ON;
  // Выбрать режим Slave
  SPI_InitType.SPI_Mode = SPI_SLAVE;
  // Претделитель не нужен
  SPI_InitType.SPI_Prescaler = SPI_PRESCALER_NO;
  // Задание полярности тактового сигнала
  SPI_InitType.SPI_Polaric = SPI_CPOL_LOW;
  // Задание фазы тактового сигнала
  SPI_InitType.SPI_Phase = SPI_CPHA_1EDGE;
  // Выбор направления передачи данных
  SPI_InitType.SPI_Direct = SPI_DIRECT_MSB;

SPI_init(&SPI_InitType); // Инициализация SPI

lcd_init(0); // Инициализация LCD для вывода данных

  while(1)
  {
    data = SPI_S_byte_io(0xFF, 10); // Получение байта из порта
		
    // Проверка на получение новых данных
    if((data != data_old) && (data != 0xFF)) 
     {
	data_old = data; // Обновить старые данные новыми
	lcd_gotoxy(0, 0); // Установить курсор		
	sprintf(str, "0x%02X", data); // Подготовить данные для вывода
	lcd_str_out(str); // Вывести полученные данные на LCD
	data++;  // Увеличить полученные данные на единицу
	SPI_S_byte_io(data, 10); // Отправить увеличенные данные мастеру
     }
  }
}


Данная программа получает от мастера байт, проверяет не изменился ли он по отношению предыдущего полученного байта и если разница есть, то записывает текущее значение как старые, выводит на дисплей, увеличивает на единицу и отправляет мастеру. Мастер получив байт от слейва тут же возвращает его назад. Если данные пример залить в МК то на дисплее появится нулевое значение, а затем каждую секунду оно будет увеличиватся на единицу.






Скачать библиотеку. axlib 1.0 Версия 1.0 Июнь 2015
Скачать библиотеку. axlib 1.1 Версия 1.1 Март 2016
(Внесены изменения в файл main_init.h в директивы асоциаций типов переменных)



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



Вячеслав    20.08.15 10:50

Приветствую!!! Идея очень похвальная... Буду проверять работоспособность модулей... Если что отпишусь... Нехватает конечно SPI, но надеюсь вы на этом не остановитесь... А может я и сам сдюжу.

Алексей    20.08.15 18:35

Спасибо. Я потихонечку что-то дорабатываю по мере появления ошибок, что-то добавляю. Чем больше людей будет использовать тем быстрее исправлю все ошибки. Мне сложно тестировать на всех режимах. Так что если что-то не пойдет, пишите, поправлю. SPI думаю добавлю. Так как на нее можно флешки вешать.

Вячеслав    27.08.15 12:22

Приветствую... В файле port.h ость опечатка (copipaste, два раза описан PORTC.) // Вывод значения в порт #define PORTA_DATA_OUT(a) PORTA = a #define PORTB_DATA_OUT(b) PORTB = b #define PORTC_DATA_OUT(c) PORTC = c #define PORTC_DATA_OUT(d) PORTD = d

Алексей    27.08.15 20:03

Спасибо, поправил. Сейчас тружусь над SPI и TFT дисплеем ST7735.

Кирилл    08.11.15 17:58

Спасибо за библотеку. Если бы ещё добавить 8-битный режим?

Алексей    08.11.15 21:46

8-битный для ST7735?

Юрий    10.11.15 15:28

Здравствуйте! Можно подробнее про работу ЖК? Как вывести переменную?

Алексей    10.11.15 17:04

Для этого необходимо подключить стандартную библиотеку stdio.h. Далее создать байтовый массив BYTE str[20]. Затем вызвать функцию sprintf(str, "%i", переменная). После выводить на ЖК lcd_str_out(str).

Владимир    16.11.15 16:23

Мужик! Молодец! Читаю с интересом!

Олег    01.12.15 09:13

А можно сюда добавить управление часами DS1307.

Алексей    01.12.15 18:03

Чуть по позже. У меня сейчас на работе безумие. Нет времени.

Сергей    14.12.15 10:57

Я никак ни найду как дефайнится порт на который подключается датчик. и как перечислить все датчики в сети?

Сергей    14.12.15 10:58

Речь идет о 1-Ware

Алексей    14.12.15 11:28

Дефайнятся порт и пин в main_init.h, а датчики, по одному получить ром коды и задефайнить. Руки не доходят добавить функцию чтения нескольких датчиков, это в перспективе.

Алексей    27.12.15 17:34

Олег, Добавил.

Андрей    04.02.16 01:53

Спасибо большое, думал уже не найду нормальные библиотеки с описанием!!!

Степа    11.02.16 07:26

Доброго времени суток, а как бы сделать вывод времени и температуры не на жк дисплей, а на семисегментные индикаторы? И еше вопрос, мне бы через будильник сделать чтобы мк выдавал на ножке одиночный импульс один раз в 24 часа.

Алексей    11.02.16 08:37

Намек на функции для 7-ми сегментника? )))

Степа    11.02.16 09:03

Ага)

Алексей    11.02.16 09:19

Сделаем.

Степа    11.02.16 09:19

Если это важно, то имеется микруха MAX7219 ENG

Степа    12.02.16 18:06

А ты случаем не из Братска?)

Алексей    12.02.16 21:00

Если честно, то я даже не знаю где это. ))

Степа    12.02.16 22:19

В видео к "Работа с UART в AVR" в программе написано ООО"Логика" г.Братск, вот я и предположил, т.к. сам там живу

Алексей    13.02.16 09:57

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

АНОНИМ    15.02.16 12:24

Добрый день.А для датчика SHT21D случайно не собираетесь делать?

Алексей    15.02.16 12:37

Можно было бы, но для отладки я не готов выложить 3 тыра за датчик. Если он есть в протеусе, то можно.

Игорь    16.02.16 14:36

В 7,10 и в 8,0 есть точно

Алексей    16.02.16 16:46

Ок. Гляну.

Алексей    16.02.16 22:03

Глянул. У меня версия 7.7, в ней нет такого датчика.(

Игорь    17.02.16 18:06

Могу прислать 7,10 101 Mb

Алексей    17.02.16 18:48

Не, не надо. Я нарыл 8.3. Уже начал ковырять датчик.

Алексей    19.02.16 09:18

К сожалению протеус отказался работать с софтверным I2C. Искать багу в протеусе мне тоже не хочется. Проверку сделал на железе с микросхемой часов. В железе работает, а в протеусе нет. Если все же есть желание продолжить с библиотекой, то предлагаю перейти на форум. Я туда буду выкладывать наработки, а Вы будете тестировать на железной микросхеме. После отладки, можно уже будет дополнить библиотеку. Данный коммент относится к микросхемам SHT21 и MAX7219.

Игорь    19.02.16 11:38

У меня Mega8, китаец(не русифицированный) 16х2 и датчик SHT21D. Схема сборки стенда?

Алексей    19.02.16 12:19

Могу вечером скинуть для теста чтение температуры.

Алексей    21.02.16 14:29

Куда тестовые функции скидывать?

Игорь    21.02.16 15:54

55-111*bk.ru

Алексей    21.02.16 16:13

Скинул. Если полезут косяки, то сразу отпишитесь.

Алексей    23.02.16 11:25

Степа, С учетом того что у меня нет в наличии MAX7219, а в протеусе не работает ни при каких обстоятельствах, могу скинуть файл для теста на железе. Если интерес еще не угас, то давайте Вашу почту и я скину файл с описанием.

Игорь    25.02.16 10:37

Скажите какой максимальный период работы Вашего программного таймера? Как стандартный T2 или другой?

Игорь    25.02.16 17:58

Уточняю вопрос. (WORD time - Время периода работы таймера. Задается в миллисекундах) какое допустимое значение?

Алексей    25.02.16 20:06

32767 мс.

Павел    27.03.16 02:25

Нашёл критический недостаток в 1w.h. Если во время инициализации (owire_init)шина данных притянута к земле (например, ненадёжным коротящим контактом), прошивка зависает насмерть. Предлагаю вариант, в котором максимальная задержка опроса притянутого вниз контакта сокращена до ~260 мкс (это несколько больше максимального времени ответа по стандарту 1-wire). Заодно добавил в архив ds1820.h с исправленным описанием одной из функций и добавленной проверкой отсутствия устройства, :- ).

Алексей    27.03.16 10:38

Спасибо. Сегодня посмотрю и поправлю. Правда единственная проблема, не загружается архив.

Степан    27.03.16 11:06

Писал на почту которая указана в обратной связи, но ответа так и не дождался по описанию MAX7219. Может на какую то другую почту написать?

Алексей    27.03.16 11:12

У меня сейчас дурдом. Помер хард на сервере из-за частого отключения питания. Возможно в это время и затерялось. Сейчас почта работает и можно писать письма.

Павел    28.03.16 23:58

Упс, виноват, забыл ссылку исправить. Вот так должно работать.

Алексей    29.03.16 00:46

О, супер. Обновил.

Дмитрий    16.04.16 23:00

Доброй ночи! Отличные библиотеки, все очень здорово написано, спасибо! У меня возникла неясность в библиотеке SPI.h : у вас в функции отправки данных ведомым устройством - ведущему присутствует линия PORT_S_OUT , которая сигнализирует ведомому о том, что ведущий готов отправить данные. Мне непонятно, что это за линия и куда она подключается?? При условии, что она у вас весит на PB0, а стандартные линии SPI интерфейса SS/ sck/ mosi / miso уже заняты и определены другими портами O_o. + мне кажется, что необходимо все-таки создать функцию spi_start(uint8_t ss_pin) и spi_stop(uint8_t ss_pin), так как у вас линия SS наглухо забита в лог. уровень 0 , что не позволяет определять начало и конец сессии обмена данными , а также использовать SPI интерфейс при условии, что на шине находится одновременно несколько подчиненных. Надеюсь, что столь отличный проект еще не закрылся и получит дальнейшее развитие.

Алексей    17.04.16 00:29

Иду спать. Я уже офигел, но закончил программу генератор проекта под студию и скоро выложу видео. С SPI надо подумать. Скорее всего внесу изменения в программу. Проект не закрыт, а только начинает набирать обороты. Я даже сам такого не ожидал.

Дмитрий    17.04.16 02:10

Алексей, это просто супер, будет здорово увидеть. А на счет SPI нужно действительно подумать. Мне лично не ясно предназначение линии PORT_S_OUT, если уже есть линия SS, причем для чего в конце отправки слэйвом данных она принимает значение лог. 0 . + пример для spi на сайте, мне кажется нужно поправить. Я могу ошибаться, но мне кажется, что условие if(data != data_old) всегда будет ЛОЖЬ т.к мастер отправляет слэйву 0 , а тот сравнивает data=0 c old_data =0. В итоге 2 контроллера должны бесконечно обмениваться нулями без инкрементации data.

Дмитрий    17.04.16 02:11

Прошу прощения, опечатка : * конце отправки слэйвом данных она принимает значение ЛОГ. 1

Алексей    17.04.16 11:00

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

Дмитрий    17.04.16 16:16

А что на счет примера на сайте ? Правильно ли суждение, что такая программа работать не будет? Ведь мастер посылает 0x00 -> ведомый принимает 0x00 и сохраняет это значение в переменную data. После чего идет сравнение if(data != data_old). т.к data_old =0 сравнение будет ложным и функция вложения выполняться не будет. В ответ , ведомое отправит ведущему содержимое своего регистра SPDR, где также будет находиться 0x00. Далее, ведущий примет значение 0х00 от ведомого и возвратит его функцией BYTE SPI_M_byte_io(BYTE data). Потом в эту же функцию опять подставит значение глобальной переменной data =0 и оправит. Далее процесс будет бесконечно продолжаться обменом 0х00 и все.

Алексей    17.04.16 17:16

Да тут все не работает. Я вообще не могу понять как слейв передает мастеру. В этом месте тупик полный. Уже с утра голову ломаю.

Дмитрий    17.04.16 18:25

Возможно я смогу вам немного помочь: аппаратный SPI интерфейс идет не полудуплекс, а дуплекс обмен данными. т.е имеется 2 регистра данных SPDR: один 1 мастера, 2 у слейва. Они закольцовываются линиями MISO и Mosi. Мастер инициализирует передачу ( только мастер) . В момент, когда мастер отправит данные, которые находятся в его регистре SPDR слейв примет эти данные и автоматически отправит мастеру содержимое SPDR своего регистра ( происходит замещение) т.е то, что было у мастера будет у слейва, и наоборот.

Алексей    17.04.16 18:41

Я все это знаю. У меня мастер работает как часы. Проблема с передачей данных мастеру от слейва. Я даже в слейве настроил прерывания по приему и данные вытаскиваю в обработчике, а вот обратно переслать ничего не могу. Можно перейти на форум, там есть ветка про библиотеку. А то тут много не напишешь.

Дмитрий    17.04.16 19:27

Сейчас буду ехать по работе, вечерком загляну на форум. Может что-то сообразим. Кстати, еще нужно подправить библиотеку 1w.h там есть упущения. Но, в отличии от spi слейва там все ясно, просто и всего пару строк :) 1) Запрещать прерывания вначале функции инициализации и разрешать их в конце не совсем корректно т.к это может привести к необъяснимым глюкам, в больших проектах. Лучше вначале функции сохранить значение регистра флагов прерывания SREG , что-то типа char temp = SREG; потом запретить прерывания и в конце вернуть флаги на свои места SREG=temp. 2) также, в функции имеется 2 цикла for 100 мкс и 255 мкс в которых идет опрос линии. В цикле на 255 мкс есть условие досрочного выхода, а в 100 мкс - условия выхода не имеет. 70 % устройств опустят линию в лог.0 на 60-80 итерации , в итоге 40-20 итераций будет идти "переопрос" устройства, которое и без того уже откликнулось на шине. 3) в этой же функции нужно немного переработать возвращаемые значения. т.е пока гуляем в цикле возвращаются единицы т.е есть какой-то контроль, что все ок, а когда из него выходим - возвращаем 0, что не даст в будущем использовать данную функцию в

Дмитрий    17.04.16 19:29

* в качестве аргимента для какого-то условия.

Алексей    17.04.16 23:05

Все, я его победил.

Алексей    17.04.16 23:32

По поводу 1w.h Если в цикле 255 мс объявится устройство, то тут же произойдет включение прерывания и выход из функции инициализации с возвращаемым значением 1.Либо если вышел срок, а линия все еще в нуле, значит проблема на линии и возвращается 0. 100 мс цикл нужен лишь для ожидания опускания линии устройством. Если в течении 100 мс линию не прижали к нулю, то считается что устройств на шине нет. Сохранения SREG добавил.

Дмитрий    18.04.16 00:19

Да, это я не увидел. Радует, что победили SPI! Уже выложили исправления для 1w и spi? Хотя 1W я уже исправил, так что он не представляет интереса, а вот spi - очень интересно :)

Алексей    18.04.16 01:07

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

Дмитрий    18.04.16 01:41

Еще почитал про энкодер (раньше никогда не пользовался ими). Не могли бы вы мне немного прояснить, а то я запутался в некоторых мелочах, только подробнее: 1) При одном тактильном щелчке приходит 4 одинаковых импульса, так ? Откуда можно узнать сколько их придет? (читал даташиты и не нашел такой информации) -1.1 если импульса придет 4, то мы просто попадаем в один из свичей и дата увеличится 4 раза ? 2) Вы говорите, что используете 16 битную переменную и тут я совсем туплю.. Как у вас получается 255 значений ? Ведь в ней же 65536 значений. Делим на 4 - получаем 16384 возможных значения, а на видео четко видно, что в 255 идет переполнение и отсчет начинается сначала. Надеюсь прольете свет, а то теперь мне этот энкодер спать не дает:)

Дмитрий    18.04.16 03:57

На счет импульсов уже все понял :) Импульса то 2, немного смещенных на 1 оборот, а состояний - 4. Того за 1 оборот data инкрементируется на data+=4. А вот с int переменной все равно не понял, к сожалению, как такое происходит, что она переполняется.

Алексей    18.04.16 09:02

int нужна для счета энкодера. Если она будет char то программа сосчитает только до 64, а с int максимальное значение это 255*4. То есть то что натикал энкодер. У меня как раз в планах добавить в библиотеку обработчик энкодера. А переполнение происходит в регистре вывода порта.

Дмитрий    18.04.16 14:08

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

Алексей    18.04.16 16:41

А вот я описывал работу здесь с энкодером на 400 шагов на внешнем прерывании.

Дмитрий    18.04.16 21:46

Читал, прикольная штука и наверно очень не дешевая :) Но там реализовано через прерывания, а мне кажется, что это не всегда практично. Немного прошерстил и допилил библиотеку для энкодера. Посмотрите, уверен , что так лучше. Залил сюда

Алексей    18.04.16 21:52

Ссылка пустая(поправил). Энкодер покупал здесь.

Дмитрий    18.04.16 22:01

Алиэкспресс, как обычно, творит чудеса o_O

Алексей    18.04.16 22:03

Посмотрел код. Все таки лучше на прерываниях. Если программно то есть небольшая падляна. К примеру вызывается функция вывода на ЖК строки. У ЖК дисплея довольно большие задержки, порядка 10мс. А в этот момент повернули энкодер. Или например идет ожидание данных от датчика. Или пошла передача пакета протоколом. У внешнего прерывания наивысший приоритет и он выполнится по любому и довольно быстро, а вот уже значение которое он записал можно потом и обработать. На глаз будет незаметно и потерь данных не будет. Я на это нарывался как раз когда с 400 шаговым энкодером развлекался.

Дмитрий    18.04.16 22:18

Если использовать LCD, то да ( Причем это касается LCD на базе контроллера HD44780) т.к там с задержками все туго. Например SSD1306 (при условии, что он висит на SPI интерфейсе ) , а энкодер используем обычный, механический (требует опроса всего 800 раз в сек) - будет нормально все. А вообще, для каждой задачи - свое. Где-то будет лучше на прерываниях, а где-то программно. Для проекта типа вашего я бы собрал две библиотеки в одну и сделал, чтобы дефайном можно было выбрать директиву выборочной компиляции : 1- работа на прерываниях ; 0 - работа без прерываний. Так было бы реально круто

Алексей    18.04.16 23:03

Это я уже буду добавлять в программу генератора кода. Там как раз можно галочкой выбрать с прерыванием или без. Вот для затравки скрин программы.

Дмитрий    19.04.16 01:02

Откровенно говоря даже не ожидал. Выглядит шикарно. Представляю, какой труд. Отлично! Без шуток, если ее потом до ума довести ( что будет не легко на самом деле) и раскрутить, то CWAVR прийдет конец(хотя я, например, никогда ей не пользовался). Как по мне она генерит "быдло код" + если заглянуть в некоторые ее библиотеки, то там такое чувство, что их обезьяна писала. Еще можно будет в генератор кода программный SPI запилить. Если лень писать, то могу скинуть свой. Когда на свет появится сея чудо ?

Алексей    19.04.16 10:44

Ну это перебор. До CVAVR мне далековато еще. А вот на счет их библиотек, то это да. Я как раз подорвавшись на DS18b20 решил начать писать свою. Если посмотреть их функцию чтения температуры, то можно ужаснуться. У датчика есть несколько режимов точности отциыровки температуры и самый точный занимает 750мс времени. Так же у датчика есть сигнал окончания отцифровки. Он при старте прижимает линию к нулю, а когда температуру отцифровал, то отпускает ее. И по идее можно определить готовность по этому сигналу. А с CVAVR тупо для всех режимов выделяет 750мс что приводит к туплению МК почти на секунду.

Дмитрий    19.04.16 17:47

Ну так у вас же пока что первая версия будет. Если генератором заинтересуется народ и энтузиазм не угаснет, то за некоторое время можно прийти к тому, что будет на уровне. А на счет ds18b20 - знаю этот прикол. Из-за этой самой задержки на линии иногда бывают сбои и датчик вообще ничего не возвращает т.к мы сильно долго тупим. Ну а даже если упустить момент того, что есть сигнал готовности памяти датчика, то в ДШ все равно написано время оцифровки для разных режимов. Причем ds18b20 это далеко не единственный пример

Дмитрий    19.04.16 17:48

Так когда все-таки выйдет генератор ? :)

Алексей    19.04.16 20:58

Сейчас прошла таможню моя новая отладочная плата. Я ее скоро получу, соберу и на ней покажу все что может программа. Будет много видео.

Дмитрий    20.04.16 03:29

Заговорили о CWAVR, решил ее поковырять. Нашел еще незначительный прикол в ней. Например: хочу получить условия, при которых таймер 0 будет переполняться каждые 1ms и уходить в прерывания по вектору переполнения. CWAVR утверждает, что если я буду работать в режиме NORMAL, то при F_CPU 16 Mhz + прескаллер на 64 и TCNT0 = 0X06 будет мне счастье - согласен с ним. А вот, якобы, в режиме FAST PWR top=0xff при всех тех же условиях период переполнения счетчика будет равен 1.024ms - что совсем не так, ведь будут те же 1ms и дебажер Atmel со мной согласен. Это не очень критично, но начинающего это может ввести в заблуждение т.к человек будет абсолютно уверен, что СWAVR врать не может :)

Дмитрий    20.04.16 03:38

Сразу оговорюсь о том, что в прерывании TCNT0 программно устанавливаем в 0х06 ISR(TIMER0_OVF_vect) { TCNT0=0x06; i++; } СWAVR генерит это но все равно говорит,что период 1.024ms

Алексей    20.04.16 08:06

Там есть еще бага по UART. Если использовать прерывание по приему байта, то в обработчик сваливаешся через раз.

Виталий    26.04.16 22:24

Я не понял как подключать датчик 2103, датчик одно контактный, 2рой контакт на массе, что у Вас там за датчик я так и не понял. по поводу 1ware тоже непонятки, у меня с Вашим кодом так и не пошло, пришлось переписать, объясните пожалуйста как вот это должно работать: ......... #define OWIRE_0 DDR |= (1<<PIN_W) #define OWIRE_1 DDR &= ~(1<<PIN_W) ......... OWIRE_0; _delay_us(480); OWIRE_1; _delay_us(2); то есть Вы сбрасываете шину в 0, юзая регистр DDR, я уж сижу и думаю то ли я дурак то ли лыжи не едут, чтобы изменить состояние выхода, надо DDR установить в 1 и порт уже от требуемого значения, и вернуть DDR в 0, если была записана 1 в порт, то останется подтяжка. Код тестировал на атмега328 на собранной схеме с 18b20 с резистором на +, 2.7к. На шине тишина (осциллографом смотрел) висит вечный +

Алексей    26.04.16 22:55

Датчик подключается к каналу АЦП от клеммы по середине, а GND на корпус. Если посмотреть кишки датчика, то можно представить его как переменный резистор. На счет шины, лыжи не едут. Первое что нужно понять, так это то что однопроводная шина работает по принципу монтажное И. Что это значит. Линия должна быть подтянута к плюсу питания резистором. Поэтому на шине висит всегда единица. Если кому-то приспичит послать на линию ноль, то он просто прижимает ее к земле. Для подачи единицы линия просто отпускается. Зачем это нужно. Представим что мастер прижал линию к земле дабы подать сигнал опроса линии, а в этот момент какой-нибудь слейв сошел с ума и подал на линию единицу. Если следовать вашим рассуждениям, то будет что? Правильно КЗ. Поэтому шина и работает как монтажное И. Если кто-то отпустил линию для передачи единицы, а кто-то прижал к земле для передачи нуля, то приоритет имеет ноль. Логика 0 И 1 = 0. Отсюда и берется дергание DDR. Либо вешаем ножку в воздух и читаем значение, а подтягивающий резистор выводит единицу, либо переводим DDR на вывод, а по умолчанию это ноль. По поводу датчика, если исп

Алексей    26.04.16 23:00

Нужно увеличить количество символов в комментах(( По поводу датчика. Если используется датчик DS18B20, то нужно использовать функцию с передачей в качестве аргумента его РОМ код. Это требуется для распознавания типа датчика. Дело в том что у датчиклв DS1820 и DS218B20 разная логика расчета температуры. А функция без РОМ кода, работает только с датчиком DS1820.

Степан    06.05.16 10:38

Доброго времени суток! Непонятки образовались при компиляции, в файле spi.h выдал ошибку if(spi->SPI_Mode == SPI_MASTER) { SPI_M_PORT; //в этой строке перед ";" должна быть ")" SPI_M_SS_OFF; SPCR = (spi->SPI_set | spi->SPI_Mode | spi->SPI_Direct | spi->SPI_Polaric | spi->SPI_Phase); } Я так и не понял почему она там должна стоять, поэтому просто поставил и он стал компилировать без ошибок. Кто подскажет зачем она там?

Алексей    06.05.16 12:21

А какая версия библиотеки? И когда скачали ее? Такая беда была в ранних версиях, сейчас ее исправил. А лучше скачайте генератор кода, там точно все работает. Генератор кода можно скачать тут. Там и видео есть как с помощью SPI в режиме мастер идет управление TFT дисплеем.

Игорь    13.05.16 16:35

Подскажите.Для того чтобы программный таймер мог считать не кратно одной мс, а кратно 10 мс необходимо поменять только: #define TIME_F_CPU (0.001*F_CPU) или что-то поменять в Функция инициализации таймера (мне кажется делителя 64 будет мало)

Алексей    13.05.16 18:45

А с чего вы взяли что он программный. Тики происходят в обработчике прерывания таймера. timer(TIMER_0, 10, ON); Включение таймера 0 с тиком в 10 мс.

Игорь    14.05.16 11:44

Я правильно понимаю? Таймер Т2 тикает и каждую милисекунду происходит прерывание по совпадению. Счетчик милисекунд увеличивается на единицу.Задача функции инициализации вычислить OCR2 и предделитель в зависимости от частоты процессора. В связи с тем, что мне допустим нужны тики таймера Т2 с периодом 10мс, я могу вручную вписать значения TCCR2 и OCR2 в функцию иницилизации. И тогда запись timer(TIMER_0, 10, ON); будет означать, что таймер у меня будет срабатывать каждые 100мс (десять тиков по 10 мс).

Алексей    14.05.16 13:44

Да. Все верно.

Денис    22.05.16 20:30

Здравствуйте, Алексей. Скажите, а Ваша библиотека ATmega128 поддерживает? А то, я попытался для ATmega128 воспользоваться функциями АЦП, а компилятор ругается, как будто бы функция ADCW не определена до первого использования. При этом, тот же код для ATmega8 нормально компилируется. У меня совсем небольшой опыт работы с микроконтроллерами, и Ваша библиотека сильно облегчила бы мне жизнь.

Алексей    22.05.16 22:49

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

Денис    23.05.16 16:03

Нашёл у себя 8-ку. Так что, удастся воспользоваться Вашими библиотеками. АЦП отрабатывает корректно, остальное буду пробовать. Спасибо за библиотеку.

Алексей    23.05.16 19:12

Если использовать генератор кода, то создавать проекты становится еще проще.

Алексей    17.06.16 10:40

Добрый день, Алексей, пытаюсь использовать вывести температуру DS18B20 на LCD: temperatura = ds1820_read_t(0); далее sprintf(str,"%i", temperatura); - в результате в протеусе выводит 0. Каким должен быть аргумент у функции? Пробовал вашим примером выдает просто "?".

Алексей    17.06.16 15:13

BYTE str[20] = {0};
BYTE rom[8] = {0}; // Для РОМ кода
WORD temperatura = 0;

// Читаем РОМ код датчика.
ds1820_rom_code(rom);

// Получаем температуру умноженную на 10
temperatura = ds1820_read_t(rom);

// Форматируем строку
sprintf(str, "T %0.1f", (ADATA)(temperatura/10));

// Вывод на ЖК
lcd_goto(0,0);
lcd_str_out(str);

Алексей    17.06.16 16:10

Спасибо за быстрый ответ! Сделал по написанному, но результата нет, вместо температуры знак вопроса.

Алексей    17.06.16 16:38

Так нужно подключить поддержку чисел с плавающей точкой в свойствах пороекта.

Алексей    17.06.16 16:38

Заменил %0.1f на %i выдает 0.

Алексей    17.06.16 16:40

Извините, Алексей, только учусь. Где это сделать?

Алексей    17.06.16 18:32

Я сейчас в пробке за рулем. Вечером доберусь и напишу. А сейчас рекомендую посмотретть цикл видео по генератору кода. Много что прояснится.

Алексей    18.06.16 18:16

Чтобы избавиться от вопросов и выводить число с запятой, нужно посмотреть видео про генератор кода часть 6. Время 9:50 я как раз рассказываю как и что нужно сделать.

Алексей    19.06.16 03:12

Спасибо, все заработало и с запятой отображает. Правда после запятой ноль(ноли). Может протеус глючит, проверю завтра на железе.

Алексей    19.06.16 09:54

Я обычно все делаю на железе. Протеус не всегда корректно исполняет код.

Алексей    19.06.16 14:41

К сожалению нет отладочной платы. Но это мелочи. Интересует возможность счета импульсов от внешнего источника. Если конкретнее измерение частоты генератора на NE555.

Алексей    19.06.16 15:06

На внешнем прерывании.

Алексей    19.06.16 15:19

А в библиотеке или генераторе это ожидается?

Алексей    19.06.16 18:28

Да, уже спрашивали. Буду добавлять.

Александр    07.07.16 09:39

Здравствуйте! Скачал Вашу библиотеку,все очень нравится! По поводу i2c. С датчиком ds1621 в протеусе все работает! Спасибо!

Алексей    07.07.16 09:57

Главное чтоб работало в железе. Протеус это темная лошадка))))

Тёмыч    24.07.16 21:01

День добрый! Не могли бы Вы мне переделать библиотеку под CodeVisionAVR (конкретно нужно только для дисплея на st7735s, перерыл весь интернет, такой библиотеки не нашёл)? Или хотя бы как нибудь помочь с моей проблемой. Пробовал залить Вашу в CodeVisionAVR - выдаёт ошибку: Error: C:\cvavreval\inc\main_init.h(1), included from: Òåñò TFT st7735s.c: 'ï' not expected С уважением,Тёмыч.

Алексей    26.07.16 18:19

Ну ошибки это нормально. В конце концов разные IDE. А так под кодвижн нужно писать свою, так как у нее свои библиотеки длч работы с SPI. Либо периходить на студию.

Тёмыч    26.07.16 22:56

Алексей, спасибо и на этом. Значит придётся переходить на студию из-за одного только дисплея :) хотя я и в кодевижене ещё только начинающий. :)

Алексей    27.07.16 08:40

Я слез с кодвижена по двум причинам. Первая, это закрытые библиотеки, второе, это блокировка прерываниц и подгонка для универсальности во преки работе кода. И так же есть нееоторые косяки из-за этого. Например криво работает прерывание при работе с UART, хотя в новых версиях может и исправили. Так же студие бесплатна в отличии от вижена.

Степан    12.08.16 16:36

Как успехи с радио модулем? Или уже предумали под него библиотеку писать?

Алексей    13.08.16 08:21

Пока тупик. Много багов в модулях. Умные люди вообще посоветовали бросить это занятия. Работают крайне не стабильно. Сейчас общение с модулем на ура, а при предаче много битых пакетов приходит. Толи модули у меня паленые, толи действительно сами камни лажовые. С блютузом и вайфай таких проблем небыло.

Степан    13.08.16 10:13

Радиоуправление моделью на чём лучше сделать?

Алексей    13.08.16 14:51

Какая дистанция?

Степан    14.08.16 14:37

Метров 100, не более

Алексей    14.08.16 15:05

Тогда проще блютуз использовать. Данные модули представляют собой радио удлиннитель UART и на 100 метров бьет как нечего делать. Можно припаять проволрку к антене и увеличить качество связи. Для управления нужно подать пару команд, а дальше модули сами будут соединятся и передовать данные.

Константин    15.08.16 11:52

Огромное спасибо за библиотеку! Я тут мудрю над GSM-шлюзом для ворот на ATMEGA328, и думаю, где хранить список телефонов (около 200 штук). Есть 2 варианта: 1. На SD карте (мне не нравится, да и в библиотеке нет :)) 2. В EEPROM. Отсюда вопрос - как запихать массив с телефонами в EEPROM не задействуя МК? Или задействуя но один раз при старте... Поможете?

Алексей    15.08.16 22:00

Во первых нужно подумать над концепцией записи телефонов. Если хранить номер как ASCII, то понадобится по 10 байт на номер, так как в номере 10 цифр. Можно уплотнить вдвое записывая по две цифры в байт. Один полубайт может записать от 0 до 15. Правда придется потом на ходу разбирать байт на полубайт и прибавлять 0x30 к каждой цифре. Из этих рассуждений можно посчитать что для 10 байтового хранения нужно выделить 10*200=2000 почти 2Кб, а для 5 байтового 1Кб. Отсюда могу предложить заносить номера по очереди, а читать по порядковому номеру со смещением на 5. Чтение вести пакетом по 5 байт. Второй вопрос первоначальной записи. Здесь есть два варианта. Первый - это создать HEX файл со семи номерами и залить в EEPROM при помощи программатора, а второй - это записывать номера через МК, который считывает из написанной на скорую руку программы под ПК по линии UART, через переходник USB-UART. Я давно писал программу для управления шлагбаумом. Модуль состоял из MEGA8 и SIM900D и как раз такой же EEPROM. Когда нужно было открыть шлагбаум, человек звонил на модуль. Модуль смотрел номер звонящего по определителю и если тот совпадал с базой, то он открывал шлагбаум. В базе было 1000 номеров и к каждому еще было записано имя и фамилия хозяина. Короче так этот модуль в дело не пошел))) Базу можно править СМС сообщениями. Так вот если я найду исходники, то могу поделиться.

Константин    15.08.16 23:43

Вы будете смеяться - но именно эта задача у мну и выполняется.. :) И на данный момент это счастье работает на M590E + Arduino Pro mini + SD + DS1307 + 1602. Я даже ради такого дела ЛУТ освоил - плату вытравил и напаял разъемов.. :) Но SD периодически отваливается и я подумал про EEPROM или FLASH... В общем внутренний перфекционист свирепствует. А поскольку последний раз брал паяльник для пайки мультивибратора на МП42Б в школе, а высшим достижением в программизме была сортировка "пузырьком" почти 20 лет назад, приходится осваивать все заново... :) По делу: для загрузки телефонов мне видится софтина, читающая текстовый файл, пихающая его МК по USART, а МК, при 1 на какой-нибудь ноге, пихал поток в EEPROM. Вот только с памятью не разберусь. Я так понял, что бывает параллельная (i2c) и последовательная (SPI). Думал про что-то типа 24C64AN-РU27 - должно хватить с запасом. Хотелки-то растут.. Пока балуюсь с at24c02 - вроде получается... Что-то я не понял, как хранить номер в 5 байтах... З.Ы. Для балбесов типа меня надо бы в библиотеку (и генератор) добавить работу с SD... :)

Алексей    16.08.16 08:41

SD - это стрельба из пушки по воробьям. Да и с картой лучше работать на STM32 у которой есть полноценный SDIO, а не ущербный SPI. По поводу I2C - это последовательная шина, а не параллельная. У AVR это TWI дабы не платить оброк Philips. Лучше использовать EEPROM. Телефон в пяти байтах выглядит так: +7 и 8 это всегда одно и тоже, так4 что их запоминать не надо. 916-123-45-67 в пяти байтах 0x91, 0x61, 0x23, 0x45, 0x67. Для чтения из памяти нужно адрес смещать на 5 байт. Например для чтения телефона по адресу 138 нужно 138*5 и получится адрес первого байта телефона 690. Далее читаем 5 байт и разбираем их на номер.

Сергей    17.09.16 13:53

А можно в следующей версии программы сделать поддержку ATMEGA128A ? Они сейчас по цене не сильно дороже ATMEGA8 на алиэкспрессе ,логично начать их применять более широко.

Алексей    17.09.16 18:42

Они очень сильно отличаются в периферии. Но я думаю что можно будет добавить.

Сергей    17.09.16 19:57

Спасибо. Буду ждать с нетерпением (наверняка не я один).Очень полезный проект.Спасибо за него.

Константин    20.09.16 09:05

Для 328Р неправильно инициализируются таймеры... :(

Алексей    20.09.16 10:47

Что не так? 328 специфическая микросхема)) Я так бутлоадер на ней и не поднял. Что не так с таймерами? Я поправлю.

Константин    21.09.16 16:48

Виноват, это скорее к генератору кода... Файл timers.h из библиотеки генератора. Функция timers_init(): void timers_init(void) { if(TIME_F_CPU > 256) { if((TIME_F_CPU/8) > 256) { TCCR2 |= (1 << CS21)|(1 << CS20); // Предделитель OCR2 = (BYTE)(0.001*F_CPU_64); // Значение сравнения } else { TCCR2 |= (1 << CS21); // Предделитель OCR2 = (BYTE)(0.001*F_CPU_64); // Значение сравнения } } else { TCCR2 |= (1 << CS20); // Предделитель OCR2 = (BYTE)(0.001*F_CPU); // Значение сравнения } TCNT2 = 0x00; // Счетчик TIMSK |= (1 << OCIE2); // Разрешение прерывания Т2 по совпадению sei(); } В 328 меге регистры по другому называются: TCCR2 - TCCR2B OCR2 - OCR2B TIMSK - TIMSK2 И, соответственно, фунция прерывания ISR(TIMER2_COMP_vect) тоже должна быть другой - ISR(TIMER2_COMPB_vect) Если, конечно, я ничего не напутал.. :)

vuser133    21.09.16 22:11

Здравствуйте. Вопрос - что означает "Включить генератор портов"? Вроде в видео где то было про этот пункт, но что то не найду. p.s. Отличный генератор! Надеюсь еще есть энтузиазм! :)

Алексей    21.09.16 22:18

Константин. Я исправил багу. Есть готовый файл. timers.h Его нужно подменить в проекте. Я его потом добавлю в генератор. Ща просто нет времени, занимаюсь вплотную 3D принтером.

vuser133. Это значит что если поставить галочку, то подключиться библиотека с портами и проинициализируются те порты и пины что были выбраны. Если галочку снять, то библиотека портов не подключиться.

vuser133    26.09.16 15:09

Приветствую еще раз! :) А такой вопрос - если есть желание использовать IAR, то много переделывать придется в исходниках полученного проекта?

Алексей    26.09.16 15:38

Мне нужно посмотреть на хидер под камень. И еще нужно будет переписать задержки. Обработчики прерываний. В общем прилично так.

Олег    02.10.16 00:17

Пытаюсь подключить 18b20 , так выводить ерунду
temper = (((WORD)temp[1] << 8) | (WORD)(temp[0] * 5));
сделал по даташиту
temper =( (((WORD)temp[1] << 8) | (WORD)(temp[0]))*0.0625*10);
похоже на првду, как надо?

Алексей    02.10.16 22:18

Данные функции изначально писались для DS1820. Поэтому для того чтобы получить температуру из DS18B20 нужно использовать функцию

WORD ds1820_read_t(BYTE *rom)

Она умеет определять тип датчика и сама вычислит температуру.

vuser133    03.10.16 08:01

Попробовал повторить по видео подключение DS18B20 и вывод на ЖК дисплей - все заработало. МК Atmega16a.

Алексей    03.10.16 11:13

Все верно, косяки пока с 328 мегой. Там архитектура немного хитрая. Сейчас работаю над этим.

Александр    09.10.16 19:11

Пытаюсь вывести знак минус на семисегментник, используя микруху MAX 7219. Не получается. Подскажите как.

Александр    09.10.16 19:12

Вывожу так:
max7219_data_out(1, 0b00000010, MAX7219_POINT_OFF);

Александр    09.10.16 19:30

Режим декодирования включен, но в даташите на max7219 написано, что минус выводиться должен при таком режиме. Буквы H E L P выводятся, пустой символ тоже, с минусом какая-то трабла.

Алексей    09.10.16 19:34




#include

#include "main_init.h"
#include "axlib/max7219.h"

// Здесь должны находиться ваши подключаемые файлы


// Здесь должны находиться ваши глобальные переменные


int main(void)
{
// Здесь должны находиться ваши локальные переменные

// Инициализация MAX7219
max7219_init(MAX7219_TEST_ON, MAX7219_DECODE, 2);
// Настройка яркости сегментов
max7219_light(0);
// Очистка дисплея
max7219_clear();

// 1 разряд выводим 5
max7219_data_out(1, 5, MAX7219_POINT_OFF);
// 2 разряд выводим -
max7219_data_out(2, 10, MAX7219_POINT_OFF);

while(1)
{

// Здесь должен находиться ваш код
}
}





Александр    09.10.16 19:47

Спасибо огромное, все получилось.

Александр    09.10.16 19:55

Еще, подскажите пожалуйста, правильно ли я вывожу температуру на семисегментник:

куски кода:

BYTE rom [8] = {0};
WORD temperatura = 0;


ds1820_rom_code (rom);


temperatura = (ADATA)(ds1820_read_t(rom)/10);


max7219_data_out(4, 10, MAX7219_POINT_OFF);
max7219_data_out(3,((temperatura)/10),MAX7219_POINT_OFF);
max7219_data_out(2,((temperatura)%10),MAX7219_POINT_OFF);
max7219_data_out(1, 10, MAX7219_POINT_OFF);

Алексей    09.10.16 20:24

А зачем такие сложности. Проще вызвать функция sprintf и она загрузит число в массив разобрав его по символам, а потом по ячейке массива вывести число.

Александр    09.10.16 21:27

Вот я сначала и пробовал со sprintf. Но то-ли я что-то не так написал, то-ли не понял вообще, как на семисегментник с её помощью вывести значения температуры. Если не трудно, на моем примере кода можете показать как правильно?

Алексей    09.10.16 21:38




// Массив для вывода
BYTE str[5] = {0};

// Допустим температура 35,5 градусов, то есть 355 в переменной

sprintf(str, "%i", temperatura);

// Теперь
str[0] = 0x33; // Это символ трешки
str[1] = 0x35; // Это символ пятерки
str[2] = 0x35; // Это символ пятерки
str[4] = 0x00; // Это конец строки



Александр    09.10.16 21:41

Спасибо, вот я дятел, один косячок вписал. А так все правильно было.)))

Алексей    09.10.16 21:55

Всякое бывает.

Александр    10.10.16 23:18

Появляется вот такой варнинг:
Warning iteration 3u invokes undefined behavior [-Waggressive-loop-optimizations]
в 1307.h в строке

*str = ((temp[i] & 0x0F)+((temp[i] >> 4) * 10));

Алексей    11.10.16 08:04

Что-то перемудрили в коде, такого недолжно быть. Скиньте весь проект.

Евгений    12.10.16 07:52

Добрый день. Библиотека совместима со студией 4ой версии (4.19, build 730) ?

Алексей    12.10.16 10:23

Не пробовал. Возможно заработает.

Евгений    12.10.16 10:48

Понятно, буду пробовать, при компиляции идут ошибки на файл с типами данных и т.д., пытаюсь подправить.
Алексей - еще вопрос по поводу меги128, будет поддержка? необходимо два UART'а для задачи, как и что нужно подправить чтобы возможно было работать с обоими UART'ами меги128 ?

Алексей    12.10.16 11:08

Нужно перепахать кольцевой буфер, добавить обработчик прерывания второго UART и немного поправить функции для выбора порта. Задачка не простая, так что я пока за нее не брался.

Александр    12.10.16 11:10

Если делать так:
// Массив для вывода
BYTE str[5] = {0};

// Допустим температура 35,5 градусов, то есть 355 в переменной

sprintf(str, "%i", temperatura);

// Теперь
str[0] = 0x33; // Это символ трешки
str[1] = 0x35; // Это символ пятерки
str[2] = 0x35; // Это символ пятерки
str[4] = 0x00; // Это конец строки

то код в 2 раза больше памяти занимает, чем так:

max7219_data_out(4, 10, MAX7219_POINT_OFF); // У меня индикатор 4-х разрядный с двоеточием и точками, поэтому
// вместо двоеточия на дате включил разделитель точку
temper = (ADATA)(ds1820_read_t(rom)/10);
max7219_data_out(3, ((temper)/10), MAX7219_POINT_OFF);
max7219_data_out(2, ((temper)%10), MAX7219_POINT_OFF);
max7219_data_out(1, 10, MAX7219_POINT_OFF);

Алексей    12.10.16 11:13

А почему в два раза больше? Или программа просто читает температуру и выводит на дисплей?

Александр    12.10.16 11:14

С варнингами разобрался. Студия что-то косячит. При повторной компиляции варнинги исчезают

Александр    12.10.16 11:15

Именно, читает и просто выводит на индикатор

Евгений    12.10.16 11:16

Алексей, а как еще можно организовать такую задачу - головной контроллер работает с SIM900, а также должен общаться через RS-485 с двумя слейвами (в обе стороны - ну понятное дело по запросу мастера)

Алексей    12.10.16 11:47

Евгений >> На одном порту и SIM900 и RS-485? В принципе это возможно. Для этого нужно поставить микросхему 6 буферных элементов с тремя состояниями. Например 74HCT367N. Она разбита на 2 и 4. На пару вешаешь SIM900, а из четырех оставшихся вешаешь на MAX485. Далее МК ножками OE1 и OE2 выбирает с кем нужно сейчас общаться.

Алексей    12.10.16 11:48

Александр >> Е=Если это все что нужно, то чего трястись над памятью.)))

АНОНИМ    12.10.16 12:03

Как вариант, да, только как все это разделить во времени ? ) надо обдумать. Поэтому и хотелось на разные порты посадить, чтоб два UART'а было. Или это сложнее получиться ? Не могу сам пока представить как и что. На данный момент есть девайс рабочий с SIM900, нужен обмен со слейвами. Кстати тут готовую платку исследовал - там на порту висит 4х канальный аналоговый мультиплексер/демультиплексер HCF4052 - им и коммутируется порт либо на rs485 либо на обмен данными с другим контроллером

Алексей    12.10.16 12:50

мультиплексер/демультиплексер не может каналя переключать. У него на вход подается бинарное число, а на выходе соответствующая нога падает в ноли или в единицу. Если наоборот, то подав бит на ногу входа, на выходе появляется бинарное число. Здесь только буфер подойдет. Для управления нужна всего одна нога и NPN транзиль в ключевом режиме. Если загорячиться, то можно на транзилях схему собрать, тоже работать будет, для этого 4 транзистора нужно. Два NPN и два PNP.

АНОНИМ    12.10.16 12:58

Алексей, вот посмотри схемку включения, я конечно не разбирался еще что и как работает, пока зарисовал просто.ссылка

Алексей    12.10.16 13:15

Ссылка битая, нет адреса сервера.

Евгений    12.10.16 13:16

Алексей, подключил библиотеку на 4 студии, возник вопрос об индикации обмена данными - функции mhbus_led_init и led_on, led_off, их нет нигде, как в видео.

Евгений    12.10.16 13:18

Чтобы не засорять статью, Алексей, можно связаться с Вами по e-mail или другим способом?

Евгений    12.10.16 13:20

Там просто ссылка получилась не верная, после обработки кодом сайта ) ftp://john584.ddns.net/4052.jpg

Алексей    12.10.16 13:48

Моя почта на самом верху справа над ящиком почтовым. По схеме 4052 выполняет ту же работу что и 74HCT367N. Так же можно взять микросхему KP3040SB и будет вообще опторазвязка))) Короче вариантов раздваить порт, куча.

Александр    13.10.16 09:53

Да как бы не хватает ее (памяти). На другой контроллер переходить жаба душит- плата разведена и собрана. На мегу 328 перейти- что-то я косяк с ацп заметил ( не такие значения выводит в UART, меньше). Соответственно или методом научного тыка подбирать резистор, или в коде что-то править. Код то одинаковый, а вот разница примерно в половину. Да и не работал я с ней толком. Для моих проектов ATMega 16- с головой хватает для больших и atmega8 поменьше. Ну и тинька 13. От нее вообще балдю )))

Алексей    13.10.16 09:55

Неужели нехватает 8кб для того чтобы читать температуру и выводить на дисплей. Чтож там за код такой хитрый))))

Алексей    13.10.16 09:57

Блин, от 328 одни проблемы, то не работает, се глючит. надо с ней серьезно разобраться.

Александр    13.10.16 09:59

Да нет, там то не только это. Контроллер для террариума делаю. Там еще и релюхи (подогрев воды, подогрев площадки), ультрафиолет и просто освещение, и таймеры и кормушка на шаговом движке.

Александр    13.10.16 10:01

Купил на свою голову сынуле черепашек)))

Алексей    13.10.16 10:02

Правильно, нужно Было кошку покупать. Приучил к толчку, только спускать остается.))))

Александр    13.10.16 10:06

Кошка , как оказалось, дешевле обошлась бы )))

Александр    13.10.16 10:12

Просто хотелось попробовать в работе MAX7219. Микруха понравилась. А то дома 10 штук матриц 8х8 двухцветных без дела лежат. На сдвиговом регистре слишком много всего нужно будет, а на мах7219 вообще халява со схемотехникой. Ардуину не хочу ставить, хоть и готовых скетчей на нее туева хуча. Планирую на меге 16, потому, что слишком много задумок.

Алексей    13.10.16 10:17

Я от 16 отказался в пользу 32. Тот же корпус, теже деньги, а памяти в два раза больше. Даже загрузчик под не запилил.

Евгений    13.10.16 11:42

Алексей ! хотел спросить - а при коммутации порта uart с помощью 74HCT367N, порт нужно сначала в программе отключать ? задавать параметры обмена и включать уже с другими параметрами для связи с другим девайсом ?

Алексей    13.10.16 12:26

Если у девайсы требуют другие параметры, то да.

Евгений    13.10.16 12:33

А если одинаковые, то ничего не надо останавливать ? просто переключать и все ?

Алексей    13.10.16 12:45

Да. Это же не ПК, драйвера перегружать не надо. Просто меняем линии и продолжаем передачу данных.

Олег    15.10.16 13:06

Спасибо за Ваш труд. Как вывести русский шрифт на дисплей 1602?

Алексей    15.10.16 13:15

Смотря какой дисплей.

Олег    15.10.16 13:58

Какие бывают, как отличить, вот у меня только написано 1602А.

Алексей    15.10.16 14:11

Китайский или МЭЛТ? Winstar?

Олег    15.10.16 14:33

Самый дешевый из китая.

Алексей    15.10.16 15:07

В axlib есть поддержка русского, но она сырая и не совсем корректно работает. В любом случае можно ее попробовать, но есть ограничения. Нельзя использовать больше 8 уникальных русских букв. Дублировать можно. Это связано с памятью ЖК. Для активации поддержки русских букв, нужно в файле main_init.h разархивировать строку
//#define RUS_FONT.
А для вывода строк, использовать функцию
void lcd_rus_out(BYTE *str, BYTE x, BYTE y).

Олег    15.10.16 16:36

Генератор кода не поставил в проект #define RUS_FONT и RUS_FONT.h, подкинул руками. Но при попытки вывести русскую стр выводит тольrj одну букву I ,нашел на просторах фразу "ѕpёіeї јёp" получил "оригеп мир", как правильно выводить?

Алексей    15.10.16 17:38

Ха.. Все верно. Так как эти функции еще сырые, то я их в генератор не вставлял. Что вывести надо? Какую фразу?

Олег    16.10.16 00:33

Разные фразы , понять принцип надо...

Алексей    16.10.16 11:56

Не, что-то не работает. Мой совет, проще купить дисплей с поддержкой русских букв. WINSTAR, МЭЛТ. И не морочить себе голову. У меня сейчас нет времени разбираться с функцией русских букв. Я забросил это дело из-за того что дисплей может держать в памяти не более 8 символов, а этого мало для русского алфавита. Видать когда я пытался впихнуть не впихуемое, то потерпел неудачу и забил на это. Поэтому данная функция официально не входит в состав библиотеки. если все же есть желание допилить ее, то милости просим. Русские шрифты уже готовы, так что осталось только допилить функцию. Если конечно получится)))

Олег    17.10.16 00:07

Алексей спасибо за совет, сам понял, что дисплей с русским шрифтом проще и память мк целее.Но увидеть русские буквы мне удалось перебирая аски коды в стр , они получаются не на своих местах ,это увидел и в массиве lcd_rus_b, но не понял почему так. Какая функция выведет русский шрифт на русифицированный дисплей?

Алексей    17.10.16 10:37

Здесь опять же нужео смотреть на дисплей. Если наш, от фирмы МЭЛТ, то в некоторых есть команда смены страницы знакогенератора и сменив на русский можно напрямую печатать русскими буквами. Если винстаровский, то есть куча программ генераторов, которые переводят русские буквы в необходимые коды для ЖК. Некоторые сразу генерят массив.

Олег    17.10.16 17:28

Получилось , дисплей пишет по русски, но пришлось поменять коды символов под то что выдает sprinf (win-1251) и lcd_rus_out соответственно определение шрифтов , не зная насколько это плохо и какие грабли будут, главное не понял как работает проверка на D0 D1 в начале функции, D0 D1 это кто? Буду признателен если посмотрите код , куда его кинуть.

Алексей    17.10.16 19:15

На почту.

Алексей    17.10.16 20:33

D1 и D0 это буквы UTF-8.

Александр    23.10.16 19:31

Алексей, а нельзя запилить в генератор библиотеку дисплея Nokia 3310 (5110)?

Алексей    23.10.16 19:46

Можно было бы, да у меня такого нет и я с ним не работал. Если кто одолжит, то можно добавить и в генератор.

Иван    25.10.16 17:19

Здравствуйте, интересный проект... а с какими версиями AVR Studio он работают? у меня стоит 4.19. там нет такого пути как описано у вас в начале статьи.

Алексей    25.10.16 18:00

Ответ в названии статьи. "Библиотека для AtmelStudio 6.x а-ля CodeVisionAVR" )))))

Александр    26.10.16 22:41

Есть у меня в загашнике 3 дисплейчика Nokia 3310 (5110). Могу поделиться/

Алексей    27.10.16 00:42

Я из любопытства на али заказал. Через пару недель приползет)))

Александр    27.10.16 09:08

Мои от туда же. Работают.

Алексей    27.10.16 11:00

Я наверное еще добавлю дисплей OLED SSD1306 128x64. Только с шиное I2C в режиме записи. Можно выводить текст и рисовать свои картинки.

Александр    28.10.16 09:25

Маловат он, может лучше KS0107, KS0108 ?

Александр    28.10.16 09:32

И еще хотелось бы (если возможно и сильно не затруднит), библиотеку опроса кнопок. Я использую от сюда:библиотека. Нравится, что многое предусмотрено.

Алексей    28.10.16 10:25

Матричную ХхУ клавишь?

Александр    28.10.16 10:59

Да нет, обычные тактовые, на долгое нажатие, двойной клик, отпускание кнопки, обычное нажатие. И на кучу кнопок.

Алексей    28.10.16 11:25

Я подумаю.

Александр    28.10.16 15:31

Кстати, по работе с max7219. Количество знаков нужно указывать на один меньше. Т.е, у меня 4-х знаковый индикатор, в инициализации нужно писать так:
max7219_init(MAX7219_TEST_ON, MAX7219_UNDECODE, 3);

Работает, конечно и так:
max7219_init(MAX7219_TEST_ON, MAX7219_UNDECODE, 4);
тогда при восьми нужно писать 7? или 8? Не пробовал.

Алексей    28.10.16 18:37

Нет не правильно. Нужно задавать от 1 до 8. Интересно, а сколько должно загореться символов если передать например 0 или -8?

Александр    30.10.16 16:12

Я думал,что это- количество подключенных индикаторов, а не сегментов. Или я не прав? Просто , если на моем четырехзначном индикаторе выставить 2 в инициализации, то горят 3 индикатора, а на четвертый ничего не выводится

Алексей    30.10.16 18:17

Это количество разрядов. Эти данные передаются микросхеме управления для правильного расчета тока подаваемые на сегменты.

Андрей    23.11.16 23:09

Почему то в новой версии Atmel Studio 7 при подключении этой библиотеки выдаёт ошибку, якобы она не найдена, хотя я прямо прогу "носом тыкнул" прописав полный путь. С предыдущими версиями такого не наблюдалось...

Алексей    24.11.16 17:35

А у меня вообще 7 студия вылетает с ошибкой. По ходу 7-й можно пользоваться через годик. Та же песня что и шестая. Выявили все баги и она заработала)))

Александр    24.11.16 21:34

Работаю в 7-й версии. Пока был только один баг выявлен.

Алексей    24.11.16 21:40

Наверное уже по испровляли, нужно скачать новую версию и попробовать.

Александр    24.11.16 21:48

Алексей, c Вашей библиотекой MAX7219 можно только с одной микросхемой работать. Нельзя ли добавить поддержку работы больше, чем с одной микросхемой? И еще, по- моему, включение и выключение точки хорошо только для семисегментников, а вот с Led-матрицей получается полная ерунда. Ну и бегущую строку практически нереально реализовать. Пришлось писать свою библиотеку на эту микруху. Вроде работает, строка бежит. Надо только до ума довести код. А так получилось- текст ввел, длиной лишь бы памяти хватило, и все.

Алексей    24.11.16 22:46

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

Антон    08.12.16 22:29

Спасибо! Колоссальный труд!

Артём    11.12.16 15:39

Спасибо Вам огромное!

Виталик    11.12.16 18:46

Вот смотрю и офигиваю над вами. Что тут, что модели для диптраса. Спасибо, класс, а можно сделать так, а добавте в библиотеку такую микросхему. А сами что, слабо. Не хотите, не можете, ну так хоть отблагодарите человека.

Руслан    02.02.17 00:58

Хотел спросить есть ли у кого нить библиотека под Atmel Studio
для 18d20.
Если есть то скиньте на мой емейл:
ruslan_markiv@mail.ru
Заранее благодарен!

Алексей    02.02.17 07:49

А эта типа не подходит. Нужно что-то экзотичнее?

Руслан    04.02.17 23:46

Не могу сказать что она мне не подходит (єто единственная библиотека которая у меня подключилась к Atmel Studio ) но не могу разобратся как вивести температуру и ROM код датчика.
Написал как у вас в примере:

#define F_CPU 8000000UL
#include <avr/io.h>
#include <util/delay.h>
#include <avr/eeprom.h>
#include <avr/pgmspace.h>
#include <string.h>
#include <stdio.h>

#include "1w.h"
#include "ds1820.h"

#include "DEFINE.h"
#include "1616_S_SPI.c"


char id_ds [8] ;
char id_lcd [8] = {0};
char t1_lcd [10] = {0};

void preset (void)
{
LCD_DDR = 0xFF;
LCD_PORT = 0x00;
owire_init();
lcd_init_rgb();
ds1820_rom_code(id_ds);


SetOrientation(LCD_ORIENTATION_270);


}

int main(void)
{
preset();
while(1)
{
bgcolor = YELLOW;
put_string(0, 1, "temperatura", BLACK,1);
if (owire_init())
{
put_string(0, 15, "Dat OK", BLUE,1);
}
esle
{
put_string(0, 15, "No Dat", RED,1);
}

sprintf(id_lcd,"%x",id_ds);
put_string(0, 35, id_lcd, GRAY,1);

sprintf(t1_lcd, "T %0.1f", (long)(ds1820_read_t(id_ds)/10));
put_string(0, 75, t1_lcd, BLACK,2);
}
}

Датчик єта программа видит (когда он есть прога пишет Dat OK а когда его нет то No Dat) а вот вивести ROM код и температуру не виводит.
Вместо ROM кода написано 151 а вместо температури Т ? (когда он есть и когда его нет).




АНОНИМ    04.02.17 23:53

Вашу библиотеку немного упростил чтоб не нужно било подключать main_init.h и type_var.h

Руслан    05.02.17 00:03

Просил библиотеку бо думал может на другой получится вивести ROM код и температуру.

Алексей    05.02.17 09:47

Скачайте генератор кода. С ним на много проще.

Руслан    05.02.17 13:04

С вашей библиотекой проблем нет!
Мне только не нравилось что там нужно подключать 4-е файли 1 из которих только для вибора порта к которому подключен датчик а второй вообще не пойму для чего (для чего преобразовивать типи исчислений char, int, float... в совсем другие слова и потом оперировать ими) их я и удалил подкоректировав код в двух остальних!
А вот с помощью
sprintf(t1_lcd, "T %0.1f", (long)(ds1820_read_t(id_ds)/10));
put_string(0, 75, t1_lcd, BLACK,2);
никак не удавалось вивести число на єкран (Т ?)
За 3 дня поисков в интернете нашел несколько методов вивода числа на єкран перепробовал все и только с функцией itoa мне єто удалось!
А вот вивести число ROM код датчика так и не удается!
Теперь я понимаю почему но не могу найти способ!
ROM код записан в масив в шеснадцатеричной системе исчисления (01,2а,1с,00,09,2b,4c,0f и система перевода понимает что 2b или 4c или 0f єто цифра 0-9 и потому их виводит не коректно )
Пока что не смог найти функцию которая єто может коректно перевести!
Если ви знаете такую(чтоб преобразовать масив в шеснадцатеричной системе в масив char типа для вивода его на єкран ) то подскажите пожалуйста!
Заранее благодарен!!!

Алексей    05.02.17 17:35

Вот кино с ответами на все вопросы.
А вот архив проекта к видео.

Руслан    05.02.17 21:59

Огромнейшее тебе спасибо от меня и моего дисплея :)!
Жаль не могу фотку прикрепить!
Все работает!

sprintf(str, "%02X%02X%02X%02X%02X%02X%02X%02X", rom[0], rom[1], rom[2], rom[3], rom[4], rom[5], rom[6], rom[7]);

Да никогда в жизни би не додумался до єтого!
Еще один вопрос а масив в шеснадцатеричной системе каким нибудь другим способом вивести на дисплей можно?
А то єта функция уж больно сильно прожорливая!!!

Program Memory Usage : 7180 bytes 21,9 % Full
Data Memory Usage : 194 bytes 9,5 % Full

И єто только несколько надписей rom код и температура!
Хорошо что у меня Atmega328 а если б єто била Atmega8?

Алексей    06.02.17 14:01

И снова кино)))

Руслан    13.02.17 23:16

Привет!
И еще раз огромнейшее тебе спасибо!!!
Даже и не знаю что б я без тебя делал!!!
Очень мало таких людей которие готови помочь начинающему в освоении новой для него информации и поєтому много людей на спотикавшись вдоволь оставляют єту затею так ничего и не добившись!

Єто бил висший пилотаж!
И вроде би очень просто но у меня даже и в мислях не било что можно такими простими действиями перевести шеснадцатеричное число в символ.
Да и про прогу "Таблица символов" не знал.
Очень познавательное видео!
Огромное спасибо!!!

Алексей    14.02.17 11:08

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

АНОНИМ    15.02.17 00:27

Если тебе интересно то могу предложить библиотеку для студии для дисплея от нокии 1616!
Я сам ее переделивал потому что она била написана для кодвижина, и добавил ей такие возможности как вивод прямоугольника, круга, ромба, прямой (горизонтальной, вертикальной, под углом), сделал возможность повернуть екран в любую сторону (я не писал все єто сам я брал куски кода с других библиотек и подстраивал их под єтот дисплей).
Очень класний дисплейчик можеш даже его интегрировать в свой генератор кода.
Главное дешевий и очень ходовой, используется во многих нокиях (Nokia 1616, 1661, 1662, 1800, 5030, 5131, 100, 101, 108, 112, 113, 130 Single SIM, C1-00, C1-01, C1-02, C1-03, C2-00, X1-01).
Управляется по SPI.

Алексей    15.02.17 07:49

Можно. У меня такой есть. Лежит и ждет своей очереди.

Руслан    15.02.17 20:37

А куда скинуть?

Руслан    15.02.17 20:59

Если сюда avrki@avrki.ru то уже скинул.
Будут вопроси задавайте!

Алексей    15.02.17 23:16

Хорошо, спасибо.

Руслан    24.02.17 22:38

Добрий вечер!
Просмотрел все ваши видео и понял что если б я их просмотрел раньне то может и не задавал би вам вопросов про вивод шеснадцатеричного числа на дисплей!
Так что извините за то что вам пришлось лишний раз разяснять мне то что уже било виложено в ваших видео!

Задавал вам вопроси на ютюбе но внятних ответов так и не услишал (не прочел :))! Так что задам тут!
1)Почему не дефайнят функции которие редко используются в библиотеках для економии места в флеш памяти микроконтроллера, и как ето сделать правильно самому (как задефайнить, как с ними потом работать и есть ли какие нибудь подводние камни)?
2)Когда будет видео про указатели?
3)Как обстоят дела с вайфай модулями о которих ви расказивали в 6-й части "Генератор Кода для AVR МК с библиотекой axlib"?

Алексей    25.02.17 09:02

Меня в понедельник прооперировали. В этом и вся загвоздка с задержками ответов. Так что пока на простые вопросы я отвечаю, а там где нужно видео снять... Пока увы.

Руслан    25.02.17 12:01

Ой! Ссорри! Не знал!
Желаю вам побистрее виздороветь и никогда больше не болеть!!!

Алексей    25.02.17 16:51

Про указатели готово.

Руслан    01.03.17 16:16

Спасибо!
Начал разбираться с USART-ом и получил вот такие грабли:
если в функции main функцией sizeof опрашиваю масив то все работает как надо

int main(void)
{
while(1)
{
d = sizeof(out_bukva);
}
}

а если вот так

void out (unsigned char *t)
{
d = sizeof(t);
}
то d всегда 2
масив у меня unsigned char out_tsifra [15] = "Pryiniav tsifru";
что я делаю не так и почему d всегда 2?
вчера пол дня убил разбираясь почему у меня в терминал компютера виводятся только 2 первие символа строки.
Если можете разясните пожалуйста.
Весь код прилагаю:



#define F_CPU 16000000UL
#include <avr/io.h>
#include <avr/interrupt.h>
#include "DEFINE.h"
#include "1616_S_SPI.c"

unsigned char peredacha_danyh, i, k, in;
unsigned char d = 0;
unsigned char out_tsifra [15] = "Pryiniav tsifru";
unsigned char out_bukva [15] = "Pryiniav bukvu ";
unsigned char out_symvol [15] = "Pryiniav symvol";
void out (unsigned char *t);

ISR(USART_RX_vect)
{
in = UDR0;
LCD_Char(30, 40, in, BLACK, 1);
peredacha_danyh = 1;
UCSR0B &= ~ (1<<RXCIE0);
UCSR0B |= (1<<UDRIE0);
}

ISR(USART_UDRE_vect)
{
asm("nop");
if (peredacha_danyh == 1)
{
switch (in)
{
case 0x30 ... 0x39: out(out_tsifra); break;
case 0x41 ... 0x5A: out(out_bukva); break;
case 0x61 ... 0x7A: out(out_bukva); break;
default: out(out_symvol);
}
}
}

void out (unsigned char *t)
{
d = sizeof(t);
if (k < 15)
{
UDR0 = t[k];
k++;
}
esle
{
k = 0;
peredacha_danyh = 0;
UCSR0B &= ~ (1<<UDRIE0);
UCSR0B |= (1<<RXCIE0);
}
}

void preset (void)
{
//////////////////LCD///////////////////////
LCD_DDR |= (1<<RESET)|(1<<CS)|(1<<SDATA)|(1<<CLK);
lcd_init_rgb();
SetOrientation(LCD_ORIENTATION_270);
fill_screen(YELLOW);
put_string(0, 50, "0k", BLACK, 1);
/////////////////USART//////////////////
DDRD |= (1<<PIND1);
PORTD |= (1<<PIND1);
// UCSR0A = 0x00;
UCSR0B |= (1<<RXCIE0)|(0<<TXCIE0)|(0<<UDRIE0)|(1<<RXEN0)|\
(1<<TXEN0)|(0<<UCSZ02)|(0<<RXB80)|(0<<TXB80);
UCSR0C |= (1<<UMSEL01)|(0<<UMSEL00)|(1<<UPM01)|(1<<UPM00)|\
(0<<USBS0)|(1<<UCSZ01)|(1<<UCSZ00)|(0<<UCPOL0);
UBRR0 = 103; //9600
asm ("sei");
}

int main(void)
{
preset();
while(1)
{
d = sizeof(out_bukva);
}
}


Алексей    01.03.17 18:06

-> что я делаю не так и почему d всегда 2?

Потому что нужно было внимательно смотреть кино про указатели. Если передовать функции sizeof() указатель, то для меги он будет всегда двубайтным, так как адрес больше 256. Вот он 2 и возвращает.

Руслан    01.03.17 21:41

Еще раз просмотрел внимательно видео:
10-я минута про размер самого указателя - етот момент я сначало не понял а потом еще подумал что во время исполнения функции указатель будет указивать на конкретний масив и функция sizeof возьмет данние уже самого масива а оказивается что не тут то било!
Признаю протупил!

Руслан    01.03.17 22:26

Пока писал вам пришла в голову еще одна мисль:



void out (unsigned char *t)
{
if (t[k] > 0x00)
{
UDR0 = t[k];
k++;
}
esle
{
k = 0;
peredacha_danyh = 0;
UCSR0B &= ~ (1<<UDRIE0);
UCSR0B |= (1<<RXCIE0);
}
}


но так тоже не получается, оно получается только когда масив такого типа:
unsigned char out_symvol [] = {'P', 'r', 'y', 'i', 'n', 'a', 'v', ' ', 's', 'y', 'm', 'v', 'o', 'l', 0x00};

а с таким масивом:
unsigned char out_symvol [15] = "Pryiniav symvol";
не получаєтся!

Алексей    01.03.17 23:27

Потому что последний байт в массиве должен быть 0х00. Это вне гласный закон конца строки.

Алексейbird    13.03.17 16:30

Привет, Алексей!
Вот код, уже вверху проскакивал он

lcd_gotoxy(0,1);
ds1820_rom_code(rom);
temperatura = ds1820_read_t(rom);
sprintf(str, "T %0.1f", (ADATA)(temperatura/10));


Но на дисплее почему-то не изменяется число после точки, т.е. температура всегда целая 28.0;29.0;30.0 и тд.
Также не могу понять, как изменить(точнее убрать) пустой символ между Т и +(в этой строке имею ввиду "T %0.1f"), если ставлю один пустой символ, то стирается первый символ температуры, а если оба, то + влезает в значение температуры, кароч и так и этак ерунда получается.
И ещё, можно сказать основной вопрос. Идея когда на одном проводе висит несколько датчиков температуры мне кажется малоприменимой на практике, потому что уникальный номер датчика до подключения не известен и соответственно до чтения ROMа не ясно где какой установлен. Можно конечно замутить меню со чтением ROMа всех датчик, а потом в меню их отсортировать, но это AVR, а не комп, тут ограниченная память, да и меню усложняется, хотя опять же неясен вопрос как понять где какой датчик находится. Поэтому я сейчас собираю устройство, где каждый датчик, а их там 4 штуки имеет отдельный канал. Вопрос, Алексей, твою библиотеку как-то можно приспособить под "многоканальный" 1-Wire? Спасибо!

Алексей    13.03.17 19:22

Попробуй написать так

sprintf(str, "T %0.1f", ((ADATA)temperatura/10));

Можно. Здесь в комментах где-то, кто-то уже делал. А вообще правильнее причитать РОМ код, а потом подрубить датчик. Это как с домофоном. Выбрал в меню запись РОМ кода ключа, прислонил ключ и готово. С датчиком та же песня. Подключил, считал РОМ, а теперь вешай куда хочешь.

Алексейbird    13.03.17 19:43

Алексей, ещё вопрос: а можно ли как-то обойтись без использования библиотеки libprintf_flt.a и той галки, которая для работы с плавающей запятой. Ведь код очень сильно увеличивается, а другие примеры, которые я встречал, не используют эту плавающую точку и норм работают с этими датчиками. Или это особенность твоей библиотеки?

Алексей    13.03.17 23:21

Выше этажом есть кино на эту тему, так как этот вопрос уже задавали. Вот адрес коммента 06.02.17 14:01

Алексейbird    14.03.17 21:09

Алексей, кино посмотрел, спасибо!
А вот по использование нескольких датчиков 18B20 в одном МК, но на разных линия я что-то не нашел, может не в этих комментах?
И еще насчет измерения температуры: датчик измеряет с шагом 0,5, это от разрешения зависит?

Алексей    14.03.17 21:31

Разрешение зависит от датчика. DS18B20 может измерять с точностью до 0.0625°C. Для этого его нужно перевести в 12 битный режим.

Алексейbird    14.03.17 21:40

Так 12-битный режим он по умолчанию идет, если при инициализации этот режим не менять, то он и преобразует каждые 750мс температуру как раз в 12-битном режиме. Судя по коду в ds1820.h можно изменять разрешение путём передачи на функцию "ds18b20_resol" соответствующей команды. Но если специально не использовать эту функцию, то вроде она и не применяется. Значит где-то в другом месте ограничивается разрешение 0,5 градуса, верно?

Алексей    15.03.17 00:11

Я не помню. Нужно смотреть. По моему при инициализации датчик настраивается на 9-ти битный режим.

Алексейbird    15.03.17 09:00

owire_init() нет ничего указывающего на изменение режима преобразования. Да и принудительно использовал ds18b20_resol(RESOL_12), тоже никакого эффекта.
Также Алексей подскажи, почему вот такой код


...
lcd_gotoxy(0,3);
lcd_str_out(*temp);
...


Массив temp берется из функции ds1820_read_t, которую я перенёс в основной код и переменные которой сделал глобальные. Так вот этот код делает предупреждение "passing argument 1 of 'lcd_str_out' makes pointer from integer without a cast" и соответственно ничего не выводит.
Спасибо!

Олег    26.03.17 23:24

Как одновременно подключить модуль SIM800L и организовать связь по rs485 с другим МК ?

Алексей    27.03.17 09:52

О раздвоении UART я писал здесь.

Олег    27.03.17 09:57

А программная реализация Uart для simm800 или rs485 будет работать ?

Алексей    27.03.17 10:04

Нет. В axlib все функции завязаны с аппаратным UART. Может со временем я ражу программный UART.

АНОНИМ    27.03.17 10:14

В случаи применения программного UART, как с надежностью связи, есть противопоказания для каких то устройств?

Алексей    27.03.17 10:35

Все зависит от приоритета таймера. А так какая разница в какой регистр класть данные, в программный или железный.

Олег    27.03.17 11:24

Понял, спасибо.

Игорь    01.04.17 11:31

Тут спрашивали:
Решил я проблему нескольких 1W шин добавив три строчки в 1W.h.
volatile uint8_t pin_w=0;
#define OWIRE_0 PORTB_OUT(pin_w)
#define OWIRE_1 PORTB_IN(pin_w)
При обращении к датчику меняю pin_w на нужный в порту.

StAlware    07.07.17 13:56

Усем привет. Недавно в качестве хобби начал осваивать AVR микроконтроллеры и их программиррвание. Дома стоит сиули седьмая и CodeVision ограниченная версия. С ограничениеми в CodeVision столкнклся уже на первых шагах в самых простых программах, но с большим объёмом данных. Да и писать на чистом асме как-то не шибко хотелось бы, хотя для развития и не помешает. Поэтому естественно возник вопрос по библиотекам, а именно при пользовании ими код будет разрастаться и програму не потянет ограниченный CodeVision. Поэтому захотелось поближе к WinAvr и gcc. Но вот, что я прочитал на kazus.ru: "Судя по опросу, который проводил более месяца назад, большинство программистов (более 50%) пользуются именно CodeVisionAVR. И возник вопрос: почему большинство библиотек написанны именно под WinAVR? Ведь он менее популярен, интерфейс хуже, и т.д.
И возникла идея: в этой теме делится библиотеками с описаниями именно под CodeVisionAVR." И вот по сему поводу вопрос: Зачем вы пишите библиотеки эти, если пишут, что их много, больше даже чем для CodeVision? Правда где их взять? Вот тоже вопрос. Ну пишут же, что они есть и их много!

StAlware    07.07.17 13:57

Опечатка в начале: студия седьмая и CodeVision

StAlware    07.07.17 17:34

И ещё такой вопрос. То, что у вас в начале страницы, в шапке так сказать, даденные ссылки на библиотеки axlib 1.1, и кодегенератор это самые последние и самые актуальные? Я прочитал часть комментов и там идёт переписка и вы постоянно модифицируете и усовершенствуете ваш код, поэтому такой вопрос, т.е. скачав по ссылке всегда скачаешь самую последнюю модификацию кода или как? Будет ли работать на седьмой студии? Она у меня уже стоит. Вы себе будете её устанавливать?

Алексей    07.07.17 22:45

Версия для скачивания самая последняя. С 7 студией не работает. Точнее генератор кода создает только под 6 студию. Под 7 не получается так как файл проекта имеет криптографический ключ с нестондартной функцией. Поэтому я не могу написать код для создания проекта под 7 студию. На данный момент разрабатывается своя студия для работы без программ от атмел.

StAlware    08.07.17 00:09

А что скажите по поводу вопроса, который я написал в 13:56?

StAlware    08.07.17 00:17

Повторюсь. Вот цитата:
Начало цитаты:
"Судя по опросу, который проводил более месяца назад, большинство программистов (более 50%) пользуются именно CodeVisionAVR. И возник вопрос: почему большинство библиотек написанны именно под WinAVR? Ведь он менее популярен, интерфейс хуже, и т.д.
И возникла идея: в этой теме делится библиотеками с описаниями именно под CodeVisionAVR."
Конец цитаты.
Я это прочитал на форуме kazus.ru.

Мой вопрос:
Зачем вы пишите библиотеки эти, если пишут, что их много, больше даже чем для CodeVision? Правда где их взять? Вот тоже вопрос. Ну пишут же, что они есть и их много!

Алексей    08.07.17 09:11

Я не знаю кто и что пишет, я писал библиотеку лично для себя любимого. Во первых так мне проще, если возникает ошибка, то я знаю где ее искать. Во авторых я ненавижу разбирался с чужим кодом, даже если он хорошо и понятно написан.

StAlware    08.07.17 09:12

Понял, спасибо.

Алексей    08.07.17 09:16

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

StAlware    08.07.17 10:13

Скажите, вот вы пишите библиотеки, знаете протоколы spi, i2c, 1-w, uart.., вы как их осваивали? Искали по крупицам информацию по ним в разных источниках, или же где-то есть полная информация по ним на русском языке? Не подскажите где можно взять для освоения.

Алексей    08.07.17 10:24

В интернете полно информации по всем протоколам. Достаточно написать в поисковике например, UART принцип работы на русском, и вылезет куча информации. Так же можно посмотреть у меня на канале в ютубе. Я там тот же uart разжевал во всех подробностях и даже написал программный. По остальным шинам я много писал на этом сайте.

АНОНИМ    08.07.17 11:57

Хорошо, обязательно посмотрю, не смотрел до этого потому как с планшета в основном в нете.

Олег    15.12.17 00:15

По моему функция ds3231_read_data пишет в пятый элемент массива...BYTE data[4] = {0};


while(i < 4) ?????
{
*str = ((temp[i] & 0x0F)+((temp[i] >> 4) * 10));
str++;
i++;


Алексей    15.12.17 23:23

Нет не пишет. При условии 4<4 это лож. Так что заполнение будет от 0 до 3.

Олег    16.12.17 22:33

Не пойму тогда почему BYTE temp[3] и стр++ перед while(i < 4) , у меня в соседний переменной мусор получается , пропадает если объявить data[5] или поменять в функции на while(i < 3) , при этом дата выводиться нормально , пробовал (i < 2) год пропадает , почему это может быть?

Андрей    21.01.18 00:36

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

Андрей    21.01.18 09:58

Я просто хочу научиться считывать с дисплея используя ножку R/W, а для этого нужно править библиотеку. подскажите где копать

Алексей    22.01.18 12:52

МК задает команды дисплею по 4-х битной шине. То есть старшие 4 разряда пишут данные и команды в дисплей. При чтении данных из дисплея нужно использовать те же пины. Для того чтобы функция понимала на какие пины и на каких портах нужно выводить данные в дисплей, используются макросы. Данные макросы определяя пины с портами, раскладывают байт команд или данных. Для чтения данных из МК, нужно писать дополнительные функции для перевода бит в режим чтения, а затем записывать их в байт.

Андрей    23.01.18 12:50

большое спасибо за ответ. Очень помогло, вот только не пойму странное макроопределение
#define E_SET() (PORT_E |= (1 << E))
как функция, но не функция.
короче буду разбираться

Алексей    23.01.18 14:23

Выставляет на порту Е единицу в разряде Е дисплея.

Alex    18.02.18 21:57

А не появилось у вас библиотеки для SSD1106, вроде как собирались сделать

Алексей    19.02.18 15:20

Появилась, но она в сыром виде. Обкатать нужно.

Андрей    04.03.18 17:48

Доброе время суток! Алексей, в Вашем генераторе нет поддержки Atmega64/128 но как я понимаю самим же библиотекам без разницы для какого камня их будут подключать в ручную без генератора? Меня интересует USART для Atmega64.

Алексей    04.03.18 20:56

Да, вы правы. Разницы никакой.

Виктор    12.03.18 05:59

а можно SSD1106 взять на обкатку?

Алексей    12.03.18 08:25

Что знчит "на обкатку"?

Антон    25.04.18 19:22

Здравствуйте. Огромное спасибо за библиотеку. Возник вопрос по библиотеке для DS3231. Подскажите пожалуйста как можно настроить режим работы будильника, он у меня сбился и теперь будильник срабатывает каждый час(то бишь ориентируясь только на выставленные минуты...). почитал даташит нашел пункт касающийся данного вопроса, нужно записать опредленные биты в регистры, каким образом это можно сделать?

даташит 12 страница: https://datasheets.maximintegrated.com/en/ds/DS3231.pdf

Антон    25.04.18 21:10

UPD: разобрался)))
но странно что вы не реализовали функцию выбора режима работы будильников в либе.

Алексей    26.04.18 00:01

Ну, не углядел))) Я не вездесущ.

Аракел    01.05.18 21:19

На какой скорости I2C работает? Всю библиотеку перерыл не найду даже где инициализируются нужные регистры или там все по умолчанию.

Алексей    02.05.18 08:51

По умолчанию.

Аракел    02.05.18 09:26

Алексей, ещё подскажите, не могу понять, I2C интерфейс программно выполнен или аппаратный используется?

Алексей    03.05.18 08:04

Программно.

Александр    06.09.18 10:16

Здравствуйте! Прошу помощи! Вывод данных на st7735 18b20! Пример кода если можно! Спасибо!!!

Алексей    06.09.18 19:51




#include <avr/io.h>
#include <stdio.h>

#include "main_init.h"
#include "axlib/1w.h"
#include "axlib/ds1820.h"
#include "axlib/spi.h"
#include "axlib/st7735.h"

// Здесь должны находиться ваши подключаемые файлы


// Здесь должны находиться ваши глобальные переменные


int main(void)
{
// Здесь должны находиться ваши локальные переменные
BYTE str[20] = {0};
BYTE rom[8] = {0};
WORD t = 0;
// Инициализация 1wire
owire_init();

// Инициализация TFT ST7735
lcd_st7735_init();

// Залить экран черным
lcd_st7735_screen(RGB16(0x000000));

// Получение ром кода датчика
ds1820_rom_code(rom);

while(1)
{
// Чтение температуры
t = ds1820_read_t(rom);

// Подготовка к выводу на дисплей
sprintf(str, "T = %d", t);

// Вывод на дисплей
lcd_st7735_putstr_xy(0, 0, str, RGB16(0xFFFFFF), RGB16(0x000000));

}
}


Александр    07.09.18 01:42

Спасибо!!!!
Да........
Я в шоке!
Я долго тупил!
Спасибо за помощь!
Я год назат собирал тестер на Atmega644p и st7735 (Karl-Hainz) изготовил дома двух стор.плату с переходными отверстиями (полгода экспериментов с химией) плата получилась. И 4 месяцев запуска. Две Atmega644p подряд были кривые на одной jtagen не выключался на другой одна нага не дрыгает прям та которая по схеме на LSD. Спасибо Карлу очень помог.

А сам не как не могу туплю!
Спасибо.

Александр    07.09.18 02:06

Пока т=-32768

Александр    07.09.18 02:11

Как часовой кварц 32768

Александр    07.09.18 19:11

Алексей!
Прошу помощи!
Ds18b20 st7735 atmega8
Т=℅d результат Т=-32768
Т=℅0.1f результат Т=?
1wire порт-B пин-0

Алексей    07.09.18 19:30

T=? Потому что в студии вывод числа с плавающей точкой выключен. Нужно подключить библиотеку.

Александр    07.09.18 20:22

Где можно взять такую библиотеку

Алексей    07.09.18 20:45

Она в студии есть.

Александр    07.09.18 21:58

Printf_flt
Skanf_flt

Эти настройки

Алексей    08.09.18 00:50

Нет. Вот серия кино. https://youtu.be/Hu8-XFugzjk

Александр    08.09.18 08:00

Спасибо!!!!

Александр    09.09.18 00:51

Алексей!
Вопросик?
St7735
Пины для CS A0 RES можно менять.
А для SCK SDA только SCK MOSI?

Алексей    09.09.18 07:30

Да. SPI аппаратный.

В    21.09.18 16:11

Алексей! Спасибо Вам большое за библиотеку и за ваш труд! Воспользовался ею для работы с st7735 в CodeVision, всё работает.

Владимир    21.09.18 16:22

Самое главное - доработал функцию lcd_st7735_putchar для вывода букв, увеличенных по ширине и/или высоте относительно основного фонта. Параметры kx и ky - коэффициенты увеличения размера шрифта по оси x и y соответственно. Таким образом можно выводить шрифты различного размера (заголовки например)




void lcd_st7735_putchar(BYTE x, BYTE y, BYTE kx, BYTE ky, BYTE chr, UWORD charColor, UWORD bkgColor)
{
BYTE i;
BYTE j;
BYTE h;
UWORD color,ii;
BYTE k,n,m;
BYTE chl;
BYTE chl_mem[3];

if((kx==0)||(ky==0)){return;}

CS_ON;

lcd_st7735_at(y, x, y+((13*ky)-1), x+(8*kx));
lcd_st7735_send_cmd(0x2C);


for (i=0;i<7;i++)
{
for (k=2;k>0;k--)
{
//(k=2-это нижн. половина символа, к=1-верхняя)
chl = pgm_read_byte(&(NewBFontLAT[((chr-0x20)*14 + i + 7*(k-1)) ]));
chl_mem[k]=chl;

chl=chl<<2*(k-1); // если это нижняя половина символа, то сдвигаем байт на 2 разряда влево, чтобы 5-й разряд стал самым старшим (7-мым)!
if (k==2) h=6; esle h=7; // у нижней половины выведем 6 точек, у верхней - 7 точек

for (j=0; j<h; j++)
{
if (chl & 0x80) color=charColor; esle color=bkgColor;
chl = chl<<1;
for (m=0; m<ky; m++)
{
lcd_st7735_send_data((BYTE)((color & 0xFF00)>>8));
lcd_st7735_send_data((BYTE) (color & 0x00FF));
}
}
}

//несколько раз повторяем вывод, если kx>1
if(kx>1)
{
for (n=0; n<(kx-1); n++)
{
for (k=2; k>0; k--)
{
chl=chl_mem[k];

chl=chl<<2*(k-1);
if (k==2) h=6; esle h=7;

for (j=0; j<h; j++)
{
if (chl & 0x80) color=charColor; esle color=bkgColor;
chl = chl<<1;
for(m=0; m<ky; m++)
{
lcd_st7735_send_data((BYTE)((color & 0xFF00)>>8));
lcd_st7735_send_data((BYTE) (color & 0x00FF));
}
}
}
}
}

}


// рисуем справа от символа пустую вертикальную линию (или несколько) для бокового интервала
for (ii=0; ii<(13*kx*ky); ii++)
{
lcd_st7735_send_data((BYTE)((bkgColor & 0xFF00)>>8));
lcd_st7735_send_data((BYTE) (bkgColor & 0x00FF));
}

CS_OFF;
}



Александр    27.10.18 19:17

Доброго вечера.

Прошу помощи (как правильно вывести графику измерения напряжении)

lcd_st7735_put_pix(3+(Voltage*10),3 + x++,RED); (что то не так )

спасибо!!!

#define F_CPU 16000000UL
#include <avr/io.h>
#include <util/delay.h>
#include <string.h>
#include "main_init.h"
#include "axlib/st7735.h"
#include <stdio.h>

#define RED 0xf800
#define GREEN 0x07e0
#define BLUE 0x001f
#define WHITE 0xffff
#define BLACK 0x0000
#define YELLOW 0xFFE0
#define GRAY0 0xEF7D
#define GRAY1 0x8410
#define GRAY2 0x4208

int x = 0;
int i = 0;

ISR (ADC_vect) //Прерывание окончания преобразования АЦП
{
float Voltage = ADCW*0.0048828;//Результат
char buffer [10];// Строка для отправки LCD
sprintf(buffer,"U=%.2f V",Voltage);
//_delay_ms(2);// Пауза для ожидания завершения
lcd_st7735_putstr_xy(3, 6, buffer, RGB16(0xFFFFFF),RGB16(0x000000));

lcd_st7735_put_pix(3+(Voltage*10),3 + x++,RED);

//_delay_ms(100); //Пауза
ADCSRA |=(1<<ADSC); //Запускаем следующее преобразование

if (x > 115) x = 0;
else if (x >= 114)

{

lcd_st7735_full_rect(0,0, 116, 60,BLACK);

}

}

void Init_ADC(void)
{

// Настройка АЦП
ADMUX |=(1<<REFS0);//AVCC (+5) — источник опорного напряжения
ADCSRA |=(1<<ADEN)|(1<<ADIE)|(1<<ADPS0)|(1<<ADPS1)|(1<<ADPS2);// Включаем АЦП, разрешаем прерывание, настраиваем тактирование
sei ();// Глобально разрешаем прерывания


}


int main(void)
{

lcd_st7735_init();
lcd_st7735_screen(RGB16(0x000000));
Init_ADC();


ADCSRA |=(1<<ADSC);// Т.к. мы работаем в режиме однократного преобразования — запускаем цикл преобразования.



}


while(1)
{

}
}



Ещё вопросик данную функцию можно вставить в библиотеку #include "axlib/st7735.h"

void lcd_st7735_putchar(BYTE x, BYTE y, BYTE kx, BYTE ky, BYTE chr, UWORD charColor, UWORD bkgColor)

Александр    28.10.18 00:47

Перенёс вывода информации в момент закрашивание и скорость стала лучше


lcd_st7735_put_pix(3+(Voltage*10),3 + x++,YELLOW);

if (x > 160) x = 0;
else if (x >= 157)

{

lcd_st7735_full_rect(0,0, 160, 60,BLACK);
lcd_st7735_putstr_xy(3, 6, buffer, RGB16(0xFFFFFF),RGB16(0x000000));

}

Алексей    29.10.18 19:52

Ну переменная Voltage же вещественная. Voltage*10 будет та же вещественная но на порядок больше))) Нужно обязательно приводить к одному типу. (unsigned int)Voltage*10. Вот теперь это будет целочисленное и без знака.

Александр    29.10.18 22:28

Спасибо за помощь АЛЕКСЕЙ!!!
Спасибо за библиотеки!
но так график не эластичный а грубый.
Умножаю чтоб увеличить!
без unsigned int он красивый/
Проблема в том что то я не так делаю или не хватает скорости когда 0v 5v отсутствуют боковые линии есть 0 ____ и 5-----.
Когда плавный переход всё хорошо.


И ещё вопросик как правильно будет обновлять графику при заполнении его чтоб уменьшить мерцание?




if (x > 160) x = 0;
else if (x >= 157)

{
lcd_st7735_full_rect(3,3, 154, 55,BLACK);
for (int i=3; i<160; i+=30) {

lcd_st7735_put_pix(5,i,GRAY0 );
lcd_st7735_put_pix(15,i,GRAY0 );
lcd_st7735_put_pix(25,i,GRAY0 );
lcd_st7735_put_pix(35,i,GRAY0 );
lcd_st7735_put_pix(45,i,GRAY0 );
lcd_st7735_put_pix(55,i,GRAY0 );
}

}

Так симпатично но мерцает?

Разные шрифты возможно применить?


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

#include "main_init.h"
#include "axlib/st7735.h"

#define RED 0xf800
#define GREEN 0x07e0
#define BLUE 0x001f
#define WHITE 0xffff
#define BLACK 0x0000
#define YELLOW 0xFFE0
#define GRAY0 0xEF7D
#define GRAY1 0x8410
#define GRAY2 0x4208

int y;
int x;


char string[10];
int main(void)
{

ADMUX |=(1<<REFS0);//AVCC (+5) — источник опорного напряжения
ADCSRA |=(0<< ADATE)//Автоматический запуск преобразования.
|(0<<ADIF)//Флаг прерывания.
|(1<<ADEN)|(1<<ADIE)// Включаем АЦП, разрешаем прерывание.
|(0<<ADPS0)|(0<<ADPS1)|(1<<ADPS2);// Настраиваем тактирование

lcd_st7735_init();
lcd_st7735_screen(RGB16(0x000000));

while (1)
{

ADCSRA |=(1<<ADSC); //Запускаем следующее преобразование

float Voltage = ADCW*0.0048828; // Переводим в вольты

sprintf(string, "U= %1.2f V",Voltage); // форматируе

y+= 1;
x=(unsigned int)Voltage*13;

lcd_st7735_put_pix(3+x,3 + y,GREEN);



if (y > 160) y = 0;
else if (y >= 157)

{




lcd_st7735_putstr_xy(3, 6, string, WHITE,BLACK);

lcd_st7735_putstr_xy(0,0,"0 . . . . . . .",GRAY2,BLACK);
lcd_st7735_putstr_xy(0,1,"1 . . . . . . .",GRAY2,BLACK);
lcd_st7735_putstr_xy(0,2,"2 . . . . . . .",GRAY2,BLACK);
lcd_st7735_putstr_xy(0,3,"3 . . . . . . .",GRAY2,BLACK);
lcd_st7735_putstr_xy(0,4,"4 . . . . . . .",GRAY2,BLACK);
lcd_st7735_putstr_xy(0,5,"5 . . . . . . .",GRAY2,BLACK);

}

Александр    12.11.18 02:23

Здравствуйте!
Прошу помощи!
Как возможно реализовать сдвиг видимой области экрана (ST-7735) для реализации графики чтобы не использовать закраску при заполнении?
Если это не сложно !!!

Алексей    12.11.18 21:23

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

Александр    13.11.18 01:05

Алексей если возможно и не сложно пример (пожалуйста)!

Александр    13.11.18 22:03

Алексей!!!
ATMEGA328P на 16mhz ST7735 работает но если установить кварц на 20mhz ST7735 не запускается (программа работает) в чем может проблема?

Алексей    14.11.18 08:31

Ну наверное потому что максимально возможно устанавливать кварц на 16МГц. Даташит страница 51.

Александр    14.11.18 20:00

Извини Алексей!
что то я совсем.....
Здесь 0-20Mhz

http://files.amperka.ru/datasheets/ATmega328.pdf

• Operating Voltage:
– 1.8 - 5.5V for ATmega48PA/88PA/168PA/328P
• Temperature Range:
– -40°C to 85°C
• Speed Grade:
– 0 - 20 MHz @ 1.8 - 5.5V


а здесь максимум 16 Mhz

http://ww1.microchip.com/downloads/en/DeviceDoc/Atmel-7810-Automotive-Microcontrollers-ATmega328P_Datasheet.pdf

Алексей    14.11.18 23:14

На атмере курнули чего-то. Даже в блоксхеме ядра тактирование до 16МГц

Александр    21.11.18 00:36

Алексей здравствуйте!!!!!
Опять Я!!!
Встретил в просторах интернета!
ATMega328p разогнанный до 27МГц!!!
http://srukami.inf.ua/pultoscop_v2.html

Алексей    21.11.18 09:45

Возможно, но за стабильность работы никто не отвечает.

Павел    29.11.18 18:45

Здравствуйте Алексей. Пытаюсь получить полный 16битный код от датчика ds18b20 но получаю только младший бит, старший равен 0х00, надеюсь просто лыжи не едут!? или что-то не так делаю?

Павел    29.11.18 18:48

i=(ds1820_all()/10);
i1=(i>>8);
i2=i;
usart_char_out(i1);
usart_char_out(i2);
_delay_ms(500);

Павел    29.11.18 18:51

uint16_t i=0;
uint8_t i1=0, i2=0;

Павел    29.11.18 18:53

получаю младший БАЙТ.

Алексей    30.11.18 00:38

Завтра посмотрю. Найдем потерянные байты.

Алексей    30.11.18 16:42

Я так полагаю нужен тип датчика? Если да, то нужно прочитать его ROM код. Для этого есть функция BYTE ds1820_rom_code(BYTE *str); В качестве аргумента она принимает указатель на 8-и байтный массив. После вызова данной функции в массиве будет лежать ROM код датчика. В младшем байте будет лежать тип датчика. Для DS18B20 это 0x28.

Павел    01.12.18 09:43

Увы нет. Мне нужно в "uint16_t i=0;" положить два ПОЛНОЦЕННЫХ байта возвращаемой датчиком ds18b20 температуры, для дальнейшего анализа и воздействия на внешние элементы схемы.

Алексей    01.12.18 22:25

Вот теперь я понял. К сожалению функции получения всего дампа памяти из датчика нет. Но если очень нужно, то ее можно дописать.

Павел    02.12.18 15:31

Да не не парьтесь, я его уже получил немного другим путем. Просто хотел полностью на вашу библиотеку опереться, но моим путем зато более познавательно! И спасибо за хорошую рабочую библиотеку!

Pavel    11.12.18 19:12

Здравствуйте, Алексей.
Огромное спасибо за библиотеку. Встретил Ваш сайт, очень выручает.
Сейчас разбираюсь с часами DS1307, использовал Вашу библиотеку и почти все заработало. Честно скажу, не читал документацию на эти часы, по этому не могу точно понять где что должно происходить.
Использую готовый модуль с DS1307 и 24c32 на плате, так что сам не паял.
Дело вот в чем, часы пошли после установки даты и времени, прочитать удается успешно дату, а вот со временем проблема, часы возвращаются не корректно. Думал модуль неисправен, но запуск в Proteus показал тот же результат.
Пошаговая отладка в Proteus показала что время считывается нормально, но когда читается дата, то время искажается. Разбираясь дальше пришел к этой функции


void ds1307_read_data(BYTE *str)
{
BYTE temp[3];
UBYTE i = 0;

i2c_start();
i2c_send_byte(DS1307_ADD_W);
i2c_send_byte(DS1307_DAY);
i2c_restart();
i2c_send_byte(DS1307_ADD_R);
*str = i2c_read_byte(ACK);
temp[0] = i2c_read_byte(ACK);
temp[1] = i2c_read_byte(ACK);
temp[2] = i2c_read_byte(NACK);
i2c_stop();

str++;
while(i < 4)
{
*str = ((temp[i] & 0x0F)+((temp[i] >> 4) * 10));
str++;
i++;
}
}


Выделил вместо 4 байт для date, 8 байт и увидел что при чтении даты занято 5 байт, то есть выходит за пределы и "портит" следующий байт, а это уже time, вот час и искажается.
Не очень понимаю происходящее в этой функции, по этому просто выделил 5 байт и проблему решил, время читается успешно, но все же нужно тут что то поправить.
Или может это у меня где то сбой.

Алексей    11.12.18 21:32

Мне уже жаловались на часы именно с этим косяком. На выходных просмотрю все подробно. Нужно исправить.

Алексейbird    05.01.19 18:46

Алексей, добрый день! Подскажи, в куске кода (ADATA)(temperatura/10), что есть ADATA? Это из коммента от 13.03.17, кстати видео в комменте 06.02.17 почему то недоступно((

Алексей    05.01.19 22:59

ADATA это float.
Видео были на яндекс диске или сервере, и там и там удалены(

Алексейbird    05.01.19 23:25

Алексей, а можете подсказать как быть, если я хочу сэкономить флеш, путём неиспользования преобразования float, т.е. мне достаточно показаний температуры с точностью до единиц, после запятой цифры мне не нужны. Хотел видео посмотреть, но его нет(( надо было его сразу на ютуб залить...

Алексейbird    05.01.19 23:28

А откуда этот ADATA берётся, в коде не нашёл, в гугле не гуглится?))

Алексей    06.01.19 00:21

"А откуда этот ADATA берётся"
В файле main_init.h
#define ADATA float
Функция возвращает температуру умноженную на 10, так что просто делим на 10 и кладем в переменную BYTE.

Евгений    26.03.19 14:22

Интересные библиотеки, но зачем было портить все это хозяйство библиотекой delay.h
Она же запрещает прерывания, получается что ничего более-менее серьезного на этих либах не сделать, почему нельзя было использовать задержки в функциях по прерыванию таймера?

Алексей    26.03.19 21:38

По хорошему там есть еще некоторые косяки. Поэтому в планах многое переделать. Но на это нет времени.

Aleksei_bird    28.04.19 12:48

Алексей, я так понимаю это нормально, что вот эта конструкция:
temp = 0;
while(!temp)
{
temp = mhbus_read(add, 50); // Проверка на наличия полученного пакета
}
дико тормозит весь код. Это как-то можно исправить?

Алексей    28.04.19 17:20

Скинь проект мне на почту. Я посмотрю.

Aleksei_bird    30.04.19 18:37

Алексей, я скинул на почту, получил?

Алексей    01.05.19 08:59

Да, да я видел. Я обязательно посмотрю в праздники.

Aleksei_bird    05.06.19 21:57

Алексей, доброго дня! Есть новости по библиотеке?

Алексей    06.06.19 11:14

Пока нет. Работаю до часу ночи. Домой прихожу только спать.




Чтобы вставить ссылку используйте форму вида[url]http://www.адрес.ru[/url][text]текст ссылки[/text]
Чтобы вставить код используйте форму вида[code]код[/code]

Имя:   





  







Рейтинг@Mail.ru Яндекс.Метрика