Форум программистов, компьютерный форум, киберфорум
Микроконтроллеры ATmega AVR
Войти
Регистрация
Восстановить пароль
 
 
Рейтинг 4.67/3: Рейтинг темы: голосов - 3, средняя оценка - 4.67
0 / 0 / 0
Регистрация: 14.05.2020
Сообщений: 4
1

Частотомер на ATmega128

15.05.2020, 01:02. Просмотров 592. Ответов 25

Здравствуйте, не могу разобраться в чем проблема. Написан код для того, что бы на выход PB4 подавался ШИМ сигнал, а с входа PD6 считывалась частота и всё это выводилось на ЖКИ. При подключении в протеусе у соответствующих портов мигают идикаторы, то есть сигнал приходит, но на ЖКИ ничего не выводится

C
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
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
//библиотека хранящая адреса портов
#include <avr/io.h>
// Частота МК
#define F_CPU 10000000UL
#include <util/delay.h>
//библиотека для функций прерывания
#include <avr/interrupt.h>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
 
 
//инициализация переменных, хранящих численное значение
//частоты сигнала
uint32_t f = 0;
//инициализация массива для вывода числа(частоты) на дисплей
char arr_f[10];
//переменная для отсчета времени в 100мс для вывода информации на дисплей
//и подсчета кол-ва инпульсов
uint32_t timer = 0, timer2 = 0;
 
//Для доступа к портам avr atmega заведем макросы:
 
//линии данных
#define LCD_DATA       PORTC
#define LCD_DATA_DDR   DDRC
 
//управляющие линии
#define LCD_CTRL       PORTC
#define LCD_CTRL_DDR   DDRC
 
 
#define LCD_RS_DATA     0x01    // 1 - данные
#define LCD_RS_COMMAND  0x00    // 0 - команды
#define LCD_E           0x02
/*выставить в 1 линию E импульс длительностью не менее 500 мс
 на этом выводе определяет сигнал для чтения данных с выводов DB0-DB7, RS и W/R*/
#define lcd_set_e   LCD_CTRL |= LCD_E
/*выставить в 1 линию RS означает, что сигнал на выходах DB0-DB7 является данными*/
#define lcd_set_rs  LCD_CTRL |= LCD_RS_DATA
 
/*выставить в 0 линию E импульс длительностью не менее 500 мс на этом выводе
 определяет сигнал для записи данных с выводов DB0-DB7, RS и W/R*/
#define lcd_clear_e  LCD_CTRL &= ~LCD_E
/*выставить в 0 линию RS означает, что сигнал на выходах DB0-DB7 является командой*/
#define lcd_clear_rs LCD_CTRL &= ~LCD_RS_DATA
//rw = 0,(он заземлен) т.е. все врем производится запись.
 
//Для облегчения настройки контроллера hd44780 заведем макросы, описывающие систему команд:
/*Очистить дисплей*/   //    Очистка экрана, AC=0, адресация AC на DDRAM
#define LCD_CLR              1<<0
/*Переход в начало экрана*/
//AC=0, адресация на DDRAM, сброшены сдвиги, начало строки адресуется в начале DDRAM
#define LCD_HOME             1<<1
 
#define LCD_MODE             1<<2 /*Сдвиг курсора или экрана при записи символа*/
#define LCD_MODE_SHIFT       1<<0 //включение движения
#define LCD_MODE_INC         1<<1 //движение в увеличение
#define LCD_MODE_DEC         0<<1 //движение в уменьшение
#define LCD_MODE_OFF_SHIFT   0<<0 //выключение движения
 
#define LCD_ON               1<<3 /*Вкл/выкл дисплей, курсор, мигание*/
#define LCD_ON_DISPLAY       1<<2 //Наличие изображения: 1 — включено
#define LCD_ON_CURSOR        1<<1 //Курсор в виде символа подчеркивания: 1 — включен
#define LCD_OFF_CURSOR       0<<1 //Курсор в виде символа подчеркивания: 0 — выключен
#define LCD_ON_BLINK         1<<0 //Курсор в виде мерцающего знакоместа: 1 — включен
#define LCD_OFF_BLINK        0<<0 //Курсор в виде мерцающего знакоместа: 0 — выключен
 
#define LCD_SHIFT            1<<4 /*Команда сдвига курсора/экрана*/
#define LCD_SHIFT_DISPLAY    1<<3 //Определяет объект смещения: 1 — сдвигается экран
#define LCD_SHIFT_CURSOR     0<<3 //Определяет объект смещения: 0 — сдвигается курсор
#define LCD_SHIFT_RIGHT      1<<2 //Уточняет направление сдвига: 1 — вправо
#define LCD_SHIFT_LEFT       0<<2 //Уточняет направление сдвига: 0 — влево
 
#define LCD_FUNCTION         1<<5 /*Разрядность шины данных, кол-во строк, размер шрифта*/
#define LCD_FUNCTION_4BIT    0<<4 //Флаг, определяющий ширину шины данных: 0 — 4 разряда
#define LCD_FUNCTION_8BIT    1<<4 //Флаг, определяющий ширину шины данных: 1 — 8 разрядов
#define LCD_FUNCTION_1LINES  0<<3 //Режим развертки изображения на ЖКИ: 0 — одна строка
#define LCD_FUNCTION_2LINES  1<<3 //Режим развертки изображения на ЖКИ: 1 — две строки
#define LCD_FUNCTION_8DOTS   0<<2 //Размер матрицы символов: 0 — 5x8 точек
#define LCD_FUNCTION_10DOTS  1<<2 //Размер матрицы символов: 1 — 5x10 точек
 
