2014-03-05 54 views
1

我試圖在1-Wire上使用UART編程數字溫度計DS18B20,並且出現了奇怪的問題。當我調試沒有斷點運行的程序時(或者只是在沒有調試的情況下運行程序),我讀取的溫度約爲100°C。當我在接收溫度信息之前放置斷點時,它會給我大約50°c。第三種選擇是,當我看到SFR並擴展UART4部分時,只需打開此窗口,就可以獲得25°C左右的正確讀數。我有Saleae邏輯分析儀,在所有這3種情況下,它向我發送有效數據(約25°C)。我試圖把一些延遲放在斷點(甚至延遲2秒)的地方,但它並沒有幫助。它給我的讀數大約爲50°C(就像斷點和不擴展的SFR窗口一樣)。這可能是編程錯誤(我開始),但是這種擴展了SFR窗口的操作超出了我的推理。 我真的不知道發生了什麼事。我希望你能爲我闡明這種情況。STM32在調試時出現了不同的結果

我正在使用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); 
    } 

} 
+0

之前從未使用STM,但是在它們的[參考手冊]尋找(http://www.st.com/web/en/resource/technical/document/reference_manual/DM00031020.pdf )它看起來像GPIO需要開漏+拉起;你的代碼意味着它被設置爲推輓。我認爲你需要'GPIO_OType_OD',但是我找不到合適的頭文件。當1-wire將您的USART輸出短接到地時,運行調試器的額外功耗可能會導致您遇到的問題? –

+0

感謝您的回覆。起初,我設置漏極開路,並通過外部4.7k電阻將其拉高,當我試圖讀取設備的激光ROM編號並且一切正常時,調試器中的讀數與saleae中的讀數相同,所以我想知道是否我把它設置爲pushpull,並在內部拉起來,它會工作,它確實,所以我只是把它留在那裏:)。將其改回漏管並將其從外部拉起來並不能提供幫助。我也有同樣的問題。 – Dziat

+0

我發現了另一件可以提供幫助的東西。讓我們調用這3個可能的選項來運行該程序FS全速,斷點選項BP和SFR查看SFR。我讀到:FS - 0x5BE,BP - 0x2DE,SFR - 0x16E。 4個LSB是小數部分,它們總是很好。尾數部分是0x5B >> 1 = 0x2D,0x2D >> 1 = 0x16。所以(一半的措施)快速解決我只是>> 2我的尾數,它在FS工作,但仍然沒有工作在BP和SFR。也許這將是一些線索。 – Dziat

回答

0
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; 
} 
相關問題