1

I'm trying to program a digital thermometer DS18B20 on 1-Wire using UART and I have weird problems. When I'm debugging this program that runs without breakpoints (or just running program without debugging) I have readings about 100°C. When I put breakpoint before receiving temperature information, it gives me about 50°c. And 3rd option when I just open this window when I can see SFRs and expand UART4 section it gives me proper readings about 25°C. I have Saleae logic analyzer and in all these 3 cases it sends me valid data (about 25°C). I tried to put some delay where breakpoint is (even 2s delay) and it doesn't help. It gives me readings about 50°C (like with breakpoints and not expanded SFRs window). This is probably programming error (I'm starting), but this action with expanded SFRs window is beyond my reasoning. I really don't know what's going on. I hope you can put some light on this situation for me.

I'm using STM32F4-Discovery evaluation board and programming it on Atollic 4.1.0.

My "Library" file:

#include "DS18B20_Lib.h"


void DS18B20_Init(void)
{
    //USART4 PA0
    GPIO_InitTypeDef GS;
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_UART4,ENABLE);
    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA,ENABLE);
    GPIO_PinAFConfig(GPIOA,GPIO_PinSource0,GPIO_AF_UART4);

    GS.GPIO_Mode = GPIO_Mode_AF;
    GS.GPIO_OType = GPIO_OType_PP;
    GS.GPIO_PuPd = GPIO_PuPd_UP;
    GS.GPIO_Speed = GPIO_Speed_50MHz;
    GS.GPIO_Pin = GPIO_Pin_0;
    GPIO_Init(GPIOA,&GS);

    USART_InitTypeDef US;
    US.USART_BaudRate = 115200;
    US.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
    US.USART_Mode = USART_Mode_Tx | USART_Mode_Rx;
    US.USART_Parity = USART_Parity_No;
    US.USART_StopBits = USART_StopBits_1;
    US.USART_WordLength = USART_WordLength_8b;
    USART_Init(UART4,&US);
    USART_SetAddress(UART4,0x12);
    USART_Cmd(UART4,ENABLE);
    USART_HalfDuplexCmd(UART4,ENABLE);

    USART_ITConfig(UART4,USART_IT_TXE | USART_IT_RXNE | USART_IT_TC ,ENABLE);
    /*NVIC_InitTypeDef NS;
    NS.NVIC_IRQChannel = UART4_IRQn;
    NS.NVIC_IRQChannelCmd = ENABLE;
    NS.NVIC_IRQChannelPreemptionPriority = 1;
    NS.NVIC_IRQChannelSubPriority = 1;
    NVIC_Init(&NS);*/

}

uint16_t Reset_1Wire(void)
{
    uint16_t Present;
    while (USART_GetFlagStatus(UART4, USART_FLAG_TC) == RESET);
    UART4->BRR = 0x1117;
    while (USART_GetFlagStatus(UART4, USART_FLAG_TXE) == RESET);
    USART_SendData(UART4,0xF0);
    while (USART_GetFlagStatus(UART4, USART_FLAG_RXNE) == RESET);
    Present = USART_ReceiveData(UART4);
    while (USART_GetFlagStatus(UART4, USART_FLAG_TC) == RESET);
    UART4->BRR = 0x016D;
    return Present;
}

char Read_1Wire(void)
{

    char Data=0;
    int i;
    for(i=0;i<8;i++)
    {
        while (USART_GetFlagStatus(UART4, USART_FLAG_TXE) == RESET);
        USART_SendData(UART4,0xFF);
        while (USART_GetFlagStatus(UART4, USART_FLAG_RXNE) == RESET);
        if(USART_ReceiveData(UART4)==0xFF)
            Data|=0x80;
        else Data|=0;
        if (i!=7) Data=Data>>1;
    }
    return Data;
}

void Write_1Wire(char Data)
{
    char Mask=1;
    int i;
    for(i=0;i<8;i++)
    {
        while (USART_GetFlagStatus(UART4, USART_FLAG_TXE) == RESET);
        if (Data & Mask)
            USART_SendData(UART4,0xFF);
        else
            USART_SendData(UART4,0x00);
        Mask=Mask<<1;
    }
}

uint16_t DS18B20_MeasTemp(void)
{
    uint16_t Data;
    uint16_t LSB;
    uint16_t MSB;
    Reset_1Wire();
    Write_1Wire(0xCC); //SkipRom only 1 device
    Write_1Wire(0x44);
    while(Read_1Wire()==0x00);
    Reset_1Wire();
    Write_1Wire(0xCC);
    Write_1Wire(0xBE);
   /*--------BRAKEPOINT HERE--------*/
    LSB=Read_1Wire();
    MSB=Read_1Wire();
    Data=MSB<<8|LSB;
    Reset_1Wire();
    return Data;
}

And my main function:

