实现从 DS18B20 读取温度并显示在 LCD 上的功能
Make function to read Temperature from DS18B20 and show on LCD
我想创建一个新函数,它将 return DS18B20 的实际温度作为浮点变量。我需要那种变量来在 LCD 上放置一个字符串。
我已经在使用这样的函数来读取温度了:
int8_t readTemp(struct ds18b20 *d) {
struct ds18b20 *newTemp;
char tempAct[5];
while (d->next != NULL)
{
d = d->next;
int fd = open(d->devPath, O_RDONLY);
if (fd == -1)
{
perror("Couldn't open the w1 device.");
return 1;
}
char buf[256];
ssize_t numRead;
while ((numRead = read(fd, buf, 256)) > 0)
{
newTemp = malloc(sizeof(struct ds18b20));
strncpy(newTemp->tempData, strstr(buf, "t=") + 2, 5);
//float tempC = strtof(d->tempData, NULL);
sprintf(tempAct, "%s C", newTemp->tempData);
//printf("Device: %s - ", d->devID);
//printf("Temp: %.3f C ", tempC / 1000);
//printf("%.3f F\n\n", (tempC / 1000) * 9 / 5 + 32);
}
close(fd);
}
return 1;}
这一行的 sprintf 有问题:
sprintf(tempAct, "%s C", newTemp->tempData);
在主要代码中:
int main(void) {
struct ds18b20 *rootNode;
struct ds18b20 *devNode;
struct ds18b20 *getTemp;
// Load pin configuration. Ignore error if already loaded
system("echo w1 > /sys/devices/bone_capemgr.9/slots>/dev/null");
while (1) {
rootNode = malloc(sizeof(struct ds18b20));
devNode = rootNode;
getTemp = rootNode;
int8_t devCnt = findDevices(devNode);
printf("\n Found %d devices\n\n", devCnt);
int8_t tempAct = readTemp(getTemp);
printf("\n Temp Act: %d \n\n", tempAct);
//readTemp(rootNode);
// Free linked list memory
while (rootNode) {
// Start with current value of root node
devNode = rootNode;
// Save address of next devNode to rootNode before deleting current devNode
rootNode = devNode->next;
// Free current devNode.
free(devNode);
}
free(rootNode);
}
return 0;}
我正在尝试从 finddevices 重新创建函数:
int8_t devCnt = findDevices(devNode);
printf("\n Found %d devices\n\n", devCnt);
int8_t tempAct = readTemp(getTemp);
printf("\n Temp Act: %d \n\n", tempAct);
但是 tempData* 没有从 readTemp 函数导入到主代码。
代码中充斥着一些问题,这些问题并不明确属于您的问题。只是一些:
readTemp()
不return温度。事实上它 returns 如果失败则为 1,如果成功则为 1。这可能是一个错误。
readTemp()
似乎读取 所有 可用的温度传感器,作为 struct ds18b20
的链表传递给它,而不仅仅是一个。但实际上跳过根节点并访问第二个和后续节点而不检查它是否有效。如果根节点不包含任何设备(只是指向第一个设备的指针),那么您只需将其传递给 rootNode->next
即可。
不清楚为什么它会动态分配一个新的 struct ds18b20
或为什么它稍后会失败 de-allocate。那是严重的内存泄漏。
猜测以下内容更可能接近您的需要(不知道 struct ds18b20
或传感器的预期输出是什么 - 只是根据代码中的证据(和注释掉您发布的代码)- 因此做出了一些大胆的假设。
int readTemp( struct ds18b20 *d, // List of sensors
float* temperatures, // Pointer to array to receive temperatures
int8_t max_temperatures ) // Max number of temperatures to receive
{
struct ds18b20* sensor = d ;
int count = 0 ;
while( sensor != NULL && count < max_temperatures )
{
int fd = open( sensor->devPath, O_RDONLY ) ;
if( fd >= 0 )
{
if( read( fd, buf, sizeof(buf) ) > 0 )
{
char buf[256];
char* temp_str = strstr(buf, "t=") + 2 ;
sscanf( temp_str, "%f", &temperatures[count] ) ;
temperatures[count] /= 1000 ;
count++ ;
}
close( fd ) ;
sensor = sensor->next ;
}
else
{
perror("Couldn't open the w1 device.");
}
}
return count ;
}
然后你可以这样称呼它:
int8_t devCount = findDevices( rootNode ) ;
float* temperatures = malloc( devCnt * sizeof(float) ) ;
int8_t tempCount = readTemp( rootNode->next, temperatures, devCount ) ;
for( int i = 0; i < tempCount; i++ )
{
printf( "Temp Act: %f\n", temperatures[i] ) ;
}
free( temperatures ) ;
如果你知道只有一个设备或者你只需要打印第一个,那么这可以简化:
int8_t devCount = findDevices( rootNode ) ;
if( devCount > 0 )
{
float temperature = 0f ;
int8_t tempCount = readTemp( rootNode->next, temperature, 1 ) ;
if( tempCount > 0 )
{
printf( "Temp Act: %f\n", temperature ) ;
}
}
您 main()
中的问题也多种多样,包括:
- 根节点是不必要的动态分配
- 不必要地为根节点创建了几个别名
- 设备列表重复re-enumerated,并且在non-terminating循环的每次迭代中分配和释放设备列表。假设代码为 运行 时传感器数量不变,这是不必要的。
- 循环永远不会结束 - 即使出现错误。
更好的实现可能类似于:
int main(void)
{
// Load pin configuration. Ignore error if already loaded
system("echo w1 > /sys/devices/bone_capemgr.9/slots>/dev/null");
struct ds18b20 rootNode = { 0 } ;
int8_t devCount = findDevices( rootNode ) ;
if( devCount > 0)
{
struct ds18b20* devlist = rootNode->next ;
float* temperatures = malloc( devCount * sizeof(float) ) ;
int8_t tempCount = 0 ;
do
{
tempCount = readTemp( devList, temperatures, devCount ) ;
for( int i = 0; i < tempCount; i++ )
{
printf( "Temp Act: %f\n", temperatures[i] ) ;
}
} while (tempCount > 0 ) ;
// Free resources after a temperature read fails
free( temperatures ) ;
// Free linked list memory
while( devlist != NULL )
{
// Save address of next before deleting current
struct ds18b20* next = devlist->next ;
// Free current devNode.
free( devlist ) ;
// get next
devlist = next ;
}
}
return 0 ;
}
我想创建一个新函数,它将 return DS18B20 的实际温度作为浮点变量。我需要那种变量来在 LCD 上放置一个字符串。
我已经在使用这样的函数来读取温度了:
int8_t readTemp(struct ds18b20 *d) {
struct ds18b20 *newTemp;
char tempAct[5];
while (d->next != NULL)
{
d = d->next;
int fd = open(d->devPath, O_RDONLY);
if (fd == -1)
{
perror("Couldn't open the w1 device.");
return 1;
}
char buf[256];
ssize_t numRead;
while ((numRead = read(fd, buf, 256)) > 0)
{
newTemp = malloc(sizeof(struct ds18b20));
strncpy(newTemp->tempData, strstr(buf, "t=") + 2, 5);
//float tempC = strtof(d->tempData, NULL);
sprintf(tempAct, "%s C", newTemp->tempData);
//printf("Device: %s - ", d->devID);
//printf("Temp: %.3f C ", tempC / 1000);
//printf("%.3f F\n\n", (tempC / 1000) * 9 / 5 + 32);
}
close(fd);
}
return 1;}
这一行的 sprintf 有问题:
sprintf(tempAct, "%s C", newTemp->tempData);
在主要代码中:
int main(void) {
struct ds18b20 *rootNode;
struct ds18b20 *devNode;
struct ds18b20 *getTemp;
// Load pin configuration. Ignore error if already loaded
system("echo w1 > /sys/devices/bone_capemgr.9/slots>/dev/null");
while (1) {
rootNode = malloc(sizeof(struct ds18b20));
devNode = rootNode;
getTemp = rootNode;
int8_t devCnt = findDevices(devNode);
printf("\n Found %d devices\n\n", devCnt);
int8_t tempAct = readTemp(getTemp);
printf("\n Temp Act: %d \n\n", tempAct);
//readTemp(rootNode);
// Free linked list memory
while (rootNode) {
// Start with current value of root node
devNode = rootNode;
// Save address of next devNode to rootNode before deleting current devNode
rootNode = devNode->next;
// Free current devNode.
free(devNode);
}
free(rootNode);
}
return 0;}
我正在尝试从 finddevices 重新创建函数:
int8_t devCnt = findDevices(devNode);
printf("\n Found %d devices\n\n", devCnt);
int8_t tempAct = readTemp(getTemp);
printf("\n Temp Act: %d \n\n", tempAct);
但是 tempData* 没有从 readTemp 函数导入到主代码。
代码中充斥着一些问题,这些问题并不明确属于您的问题。只是一些:
readTemp()
不return温度。事实上它 returns 如果失败则为 1,如果成功则为 1。这可能是一个错误。readTemp()
似乎读取 所有 可用的温度传感器,作为struct ds18b20
的链表传递给它,而不仅仅是一个。但实际上跳过根节点并访问第二个和后续节点而不检查它是否有效。如果根节点不包含任何设备(只是指向第一个设备的指针),那么您只需将其传递给rootNode->next
即可。不清楚为什么它会动态分配一个新的
struct ds18b20
或为什么它稍后会失败 de-allocate。那是严重的内存泄漏。
猜测以下内容更可能接近您的需要(不知道 struct ds18b20
或传感器的预期输出是什么 - 只是根据代码中的证据(和注释掉您发布的代码)- 因此做出了一些大胆的假设。
int readTemp( struct ds18b20 *d, // List of sensors
float* temperatures, // Pointer to array to receive temperatures
int8_t max_temperatures ) // Max number of temperatures to receive
{
struct ds18b20* sensor = d ;
int count = 0 ;
while( sensor != NULL && count < max_temperatures )
{
int fd = open( sensor->devPath, O_RDONLY ) ;
if( fd >= 0 )
{
if( read( fd, buf, sizeof(buf) ) > 0 )
{
char buf[256];
char* temp_str = strstr(buf, "t=") + 2 ;
sscanf( temp_str, "%f", &temperatures[count] ) ;
temperatures[count] /= 1000 ;
count++ ;
}
close( fd ) ;
sensor = sensor->next ;
}
else
{
perror("Couldn't open the w1 device.");
}
}
return count ;
}
然后你可以这样称呼它:
int8_t devCount = findDevices( rootNode ) ;
float* temperatures = malloc( devCnt * sizeof(float) ) ;
int8_t tempCount = readTemp( rootNode->next, temperatures, devCount ) ;
for( int i = 0; i < tempCount; i++ )
{
printf( "Temp Act: %f\n", temperatures[i] ) ;
}
free( temperatures ) ;
如果你知道只有一个设备或者你只需要打印第一个,那么这可以简化:
int8_t devCount = findDevices( rootNode ) ;
if( devCount > 0 )
{
float temperature = 0f ;
int8_t tempCount = readTemp( rootNode->next, temperature, 1 ) ;
if( tempCount > 0 )
{
printf( "Temp Act: %f\n", temperature ) ;
}
}
您 main()
中的问题也多种多样,包括:
- 根节点是不必要的动态分配
- 不必要地为根节点创建了几个别名
- 设备列表重复re-enumerated,并且在non-terminating循环的每次迭代中分配和释放设备列表。假设代码为 运行 时传感器数量不变,这是不必要的。
- 循环永远不会结束 - 即使出现错误。
更好的实现可能类似于:
int main(void)
{
// Load pin configuration. Ignore error if already loaded
system("echo w1 > /sys/devices/bone_capemgr.9/slots>/dev/null");
struct ds18b20 rootNode = { 0 } ;
int8_t devCount = findDevices( rootNode ) ;
if( devCount > 0)
{
struct ds18b20* devlist = rootNode->next ;
float* temperatures = malloc( devCount * sizeof(float) ) ;
int8_t tempCount = 0 ;
do
{
tempCount = readTemp( devList, temperatures, devCount ) ;
for( int i = 0; i < tempCount; i++ )
{
printf( "Temp Act: %f\n", temperatures[i] ) ;
}
} while (tempCount > 0 ) ;
// Free resources after a temperature read fails
free( temperatures ) ;
// Free linked list memory
while( devlist != NULL )
{
// Save address of next before deleting current
struct ds18b20* next = devlist->next ;
// Free current devNode.
free( devlist ) ;
// get next
devlist = next ;
}
}
return 0 ;
}