#define LCD_SET_CGRAM        0x40 /*Присвоение счетчику курсора адреса в области CGRAM*/
 
#define LCD_SET_DDRAM        0x80 /*Присвоение счетчику курсора адреса в области DDRAM*/
 
/*Функция ожидания готовности контроллера hd44780. Можно считывать статусный бит,
но мы будем просто делать паузу, в течение которой команда будет гарантированно выполнена.*/
#define lcd_wait     _delay_us(50);
 
/* Макрос перемещения курсора в начальную  позицию (0, 0) */
#define lcd_home      lcd_data(0x02, LCD_RS_COMMAND);
 
 
/* инициализация портов,
подключенных к жки */
#define init_port\
    LCD_DATA_DDR = 0xFF;\
    LCD_DATA = 0x00;\
    LCD_CTRL_DDR = 0xFF;\
    LCD_CTRL = 0x00;
 
 
/* функция передачи тетрады в жки. передается
младшая тетрада входного байта */
void lcd_low_data(char t)
{
    t <<= 4;
    lcd_set_e;
    LCD_DATA &= 0x0F;
    LCD_DATA |= t;
    lcd_wait;
    lcd_clear_e;
    lcd_wait;
}
 
/* функция передачи байта в жки */
void lcd_data(char c, char rs)
{
    char highc = 0;
    highc = c >> 4;
    if (rs == LCD_RS_COMMAND)
    {
        lcd_clear_rs;
    }
    else
    {
        lcd_set_rs;
    }
    lcd_low_data(highc);
    lcd_low_data(c);
}
 
/* функция очистки дисплея и возврата
курсора в начальную позицию*/
void lcd_clear()
{
    lcd_data(0x01, LCD_RS_COMMAND);
    _delay_us(1500);
}
 
 
/* функция перемещения курсора в заданную позицию*/
void lcd_goto(char x, char y)
{
    char cursor;
    y &= 1;
    cursor  = 0x40 * y + x;
    cursor |= LCD_SET_DDRAM;
    lcd_data(cursor, LCD_RS_COMMAND);
}
 
 
//Макрос вывода символа на дисплей.
void lcd_putc(char x)
{
    lcd_data(x, LCD_RS_DATA);
}
 
 
//Функция вывода строки.
void lcd_puts( char *str)
{
  while( *str )
  {
    lcd_putc( *str++ );
  }
}
 
 
 
/* функция инициализации работы жки в 4-битном режиме, без курсора */
void lcd_init()
{
    _delay_ms(100);
    // Сброс шины данных
    lcd_clear_rs; // установка нуля на линии RS
 
    lcd_low_data(0x00);
    _delay_ms(5);
    lcd_low_data(0x00);
    _delay_ms(5);
    lcd_low_data(0x00);
    _delay_ms(5);
    lcd_low_data(0x00);
    _delay_ms(5);
    lcd_low_data(0x00);
    _delay_ms(5);
 
    // физический выбор шины, дисплея
    lcd_low_data(0x02);
    lcd_low_data(0x02);
    lcd_low_data((LCD_FUNCTION | LCD_FUNCTION_4BIT | LCD_FUNCTION_2LINES | LCD_FUNCTION_8DOTS) & 0x0F);
    // Здесь должна быть проверка флага занятости
    _delay_ms(50);
 
    // Display ON/OFF Control
    lcd_data((LCD_ON | LCD_ON_DISPLAY | LCD_OFF_CURSOR | LCD_OFF_BLINK), LCD_RS_COMMAND);
    // Здесь должна быть проверка флага занятости
    _delay_ms(50);
 
    // Очистка дисплея
    lcd_clear();
    // Здесь должна быть проверка флага занятости
    _delay_ms(50);
 
    // Режим вывода
    lcd_data((LCD_MODE | LCD_MODE_INC), LCD_RS_COMMAND);
 
    // Дополнительно: возврат в координату (0, 0)
    lcd_home;
 
    lcd_set_rs;
}
 
//функция обработчик прерывания по переполнению
//счетного регистра таймера 1
ISR(TIMER?1?_OVF_vect)
{
    //условие на 500 переполнений
    if(timer2 == 500)
    {   //расчет значения частоты
        f = (uint32_t)((timer*F_CPU) / (timer2*256));
        //заполнение массива числом посимвольно
        itoa(f, arr_f, 10);
        //очистка дисплея ЖКИ
        lcd_clear();
        //курсор в 0-ю позицию первой строки
        lcd_goto(0 , 0);
        //вывод значения на дисплей
        lcd_puts(arr_f);
        //сброс таймера для отсчета периода времени
        timer2 = 0;
        //сброс счетчика кол-ва импульсов
        timer = 0;
        //сброс счетного регистра
        TCNT0 = 0;
    }
    else
    {   //счет кол-ва переполнений
        timer2++;
    }
}
 
//функция обработчик прерывания по внешнему запросу
ISR(INT?1?_vect)
{   //счет кол-ва импульсов
    timer++;
}
 
