Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Микроконтроллеры (MCU) и микропроцессоры (MPU) > [arm] Термодатчик TMP03/TMP04


Автор: kray20 8.11.2010, 23:21
Нужно запрограммировать термодатчик TMP03/TMP04 в среде IAR  так, чтобы он измерял температуру в каждый момент времени , а потом определял среднее значение температуры . Датчик подключается к плате atmel  используется вывод PB23 Temperature (вывод указан в pdf файле). В вопросе разбираюсь плохо , поэтому буду благодарен любой инф-ии: тексты аналогичных программ, советы , книги, сайты и т.п. 

Автор: UniBomb 9.11.2010, 08:44
Я так подозреваю, что надо запрогроммировать всё же не термодатчик, а эту самую "плату atmel". Но вот что за мк - я так и не смог идентифицировать. Может быть это вымершая серия "классик"?

Автор: Mazzi 9.11.2010, 10:15
Похоже на АРМ. 
Есть документация на плату?

Автор: kray20 14.11.2010, 23:15
Да , согласен, нужно запрограммировать именно плату Atmel ! Микроконтроллер: AT91SAM7X128  

Автор: UniBomb 15.11.2010, 08:56
Ок. Вот тебе ссылки:

http://www.atmel.com/dyn/products/product_card.asp?part_id=3754 со списком справочной информации о мк.
http://www.analog.com/en/temperature-sensing-and-thermal-management/digital-temperature-sensors/tmp03/products/product.html с даташитом на температурный датчик. В даташите к тому же есть пример работы с датчиком на Си.

Автор: kray20 15.11.2010, 10:11
Спасибо, UniBomb  ,но в даташите на датчик пример на asm , а не на си ,к сожалению  ! 

Автор: UniBomb 15.11.2010, 10:16
kray20, опечатался  smile

Автор: kray20 15.11.2010, 12:10
На одном из иностранных форумов нашел код на си по этому датчику(TMP03). Выкладываю вместе с комментарием автора этого кода : 

I was looking for something else, when I discovered this black small thing lost in the middle of the components from the "A trier" (“to be tidy up”) box.
TMP03 is its name. Among the numerous temperature sensors, this one has something different: instead of generating a voltage, or changing its impedance, it produces a variable pulse width ratio depending upon the temperature.
Advantages: The sensor can read temperature meters far from the controller without impedance adaptator. Its provides very accurate reading without costy A/D converter. It comes in convenient TO92 package or in a flat SOT 8 pins chip; and its cheap.

I decided to give him a try. First idea was to use interrupts. Quick and easy, I simply (not to say basically) used the attachInterrupt command. It worked fine. Until the time I decided to switch from one sensor to an other. Brrrm, not so clean. And finally, I decided to use a timeout in order to prevent infinite loops in case of signal failure. Arrrrgl. The attachInterrupt is not a good friend of timers. I then decided to go for a pretty ackward routine made of “wait until level changes”. Which proved to work like a charm. In addition, it is very easy to initialize and to switch from one channel to an other (as many channels as digital inputs…). The timing accuracy is 4µs, which is good enough to achieve .05 °C (Who cares about better?). Here is the code:


Код

// Get actual temperature
void getTemperature(int selectedChannel){
  PORTB |=  (1<<PINB5); // Turn status led off
  long timeOut = (micros()+50000); // 50 ms
  byte signalPinMask = (1<<(selectedChannel-1));
  while (PINB & signalPinMask) { // Wait for low state on signal pin
    if (micros() > timeOut) break;
  }
  while (~PINB & signalPinMask) { // Wait for high state on signal pin
   if (micros() > timeOut) break;
  }
  long T1Start = micros();  // T1 starts now
  while (PINB & signalPinMask) { // While T1 is on
    if (micros() > timeOut) break;
  }
  long T2Start = micros();   
  long T1Duration = (T2Start - T1Start);
  while (~PINB & signalPinMask) { // While T2 is on
    if (micros() > timeOut) break;
  }
  if (micros() > timeOut) {
    errorCode = ERR_MIS_SIGNAL; // Set global variable error code
    temperature = 0;
  }
  else {
    long T2Duration = micros() - T2Start;
    errorCode = ERR_NONE; // Set global variable error code
    temperature = 508150 - long((400000.00F * T1Duration) / T2Duration);
  }
  PORTB &= ~(1<<PINB5); // Turn status led off
}


Что можно сказать по этому коду ?! может он подойти под мои задачи ?! 


