Форум программистов, компьютерный форум, киберфорум
Микроконтроллеры ATmega AVR
Войти
Регистрация
Восстановить пароль
Карта форума Темы раздела Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.50/6: Рейтинг темы: голосов - 6, средняя оценка - 4.50
0 / 0 / 0
Регистрация: 13.04.2022
Сообщений: 24
1

Искажается массив структур!

25.05.2022, 17:48. Показов 1203. Ответов 7
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
Добрый день. Столкнулся с проблемой искажения массива структур mas_key_for_compare[]. Пишу в Atmel Studio. atmega 328.
В начале программы массив mas_key_for_compare[] заполняется из памяти EEprom. Далее с ним сравнивается считанный ключ.
После нескольких сравнений массив иногда обнуляется, иногда искажается???
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
#include "Signal_alarm.h"
 
 
#define STOP 100
#define Led_on  PORTD |=(1<<PIND7)
#define Led_off PORTD &=~(1<<PIND7)
 
volatile bool timer1_trick = false;
volatile uint8_t chanel_adc = 0;
volatile bool adc_go = true;
I_Button_key_type adc_Value;
uint16_t adc_count = 0;
volatile uint8_t adc_count_fake = 0;
volatile bool adc_value_ready = false;
uint8_t chanel_adc_mas[8]{0,0,0,0}; 
uint16_t ADC_sum = 0;   
 
uint8_t value_key_in_EEprom = 0;
 
 
I_Button_1990a my_button(&PORTD,PIND4);
ISR(USART_UDRE_vect)
{
    Usart_tx_handler_txq();
}
ISR(TIMER1_OVF_vect)
{
    timer1_trick = true;
}
ISR(USART_TX_vect)
{
    USART_TX_vect_ready();
    adc_go = true;
    
}
ISR(ADC_vect)
{
    PORTB |=(1<<PINB0);
    PORTB &=~(1<<PINB0);
    if(adc_count_fake>5)
    {
        adc_count++;
        ADC_sum += ADC>>2 ; 
        //adc_Value.key_code[adc_count-1] = ADC>>2;//
    
        if(adc_count >= 16)//8
        {
            adc_stop();
            adc_count_fake = 0;
            
            adc_count = 0;
            adc_value_ready = true;
            
            
            adc_Value.key_code[chanel_adc] =ADC_sum>>4;// //3 ADC_sum/8 
            ADC_sum = 0;
 
            adc_Value.read_Ok = chanel_adc;
            chanel_adc++;
            if(chanel_adc>=4)chanel_adc = 0;
            
        }
        
    }else
    {
        adc_count_fake++;
    }
}
bool check_key_eeprom(void)//Проверка памяти на наличие в ней ключей
{
    value_key_in_EEprom = EEPROM_read(0);// количество ключей в памяти
    if((value_key_in_EEprom==0xff)|(value_key_in_EEprom==0)) return false;
    else return true;
}
 
//unsigned char m[8]{1,193,128,203,1,0,0,1};
bool check_key_data(I_Button_key_type array[5])//Проверка на совпадение 5 захваченных ключей
{
    unsigned char rez = 0;
    unsigned char i = 0,j = 0;
    unsigned char number_key_kod = 0;
    
    while(number_key_kod<8)
    {
        i =0; j = 0;
        while(i<5)
        {
            j=i+1;
            while(j<5)
            {
                if(array[i].key_code[number_key_kod]==array[j].key_code[number_key_kod]){rez++;}
                j++;
            }
            i++;
        }
        number_key_kod ++;
    }
    if(rez==80)return true;
    else return false;
}
 
void add_key_in_EEPROM()//Добавление ключа в EEprom
{
    //Запись ключа в память моргаем ледом
    I_Button_key_type mas_key_for_write[5];
    //I_Button_key_type key_for_write;// = my_button.read_key();
    uint8_t n = 0;
    while(n<5)// пока не прочитаем все 5 вариантов ключа
    {
        Led_on;
        mas_key_for_write[n] = my_button.read_key();
        if(mas_key_for_write[n].read_Ok==1)n++;
        _delay_ms(100);
    }
    if(check_key_data(mas_key_for_write))
    {
        if(value_key_in_EEprom==0xff)
        {
            EEPROM_write(0,1);
            
        }else
        {
            EEPROM_write(0,value_key_in_EEprom + 1);
        }
        _delay_ms(25);
        value_key_in_EEprom = EEPROM_read(0);
        
        for(n = 0;n<8;n++)
        {
            EEPROM_write((value_key_in_EEprom-1)*10+10+n,mas_key_for_write[0].key_code[n]);
        }
        EEPROM_write((value_key_in_EEprom-1)*10+10+8,value_key_in_EEprom);
    }
}
 
