|
STM32F100C6T6 и 1-wire, не отладить в IAR EWARM v6.30.4 |
|
|
|
Jan 21 2012, 19:58
|

Профессионал
    
Группа: Свой
Сообщений: 1 175
Регистрация: 5-01-05
Пользователь №: 1 807

|
К STM32F100C6T6 подключен DS18B20. Со времен AVR есть отлаженные исходники для 1-wire bus. Думалось, что все будет просто при наладке портированных исходников, но затык случился конкретный: отладить и проверить работу подключенного DS18B20 практически не удалось. Разбор полетов указал на... странную работу портов и решения или ошибки что-то никак не увидел. Пришлось упростить до одного файла main.c, в котором приведены два упражнения (примера). Как вывести из IAR (Win7 64) с русскими комментами вместо крякозябр - не знаю, потому см. аттач.
main.pdf ( 26.04 килобайт )
Кол-во скачиваний: 603Разочарований в STM32F100 два: 1. При частоте HCLK 24MHz максимальная частота ногодрыгания ~1.78Mhz. При макс оптимизации! Это катастрофа! Возможно, что-то сделано не так в системе тактирования? Неужели STM32 такие медленные? 2. Отладить простую процедуру сброса 1-wire не смог! Осциллом смотрю - все очень безоблачно: сначала вижу отриц импульс на 500us, потом проц освобождает шину, датчик ждет 35us и удерживает ее в нуле еще на 60-120us, т. е. с момента окончания отриц импульса до момента получения значения состояния шины я заложил 80us - вполне достаточно. Каково же было мое удивление, когда выяснилось, что проц читает это состояние как 1, хотя судя по осциллу явно должен быть 0. Проверил отладкой в EWARM через J-Link Ultra, что если вручную перед чтением установить на шине 0, то это состояние софтом читается правильно. Все дело в скорости чтения... Проц почему-то не может получить значение пина за несколько us. Стало ясно, почему и прочие процедуры чтения ключа и т. п. не работали... Попытки отключить USE_FULL_ASSERT, манипуляции оптимизацией ни к чему не привели, библиотечные функции проверены. Система тактирования проверена частично через вывод на пин MCO - Fhclk=24MHz. Нужна помощь...
|
|
|
|
|
Jan 22 2012, 00:30
|

Профессионал
    
Группа: Свой
Сообщений: 1 175
Регистрация: 5-01-05
Пользователь №: 1 807

|
Цитата(Aner @ Jan 22 2012, 03:53)  1-wire bus довольно жесткий к времянке, не каждый ARM проц его потянет. Вспомнив преждний опыт, отказался его реализовывать в лоб. Реализация сделана на F107, через RS порт. Для новичка в ARM звучит как приговор... Какой-то AVR тянет запросто, а сверхмощный (относительно AVR) STM32F100 вообще не может... Хотелось бы разобраться в границах применимости STM32, а то я тут сгоряча 4 девайса спаял для 1-wire на STM32F100C6 и теперь в полной растерянности. Возникает пара вопросов: 1. Как рассчитать частоту ногодрыганья при HCLK = 24MHz? Порылся в доках, но времен выполнения команд проца не нашел, только описание. Эксперимент показал, что Fgpio ~ Fhclk/14. 2. Что же со временем ввода через пин? В доках написано, что частота сэмплов ввода с портов равна Fapb2=24MHz. Все указывает как бы на то, что ядро медленное, или Fhclk низкая. Последнее вроде проверил - там 24MHz... В сети мало инфы по 1-wire на STM32, но вроде есть. Только для какого проца - не упоминается... Щас гляну на F107...
|
|
|
|
|
Jan 22 2012, 14:42
|

Гуру
     
Группа: Свой
Сообщений: 4 869
Регистрация: 28-02-08
Из: СПБ
Пользователь №: 35 463

|
Без опыта преждних разработок и внимательного понимания структуры процессорв можно запросто нарваться. Думая, что ARMы такие сверхмощные, не стоит поддаваться рекламе и эмоциям. ARMы немного другие против PIC, Atmel-ов. Они имеют ряд преимуществ, поскольку внутри много готовых инжин. Все из себя 32 битные. Но вот как только делаешь свою инжину, особенно привязанню к регистрам, потрам, времянке, то тут ARMы слабоваты. И в ряде проектов пришлось вернуться к PIC, Atmel-ам и их клонам. Например к параллаксовским процам, SX -ам, или к "8-ядерному" пропеллеру.
|
|
|
|
|
Jan 22 2012, 15:56
|
Участник

Группа: Участник
Сообщений: 42
Регистрация: 4-12-05
Из: Екатеринбург
Пользователь №: 11 773

|
не знаю, что у Вас там не получается... но у меня на платке STM32Discovery данный датчик шуршит без проблем... и как раз Atmel-овский примерчик был взят за основу... так что скорее всего где-то ошибочка закралась... выкладывайте код - будем смотреть
|
|
|
|
|
Jan 22 2012, 16:44
|
■ ■ ■ ■
    
Группа: Свой
Сообщений: 1 100
Регистрация: 9-08-06
Пользователь №: 19 443

|
Цитата Все из себя 32 битные. Но вот как только делаешь свою инжину, особенно привязанню к регистрам, потрам, времянке, то тут ARMы слабоваты. И в ряде проектов пришлось вернуться к PIC, Atmel-ам и их клонам. Например к параллаксовским процам, SX -ам, или к "8-ядерному" пропеллеру. Цитата К STM32F100C6T6 подключен DS18B20. Со времен AVR есть отлаженные... Это вы программно делаете 1-wire?
--------------------
Делай что должен и будь что будет.
|
|
|
|
|
Jan 22 2012, 17:28
|

Профессионал
    
Группа: Свой
Сообщений: 1 175
Регистрация: 5-01-05
Пользователь №: 1 807

