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);
}
}
之前从未使用STM,但是在它们的[参考手册]寻找(http://www.st.com/web/en/resource/technical/document/reference_manual/DM00031020.pdf )它看起来像GPIO需要开漏+拉起;你的代码意味着它被设置为推挽。我认为你需要'GPIO_OType_OD',但是我找不到合适的头文件。当1-wire将您的USART输出短接到地时,运行调试器的额外功耗可能会导致您遇到的问题? –
感谢您的回复。起初,我设置漏极开路,并通过外部4.7k电阻将其拉高,当我试图读取设备的激光ROM编号并且一切正常时,调试器中的读数与saleae中的读数相同,所以我想知道是否我把它设置为pushpull,并在内部拉起来,它会工作,它确实,所以我只是把它留在那里:)。将其改回漏管并将其从外部拉起来并不能提供帮助。我也有同样的问题。 – Dziat
我发现了另一件可以提供帮助的东西。让我们调用这3个可能的选项来运行该程序FS全速,断点选项BP和SFR查看SFR。我读到:FS - 0x5BE,BP - 0x2DE,SFR - 0x16E。 4个LSB是小数部分,它们总是很好。尾数部分是0x5B >> 1 = 0x2D,0x2D >> 1 = 0x16。所以(一半的措施)快速解决我只是>> 2我的尾数,它在FS工作,但仍然没有工作在BP和SFR。也许这将是一些线索。 – Dziat