int main(void)
{
  char strLine[25];
  uint16_t Temperature;

  LCD_Init();
  LCD_SetColors(GREEN, BLUE);
  LCD_Clear(BLUE);
  LCD_CharSize(16);

  DS18B20_Init();

  sprintf(strLine,"%s","Temp: ");
  LCD_StringLine(20,50,(uint8_t*) strLine);
  //GPIO_Config();
  while (1)
  {
    Presence1Wire();
    Temperature = DS18B20_MeasTemp();
    if (Temperature&0xF000)
        LCD_PutChar(60,50,'-');
    else LCD_PutChar(60,50,'+');
    LCD_PutInt(68,50,(Temperature&0x0FF0)>>4);
    LCD_PutInt(72,64,(Temperature&0xF)*625);
  }

}
Peter Westlake
  • 4,894
  • 1
  • 26
  • 35
Dziat
  • 11
  • 2
  • Never used an STM before, but looking at their [reference manual](http://www.st.com/web/en/resource/technical/document/reference_manual/DM00031020.pdf) it looks like the GPIO needs to be open-drain+pull up; your code implies it is set to push-pull. I think you need `GPIO_OType_OD`, but I can't find a proper header file to be sure. Perhaps the extra power drain running the debugger while the 1-wire is shorting your USART output to ground is causing the issues you are seeing? – Rich Hendricks Mar 06 '14 at 06:19
  • Thanks for your reply. At first I set it open drain and pulled it up by external 4.7k resistor when I was trying to read this lasered ROM number of device and everything was working good, my readings in debugger was the same as in saleae, so I was wondering if I set it pushpull and pull up internally will it work and it did, so i just left it there:). Changing it back to open drain and pulling it up externally didnt help. I have the same problem. – Dziat Mar 06 '14 at 09:17
  • I found out another thing which can help. Lets call these 3 possible options to run this program FS for full speed, BP for breakpoint option and SFR for looking at SFRs. I got readings: FS - 0x5BE, BP - 0x2DE, SFR - 0x16E. 4 LSBs are fraction part and they are good at all times. With mantissa part it is 0x5B>>1 = 0x2D, 0x2D>>1 = 0x16. So as (half measure) quick fix I just >>2 my mantissa and it works in FS but still does't work in BP and SFR. Maybe this will be some clue. – Dziat Mar 06 '14 at 11:54
  • Can you try to remove the call to USART_ITConfig? You don't need this when you use the USART in polling mode(not with interrupts). – Étienne Mar 06 '14 at 17:54
  • Your variables MSB and LSB should be of types uint8_t, not uint16_t. Otherwise I don't see the problem in your code. I would advise you to program it using USART interrupts instead of polling the flags and see if it makes a difference. – Étienne Mar 06 '14 at 18:04
  • Thanks for reply Etienne. I finished my code with this "quick fix" I wrote about and i also fixed these 2 things you told me to. Program works good in full speed, but with breakpoint and looking at SFRs it still doesn't work. I could write it on interrupts and problem probably wouldn't appear, but i wrote and measured what I wanted and I was wondering what was causing this problem, so I could know how to fix it in the future if it appears. – Dziat Mar 09 '14 at 09:37

2 Answers2

0
Write_1Wire(0xCC);
Write_1Wire(0xBE);
  • send bytes to UART and no read. Receive data in fifo.
Read_1Wire()
  • read old this data in fifo.
uint16_t DS18B20_MeasTemp(void)
{
    uint16_t Data;
    uint16_t LSB;
    uint16_t MSB;
    Reset_1Wire();
    Write_1Wire(0xCC); //SkipRom only 1 device
    Write_1Wire(0x44);
    while(Read_1Wire() == 0x00);
    Reset_1Wire();
    Write_1Wire(0xCC);
    Write_1Wire(0xBE);
   /*--------BRAKEPOINT HERE--------*/
    // !!!!!!! Paste this
    while (USART_GetFlagStatus(UART4, USART_FLAG_RXNE) != RESET)
      USART_ReceiveData(UART4);
    // !!!!!!!
    LSB = Read_1Wire();
    MSB = Read_1Wire();
    Data = MSB << 8 | LSB;
    Reset_1Wire();
    return Data;
}
Unihedron
  • 10,902
  • 13
  • 62
  • 72
0

I've also encountered a similar problem, I was measuring capacitance of a capacitance water level sensor and while running in debugging I got different values than in run mode without the usage of debugger (just plainly connecting it to an external power supply).

I think the issue is with the architecture of the processor, when you are debugging the breakpoint it pauses the cpu but not the peripheral clocks, and GPT aren't getting paused which gives different readings since my measurements are timer dependent.

I'm speaking from my perspective so it might not be happening in your case but it could give you a different view to the problem.

marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
Robert Sabljo
  • 11
  • 1
  • 3