|
Цитата(Aner @ Jan 22 2012, 18:42)  Без опыта преждних разработок и внимательного понимания структуры процессорв можно запросто нарваться. Думая, что ARMы такие сверхмощные, не стоит поддаваться рекламе и эмоциям. ARMы немного другие против PIC, Atmel-ов. Они имеют ряд преимуществ, поскольку внутри много готовых инжин. Все из себя 32 битные. Но вот как только делаешь свою инжину, особенно привязанню к регистрам, потрам, времянке, то тут ARMы слабоваты. И в ряде проектов пришлось вернуться к PIC, Atmel-ам и их клонам. Например к параллаксовским процам, SX -ам, или к "8-ядерному" пропеллеру. Теперь понятно... Но раз уж платы сделаны, хотелось бы лучше осознать. С ногодрыганием (выводом в порт) я разобрался: при Fhclk = 24MHz частота вывода на пин составляет 6MHz. Но это только при макс оптимизации и в случае НЕИСПОЛЬЗОВАНИЯ библиотек. Пришлось выкинуть все, чтобы добиться Fgpio=Fhclk/4. И тут признаем, что такого быстродействия вроде достаточно для вывода на 1-wire. Но что со вводом??? Тут мне не помогли никакие оптимизации и др ухищрения - не может проц правильно прочитать пин за 10us, хотя нет видимых причин... Под конец, я решил переписать функцию генерирования задержки: Код __INLINE void Delay1wire(unsigned int Ticks){ unsigned int tmp = Ticks/3; while(tmp--); } И это сработало!!! Функция BusReset() возвратила ноль! Но остался важный вопрос - почему нельзя в данном контексте использовать SysTick таймер? Функцию задержки на его основе я проверял - отдельно все работает нормально... Естественно, компиляция замененной Delay1wire в режиме Debug нарушила тайминги, но это и понятно... Хотелось бы решить вопрос с ТОЧНОЙ генерацией таймингов для 1-wire на STM32F100 да еще чтобы и в Debug можно было спокойно работать... Может попробовать реализацию задержек на TIM2?...
|
|
|
|
|
Jan 23 2012, 03:17
|
Участник

Группа: Участник
Сообщений: 23
Регистрация: 6-04-11
Пользователь №: 64 159

|
Я тоже так и не смог подключить DS18B20 к дисковери. Делал все как надо, таймер на 1 мкс, без уарта, дрыгал ножкой. А он даже на резет не отзывался. Для отслеживания резета пользовался парой циклов: Код #define Set_PortC_Pin_6_input ((GPIOC->CRL &= ~0x3000000)|(GPIOC->CRL |= 0x4000000)) #define Set_PortC_Pin_6_output ((GPIOC->CRL |= 0x3000000)|(GPIOC->CRL &= ~0xC000000))
int start = 0; int stop = 0; int count = 0;
Set_PortC_Pin_6_output; GPIOC->BSRR = GPIO_BSRR_BR6; delay_us(500); GPIOC->BSRR = GPIO_BSRR_BS6; Set_PortC_Pin_6_input; delay_us(1);
while (DS && count < 10000) { start++; count++; delay_us (1); } count = 0; while ((!(DS)) && count < 10000) { stop++; count++; delay_us (1); }
sprintf(out,"%d-%d",start,stop); ClrLCD (); LCDgotoxy(1,1); LCDputs (out); Но всегда была 1. Перенес код без изменений на lpc1768 и все заработало. В чем разница ? В частоте камня\дергания ножек или настройках пинов ?
|
|
|
|
|
Jan 23 2012, 04:35
|
Частый гость
 
Группа: Свой
Сообщений: 93
Регистрация: 13-01-12
Из: Гатчина
Пользователь №: 69 333

|
Цитата(Aner @ Jan 22 2012, 18:42)  Все из себя 32 битные. Но вот как только делаешь свою инжину, особенно привязанню к регистрам, потрам, времянке, то тут ARMы слабоваты. И в ряде проектов пришлось вернуться к PIC, Atmel-ам и их клонам. Например к параллаксовским процам, SX -ам, или к "8-ядерному" пропеллеру. Обвинять микроконтроллер - крайняя стадия выгораживания своей неопытности. Обычно начинают, что во всем виноват компилятор
|
|
|
|
|
Jan 23 2012, 05:33
|

Профессионал
    
Группа: Свой
Сообщений: 1 175
Регистрация: 5-01-05
Пользователь №: 1 807

|
Цитата Это вы программно делаете 1-wire? Ну да. А что в этом такого? Это этакий старт в рамках изучения STM32 ))) Цитата Но всегда была 1 Вот вот... Пока я считаю, что виновата неадекватная реализация задержек... Почему не получилось использовать SysTick надеюсь кто-нить подскажет. И еще в вашем примере довольно странное управление пином... Конфигурацию его нужно делать один раз в режим output open drain и далее принимать инфу через IDR регистр а выставлять на шину через BSRR. И как у вас реализована функция delay_us(1)? И что там за переменная DS? Далее... Читал доки. Вроде заранее узнать длительность выполнения последовательности команд в Cortex-M3 не так то просто как например в AVR. Возможно ли реально это увидеть в IAR EWAVR при подключении через J-link? У меня складывается ощущение, что формировать тайминги на 1-wire в случае STM32 нужно максимально задействовав периферию (EXTI и таймеры). Так может получиться проще и круче ))))
|
|
|
|
|
Jan 23 2012, 05:54
|
Местный
  
Группа: Участник
Сообщений: 313
Регистрация: 2-07-11
Пользователь №: 66 023

|
Цитата(ivainc1789 @ Jan 22 2012, 21:28)  при Fhclk = 24MHz частота вывода на пин составляет 6MHz. Но это только при макс оптимизации и в случае НЕИСПОЛЬЗОВАНИЯ библиотек. Конечно, библиотеки выкинуть. Для такого совсем не годятся. Цитата(ivainc1789 @ Jan 22 2012, 21:28)  Но остался важный вопрос - почему нельзя в данном контексте использовать SysTick таймер? Функцию задержки на его основе я проверял - отдельно все работает нормально... Задержка на SysTick вроде нормально сделана... Можно, дёргая какую-нибудь ногу до и после, проверить осциллографом на сколько она задерживает в работе с 1-wire? То есть например вставить в вашу программу, для ноги 2 порта B: Код GPIOB->BSRR=GPIO_BSRR_BS2; Delay1wire(80*us); GPIOB->BSRR=GPIO_BSRR_BR2;
Сообщение отредактировал maksimp - Jan 23 2012, 06:16
|
|
|
|
|
Jan 23 2012, 06:12
|
Участник

Группа: Участник
Сообщений: 23
Регистрация: 6-04-11
Пользователь №: 64 159

