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

Принять данные по UART, начиная с указанной позиции

03.08.2018, 12:58. Просмотров 933. Ответов 7
Метки нет (Все метки)


Приветствую!

Работаю в AtmelStudio 7 с мк Atmega8

Как можно организовать получение данных с указанной позиции и отображения их на LCD?

Есть такой код
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
#include <avr/io.h>
#include <avr/interrupt.h>
 
#define BAUDRATE 9600 // Скорость обмена данными
#define F_CPU 8000000UL // Рабочая частота контроллера
 
unsigned char NUM = 0;
unsigned char count = 0;
unsigned char byte_receive = 0;
unsigned char i = 1;
 
// Функция задержки в мкс
void _delay_us(unsigned char time_us)
{ register unsigned char i;
    
    for(i = 0; i < time_us; i++)
    {
        asm volatile(" PUSH  R0 ");
        asm volatile(" POP   R0 ");
    }
}
 
// Функция задержки в мс
void _delay_ms(unsigned int time_ms)
{ register unsigned int i;
    
    for(i = 0; i < time_ms; i++)
    {
        _delay_us(250);
        _delay_us(250);
        _delay_us(250);
        _delay_us(250);
    }
}
 
#define RS PD2
#define EN PD3
 
// Функция передачи команды
void lcd_com(unsigned char p)
{
    PORTD &= ~(1 << RS); // RS = 0 (запись команд)
    PORTD |= (1 << EN); // EN = 1 (начало записи команды в LCD)
    PORTD &= 0x0F; PORTD |= (p & 0xF0); // старший нибл
    _delay_us(100);
    PORTD &= ~(1 << EN); // EN = 0 (конец записи команды в LCD)
    _delay_us(100);
    PORTD |= (1 << EN); // EN = 1 (начало записи команды в LCD)
    PORTD &= 0x0F; PORTD |= (p << 4); // младший нибл
    _delay_us(100);
    PORTD &= ~(1 << EN); // EN = 0 (конец записи команды в LCD)
    _delay_us(100);
}
 
// Функция передачи данных
void lcd_data(unsigned char p)
{
    PORTD |= (1 << RS)|(1 << EN); // RS = 1 (запись данных), EN - 1 (начало записи команды в LCD)
    PORTD &= 0x0F; PORTD |= (p & 0xF0); // старший нибл
    _delay_us(100);
    PORTD &= ~(1 << EN); // EN = 0 (конец записи команды в LCD)
    _delay_us(100);
    PORTD |= (1 << EN); // EN = 1 (начало записи команды в LCD)
    PORTD &= 0x0F; PORTD |= (p << 4); // младший нибл
    _delay_us(100);
    PORTD &= ~(1 << EN); // EN = 0 (конец записи команды в LCD)
    _delay_us(100);
}
 
// Функция инициализации LCD
void lcd_init(void)
{
    _delay_ms(50); // Ожидание готовности ЖК-модуля
    
    // Конфигурирование четырехразрядного режима
    PORTD |= (1 << PD5);
    PORTD &= ~(1 << PD4);
    
    // Активизация четырехразрядного режима
    PORTD |= (1 << EN);
    PORTD &= ~(1 << EN);
    _delay_ms(5);
    
    lcd_com(0x28); // шина 4 бит, LCD - 2 строки
    lcd_com(0x08); // полное выключение дисплея
    lcd_com(0x01); // очистка дисплея
    _delay_us(100);
    lcd_com(0x06); // сдвиг курсора вправо
    lcd_com(0x0C); // включение дисплея, курсор не видим
}
 
// Функция вывода строки на LCD
void lcd_string(unsigned char command, char *string)
{
    lcd_com(0x0C);
    lcd_com(command);
    while(*string != '\0')
    {
        lcd_data(*string);
        string++;
    }
}
 
// Функция передачи данных по USART
void uart_send(char data)
{
    while(!( UCSRA & (1 << UDRE)));   // Ожидаем когда очистится буфер передачи
    UDR = data; // Помещаем данные в буфер, начинаем передачу
}
 
// Функция передачи строки по USART
void str_uart_send(char *string)
{
    while(*string != '\0')
    {
        uart_send(*string);
        string++;
    }
}
 