// Предварительная настройка таймера
void timer_init() {
    long int oc = 49999; // ввод переменной для OCR0;
    //Инициализация Т/С0
    TCCR0 = 0;
    //настройка ножки OC0 в работу, предделитель равен 1,
    TCCR0 =  (0 << COM01) | (1 << COM00) | (1 << WGM01) | (0 << WGM00) | (1 << CS00);
    //Выбор режима PWM и предделителя
    //устанавливаем период сигнала(для частоты 1кГц)
    OCR0 = oc;
    DDRB = (1 <<4 ); //инициализация порта OC0 на выход
}
 
void timer_init2() {
    //Инициализация T/C1
    TCCR1А = 0;
    //Внешний тактовый источник с вывода T1, режим СТС;
    TCCR1B = (1 << CS12) | (1 << CS11) | (1 << WGM12);
    TCCR1C = 0;
    OCR1A = 2500;
    // Разрешаем прерывание по достижению максимума
    TIMSK  = (1 << OCIE1A);
    ETIMSK = 0x00;
    //Инициализация T1 на вход
    PORTD = 0;
    DDRD = (1 << 6)
}
 
 
 
int main(void) {
    // Запрет прерываний
    cli();
    //инициализируем таймер
    timer_init();
    timer_init2();
    init_port;
    //инициализация ЖКИ
    lcd_init();
    //очистить дисплей
    lcd_clear();
    // Глобальное разрешение прерываний
    sei();
    // Рабочий цикл
    while(1)
    {
 
    }
}
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
15.05.2020, 01:02
Ответы с готовыми решениями:

Частотомер
Всем привет. Решил обзавестись сим девайсом, погуглив в инете и просмотрев несколько вариантов схем...

Частотомер.
Делаю частотомер для струнного датчика с автогенератором, сигнал на выходе 0,3 В прямоугольный от 2...

Частотомер
Помогите разобраться в схеме: http://i025.***********/1108/36/f927493416ca.jpg Вопросы: ...

Частотомер
Привет всем, есть программа таймера ( частотомера) написана на ассемблере, в протеусе проверил сам...

25
458 / 307 / 29
Регистрация: 15.08.2011
Сообщений: 960
17.05.2020, 19:18 2
А схема считаете не нужна?
0
1130 / 488 / 208
Регистрация: 11.10.2018
Сообщений: 2,738
17.05.2020, 20:55 3
Какой ЖКИ-то вообще?

Добавлено через 1 час 16 минут
В Proteus "LM044L"?
0
0 / 0 / 0
Регистрация: 14.05.2020
Сообщений: 4
18.05.2020, 00:29  [ТС] 4
В Proteus "LM016L"
0
0 / 0 / 0
Регистрация: 14.05.2020
Сообщений: 4
18.05.2020, 00:31  [ТС] 5
Вот схема
0
Вложения
Тип файла: 7z lab3_proteus.7z (18.2 Кб, 5 просмотров)
1130 / 488 / 208
Регистрация: 11.10.2018
Сообщений: 2,738
18.05.2020, 12:18 6
Исправил некоторые косячки в программе
Кликните здесь для просмотра всего текста
C
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
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
/*
 * Sky.c
 *
 * Created: 18.05.2020 11:50:17
 * Author: Михаил
 */
 
#include <io.h>
#include <mega128a.h>
 
 
 
 
 
//библиотека хранящая адреса портов
//#include <avr/io.h>
// Частота МК
#define F_CPU 10000000UL
#include <delay.h>
//библиотека для функций прерывания
#include <interrupt.h>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
 
 
//инициализация переменных, хранящих численное значение
//частоты сигнала
long int f = 0;
//инициализация массива для вывода числа(частоты) на дисплей
char arr_f[10];
//переменная для отсчета времени в 100мс для вывода информации на дисплей
//и подсчета кол-ва инпульсов
long int timer = 0, timer2 = 0;
 
//Для доступа к портам avr atmega заведем макросы:
 
//линии данных
#define LCD_DATA       PORTC
#define LCD_DATA_DDR   DDRC
 
//управляющие линии
#define LCD_CTRL       PORTC
#define LCD_CTRL_DDR   DDRC
 
 
#define LCD_RS_DATA     0x01    // 1 - данные
#define LCD_RS_COMMAND  0x00    // 0 - команды
#define LCD_E           0x02
/*выставить в 1 линию E импульс длительностью не менее 500 мс
 на этом выводе определяет сигнал для чтения данных с выводов DB0-DB7, RS и W/R*/
#define lcd_set_e   LCD_CTRL |= (1 << 1)
/*выставить в 1 линию RS означает, что сигнал на выходах DB0-DB7 является данными*/
#define lcd_set_rs  LCD_CTRL |= (1 << 0)
 
/*выставить в 0 линию E импульс длительностью не менее 500 мс на этом выводе
 определяет сигнал для записи данных с выводов DB0-DB7, RS и W/R*/
#define lcd_clear_e  LCD_CTRL &= ~(1 << 1)
/*выставить в 0 линию RS означает, что сигнал на выходах DB0-DB7 является командой*/
#define lcd_clear_rs LCD_CTRL &= ~(1 << 0)
//rw = 0,(он заземлен) т.е. все врем производится запись.
 