|
Цитата(ivainc1789 @ Jan 23 2012, 08:33)  И еще в вашем примере довольно странное управление пином... Конфигурацию его нужно делать один раз в режим output open drain и далее принимать инфу через IDR регистр а выставлять на шину через BSRR. И как у вас реализована функция delay_us(1)? И что там за переменная DS? Код #define DS (GPIOC->IDR & GPIO_IDR_IDR6)
void DevTIM2 (void) { RCC->APB1ENR |= RCC_APB1ENR_TIM2EN; TIM2->CR1 = 0; TIM2->CR2 = 0; TIM2->CR1 |= TIM_CR1_OPM | TIM_CR1_ARPE; }
void delay_us (uint32_t us) { TIM2->PSC = 23; TIM2->ARR = us; TIM2->CR1 |= TIM_CR1_CEN; while (TIM2->CR1 & TIM_CR1_CEN); return; }
void delay_ms( uint16_t ms ) { int i; for (i=0; i < ms; i++){ delay_us (1000); } } Нет, пин нужно настраивать и на ввод и на вывод (вроде во всех основоположниках от макса и атмель так делается). В зависимости от ситуации. Я свой код с stm32 абсолютно без изменений (кроме заголовочного файла и настроек пина и таймера) перенес на lpc1768 и у меня все заработало строго по временным диаграммам из даташита. У меня 0 при резете ловился стабильно, только если задержку между опусканием шины и освобождением делать не более 50 мкс. И было это уже не резет, а 1. А вот стоит задержку увеличить до штатных не менее 480 мкс, все, тишина. А без резета все остальное не работает.
Сообщение отредактировал lexanet - Jan 23 2012, 06:14
|
|
|
|
|
Jan 23 2012, 08:05
|

Профессионал
    
Группа: Свой
Сообщений: 1 175
Регистрация: 5-01-05
Пользователь №: 1 807

|
Цитата Можно, дёргая какую-нибудь ногу до и после, проверить осциллографом на сколько она задерживает Именно так я ее и проверял - работает нормально и в пределах допусков! Но после такой задержки прочитать заранее известное состояние шины 1-wire почему-то не получается (см. main.c из первого поста) и это тревожит... Т. е. как бы выходит, что SysTick таймер, являющийся периферией ядра - это не то же самое, что стандартные периферийние таймеры на APB2 (при Fhclk = Fapb2 естественно). И это при том, что если вручную установить (замкнуть шину) 1-wire на землю, то в рантайме после этой задержки посредством SysTick состояние 1-wire прекрасно читается как 0. Чудеса какие-то... Цитата Нет, пин нужно настраивать и на ввод и на вывод (вроде во всех основоположниках от макса и атмель так делается) все же рекомендую обратиться к ref manual на STM32F100 rev4 стр. 103: Output configuration When the I/O Port is programmed as Output: ● The Output Buffer is enabled: – Open Drain Mode: A ”0” in the Output register activates the N-MOS while a ”1” in the Output register leaves the port in Hi-Z. (the P-MOS is never activated) – Push-Pull Mode: A ”0” in the Output register activates the N-MOS while a ”1” in the Output register activates the P-MOS. ● The Schmitt Trigger Input is activated. ● The weak pull-up and pull-down resistors are disabled. ● The data present on the I/O pin is sampled into the Input Data Register every APB2 clock cycle ● A read access to the Input Data Register gets the I/O state in open drain mode ● A read access to the Output Data register gets the last written value in Push-Pull modeПоэтому лучше все же конфиг на лету не делать, но по-вашему вроде все равно должно работать... Цитата У меня 0 при резете ловился стабильно, только если задержку между опусканием шины и освобождением делать не более 50 мкс. И было это уже не резет, а 1. А вот стоит задержку увеличить до штатных не менее 480 мкс, все, тишина. секунду... что-то тут не так... задержка между отпусканием шины и ЧТЕНИЕМ ее уже известна на момент отпускания и равна примерно (35+50)us. Причем 35 формирует датчик и 50 добавляем мы... или я что-то не понял?..... После "вторых" 480us - ясный хрен будет прочитана 1... Посмотрел, у вас задержки сделаны на TIM2. Неужели и так не прочитаю 0??? Сення после работы попробую обязательно... И еще... Стабильность HSI для поддержки 1-wire вполне достаточна (~2.5% в широком темп диапазоне) и не может стать причиной сбоев на шине при переходе от mcu к mcu... Все это ИМХО, конечно....
|
|
|
|
|
Jan 23 2012, 08:19
|
Участник

Группа: Участник
Сообщений: 23
Регистрация: 6-04-11
Пользователь №: 64 159

|
Для проверки живости датчика и работоспособности программы ни кварц ни таймер не нужен. Для функции резета и приема от датчика ответа временные зависимости не нужны. Достаточно на глаз настроить цикл типа: Код void Delay (long cnt) { while (cnt--); } и дальше как по DS. Выставляем ногу на вывод, выводим 0, и ждем хоть бесконечность, но можно на глаз около секунды. А потом либо выводим 1 и ногу на ввод или сразу ногу МК на ввод. И в бесконечном цикле ждем пока на ноге появиться 0. Должна появиться, запускаем новый цикл и ждем опять 1. Если это все происходит, то датчик есть, он живой и МК готов с ним работать.
Сообщение отредактировал lexanet - Jan 23 2012, 08:20
|
|
|
|
|
Jan 23 2012, 08:32
|

Профессионал
    
Группа: Свой
Сообщений: 1 175
Регистрация: 5-01-05
Пользователь №: 1 807

|
Цитата Достаточно на глаз настроить... а если частота тактирования Fhclk изменится (в другом проекте)??? Опять настраивать? Цитата ...И в бесконечном цикле ждем пока на ноге появиться 0 Конечно, так делать не стоит. Любая помеха на шине будет воспринята как присутствие девайса. Хотя потом его ROM код все равно не прочитается )))) ....
|
|
|
|
|
Jan 23 2012, 08:45
|
Местный
  
Группа: Участник
Сообщений: 313
Регистрация: 2-07-11
Пользователь №: 66 023

