在 AVR 微控制器上使用结构
Working with Structs on a AVR microcontroller
我正在尝试将来自 ATMega32 微控制器的 uint8_t 和 uint16_t 成员的结构保存到外部 EEPROM 中。出于这个原因,我写了一个函数来保存这个结构,另一个函数来再次读取它。
在读取函数中,地址作为指针传入。在函数内部,值是通过 RS232 打印的,但我得到了错误的数据和错误的地址(下面的终端输出)。但我没有更改地址(如你所见),我不知道为什么输出为“600”。
保存单个字节的函数工作正常,我已经分别测试了它们。
这是我尝试准备结构、保存它并最终再次读取它的主程序。主程序下
uint16_t testSaveAddr = 20;
uint16_t testLoadAddr = 20;
dataEntry testData;
dataEntry loadData;
testData.airPressure = 1023;
testData.batteryCharge = 140;
testData.dayOfMonth = 20;
testData.hours24 = 11;
testData.humidityInside = 63;
testData.humidityOutside = 80;
testData.lightVal = 123;
testData.minutes = 30;
testData.month = 11;
testData.rain = 0;
testData.temperatureInside = 240;
testData.temperatureOutside = 130;
testData.windDirection = 4;
testData.windVelocity = 300;
testData.yearS70 = 35;
saveDataSet(EEPROM_1_ADDR,testData,&testSaveAddr);
_delay_ms(200);
readDataSet(EEPROM_1_ADDR,&testLoadAddr,&loadData);
_delay_ms(200);
uint8_t saveDataSet (char address_device, dataEntry dS, uint16_t *firstAvailableAddr)
{
uart_puts("*** SAVING NOW ****\n");
//hum -> timeStamp, LOW -> HIGH
uint16_t addr = *firstAvailableAddr;
char text[20];
sprintf(text,"1.| addr: %d\t data: %d\n",addr,dS.humidityOutside);
uart_puts(text);
save_byte_to_eeprom(address_device, addr++, dS.humidityOutside);
sprintf(text,"1.| addr: %d\t data: %d\n",addr,dS.humidityInside);
uart_puts(text);
save_byte_to_eeprom(address_device, addr++, dS.humidityInside);
save_byte_to_eeprom(address_device, addr++, (dS.temperatureOutside)&0xFF);
save_byte_to_eeprom(address_device, addr++, ((dS.temperatureOutside)>>8)&0xFF);
save_byte_to_eeprom(address_device, addr++, (dS.temperatureInside)&0x0FF);
save_byte_to_eeprom(address_device, addr++, ((dS.temperatureInside)>>8)&0xFF);
save_byte_to_eeprom(address_device, addr++, (dS.airPressure)&0xFF);
save_byte_to_eeprom(address_device, addr++, ((dS.airPressure)>>8)&0xFF);
save_byte_to_eeprom(address_device, addr++, (dS.windVelocity)&0xFF);
save_byte_to_eeprom(address_device, addr++, ((dS.windVelocity)>>8)&0xFF);
save_byte_to_eeprom(address_device, addr++, dS.windDirection);
save_byte_to_eeprom(address_device, addr++, dS.lightVal);
save_byte_to_eeprom(address_device, addr++, dS.rain);
save_byte_to_eeprom(address_device, addr++, dS.batteryCharge);
//timeStamp
save_byte_to_eeprom(address_device, addr++, dS.minutes);
save_byte_to_eeprom(address_device, addr++, dS.hours24);
save_byte_to_eeprom(address_device, addr++, dS.dayOfMonth);
save_byte_to_eeprom(address_device, addr++, dS.month);
save_byte_to_eeprom(address_device, addr++, dS.yearS70);
//update, when dataset is fully stored, in case of an error
*firstAvailableAddr = addr;
return 1;
}
uint8_t readDataSet (char address_device, uint16_t *nextDSaddr, dataEntry dS)
{
uint16_t addr = *nextDSaddr;
char text[20];
uart_puts("**** READING NOW ****");
dS->humidityOutside = read_byte_from_eeprom(address_device,addr);
sprintf(text,"1.| addr: %d\t data: %d\n",addr,dS->humidityOutside);
uart_puts(text);
addr++;
dS->humidityInside = read_byte_from_eeprom(address_device,addr++);
uint8_t tempOutLow = read_byte_from_eeprom(address_device,addr++);
uint8_t tempOutHigh = read_byte_from_eeprom(address_device,addr++);
dS->temperatureOutside = (tempOutHigh<<8)+tempOutLow;
uint8_t tempInLow = read_byte_from_eeprom(address_device,addr++);
uint8_t tempInHigh = read_byte_from_eeprom(address_device,addr++);
dS->temperatureInside = (tempInHigh<<8)+tempInLow;
uint8_t airPressLow = read_byte_from_eeprom(address_device,addr++);
uint8_t airPressHigh = read_byte_from_eeprom(address_device,addr++);
dS->airPressure = (airPressHigh<<8)+airPressLow;
uint8_t windVelLow = read_byte_from_eeprom(address_device,addr++);
uint8_t windVelHigh = read_byte_from_eeprom(address_device,addr++);
dS->airPressure = (windVelHigh<<8)+windVelLow;
dS->windDirection = read_byte_from_eeprom(address_device,addr++);
dS->lightVal = read_byte_from_eeprom(address_device,addr++);
dS->rain = read_byte_from_eeprom(address_device,addr++);
dS->batteryCharge = read_byte_from_eeprom(address_device,addr++);
//timestamp
dS->minutes = read_byte_from_eeprom(address_device,addr++);
dS->hours24 = read_byte_from_eeprom(address_device,addr++);
dS->dayOfMonth = read_byte_from_eeprom(address_device,addr++);
dS->month = read_byte_from_eeprom(address_device,addr++);
dS->yearS70 = read_byte_from_eeprom(address_device,addr++);
*nextDSaddr = addr;
return 1;
}
终端输出:
*** SAVING NOW ****
1.| addr: 20 data: 80
1.| addr: 21 data: 63
**** READING NOW ******
1.| addr: 600 data: 255
我认为当您在 saveDataSet
中生成字符串时,您可能会通过溢出 text
缓冲区来覆盖 testLoadAddr
变量的内容。您只允许使用 20 个字符,但您有 2 个数字,所以有一个 24 个字符的字符串,包括终止 NUL。这当然是一个问题,但究竟哪些变量受到影响将取决于编译器创建的堆栈布局。
我正在尝试将来自 ATMega32 微控制器的 uint8_t 和 uint16_t 成员的结构保存到外部 EEPROM 中。出于这个原因,我写了一个函数来保存这个结构,另一个函数来再次读取它。 在读取函数中,地址作为指针传入。在函数内部,值是通过 RS232 打印的,但我得到了错误的数据和错误的地址(下面的终端输出)。但我没有更改地址(如你所见),我不知道为什么输出为“600”。 保存单个字节的函数工作正常,我已经分别测试了它们。
这是我尝试准备结构、保存它并最终再次读取它的主程序。主程序下
uint16_t testSaveAddr = 20;
uint16_t testLoadAddr = 20;
dataEntry testData;
dataEntry loadData;
testData.airPressure = 1023;
testData.batteryCharge = 140;
testData.dayOfMonth = 20;
testData.hours24 = 11;
testData.humidityInside = 63;
testData.humidityOutside = 80;
testData.lightVal = 123;
testData.minutes = 30;
testData.month = 11;
testData.rain = 0;
testData.temperatureInside = 240;
testData.temperatureOutside = 130;
testData.windDirection = 4;
testData.windVelocity = 300;
testData.yearS70 = 35;
saveDataSet(EEPROM_1_ADDR,testData,&testSaveAddr);
_delay_ms(200);
readDataSet(EEPROM_1_ADDR,&testLoadAddr,&loadData);
_delay_ms(200);
uint8_t saveDataSet (char address_device, dataEntry dS, uint16_t *firstAvailableAddr)
{
uart_puts("*** SAVING NOW ****\n");
//hum -> timeStamp, LOW -> HIGH
uint16_t addr = *firstAvailableAddr;
char text[20];
sprintf(text,"1.| addr: %d\t data: %d\n",addr,dS.humidityOutside);
uart_puts(text);
save_byte_to_eeprom(address_device, addr++, dS.humidityOutside);
sprintf(text,"1.| addr: %d\t data: %d\n",addr,dS.humidityInside);
uart_puts(text);
save_byte_to_eeprom(address_device, addr++, dS.humidityInside);
save_byte_to_eeprom(address_device, addr++, (dS.temperatureOutside)&0xFF);
save_byte_to_eeprom(address_device, addr++, ((dS.temperatureOutside)>>8)&0xFF);
save_byte_to_eeprom(address_device, addr++, (dS.temperatureInside)&0x0FF);
save_byte_to_eeprom(address_device, addr++, ((dS.temperatureInside)>>8)&0xFF);
save_byte_to_eeprom(address_device, addr++, (dS.airPressure)&0xFF);
save_byte_to_eeprom(address_device, addr++, ((dS.airPressure)>>8)&0xFF);
save_byte_to_eeprom(address_device, addr++, (dS.windVelocity)&0xFF);
save_byte_to_eeprom(address_device, addr++, ((dS.windVelocity)>>8)&0xFF);
save_byte_to_eeprom(address_device, addr++, dS.windDirection);
save_byte_to_eeprom(address_device, addr++, dS.lightVal);
save_byte_to_eeprom(address_device, addr++, dS.rain);
save_byte_to_eeprom(address_device, addr++, dS.batteryCharge);
//timeStamp
save_byte_to_eeprom(address_device, addr++, dS.minutes);
save_byte_to_eeprom(address_device, addr++, dS.hours24);
save_byte_to_eeprom(address_device, addr++, dS.dayOfMonth);
save_byte_to_eeprom(address_device, addr++, dS.month);
save_byte_to_eeprom(address_device, addr++, dS.yearS70);
//update, when dataset is fully stored, in case of an error
*firstAvailableAddr = addr;
return 1;
}
uint8_t readDataSet (char address_device, uint16_t *nextDSaddr, dataEntry dS)
{
uint16_t addr = *nextDSaddr;
char text[20];
uart_puts("**** READING NOW ****");
dS->humidityOutside = read_byte_from_eeprom(address_device,addr);
sprintf(text,"1.| addr: %d\t data: %d\n",addr,dS->humidityOutside);
uart_puts(text);
addr++;
dS->humidityInside = read_byte_from_eeprom(address_device,addr++);
uint8_t tempOutLow = read_byte_from_eeprom(address_device,addr++);
uint8_t tempOutHigh = read_byte_from_eeprom(address_device,addr++);
dS->temperatureOutside = (tempOutHigh<<8)+tempOutLow;
uint8_t tempInLow = read_byte_from_eeprom(address_device,addr++);
uint8_t tempInHigh = read_byte_from_eeprom(address_device,addr++);
dS->temperatureInside = (tempInHigh<<8)+tempInLow;
uint8_t airPressLow = read_byte_from_eeprom(address_device,addr++);
uint8_t airPressHigh = read_byte_from_eeprom(address_device,addr++);
dS->airPressure = (airPressHigh<<8)+airPressLow;
uint8_t windVelLow = read_byte_from_eeprom(address_device,addr++);
uint8_t windVelHigh = read_byte_from_eeprom(address_device,addr++);
dS->airPressure = (windVelHigh<<8)+windVelLow;
dS->windDirection = read_byte_from_eeprom(address_device,addr++);
dS->lightVal = read_byte_from_eeprom(address_device,addr++);
dS->rain = read_byte_from_eeprom(address_device,addr++);
dS->batteryCharge = read_byte_from_eeprom(address_device,addr++);
//timestamp
dS->minutes = read_byte_from_eeprom(address_device,addr++);
dS->hours24 = read_byte_from_eeprom(address_device,addr++);
dS->dayOfMonth = read_byte_from_eeprom(address_device,addr++);
dS->month = read_byte_from_eeprom(address_device,addr++);
dS->yearS70 = read_byte_from_eeprom(address_device,addr++);
*nextDSaddr = addr;
return 1;
}
终端输出:
*** SAVING NOW ****
1.| addr: 20 data: 80
1.| addr: 21 data: 63
**** READING NOW ******
1.| addr: 600 data: 255
我认为当您在 saveDataSet
中生成字符串时,您可能会通过溢出 text
缓冲区来覆盖 testLoadAddr
变量的内容。您只允许使用 20 个字符,但您有 2 个数字,所以有一个 24 个字符的字符串,包括终止 NUL。这当然是一个问题,但究竟哪些变量受到影响将取决于编译器创建的堆栈布局。