当我今晚面临同样的问题时,我想加强一下并说明 Flávio 的答案。
那么我该如何以另一种方式读取签名行?
Flávio 的解决方法做得很好:
#define SIGRD 5
#include <avr/boot.h>
void read_signature_row(uint8_t sr[3])
{
sr[0] = boot_signature_byte_get(0x0000);
sr[1] = boot_signature_byte_get(0x0002);
sr[2] = boot_signature_byte_get(0x0004);
}
void setup()
{
Serial.begin(9600);
delay(100);
uint8_t sr[3] = {0xcc, 0xcc, 0xcc};
read_signature_row(sr);
char buff[100];
snprintf(buff, sizeof buff, "Device signature: %02X %02X %02X", sr[0], sr[1], sr[2]);
Serial.println(buff);
}
void loop()
{}
我没有 ATmega32,尽管此方法为我的 ATmega328P (1E 95 0F) 和 ATmega168PA (1E 94 0B) 检索正确的签名。
这似乎是因为我们只能使用 SPMCR 中具有 SIGRD 位的 AVR 读取签名(我想!)。
是这样吗?
不,它实际上在调用 LPM 之前将 SIGRD 设置为 SPMCR,如 avr/boot.h 所示:
#define __BOOT_SIGROW_READ (_BV(__SPM_ENABLE) | _BV(SIGRD))
#define boot_signature_byte_get(addr) \
(__extension__({ \
uint8_t __result; \
__asm__ __volatile__ \
( \
"sts %1, %2\n\t" \
"lpm %0, Z" "\n\t" \
: "=r" (__result) \
: "i" (_SFR_MEM_ADDR(__SPM_REG)), \
"r" ((uint8_t)(__BOOT_SIGROW_READ)), \
"z" ((uint16_t)(addr)) \
); \
__result; \
}))