|
Цитата(ivainc1789 @ Jan 23 2012, 12:05)  Именно так я ее и проверял - работает нормально и в пределах допусков! Но после такой задержки прочитать заранее известное состояние шины 1-wire почему-то не получается (см. main.c из первого поста) и это тревожит... Если попробовать примерно так, убрав непонятные (некоторым, например мне) функции, вывести результат чтения на другую ногу. Здесь ноги 12 и 13 порта B индицируют работу задержки и результат чтения: Код Work: GPIOC->BSRR=GPIO_BSRR_BR15; Delay1wire(500*us); __istate_t s = __get_interrupt_state(); __disable_interrupt(); GPIOC->BSRR=GPIO_BSRR_BS15; // через 35us DS18B20 удерживает DQ=0 100us GPIOB->BSRR=GPIO_BSRR_BS12; Delay1wire(80*us); GPIOB->BSRR=GPIO_BSRR_BR12; tmp=(GPIOC->IDR >> 15)&1; GPIOB->BSRR=tmp?GPIO_BSRR_BS13:GPIO_BSRR_BR13; GPIOB->BSRR=GPIO_BSRR_BS12; Delay1wire(500*us); GPIOB->BSRR=GPIO_BSRR_BR12; __set_interrupt_state(s); goto Work; Или вот так: Код Work: GPIOC->BSRR=GPIO_BSRR_BR15; Delay1wire(500*us); __istate_t s = __get_interrupt_state(); __disable_interrupt(); GPIOC->BSRR=GPIO_BSRR_BS15; // через 35us DS18B20 удерживает DQ=0 100us int i; for(i=0;i<20;i++) { GPIOB->BSRR=GPIO_BSRR_BS12; Delay1wire(8*us); GPIOB->BSRR=GPIO_BSRR_BR12; GPIOB->BSRR=GPIO_BSRR_BS13; Delay1wire(1*us); GPIOB->BSRR=GPIO_BSRR_BR13; Delay1wire(1*us); tmp=(GPIOC->IDR >> 15)&1; GPIOB->BSRR=tmp?GPIO_BSRR_BS13:GPIO_BSRR_BR13; } GPIOB->BSRR=GPIO_BSRR_BS12; Delay1wire(500*us); GPIOB->BSRR=GPIO_BSRR_BR12; __set_interrupt_state(s); goto Work; Здесь на ноге 13 порта B увидим 20 пичков через 10 мкс, и после каждого - уровень прочтённый с шины. (и отладочные ноги нужно заранее сконфигурировать на выход)
Сообщение отредактировал maksimp - Jan 23 2012, 13:08
|
|
|
|
|
Jan 23 2012, 10:06
|
Участник

Группа: Участник
Сообщений: 23
Регистрация: 6-04-11
Пользователь №: 64 159