// Функция приема данных по USART
int uart_receive(void)
{
    while(!(UCSRA & (1 << RXC))); // Ожидаем, когда данные будут получены
    return UDR; // Читаем данные из буфера и возвращаем их при выходе из подпрограммы
}
 
// Функция инициализации USART
void uart_init(void)
{
    // Параметры соединения: 8 бит данные, 1 стоповый бит, нет контроля четности
    // USART Приемник: Включен
    // USART Передатчик: Включен
    // USART Режим: Асинхронный
    // USART Скорость обмена: 9600
    
    UBRRL = (F_CPU/BAUDRATE/16-1); // Вычисляем скорость обмена данными
    UBRRH = (F_CPU/BAUDRATE/16-1) >> 8;
    
    UCSRB |= (1 << RXCIE)| // Разрешаем прерывание по завершению приема данных
    (1 << RXEN)|(1 << TXEN); // Включаем приемник и передатчик
    
    UCSRC |= (1 << URSEL)| // Для доступа к регистру UCSRC выставляем бит URSEL
    (1 << UCSZ1)|(1 << UCSZ0); // Размер посылки в кадре 8 бит
}
 
// Прерывание по окончанию приема данных по USART
ISR(USART_RXC_vect)
{
    NUM = UDR; // Принимаем символ по USART
    byte_receive = 1;
    uart_send(NUM); // Посылаем символ по USART
    
    if(NUM == 'a') // Если принят символ "a", включаем светодиод
    PORTB |= (1 << PB0);
    if(NUM == 'b') // Если принят символ "b", выключаем светодиод
    PORTB &= ~(1 << PB0);
    if (NUM == L "02H0") //Считывание данных 
    lcd_data(NUM(NUM == 4) + L"\r\n");
    
}
 
// Главная функция
int main(void)
{
    DDRB |= (1 << PB0); // Светодиод
    PORTB = 0x00;
    
    DDRC  = 0x00;
    PORTC = 0xFF;
    
    DDRD  = 0b11111110;
    PORTD = 0x00;
    
    lcd_init(); // Инициализация LCD
    uart_init(); // Инициализация USART
    
    sei(); // Глобально разрешаем прерывания
    
    str_uart_send("Initialization system\r\n"); // Передаем строку по USART
    lcd_string(0x80, " SYSTEM STARTING! "); // Выводим строку на LCD
    _delay_ms(2500);
    lcd_com(0x01); // Очищаем LCD
    
    while(1)
    {
        
        if((PINC & (1 << PC0)) == 0) // Если нажата кнопка 1
        {
            while((PINC & (1 << PC0)) == 0){} // Ждем отпускания кнопки 1
            str_uart_send("Button 1 TEST\r\n"); // Передаем строку по USART
            lcd_string(0x80, "SYSTEM REBOOTING"); // Выводим строку на LCD
            PORTB = 0xFF;
            _delay_ms(1000);
            lcd_com(0x01); // Очищаем LCD
            PORTB = 0x00;
        }
        
        if((PINC & (1 << PC1)) == 0) // Если нажата кнопка 2
        {
            while((PINC & (1 << PC1)) == 0){} // Ждем отпускания кнопки 2
            str_uart_send("Button 2 TEST\r\n"); // Передаем строку по USART
            lcd_string(0x80, "Button 2 TEST"); // Выводим строку на LCD
            _delay_ms(1000);
            lcd_com(0x01); // Очищаем LCD
        }
        
        if((PINC & (1 << PC2)) == 0) // Если нажата кнопка 3
        {
            while((PINC & (1 << PC2)) == 0){} // Ждем отпускания кнопки 3
            str_uart_send("Button 3 TEST\r\n"); // Передаем строку по USART
            lcd_string(0x80, "Button 3 TEST"); // Выводим строку на LCD
            _delay_ms(1000);
            lcd_com(0x01); // Очищаем LCD
        }
        
        if(byte_receive)
        {
            byte_receive = 0;
            count++;
            lcd_data(NUM); // Выводим символ на LCD
            if(count > 8) // Если строка заполнена
            {
                count = 0;
                lcd_com(0x01); // Очищаем LCD
            }
        }
        
    }
}
Схема Proteus

Принять данные по UART, начиная с указанной позиции


