【问题标题】:STM32 Different results while debuggingSTM32调试时结果不同
【发布时间】:2014-03-05 23:45:33
【问题描述】:

我正在尝试使用 UART 在 1-Wire 上对数字温度计 DS18B20 进行编程,但遇到了奇怪的问题。当我调试这个没有断点运行的程序(或者只是运行没有调试的程序)时,我的读数约为 100°C。当我在接收温度信息之前设置断点时,它给了我大约 50°c。第三个选项当我打开这个窗口时,我可以看到 SFR 并展开 UART4 部分,它给了我大约 25°C 的正确读数。我有 Saleae 逻辑分析仪,在所有这 3 种情况下,它都会向我发送有效数据(约 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);
  }

}

【问题讨论】:

  • 以前没用过STM,但是看他们的reference manual 好像GPIO需要开漏+上拉;您的代码暗示它被设置为推拉。我认为您需要GPIO_OType_OD,但我找不到合适的头文件来确定。也许在 1-wire 将您的 USART 输出与地短路时运行调试器的额外功耗会导致您看到的问题?
  • 感谢您的回复。起初,我将它设置为开漏并通过外部 4.7k 电阻将其拉起,当我试图读取这个设备的激光 ROM 编号并且一切正常时,我在调试器中的读数与在 saleae 中的读数相同,所以我想知道是否我将它设置为 pushpull 并在内部拉起它会起作用并且确实如此,所以我把它留在那里:)。将其改回开放式排水管并将其从外部拉起并没有帮助。我也有同样的问题。
  • 我发现了另一件事可以提供帮助。让我们调用这 3 个可能的选项来运行这个程序 FS 以全速运行,BP 为断点选项,SFR 用于查看 SFR。我得到读数:FS - 0x5BE,BP - 0x2DE,SFR - 0x16E。 4 LSB 是小数部分,它们在任何时候都很好。尾数部分为 0x5B>>1 = 0x2D,0x2D>>1 = 0x16。因此,作为(一半测量)快速修复,我只是 >>2 我的尾数,它在 FS 中有效,但在 BP 和 SFR 中仍然无效。也许这会是一些线索。
  • 您可以尝试删除对 USART_ITConfig 的调用吗?在轮询模式下使用 USART 时不需要这个(不带中断)。
  • 您的变量 MSB 和 LSB 应该是 uint8_t 类型,而不是 uint16_t。否则我在您的代码中看不到问题。我建议您使用 USART 中断对其进行编程,而不是轮询标志,看看它是否有所作为。

标签: c debugging uart stm32 1wire


【解决方案1】:
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;
}

【讨论】:

    【解决方案2】:

    我也遇到过类似的问题,我正在测量电容式水位传感器的电容,在调试中运行时,我得到的值与在不使用调试器的运行模式下不同(只是简单地将其连接到外部电源)。

    我认为问题出在处理器的体系结构上,当您调试断点时,它会暂停 cpu 而不是外围时钟,并且 GPT 不会暂停,这会给出不同的读数,因为我的测量值取决于计时器。

    我是从我的角度说的,所以它可能不会发生在你的情况下,但它可以让你对这个问题有不同的看法。

    【讨论】:

      猜你喜欢
      • 2020-12-11
      • 2015-01-24
      • 2020-01-15
      • 1970-01-01
      • 2013-09-08
      • 2020-11-08
      • 2017-06-28
      • 2017-04-20
      • 2011-09-19
      相关资源
      最近更新 更多