M
UniBomb
Для форматирования кода не забываем использовать соответствующую кнопку



Автор: UniBomb 15.11.2010, 13:10
kray20, на вид можно сказать, что код рабочий. Смущает только число 508150 в 28 строчке, ибо судя по даташиту там должно стоять 235000. И конечно когда будете переносить код не забудьте изменить регистры (вернее даже соответствующие выводы) под свою схему.

Автор: kray20 15.11.2010, 22:57
Спасибо большое, UniBomb , замечание насчет кода учту ! 
Укажите ,плиз,  строчки, в которых нужно поменять вывод в соответствии со своей платой !
что нужно задавать в переменной selectedChannel ?

Автор: UniBomb 16.11.2010, 00:06
Цитата(kray20 @  15.11.2010,  22:57 Найти цитируемый пост)
что нужно задавать в переменной selectedChannel ?

Подозреваю что 24. Остальное в принципе без изменений.

Автор: kray20 16.11.2010, 20:29
Цитата(UniBomb @ 16.11.2010,  00:06)
Цитата(kray20 @  15.11.2010,  22:57 Найти цитируемый пост)
что нужно задавать в переменной selectedChannel ?

Подозреваю что 24. Остальное в принципе без изменений.

Ни совсем понял почему 24, нельзя ли пояснить, за что конкретно отвечает переменная  selectedChannel?!


В чем различие между:  while (PINB & signalPinMask) и  while (~PINB & signalPinMask) ?!
судя по комментарием ,это ожидание среза выходного сигнала термодатчика и ожидание его фронта во втором случае ! 
                                     

Автор: UniBomb 17.11.2010, 10:54
Цитата(kray20 @  16.11.2010,  20:29 Найти цитируемый пост)
Ни совсем понял почему 24, нельзя ли пояснить, за что конкретно отвечает переменная  selectedChannel?!

24 потому, что это вывод, (судя по таблице) к которому подключается датчик, по счёту двадцать четвёртый. Т.к. нумерация с нуля, то номер 23 (потому там и декремент). Переменная же эта задаёт маску. 


Цитата(kray20 @  16.11.2010,  20:29 Найти цитируемый пост)
while (PINB & signalPinMask) и  while (~PINB & signalPinMask) 

Первый цикл работает "пока установлен", а второй "пока не установлен". Разница в операции "~", которая инвертирует значение порта. Ну например в данном случае:

PINB:
01011010010110100101101001011010

маска:
00000000100000000000000000000000

результат операции &:
00000000000000000000000000000000

А если PINB имеет следующее значение:
01011010110110100101101001011010

то результат будет:
00000000100000000000000000000000

Таким образом благодаря маске можно отслеживать какие-то конкретные выводы.

Автор: kray20 19.11.2010, 23:40
Большое спасибо ,UniBomb ! Теперь стало яснее ! 
 В строке не совсем понятен побитовый сдвиг влево после декрементации:  byte signalPinMask = (1<<(selectedChannel-1));
допустим в моем случае : selectedChannel=24
затем декрементируем selectedChannel=23
в двоичном коде 23 : 10111
сдвигаем 1<< :           01110
что дает побитовый сдвиг в итоге ?! 

Автор: UniBomb 22.11.2010, 10:10
Цитата(kray20 @  19.11.2010,  23:40 Найти цитируемый пост)
что дает побитовый сдвиг в итоге ?! 

Побитовый сдвиг указывает на какое место нужно поставить исходные биты. Ну например "1 << 5" можно читать как "единичный бит поставить на место пятого бита". Так и тут:

1 << 23 = 100000000000000000000000.

Т.е. не нужно 23 приводить к двоичному виду, оно к тому же и не изменяется.

Добавлено через 13 минут и 25 секунд
И кстати говоря - в твоём случае (когда термодатчик цепляется к одной-единственной ноге и никуда не перетыкается) эту переменную можно объявить константой. 

Автор: kray20 22.11.2010, 21:51
Спасибо большое, теперь все стало понятнее ! 
Начал разбираться с переменной PINB. Вы писали(в посте выше) , что в моем случае PINB это:

01011010010110100101101001011010

В моей таблице выводов в столбце pin записано 69 , если теперь 69 перевести в двоичный код это будет :

1000101

Почему это число в двоичном коде не совпадает с числом 01011010010110100101101001011010  ?!
 

