Вопросы по С/С++ (СИ)

Если ваш вопрос не влез ни в одну из вышеперечисленных тем, вам сюда.
Ответить
Держит паяльник хвостом
Сообщения: 963
Зарегистрирован: Чт апр 03, 2014 23:16:55
Откуда: Россия

Сообщение Rtmip »

paskal писал(а):Помогите справиться с особенностями кейла... МК - AT89S52... В некоторую определенную область ОЗУ пишется определенная сигнатура...Так вот, программа на си при старте заполняет ОЗУ нулями, затирая сигнатуру. Как у Кейла отключить эту фичу?
При чем тут Кейл? Разве ОЗУ это энергонезависимая память? При старте там будет, что угодно, включая старые остатки знаний. Вообщем при старте содержимое ОЗУ теряется, а регистры, за исключением SP=7 обнуляются. Может неверно понята логика работы программы?
ARV верно подсказывает про PCON.
Реклама
Нашел транзистор. Понюхал.
Аватара пользователя
Сообщения: 160
Зарегистрирован: Пн сен 05, 2011 10:03:06
Откуда: Тула

Сообщение paskal »

ARV писал(а): изучайте регистр PCON и конкретно флаг (бит) этого регистра POF
Отлично! Вопрос с памятью тоже снят! :))
Rtmip писал(а):При чем тут Кейл? Разве ОЗУ это энергонезависимая память? При старте там будет, что угодно, включая старые остатки знаний.
Компилятор вставляет в начало программы такой код:

Код: Выделить всё

                MOV     R0,#IDATALEN - 1
                CLR     A
IDATALOOP:      MOV     @R0,A
                DJNZ    R0,IDATALOOP
И делает так даже при голой сишной программе. Уговорить его чтоб он так не делал, я не смог.
Если бы на станции "Мир" стояли Винды, она бы еще висела и висела...
Реклама
Друг Кота
Сообщения: 4583
Зарегистрирован: Вс дек 05, 2010 06:10:34
Откуда: ЮВ

Сообщение HHIMERA »

Грызите доку на компилятор... там должно быть что-то типа noinit... не инициализировать...
"Я не даю готовых решений, я заставляю думать!"(С)
Держит паяльник хвостом
Сообщения: 963
Зарегистрирован: Чт апр 03, 2014 23:16:55
Откуда: Россия

Сообщение Rtmip »

paskal писал(а):Компилятор вставляет в начало программы такой код:

Код: Выделить всё

                MOV     R0,#IDATALEN - 1
                CLR     A
IDATALOOP:      MOV     @R0,A
                DJNZ    R0,IDATALOOP
И делает так даже при голой сишной программе. Уговорить его чтоб он так не делал, я не смог.
Я понял Вас, но Вы меня нет. Это хорошо, что он так делает,
встречал даже где-то вопрос, как так делать. Но раз хозяин барин, то либо не используйте в проекте файл "STARTUP.A51" - то есть при создании откажитесь от него,
либо создайте копию и пропишите в ней, то, что хотите :)
Реклама
Эиком - электронные компоненты и радиодетали
Нашел транзистор. Понюхал.
Аватара пользователя
Сообщения: 160
Зарегистрирован: Пн сен 05, 2011 10:03:06
Откуда: Тула

Сообщение paskal »

Rtmip писал(а):Я понял Вас, но Вы меня нет. Это хорошо, что он так делает,
встречал даже где-то вопрос, как так делать. Но раз хозяин барин, то либо не используйте в проекте файл "STARTUP.A51"
Это вы меня не поняли. Я отказывался от ассемблерного стартапа при создании проекта. Проект состоит из голого сишного файла. При этом он компилируется в такой код:
Изображение
Если бы на станции "Мир" стояли Винды, она бы еще висела и висела...
Реклама
Встал на лапы
Сообщения: 145
Зарегистрирован: Ср фев 01, 2012 10:55:53

Сообщение BorisSPB »

paskal, посмотри эту ссылку http://www.keil.com/support/man/docs/c5 ... varloc.htm.
По-моему это то что тебе надо.
Если все-таки нужный адрес обнуляется, то в стандартном стартапе уменьшить размер сегмента IDATA и разместить сигнатуру по освободившимся адресам.
Последний раз редактировалось BorisSPB Вс окт 12, 2014 22:45:22, всего редактировалось 1 раз.
Реклама
Держит паяльник хвостом
Сообщения: 963
Зарегистрирован: Чт апр 03, 2014 23:16:55
Откуда: Россия