|
Цитата(ivainc1789 @ Jan 23 2012, 11:32)  а если частота тактирования Fhclk изменится (в другом проекте)??? Опять настраивать? Конечно, так делать не стоит. Любая помеха на шине будет воспринята как присутствие девайса. Хотя потом его ROM код все равно не прочитается )))) .... Нет, никакого проекта, все это исключительно для проверки, так сказать, первого подхода в жизни к 1-wire. Блин, сложности какие то с простейшим датчиком. Вся работа с ним должна реализовываться начальными знаниями. Достаточно человеку уметь зажечь/погасить светодиод и прочитать состояние пина и все, ничего более. Вот рабочий код LPC1768 (рабочий - значит работает): Код char ow_reset (void) { char ret = 10;
LPC_GPIO2->FIODIR |= (1<<1); //Pin 2.1 - OUT LPC_GPIO2->FIOSET |= (1<<1); //Pi 2.1 - "1" delay_us (1); LPC_GPIO2->FIOCLR |= (1<<1); //Pin 2.1 - "0" delay_us (480); LPC_GPIO2->FIODIR &= ~(1<<1); //Pin 2.1 - IN delay_us (80); if (LPC_GPIO2->FIOPIN & 2) //Если через 80 мкс все еще на пине "1", датчика нет { ret = 0; } else { ret = 1; } delay_us (400); //Ждем окончания тайм-слота return ret; } то же код на stm32f100 - не работает: Код #define Set_PortC_Pin_6_output ((GPIOC->CRL |= 0x3000000)|(GPIOC->CRL &= ~0xC000000)) #define Set_PortC_Pin_6_input ((GPIOC->CRL &= ~0x3000000)|(GPIOC->CRL |= 0x4000000))
char ow_reset (void) { char ret = 10;
Set_PortC_Pin_6_output; // OUT GPIOC->BSRR = GPIO_BSRR_BS6; // "1" delay_us (1); GPIOC->BSRR = GPIO_BSRR_BR6; // "0" delay_us (480); Set_PortC_Pin_6_input; // IN delay_us (80); if (GPIOC->IDR & GPIO_IDR_IDR6) //Если через 80 мкс все еще на пине "1", датчика нет { ret = 0; } else { ret = 1; } delay_us (400); //Ждем окончания тайм-слота return ret; } В чем же проблема ? Какие еще тайные знания нужны ? Может в stm не тот режим пина ?
|
|
|
|
|
Jan 23 2012, 13:04
|
Местный
  
Группа: Участник
Сообщений: 313
Регистрация: 2-07-11
Пользователь №: 66 023

|
Цитата(lexanet @ Jan 23 2012, 14:06)  то же код на stm32f100 - не работает: В чем же проблема ? Какие еще тайные знания нужны ? Может в stm не тот режим пина ? Тактирование разрешено? Код RCC->APB2ENR |= RCC_APB2ENR_IOPCEN | RCC_APB2ENR_AFIOEN; Тоже, как я выше писал, добавьте дрыгание ещё одной ногой и осциллографом таким образом проверьте величины задержек.
|
|
|
|
|
Jan 23 2012, 13:33
|
Участник

Группа: Участник
Сообщений: 23
Регистрация: 6-04-11
Пользователь №: 64 159

|
Цитата(maksimp @ Jan 23 2012, 16:04)  Тактирование разрешено? Код RCC->APB2ENR |= RCC_APB2ENR_IOPCEN | RCC_APB2ENR_AFIOEN; Тоже, как я выше писал, добавьте дрыгание ещё одной ногой и осциллографом таким образом проверьте величины задержек. Тактирование разрешено. На том же порту PORTС.8 и PORTC.9 светодиоды, один мыргает раз в секунду (от таймера, позволяет приблизительно проверить его), второй должен включиться, когда наконец то обнаружится ответ о датчика. В настройке таймера прескалер переменный, в главном цикле он меняется от 10 до 50 с шагом 1. Также переменная задержка в функции резета между 0 и отпусканием шины (200 - 1000 мкс, шаг 25 мкс). В общем, ответ ОБЯЗАН быть, при таких условиях поиска. А нет его, скорей всего, изза каких то тонкостей, которых я не знаю (не тот режим пина (общего назначения, общего назначения с открытым стоком или вход не в том режиме или во время переключения с выхода на вход что то проскакивает, что сносит башню датчику)). Во всех виденных мною рабочих прог (по словам создателей), настройка пинов происходит с помощью библиотечных функций: Код void oow_pin_out(void) { RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_Init(GPIOA, &GPIO_InitStructure); }
void oow_pin_in(void) { RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; GPIO_Init(GPIOA, &GPIO_InitStructure); } Может в GPIO_Init() есть какой то секрет ?
Сообщение отредактировал lexanet - Jan 23 2012, 13:41
|
|
|
|
|
Jan 23 2012, 18:33
|
Местный
  
Группа: Участник
Сообщений: 313
Регистрация: 2-07-11
Пользователь №: 66 023

|
Цитата(lexanet @ Jan 23 2012, 17:33)  Тактирование разрешено. На том же порту PORTС.8 и PORTC.9 светодиоды, один мыргает раз в секунду Уберите мигание PORTС.8 там где оно у вас сейчас и приделайте его прямо сюда: Код GPIOC->BSRR = GPIO_BSRR_BS6; // "1" GPIOC->BSRR = GPIO_BSRR_BS8; // +++ delay_us (1); GPIOC->BSRR = GPIO_BSRR_BR8; // +++ GPIOC->BSRR = GPIO_BSRR_BR6; // "0" delay_us (480); Set_PortC_Pin_6_input; // IN GPIOC->BSRR = GPIO_BSRR_BS8; // +++ delay_us (80); GPIOC->BSRR = GPIO_BSRR_BR8; // +++ И проверьте осциллографом что на PORTС.6 и на PORTС.8. Подтяжка вверх на PORTС.6 у вас резистором к +питания на плате? Если нет то её нужно включить у процессора, сейчас она выключена. Цитата(lexanet @ Jan 23 2012, 17:33)  Может в GPIO_Init() есть какой то секрет ? Вряд ли. У меня через GPIOC->CRL работает.
Сообщение отредактировал maksimp - Jan 23 2012, 18:41
|
|
|
|
|
Jan 24 2012, 02:59
|
Участник

Группа: Участник
Сообщений: 23
Регистрация: 6-04-11
Пользователь №: 64 159

|
Цитата(maksimp @ Jan 23 2012, 21:33)  Уберите мигание PORTС.8 там где оно у вас сейчас и приделайте его прямо сюда: Код GPIOC->BSRR = GPIO_BSRR_BS6; // "1" GPIOC->BSRR = GPIO_BSRR_BS8; // +++ delay_us (1); GPIOC->BSRR = GPIO_BSRR_BR8; // +++ GPIOC->BSRR = GPIO_BSRR_BR6; // "0" delay_us (480); Set_PortC_Pin_6_input; // IN GPIOC->BSRR = GPIO_BSRR_BS8; // +++ delay_us (80); GPIOC->BSRR = GPIO_BSRR_BR8; // +++ И проверьте осциллографом что на PORTС.6 и на PORTС.8. Подтяжка вверх на PORTС.6 у вас резистором к +питания на плате? Если нет то её нужно включить у процессора, сейчас она выключена. Вряд ли. У меня через GPIOC->CRL работает. Подтяжка есть, осцила нет. Да и что именно проверять им ? Единица на пин выводится обнозначно, а точность delay_us (1) на данном этапе не критична, delay_us (1000000) - на глаз секунда и этого достаточно. Дайте, если не трудно, свою настройку пина и функции резета. Может я что то упускаю из вида.
|
|
|
|
|
Jan 24 2012, 05:32
|
Местный
  
Группа: Участник
Сообщений: 313
Регистрация: 2-07-11
Пользователь №: 66 023

|
Цитата(lexanet @ Jan 24 2012, 06:59)  Подтяжка есть, осцила нет. Да и что именно проверять им ? Осциллограф - критически важный прибор для наладки таких устройств. Проверять - что именно там у вас происходит, форму сигналов посмотреть. Иногда совешенно неясная проблема становится очевидной. Осциллограф можно сделать из самого контроллера. Настроить АЦП чтобы через DMA в буфер складывал отсчёты. Как буфер заполнится - по UART его весь в компьютер и можно смотреть что там происходило. Цитата(lexanet @ Jan 24 2012, 06:59)  а точность delay_us (1) на данном этапе не критична, delay_us (1000000) - на глаз секунда и этого достаточно. Точность не критична лишь до определённого предела. А если delay_us (1) даёт задержку на 900 микросекунд например? Цитата(lexanet @ Jan 24 2012, 06:59)  Дайте, если не трудно, свою настройку пина и функции резета. Может я что то упускаю из вида. С такими и подобными микросхемами не работал, такой функции дать не могу. Настройку провожу например так: Код // 0 = аналог; 4 = вход; 8 = вход с подтяжкой // норм выход двухтактн: 2 = вых 2 МГц; 1 = вых 10 МГц; 3 = вых 50 МГц; // норм выход октр колл: 6 = вых 2 МГц; 5 = вых 10 МГц; 7 = вых 50 МГц; // спец выход двухтактн: 0xa = вых 2 МГц; 9 = вых 10 МГц; 0xb = вых 50 МГц; // спец выход октр колл: 0xe = вых 2 МГц; 0xd = вых 10 МГц; 0xf = вых 50 МГц;
GPIOA->CRL=0x00220000; // PA7...PA0 GPIOA->CRH=0x44488466; // PA15...PA8 и далее для остальных портов.
|
|
|
|
|
Jan 24 2012, 09:00
|
Местный
  
Группа: Участник
Сообщений: 313
Регистрация: 2-07-11
Пользователь №: 66 023

|
Цитата(ivainc1789 @ Jan 24 2012, 12:19)  Такой цикл выдает на пин С15 импульс/пауза 600us/400us, а не 500us/500us. И это при макс оптимизации. Стоит только вместо двух последних вызовов Delay1wire вставить один Delay1wire(500*us) и все становится нормально: 500us/500us. Почему такой эффект, не пойму? Не знаю но подозреваю на эффекты с регистром SysTick->CTRL . Если так попробовать: Код SysTick->CTRL = 0x00000005;// запуск таймера заранее SysTick->LOAD = 0xffffff; И собственно задержка Код // генератор прецизионных таймингов для 1wire (Tmax[sec]=2^23/Fhclk) static __INLINE void Delay1wire(unsigned int Ticks) { unsigned int x = SysTick->VAL - Ticks; // конечное значение таймера while((x - SysTick->VAL)&0x800000); // пока текущее не уменьшится до конечного // если SysTick->VAL > x то при вычитании происходит переполнение // и старшие разряды становятся равными 1, что проверяется с помощью &0x800000 // такой способ сравнения нужен чтобы правильно работать когда // таймер в счёте переходит с 0 на 0xffffff } Прерывания разрешены или запрещены? Если разрешены то от таймера есть прерывания? С какой частотой?
Сообщение отредактировал maksimp - Jan 24 2012, 17:01
|
|
|
|
|
Jan 24 2012, 11:14
|

Профессионал
    
Группа: Свой
Сообщений: 1 175
Регистрация: 5-01-05
Пользователь №: 1 807

|
Цитата Прерывания разрешены или запрещены? Если разрешены то от таймера есть прерывания? С какой частотой? Все прерывания запрещены еще в SystemInit(). Цитата Код while((x - SysTick->LOAD)&0x800000); // пока текущее не уменьшится до конечного тут не SysTick->VAL должен быть?
|
|
|
|
|
Jan 24 2012, 12:34
|
Местный
  
Группа: Участник
Сообщений: 313
Регистрация: 2-07-11
Пользователь №: 66 023

|
Цитата(ivainc1789 @ Jan 24 2012, 15:14)  тут не SysTick->VAL должен быть? Точно! И в вашем исходном варианте тоже SysTick->VAL нужно вместо LOAD. (отредактировал своё сообщение выше, исправив LOAD на VAL, чтобы заведомо неверный код не попался кому-нибудь и не стоил потраченного зря времени)
Сообщение отредактировал maksimp - Jan 24 2012, 12:43
|
|
|
|
|
Jan 24 2012, 17:39
|
Группа: Участник
Сообщений: 12
Регистрация: 15-07-09
Пользователь №: 51 296

|
Почитал дискусиию и решил проверить действительно ли такие траблы с дискавери. Достал с полки запылившуюся плату (не разу даже не включал до этого), подключил к ней датчик, нашел месяц назад модифицированный под использование с ds18b20 стандартный кейловский проект для stm32f103, скопировал его в новую папку, указал в настройках проекта нужный чип, указал отладку st-link, поправил константу тактовой частоты в хедере, содержащем код задержек (написан по мотивам winavr delay.h), скомпилил и запустил в отладке (лениво было искать ttl-usart->usb переходник). На выходе в переменной вижу искомую температуру. Погрел рукой датчик - температура меняется без проблем. Либу писал ещё для atmega64 - без проблем работает на 8 МГц. С небольшими доработками (в основном касаемо GPIO) вставлял либу в проекты для LPC2368, LPC1768, LPC1343, LPC1114 (кроме того пришлось поменять значение с 3e6 на 4е6 в процедурах задержки на микросекунды). Легко прикрутилась к stm32f103 и как оказалось к stm32f100. Проект в Keil прилагаю. Если датчик не обнаружен или проблемы при сравнении CRC, то возвращает -128 как ошибку (такую температуру реальный датчик всё равно не возвращает). Кому интересно - пользуйтесь на здоровье.
|
|
|
|
|
Jan 25 2012, 04:55
|
Участник

Группа: Участник
Сообщений: 23
Регистрация: 6-04-11
Пользователь №: 64 159

|
Цитата(shista @ Jan 24 2012, 20:39)  Кому интересно - пользуйтесь на здоровье. Спасибо, ЧЕЛОВЕЧИЩЕ !!! Взял у Вас функции _delay_us(), _delay_ms(), _delay_loop(), перенес в свой проект и все заработало  Еще раз, огромное спасибо.
|
|
|
|
|
Jan 25 2012, 07:05
|

Профессионал
    
Группа: Свой
Сообщений: 1 175
Регистрация: 5-01-05
Пользователь №: 1 807

|
Код Почитал дискусиию и решил проверить действительно ли такие траблы... Если вы внимательно читали, то понимаете, что суть темы не в том, чтобы подключить датчик DS18B20 к STM32F100 как таковой - он у меня уже давно работает именно на софтовых задержках, реализации которых в принципе достаточно для большинства проектов. Я бы даже сказал, что нет необходимости эту реализацию задержек как-то переделывать, т. к. на время работы с шиной 1-wire все равно придется приостанавливать большинство других софтверных задач, т. к. времянка слишком жесткая... Мое неудачное портирование исходников 1-wire на STM32F100 было связано с попыткой использования для счета задержек systick таймера ядра. Опять же, я осознаю, что это излишне и не нужно - по сути ничего не дает, но поведение этого таймера на счете "мелких" задержек вызвало мое непонимание его работы. Вот это и напрягает... Я был бы признателен тому, кто смог бы выделить время и проверить, в чем тут может быть проблема... Повторюсь, в чем проблема... После счета задержки на основе этого таймера состояние шины 1-wire не может быть достоверно прочитано в рамках, например, сброса/проверки этой шины: Код // генератор прецизионных таймингов для 1wire (Tmax[sec]=2^24/Fhclk) __INLINE void Delay1wire(unsigned int Ticks){ SysTick->LOAD = Ticks - 1;// возможна подстройка для точности SysTick->CTRL = 0x00000005;// запуск таймера while(!BITCHK(SysTick->CTRL,SysTick_CTRL_COUNTFLAG));// пока не установится COUNTFLAG SysTick->CTRL = 0x00000004;// останов таймера }
// пин C15 настроен как GPIO_Mode_Out_OD ( эмуляция 1-wire) // к пину C15 припаян внешний pull-up 5k с датчиком DS18B20 // пин A11 тестовый , настроен как GPIO_Mode_Out_PP Work: GPIOC->BRR=GPIO_BRR_BR15;// сбросить С15 (шина в состояние "0") Delay1wire(500*us); __istate_t s = __get_interrupt_state(); __disable_interrupt(); GPIOC->BSRR=GPIO_BSRR_BS15;// установить C15 (шина в состояние "1") Delay1wire(80*us); tmp=(GPIOC->IDR >> 15)&1;// получить текущее состояние шины(должен быть "0" при испр датчике __set_interrupt_state(s); GPIOA->BSRR=tmp?GPIO_BSRR_BS11:GPIO_BSRR_BR11;// тестовый пин(при подкл исправном датчике) всегда = 1 = ошибка !!!!!! Delay1wire(420*us); goto Work; В вышеприведенном коде не удается правильно прочитать состояние шины. Далее, для поиска возможной ошибки, я упростил процедуру максимально: Код // пин C15 настроен как GPIO_Mode_Out_OD ( эмуляция 1-wire) // к пину C15 припаян внешний pull-up 5k с датчиком DS18B20 Work: GPIOC->BRR=GPIO_BRR_BR15;// сбросить С15 Delay1wire(500*us); GPIOC->BSRR=GPIO_BSRR_BS15;// установить C15 Delay1wire(80*us); Delay1wire(420*us); goto Work; По идее, этот код должен давать на С15 сигнал импульс/пауза 500us/500us. У меня он почему-то дает 600us/400us. Естественно все прерывания запрещены. Хотелось бы понять причину такого несоответствия... Возможно, это поможет понять почему исходно не читается правильно состояние шины...
|
|
|
|
|
Jan 25 2012, 13:52
|
Группа: Участник
Сообщений: 12
Регистрация: 15-07-09
Пользователь №: 51 296

|
Цитата Мое неудачное портирование исходников 1-wire на STM32F100 было связано с попыткой использования для счета задержек systick таймера ядра. Пришел домой с работы. Модифицировал предыдущий код на работу с systick таймером. Проверил значение переменной в отладке. Менял температуру датчика. Опять работает... Что я делаю не так? Сразу скажу, что кусок кода не мой, я брал из библиотеки Cox, жаль её перерабатывают, старые исходники снесли с сайта, а новых до сих пор не написали... Цитата Хотелось бы понять причину такого несоответствия... А можно весь проект? Или хотя бы основной файл, чтобы не заниматься лишней работой по инициализации, а просто потестить хотя бы в том же отладчике...
|
|
|
|
|
Jan 25 2012, 17:27
|

Профессионал
    
Группа: Свой
Сообщений: 1 175
Регистрация: 5-01-05
Пользователь №: 1 807

|
Цитата А можно весь проект? Конечно. Все подготовил и перепроверил. Проблема описана в main.c и присутствует при отладке с любым уровнем оптимизации... Я бессилен... ))) Проект создан в IAR EWARM v6.30.4.
|
|
|
|
|
Jan 25 2012, 19:01
|
Группа: Участник
Сообщений: 12
Регистрация: 15-07-09
Пользователь №: 51 296