Если мы получаем данные с компьютера в формате "ALLT0123". Последние 4 цифры постоянно меняются, статическими остаются только первые 4 символа. Каким образом можно отобразить на LCD только последние 4 цифры "0123"?
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
03.08.2018, 12:58
Ответы с готовыми решениями:

Как в симуляторе "принять" байт по UART?
Всем привет! Вопрос такого плана... Как в симуляторе студии &quot;принять&quot; байт по UART? Т.е. например...

Принять через uart байт и записать его в память
Вобщем, если верить преподавателю, этот код надо немного переделать для желаемого эффекта .device...

Дан текст. Замените в нем символы «:» на «.», начиная с указанной позиции
Дан текст. Замените в нем символы «:» на «.», начиная с указанной позиции. Пожалуйста...

Написать и протестировать функцию для замены символов ‘:’ на ‘.’ в заданной строке, начиная с указанной позиции
Написать и протестировать функцию для замены символов ‘:’ на ‘.’ в заданной строке, начиная с...

7
6557 / 2652 / 365
Регистрация: 17.02.2013
Сообщений: 3,884
04.08.2018, 11:31 2
Принять первый 4-е символа и потерять. Просто забыть про них. Принять последних 4-и и отобразить.
0
0 / 0 / 0
Регистрация: 21.03.2017
Сообщений: 24
04.08.2018, 13:04  [ТС] 3
На схеме всё показано как поступают данные. Так вот и пишу что с порта RS232 данные поступают в МК все 8 символов. А нужно чтобы на LCD отобразились только последние 4. Как можно организовать код так, чтобы он создавал условие, если в мк поступила телеграмма начиная с "ALLT", то отобразить на LCD последние 4 цифры "0123". Цифры могут меняться, поэтому такое условие подходящее.

Добавлено через 10 минут
Ethereal, в принципе так и есть
0
1576 / 809 / 146
Регистрация: 13.06.2015
Сообщений: 3,013
04.08.2018, 14:22 4
Цитата Сообщение от BIXTAR Посмотреть сообщение
Работаю в AtmelStudio 7
Вот сколько раз людям говорить - не работайте в атмелстудии, пока существует CVAVR. Создайте там проект с помощью мастера, и посмотрите какой код он сгенерирует в части буфера приёма UART. Вам нужен буфер на 8 символов, когда он заполнится - 4 последних символа выводим на LCD и очищаем буфер (тупо установкой указателя на начало и сбросом счётчика).
0
0 / 0 / 0
Регистрация: 21.03.2017
Сообщений: 24
04.08.2018, 14:40  [ТС] 5
Kukuxumushu, чем atmel отличается от code vision? По моему это два одинаковых языка, один не легче дргого
0
1576 / 809 / 146
Регистрация: 13.06.2015
Сообщений: 3,013
04.08.2018, 17:26 6
BIXTAR, тем, что в CVAVR огромная часть кода генерируется автоматически мастером (в некоторых проектах - до 90%) и имеется набор библиотек практически на все случаи жизни. В AtmelStudio абсолютно ВСЁ приходится прописывать руками, что вызывает море ошибок.
0
0 / 0 / 0
Регистрация: 21.03.2017
Сообщений: 24
04.08.2018, 20:09  [ТС] 7
Kukuxumushu, с какой версией cvavr посоветуешь работать ?
0
1576 / 809 / 146
Регистрация: 13.06.2015
Сообщений: 3,013
05.08.2018, 02:37 8
BIXTAR, у меня 3.12, а так наверное очевидно, что с самой последней.
0
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
05.08.2018, 02:37

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

Заменить символ двоеточия на символ точки в заданной строке, начиная с указанной позиции
Правильно ли я делаю задание: Составить и протестировать функцию для замены символа двоеточие на...

Прочитать данные из файла в матрицу с указанной позиции
&quot;дата 16.09.03 время 0:03:28 число точек 6144 частота 0616000 станция радиостация дискретность...

Удалить из исходного списка элементы, начиная с позиции K до позиции N
Удалить из исходного списка элементы, начиная с позиции K до позиции N

Указанный символ на указанной позиции
Есть текстовый файл каждая строка которого содержит некоторый текст. Доработать программу в...


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

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

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