Автор: UniBomb 23.11.2010, 10:15
kray20, я написал "например"  smile Это просто сферическое число в вакууме, высосанное из пальца, и призванное показать смысл операции &

Автор: kray20 23.11.2010, 11:21
извините, UniBomb, невнимательно прочитал ваш пост ! smile

Я ни совсем понял тогда смысл конструкции 

while (PINB & signalPinMask) и  while (~PINB & signalPinMask) 

Получается, что PINB содержит некий массив выводов и ,использую переменную signalPinMask, я могу контролировать нужный мне вывод, т.е. 23 , в цикле while . 

А можно заменить данную часть кода :

Код

  byte signalPinMask = (1<<(selectedChannel-1));
  while (PINB & signalPinMask) { // Wait for low state on signal pin
    if (micros() > timeOut) break;
}


на

Код

int PINB=selectedChannel-1;
 while(PINB LOW) {      // Wait for low state on signal pin
     if (micros() > timeOut) break;
}



и 
Код


  while (~PINB & signalPinMask) { // Wait for high state on signal pin
   if (micros() > timeOut) break;
  }


на

Код

 while(PINB HIGH) {      // Wait for high state on signal pin
     if (micros() > timeOut) break;
}


Будет ли такая замена корректной ?! 

Автор: UniBomb 23.11.2010, 12:59
нет. Во-первых строчка "int PINB=selectedChannel-1;" вызовет ошибку из-за того, что PINB уже определена. Во-вторых не ясен смысл присвоения ему правой части  smile 

Если уж сокращать, то как-то так:

Код

#define isLow PINB&(1 << 23)
#define isHigh ~PINB&(1 << 23)

while(isLow)
{
    //...
}

while(isHigh)
{
    //...
}


Добавлено через 2 минуты и 57 секунд
И тогда в этом случае переменные signalPinMask и selectedChannel будут не нужны.

Автор: kray20 23.11.2010, 22:37
Спасибо большое,  UniBomb, с сокращением теперь все ясно ! smile



Код

int PINB=selectedChannel-1;
 while(PINB LOW) {      // Wait for low state on signal pin
     if (micros() > timeOut) break;
}



Цитата

Во-первых строчка "int PINB=selectedChannel-1;" вызовет ошибку из-за того, что PINB уже определена. Во-вторых не ясен смысл присвоения ему правой части  smile 

Смысл присвоения в том ,что я думал PINB нужно присвоить номер вывода термодатчика, т.е. 23 , но тут понятно ,что я ошибся ! smile


а что в таком случае содержит переменная PINB ?! 
Предполагаю , что PINB=69 ,если учесть, что в таблице выводов для термодатчика в столбце: Port стоит PB24  ,а в столбце Pin стоит число 69

Автор: UniBomb 24.11.2010, 11:49
kray20, я с архитектурой arm плохо знаком. Поэтому не уверен что там как устроено. Посему мои дальнейшие слова стоит проверить в документации.

Во многих контроллерах на управление портами ввода/вывода отводятся несколько регистров. В зависимости от архитектуры это количество может изменяться. Например в простом случае есть регистр направления, указывающий является вывод входом или выходом, есть регистр, который задаёт значение на выходе контроллера. PINx - это регистр, который отображает фактическое состояние выводов вне зависимости от настроек порта.

Т.е. есть несколько выводов, объединённых в регистр B. Некоторые выводы настроены на вход, некоторые на выход. Но на каждом выводе в любой момент времени висит логический уровень "1" или "0". Так вот PINB покажет на каком выводе что находится. Этот регистр как правило доступен только для чтения. Т.е. нельзя изменить его содержимое.

В данном микроконтроллере этот регистр называется вроде как PIO_PDSR.

Автор: kray20 24.11.2010, 13:00
Спасибо большое, за обстоятельное разъяснение вопроса ! Буду изучать ! Получается , что PINB мне ,скорее всего, придется переименовать на подходящий для моего контроллера регистр состояния ?! 

Автор: UniBomb 24.11.2010, 13:06
Цитата(kray20 @  24.11.2010,  13:00 Найти цитируемый пост)
придется переименовать на подходящий для моего контроллера регистр состояния ?!  

 smile 

Автор: kray20 24.11.2010, 13:12
Спасибо, UniBomb ! smile
открыл руководство пользователя П.П.Редькина там написано:
 
PIO_PDSR - регистр состояния данных на ножке
доступ: только для чтения

Благодарю за подсказку ! 

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)