bool compare_key_in_Eeprom(volatile I_Button_key_type *mas_key,uint8_t *max_index,I_Button_key_type *key)//
{//Проверка на наличие или отсутствие ключа в  Eeprom
    uint8_t number_key=0;
    uint8_t bit=0;
    uint8_t rez=0;
    volatile I_Button_key_type mas_temp[*max_index];    
    for(uint8_t number = 0;number<*max_index;number++)
    {
        for(uint8_t bit=0;bit<8;bit++)
        {
            mas_temp[number].key_code[bit] = mas_key[number].key_code[bit];
        }
    }
    for(number_key = 0; number_key < *max_index; number_key++)
    {
        for(bit = 0;bit<8; bit++)
        {
            if(mas_temp[number_key].key_code[bit] == key->key_code[bit])rez++;
        }
    }
    if(rez==8)return true;
    else return false;
}
int main(void)
{
    DDRB |=(1<<PINB0);//для отладки 
    DDRD |=(1<<PIND7);//для отладки
    
    asm("cli"); 
    Usart_ini(10);
    _delay_ms(1000);
    
    
    
        
    volatile I_Button_key_type mas_key_for_compare[value_key_in_EEprom];//Массив ключей, прочитанных из памяти. 
                                            //  В нем вся проблема!!! Начинают искажаться в нем данные,                  
    signed char count_event_add_keys = 0;   //  после  нескольких проверок!!!
    timer1_on_off(1);
 
    adc_ini();
    
    asm("sei");
 
    
     while(check_key_eeprom()==false)//если память пуста ждем пока не запишем ключ
      {
            add_key_in_EEPROM();
      }
    
//*********** Вычитываем еепром 
    uint16_t n_key_eeprom = 0;
    while(n_key_eeprom < value_key_in_EEprom)
    {
        for(unsigned char bit = 0;bit<8;bit++)
        {
            mas_key_for_compare[n_key_eeprom].key_code[bit] = EEPROM_read(bit+10); 
        }
        PORTB |=(1<<PINB0);
        n_key_eeprom++;
    }  
    //Проверка:
    while(n_key_eeprom <(uint16_t)value_key_in_EEprom*10+10 )
    {
        Usart_send_uint8_t(n_key_eeprom);
        _delay_ms(25);
        Usart_send_uint8_t(EEPROM_read(n_key_eeprom));
        _delay_ms(25);
        n_key_eeprom++;
    }
    _delay_ms(500);
    Usart_frame_txq(mas_key_for_compare);
    _delay_ms(500);
    Usart_frame_txq(mas_key_for_compare+1);
    _delay_ms(500);
    PORTB |=(1<<PINB0);
    
    
    
//************* 
    
    
    _delay_ms(50);
    while (1) 
    {   Led_off;
    
        if(timer1_trick)
        {
             
            
        
            I_Button_key_type tmp;
            tmp.read_Ok = 0;
            tmp = my_button.read_key();
            
            if(tmp.read_Ok==1)
            {
                
                unsigned char in = 1;
                I_Button_key_type key_tmp_array[5];//5  для анвлиза
                key_tmp_array[0] = tmp;  
                while(in<5)
                 {
                     key_tmp_array[in] = my_button.read_key();
                     in++;
                 }
                 
                 if (check_key_data(key_tmp_array))//проверка захваченных 5 ключей на равество
                 {                                 // то есть нет ошибки, все 5 одинаковые
                     
                    Usart_frame_txq(&tmp);
                    _delay_ms(2);
//                  Usart_frame_txq(mas_key_for_compare);
                    if(mas_key_for_compare[0].key_code[7] != 0x58){while(1){PORTB |=(1<<PINB0);PORTB &=~(1<<PINB0);}}//это для отладки анализатором
                    if(compare_key_in_Eeprom(mas_key_for_compare,&value_key_in_EEprom,&tmp))//проверка наличия ключа в памяти
                    {
                            Led_on; //открыть дверь
                    //Предположительно здесь происходит искажение массива структур ключей mas_key_for_compare[]
                    // когда полностью, когда частично.
 
                            
                            count_event_add_keys += 2;
                            if(count_event_add_keys > 13)//примерно удерживать 5 секунд для добавления нового ключа
                            {
                                
                                while((tmp.key_code[7] == my_button.read_key().key_code[7])&(tmp.key_code[3] == my_button.read_key().key_code[3]))
                                {
                                    //ожидаем пока уберем мастер ключ                 
                                }
                                _delay_ms(100);
                                
                                //проверить что добавляемый ключ отсутствует в памяти
                                //Добавить ключ
                                Led_on;
                                _delay_ms(3000);
                                count_event_add_keys = 0;
                            }
                            _delay_ms(100);
                    }
                    
                 }
                    
            }
            count_event_add_keys -= 1;
            if(count_event_add_keys < 0)count_event_add_keys = 0; 
            timer1_trick = false;
            if(adc_go)
            {
                adc_start(chanel_adc);
                adc_go = false;
            }
            
        }
        if (adc_value_ready)
        {
            adc_value_ready = false;
            Usart_frame_txq(&adc_Value);
        }
        
    }
}
Вложения
Тип файла: rar Signal_alarm.rar (93.5 Кб, 7 просмотров)
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
25.05.2022, 17:48
Ответы с готовыми решениями:

