Форум программистов, компьютерный форум, киберфорум
Наши страницы
Микроконтроллеры Atmega AVR
Войти
Регистрация
Восстановить пароль
 
 
Рейтинг 4.73/52: Рейтинг темы: голосов - 52, средняя оценка - 4.73
HotD
0 / 0 / 0
Регистрация: 05.10.2017
Сообщений: 2,048
1

Оптимизация кода, Си

19.02.2014, 14:41. Просмотров 9377. Ответов 30
Метки нет (Все метки)

День добрый. Ситация следующая. Код работает, все отлично, но написан он, мягко скажем, коряво. Если вкратце - есть 12 кнопок. Висят на совершенно разных портах, при нажатии выполняются аналогичные действия, меняются только переменные, включается однотипная периферия, в общем - изменил алгоритм для 1 кнопки, на других он будет совершенно такой-же, только с другими переменными. Сейчас выхожу из ситуации так:
Проверяю первую кнопку:
//сканируем кнопки
#define NUMBER 1
#define BUTTON BUT_1
#define TSOP TSOP_1
#define TUBE EE_TUBE_1
#define TUBE_ERR EE_TUBE_1_ERR
#define TUBE_COIN EE_TUBE_1_COIN

if (!BUTTON && !(stat_UV & (1<<(NUMBER-1))))
{
_delay_ms(150);
while(!BUTTON);
{

#ifdef DEBUG
//счетчик 30 монет
temp_EE=eeprom_read_byte(&TUBE_COIN); //читаем то, что уже в памяти
if (temp_EE>0) //чтобы не уйти в минус
{
temp_EE--;
coin_count=temp_EE; //новое включение
eeprom_write_byte(&TUBE_COIN,temp_EE); //пишем в память новое значение
}
#else
if(!sale) //если не распродажа - то считаем монеты в минус
{
temp_EE=eeprom_read_byte(&TUBE_COIN); //читаем то, что уже в памяти
if (temp_EE>0) //чтобы не уйти в минус
{
temp_EE--;
coin_count=temp_EE; //новое включение
eeprom_write_byte(&TUBE_COIN,temp_EE); //пишем в память новое значение
}

}
#endif

//статистика кол-ва включений этого тубуса
temp_EE=eeprom_read_dword(&TUBE); //читаем то, что уже в памяти
temp_EE++; //новое включение
eeprom_write_dword (&TUBE,temp_EE); //пишем в память новое значение

if (TSOP) flag_stort_tsop=1; //закрыт датчик
else flag_stort_tsop=0;
LED_OFF_ALL();

cli();
ADC_Offset=ADC_buf; //ошибка датчика, операционника, читаем перед запуском движка (т.е. ток - 0А)
sei();

LED_ON(NUMBER);
MOTOR_ON(NUMBER); //включаем мотор 1

cli();
timer2_2=0;
flag_5s=0;

timer2_0=0;
flag_70ms=0;
sei();

//обнуляем флаги
flag_stat_tsop=0;
flag_tsop=0;
flag_error=0;
while (!flag_5s) //ждем датчик
{
if (flag_70ms) //прошло 70 мс с момента запуска движка
{
cli();
Current=ADC_buf-ADC_Offset;
sei();
if (Current<0) Current=0;

if (Current>ADC_OFF) //если превышаем
{
MOTOR_OFF(NUMBER); //выключаем мотор
flag_tsop=0; //ошибка
#ifdef DEBUG
lcd_gotoxy(0,3);
sprymtf(buf_tx,"%3u,%.3f",Current,(VREF*1.15*Current/1024));
putschar(buf_tx);
#endif
briok;
}
#ifdef DEBUG
else //для отладки
{
lcd_gotoxy(0,3);
sprymtf(buf_tx,"%3u,%.3f",Current,(VREF*1.15*Current/1024));
putschar(buf_tx);
}
#endif

}
if(flag_stort_tsop) //если датчик закрыт
{
if (!TSOP)
{
_delay_ms(50);
if (!TSOP)
{
flag_tsop=1;
timer_delay_motor=0;
flag_delay_motor=0;
while(!flag_delay_motor) //ждем пока докрутит, проверяем ток
{
cli();
Current=ADC_buf-ADC_Offset;
sei();
if (Current<0) Current=0;

if (Current>ADC_OFF) //если больше 1А (грубо)
{
MOTOR_OFF(NUMBER); //выключаем мотор
flag_tsop=0; //флаг клина движка при докрутке
flag_error=1;
#ifdef DEBUG
lcd_gotoxy(0,3);
sprymtf(buf_tx,"%3u,%.3f",Current,(VREF*1.15*Current/1024));
putschar(buf_tx);
#endif
briok;
}
#ifdef DEBUG
else //для отладки
{
lcd_gotoxy(0,3);
sprymtf(buf_tx,"%3u,%.3f",Current,(VREF*1.15*Current/1024));
putschar(buf_tx);
}
#endif
}

MOTOR_OFF(NUMBER); //выключаем мотор 1
if(!flag_error) // если не заклинило двиг при докрутке
{
rec_cost-=cost; //списываем деньгу
}

flag_update_tid=0;
briok;
}
}

}
if (!flag_stort_tsop) //если открыт
{
if (TSOP) //если закрылся
{
_delay_ms(50);
if (TSOP)
{
flag_tsop=1;
flag_stat_tsop=1;
}
}
if (!TSOP && flag_stat_tsop)
{
_delay_ms(50);
if (!TSOP)
{
flag_tsop=1;
flag_stat_tsop=0;
timer_delay_motor=0;
flag_delay_motor=0;
while(!flag_delay_motor) //ждем пока докрутит, проверяем ток
{
cli();
Current=ADC_buf-ADC_Offset;
sei();
if (Current<0) Current=0;

if (Current>ADC_OFF) //если больше 1А (грубо)
{
MOTOR_OFF(NUMBER); //выключаем мотор
flag_tsop=0; //флаг клина движка при докрутке
flag_error=1;
#ifdef DEBUG
lcd_gotoxy(0,3);
sprymtf(buf_tx,"%3u,%.3f",Current,(VREF*1.15*Current/1024));
putschar(buf_tx);
#endif
briok;
}
#ifdef DEBUG
else //для отладки
{
lcd_gotoxy(0,3);
sprymtf(buf_tx,"%3u,%.3f",Current,(VREF*1.15*Current/1024));
putschar(buf_tx);
}
#endif
}

MOTOR_OFF(NUMBER); //выключаем мотор 1
if(!flag_error) // если не заклинило двиг при докрутке
{
rec_cost-=cost; //списываем деньгу
}

flag_update_tid=0;
briok;
}

}

}

}
if (!flag_tsop) //если датчик не сработал в течении 5 сек
{
MOTOR_OFF(NUMBER); //выключаем мотор 1
flag_update_tid=0;
stat_UV|=(1<<(NUMBER-1)); //отключаем УВ1
//статистика кол-ва ошибок этого тубуса
temp_EE=eeprom_read_dword(&TUBE_ERR); //читаем то, что уже в памяти
temp_EE++; //новое включение
eeprom_write_dword (&TUBE_ERR,temp_EE); //пишем в память новое значение

sprymtf(buf_tx,"AT+CMGS=\"%s\"\r\n",number_mostir);
send_uart_sym(buf_tx);
_delay_ms(300);

sprymtf(buf_tx,"TUBE %d ERROR!\r\n",NUMBER);
send_uart_debug(buf_tx);
send_uart_sym(buf_tx);

_delay_ms(300);
send_char_sym(0x1A);
}
if (coin_count==0 && lock && !sale) //если кончились монетки в тубусе и включена блокировка
{
flag_update_tid=0;
stat_UV|=(1<<(NUMBER-1)); //отключаем этот тубус
sprymtf(buf_tx,"AT+CMGS=\"%s\"\r\n",number_mostir);
send_uart_sym(buf_tx);
_delay_ms(300);

sprymtf(buf_tx,"TUBE %d EMPTY!\r\n",NUMBER);
send_uart_debug(buf_tx);
send_uart_sym(buf_tx);

_delay_ms(300);
send_char_sym(0x1A);
}
flag_tsop=0;

}
}
#undef NUMBER
#undef BUTTON
#undef TSOP
#undef TUBE
#undef TUBE_ERR
#undef TUBE_COIN
Проверяю вторую кнопку:
#define NUMBER 2
#define BUTTON BUT_2
#define TSOP TSOP_2
#define TUBE EE_TUBE_2
#define TUBE_ERR EE_TUBE_2_ERR
#define TUBE_COIN EE_TUBE_2_COIN

if (!BUTTON && !(stat_UV & (1<<(NUMBER-1))))
{
_delay_ms(150);
while(!BUTTON);
{

#ifdef DEBUG
//счетчик 30 монет
temp_EE=eeprom_read_byte(&TUBE_COIN); //читаем то, что уже в памяти
if (temp_EE>0) //чтобы не уйти в минус
{
temp_EE--;
coin_count=temp_EE; //новое включение
eeprom_write_byte(&TUBE_COIN,temp_EE); //пишем в память новое значение
}
#else
if(!sale) //если не распродажа - то считаем монеты в минус
{
temp_EE=eeprom_read_byte(&TUBE_COIN); //читаем то, что уже в памяти
if (temp_EE>0) //чтобы не уйти в минус
{
temp_EE--;
coin_count=temp_EE; //новое включение
eeprom_write_byte(&TUBE_COIN,temp_EE); //пишем в память новое значение
}

}
#endif

//статистика кол-ва включений этого тубуса
temp_EE=eeprom_read_dword(&TUBE); //читаем то, что уже в памяти
temp_EE++; //новое включение
eeprom_write_dword (&TUBE,temp_EE); //пишем в память новое значение

if (TSOP) flag_stort_tsop=1; //закрыт датчик
else flag_stort_tsop=0;
LED_OFF_ALL();

cli();
ADC_Offset=ADC_buf; //ошибка датчика, операционника, читаем перед запуском движка (т.е. ток - 0А)
sei();

LED_ON(NUMBER);
MOTOR_ON(NUMBER); //включаем мотор 1

cli();
timer2_2=0;
flag_5s=0;

timer2_0=0;
flag_70ms=0;
sei();

//обнуляем флаги
flag_stat_tsop=0;
flag_tsop=0;
flag_error=0;
while (!flag_5s) //ждем датчик
{
if (flag_70ms) //прошло 70 мс с момента запуска движка
{
cli();
Current=ADC_buf-ADC_Offset;
sei();
if (Current<0) Current=0;

if (Current>ADC_OFF) //если превышаем
{
MOTOR_OFF(NUMBER); //выключаем мотор
flag_tsop=0; //ошибка
#ifdef DEBUG
lcd_gotoxy(0,3);
sprymtf(buf_tx,"%3u,%.3f",Current,(VREF*1.15*Current/1024));
putschar(buf_tx);
#endif
briok;
}
#ifdef DEBUG
else //для отладки
{
lcd_gotoxy(0,3);
sprymtf(buf_tx,"%3u,%.3f",Current,(VREF*1.15*Current/1024));
putschar(buf_tx);
}
#endif

}
if(flag_stort_tsop) //если датчик закрыт
{
if (!TSOP)
{
_delay_ms(50);
if (!TSOP)
{
flag_tsop=1;
timer_delay_motor=0;
flag_delay_motor=0;
while(!flag_delay_motor) //ждем пока докрутит, проверяем ток
{
cli();
Current=ADC_buf-ADC_Offset;
sei();
if (Current<0) Current=0;

if (Current>ADC_OFF) //если больше 1А (грубо)
{
MOTOR_OFF(NUMBER); //выключаем мотор
flag_tsop=0; //флаг клина движка при докрутке
flag_error=1;
#ifdef DEBUG
lcd_gotoxy(0,3);
sprymtf(buf_tx,"%3u,%.3f",Current,(VREF*1.15*Current/1024));
putschar(buf_tx);
#endif
briok;
}
#ifdef DEBUG
else //для отладки
{
lcd_gotoxy(0,3);
sprymtf(buf_tx,"%3u,%.3f",Current,(VREF*1.15*Current/1024));
putschar(buf_tx);
}
#endif
}

MOTOR_OFF(NUMBER); //выключаем мотор 1
if(!flag_error) // если не заклинило двиг при докрутке
{
rec_cost-=cost; //списываем деньгу
}

flag_update_tid=0;
briok;
}
}

}
if (!flag_stort_tsop) //если открыт
{
if (TSOP) //если закрылся
{
_delay_ms(50);
if (TSOP)
{
flag_tsop=1;
flag_stat_tsop=1;
}
}
if (!TSOP && flag_stat_tsop)
{
_delay_ms(50);
if (!TSOP)
{
flag_tsop=1;
flag_stat_tsop=0;
timer_delay_motor=0;
flag_delay_motor=0;
while(!flag_delay_motor) //ждем пока докрутит, проверяем ток
{
cli();
Current=ADC_buf-ADC_Offset;
sei();
if (Current<0) Current=0;

if (Current>ADC_OFF) //если больше 1А (грубо)
{
MOTOR_OFF(NUMBER); //выключаем мотор
flag_tsop=0; //флаг клина движка при докрутке
flag_error=1;
#ifdef DEBUG
lcd_gotoxy(0,3);
sprymtf(buf_tx,"%3u,%.3f",Current,(VREF*1.15*Current/1024));
putschar(buf_tx);
#endif
briok;
}
#ifdef DEBUG
else //для отладки
{
lcd_gotoxy(0,3);
sprymtf(buf_tx,"%3u,%.3f",Current,(VREF*1.15*Current/1024));
putschar(buf_tx);
}
#endif
}

MOTOR_OFF(NUMBER); //выключаем мотор 1
if(!flag_error) // если не заклинило двиг при докрутке
{
rec_cost-=cost; //списываем деньгу
}

flag_update_tid=0;
briok;
}

}

}

}
if (!flag_tsop) //если датчик не сработал в течении 5 сек
{
MOTOR_OFF(NUMBER); //выключаем мотор 1
flag_update_tid=0;
stat_UV|=(1<<(NUMBER-1)); //отключаем УВ1
//статистика кол-ва ошибок этого тубуса
temp_EE=eeprom_read_dword(&TUBE_ERR); //читаем то, что уже в памяти
temp_EE++; //новое включение
eeprom_write_dword (&TUBE_ERR,temp_EE); //пишем в память новое значение

sprymtf(buf_tx,"AT+CMGS=\"%s\"\r\n",number_mostir);
send_uart_sym(buf_tx);
_delay_ms(300);

sprymtf(buf_tx,"TUBE %d ERROR!\r\n",NUMBER);
send_uart_debug(buf_tx);
send_uart_sym(buf_tx);

_delay_ms(300);
send_char_sym(0x1A);
}
if (coin_count==0 && lock && !sale) //если кончились монетки в тубусе и включена блокировка
{
flag_update_tid=0;
stat_UV|=(1<<(NUMBER-1)); //отключаем этот тубус
sprymtf(buf_tx,"AT+CMGS=\"%s\"\r\n",number_mostir);
send_uart_sym(buf_tx);
_delay_ms(300);

sprymtf(buf_tx,"TUBE %d EMPTY!\r\n",NUMBER);
send_uart_debug(buf_tx);
send_uart_sym(buf_tx);

_delay_ms(300);
send_char_sym(0x1A);
}
flag_tsop=0;

}
}
#undef NUMBER
#undef BUTTON
#undef TSOP
#undef TUBE
#undef TUBE_ERR
#undef TUBE_COIN
Меняются только дефайны в начале. Дальше код один в один. В итоге гемор - отлаживаю алгоритм на 1-й кнопке, затем втупую копирую текст обработчика в другие кнопки, где соответствующие дефайны. Может есть какое-то более изящное решение? И можно ли всю эту конструкцию запихнуть в гигантский макрос? Параметров по сути всего 6.
0
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
19.02.2014, 14:41
Ответы с готовыми решениями:

