Перейти к содержанию
    

Пытаюсь завести DS18B20 на STM32(дискавери) по USART. Работу с 1-wire делаю по апптоуту максима

Проблемы начинаются после инициализации, после того как послали 0xF0 получили 0x0E, что значит датчик наместе, далее посылаем 0xCC и т.п не буду повторять код. вот собственно после передачи всех команд начинаем получать биты температуры, но все время нули вылазят. Я думаю что ошибка возможна в OneWireReadByte() хотя хз. OneWireSendByte() формирует из hex -> bin вроде правильно, к примеру 0xCC в двоичной 1100 1100, OneWireSendByte формирует и отсылает 0011 0011, какбы задом наперед, т.е сначала младшие биты слова потом старшие.

 

#include "stm32l1xx.h"
#include "PLL/inc/stm32l1xx_gpio.h"
#include "PLL/inc/stm32l1xx_usart.h"
#include "PLL/inc/stm32l1xx_rcc.h"
void Delay_ms(uint32_t ms)
{
       volatile uint32_t nCount;
       RCC_ClocksTypeDef RCC_Clocks;
       RCC_GetClocksFreq (&RCC_Clocks);

       nCount=(RCC_Clocks.HCLK_Frequency/10000)*ms;
       for (; nCount!=0; nCount--);
}

void initPereherial()
{ 
     GPIO_InitTypeDef  GPIO_InitStructure;

     /* Включаем тактирование */
     RCC_AHBPeriphClockCmd(RCC_AHBENR_GPIOAEN, ENABLE);
     RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);

     /* USART1 Rx (PA10) вход */
     GPIO_InitStructure.GPIO_Pin   = GPIO_Pin_10;
     GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz;
     GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_IN;
     GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_AF;
     GPIO_Init(GPIOA, &GPIO_InitStructure);

     /* USART1 Tx (PA9) выход  */
     GPIO_InitStructure.GPIO_Pin   = GPIO_Pin_9;
     GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz;
     GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
     GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_AF;
     GPIO_Init(GPIOA, &GPIO_InitStructure);

     /* Конфигурируем порты PA9, PA10 как альтернативную функцию для USART1 */
     GPIO_PinAFConfig(GPIOA, GPIO_PinSource9, GPIO_AF_USART1);
     GPIO_PinAFConfig(GPIOA, GPIO_PinSource10, GPIO_AF_USART1);

}

void UsartInit(int BaudRate)
{
     USART_InitTypeDef USART_InitStructure; 

     /* Настраиваем USART1 */
     USART_InitStructure.USART_BaudRate            = BaudRate;
     USART_InitStructure.USART_WordLength          = USART_WordLength_8b;
     USART_InitStructure.USART_StopBits            = USART_StopBits_1;
     USART_InitStructure.USART_Parity              = USART_Parity_No ;
     USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
     USART_InitStructure.USART_Mode                = USART_Mode_Rx | USART_Mode_Tx;

     /* Включаем USART1 */
     USART_Init(USART1, &USART_InitStructure);
     USART_Cmd(USART1, ENABLE);
}

volatile uint16_t temp[7];

void OneWireSendByte(uint16_t byte)
{
 for(int i=0; i<8; i++)
 {
   if((byte & (1<<i) ) != 0)
   {
     USART_SendData(USART1, 0xFF);
     Delay_ms(1);
   }else{
     USART_SendData(USART1, 0x00);
   }
 }
}

uint16_t OneWireReadByte()
{
 uint16_t result=0; 

 for(int i=0; i<8; i++)
 {
   USART_SendData(USART1, 0xFF);
   Delay_ms(1);
 }

 for(int i=0; i<8; i++)
 {
   if(USART_ReceiveData(USART1) != 0xFF)
   {
     result |= (1<<i);
   }
 }

return result;
}


int main()
{
 initPereherial();

 UsartInit(9800);
 USART_SendData(USART1, 0xF0);


 USART_DeInit(USART1);
 UsartInit(115200);
 OneWireSendByte(0xCC);
 OneWireSendByte(0x44);

 Delay_ms(750);

 USART_DeInit(USART1);
 UsartInit(9800);
 USART_SendData(USART1, 0xF0);


 USART_DeInit(USART1);
 UsartInit(115200);
 OneWireSendByte(0xCC);
 OneWireSendByte(0xBE);


 for(int i=0; i<8; i++)
 { 
   temp[i] = OneWireReadByte();
 }

}

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Загляните внурь функций USART_SendData/USART_ReceiveData Думаю вопросы отпадут.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Загляните внурь функций USART_SendData/USART_ReceiveData Думаю вопросы отпадут.