Сообщение Rtmip »

paskal писал(а):Это вы меня не поняли.
Хорошо, не получается запустить проект без "стартапа", но что мешает закоментировать в STARTUP.A51 обнуление?
Нашел транзистор. Понюхал.
Аватара пользователя
Сообщения: 160
Зарегистрирован: Пн сен 05, 2011 10:03:06
Откуда: Тула

Сообщение paskal »

Rtmip писал(а):Хорошо, не получается запустить проект без "стартапа", но что мешает закоментировать в STARTUP.A51 обнуление?
В принципе можно, но тут выяснилось что есть более легкий путь решения проблемы
Если бы на станции "Мир" стояли Винды, она бы еще висела и висела...
Встал на лапы
Сообщения: 145
Зарегистрирован: Ср фев 01, 2012 10:55:53

Сообщение BorisSPB »

Так и останется навсегда тайной как paskal решил свою проблему...
Опытный кот
Сообщения: 884
Зарегистрирован: Пн июл 08, 2013 22:59:45

Сообщение kelod »

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

Код: Выделить всё

int x=(rt*eeprom_read_byte(&t_og_t[min]))/10;
по отдельности rt = 2198, а eeprom_read_byte(&t_og_t[min])=40, т.е. перемножением должны получить 87920, делим на 10 итого 8792, но вместо этого контроллер почему то выдаёт 2238, т.е. 2198+40=2238 и игнорирует деление
ARV
Ум, честь и совесть. И скромность.
Аватара пользователя
Сообщения: 18788
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск

Сообщение ARV »

int x=(rt*(long)eeprom_read_byte(&t_og_t[min]))/10L;
или
int x=((long)rt*eeprom_read_byte(&t_og_t[min]))/10L;
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

Мой уютный бложик... заходите!
Контактная информация:
Опытный кот
Сообщения: 884
Зарегистрирован: Пн июл 08, 2013 22:59:45

Сообщение kelod »

а как быть с этим

Код: Выделить всё

r=(rt*eeprom_read_byte(&t_og_t[min])-rt*eeprom_read_byte(&t_og_t[max])+eeprom_read_dword(&t_og_r[min])*eeprom_read_byte(&t_og_t[max])-eeprom_read_dword(&t_og_r[max])*eeprom_read_byte(&t_og_t[min]))*pow((eeprom_read_dword(&t_og_r[min])-eeprom_read_dword(&t_og_r[max])),-1);
написал вот так

Код: Выделить всё

int r=(rt*(long)eeprom_read_byte(&t_og_t[min])-rt*(long)eeprom_read_byte(&t_og_t[max])+(long)eeprom_read_dword(&t_og_r[min])*(long)eeprom_read_byte(&t_og_t[max])-(long)eeprom_read_dword(&t_og_r[max])*(long)eeprom_read_byte(&t_og_t[min]))*pow(((long)eeprom_read_dword(&t_og_r[min])-(long)eeprom_read_dword(&t_og_r[max])),-1);
вроде всё заработало, но в положительной части за исключением варианта, 1459*50-1459*40+973*40-1459*50/(973-1459), вместо 40 получается почему то 33, а при ожидании отрицательных результатов мало того что числа получаются положительные, так ещё и невообразимо большие
ARV
Ум, честь и совесть. И скромность.
Аватара пользователя
Сообщения: 18788
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск

Сообщение ARV »

как быть? помнить о неявном приведении типов операндов в выражениях. ну и разбить сложную цепочку вычислений на несколько отдельных строк - оптимизатор все равно уберет избыточность, а свои ошибки найти будет проще. к тому же многократное обращение к функции чтения EEPROM - зачем?! можно же один раз считать в промежуточную переменную и затем ее использовать везде :) заодно и быстродействие повысится

запомните простые правила преобразования типов (вместо умножения любой арифметический знак):

int * int = int
int * char = int
char * char = int * int с последующим приведением к char
long * char = long
long * int = long
10 = int
10L = long

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

Мой уютный бложик... заходите!
Контактная информация:
Друг Кота
Аватара пользователя
Сообщения: 6348
Зарегистрирован: Вт апр 24, 2007 07:45:40
Откуда: Minsk

Сообщение Jack_A »