Почему искажается массив?
Вот такой фрагмент и результат его выполнения. Почему то искажается содержимое массива a после...

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

Структуры.Обработка массивов структур.Создать массив структур из 10-ти элементов
Создать массив структур из 10-ти элементов: &lt;Номер договора&gt;&lt;Фамилия клиента&gt;&lt;стоимость...

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

Массив структур, сохранение начала каждой из структур
Я создал такую структуру class Lancuch { public: char cos; Lancuch * nastepny; }; Lancuch...

7
фрилансер
5497 / 5093 / 1047
Регистрация: 11.10.2019
Сообщений: 13,337
25.05.2022, 19:45 2
Лучший ответ Сообщение было отмечено F_Serg_Kn как решение

Решение

Цитата Сообщение от F_Serg_Kn Посмотреть сообщение
volatile I_Button_key_type mas_key_for_compare[value_key_in_EEprom];
value_key_in_EEprom - должна быть константой времени компиляции. Сейчас это переменная

Добавлено через 1 минуту
и для чего этот массив сделан volatile ? Кто-то его будет менять снаружи ?
1
0 / 0 / 0
Регистрация: 13.04.2022
Сообщений: 24
25.05.2022, 20:29  [ТС] 3
Вы, правы, value_key_in_EEprom переменная количества ключей, считанных из памяти.Следовательно, число ключей равно разрядности массива. Данная переменная,как и массив ключей считывается из eeprom в начале main. Тем самым хотел сэкономить на массиве. Сейчас попробую сделать фикированный массив на 100 ключей. А каким образом данная трабла может влиять на искажение массива структур? Ведь, как я понимаю, любой массив передается по начальному адресу?

Добавлено через 1 минуту
Цитата Сообщение от Алексей1153 Посмотреть сообщение
и для чего этот массив сделан volatile ? Кто-то его будет менять снаружи ?
Тем самым пытался исправить баг, снаружи никто менять его не будет.Не помогло.

Добавлено через 14 минут
Исправил на volatile I_Button_key_type mas_key_for_compare[100]; и заработало, пока не вылетала. Только почему, так и не понял? Получается в МК нельзя использовать массивы переменной длины?
0
Модератор
Эксперт по электронике
8908 / 6677 / 918
Регистрация: 14.02.2011
Сообщений: 23,520
25.05.2022, 20:40 4
Цитата Сообщение от F_Serg_Kn Посмотреть сообщение
if((value_key_in_EEprom==0xff)|(value_key_in_EEprom==0))
вот здесь использоватся должна не бинарная ИЛИ(|) а логическая (||), дальше пока не смотрел
Цитата Сообщение от F_Serg_Kn Посмотреть сообщение
Далее с ним сравнивается считанный ключ.
После нескольких сравнений массив иногда обнуляется, иногда искажается???
Покажи кусок кода где происходит сравнение и желательно прокомментируй, пока по симптомам похоже на выход за границы массива
1
фрилансер
5497 / 5093 / 1047
Регистрация: 11.10.2019
Сообщений: 13,337
25.05.2022, 21:02 5
Лучший ответ Сообщение было отмечено F_Serg_Kn как решение

