15.1程序加密工作原理
STM32通过读取芯片唯一ID号来实现程序的保护,防止被抄袭。96位的产品唯一身份标识所提供的参考号码对任意一个STM32微控制器,在任何情况下都是唯一的。用户在何种情况下,都不能修改这个身份标识。按照用户不同的用法,可以以字节(8位)为单位读取,也可以以半字(16位)或者全字(32位)读取。在这里要提醒读者,要注意大端小端模式。
15.2程序加密具体代码分析
其实读取ID很简单,如果存储ID的变量为8位。则需要读取12次,如下所示。
/**
* @brief The application entry point.
* @retval int
*/
int main(void)
{
/* USER CODE BEGIN 1 */
uint8_t Sys_ID[12],i;
/* USER CODE END 1 */
/* MCU Configuration--------------------------------------------------------*/
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* USER CODE BEGIN Init */
/* USER CODE END Init */
/* Configure the system clock */
SystemClock_Config();
/* USER CODE BEGIN SysInit */
/* USER CODE END SysInit */
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_USART1_UART_Init();
/* USER CODE BEGIN 2 */
HAL_UART_Receive_IT(&huart1, (uint8_t *)&RxBuffer, 1);
for(i=0;i<12;i++)
{
Sys_ID
=*(uint8_t*)(0x1FFFF7E8+i);
printf(" %0.2X",Sys_ID);
}
//ID 39 FF DF 05 4E 42 32 32 10 61 14 51
if(Sys_ID[0]==0x39 && Sys_ID[1]==0xFF && Sys_ID[2]==0xDF &&
Sys_ID[3]==0x05 && Sys_ID[4]==0x4E && Sys_ID[5]==0x42 &&
Sys_ID[6]==0x32 && Sys_ID[7]==0x32 && Sys_ID[8]==0x10 &&
Sys_ID[9]==0x61 && Sys_ID[10]==0x14 && Sys_ID[11]==0x51)
{
printf("\r\n通过\r\n");
}
else
{
printf("\r\n失败\r\n");
}
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
/* USER CODE END WHILE */
//printf("USART1 Test!\n");
HAL_Delay(1000);
/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
}
如果存储ID的变量为32位。则需要读取3次。
uint32_t Sys_ID[3];
Sys_ID[2] = *(__IO uint32_t *)(0X1FFFF7E8); // 低字节
Sys_ID[1] = *(__IO uint32_t *)(0X1FFFF7EC); //
Sys_ID[0] = *(__IO uint32_t *)(0X1FFFF7F0); // 高字节
STM32单片机的存储方式为小端模式。
【注】大小端
地址从小到大,先放低字节,再放高字节:小端模式
地址从小到大,先放高字节,再放低字节:大端模式
15.3实验现象
将程序编译完成后下载到板子中,可以看到打印出来来的唯一ID,该程序是通过现读取ID在通过ID判断,才会打印出ID后面的“通过”字样。

图1 【注】由于ID是唯一的,不折碰有要想在自己的板子上运行成功,要注意更改ID额。
【注】关于STM32 ID 的读取还可以使用STlink读取,请有兴趣的朋友自行查找吧。