|
Посмотреть смогу не раньше пятницы, в четверг в командировке буду. Кстати, вышеприведённый келовский вариант с systick запускать не пробовали? У меня там всё ОК работает. Анализатором времянки не смотрел, но датчик стабильно выдаёт температуру.
Мельком глянул исходник и не увидел переключение направления работы пина (вход/выход). Т.е. вы устанавливаете пин в высокое состояние и после паузы не переключив направления работы пина пытаетесь с него прочитать. Ну тут начинается соперничество токов выхода порта контроллера и выхода датчика, думаю не в пользу последнего. Отсюда и пожизненная единица. Для начала сделайте переключение направления работы пина (регистры GPIOx_CRL). Можете глянуть как это сделано у меня (макросы T_SENS_DOWN, T_SENS_FREE).
|
|
|
|
|
Jan 25 2012, 23:30
|

Профессионал
    
Группа: Свой
Сообщений: 1 175
Регистрация: 5-01-05
Пользователь №: 1 807

|
Цитата(shista @ Jan 25 2012, 23:01)  Посмотреть смогу не раньше пятницы, в четверг в командировке буду. Кстати, вышеприведённый келовский вариант с systick запускать не пробовали? У меня там всё ОК работает. Анализатором времянки не смотрел, но датчик стабильно выдаёт температуру. Обязательно попробую, но тоже не быстро... Цитата Мельком глянул исходник и не увидел переключение направления работы пина (вход/выход) Я вроде выше цитировал ref manual. Если пин настроен на вывод, то сэмплирование его (через IDR регистр) на вход не отключается и доступно. Это же не AVR! Благодаря пулл-апу шина восстанавливается очень быстро. См. ниже вариант с задержкой 500/500 - там ведь пин нормально переключается?... Кроме того, если задержку заменить на чисто софтовую без systick'а - сразу все работает...
|
|
|
|
|
Jan 26 2012, 05:28
|
Местный
  