//Для облегчения настройки контроллера hd44780 заведем макросы, описывающие систему команд:
/*Очистить дисплей*/   //    Очистка экрана, AC=0, адресация AC на DDRAM
#define LCD_CLR              1<<0
/*Переход в начало экрана*/
//AC=0, адресация на DDRAM, сброшены сдвиги, начало строки адресуется в начале DDRAM
#define LCD_HOME             1<<1
 
#define LCD_MODE             1<<2 /*Сдвиг курсора или экрана при записи символа*/
#define LCD_MODE_INC         1<<1 //движение в увеличение
#define LCD_MODE_DEC         0<<1 //движение в уменьшение
#define LCD_MODE_SHIFT       1<<0 //включение движения
#define LCD_MODE_OFF_SHIFT   0<<0 //выключение движения
 
#define LCD_ON               1<<3 /*Вкл/выкл дисплей, курсор, мигание*/
#define LCD_ON_DISPLAY       1<<2 //Наличие изображения: 1 — включено
#define LCD_ON_CURSOR        1<<1 //Курсор в виде символа подчеркивания: 1 — включен
#define LCD_OFF_CURSOR       0<<1 //Курсор в виде символа подчеркивания: 0 — выключен
#define LCD_ON_BLINK         1<<0 //Курсор в виде мерцающего знакоместа: 1 — включен
#define LCD_OFF_BLINK        0<<0 //Курсор в виде мерцающего знакоместа: 0 — выключен
 
#define LCD_SHIFT            1<<4 /*Команда сдвига курсора/экрана*/
#define LCD_SHIFT_DISPLAY    1<<3 //Определяет объект смещения: 1 — сдвигается экран
#define LCD_SHIFT_CURSOR     0<<3 //Определяет объект смещения: 0 — сдвигается курсор
#define LCD_SHIFT_RIGHT      1<<2 //Уточняет направление сдвига: 1 — вправо
#define LCD_SHIFT_LEFT       0<<2 //Уточняет направление сдвига: 0 — влево
 
#define LCD_FUNCTION         1<<5 /*Разрядность шины данных, кол-во строк, размер шрифта*/
#define LCD_FUNCTION_4BIT    0<<4 //Флаг, определяющий ширину шины данных: 0 — 4 разряда
#define LCD_FUNCTION_8BIT    1<<4 //Флаг, определяющий ширину шины данных: 1 — 8 разрядов
#define LCD_FUNCTION_1LINES  0<<3 //Режим развертки изображения на ЖКИ: 0 — одна строка
#define LCD_FUNCTION_2LINES  1<<3 //Режим развертки изображения на ЖКИ: 1 — две строки
#define LCD_FUNCTION_8DOTS   0<<2 //Размер матрицы символов: 0 — 5x8 точек
#define LCD_FUNCTION_10DOTS  1<<2 //Размер матрицы символов: 1 — 5x10 точек
 
#define LCD_SET_CGRAM        0x40 /*Присвоение счетчику курсора адреса в области CGRAM*/
 
#define LCD_SET_DDRAM        0x80 /*Присвоение счетчику курсора адреса в области DDRAM*/
 
/*Функция ожидания готовности контроллера hd44780. Можно считывать статусный бит,
но мы будем просто делать паузу, в течение которой команда будет гарантированно выполнена.*/
#define lcd_wait     delay_us(50);
 
/* Макрос перемещения курсора в начальную  позицию (0, 0) */
#define lcd_home      lcd_data(0x02, LCD_RS_COMMAND);
 
 
/* инициализация портов,
подключенных к жки */
#define init_port\
    LCD_DATA_DDR = 0xFF;\
    LCD_DATA = 0x00;\
    LCD_CTRL_DDR = 0xFF;\
    LCD_CTRL = 0x00;
 
 
/* функция передачи тетрады в жки. передается
младшая тетрада входного байта */
void lcd_low_data(unsigned char t)
{
    t <<= 4;
    lcd_set_e;
    LCD_DATA &= 0x0F;
    LCD_DATA |= t;
    lcd_wait;
    lcd_clear_e;
    lcd_wait;
}
 
/* функция передачи байта в жки */
void lcd_data(char c, char rs)
{
    char highc = 0;
    highc = c >> 4;
    if (rs == LCD_RS_COMMAND)
    {
        lcd_clear_rs;
    }
    else
    {
        lcd_set_rs;
    }
    lcd_low_data(highc);
    lcd_low_data(c);
}
 
/* функция очистки дисплея и возврата
курсора в начальную позицию*/
void lcd_clear()
{
    lcd_data(0x01, LCD_RS_COMMAND);
    delay_us(1500);
}
 
 
/* функция перемещения курсора в заданную позицию*/
void lcd_goto(char x, char y)
{
    char cursor;
    y &= 1;
    cursor  = 0x40 * y + x;
    cursor |= LCD_SET_DDRAM;
    lcd_data(cursor, LCD_RS_COMMAND);
}
 
 
//Макрос вывода символа на дисплей.
void lcd_putc(char x)
{
    lcd_data(x, LCD_RS_DATA);
}
 
 
//Функция вывода строки.
void lcd_puts( char *str)
{
  while( *str )
  {
    lcd_putc( *str++ );
  }
}
 
 
 