Решение

F_Serg_Kn, автоматические массивы не умеют быть переменного размера, их размер фиксированный и известен на этапе компиляции. То, что компилятор позволил указать в качестве размера переменную - это нестандартное расширение компилятора (VLA). И даже если компилятор это позволил, то размер такого массива всё равно будет равен значению той переменной на момент определения массива. То есть, размер всё равно будет неизменный. Если проследить глазами, то видно, что этот размер == 0. Точнее будет видно под отладчиком

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

Добавлено через 1 минуту
Цитата Сообщение от F_Serg_Kn Посмотреть сообщение
Получается в МК нельзя использовать массивы переменной длины
в ПК тоже
1
0 / 0 / 0
Регистрация: 13.04.2022
Сообщений: 24
25.05.2022, 21:21  [ТС] 6
Я так полагаю, одинарное или будет сравниваться доконца условия, а двойное ---выход по первому? Кстати, на проблемы мне уже указали в другой ветке. Нужно было использовать фиксированный массив ключей, вместо переменного.

Было:
C++
1
2
    uint8_t value_key_in_EEprom;
    volatile I_Button_key_type mas_key_for_compare[value_key_in_EEprom];
стало:
C++
1
    volatile I_Button_key_type mas_key_for_compare[100];
И все заработало,только почему я так и не понял???
0
0 / 0 / 0
Регистрация: 13.04.2022
Сообщений: 24
25.05.2022, 21:40  [ТС] 7
Алексей1153, Да, спасибо Вам за ответ. Сам бы век не додумал бы. Походу у меня весь код такой! Везде рассказывают как создать массив,класс, структуру, запустить таймер, шим, ацп на мелких отдельных примерах.А как использовать это все в комплексе в структуре программы не найдешь. А смотреть "настоящий код,профессиональный", там все для меня на "китайском" языке, каждую строчку можно весь вечер изучать. Еще раз спасибо Вам за обьяснение!!!
0
612 / 373 / 69
Регистрация: 21.09.2008
Сообщений: 1,277
28.05.2022, 06:28 8
Цитата Сообщение от F_Serg_Kn Посмотреть сообщение
Я так полагаю, одинарное или будет сравниваться доконца условия, а двойное ---выход по первому?
Нет.
10. Какое отличие между логическими операциями и поразрядными логическими операциями?

В логических операциях сравнивается значение двух операндов целиком. Каждый из операндов может иметь значение true или false. Язык C/C++ допускает сравнение операндов, которые являются целыми числами. В этом случае целочисленное значение 0 соответствует значению false, а ненулевое (любое другое) значение соответствует значению true.

Поразрядные логические операции работают строго с битами любого операнда. Бит может иметь 2 значения: 0 или 1. Поэтому, вычислению подлежат соответствующие биты каждого операнда а не значение операнда в целом.
Подробнее.

Цитата Сообщение от F_Serg_Kn Посмотреть сообщение
Нужно было использовать фиксированный массив ключей, вместо переменного.
И все заработало,только почему я так и не понял???
Такая возможность (массивы переменной длины, Variable-length arrays) появилась в С99. При сборке какой стандарт указывали?

Добавлено через 2 минуты
По С++ ответ здесь.

Добавлено через 7 минут
1
28.05.2022, 06:28
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
28.05.2022, 06:28
Помогаю со студенческими работами здесь

Динамический массив структур в другом массиве структур
Можно ли реализовать динамический (или статический) массив структур в другом массиве структур?...

Как объявить динамический массив структур, и как выглядит обращение к полям структур по указателю?
Ребята подскажите как объявить динамический массив структур, и как выглядит обращение к полям...

Массив структур в массиве структур
Всем добрый день. Делаю менюшку для управления и терзаю Arduino IDE слегка подвис со следующей...

Массив структур содержащих массив структур
Товарищи, подскажите пожалуйста. Есть вот такой класс: public class DATA { ...

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


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

Или воспользуйтесь поиском по форуму:
8
Ответ Создать тему
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru