Обсуждаем контроллеры компании Atmel.
Пт авг 11, 2017 16:15:47
Вообщем проблема в следующем. Создаю массив, забиваю его нулями. В последствии оказывается что там не везде нули. Никаких операций с указателями не делаю, переполсти за пределы массива тоже не должен. При изменении кода прокта (абсолютно постороних) значения в массиве меняются без видимых кореляций. Изменение опций оптимизации так же приводит к измению данных. Упростил код до безумия - не пойму. Второй день сижу, поглядите, плз.
Вот код
- Код:
#include <avr/interrupt.h>
#include <util/delay.h>
#define SETBIT(x,y) (x|=(1<<y))
#define CLRBIT(x,y) (x&=~(1<<y))
#define INVBIT(x,y) x ^= (1<<y)
#define RGB_PORT PORTD
#define RED_PIN PD4
#define GREEN_PIN PD5
#define BLUE_PIN PD3
#define RED_ON SETBIT(RGB_PORT,RED_PIN)
#define RED_OFF CLRBIT(RGB_PORT,RED_PIN)
#define GREEN_ON SETBIT(RGB_PORT,GREEN_PIN)
#define GREEN_OFF CLRBIT(RGB_PORT,GREEN_PIN)
#define BLUE_ON SETBIT(RGB_PORT,BLUE_PIN)
#define BLUE_OFF CLRBIT(RGB_PORT,BLUE_PIN)
#define EventCount 20
// Скорость обмена UART в бит/с
#define UART_BAUD 9600ul
#include <uart.c>
volatile unsigned char cR=0, cB=0, cG=0; /* текущие значения яркости каждого канала */
/* массивы времени (в минутах) и значений цвета по каналам */
volatile unsigned char aHour[EventCount];
volatile unsigned char aMin[EventCount];
volatile unsigned char aRed[EventCount];
volatile unsigned char aGreen[EventCount];
volatile unsigned char aBlue[EventCount];
volatile unsigned char gH,gM,gS;
volatile int T; /* текущее время*/
ISR(TIMER0_OVF_vect) { /* шим ленты */
static unsigned char Tmr=0;
if (Tmr<cR) RED_ON;
else RED_OFF;
if (Tmr<cG) GREEN_ON;
else GREEN_OFF;
if (Tmr<cB) BLUE_ON;
else BLUE_OFF;
Tmr++;
}
ISR(TIMER1_OVF_vect) { /* следим за временем и менем яркость ленты */
unsigned char n=0,i;
T=gH*60+gM;
for (i=0;i<EventCount;i++) { /* узнаем каким должно быть текущее значение ленты*/
if (T>=(aHour[i]*60+aMin[i])) n=i;
}
UART_SendChar(T>>8 & 0xFF);
UART_SendChar(T & 0xFF);
UART_SendChar(gS);
UART_SendChar(cR);
UART_SendChar(aRed[n]);
UART_SendChar(cG);
UART_SendChar(aGreen[n]);
UART_SendChar(cB);
UART_SendChar(aBlue[n]);
UART_SendChar(n);
UART_SendChar(0x0);
UART_SendChar(0x0);
UART_SendChar(0x0);
UART_SendChar(0x0);
UART_SendChar(0x0);
UART_SendChar(0x0);
}
void Load_Raspisanie(void) {
for (unsigned char j=0;j<EventCount;j++) {
aHour[j]=0;
aMin[j]=0;
aRed[j]=0;
aGreen[j]=0;
aBlue[j]=0;
}
aHour[17]=16;
aMin[17]=27;
aHour[18]=16;
aMin[18]=28;
aHour[19]=16;
aMin[19]=29;
}
int main (void) {
UART_Init();
sei();
Load_Raspisanie();
TCCR1B = (0<<CS12)|(1<<CS11)|(0<<CS10);
TIMSK |= (1<<TOIE1); // разрешаем прерывание по переполнению таймера
gH=16;
gM=26;
gS=0;
while(1) {
if (gS++>60) {
gS=0;
gM++;
}
_delay_ms(900);
}
}
При запуске в функции LoadRaspisanie зачищаем массив. В полсдествии в перерывании выводим значения. Байт часов, байт минут, далее три пары байт, второй байт - значения массива. Потом индекс массива который выводится. И вот в третьей паре второй байт он не ноль.
ВиеАвр 20100110 avr-gcc 4.3.3
протеус 8.1 sp1 билд 17358
Добавлено after 34 seconds:attiny2313
- Вложения
-
- Archive.zip
- вот сам проект с исходниками
- (120.4 KiB) Скачиваний: 234
Пт авг 11, 2017 16:33:19
А сколько ОЗУ в МК
?
Вс авг 13, 2017 19:16:37
То есть ему оперативки не хватает? А как то написать об этом он не должен? Если массивы сделать побольше, то при компиляции winavr пишет, что .data столько то и в процентах, если перебор, то больше 100. Но тут вроде все в допусках.
Пн авг 14, 2017 05:25:00
Вот именно что вроде. Когда используете память на грани, надо ее точно рассчитывать не забывая про стек.
Пн авг 14, 2017 17:56:15
положил массивы в еепром, вроде все нормализовалось. Но я этого прикола не понял. В изначальном варианте я уменьшал размеры массива и winavr писал что data занято на 90%. С какого момента вообще нужно "начинать считать"? Почему компилятор перезаписывает переменные? Это ведь не такая уж и травиальная задача посчитать нужны объем памяти, я уж молчу про стек... "как жить, как страной управлять" (с)
Пн авг 14, 2017 18:05:25
Трудновато будет стек посчитать программируя на ЯВУ. Надо смотреть скомпилированный код. Локальные переменные скорее всего там будут. В обработчике прерывания некое количество регистров будет скинуто. Кстати, можно поглядеть как скомпиллися вход в main, возможно командой rcall, а так как из main выхода не будет, можно поправить указатель стека, тем самым сэкономив два байта.
Если в еепром часто писать, то не долго проживет.
У Вас "цветные" массивы какие значения могут принимать? Наверняка можно что-то с оптимизировать.
Пн авг 14, 2017 19:57:33
экономия двух байтов ничего не даст. Я уменьшил массивы на 20 байт - такая же петрушка осталась.
Писать в еепром часто и не будется, там один раз записали и потом только читать. Просто чтение в прерывании и мне кажется более правильно с переменными работать. Там изначально предполагалось что массивы будут в еепром храниться, просто работать хотел с переменными.
значения от 0до255, оптимизировать можно первые два массива - часы и минуты. Можно там выкроить по паре бит, но это усложнит чтение и запись и я решил что оно того не стоит.
на самом деле меня больше сам факт удивляет: пишешь, компилируешь, все ок, а потом фигагс и пойми что там происходит. И это я еще заметил что что то не так, а если бы это вылазило бы не всегда (при некоторых изменениях он вроде нормально гонит, но я так понимаю это до поры до времени).
И самое главное - а как вот сейчас узнать что все в порядке. Массивы я убрал, оставил только один. винавр пишет что 40% озу занято...
PS Загнал проект в протеус (всмысле исходник), под отладчиком смотрел адреса переменных - не нашел что бы адреса совпадали, похоже реально стек рушит...
Пн авг 14, 2017 20:04:24
Не надо ждать чудес от компилятора, все он не просчитает. Если при 60% свободной памяти что-то не так, то это уже не стек.
А константы лучше хранить в памяти программ, собственно они и так там.
Пн авг 14, 2017 22:55:50
А константы лучше хранить в памяти программ
всмысле? В ОЗУ? В виде переменных?
У меня "по плану" так: все эти массивы хранятся в еепром. Массив со временем продублирован и хранится в ОЗУ в виде массива переменных. А значения RGB читаются из eeprom.
чтение из eeprom не изнашивает же его? Запись туда очень редко,а вот чтение будет регулярно....
Вт авг 15, 2017 06:51:06
Проведи тестирование каждого фрагмента автономно, затем в комплекте (присоединяя по одному дополнительному модулю на тест). Где-то "накладка" имеется. Или банальный общий сбой работы МК.
Вт авг 15, 2017 10:31:36
Отключил уже все модули, упростил до невозможности. Похоже и вправду нахватает памяти и идёт перезапись переменных
Вт авг 15, 2017 10:42:41
С attiny2313 лучше под ассемблером работать...
Вт авг 15, 2017 15:51:52
alex1126 писал(а):всмысле? В ОЗУ? В виде переменных?
Память программ - это память программ, та память в которой лежит программа, она же флешь. Если данные не планируется менять в процессе работы программы и не хватает ОЗУ, то зачем их дублировать в ОЗУ.
- Код:
if (gS++>60) {
gS=0;
gM++;
}
_delay_ms(900);
Неудачный алгоритм счета времени. Не потому что у Вас в минуте 61 секунда. Время лучше считать от таймера, например в том же обработчике прерывания от него. А вот сличать текущее время с заданным можно и в основном цикле. Я там понимаю 900мс опытным путем навскидку подобрано?
--
ЕЕПРОМ от чтения не портится.
Вт авг 15, 2017 22:53:35
Если данные не планируется менять в процессе работы программы и не хватает ОЗУ, то зачем их дублировать в ОЗУ.
планируется, но очень редко. Впринципе хранить их в еепром меня устаривает.
Неудачный алгоритм счета времени. Не потому что у Вас в минуте 61 секунда. Время лучше считать от таймера, например в том же обработчике прерывания от него. А вот сличать текущее время с заданным можно и в основном цикле. Я там понимаю 900мс опытным путем навскидку подобрано?
это типа заглушки. В реальности там с ds1307 берется время, но при поиски ошибки я отключил все модули который касаються часов и собственно i2c.
Добавлено after 2 minutes 42 seconds:С attiny2313 лучше под ассемблером работать...
не читаем получается код
Да и из 2кб можно много выжать, если постараться. Я туда запихивал софтовую реализацию юсб и еще на "работу" хватило. вот где битва за каждый байт была
Ср авг 16, 2017 08:22:26
Под ассемблером и "нечитаем"??
Это конечно не алгоритмы под СИ, однако "надо уметь готовить" дабы чего после двух-трех месяцев после написания прочесть.
...
Ср авг 16, 2017 15:55:10
Ну хорошо, скажу по другому - не так легко читаем. Вообще я стараюсь писать так, что бы одна функция помещалась на экране без перелистывания. На асме так сделать не просто. Там только написание цикла полэкрана займет - положим начальное значение, увеличим, сравним с конечным значением, переход туда, переход сюда...
И вообще мы как то от темы отдалились.
Powered by phpBB © phpBB Group.
phpBB Mobile / SEO by Artodia.