/* функция инициализации работы жки в 4-битном режиме, без курсора */
void lcd_init()
{
    delay_ms(100);
    // Сброс шины данных
    lcd_clear_rs; // установка нуля на линии RS
 
    lcd_low_data(0x00);
    delay_ms(5);
    lcd_low_data(0x00);
    delay_ms(5);
    lcd_low_data(0x00);
    delay_ms(5);
    lcd_low_data(0x00);
    delay_ms(5);
    lcd_low_data(0x00);
    delay_ms(5);
 
    //физический выбор шины, дисплея
    lcd_low_data(0x02);
    lcd_low_data(0x02);
    lcd_low_data((LCD_FUNCTION | LCD_FUNCTION_4BIT | LCD_FUNCTION_2LINES | LCD_FUNCTION_8DOTS) & 0x0F);
    // Здесь должна быть проверка флага занятости
    delay_ms(50);
 
    //Display ON/OFF Control
    lcd_data((LCD_ON | LCD_ON_DISPLAY | LCD_ON_CURSOR | LCD_ON_BLINK), LCD_RS_COMMAND);
    //Здесь должна быть проверка флага занятости
    delay_ms(50);
 
    
    //Очистка дисплея
    lcd_clear();
    // Здесь должна быть проверка флага занятости
    delay_ms(50);
 
    // Режим вывода
    lcd_data((LCD_MODE | LCD_MODE_INC), LCD_RS_COMMAND);
 
    // Дополнительно: возврат в координату (0, 0)
    lcd_home;
 
    lcd_set_rs;
}
 
//функция обработчик прерывания по переполнению
//счетного регистра таймера 1
#pragma vector=15
__interrupt void Timer1_OVF(void)
//ISR(TIMER1_OVF_vect)
{
    //условие на 500 переполнений
    if(timer2 == 500)
    {   //расчет значения частоты
        f = (long int)((timer*F_CPU) / (timer2*256));
        //заполнение массива числом посимвольно
        itoa(f, arr_f);
        //очистка дисплея ЖКИ
        lcd_clear();
        //курсор в 0-ю позицию первой строки
        lcd_goto(0 , 0);
        //вывод значения на дисплей
        lcd_puts(arr_f);
        //сброс таймера для отсчета периода времени
        timer2 = 0;
        //сброс счетчика кол-ва импульсов
        timer = 0;
        //сброс счетного регистра
        TCNT0 = 0;
    }
    else
    {   //счет кол-ва переполнений
        timer2++;
    }
}
 
//функция обработчик прерывания по внешнему запросу
#pragma vector=3
__interrupt void INT1_ISR(void)
//ISR(INT1_vect)
{   
    //счет кол-ва импульсов
    timer++;
}
 
// Предварительная настройка таймера
void timer_init()
{
    long int oc = 49999; // ввод переменной для OCR0;
    //Инициализация Т/С0
    TCCR0 = 0;
    //настройка ножки OC0 в работу, предделитель равен 1,
    TCCR0 =  (0 << COM01) | (1 << COM00) | (1 << WGM01) | (0 << WGM00) | (1 << CS00);
    //Выбор режима PWM и предделителя
    //устанавливаем период сигнала(для частоты 1кГц)
    OCR0 = oc;
    DDRB = (1 <<4 ); //инициализация порта OC0 на выход
}
 
void timer_init2()
{
    //Инициализация T1
    TCCR1A = 0;
    //Внешний тактовый источник с вывода T1, режим СТС;
    TCCR1B = (1 << CS12) | (1 << CS11) | (1 << WGM12);
    TCCR1C = 0;
    OCR1A = 2500;
    // Разрешаем прерывание по достижению максимума
    TIMSK  = (1 << OCIE1A);
    ETIMSK = 0x00;
    //Инициализация T1 на вход
    PORTD = 0;
    DDRD = (1 << 6);
}
 
 
 
void main(void)
{
    //Запрет прерываний
    cli();
    //инициализируем таймер
    timer_init();
    timer_init2();
    init_port;
    //инициализация ЖКИ
    lcd_init();
    //очистить дисплей
    lcd_clear();
    // Глобальное разрешение прерываний
    sei();
   
    //функция передачи байта в жки */
    //void lcd_data(char c, char rs)
    lcd_data('C', '1');
    
    //Рабочий цикл
    while(1)
    {
 
    }
}

Это код выводит просто символ C в дисплей. Код приспособлен под CodeVisionAVR(CVAVR).

Добавлено через 7 минут
И посмотрите там в Протеусе проводник на левом выводе конденсатора C1, я его переделал.

Добавлено через 13 минут
cfire4, а Вас код противоречит сам себе. Вот эта команда не выполнится
C
1
lcd_low_data((LCD_FUNCTION | LCD_FUNCTION_4BIT | LCD_FUNCTION_2LINES | LCD_FUNCTION_8DOTS) & 0x0F);
из-за того что идет ограничение только на правый полубайт командой "& 0x0F".
Вероятно требуется шина данных 8-бит.
Смешали 2 сложные темы: 1) Дисплей HD44780 и 2) частотомер.
Это 2 итак большие темы, а Вы их смешали, да еще и не понимаете ничего.
Нужна шина данных 8-бит, как Вы 4-битной шиной собрались управлять дисплеем?
Частотомер - это отдельная тема и большая я бы сказал. Ей может быть посвящена отдельная статья.
0
0 / 0 / 0
Регистрация: 14.05.2020
Сообщений: 4
18.05.2020, 13:35  [ТС] 7
Просто знаний мало, много чего непонятно в связи, с тем, что нормальных занятий нет, а работы нужно выполнить

