#define F_CPU 16000000UL //Частота в герцах(16МГц) #include <avr/io.h> //Библиотека для упрощённой работы с вводами/выводами (_BV, и др.) #include <util/delay.h> //Библиотека с функциями задержек #include <stdio.h> //Standart Input Output Library (Библиотека Стандартного Ввода Вывода, sprintf, и др...) #include <stdbool.h> //Библиотека с битовой переменной типа bool(1/0) //---------------------------------------- #define e1 PORTB|=_BV(PB5) // установка линии E в 1 #define e0 PORTB&=~_BV(PB5) // установка линии E в 0 #define a1 PORTB|=_BV(PB4) // установка линии A в 1 (данные) #define a0 PORTB&=~_BV(PB4) // установка линии A в 0 (команда) //---------------------------------------- //Пример функции с описанием int simp(int num, char c, unsigned char uc, bool logic) /* int - тип значенечиния возвращаемого функцией (после оканчание её работы) simp - имя функции (int num, char c, unsigned char uc, bool log) - аргументы передоваемые в функцию int num - аргумент типа int(сокр от integer(целочисленный) в avr может содержать цифры -32768 до +32767) и занимает 2 байта с именем num внутри функции виден как переменная типа int по имени num char c - аргумент(переменная) типа char(содержит коды символов в диапазоне -128 до +127 и занимает 1 байт) и именем с unsigned char uc (unsigned (беззнаковая) переменная типа char (содержит от 0 до +255) также 1 байт) bool logic битавай переменная может содержать 0 либо 1 */ {//Начало тела функции /*что-то делаем*/ return num-logic; /*return значение; значение возврощаемое при выходе из функции можно получит след обр int var = simp(3, 'd', 34, 1); var будет содержать возворщённое значение в данном случае 2 */ }//конец тела функции unsigned int voltage_ADC ;//переменная результата напряжения ISR (ADC_vect)//прерывание по завершению преобразования АЦП { voltage_ADC = ADCW;//считываем значение АЦ преобразования ADCSR |= (1<<ADSC);//запускаем очередное преобразование } //Объявление прототипов функций для вызова функции из другой функции // нужно что бы функция вызываемая в новой была либо выше, либо обьявлена тут void LCD_ini(); void ADC_ini(); void setpos(unsigned char, unsigned char); void str_lcd (char str1[]); void sendhalfbyte(unsigned char); void sendbyte(unsigned char, unsigned char); void clearlcd(); void port_init(); //---------------------------------------- void sendhalfbyte(unsigned char c) //Передача 4 бит { e1; //включаем линию Е PORTC=0b00000000; //стираем информацию на входах DB4-DB7 _delay_us(250); PORTC|=c; //Передаём данные из переменной c _delay_us(50); e0; //выключаем линию Е _delay_us(250); PORTC=0x00; //16 запись, эквивалентно 0b00000000 в двоичном виде } //---------------------------------------- void sendbyte(unsigned char c, unsigned char mode) //Передача полных 8 бит { if (mode==0) a0;//Если mode = 1 установка режима команд(A=0) else a1;//в противно случае установка режима передачи данных(A=1) unsigned char hc=0;//объявление временной переменной для старших 4 бит hc=c>>4; //Отделение 4 старших бит из переменной с, в переменную hc sendhalfbyte(hc);//Отправка 4 старших бит sendhalfbyte(c);//Отправка оставшихся 4 младших бит } //---------------------------------------- void setpos(unsigned char x, unsigned char y)//Функция установки позиции курсора { char adress;//Временная переменная адреса /************************************************************************/ /*0b1ХХХХХХХ Установка адреса в память дисплея для последующей записи символов, где ХХХХХХХ адрес. 0b00000000 (адрес 0 символа, 0 строки на дисплее) 0b01000000 (адрес 0 символа, 1 строки на дисплее) */ /************************************************************************/ adress=(0x40*y+x)|0b10000000; //0x40(0b01000000) смещение второй строки //установка курсора в позицию // 0x40 *y+ x |0b10000000=adress //x=0 символ y=0 строки (0x01000000*0+0b00000000)|0b10000000=0b10000000 //x=0 символ y=1 строки (0x01000000*1+0b00000000)|0b10000000=0b11000000 //x=1 символ y=0 строки (0x01000000*0+0b00000001)|0b10000000=0b10000001 //x=1 символ y=1 строки (0x01000000*1+0b00000001)|0b10000000=0b11000001 //x=5 символ y=0 строки (0x01000000*0+0b00000101)|0b10000000=0b10000101 //x=5 символ y=1 строки (0x01000000*1+0b00000101)|0b10000000=0b11000101 sendbyte(adress, 0); //Отправка команды _delay_us(50); } //---------------------------------------- void LCD_ini(void) { _delay_ms(20); //Ждем 20 мс (стр 5) //Начальная инициализация дисплея для работы в 4х битном режими sendhalfbyte(0b00000011); _delay_us(40); sendhalfbyte(0b00000011); _delay_us(40); sendhalfbyte(0b00000011); _delay_us(40); sendhalfbyte(0b00000010); _delay_us(40); //Отправка команд установки параметров дисплея sendbyte(0b00101000, 0); //0b001(DL)10(P)0, 4 бит-режим DL=0(8бит-зежим DL=1), P - Таблица знакогенератора _delay_ms(1); sendbyte(0b00001100, 0); //включаем изображение на дисплее (D=1), курсоры никакие не включаем (C=0, B=0) _delay_ms(1); sendbyte(0b00000110, 0); //курсор (хоть он у нас и невидимый) будет двигаться влево _delay_ms(1); } //---------------------------------------- void clearlcd() { sendbyte(0b00000001, 0);//Отправка команды очистки дисплея _delay_us(1500); } //---------------------------------------- void str_lcd (char str1[]) //Функция вывода строки { int n; //Временная переменная счётчика for(n=0;str1[n]!='\0';n++) {//Посимвольный перебор строки до символа '\0'(Конец строки) sendbyte(str1[n],1);//Вывод 1 символа } } //---------------------------------------- void port_ini(void)//Инициализация портов { DDRB|=_BV(PB5)|_BV(PB4); //Установка PB4 - E, PB5 - A, в режим вывода DDRB=0b00110000; DDRC=0b00001111;//Установка PC0-PC3(DB4-DB7) в режим вывода DDRD&=~_BV(PD2); DDRD&=~_BV(PD3); //Установка PD3-PD2 в режим ввода PORTC=0x00;//Установка PC(0-7) в лог 0(GND) PORTB=0x00;//Установка PB(0-7) в лог 0(GND) PORTD|=_BV(PD2)|_BV(PD3); //Включение внутренних подтягивующих PD2-PD3 (к +пит) резисторов //DDRD|=_BV(PD2)|_BV(PD3); //Установка PD3-PD2 в режим ввода } //---------------------------------------- void ADC_ini() { // 7 6 5 4 3 2 1 0 //ADMUX = REFS1 REFS0 ADLAR – MUX3 MUX2 MUX1 MUX0 ADMUX |= (1<<REFS0);//в качестве опорного - напряжение питания, результат выравнивается вправо, 0-й канал АЦП (PC0) // 7 6 5 4 3 2 1 0 //ADCSRA = ADEN ADSC ADFR ADIF ADIE ADPS2 ADPS1 ADPS0 ADCSRA |= (1<<ADEN) | (1<<ADSC) | (1<<ADIE) | (1<<ADPS1) | (1<<ADPS0);//разрешаем преобразование, запускаем его, разрешаем прерывание от АЦП //тактовую частоту делим на 8 - получаем частоту преобразования 125 кГц } //---------------------------------------- int main(void) { port_ini(); //Инициализируем порты LCD_ini(); //Инициализируем дисплей ADC_ini(); //Инициализируем АЦП sei(); //разрешение прерываний clearlcd(); //Очистка индикатора setpos(0,0); //Установка позиции курсора на 0 строку 0 символ char tmp[18]; //Временный буфер для строки (количество символов + символ конца строки + 1 на всякий случай)) ) int i = 2017; //Пример переменной (В данном случае год) //clearlcd(); // sendbyte(0b00101010, 0); //смена таблицы символов из 0 в 1 sprintf(tmp, "#Mac%cepa %d", 0xbf, i); //Заполнение буферной переменной str_lcd(tmp); //Вывод данных на дисплей setpos(0,1); //Установка курсора на 1 строку 0 символ sprintf(tmp, "Bc%c%ca%c xpe%c%c", 0xC7, 0xBA, 0xC7, 0xBD, 0xC4); //Заполнение буферной переменной str_lcd(tmp); //Вывод данных на дисплей _delay_ms(3000); clearlcd(); bool d_upd=0; //Переменная для флага очистки дисплея while(1) { if(d_upd==1) //В случае присутствия флага очистка дисплея { clearlcd(); //Очистка дисплея d_upd=0; //Сброс флага очистки sprintf(tmp, "ADC0=%d",voltage_ADC); str_lcd(tmp); //Вывод данных на дисплей } if(!(_BV(PD2)& PIND)) //Если на входе PD2 уст лог 0 (Кнопка Menu нажата) { setpos(0,1); //Установка курсора на 1 строку 0 символ str_lcd("MENU BUT PRESSED"); //Вывод данных на дисплей d_upd=1; //Установка флага очистки while(!(_BV(PD2)& PIND)) { //Ожидания отпуска кнопки _delay_ms(500); //Задержка 0.5 сек для компенсации дребезга } } else if(!(_BV(PD3)& PIND)) //Если на входе PD3 уст лог 0 (Кнопка OK нажата) { setpos(0,1); //Установка курсора на 1 строку 0 символ str_lcd("OK BUT PRESSED "); //Вывод данных на дисплей d_upd=1;; //Установка флага очистки while(!(_BV(PD3)& PIND)) { //Ожидания отпуска кнопки _delay_ms(500); //Задержка 0.5 сек для компенсации дребезга } } } }