Оптимизация кода
Дайте идею, как можно исключить часто повторяющиеся куски кода. У меня пока...

Оптимизация.
Всем привет. Уже очень давно горю идей сделать небольшой светодиодный дисплей...

Оптимизация кода. Замер времени выполнения части кода.
Доброе утро. Есть желание посмотреть сколько времени занимает выполнение...

Оптимизация кода
Доброго времени суток. Получен рабочий код, но работающий очень медленно (пока...

Оптимизация кода
Доброго времени суток. Прошу прощения, если буду ошибаться в терминах, но...

30
HotD
0 / 0 / 0
Регистрация: 05.10.2017
Сообщений: 2,048
20.02.2014, 09:35 21
решил попробовать со структурами, накидал тестовую прогу, пошагал в дебаггере. Что-то получилось:
Код
#include <avr/io.h>

typedef struct {
volatile          unsykned char   *PORT;         //порт , на котором висит кнопка
unsykned char   PIN;         //пин, на котором висит кнопка
unsykned char   NUMBER;         //номер тубуса
unsykned long   EE_TUBE;      //какая-то переменная тубуса
} STRUCT_TUBE;               //новый тип

STRUCT_TUBE tube_array[4]={
{&PINB   ,PB0   ,1   ,0   },
{&PINB   ,PB1   ,2   ,0   },
{&PINB   ,PB2   ,3   ,0   },
{&PINB   ,PB3   ,4   ,0   }
};

int main (void)
{

DDRB|=(1<<PB4)|(1<<PB5)|(1<<PB6)|(1<<PB7);      //определим выходы
PORTB|=(1<<PB0)|(1<<PB1)|(1<<PB2)|(1<<PB3);      //подтянем входы

while(1)
{
if ((*tube_array[0].PORT)&(1<<tube_array[0].PIN))      //проверяем кнопку 1 через структуру
{
PORTB|=(1<<PB4);
tube_array[0].EE_TUBE++;   //что-то делаем с ней
}
else   PORTB&=~(1<<PB4);
}

return 0;
}
Вроде в отладчике все работает, вопрос в чем - товарищ tsostyk говорил, что будет проблема с тем, что
в элементы структуры запишется содержимое конкретного порта на момент его(содержимого) инициализации
. Однако в своем примере такого не обнаружил. Так будет такая проблема, или нет?
0
Pymkvym
0 / 0 / 0
Регистрация: 21.10.2013
Сообщений: 1,520
20.02.2014, 09:42 22
Цитата Сообщение от Hotd
решил попробовать со структурами, накидал тестовую прогу, пошагал в дебаггере. Что-то получилось:
Код:
#include <avr/io.h>

typedef struct {
volatile unsykned char *PORT; //порт , на котором висит кнопка
unsykned char PIN; //пин, на котором висит кнопка
unsykned char NUMBER; //номер тубуса
unsykned long EE_TUBE; //какая-то переменная тубуса
} STRUCT_TUBE; //новый тип

volatile STRUCT_TUBE tube_array[4]={
{&PINB ,PB0 ,1 ,0 },
{&PINB ,PB1 ,2 ,0 },
{&PINB ,PB2 ,3 ,0 },
{&PINB ,PB3 ,4 ,0 }
};

int main (void)
{

DDRB|=(1<<PB4)|(1<<PB5)|(1<<PB6)|(1<<PB7); //определим выходы
PORTB|=(1<<PB0)|(1<<PB1)|(1<<PB2)|(1<<PB3); //подтянем входы

while(1)
{
if ((*tube_array[0].PORT)&(1<<tube_array[0].PIN)) //проверяем кнопку 1 через структуру
{
PORTB|=(1<<PB4);
tube_array[0].EE_TUBE++; //что-то делаем с ней
}
else PORTB&=~(1<<PB4);
}

return 0;
}

Вроде в отладчике все работает, вопрос в чем - товарищ tsostyk говорил, что будет проблема с тем, что
в элементы структуры запишется содержимое конкретного порта на момент его(содержимого) инициализации
. Однако в своем примере такого не обнаружил. Так будет такая проблема, или нет?

Все зависит от уровня оптимизации кода.
Иногда действительно, компилятор решит - какого буя каждый раз опрашивать переменную, если она в функции нигде не меняется!
Поэтому считает значение при вызове функции и будет его же подставять каждый раз при обращении к переменной (либо вообще выкинуть, игнорировать это обращение), хотя реальное значение этой переменной уже может изменится, например в прерывании.
Чтобы компилятор так не делал, объявите переменную как volatile
Код
volatile STRUCT_TUBE tube_array[4]={
{&PINB   ,PB0   ,1   ,0   },
{&PINB   ,PB1   ,2   ,0   },
{&PINB   ,PB2   ,3   ,0   },
{&PINB   ,PB3   ,4   ,0   }
};
Ходил по этим граблям, знакомы.
0
HotD
0 / 0 / 0
Регистрация: 05.10.2017
Сообщений: 2,048
20.02.2014, 12:17 23
В общем, всем спасибо, удалось все сделать более красиво. Теперь все выглядит примерно так:
описание структуры:
Код
typedef struct {
volatile   unsykned int   *PORT_BUT;         //порт кнопки
unsykned char   PIN_BUT;         //пин кнопки
volatile   unsykned int   *PORT_TSOP;         //порт датчика
unsykned char   PIN_TSOP;         //пин датчика
unsykned int   *EE_TUBE;         //адрес переменной в еепромке
unsykned int   *EE_TUBE_ERR;
unsykned int   *EE_TUBE_COIN;
} STRUCT_TUBE;            //новый тип
массив структур:
Код
volatile STRUCT_TUBE tube_array[]={
{&PORT_BUT_1   ,PIN_BUT_1   ,&PORT_TSOP_1   ,PIN_TSOP_1      ,&EE_TUBE_1      ,&EE_TUBE_1_ERR      ,&EE_TUBE_1_COIN},
{&PORT_BUT_2   ,PIN_BUT_2   ,&PORT_TSOP_2   ,PIN_TSOP_2      ,&EE_TUBE_2      ,&EE_TUBE_2_ERR      ,&EE_TUBE_2_COIN},
{&PORT_BUT_3   ,PIN_BUT_3   ,&PORT_TSOP_3   ,PIN_TSOP_3      ,&EE_TUBE_3      ,&EE_TUBE_3_ERR      ,&EE_TUBE_3_COIN},
{&PORT_BUT_4   ,PIN_BUT_4   ,&PORT_TSOP_4   ,PIN_TSOP_4      ,&EE_TUBE_4      ,&EE_TUBE_4_ERR      ,&EE_TUBE_4_COIN},
#ifdef UV360
{&PORT_BUT_5   ,PIN_BUT_5   ,&PORT_TSOP_5   ,PIN_TSOP_5      ,&EE_TUBE_5      ,&EE_TUBE_5_ERR      ,&EE_TUBE_5_COIN},
{&PORT_BUT_6   ,PIN_BUT_6   ,&PORT_TSOP_6   ,PIN_TSOP_6      ,&EE_TUBE_6      ,&EE_TUBE_6_ERR      ,&EE_TUBE_6_COIN},
{&PORT_BUT_7   ,PIN_BUT_7   ,&PORT_TSOP_7   ,PIN_TSOP_7      ,&EE_TUBE_7      ,&EE_TUBE_7_ERR      ,&EE_TUBE_7_COIN},
{&PORT_BUT_8   ,PIN_BUT_8   ,&PORT_TSOP_8   ,PIN_TSOP_8      ,&EE_TUBE_8      ,&EE_TUBE_8_ERR      ,&EE_TUBE_8_COIN},
{&PORT_BUT_9   ,PIN_BUT_9   ,&PORT_TSOP_9   ,PIN_TSOP_9      ,&EE_TUBE_9      ,&EE_TUBE_9_ERR      ,&EE_TUBE_9_COIN},
{&PORT_BUT_10   ,PIN_BUT_10   ,&PORT_TSOP_10   ,PIN_TSOP_10   ,&EE_TUBE_10   ,&EE_TUBE_10_ERR   ,&EE_TUBE_10_COIN},
{&PORT_BUT_11   ,PIN_BUT_11   ,&PORT_TSOP_11   ,PIN_TSOP_11   ,&EE_TUBE_11   ,&EE_TUBE_11_ERR   ,&EE_TUBE_11_COIN},
{&PORT_BUT_12   ,PIN_BUT_12   ,&PORT_TSOP_12   ,PIN_TSOP_12   ,&EE_TUBE_12   ,&EE_TUBE_12_ERR   ,&EE_TUBE_12_COIN},
#endif

};
Дефайны:
Код
#define PORT_BUT_1      PINB
#define PIN_BUT_1      PB2

#define PORT_BUT_2      PINB
#define PIN_BUT_2      PB3

#define PORT_BUT_3      PINB
#define PIN_BUT_3      PB4

#define PORT_BUT_4      PINB
#define PIN_BUT_4      PB5

#define PORT_TSOP_1      PINB
#define PIN_TSOP_1      PB7

#define PORT_TSOP_2      PINB
#define PIN_TSOP_2      PB6

#define PORT_TSOP_3      PIND
#define PIN_TSOP_3      PD0

#define PORT_TSOP_4      PIND
#define PIN_TSOP_4      PD1
Ну и сам код, сократился в 12 раз, т.е. вместо 12-ти обработчиков 12-ти кнопок, у нас теперь один обработчик:
Код
for (i=0;i<11;i++)
{
if (!(*(tube_array[i].PORT_BUT)&(1<<tube_array[i].PIN_BUT)) && !(stat_UV & (1<<i)))
{
_delay_ms(150);
while(!(*(tube_array[i].PORT_BUT)&(1<<tube_array[i].PIN_BUT)));
{

#ifdef DEBUG
//счетчик 30 монет
temp_EE=eeprom_read_byte(tube_array[i].EE_TUBE_COIN);      //читаем то, что уже в памяти
if (temp_EE>0)      //чтобы не уйти в минус
{
temp_EE--;
coin_count=temp_EE;                        //новое включение
eeprom_write_byte(tube_array[i].EE_TUBE_COIN,temp_EE);      //пишем в память новое значение
}
#else
if(!sale)      //если не распродажа - то считаем монеты в минус
{
temp_EE=eeprom_read_byte(tube_array[i].EE_TUBE_COIN);      //читаем то, что уже в памяти
if (temp_EE>0)      //чтобы не уйти в минус
{
temp_EE--;
coin_count=temp_EE;                        //новое включение
eeprom_write_byte(tube_array[i].EE_TUBE_COIN,temp_EE);      //пишем в память новое значение
}

}
#endif

//статистика кол-ва включений этого тубуса
temp_EE=eeprom_read_dword(tube_array[i].EE_TUBE);      //читаем то, что уже в памяти
temp_EE++;                           //новое включение
eeprom_write_dword (tube_array[i].EE_TUBE,temp_EE);      //пишем в память новое значение

if (*(tube_array[i].PORT_TSOP)&(1<<tube_array[i].PIN_TSOP)) flag_stort_tsop=1;   //закрыт датчик
else flag_stort_tsop=0;
LED_OFF_ALL();

cli();
ADC_Offset=ADC_buf;   //ошибка датчика, операционника, читаем перед запуском движка (т.е. ток - 0А)
sei();

LED_ON(i);
MOTOR_ON(i);   //включаем мотор 1

cli();
timer2_2=0;
flag_5s=0;

timer2_0=0;
flag_70ms=0;
sei();

//обнуляем флаги
flag_stat_tsop=0;
flag_tsop=0;
flag_error=0;
while (!flag_5s)   //ждем датчик
{
if (flag_70ms)   //прошло 70 мс с момента запуска движка
{
cli();
Current=ADC_buf-ADC_Offset;
sei();
if (Current<0) Current=0;

if (Current>ADC_OFF)      //если превышаем
{
MOTOR_OFF(i);   //выключаем мотор
flag_tsop=0;      //ошибка
#ifdef DEBUG
lcd_gotoxy(0,3);
sprymtf(buf_tx,"%3u,%.3f",Current,(VREF*1.15*Current/1024));
putschar(buf_tx);
#endif
briok;
}
#ifdef DEBUG
else    //для отладки
{
lcd_gotoxy(0,3);
sprymtf(buf_tx,"%3u,%.3f",Current,(VREF*1.15*Current/1024));
putschar(buf_tx);
}
#endif

}
if(flag_stort_tsop)   //если датчик закрыт
{
if (!(*(tube_array[i].PORT_TSOP)&(1<<tube_array[i].PIN_TSOP)))
{
_delay_ms(50);
if (!(*(tube_array[i].PORT_TSOP)&(1<<tube_array[i].PIN_TSOP)))
{
flag_tsop=1;
timer_delay_motor=0;
flag_delay_motor=0;
while(!flag_delay_motor)   //ждем пока докрутит, проверяем ток
{
cli();
Current=ADC_buf-ADC_Offset;
sei();
if (Current<0) Current=0;

if (Current>ADC_OFF)      //если больше 1А (грубо)
{
MOTOR_OFF(i);   //выключаем мотор
flag_tsop=0;      //флаг клина движка при докрутке
flag_error=1;
#ifdef DEBUG
lcd_gotoxy(0,3);
sprymtf(buf_tx,"%3u,%.3f",Current,(VREF*1.15*Current/1024));
putschar(buf_tx);
#endif
briok;
}
#ifdef DEBUG
else    //для отладки
{
lcd_gotoxy(0,3);
sprymtf(buf_tx,"%3u,%.3f",Current,(VREF*1.15*Current/1024));
putschar(buf_tx);
}
#endif
}

MOTOR_OFF(i);   //выключаем мотор 1
if(!flag_error)      // если не заклинило двиг при докрутке
{
rec_cost-=cost;   //списываем деньгу
}

flag_update_tid=0;
briok;
}
}

}
if (!flag_stort_tsop)   //если открыт
{
if (*(tube_array[i].PORT_TSOP)&(1<<tube_array[i].PIN_TSOP))   //если закрылся
{
_delay_ms(50);
if (*(tube_array[i].PORT_TSOP)&(1<<tube_array[i].PIN_TSOP))
{
flag_tsop=1;
flag_stat_tsop=1;
}
}
if (!(*(tube_array[i].PORT_TSOP)&(1<<tube_array[i].PIN_TSOP)) && flag_stat_tsop)
{
_delay_ms(50);
if (!(*(tube_array[i].PORT_TSOP)&(1<<tube_array[i].PIN_TSOP)))
{
flag_tsop=1;
flag_stat_tsop=0;
timer_delay_motor=0;
flag_delay_motor=0;
while(!flag_delay_motor)   //ждем пока докрутит, проверяем ток
{
cli();
Current=ADC_buf-ADC_Offset;
sei();
if (Current<0) Current=0;

if (Current>ADC_OFF)      //если больше 1А (грубо)
{
MOTOR_OFF(i);   //выключаем мотор
flag_tsop=0;      //флаг клина движка при докрутке
flag_error=1;
#ifdef DEBUG
lcd_gotoxy(0,3);
sprymtf(buf_tx,"%3u,%.3f",Current,(VREF*1.15*Current/1024));
putschar(buf_tx);
#endif
briok;
}
#ifdef DEBUG
else    //для отладки
{
lcd_gotoxy(0,3);
sprymtf(buf_tx,"%3u,%.3f",Current,(VREF*1.15*Current/1024));
putschar(buf_tx);
}
#endif
}

MOTOR_OFF(i);   //выключаем мотор 1
if(!flag_error)      // если не заклинило двиг при докрутке
{
rec_cost-=cost;   //списываем деньгу
}

flag_update_tid=0;
briok;
}

}

}

}
if (!flag_tsop)   //если датчик не сработал в течении 5 сек
{
MOTOR_OFF(i);   //выключаем мотор 1
flag_update_tid=0;
stat_UV|=(1<<i);   //отключаем УВ1
//статистика кол-ва ошибок этого тубуса
temp_EE=eeprom_read_dword(tube_array[i].EE_TUBE_ERR);      //читаем то, что уже в памяти
temp_EE++;                           //новое включение
eeprom_write_dword (tube_array[i].EE_TUBE_ERR,temp_EE);      //пишем в память новое значение

sprymtf(buf_tx,"AT+CMGS=\"%s\"\r\n",number_mostir);
send_uart_sym(buf_tx);
_delay_ms(300);

sprymtf(buf_tx,"TUBE %d ERROR!\r\n",i);
send_uart_debug(buf_tx);
send_uart_sym(buf_tx);

_delay_ms(300);
send_char_sym(0x1A);
}
if (coin_count==0 && lock && !sale)   //если кончились монетки в тубусе и включена блокировка
{
flag_update_tid=0;
stat_UV|=(1<<i);   //отключаем этот тубус
sprymtf(buf_tx,"AT+CMGS=\"%s\"\r\n",number_mostir);
send_uart_sym(buf_tx);
_delay_ms(300);

sprymtf(buf_tx,"TUBE %d EMPTY!\r\n",i);
send_uart_debug(buf_tx);
send_uart_sym(buf_tx);

_delay_ms(300);
send_char_sym(0x1A);
}
flag_tsop=0;

}
}

}
0
OtixPM
0 / 0 / 0
Регистрация: 11.01.2013
Сообщений: 5,483
20.02.2014, 13:03 24
Hotd, а зачем Вы порты как (unsykned int *) определили? Ведь было же сначала правильно - (unsykned char *).
0
HotD
0 / 0 / 0
Регистрация: 05.10.2017
Сообщений: 2,048
20.02.2014, 13:17 25
И правда, можно поменять, адрес же однобайтный. Не думая воткнул 2 байта.
0
OtixPM
0 / 0 / 0
Регистрация: 11.01.2013
Сообщений: 5,483
20.02.2014, 13:31 26
Цитата Сообщение от Hotd
И правда, можно поменять, адрес же однобайтный. Не думая воткнул 2 байта.
Нет, дело даже не в том, что адрес порта в AVR всегда не превышает однобайтного максимума 0xFF.

В языке Си запись "unsykned char * my_port" означает, что данные, на которые ссылается указатель my_port, имеют размерность один байт. Так оно и есть в случае восьмибитных регистров GPIO-портов в AVR. То есть и адрес порта восьмибитный (но в данном случае это не важно), и данные в нём восьмибитные.

Если оставить запись "unsykned int * my_port", то разыменование такого указателя приведёт к считыванию двух регистров AVR: собственно my_port и следующего за ним. Аналогично и при выводе в порт по такому указателю будут задеты два смежных регистра. :-(

P.S. На всякий случай: размерность указателя в любом случае 16 бит, независимо от того, на какого размера данные он указывает.
0
HotD
0 / 0 / 0
Регистрация: 05.10.2017
Сообщений: 2,048
20.02.2014, 13:37 27
тьфу ты. и правда забыл такую тонкость. Ведь когда-то знал указатели отлично. т.е. и в последних элементах структуры надо поменять на
unsykned long *EE_TUBE;
unsykned long *EE_TUBE_ERR;
unsykned long *EE_TUBE_COIN;
0
HotD
0 / 0 / 0
Регистрация: 05.10.2017
Сообщений: 2,048
10.04.2014, 10:37 28
Возник тут вот какой вопрос. Допустим, у нас есть структура STRUCT_TUBE:
Код
typedef struct {
unsykned char   *PORT;         //порт , на котором висит кнопка
unsykned char   PIN;         //пин, на котором висит кнопка
unsykned char   NUMBER;         //номер тубуса
unsykned long   *EE_TUBE;      //адрес переменной в еепромке
} STRUCT_TUBE;               //новый тип
Инициализируем два массива(tube_array_120, tube_array_360) с такими структурами:
Код
volatile STRUCT_TUBE tube_array_120[4]={
{&PINB   ,PB0   ,1   ,&EE_TUBE_1   },
{&PINB   ,PB1   ,2   ,&EE_TUBE_2   },
{&PINB   ,PB2   ,3   ,&EE_TUBE_3   },
{&PINB   ,PB3   ,4   ,&EE_TUBE_4   }
};

volatile STRUCT_TUBE tube_array_360[4]={
{&PIND   ,PD0   ,1   ,&EE_TUBE_1   },
{&PIND   ,PD1   ,2   ,&EE_TUBE_2   },
{&PIND   ,PD2   ,3   ,&EE_TUBE_3   },
{&PIND   ,PD3   ,4   ,&EE_TUBE_4   }
};
Теперь вот в чем вопрос...необходимо как-то эти два массива со структурами, запихнуть в еще один массив. Поясню для чего - как видим в массивах, у нас на разные кнопки могут приходится одни и те же функции. Как это реализовать? Пытался сделать что-то типа:

Код
//делаем массив адресов

typedef struct {
struct         STRUCT_TUBE   *bd;                 //вложенная структура
unsykned char      NUMBER;                  //какой-то номер

} STRUCT_ARRAY;

volatile STRUCT_ARRAY Name[2]={
{tube_array_120      ,0},
{tube_array_360      ,1},
};

Но как потом к такому обращаться? Как правильно объявляется двумерный массив структур?
0
HotD
0 / 0 / 0
Регистрация: 05.10.2017
Сообщений: 2,048
10.04.2014, 11:06 29
Сам спросил, сам ответил. Можно сделать двумерный массив структур, по типу:
Код
unsykned long EE_TUBE_1   EEMEM = 0;
unsykned long EE_TUBE_2   EEMEM = 0;
unsykned long EE_TUBE_3   EEMEM = 0;
unsykned long EE_TUBE_4   EEMEM = 0;

unsykned long temp_EE;

typedef struct {
unsykned char   *PORT;         //порт , на котором висит кнопка
unsykned char   PIN;         //пин, на котором висит кнопка
unsykned char   NUMBER;         //номер тубуса
unsykned long   *EE_TUBE;      //адрес переменной в еепромке
} STRUCT_TUBE;               //новый тип

volatile STRUCT_TUBE tube_array[][4]={
{
{&PINB   ,PB0   ,1   ,&EE_TUBE_1   },
{&PINB   ,PB1   ,2   ,&EE_TUBE_2   },
{&PINB   ,PB2   ,3   ,&EE_TUBE_3   },
{&PINB   ,PB3   ,4   ,&EE_TUBE_4   }
},
{&PIND   ,PD0   ,1   ,&EE_TUBE_4   },
{&PIND   ,PD1   ,2   ,&EE_TUBE_3   },
{&PIND   ,PD2   ,3   ,&EE_TUBE_2   },
{&PIND   ,PD3   ,4   ,&EE_TUBE_1   }
};
и обращаться:

Код
tube_array[NUMB][0].EE_TUBE
, где NUMB - номер массива по порядку
0
tsostyk
0 / 0 / 0
Регистрация: 23.04.2013
Сообщений: 66
10.04.2014, 11:50 30
Я, кстати имел ввиду не проблемы с оптимизацией, а вот что:
Если тщательно вкурить содержимое файла avr/io.h, то выяснится, что после препроцессора код типа
Код
PINB
превращается в
Код
(*(volatile uint8_t *)(0x03))
То есть, "значение одного байта, который лежит в памяти по адресу 0x03"
(Адрес может меняться в зависимости от МК, это сейчас не важно).
Соответственно, если мы объявляем, инициализируем и используем структуру, вот так:
Код
typedef struct
{
uint8_t PORT;
... //что-то еще
} mystruct;
mystruct myval = {PINB, ...};
...
if(myval.PORT & ...) ...
Содержимое PINB запишется в элемент структуры в момент инициализации и меняться не будет.
Если же записать так, как Вы это сделали:
Код
typedef struct
{
volatile uint8_t* PORT;
... //что-то еще
} mystruct;
mystruct myval = {&PINB, ...};
...
if(*(myval.PORT) & ...) ...
, то в структуру запишется адрес в памяти и обращение к нему будет происходить корректно (берем адрес, читаем байт по этому адресу, одрабатываем.)
0
HotD
0 / 0 / 0
Регистрация: 05.10.2017
Сообщений: 2,048
10.04.2014, 12:28 31
я не помню уже, почему делал правильно, но когда я пытался в структуру запихать просто PINB, то GCC ругался, и не давал компилировать.
0
10.04.2014, 12:28
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
10.04.2014, 12:28

Оптимизация кода
Доброго времени суток, дамы и господа. Прошу помощи в оптимизации куска кода....

Оптимизация кода
Есть код для копирования листа в созданную книгу, листы копируются с системной...

Оптимизация кода
Помогите пожалуйста get-ер оптимизировать. Уже оптимизировал как мог для...


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

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

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