MENU
Главная » Статьи » УСТРОЙСТВА НА МК

Вольтамперметр на LCD HD44780 Attiny13

Как известно ЖК дисплей на базе контроллера HD44780 требует для управления минимум 6 линий ввода/вывода микроконтроллера, поэтому подключить его к микроконтроллеру с малым числом портов, например Attiny13, в стандартном 8/4-битном режиме невозможно.

В этой статье мы рассмотрим технику управления ЖК дисплеем с использованием всего лишь трех линий ввода/вывода микроконтроллера. Команды управления и данные будут пересылаться последовательно в сдвиговый регистр 74HC595(8-разрядный сдвиговый регистр с защелкой на выходе), а параллельные выходные данные с регистра поступают на LCD.

Символьные ЖК дисплеи на базе контроллера HD44780 требуют 14 выводов для управления: 8 линий данных (D0…D7), 3 линии управления (RS, E, R/W), 3 линии питания (Vdd, Vss, Vo). Кроме того многие модели оснащены подсветкой.

К параллельным выходным линиям регистра сдвига подключен ЖК индикатор: выводы данных D4-D7 и выводы E и RS (4-битный режим работы). Такое решение потребует от микроконтроллера лишь трех линий ввода/вывода:

- SH_CP для передачи тактового сигнала
- DS для передачи данных
- ST_CP для защелкивания данных регистра.

Так как используется 4-битный режим работы, любые восемь бит (команда или данные) передаются в два этапа: сначала старший полубайт, затем передается младший полубайт. Стоит отметить также, что вывод управления индикатора R/W (чтение/запись) подключается к общему проводнику, вследствие чего чтение данных или состояния ЖК модуля при таком подключении невозможно.

Практическим примером такого решения является двухканальный вольтметр (0 - 25V) на микроконтроллере Attiny13  с выводом данных на ЖК дисплей. При подключении дисплея через регистр у контроллера остается как раз две свободных линии, воспользуемся этим и подключим к ним два канала АЦП. Микроконтроллер работает от внутреннего тактового генератора частотой 9,6MHz. Этот вольтметр не является образцовым, но обладает достаточно хорошей точностью измерения напряжения. Схема вольтметра показана на рисунке ниже:

В управляющей программе используются две функции для общения микроконтроллера и дисплея:

- функия registr(unsigned char data, unsigned char WriteOrErase) для передачи данных регистру 74HC595, где data - данные,  в зависимости от состояния переменной WriteOrErase(0 или 1) можно устанавливать отдельный бит передаваемых данных(не трогая другие) в лог. 0 или лог. 1 .
- функция write_to_lcd(char p, unsigned char rs) для передачи данных или команд в ЖК дисплей, где p - данные, в зависимости от состояния переменной rs(0 или 1) передаем команду или передаем данные.

Чтение АЦП производится с помощью функции readADC(unsigned char ch), переменная ch определяет номер используемого канала АЦП. В бесконечном цикле уже преобразованное значение АЦП раскладываем на целое значение и значение после запятой. Полный текст программы показан ниже:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
// Подключение LCD HD44780 к AVR через регистр сдвига
 
#include <avr/io.h>
#include <util/delay.h>
 
// Команды для управления портами LCD
/* RS */
#define RS1 registr(0x01, 1)
#define RS0 registr(0x01, 0)
 
/* E */
#define E1 registr(0x02, 1)
#define E0 registr(0x02, 0)
 
/* D4 */
#define D41 registr(0x04, 1)
#define D40 registr(0x04, 0)
 
/* D5 */
#define D51 registr(0x08, 1)
#define D50 registr(0x08, 0)
 
/* D6 */
#define D61 registr(0x10, 1)
#define D60 registr(0x10, 0)
 
/* D7 */
#define D71 registr(0x20, 1)
#define D70 registr(0x20, 0)
 
// Функция установки курсора в указанную точку
#define lcd_gotoxy(x, y) write_to_lcd(0x80|((x)+((y)*0x40)), 0)
 
