2014-03-05 12 views
1

UART를 사용하는 1-Wire에서 디지털 온도계 DS18B20을 프로그래밍하려고하는데 이상한 문제가 있습니다. 중단 점없이 실행되는이 프로그램을 디버깅 할 때 (또는 디버깅없이 프로그램을 실행하는 경우) 약 100 ° C의 판독 값이 있습니다. 온도 정보를 받기 전에 중단 점을 넣으면 약 50 ° C가됩니다. 세 번째 옵션은 SFR을 볼 수있을 때이 창을 열었을 때 UART4 섹션을 확장하면 약 25 ° C의 정확한 판독 값을 제공합니다. 나는 Saleae logic analyzer를 가지고 있으며이 세 가지 경우 모두 유효한 데이터 (약 25 ° C)를 보낸다. 나는 breakpoint가 (심지어 2s 지연) 어떤 지연을 넣으려고 노력했지만 도움이되지 않는다. 그것은 나에게 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

답장을 보내 주셔서 감사합니다. 처음에는 오픈 드레인을 설정하고 장치의이 레이저 ROM 번호를 읽으려고 할 때 외부 4.7k 저항으로 뽑았습니다. 모든 것이 잘 작동하고 디버거에서 읽은 값은 팔리에 같은 값 이었으므로 궁금합니다. 나는 pushpull을 설정하고 내부적으로 작동 할 것이고 그렇게했을 것이다. 그래서 나는 그것을 거기에 남겼다. :) 오픈 배수구로 다시 변경하고 그것을 외부 끌어 당기는 도움. 나는 같은 문제를 가지고있다. – Dziat

+0

도움이되는 또 다른 것을 발견했습니다. 이 프로그램 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; 
}