|
STM32F100C6T6 и 1-wire, не отладить в IAR EWARM v6.30.4 |
|
|
|
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
|
|
|