// Функция передачи данных в регистр
void registr(unsigned char data, unsigned char WriteOrErase)
{
volatile static unsigned char tempdata = 0;
     
if(WriteOrErase == 1)
tempdata = (tempdata|data);
else
tempdata &= ~(data);
PORTB &= ~(1 << PB1); // ST_CP 0
 
PORTB &= ~(1 << PB2); // SH_CP 0
if(tempdata & 0x80)PORTB |= (1 << PB0);
else PORTB &= ~(1 << PB0);
PORTB |= (1 << PB2); // SH_CP 1
PORTB &= ~(1 << PB2); // SH_CP 0
if(tempdata & 0x40)PORTB |= (1 << PB0);
else PORTB &= ~(1 << PB0);
PORTB |= (1 << PB2); // SH_CP 1
PORTB &= ~(1 << PB2); // SH_CP 0
if(tempdata & 0x20)PORTB |= (1 << PB0);
else PORTB &= ~(1 << PB0);
PORTB |= (1 << PB2); // SH_CP 1
PORTB &= ~(1 << PB2); // SH_CP 0
if(tempdata & 0x10)PORTB |= (1 << PB0);
else PORTB &= ~(1 << PB0);
PORTB |= (1 << PB2); // SH_CP 1
PORTB &= ~(1 << PB2); // SH_CP 0
if(tempdata & 0x08)PORTB |= (1 << PB0);
else PORTB &= ~(1 << PB0);
PORTB |= (1 << PB2); // SH_CP 1
PORTB &= ~(1 << PB2); // SH_CP 0
if(tempdata & 0x04)PORTB |= (1 << PB0);
else PORTB &= ~(1 << PB0);
PORTB |= (1 << PB2); // SH_CP 1
PORTB &= ~(1 << PB2); // SH_CP 0
if(tempdata & 0x02)PORTB |= (1 << PB0);
else PORTB &= ~(1 << PB0);
PORTB |= (1 << PB2); // SH_CP 1
PORTB &= ~(1 << PB2); // SH_CP 0
if(tempdata & 0x01)PORTB |= (1 << PB0);
else PORTB &= ~(1 << PB0);
PORTB |= (1 << PB2); // SH_CP 1
PORTB |= (1 << PB1); // ST_CP 1
}
 
// Функция передачи данных или команды в LCD
void write_to_lcd(char p, unsigned char rs)
{
if(rs == 1) RS1;
else RS0;
     
E1;
 
if(p&0x10) D41; else D40;
if(p&0x20) D51; else D50;
if(p&0x40) D61; else D60;
if(p&0x80) D71; else D70;
E0; 
_delay_ms(2);
     
E1;
     
if(p&0x01) D41; else D40;
if(p&0x02) D51; else D50;
if(p&0x04) D61; else D60;
if(p&0x08) D71; else D70;
E0;
 
_delay_ms(2);
}
 
// Функция инициализации LCD
void lcd_init(void)
{
write_to_lcd(0x02, 0); // Курсор в верхней левой позиции
write_to_lcd(0x28, 0); // Шина 4 бит, LCD - 2 строки
write_to_lcd(0x0C, 0); // Разрешаем вывод изображения, курсор не виден
write_to_lcd(0x01, 0); // Очищаем дисплей
}
 
// Функция вывода строки
void lcd_puts(char *str)
{
unsigned char i = 0;
 
while(str[i])
write_to_lcd(str[i++], 1);
}
 
// Функция вывода переменной
void lcd_num_to_str(unsigned int value, unsigned char nDigit)
{
switch(nDigit)
{
case 4: write_to_lcd((value/1000)+'0', 1);
case 3: write_to_lcd(((value/100)%10)+'0', 1);
case 2: write_to_lcd(((value/10)%10)+'0', 1);
case 1: write_to_lcd((value%10)+'0', 1);
}
}
 
// Функция чтения АЦП
int readADC(unsigned char ch)
{
ADMUX = ch; // Выбираем канал АЦП
      
ADCSRA |= (1 << ADSC); // Запускаем преобразование
while((ADCSRA & (1 << ADSC))); // Ждем окончания преобразования
 
return(ADC*11/2); // Возвращаем значение АЦП
}
 
int main(void)
{
DDRB = 0b00000111; // Настраиваем входы/выходы
 
ADCSRA |= (1 << ADEN) // Разрешение АЦП
       |(1 << ADPS2)|(1 << ADPS1); // Предделитель на 64
 
ACSR |= (1 << ACD); // Выключаем аналаговый компаратор
DIDR0 |= (1 << ADC3D)|(1 << ADC2D); // Отключаем неиспользуемые цифровые входы
 
lcd_init(); // Инициализация дисплея
 
write_to_lcd(0x01, 0); // Очищаем дисплей
 
lcd_gotoxy(0, 0); // Выводим строки на LCD
lcd_puts("U1 =   .  V");
lcd_gotoxy(0, 1);
lcd_puts("U2 =   .  V");
 
while(1)
{
lcd_gotoxy(5, 0);
lcd_num_to_str(readADC(2)/100, 2); // Выводим данные АЦП1 на LCD
lcd_gotoxy(8, 0);
lcd_num_to_str(readADC(2)%100/10, 1);
lcd_gotoxy(5, 1);
lcd_num_to_str(readADC(3)/100, 2); // Выводим данные АЦП2 на LCD
lcd_gotoxy(8, 1);
lcd_num_to_str(readADC(3)%100/10, 1);
_delay_ms(50);
}
}

Файлы:
Проект AVRStudio4

Дата 16.06.2013 Размер файла 39.55 KB Закачек 1298


Источник: http://radioparty.ru/index.php/prog-avr/program-c/472-lesson-74hc595-hd44780
Категория: УСТРОЙСТВА НА МК | (03.03.2015)
Просмотров: 4413 | Теги: плата, Схема, микроконтролер, ATtiny13, HD44780, Вольтамперметр, прошивка, LCD | Рейтинг: 5.0/1
Похожие материалы
Всего комментариев: 0
avatar

Copyright MyCorp © 2018    Бесплатный конструктор сайтов - uCoz                               Яндекс.Метрика