Группа: Участник
Сообщений: 313
Регистрация: 2-07-11
Пользователь №: 66 023

|
Цитата(ivainc1789 @ Jan 25 2012, 11:05)  Повторюсь, в чем проблема... После счета задержки на основе этого таймера состояние шины 1-wire не может быть достоверно прочитано в рамках, например, сброса/проверки этой шины: Код // генератор прецизионных таймингов для 1wire (Tmax[sec]=2^24/Fhclk) __INLINE void Delay1wire(unsigned int Ticks){ SysTick->LOAD = Ticks - 1;// возможна подстройка для точности SysTick->CTRL = 0x00000005;// запуск таймера while(!BITCHK(SysTick->CTRL,SysTick_CTRL_COUNTFLAG));// пока не установится COUNTFLAG SysTick->CTRL = 0x00000004;// останов таймера } Замените SysTick->LOAD на SysTick->VAL. SysTick->LOAD переписывается в SysTick->VAL доходит до 0. Когда задержка делается первый раз, то она заканчивается с SysTick->VAL равным SysTick->LOAD или немного меньше. Следующая задержка таким образом будет на столько тактов сколько в SysTick->VAL осталось с прошлго раза, то есть на величину предыдущей задержки. Вероятно нужно так: Код __INLINE void Delay1wire(unsigned int Ticks){ SysTick->VAL = Ticks - 1;// возможна подстройка для точности SysTick->CTRL = 0x00000005;// запуск таймера while(!BITCHK(SysTick->CTRL,SysTick_CTRL_COUNTFLAG));// пока не установится COUNTFLAG SysTick->CTRL = 0x00000004;// останов таймера }
|
|
|
|
|
Jan 31 2012, 09:06
|
Участник

Группа: Свой
Сообщений: 73
Регистрация: 14-10-08
Из: Omsk
Пользователь №: 40 929

|
Когда-то делал на AVR асинхронный обмен по 1-wire через регистры сравнения таймера. Таймер тактировался частотой 1 МГц, что давало разрешение 1 мкс, в первый регистр сравнения записывалась длительность задержки в зависимости от того, что нужно было сделать - передать 0, 1 или прочитать шину, во второй - общая длительность бита. В обработчиках прерываний по совпадениям делались все ногодрыги и переключения режима пина ввод-вывод. Во втором обработчике производился также запуск следующего цикла. Алгоритм строился по принципу конечного автомата. В основной программе достаточно было запустить измерение и дождаться результата. Параллельно опрашивалось 4 датчика. Значения для таймера настроил по осциллографу с учетом времени входа в обработчик прерывания и выполнения команд в нем. Думаю, что для STM32 можно применить такой подход, несколько его модернизировав, в том числе, с использованием для передачи битов режим таймера с аппаратной генерацией ШИМ, или записав в 4 регистра сравнения фиксированные значения (t0, trd, t1, tbit), разрешать соответствующие прерывания в зависимости от состояния конечного автомата. Возможно, что скоро придется это сделать...
|
|
|
|
|
Jan 31 2012, 11:01
|