Можно поподробнее почему не получится управлять дисплее с помощью 4-х битной шины, в прошлой работе необходимо было выводить текст на жки, менять его местами и стирать и всё получалось. Так же одногруппники в похожих работах тоже используют 4-х битные
0
1130 / 488 / 208
Регистрация: 11.10.2018
Сообщений: 2,738
18.05.2020, 17:18 8
Потому что константа LCD_FUNCTION = 0x20 вылазит слева при таком фильтре & 0x0F и вообще сотрется после этой операции.
Как же Вы упихнете такое число в 8-битный регистр OCR бедного Timer0
C
1
2
3
    long int oc = 49999;  // ввод переменной для OCR0;
    //...
    OCR0 = oc;
Ответ простой никак. Вы взяли 2 большие темы, которые Вам не по силам. Нужно сначала знания получить, а потом уже конструировать.

Добавлено через 3 часа 17 минут
cfire4, вот правильная настройка Таймера0, у Вас неправильно он настроен
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
//Предварительная настройка таймера
void timer_init()
{
    //Инициализация Т0, предделитель равен 32
    TCCR0 = (0 << CS02) | (1 << CS01) |  (1 << CS00);
    
    //настройка ножки OC0 в работу
    TCCR0 |= (0 << COM01) | (1 << COM00) | (1 << WGM01) | (0 << WGM00);
    
    //Выбор режима PWM и предделителя
    //устанавливаем период сигнала(для частоты 1кГц)
    OCR0 = 128;
    DDRB = (1 << 4);  //инициализация порта OC0 на выход
}
Эта настройка дает выходную частоту 1212(Гц).

Добавлено через 1 минуту
И вообще, про дисплей, надо делать шину данных 8-бит и еще 2 бита на управление - сигналы RS и E.

Добавлено через 11 минут
Вот нарегулировал частоту 1000(Гц). Настройка Таймера0
C++
1
2
3
    //Выбор режима PWM и предделителя
    //устанавливаем период сигнала(для частоты 1кГц)
    OCR0 = 155;
0
125 / 43 / 12
Регистрация: 23.03.2018
Сообщений: 169
18.05.2020, 21:26 9
Цитата Сообщение от cfire4 Посмотреть сообщение
Можно поподробнее почему не получится управлять дисплее с помощью 4-х битной шины, в прошлой работе необходимо было выводить текст на жки, менять его местами и стирать и всё получалось.
В общем, при объединении этих двух вещей - частотомера и ЖК дисплея нужно понимать следующее: подсчет частоты входящего сигнала осуществляется через прерывания.
1 тезис: При появлении или при пропадании сигнала на измерительном входе присходит прерывание (останавливаются все работающие функции и начинается запуск подсчета значений таймера для вычисления частоты).
2 тезис: Для вывода информации на жки(хоть в 4х пров. хоть в 8проводном режиме) контроллер тратит определенное (конкретное) время.
Вывод: если прерывание по измерительному входу вызовиться в момент передачи информации на дисплей, время передачи сигналов на ЖКИ изменятся и это могжет вызвать зависание ЖК дисплея.(и на практике часто вызывает).
Чтобы исключить такое необходимо:
1. 1 секунду измеряешь частоту, потом отключаешь прерывание по входу и 0,1с обновляешь дисплей и так по циклу: меришь, останавливаешь измерения, выводишь и заново запускаешь измерения.
2. Для понимания процесса вывода на дисплей можешь посмотреть урок на сайте
HTML5
1
narodstream.ru
.
там очень хорошо и простыми словами написана как работает библиотека для работы с LCD.
0
1130 / 488 / 208
Регистрация: 11.10.2018
Сообщений: 2,738
19.05.2020, 09:55 10
Здравствуйте. А как там задавать в этом дисплее 4-битный и 8-битный режим? Я вот в 8-битный режим попробовал перегнать, что-то не получается ничего. Там 4-битный режим пишут, что надо 0x0011 послать 2 раза, чтобы заработал 4-битный режим. Может и для 8-битного режима что-нибудь нужно вначале?
Марка дисплея HD44780, в Proteuse - LM016L.
0
Модератор
8199 / 6070 / 810
Регистрация: 14.02.2011
Сообщений: 21,057
19.05.2020, 11:12 11
Цитата Сообщение от FFPowerMan Посмотреть сообщение
что надо 0x0011 послать 2 раза, чтобы заработал 4-битный режим.
а не 0x03 ??? двоичное 0011

см.например здесь https://cxem.net/mc/mc134.php
0
1130 / 488 / 208
Регистрация: 11.10.2018
Сообщений: 2,738
19.05.2020, 12:10 12
Да я уже запутался совсем. У автора такой код беспонтовый что это вообще.
0
125 / 43 / 12
Регистрация: 23.03.2018
Сообщений: 169
19.05.2020, 18:47 13
Вот скидываю свою библиотеку для работы с LCD в 4проводном режиме.
rs подключаешь на PORTB.0
e подключаешь на PORTB.1
4 ножки дисплея подключаешь к ножкам PORTB.4 - PORTB.7

