Jump to content

    

AndreyS

Участник*
  • Content Count

    234
  • Joined

  • Last visited

Everything posted by AndreyS


  1. Начните последовательно (не все скопом), иначе не выясните что было основным. Первый пункт думаю будет решающим. + снижение частоты работы шины Вы Матрешку Малинку проверяли, на какой она скорости с удлинителем взаимодействует с SD картой? Хотя да, осца же нет.
  2. При точном измерении углов подобная калибровка необходима, но в данном случае не объясняется непосредственно причина формирования 245 ед на 1g в режиме +/- 24 g Я все же ожидал видеть с датчика число хотя бы как-то приближенно соответствующее паспортному значению по чувствительности (для диапазона +/- 24g = 0,012 g на ед). Иначе мне совершено непонятно, что же тогда делается на заводе и заливается в регистры? И зачем оно восстанавливается при запуске чипа (boot)? Хотелось бы получить понимание в чем именно моя ошибка. Или в большинстве MEMS датчиков данная характеристика никак не нормируется, данные идущие с датчика никогда и близко не соответствуют паспортным и даже для неточных измерений углов или ударов, требуется калибровка?
  3. Добрый день всем. Перерыл форум и инет, но ответа на свой вопрос не нашел. Работаю с 3-х осевым датчиком ускорения ST LIS331HH, в режиме SPI 4-х проводном. По документации (в коменте к общей таблице) сказано, что он 12-и битный. Данные при этом выдаются в 16 битном формате. Опытным путем выяснил, что 4 младших бита незначащих, т.е. данные прижаты к старшему биту (влево). Углы измеряются отлично, все ок. Но вот проблема не могу пересчитать полученные цифры в абсолютное значение ускорения свободного падения (конкретно просто в g, т.е. не в m/c2) При повороте датчика так, что бы на одну из осей спроецировалось ускорение свободного падения получаю число, при пересчете которого получаю не 1g, а 2.9g Смотрел на нескольких датчиках, цифры везде идут одинаковые. Проверял в разных диапазонах, в пересчете на g все равно получается 2.9g. Нахожусь в нормальных условиях - статично. В диапазоне +/- 24g получаю 245 единиц в максимальной проекции. В диапазоне +/-6g получаю 950 единиц в максимальной проекции. (в диапазоне +/-12g цифр не помню, но в пересчете получаю те же 2.9g Соответственно паспортная погрешность смещения 70mg видна на разных датчиках - в единицах это получается +/- 5 ед в диапазоне +/- 24g (в зависимости от диапазона величина разная) Пересчет в g делаю так: пример для диапазона +/-24g 245ед*48.0/4096=2.87g Для того что бы получить что-то в районе 1g число на входе должно быть в районе 85 единиц - получается смещение 159 единиц (это соответственно для диапазона +/-24g). Про такую величину смещения в документации я что-то ничего не находил. Это уже всяко больше 70mg паспортных. В принципе при калибровке - это становится не важным, но хотелось бы быть уверенным, что относительные величины g считаться будут верно. К сожалению я не могу сформировать эталонное воздействие, нет соответствующей измерительной аппаратуры. Соответственно если 4096 в формуле заменить на 65536 - (а прочитанные данные не сдвигать вправо на 4 бита) получаем тоже значение 2.9g в пересчете. Может быть кто-нибудь, кто работал с этим датчиком укажет мне на ошибку?
  4. Добрый день. Исходя из того, что ИОН для АЦП сделан на делителе, то в таком случае сдвиг нуля операционника дешевле сделать по первому варианту.
  5. Добрый день. BL51 не настраивал, он не позволяет работать с банками свободно. Работаю с LX51 Вот настройки для мое проги под бутзагрузчик идем в настройки проекта LX51 locate Там есть поле USER segment в нем можно задать конструкции по размещению в фиксированной области памяти (или в диапазоне адресов) ваших сегментов. Вот мой пример ?BANK?SELECT(C:0x7100),?BANK?SWITCH(C:0x7110),?CO?FORBOOTDATA (C:0x70F0) Тут зафиксированы три процедуры. ?BANK?SELECT ?BANK?SWITCH ?CO?FORBOOTDATA префиксы указывают на модуль (читайте описание на кейл ?CO? область кода). ?BANK? из асмового стартапа. Для переменных тут будет муторно все прописывать Можно просто переопределить классы в поле User class (для этого надо снять галочку Use Memory Layout from Target Dialog). Пропишите что у вас диапазон внешней памяти меньше чем может быть. Я например прописал себе класс для данных модуля обработчиков прерывания CODE_INTR (C:0x7000-C:0x7FFF) и вставил в модуль переопределение #pragma userclass (CODE = INTR) таким образом у меня после линковки модуль обработчикв прерываний лег в коде по фиксированному диапазону кода. С данными все тоже самое. Определите себе диапазон и пропишите его в линковщке. А все что работает с внешними ОЗУ данными положите в один модуль. Вот примерно так В модуле ставим #pragma userclass (xdata = MyClass) В настройках линкера XDATA_MYCLASS (X:0x0000-C:0x0050) PS Пример вы нашли правильный. Вы в настройках линкера уберите галочку использовать данные из диалога и в классе измените только строку XDATA(0x0000-0x0FFF)
  6. Хорошая мысль. Правда в кейле заложено 32 прерывание для 51 контроллера (вернее 32 вектора), не знаю что будет с ним если указать номер больше чем 31. А так было бы хорошо. В контроллере с 21 вектором прерываний продублировать их в старшие от 21 и до 42. И вот старшие - это прерывания бутзагрузчика. Тогда стартап файл будет короче. Попробовал сделать более 32 вектора. Ругается кейл А мысль хорошая. Главное потом в бутзагрузчике не забыть что вектор номер 10, скажем, это на самом деле вектор номер 0 :)
  7. Добрый день всем. Спасибо Всем за ответы. Значит оставлю все определения в стартапе на асме. Вот только как заставить Кеил для процедур сохранить используемые регистры в стек? А то он в моих процедурах (которые на самом деле прерывания) не сохранил в стек ничего. Видимо думает что процедура не вызывается под другой (и время жизни регистра A и R7 маленькое). Пробовал вызвать процедуру через указатель, в надежде что Кеил вставит сохранение регистров. Ничего подобного не произошло. Пока добавил в макрос определения прерывания полное сохранение в стек регистров и их восстановление. Просто таблица прерываний бутзагрузчика стала большой.
  8. Добрый день. Поясняю. Решил написать бузагрузчик с максимальным использованием Си. Для этого выбрал следующий путь для себя: 1. Удобнее всего объявить прерывания в Си и все в одном файле, тогда всегда легко можно обработчик найти (спустя время) и подкорректировать. 2. Для того что бы прерывания передавались внешней прошивке зафиксировал в битовой области флаг состояния бутзагрузчика (внешняя/бут) и это определение также дал коду внешней прошивки (что бы она его не меняла). 3. В обработчике прерывания, всех прерываний проца, (который на си объявлен) хотел поставить простую конструкцию if (IN_BOOT) { процедура бутзагрузчика, если она есть } else { #pragma asm JMP OFFSET_EXT_PROGRAM+"адрес вектора прерывания" #endasm } Что получилось. Компилятор на пустое объявление прерывания тут же вставляет PUSH ACC и POP ACC На объявление прерывания с using еще и PSW На мою конструкцию вставляет полный набор всех регистров и DPTR (даже в случае отсутствия процедуры обработки прерывания в бутзагрузчике (ну просто if и else с asmовой вставкой). Решил пока переписать все объявления прерываний на ассемблере в стартапе и там на каждый обработчик поставил свой макрос Interrupt MACRO COUNTER,VECTOR_BOOT_INT JNB BOOT_in_boot_f,$+4 LCALL VECTOR_BOOT_INT RETI LJMP BASE_ADR_EXT_PROG+COUNTER COUNTER SET COUNTER+8 ENDM Ни и пришлось описать заранее названия всех обработчик прерываний на Си (которые теперь в Си стали просто процедурами) и в стартап файл их EXTRN"ить :) Но это мне не нравится, потому как идея была изначально делать на асме все по минимуму ибо видимо лень мне нажимать на клавиатуру (хотелось больше сделать все средствами компилятора). Я правильно понимаю что нет (пока я не нашел об этом информации) возможности в Keil x51 для прерываний (и видимо для функций) запретить автоматическое сохранение регистров в стек (понятно что это рукоблудство может развалить всю прогу, но я надеялся что можно настройкой или прагмой для определенной области это сделать).
  9. Добрый день. Подскажите пожалуйста, как заставить Keil (проект на Си) не укладывать сохранение в стек регистров и соответственно не восстанавливать их из стека? Пояснение: Объявляю функцию с параметром interrupt 0 и в теле ее вызываю проверку с битовой переменной, если переменная возведена, то делаю прямой переход (через #pragma asm) на требуемый внешний обработчик. Если нет, то хочу отсюда выйти. В конце внешнего обработчика конечно стоит RETI (средствами Си, потому что этот внешний обработчик есть другая прошивка) и по нему прерывание нормально завершится. Но вот при такой конструкции Кеил упорно обрамляет вызов прерывания сохранением полного набора регистров в стек и соответственно его полного восставноления. Как это обрамление отключить??
  10. Добрый день. Появился второй вопрос (по сравнению с первым, как мне кажется более существенный). Перешел на изучение I2C. Конкретно работу в режиме передающий мастер. Настроил I2C, включил в CMU синхросигнал, реализовал обработчик прерывания I2C, настроил NVIC. Передаю данные. Вопрос по значениям состояний I2C регистра STATE. Хочу прочитать значение данных по некому адресу из EEPROM. После успешного выставления состояния START на шину в регистре должно (по документации) появиться значение 0x57. Но появляется 0x53 (2 бит TRANSMITTER) не возводится. В обработчике прерывания я ожидал 0x57 для продолжения работы, добавил 0x53. Дальше все согласно даташиту отрабатывает и приходит обратно в состояние. Т.е. я передаю 7 битный адрес с признаком записи и он подтверждается EEPROM (приходит ACK) состояние 0x97. Затем я передаю два байта адреса EEPROM (тут они уже идут как данные I2C) и получаю на каждый STATE= 0xD7. После этого посылаю Repeat START и в ответ опять получаю 0x53 (а не 0x57), после этого передаю адрес с признаком чтения данных и после этого вижу на шине осциллографом, что CLK отработало видимо не только передачу адреса, но еще что-то (количество клоков 17 штук). В регистре STATE лежит при этом 0xB3 и есть данные в регистре RXDATA. Видимо сразу за адресом прошел запрос и данных, но я не включал авто подтверждений и по идее должно было прийти сначала состояние 0x93, а уже затем я бы перешел в состояние принять байт. Ну даже если и принял байт, то почему на шине количество клоков не кратно 9 (17 вместо необходимых 18)? И в регистре RXDATA лежит 0xEE (EEPROM пустая и я еще туда ничего не записывал) ожидалось 0xFF. 0. Как правильно сбросить прерывание I2C шины? 1. Почему при выставлении START на шину (посыл команды в регистр CMD I2C_CMD_START) в регистре STATE 0x53, вместо 0x57? 2. Почему не выставляется бит TRANSMITTER? Как гарантированно перевести I2C в режим Master Transmitter? 3. Почему после отправки адреса микросхемы с признаком чтение (после RSTART) происходит передача адреса на шину и прием чего, то (клоков на шине 17)? Возвращается STATE не 0x97, а сразу 0xB3, Почему так? Инициализация I2C шины. /* Настройка I2C */ // Настройка GPIO I2C /* Pin PD14 is configured to Open-drain with pull-up and filter */ GPIO->P[3].MODEH = (GPIO->P[3].MODEH & ~_GPIO_P_MODEH_MODE14_MASK) | GPIO_P_MODEH_MODE14_WIREDANDPULLUPFILTER; /* Pin PD15 is configured to Open-drain with pull-up and filter */ GPIO->P[3].MODEH = (GPIO->P[3].MODEH & ~_GPIO_P_MODEH_MODE15_MASK) | GPIO_P_MODEH_MODE15_WIREDANDPULLUPFILTER; // Включаем 3 альтернативное рассположение (там в ките висит EEPROM) I2C0->ROUTE = (I2C0->ROUTE & ~_I2C_ROUTE_LOCATION_MASK) | I2C_ROUTE_LOCATION_LOC3; // Разрешение шины на GPIO I2C0->ROUTE |= I2C_ROUTE_SDAPEN | I2C_ROUTE_SCLPEN; // Настраиваем частоту рабоыт I2C 100кГц // div = ((14000000 - (4 * freq)) / (n * freq)) - 1; // freq= 100000 частота I2C I2C0->CLKDIV; // Настраиваем режим работы I2C I2C0->CTRL=(I2C_CTRL_CLHR_STANDARD | I2C_CTRL_EN ) & ~I2C_CTRL_SLAVE;// | I2C_CTRL_AUTOSN;// | I2C_CTRL_AUTOACK; // Определяем прерывания I2C I2C0->IFC = _I2C_IFC_MASK; I2C0->IEN = I2C_IEN_MSTOP|I2C_IEN_NACK|I2C_IEN_ACK|I2C_IEN_RSTART|I2C_IEN_BUSHOLD|I2C_IEN_ST ART; Инициация передачи данных if (I2C0->STATE & I2C_STATE_BUSY) { I2C0->CMD=I2C_CMD_ABORT; } I2C0->CMD = I2C_CMD_CLEARPC | I2C_CMD_CLEARTX; if (I2C0->IF & I2C_IF_RXDATAV) { I2C0->RXDATA; } I2C0->IFC = _I2C_IFC_MASK; I2C0->CMD=I2C_CMD_START; Обработчик прерывания // обработчик IIC прерывания void I2C0_IRQHandler(void) { dword SMB0STA; SMB0STA=I2C0->IF; I2C0->IFC=SMB0STA; SMB0STA=I2C0->STATUS; SMB0STA=I2C0->STATE; if (!iic.cycle) {// выход на шину if ((SMB0STA==MTM_START) || (SMB0STA==MTM_RSTART)) { I2C0->TXDATA=*(byte *)(&iic); //SMB0DAT=*(byte *)(&iic); // передаем адрес с признаком //IIC_CLR_START iic.cycle++; iic.ptr=0; } else IIC_GET_ERR_ } else { if (iic.work==_WRITE) {// цикл записи switch (iic.cycle) { case 1 : if (SMB0STA==MTM_SLAW_ACK) { if (iic.len--) { I2C0->TXDATA=iic.dat[iic.ptr++]; iic.cycle++; } else IIC_STOP_ } else IIC_GET_ERR_ break; case 2 : if (SMB0STA==MTM_DATA_ACK) { if (iic.len--) I2C0->TXDATA=iic.dat[iic.ptr++]; else { if (!iic.len_rd) IIC_STOP_ else { iic.work=_READ; iic.len=iic.len_rd; iic.ptr=0; iic.cycle=0; IIC_START } } } else IIC_GET_ERR_ break; default : break; } } else {// цикл чтения switch (iic.cycle) { case 1 : if (SMB0STA==MRM_SLAR_ACK) { if (iic.len) { iic.cycle++; if (--iic.len) IIC_SEND_ACK else IIC_SEND_NACK } else IIC_STOP_ } else IIC_GET_ERR_ break; case 2 : if (SMB0STA==MRM_DATA_ACK) { iic.dat[iic.ptr++]=(byte)(I2C0->TXDATA); if (--iic.len) IIC_SEND_ACK else IIC_SEND_NACK } else { if (SMB0STA==MRM_DATA_NACK) { iic.dat[iic.ptr++]=(byte)(I2C0->TXDATA); IIC_STOP_ } else IIC_GET_ERR_ } break; default : break; } } } } Макросы #define IIC_START I2C0->CMD=I2C_CMD_START; // Посыл START на линию #define IIC_STOP I2C0->CMD=I2C_CMD_STOP; // Посыл STOP на линию #define IIC_SEND_ACK I2C0->CMD=I2C_CMD_ACK; // Посылка подтверждения #define IIC_SEND_NACK I2C0->CMD=I2C_CMD_NACK; // Посылка не подтверждения #define IIC_ABORT I2C0->CMD=I2C_CMD_ABORT; // Сброс шины
  11. Добрый день. Начал разбираться со зверем EFM32GG от EnergyMicro На стадии изучения прерывания (NVIC) от GPIO не могу понять чем отличается прерывание (GPIO) ODD от EVEN (обработчики GPIO_ODD_IRQHandler и GPIO_EVEN_IRQHandler)? Настроил два пина порта A на прерывания по переднему фронту и включил их. В main'е меняю значение на одной ноге и вываливаюсь в прерывание EVEN. В нем проверяю GPIO->IF на предмет вызова по пину из main и тогда меняю состояние второй ноги. Но при этом почему то вываливаюсь не в EVEN, а в ODD прерывание (в GPIO->IF вижу что сработало прерывание от ноги измененной в EVEN обработчике). Почему? В чем их разница? В документации в качестве примера (похож на мой) сказано что должен быть выход в ODD обработчик. Я включил только его и ниразу в него не вошел. PS. Хотя наверное я понял. Это обработчики четных и нечетных внешних прерываний?
  12. А зря (по моему лучшего нет)! Какие требования к дизассемблеру?
  13. Добрый день. Вы смотрели содержимое массива именно в Watch? Проверьте содержимое в окне memory, и введите там адрес вашего массива (только префикс типа памяти не забудьте). Если там верная информация (а она должна быть именно такой, потому что через ваши указатели ptr_massiv информация отображается правильная), то не беспокойтесь. Это глюк кейла. Я помню напарывался на подобный эффект, когда в ватчах отображалось не то что там реально находилось. Так что дамп ОЗУ лучший инструмент. Ну и посмотрите карту памяти, реально переменная попала в нужную область или нет (это как второй инструмент контроля над компилятором). Удачи.
  14. добрый день. Посмотрите cypress Cy68013, оно же FX2. Если не изменяет память, то там есть инт2 и помоему еще инт4 (кроме инт0 и инт1). Правда в нем еще и USB, но есть и I2C.
  15. Добрый день. Видимо все это проверялось под ОС Винда. Очень хотелось бы услышать результаты таких исследований под любой другой ОС. У меня есть подозрение что это шалит драйвер usbd.sys под виндой. Потому как обнаружили в своей системе следующую проблему. При некоторых обстоятельствах (одно из них, 100% приводящее к этой проблеме, это огромная помеха по шине USB соответственно ведущая к потери пакетов) происходит как бы зависание USB устройства в операционной системе (физически же само исполнительное устройство device продолжает нормальное функционирование, подвисает USB шина). Это подвисание может быть кратковременным, а может быть длительным. В таком случае спасает reset_port с abort_pipe. Но вот в этот момент подвисания любой запрос к драйверу usbd.sys (посредством драйвера ezusb.sys) не приводит в появлению данных на самой шине. Производили сканирование аппаратным анализатором и обнаружили эту проблему. На шине кроме SOF пакетов ничего больше нет. А в диспетчере устройств оно доступно. Происходит это редко (при длительной эксплуатации USB шины в течении нескольких суток), но может залипнуть так, что спасает только перезагрузка. Причем вылезла эта проблема в лабораторных условиях, т.е. помех по USB шине небыло, сканер их не показал. Рысканье по инету привело к тому что в разных виндах требования на максимальный объем запрашиваемой информации в драйвере usbd.sys разный. В нашем случае мы удовлетворяем этому требованию под винду ХП, 2000 и 7 с вистой. Но само это наводит на мысль возможных глюках в работе usbd.sys под виндой.
  16. Добрый день. На всякий случай, решил добавить немного от себя (то же по опыту работы с F410). Для ALARM прерывания необходимо разрешить работу ALARM в RTC, разрешить работу самого RTC и запустить таймер RTC. В MCU разрешить работу прерывания RTC. Обновлять регистры RTC необходимо с вычитыванием старого содержимого, а то можно выключить прерывание. И еще. Для сброса прерывания необходимо обновить значение ALARM на новое, иначе тут же выйдя из прерывания снова в него попадете (ну или вообще отрубить работу ALARM). Удачи.
  17. Добрый день всем. Еще поковырял температурный датчик. Тот вывод который я сделал относился в первую очередь к частоте преобразования Гц (у меня частота преобразования 2.7 МГц и на ней он опять не заработал должным образом). Выяснилось, что (видимо так и есть) температурный датчик состоит из слаботочного источника тока и большого (по сопротивлению) терморезистора, тогда при подключении АЦП (в этот момент входная емкость АЦП полностью разряжена) происходит медленный рост конечного напряжения на терморезисторе. Короче, при включении посттрекинг тайма на максимум (т.е. 16 тактов, при частоте преобразования АЦП 2.7 МГц) только тогда пошли данные правдоподобные. Если оставить 8 тактов, то значения врут. Можно просто прикинуть на пальцах и получается что минимальное время оцифровки термодатчика не менее 12мкС (2.7МГц / (15 тактов преобразования АЦП + 18 тактов трекинга= 33 такта) получаем 81 кГц). Если взять все максимальные смещения на температурный датчик и Vref, то температура может отличаться от температуры измеренной термопарой (правда это будет адитивная погрешность) на 15 градусов, получается, что без калибровки не обойтись (хотел иметь погрешность 5 и не калиброваться). Вот теперь по этому вопросу все :)
  18. Добрый день. O.L. большое спасибо за ответ. Вашу ссылку читал еще раньше, но там как раз ответа на первый вопрос и не поступило (тишина) Что я проделал. Взял EK на F411 и залил туда свою прошивку. Результат получил точно такой же (т.е. те же 0x200 +/- сколько то единиц). Взял пример работы с АПЦ для этого контроллера и он заработал нормально (правильно, ну или правдоподобно). При сравнении кода, выяснил что за неточность работы с температурным датчиком (именно с ним, так как данные оцифрованные с других каналов, совпали с тем что на них выставлено) ответственен бит BURSTEN в регистре ADC0CN. И это при том что АЦП перед этим я принудительно включаю битом AD0EN и только потом выставляю бит запуска AD0BUSY (АЦП настроено именно на запуск вручную). Как только в инициализации сбросил бит BURSTEN, то цифры стали правдоподобными (получается что этот бит связан с работой температурного датчика). Вот такая петрушка. Может кому пригодится. Удачи
  19. Keil 9+Silabs C51+pdata

    Добрый день. Странный код у вас при вызове перевызываемой функции. Вот пример моей функции и ее листинг Вот сама процедура на Си (первые цифры - это номера строк в коде, что бы легче было произвести сравнение с листингом) На отсутствие return не смотрите. 330 bit set_CS(byte set) reentrant 331 { 332 if (SPI_mas.ptrs[SPI_mas.rd].type==SPI_SD_card) 333 {// CS для карты памяти 334 CS_SD_card=(bit)set; 335 return(CS_SD_card); 336 } 337 } Вот листинг. Тут видно что программный стек идет вниз (аппаратный идет вверх, SP. Вверх - к старшим адресам) из этого прямой вывод, что ставить начальный адрес надо как можно выше, лучше просто на максимум, т.е. вершину ставим не в конце всех переменных, а самый старший адрес памяти. ; FUNCTION _?set_CS (BEGIN) ; SOURCE LINE # 330 0000 1500 E DEC ?C_IBP 0002 A800 E MOV R0,?C_IBP 0004 A607 MOV @R0,AR7 ; SOURCE LINE # 332 0006 900000 R MOV DPTR,#SPI_mas+025EH 0009 E0 MOVX A,@DPTR 000A 75F00A MOV B,#0AH 000D A4 MUL AB 000E 2400 R ADD A,#LOW SPI_mas+0267H 0010 F582 MOV DPL,A 0012 E5F0 MOV A,B 0014 3400 R ADDC A,#HIGH SPI_mas+0267H 0016 F583 MOV DPH,A 0018 E0 MOVX A,@DPTR 0019 B40209 CJNE A,#02H,?C0043 ; SOURCE LINE # 333 ; SOURCE LINE # 334 001C A800 E MOV R0,?C_IBP 001E E6 MOV A,@R0 001F 24FF ADD A,#0FFH 0021 92A0 MOV CS_SD_card,C ; SOURCE LINE # 335 0023 A2A0 MOV C,CS_SD_card ; SOURCE LINE # 336 ; SOURCE LINE # 337 0025 ?C0043: 0025 C0D0 PUSH PSW 0027 0500 E INC ?C_IBP 0029 D0D0 POP PSW 002B 22 RET ; FUNCTION _?set_CS (END) В вашем примере я не обнаружил вообще вызов в стек. Есть какое то сложение данных по адресу 0x60 и все. То что в инициализации у вас в адрес 0x60 укладывается значение 0x7C (вы говорили о записи туда 0xFF) мне пока не говорит что это именно ?C_IBP (посмотрите ее значение в map файле, найдите в файл .map адрес этой переменной. В моем примере она лежит по адресу 0x13 в области DATA (т.е. директ мемори, не в XDATA). В общем странно это все. У меня не происходит пересечения областей памяти при вызове первызываемых функций. Мало того IBPSTACK для small модели и складывает оно все в индерект память, а не в xdata как вы указали. У вас весь код в какой модели памяти? Нет ли прагма для отдельных файлов со сменой модели памяти для этих файлов (так тоже можно и оно отлично работает, нужно только в определении функции прописать ее тип модели и тогда при вызове процедуры с другой моделью никаких проблем не будет). удачи. Просмотрел еще раз сообщения. Ощущение что код у вас в compact, а стек вы упорно пытаетесь проинитить для small.
  20. Keil 9+Silabs C51+pdata

    Добрый день. В стартап файле есть поля инициализации программного стека (в частности и для перевызываемых функций). Вот кусок из моего стартапа ;------------------------------------------------------------------------------ ; ; Reentrant Stack Initilization ; ; The following EQU statements define the stack pointer for reentrant ; functions and initialized it: ; ; Stack Space for reentrant functions in the SMALL model. IBPSTACK EQU 1; set to 1 if small reentrant is used. IBPSTACKTOP EQU 0FFH+1; set top of stack to highest location+1. ; ; Stack Space for reentrant functions in the LARGE model. XBPSTACK EQU 1; set to 1 if large reentrant is used. XBPSTACKTOP EQU 0FFFFH+1; set top of stack to highest location+1. ; ; Stack Space for reentrant functions in the COMPACT model. PBPSTACK EQU 1; set to 1 if compact reentrant is used. PBPSTACKTOP EQU 0FFFFH+1; set top of stack to highest location+1. ; ;------------------------------------------------------------------------------ Удачи
  21. Добрый день. Работаю с процом F411, включаю внутреннее АЦП на порт температурного датчика (мукс 0x18) и получаю код (в среднем 0x0200), который после расчетов (параметры взяты из даташита) с использованием смещения 0.9в и коэф передачи 0.00295в/градус получаю -210 градусов цельсия. Само собой, что цифра врет. Думал что врут настройки АЦП. Но по другим каналам (внешним входам) соответствующие напряжения, поданные на вход АЦП (т.е. после пересчета напряжений получаю соответствующие ед. АЦП). Решил измерить VDD, включил соответственно мукс на 0x19 и получил соответственно 0x0FFF, что и должно быть. Думал что не включил сам датчик (в регистр REF0CN пишу 0x17), решил записать в REF0CN 0x13 (т.е. по даташиту его выключить). Получил на этом канале значения в пределах 0x0008 (т.е. реально выключился). Вернул все обратно (т.е. включил REF0CN=0x17). И цифра опять в том же пределе 0x0200 ед АЦП. Подскажите пожалуйста формулу пересчета ед АЦП в температуру с конкретными значениями констант и если она такая же как и у меня, то как мне добиться правильного значения термодатчика в ед АЦП? Формула: T=((adc_dat.U_temp_dat*ADC_Vref/ADC_razr)-ADC_offeset_temp)/ADC_slope_temp; adc_dat.U_temp_dat - значение канала в ед АЦП ADC_Vref - 2.2 (величина ИОН) ADC_razr - 2^12 (4096) ADC_offeset_temp - 0.9 ADC_slope_temp - 0.00295 PS условия измерений - комнатная температура (отлаживаю прогу). Не ожидал споткнуться на этом месте. Корректная работа термодатчика нужна в проекте.
  22. Добрый день. ПО схеме в цепи питания стоит резистор 1 Ом. Может там на плате не 1 Ом?? Проверьте, что на 7 ноге (Regin)?
  23. Добрый день. Аналогичная ситуация была. Именно после смены кейла. Лечил удалением старой лиц.., генерацией и прописыванием новой. Удачи.
  24. Всем большое спасибо. Сделал костыль предложенный neiver (хоть и пришлось пожертвовать одним байтом ОЗУ. 0 длины массив не создал. Вернее не выкинул его, а ругнулся при требуемом типе оптимизации.) Жалко конструкция vmp на Keil не сработала. Он упорно пытался найти все что под if (хотя после компиляции его выкинул)
  25. Добрый день. Дано: 8 битный микроконтроллер Keil Си Структура для хранения переменных во внешней I2C EPROM Размер EPROM константа 256 байт Структура постепенно растет и изменяется Хотел включить макрос проверки размера структура за предел размер памяти EPROM на стадии компиляции и в случае превышеняи размера выводить ошибку. Что-то типа того: typdef struct { ... }структура; #define размер EPROM 256 #if (sizeof(структура)>размер EPROM) #error "ОШИБКА" #endif Но sizeof в данном случае использовать нельзя. Подскажите пожалуйста, как мне решить мою задачу? (считать вручную уже надоело)