【发布时间】:2011-10-15 00:47:34
【问题描述】:
我正在为嵌入式系统类编写一个极其简单的内核。该板是 TI Stellaris EKI-LM3S8962。它运行 C 并具有 OLED 显示屏。我遇到了 void 指针和取消引用它们的问题。非常感谢任何帮助。
我最初的小目标是证明传递函数指针和结构指针的概念。这是我访问指针 batteryStatePtr 指向的 var batteryState 的方式,它是传入的数据结构的一部分?
void status (void* taskDataPtr) {
// make a temporary pointer to a Status Data Struct type
SDS* data;
// set data equal to the void* taskDataPtr now cast as a SDS pointer
data = (SDS*)(taskDataPtr);
(*data->batteryStatePtr)--;
...
这是我的代码的一个非常精简的版本,重要区域可以通过 ctrl-f "HERE IS" 定位
struct MyStruct {
void (*taskPtr)(void*);
void* taskDataPtr;
};
typedef struct MyStruct TCB;
taskPtr 指向一个函数,该函数接受一个 void* 作为 arg,并且有一个 void* 指向一个数据结构。作为概念证明,我从尽可能小的开始。有两个功能,状态和显示。
typedef struct DisplayDataStruct {
uint* batteryStatePtr;
} DDS;
DDS DisplayData;
typedef struct StatusDataStruct {
uint* batteryStatePtr;
} SDS;
SDS StatusData;
Status 通过给定的 taskDataPtr 递减全局变量 batteryState。 Display 将它连接到一个字符串上并在 OLED 上显示。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef unsigned int uint;
typedef unsigned char uchar;
typedef unsigned short ushort;
void status (void* taskDataPtr);
void display (void* taskDataPtr);
void delay(uint msDelay);
// Declare a TCB structure
struct MyStruct {
void (*taskPtr)(void*);
void* taskDataPtr;
};
typedef struct MyStruct TCB;
// status var
uint batteryState = 200;
typedef struct DisplayDataStruct {
uint* batteryStatePtr;
} DDS;
DDS DisplayData;
typedef struct StatusDataStruct {
uint* batteryStatePtr;
} SDS;
SDS StatusData;
void main(void)
{
DisplayData.batteryStatePtr = &batteryState;
StatusData.batteryStatePtr = &batteryState;
int i = 0; // queue index
TCB* aTCBPtr;
TCB* queue[2];
TCB StatusTCB;
TCB DisplayTCB;
StatusTCB.taskPtr = status;
StatusTCB.taskDataPtr = (void*)&StatusData;
DisplayTCB.taskPtr = display;
DisplayTCB.taskDataPtr = (void*)&DisplayData;
// Initialize the task queue
queue[0] = &StatusTCB;
queue[1] = &DisplayTCB;
// schedule and dispatch the tasks
while(1)
{
for (i = 0; i < 2; i++) {
aTCBPtr = queue[i];
aTCBPtr->taskPtr( (void*)(aTCBPtr->taskDataPtr) );
}
systemState = (systemState + 1) % 100;
delay(50);
}
}
void status (void* taskDataPtr) {
// return if systemState != 0 aka run once every 5 sec
if (systemState) {
return;
}
// make a temporary pointer to a Status Data Struct type
SDS* data;
// set data equal to the void* taskDataPtr now cast as a SDS pointer
data = (SDS*)(taskDataPtr);
// HERE IS where I am stumped. Is (*data->batteryStatePtr)-- the way you do this????
// access the batteryStatePtr through the struct data
// then dereference the whole thing to get at batteryState
if ((*(data->batteryStatePtr)) > 0) {
// decrement batteryState
(*(data->batteryStatePtr))--;
}
return;
}
void display (void* taskDataPtr) {
// run once every 5 sec
if (systemState) {
return;
}
DDS* data;
data = (DDS*) taskDataPtr;
char hold[12] = "Batt: ";
char numHold[4];
sprintf(numHold, "%u", (*(data->batteryStatePtr)));
strcat(hold, numHold);
// display the string hold
RIT128x96x4StringDraw(hold, 15, 44, 15);
return;
}
// use for loops to waste cycles, delay taken in ms
void delay(uint msDelay)
{
// when i == 60000 and j == 100 function delays for ~ 7.6 sec
msDelay = msDelay * 150 / 19;
volatile unsigned long i = 0;
volatile unsigned int j = 0;
for (i = msDelay; i > 0; i--) {
for (j = 0; j < 100; j++);
}
return;
}
【问题讨论】:
-
(*(data->batteryStatePtr))--应该没问题...您认为有什么特别的原因吗? -
感谢您的回复。我认为这是一个问题,因为它不起作用而且我的指针专业知识很少。我只是想把那个语法添加到一堆我知道的东西中,这不是完全错误的。
-
编译器是否给出警告?
systemState声明在哪里? -
“它不起作用”是什么意思 - 您希望看到什么以及您实际看到了什么?是不是显示中的值没有减少?您是否已验证它在状态任务中递减?您可能必须使 batteryStatePtr 指针易失,以便编译器始终生成从内存读取的代码,而不是缓存值。
-
确保您没有丢失任何头文件或源文件...我在任何地方都没有看到
RIT128x96x4StringDraw()或systemState的声明,也没有看到任何#include的声明t 标准 C RTL 头文件
标签: c void-pointers embedded