Гуру
     
Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095

|
QUOTE (ivainc1789 @ Jan 26 2012, 15:26)  Ну и наконец, из-за особенностей регистра VAL SysTick таймера действительно работоспособный код будет такой: Как-то вы все усложняете. Запустите его считать один раз и навсегда. В начале задержки вычитывайте, добавляйте время задержки - получите время окончания. Далее в цикле вычитывайте VAL, вычитайте из времени окончания. Как только результат вычитания стал отрицательным - задержка окончилась. И все. Не нужно его останавливать/стартовать, можно одновременно использовать для отсчета нескольких задержек и т.д. CODE static __INLINE void Delay1wire(unsigned int Ticks){ unsigned int Stop = SysTick->VAL + Ticks; while((int)(Stop - SysTick->VAL) > 0) ; }
--------------------
На любой вопрос даю любой ответ"Write code that is guaranteed to work, not code that doesn’t seem to break" ( C++ FAQ)
|
|
|
|
|
Jan 31 2012, 11:39
|
Местный
  
Группа: Участник
Сообщений: 313
Регистрация: 2-07-11
Пользователь №: 66 023

|
Цитата(Сергей Борщ @ Jan 31 2012, 14:01)  Код static __INLINE void Delay1wire(unsigned int Ticks){ unsigned int Stop = SysTick->VAL + Ticks; while((int)(Stop - SysTick->VAL) > 0); } Неправильно. Во первых, он считает на уменьшение а не на увеличение. Поэтому не + Ticks а - Ticks. Во вторых, он не 32 разрядный а 24 разрядный. Как выполнить сравнение чтобы работало когда таймер в счёте переходит с 0 на 0xffffff я писал выше в теме.
|
|
|
|
|
Jan 31 2012, 12:05
|

Гуру
     
Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095

|
QUOTE (maksimp @ Jan 31 2012, 13:39)  Неправильно. Во первых, он считает на уменьшение а не на увеличение. Поэтому не + Ticks а - Ticks. Во вторых, он не 32 разрядный а 24 разрядный. Как выполнить сравнение чтобы работало когда таймер в счёте переходит с 0 на 0xffffff я писал выше в теме. Ну, бывает, ошибся. Тогда можно так CODE static __INLINE void Delay1wire(unsigned int Ticks){ unsigned int Stop = (SysTick->VAL - Ticks) << 8; while((int)(Stop - (SysTick->VAL << 8)) < 0) ; } Итого, все тело цикла выливается в три команды: CODE 12:main.cpp **** unsigned int Stop = (SysTick->VAL - Ticks) << 8; 82 .loc 1 12 0 83 0000 044B ldr r3, .L3 @ tmp142, 84 0002 9A68 ldr r2, [r3, #8] @ tmp143, 85 0004 101A subs r0, r2, r0 @ tmp144, tmp143, Ticks 86 .LVL1: 87 0006 0002 lsls r0, r0, #8 @ Stop, tmp144, 88 .LVL2: 89 .L2: 13:main.cpp **** while((int)(Stop - (SysTick->VAL << 8)) < 0) 90 .loc 1 13 0 discriminator 1 91 0008 9A68 ldr r2, [r3, #8] @ tmp146, 92 000a B0EB0222 subs r2, r0, r2, lsl #8 @, Stop, tmp146, 93 000e FBD4 bmi .L2 @, maksimp, у вас - четыре CODE 19:main.cpp **** unsigned int x = SysTick->VAL - Ticks; // конечное значение таймера 119 .loc 1 19 0 120 0000 034B ldr r3, .L7 @ tmp140, 121 0002 9A68 ldr r2, [r3, #8] @ tmp141, 122 0004 101A subs r0, r2, r0 @ x, tmp141, Ticks 123 .LVL4: 124 .L6: 20:main.cpp **** while((x - SysTick->VAL)&0x800000); // пока текущее не уменьшится до конечного 125 .loc 1 20 0 discriminator 1 126 0006 9A68 ldr r2, [r3, #8] @ tmp143, 127 0008 821A subs r2, r0, r2 @ tmp144, x, tmp143 128 000a 1202 lsls r2, r2, #8 @, tmp144, 129 000c FBD4 bmi .L6 @,
--------------------
На любой вопрос даю любой ответ"Write code that is guaranteed to work, not code that doesn’t seem to break" ( C++ FAQ)
|
|
|
|
|
Feb 2 2012, 10:15
|
Группа: Участник
Сообщений: 11
Регистрация: 19-08-11
Пользователь №: 66 793

|
При копировании функции _delay_loop из архива Blink_3, который был приложен ранее, и компилировании её в IAR 6.21. вылетает куча ошибок CODE __asm void _delay_loop(uint32_t __count) { loop SUBS r0,r0,#1 BNE loop BX lr } Ошибки: CODE Error[Pe130]: expected a "{" D:\Документы\IAR Project\DTH-11 ARM\delay.h 11 Error[Pe040]: expected an identifier D:\Документы\IAR Project\DTH-11 ARM\delay.h 36 Error[Pe260]: explicit type is missing ("int" assumed) D:\Документы\IAR Project\DTH-11 ARM\delay.h 36 Error[Pe020]: identifier "loop" is undefined D:\Документы\IAR Project\DTH-11 ARM\delay.h 38 Error[Pe065]: expected a ";" D:\Документы\IAR Project\DTH-11 ARM\delay.h 38 Error[Pe010]: "#" not expected here D:\Документы\IAR Project\DTH-11 ARM\delay.h 38 Error while running C/C++ Compiler Если привести код как написано в документации к IAR: CODE void _delay_loop(uint32_t __count) { asm("loop: \n"); asm("SUBS r0,r0,#1 \n"); asm("BNE loop \n"); asm("BX lr"); } Ругается так: Error[Og010]: Inline assembler instruction does not have a unique size: "BNE loop " Как быть? может что настроить нужно в IDE?
Сообщение отредактировал iPKM - Feb 2 2012, 10:16
|
|
|
|
|
Feb 2 2012, 14:47
|
Группа: Участник
Сообщений: 12
Регистрация: 15-07-09
Пользователь №: 51 296

|
Замените Код asm("BNE loop \n"); на Код asm("BNE.N loop \n"); Код asm("BX lr"); в данном случае лишняя строчка
Сообщение отредактировал shista - Feb 2 2012, 14:59
|
|
|
|
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|