C++
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
#define e1 PORTB|=0b00000010 // установка линии E в 1  эту строку ставишь рядом с инклудами
 
#define e0 PORTB&=~0b00000010 // установка линии E в 0  эту строку ставишь рядом с инклудами
 
#define rs1 PORTB|=0b00000001 // установка линии RS в 1 (данные)  эту строку ставишь рядом с инклудами
 
#define rs0 PORTB&=~0b00000001 // установка линии RS в 0 (команда)  эту строку ставишь рядом с инклудами
 
 
 
LCD_ini();   эту строку ставишь рядом в начале майна после настройки портов
 
 
void LCD_ini(void)    //функция инициализации дисплея в 4 проводном режиме
{
    _delay_ms(40); //Ждем 15 мс
 
    sendhalfbyte(0b00000011);
    _delay_ms(1);
    sendhalfbyte(0b00000011);
    _delay_ms(1);
    sendhalfbyte(0b00000011);
    _delay_ms(1);
    sendhalfbyte(0b00000010);
    _delay_ms(1);
    sendhalfbyte(0b00000010);
    _delay_ms(1);
    sendhalfbyte(0b00000010);
    _delay_ms(1);
    sendbyte(0b00101000, 0); //4бит-режим (DL=0) и 2 линии (N=1)
    _delay_ms(1);
    sendbyte(0b00001100, 0); //включаем изображение на дисплее (D=1), курсоры никакие не включаем (C=0, B=0)
    _delay_ms(1);
    sendbyte(0b00000110, 0); //курсор (хоть он у нас и невидимый) будет двигаться влево
    _delay_ms(1);
}
 
void sendbuk(unsigned char c)     //функция отправки по одной букве, например: sendbuk('E');
{
    sendbyte(c,1);
}
 
void sendbyte(unsigned char c, unsigned char mode)  //служебная функция для работы библиотеки
{
    if (mode==0) rs0;
    else rs1;
    _delay_us(50);
    unsigned char hc=0;
    unsigned char hc1=0;
    hc=c>>4;
    hc1=c<<4;
    c=0;
    c=hc1>>4;
    sendhalfbyte(hc);
    sendhalfbyte(c);
}
void sendhalfbyte(unsigned char c)  //служебная функция для работы библиотеки
{
    c<<=4;
    e1;
    PORTB&=0b00001111;
    PORTB|=c;
    _delay_ms(1);
    e0;
    _delay_ms(1);
}
void mesto(unsigned char x, unsigned y) //функция для установки курсора, например: mesto(0,0); - установит 
{                                                        //курсор в начало дисплея
    char adress;
    adress=(64*y+x)|0b10000000;
    sendbyte(adress, 0);
}
void sendsl (char str1[])                        //функция отправки слова, например: sendsl('privet');
{
    char n;
    for(n=0;str1[n]!=0;n++)
    sendbuk(str1[n]);
}
Добавлено через 3 минуты
Даже в моей библиотеке каждая буква отправляется за 4мс. Если слово будешь отправлять 4мс умножай на количество букв в слове.
Встроенная библиотека примерно так же работает- тратит примерно столько же времени.
0
1130 / 488 / 208
Регистрация: 11.10.2018
Сообщений: 2,738
23.05.2020, 17:46 14
Попробовал код - ну не работает опять. Может у меня с Протеусом глюки? Пустой экран(LCD) и все.
0
125 / 43 / 12
Регистрация: 23.03.2018
Сообщений: 169
24.05.2020, 09:07 15
Вот тебе рабочая часть, отнасящаяся только к работе с дисплеем:
C++
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
#include <avr/io.h>
 
#include <util/delay.h>
 
#define F_CPU 8000000
 
 
#define e1 PORTB|=0b00000010 // установка линии E в 1  эту строку ставишь рядом с инклудами
 
#define e0 PORTB&=~0b00000010 // установка линии E в 0  эту строку ставишь рядом с инклудами
 
#define rs1 PORTB|=0b00000001 // установка линии RS в 1 (данные)  эту строку ставишь рядом с инклудами
 
#define rs0 PORTB&=~0b00000001 // установка линии RS в 0 (команда)  эту строку ставишь рядом с инклудами
 
 
 
int main(void)
{
    DDRB=0b11111111;
    LCD_ini();  // эту строку ставишь рядом в начале майна после настройки портов
    mesto(0,1);
    sendbuk('S');
    sendbuk('T');
    sendbuk('A');
    sendbuk('R');
    sendbuk('T');
    mesto(0,0);
    sendsl("Proverka");
    while (1) 
    {
    }
}
 
 
void LCD_ini(void)    //функция инициализации дисплея в 4 проводном режиме
{
    _delay_ms(40); //Ждем 15 мс
    
    sendhalfbyte(0b00000011);
    _delay_ms(1);
    sendhalfbyte(0b00000011);
    _delay_ms(1);
    sendhalfbyte(0b00000011);
    _delay_ms(1);
    sendhalfbyte(0b00000010);
    _delay_ms(1);
    sendhalfbyte(0b00000010);
    _delay_ms(1);
    sendhalfbyte(0b00000010);
    _delay_ms(1);
    sendbyte(0b00101000, 0); //4бит-режим (DL=0) и 2 линии (N=1)
    _delay_ms(1);
    sendbyte(0b00001100, 0); //включаем изображение на дисплее (D=1), курсоры никакие не включаем (C=0, B=0)
    _delay_ms(1);
    sendbyte(0b00000110, 0); //курсор (хоть он у нас и невидимый) будет двигаться влево
    _delay_ms(1);
}
 
