STM32 Различные результаты при отладке

Я пытаюсь запрограммировать цифровой термометр DS18B20 на 1-Wire, используя UART, и у меня странные проблемы. Когда я отлаживаю эту программу, которая работает без точек останова (или просто запускаю программу без отладки), у меня показания около 100°C. Когда я ставлю точку останова до получения информации о температуре, она дает мне около 50° C. И третий вариант, когда я просто открываю это окно, когда я вижу SFR и расширяю раздел UART4, это дает мне правильные показания около 25°C. У меня есть логический анализатор Saleae, и во всех этих трех случаях он посылает мне достоверные данные (около 25°C). Я попытался поместить некоторую задержку в точку останова (даже задержка в 2 с), и это не помогло. Это дает мне показания около 50°C (как с точками останова и без расширенного окна SFR). Вероятно, это ошибка программирования (я начинаю), но это действие с расширенным окном SFR выходит за рамки моих рассуждений. Я действительно не знаю, что происходит. Я надеюсь, что вы можете пролить свет на эту ситуацию для меня.

Я использую оценочную плату STM32F4-Discovery и программирую ее на Atollic 4.1.0.

Мой файл "Библиотека":

#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;
}

И моя основная функция:

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);
  }

}

1 ответ

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.

Write_1Wire(0xCC);
Write_1Wire(0xBE);
  • отправьте байты в UART и не читайте. Получите данные в fifo.
Read_1Wire()
  • прочитайте старые эти данные в 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;
}
Другие вопросы по тегам