и что я там должен был увидеть чтобы меня осинило, записываем и читаем в\из DR, вы с аппноутом знакомы который указывал в ссылке, или работали с 1-wire по uart?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

А зачем Вы задержки налепили в 1 ms? Зачем они там нужны. Задержка только после команды 0х44. Я писал обмен по USART с этим датчиком , правда для MEGA. У ATMEL есть два Application Note (AVR318 и AVR274 ) для этого случая - где чётко расписанно как осуществлять обмен по USART и приложены коды для С. USART он и в Африке USART , а уж DS тем более про С и говорить нечего. Может поможет.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

А зачем Вы задержки налепили в 1 ms? Зачем они там нужны. Задержка только после команды 0х44. Я писал обмен по USART с этим датчиком , правда для MEGA. У ATMEL есть два Application Note (AVR318 и AVR274 ) для этого случая - где чётко расписанно как осуществлять обмен по USART и приложены коды для С. USART он и в Африке USART , а уж DS тем более про С и говорить нечего. Может поможет.

почитаю эти аппы, а про задержку в 1ms, вычитал на какомто форуме что нужно при записи ставить, хотя и без неё все изначально было и также не фурычило

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

и что я там должен был увидеть чтобы меня осинило, записываем и читаем в\из DR, вы с аппноутом знакомы который указывал в ссылке, или работали с 1-wire по uart?

не читал и не работал. Зато достаточно работал с уартом, что бы видеть что код у вас нерабочий. Перед тем как читать DR надо дождаться того что бы там что-то появилось, а перед тем как писать в него надо дождаться пока из него все будет отправлено (задержки у вас там именно за этим стоят, причем почему то не везде).

Аппноуты это конечно здорово, но документацию на контроллер тоже читать надо.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

не читал и не работал. Зато достаточно работал с уартом, что бы видеть что код у вас нерабочий. Перед тем как читать DR надо дождаться того что бы там что-то появилось, а перед тем как писать в него надо дождаться пока из него все будет отправлено (задержки у вас там именно за этим стоят, причем почему то не везде).

Аппноуты это конечно здорово, но документацию на контроллер тоже читать надо.

 

Ожидание освобожнение буфера прописывал не помогает, и ожидание никакое никанает(его там вообще не должно быть)

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Да кстати , между командами 0х44 + Delay и 0xBE должен быть RESET. И ещё один подводный камень - UDRE т.к он обдадает двойной буферизацией и если Вы будите использовать его прерывание , то алгоритм такой - послали бит - отключили UDRE - приняли бит - записали в буфер -вкл. UDRE - снова послали бит. Все команды которые Вы хотите посылать датчику , проще всего расположить в памяти ( у меня в SRAM) и "вытягивать" их оттуда побитно и возвращать на своё же место . Т.е буфер у Вас будет постоянно содержать Ваши команды.

И не забывайте , что после прочтения температуры и ее вывода необходимо (если использовать буфер) занести в часть значений для температуры 0xFF

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

Вот это:

  for(int i=0; i<8; i++)
  {
    if(USART_ReceiveData(USART1) != 0xFF)
    {
      result |= (1<<i);
    }
  }

не считает 8 байт по уарту, а 8 раз считает одно и тоже значение из регистра DR, нафига оно вам 8 раз?

Отправка данных выглядит примерно так (копипаст из семплов)

    USART_SendData(USARTy, data1);
    
    /* Loop until USARTy DR register is empty */ 
    while(USART_GetFlagStatus(USARTy, USART_FLAG_TXE) == RESET)
    {
    }

соответсвенно прием:

 
    /* Loop until the USARTz Receive Data Register is not empty */
    while(USART_GetFlagStatus(USARTz, USART_FLAG_RXNE) == RESET)
    {
    }

    /* Store the received byte in RxBuffer */
    data2 = USART_ReceiveData(USARTz);

 

PS: аппноут, кстати, почитал - интересно, не знал что с 1-wire можно работать через uart

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