void sendbuk(unsigned char c)     //функция отправки по одной букве, например: sendbuk('E');
{
    sendbyte(c,1);
}
 
void sendbyte(unsigned char c, unsigned char mode)  //служебная функция для работы библиотеки
{
    if (mode==0) rs0;
    else rs1;
    _delay_us(50);
    unsigned char hc=0;
    unsigned char hc1=0;
    hc=c>>4;
    hc1=c<<4;
    c=0;
    c=hc1>>4;
    sendhalfbyte(hc);
    sendhalfbyte(c);
}
void sendhalfbyte(unsigned char c)  //служебная функция для работы библиотеки
{
    c<<=4;
    e1;
    PORTB&=0b00001111;
    PORTB|=c;
    _delay_ms(1);
    e0;
    _delay_ms(1);
}
void mesto(unsigned char x, unsigned y) //функция для установки курсора, например: mesto(0,0); - установит
{                                                        //курсор в начало дисплея
    char adress;
    adress=(64*y+x)|0b10000000;
    sendbyte(adress, 0);
}
void sendsl (char str1[])                        //функция отправки слова, например: sendsl('privet');
{
    char n;
    for(n=0;str1[n]!=0;n++)
    sendbuk(str1[n]);
}
0
125 / 43 / 12
Регистрация: 23.03.2018
Сообщений: 169
24.05.2020, 09:08 16
И вот само подключение к дисплею в протеусе:
0
Миниатюры
Частотомер на ATmega128  
125 / 43 / 12
Регистрация: 23.03.2018
Сообщений: 169
24.05.2020, 09:19 17
Теперь для измерения времени отправки каждого слова и буквы добавляю такую функцию:
C++
1
2
3
4
5
6
7
8
9
10
11
12
void prover (void)    //при вызове этой функции ножка PORTB.2 будет менять свое значение на противоположное
{   
    if (!(PINB&0b00000100))
    {
        PORTB|=0b00000100;
                        
    }
    else
    {
        PORTB&=~0b00000100;
    }
}
И теперь вызывая функцию перед и после отправки слова и букв, подключившись осциллографом сможем увидеть время отправки каждого символа:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
LCD_ini();  // эту строку ставишь рядом в начале майна после настройки портов
    prover();
    mesto(0,1);
    prover();
    sendbuk('S');
    prover();
    sendbuk('T');
    prover();
    sendbuk('A');
    prover();
    sendbuk('R');
    prover();
    sendbuk('T');
    prover();
    mesto(0,0);
    prover();
    sendsl("Proverka");
    prover();
И увидим вот такую картину:
0
Миниатюры
Частотомер на ATmega128  
125 / 43 / 12
Регистрация: 23.03.2018
Сообщений: 169
24.05.2020, 09:22 18
Цитата Сообщение от FFPowerMan Посмотреть сообщение
Попробовал код - ну не работает опять. Может у меня с Протеусом глюки? Пустой экран(LCD) и все.
И по картинке видна длительность передачи каждого слова.
И для того, чтобы дисплей не зависал, желательно перед отправкой на него значений надо остановить прерывание по измерительному входу. И тогда все получиться.
0
1130 / 488 / 208
Регистрация: 11.10.2018
Сообщений: 2,738
24.05.2020, 11:39 19
Осциллограф это одно, но Digital Analyser - это другое. Крутой инструмент, правда пока допетрил, как им пользоваться...
Ну в общем я по нему раньше смотрел и вроде правильно микроконтроллер передает сигналы, но все-равно ничего не отображается.
0
125 / 43 / 12
Регистрация: 23.03.2018
Сообщений: 169
24.05.2020, 12:04 20
Цитата Сообщение от FFPowerMan Посмотреть сообщение
Ну в общем я по нему раньше смотрел и вроде правильно микроконтроллер передает сигналы, но все-равно ничего не отображается.
Говорю же тебе: у меня в программе других строк нет. Попробуй эти же строки применить. Эти строки и проект протеуса это я собрал и проверил сегодня утром - должен работать.
Или у тебя в протеусе частота микроконтроллера не та установлена
0
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
24.05.2020, 12:04

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

частотомер
форумчани подскажите пожалуйста, разрабатываю вот этот частотомер...

частотомер на at89c51
Сделал модель частотомера ra4nalа в протеусе. &lt;Изображение удалено&gt; не могу разобраться,...

Сделал частотомер
Сделал частотомер на ATmega8 и EPM3064A. Всю информацию для повторения выложил здесь:...

Частотомер на Arduino
Плата Arduino Nano v3. Питание 5 в. Частота 16 М. Нужна помощь в написании программы для измерения...

Сбоит частотомер
Доброго времени суток! Проблема: считаю период входного прямоугольного импульса с помощью захвата...

Цифровой частотомер
Нужен совет опытных людей в схемотехнике. Задача следующая: необходимо разработать входную часть...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2020, vBulletin Solutions, Inc.