ARV писал(а):разбить сложную цепочку вычислений на несколько отдельных строк <..> к тому же многократное обращение к функции чтения EEPROM - зачем?! можно же один раз считать в промежуточную переменную и затем ее использовать везде :) заодно и быстродействие повысится
Да, приведенный код можно считать хрестоматийным и на нем учить новичков : вот так не делайте :(
Электрический кот
Аватара пользователя
Сообщения: 1031
Зарегистрирован: Чт июн 20, 2013 00:00:58
Откуда: москва, м.Сходненская

Сообщение Mishany »

кто подскажет?
Почему не передается второе значение 0xBB, только первое 0xAA проходит по SPI.
Спойлер

Код: Выделить всё

#define F_CPU 8000000UL
#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>
#define  DDR_SPI DDRB
#define MOSI 3
#define SCK 5

void SPI_MasterInit(void)
{
/* Установка MOSI, SS и SCK на вывод, все остальные на ввод */
DDR_SPI |= (1<<MOSI)|(1<<SCK);
/* Разрешение SPI в режиме мастера, установка скорости связи fck/4 */
SPCR |= (1<<SPE)|(1<<MSTR)|(1<<SPIE)|(1<<CPOL)|(1<<CPHA);
}

void SPI_MasterTransmit(char cData)
{
/* Запуск передачи данных */
SPDR = cData;
/* Ожидание завершения передачи данных */
while((SPSR & 0x80) != 0x80 );
}

int main(void)
{
	sei();
_delay_ms(10);
SPI_MasterInit();
_delay_ms(1);
SPI_MasterTransmit(0xAA);
SPI_MasterTransmit(0xBB);
_delay_ms(1);
}
Друг Кота
Аватара пользователя
Сообщения: 4905
Зарегистрирован: Чт апр 11, 2013 11:19:59
Откуда: Минск

Сообщение WiseLord »

Код: Выделить всё

static void ls020WriteData(uint8_t data)
{
        SPDR = data;
        while(!(SPSR & (1<<SPIF)));
        return;
}
Это рабочий код из моего проекта. Похоже, вам нужно проверять на равенство нулю в цикле, а не на неравенство.
Контактная информация:
Электрический кот
Аватара пользователя
Сообщения: 1031
Зарегистрирован: Чт июн 20, 2013 00:00:58
Откуда: москва, м.Сходненская

Сообщение Mishany »

так тоже самое, похоже после первой отправки происходит зацыкливание передачи, + на SCK длительность одного из 8-ми импульсов плавающая
убрал прерывания, вроде заработало, но почему нет стабильности в длительности импульсов на SCK?
Грызет канифоль
Сообщения: 269
Зарегистрирован: Чт мар 11, 2010 17:45:37
Откуда: г.фрязино

Сообщение mastech »

день добрый. как сделать разные задержки(разную скорость моргания) на двух портах, ставлю разные задержки в итоге получается поочередное мигание. частота стоит 4Мгц.
Спойлер#include <avr/io.h>
#include <util/delay.h>

static void PORTIANKA(void)
{
PORTB &= ~(1 << PB2);
_delay_ms(70);
PORTB |= (1 << PB2);
_delay_ms(20);
}

static void ZADERZKA(void)
{
PORTB &= ~(1 << PB4);
_delay_ms(100);
PORTB |= (1 << PB4);
_delay_ms(200);
}


int main(void)
{
//DDRD = 0b00000000;
//PORTD = 0b11111111;
DDRB = 0b00010100;
PORTB = 0b00101011;


while(1)
{
while ((PINB&(1 << PB0)) == 1){}
_delay_ms(1);
if ((PINB&(1 << PB2)) == 0)
{
PORTB |= (1 << PB2);
}
else
while(1){

PORTIANKA();
ZADERZKA();
}
}
}
Друг Кота
Аватара пользователя
Сообщения: 4905
Зарегистрирован: Чт апр 11, 2013 11:19:59
Откуда: Минск

Сообщение WiseLord »

Ну так естественно, ведь в maine() обе функции мигания светодиодами вызываются по очереди одна за другой, с той только разницей, что у светодиодов будет отличаться время свечения/гашения.

По вопросу - если нужно действительно независимое мигание, надо избавляться от _delay_ms() и переходить к аппаратному таймеру.
Контактная информация:
ks0
Прорезались зубы
Аватара пользователя
Сообщения: 238
Зарегистрирован: Чт фев 28, 2013 14:16:10

Сообщение ks0 »

Имена функций доставляют

Если без таймера, то делать delay, например, порядка сотой доли от времени зедаржки, а между вызовами этой delay декрементировать счетчики задержек каждого светодиода
Ответить

Вернуться в «Разные вопросы по МК»