Вот это:

  for(int i=0; i<8; i++)
  {
    if(USART_ReceiveData(USART1) != 0xFF)
    {
      result |= (1<<i);
    }
  }

 

да тут ошибка вышла, т.к переписывал код библиотеки с использованием FT232(а там идет работа с буфером), То для STM он должен выглядить так:

 for(int i=0; i<8; i++)
  {
    USART_SendData(USART1, 0xFF); 
    while (!(USART1->SR & USART_SR_TXE)) {} // Ждать освобождения буфера.
    if(USART_ReceiveData(USART1) != 0xFF)
    {
      result |= (1<<i);
    }
  }

 

но это все равно пока проблемы не рашает. смотрю щас как сие реализовано в АВР, там заметил что прирывания на время запроса температуры запрещаются и еще помелочи что, в общем нужно проверить.

 

Да кстати , между командами 0х44 + Delay и 0xBE должен быть RESET. И ещё один подводный камень - UDRE

Я не нашел в даташите упоминание про UDRE. а 0xF0 как раз таки и есть ресет и приветствие. и между 0х44 и 0xBE он стоять не может

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

В вашем коде я не вижу, где задается временная диаграмма 1Wire. Если можно - покажите.

Например прием бита с 1Wire (смотрите рис.14 в даташит Максима): мы даем низкий уровень на более чем 1 мкс (например на 5 мкс), потом ждем например 6 мкс, потом читаем состояние шины, потом ждем >45мкс до следующего бита. Где можно увидеть на какой микросекунде слота происходит семплирование ?

Возможно имеется в виду, что отправка 8 раз подряд байта 0xFF в UART на скорости 115200 как раз эквивалентна (после сглаживания фильтром) подаче низкого уровня на время примерно 8,68мкс (то есть master reaq slot), а затем сразу делается считывание, но не вижу, где ожидание 45 мкс до следующего бита.

Не проще ли это сделать на GPIO и не занимать UART - GPIO хотя бы можно на любой порт вывести.

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Возможно имеется в виду, что отправка 8 раз подряд байта 0xFF в UART на скорости 115200 как раз эквивалентна (после сглаживания фильтром) подаче низкого уровня на время примерно 8,68мкс (то есть master reaq slot), а затем сразу делается считывание, но не вижу, где ожидание 45 мкс до следующего бита.

Не проще ли это сделать на GPIO и не занимать UART - GPIO хотя бы можно на любой порт вывести.

Именно так, потому и диаграмма ненужда. Думал просто ногами дрыгать, но хочеться именно с юартом поработать, потому GPIO пока не рассматриваю.

щас что-то вообще бредятина, при посылке F0, получаю FF, вроде датчик откликается, но ответ должен быть 0x10 - 0x90, раньшебыл 0x0E но эт нормально. при считывании температуры в DR все время болтается 0x80, это видать мои чудеса монтажа сказываются)

 

не это просто команды перепутал.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

А сколько в вашем случае времени проходит при чтении после освобождения шины мастером до момента семплирования ? Это время нужно делать максимально возможным (в пределах тех 15мкс, когда можно делать чтение). Помехоустойчивость такой схемы зависит от программы, тем более что у вас фильтры затягивают сигналы, чтобы 8 импульсов UART превращались в один. У меня были случаи, когда DS18B20 на линии длиной 100м часто сбоил, но при добавлении 2-4 мкс во временные диаграммы все начинало работать стабильно.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Я не нашел в даташите упоминание про UDRE. а 0xF0 как раз таки и есть ресет и приветствие. и между 0х44 и 0xBE он стоять не может

Это из DS тогда уж не знаю какой у Вас

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Это из DS тогда уж не знаю какой у Вас

не пудрите мозг), да ресет подается после 44, но не между 0х44 + Delay и 0xBE

( a 0xCC вместо 0xBE ) <- вот так более понятно непоняток не вызывает

 

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

80, C0, E0, F0, F8, FC, FE, FF

и глохнет, причем меняется только один бит в юарте IDLE. Видать что-то с приривыниями, нужно копать туда

Изменено пользователем iPKM

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

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

Гость
К сожалению, ваш контент содержит запрещённые слова. Пожалуйста, отредактируйте контент, чтобы удалить выделенные ниже слова.
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...