STM32基础入门学习笔记:内部高级功能应用

文章目录:

一:低功耗模式

1.睡眠模式测试程序

NVIC.h

NVIC.c

key.h

key.c

main.c

2.停机模式测试程序

main.c

3.待机模式测试程序

main.c

二:看门狗

1.独立看门狗测试程序

iwdg.h

iwdg.c

main.c

2.窗口看门狗测试程序

wwdg.h

wwdg.c

main.c

三:TIM定时器

tim.h

tim.c

main.c

四:CRC循环冗余校验计算单元与芯片ID

1.CRC功能测试程序

main.c

2.芯片ID读取程序

main.c

五:还需要补充的知识


这些是单片机的辅助功能

一:低功耗模式

单片机内部功率是各功能部分功率的总和低功耗模式是通过关掉部分内部功能达到省电STM32F103单片机共有3种低功耗模式不同模式会对系统正常工作有一定影响,需要按实际情况选择低功耗模式只针对单片机内部功能,外接电路产生的功耗不在其内单片机最小系统电路功耗,不精确测量值√正常模式:10mA√睡眠模式:2mA√停机模式:20uA√待机模式:2uA睡眠模式在ARM内核无事可做的时候,可以进入睡眠模式例如:电脑的CPU空闲状态就是单片机睡眠模式睡眠模式的应用不多,因只关闭ARM内核,节能有限,很少在非操作系统程序(裸机)中使用在嵌入式操作系统中,会采用睡眠模式优点:对系统影响最小缺点:节能效果最差停机模式因SRAM内容不消失,程序不复位,可在唤醒后继续运行节能效果与待机模式近似,却有着更多优势主要用于电池供电的设备上,提高电池寿命在电池供电的产品中必须使用,在外部供电的产品中没必要使用优点:节能效果好,程序不会复位缺点:恢复时间较长待机模式由于SRAM内容消失,唤醒后程序必须复位,从头开始运行因为待机和停机之间的功耗差别是uA级的,几乎没有差别,所以开发者大多使用停机模式,待机模式极少使用在一些偶尔需要工作的场合,且工作量不大、不复杂的情况下,待机模式可以保证最低的功耗比如应用在室外温度测量产品上,每1小时测量一次。可用RTC闹钟唤醒,测量完再待机。、优点:最节能缺点:程序会复位,只有少数条件可唤醒

 

1.睡眠模式测试程序

NVIC.h

#ifndef __NVIC_H
#define __NVIC_H	 
#include "sys.h"extern u8 INT_MARK;//中断标志位void KEY_INT_INIT (void);#endif

NVIC.c

#include "NVIC.h"u8 INT_MARK;//中断标志位void KEY_INT_INIT (void){	 //按键中断初始化NVIC_InitTypeDef  NVIC_InitStruct;	//定义结构体变量EXTI_InitTypeDef  EXTI_InitStruct;RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE); //启动GPIO时钟 (需要与复用时钟一同启动)     RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO , ENABLE);//配置端口中断需要启用复用时钟GPIO_EXTILineConfig(GPIO_PortSourceGPIOA, GPIO_PinSource0);  //定义 GPIO  中断EXTI_InitStruct.EXTI_Line=EXTI_Line0;  //定义中断线EXTI_InitStruct.EXTI_LineCmd=ENABLE;              //中断使能EXTI_InitStruct.EXTI_Mode=EXTI_Mode_Interrupt;     //中断模式为 中断EXTI_InitStruct.EXTI_Trigger=EXTI_Trigger_Falling;   //下降沿触发EXTI_Init(& EXTI_InitStruct);NVIC_InitStruct.NVIC_IRQChannel=EXTI0_IRQn;   //中断线     NVIC_InitStruct.NVIC_IRQChannelCmd=ENABLE;  //使能中断NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority=2;  //抢占优先级 2NVIC_InitStruct.NVIC_IRQChannelSubPriority=2;     //子优先级  2NVIC_Init(& NVIC_InitStruct);}void  EXTI0_IRQHandler(void){if(EXTI_GetITStatus(EXTI_Line0)!=RESET){//判断某个线上的中断是否发生 INT_MARK=1;//标志位置1,表示有按键中断EXTI_ClearITPendingBit(EXTI_Line0);   //清除 LINE 上的中断标志位}     
}

key.h

#ifndef __KEY_H
#define __KEY_H	 
#include "sys.h"//#define KEY1 PAin(0)// PA0
//#define KEY2 PAin(1)// PA1#define KEYPORT	GPIOA	//定义IO接口组
#define KEY1	GPIO_Pin_0	//定义IO接口
#define KEY2	GPIO_Pin_1	//定义IO接口void KEY_Init(void);//初始化#endif

key.c

#include "key.h"void KEY_Init(void){ //微动开关的接口初始化GPIO_InitTypeDef  GPIO_InitStructure; //定义GPIO的初始化枚举结构	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);       GPIO_InitStructure.GPIO_Pin = KEY1 | KEY2; //选择端口号(0~15或all)                        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; //选择IO接口工作方式 //上拉电阻       
//    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //设置IO接口速度(2/10/50MHz)    GPIO_Init(KEYPORT,&GPIO_InitStructure);			
}

main.c

#include "stm32f10x.h" //STM32头文件
#include "sys.h"
#include "delay.h"
#include "relay.h"
#include "oled0561.h"
#include "led.h"
#include "key.h"#include "NVIC.h"    //中断向量控制器int main (void){//主程序delay_ms(500); //上电时等待其他器件就绪RCC_Configuration(); //系统时钟初始化 RELAY_Init();//继电器初始化LED_Init();//LED KEY_Init();//KEYI2C_Configuration();//I2C初始化OLED0561_Init(); //OLED初始化OLED_DISPLAY_8x16_BUFFER(0,"   SLEEP TEST   "); //显示字符串INT_MARK=0;//标志位清0NVIC_Configuration();//设置中断优先级KEY_INT_INIT();//按键中断初始化(PA0是按键中断输入)NVIC_SystemLPConfig(NVIC_LP_SEVONPEND,DISABLE);	//SEVONPEND: 0:只有使能的中断或事件才能唤醒内核。1:任何中断和事件都可以唤醒内核。(0=DISABLE,1=ENABLE) NVIC_SystemLPConfig(NVIC_LP_SLEEPDEEP,DISABLE);	//SLEEPDEEP: 0:低功耗模式为睡眠模式。1:进入低功耗时为深度睡眠模式。NVIC_SystemLPConfig(NVIC_LP_SLEEPONEXIT,DISABLE); //SLEEPONEXIT: 0: 被唤醒进入线程模式后不再进入睡眠模式。1:被唤醒后执行完相应的中断处理函数后进入睡眠模式。while(1){GPIO_WriteBit(LEDPORT,LED1,(BitAction)(1)); //LED控制OLED_DISPLAY_8x16_BUFFER(4,"  CPU SLEEP!    "); //显示字符串delay_ms(500); //__WFI(); //进入睡眠模式,等待中断唤醒
//		__WFE(); //进入睡眠模式,等待事件唤醒GPIO_WriteBit(LEDPORT,LED1,(BitAction)(0)); //LED控制OLED_DISPLAY_8x16_BUFFER(4,"  CPU WAKE UP!  "); //显示字符串delay_ms(500); //}}

2.停机模式测试程序

main.c

#include "stm32f10x.h" //STM32头文件
#include "sys.h"
#include "delay.h"
#include "relay.h"
#include "oled0561.h"
#include "led.h"
#include "key.h"#include "NVIC.h"int main (void){//主程序delay_ms(500); //上电时等待其他器件就绪RCC_Configuration(); //系统时钟初始化 RELAY_Init();//继电器初始化LED_Init();//LED KEY_Init();//KEYI2C_Configuration();//I2C初始化OLED0561_Init(); //OLED初始化OLED_DISPLAY_8x16_BUFFER(0,"   STOP  TEST   "); //显示字符串INT_MARK=0;//标志位清0NVIC_Configuration();//设置中断优先级KEY_INT_INIT();//按键中断初始化(PA0是按键中断输入)RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR,ENABLE);  //使能电源PWR时钟while(1){GPIO_WriteBit(LEDPORT,LED1,(BitAction)(1)); //LED控制OLED_DISPLAY_8x16_BUFFER(4,"  CPU STOP!     "); //显示字符串delay_ms(500); //PWR_EnterSTOPMode(PWR_Regulator_LowPower,PWR_STOPEntry_WFI);//进入停机模式RCC_Configuration(); //系统时钟初始化(停机唤醒后会改用HSI时钟,需要重新对时钟初始化) GPIO_WriteBit(LEDPORT,LED1,(BitAction)(0)); //LED控制OLED_DISPLAY_8x16_BUFFER(4,"  CPU WAKE UP!  "); //显示字符串delay_ms(500); //}}

3.待机模式测试程序

对开发板跳线进行设置

触摸按键将最上方的PA0跳线断开

 

main.c

#include "stm32f10x.h" //STM32头文件
#include "sys.h"
#include "delay.h"
#include "relay.h"
#include "oled0561.h"
#include "led.h"int main (void){//主程序delay_ms(500); //上电时等待其他器件就绪RCC_Configuration(); //系统时钟初始化 RELAY_Init();//继电器初始化LED_Init();//LED I2C_Configuration();//I2C初始化OLED0561_Init(); //OLED初始化OLED_DISPLAY_8x16_BUFFER(0," STANDBY TEST   "); //显示字符串RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR,ENABLE);  //使能电源PWR时钟PWR_WakeUpPinCmd(ENABLE);//WKUP唤醒功能开启(待机时WKUP脚PA0为模拟输入)GPIO_WriteBit(LEDPORT,LED1,(BitAction)(0)); //LED控制OLED_DISPLAY_8x16_BUFFER(4,"  CPU RESET!    "); //显示字符串delay_ms(500); //GPIO_WriteBit(LEDPORT,LED1,(BitAction)(1)); //LED控制OLED_DISPLAY_8x16_BUFFER(4,"   STANDBY!     "); //显示字符串delay_ms(500); //PWR_EnterSTANDBYMode();//进入待机模式//因为待机唤醒后程序从头运行,所以不需要加while(1)的主循环体。
}

二:看门狗

是单片机系统功能的一个辅助功能:帮助单片机自我检查、 监控单片机程序是否正常工作

看门狗定时器(WDT,Watch Dog Timer)是单片机的一个组成部分它实际上是一个计数器,一般给看门狗计数值,程序开始运行后看门狗开始倒计数如果程序运行正常,过一段时间CPU应发出指令让看门狗复位,重新开始倒计数如果看门狗减到0就认为程序没有正常工作,强制整个系统复位看门狗是一个计数器启动后开始倒计时每过一段时间CPU要重新写入计数值(喂狗)CPU能重写计数值,表示程序运行正常如果程序运行出错或死机,则不能重写计数值当计数值减到O时,看门狗会让整个单片机复位看门狗的作用看门狗的主要目的是监控单片机程序如果程序不断喂狗,就证明单片机工作正常如果程序没有喂狗,就说明单片机出了问题看门狗不能检查问题的原因,只能通过复位单片机,让程序重新开始运行类型:独立看门狗、窗口看门狗

独立看门狗可在计数到O前随时喂狗用于监控程序是否正常运行

 

窗口看门狗必须在规定的时间范围内喂狗作用是监控单片机运行时效是否精确

 

1.独立看门狗测试程序

 新建文件夹

Basic文件夹——>iwdg文件夹——>iwdg.c  iwdg.h

iwdg.h

#ifndef __IWDG_H
#define __IWDG_H	 
#include "sys.h"//看门狗定时时间计算公式:Tout=(预分频值*重装载值)/40 (单位:ms)
//当前pre为64,rlr为625,计算得到Tout时间为1秒(大概值)。#define pre		IWDG_Prescaler_64 //分频值范围:4,8,16,32,64,128,256
#define rlr		625 //重装载值范围:0~0xFFF(4095)void IWDG_Init(void);
void IWDG_Feed(void);#endif

iwdg.c

#include "iwdg.h"void IWDG_Init(void){ //初始化独立看门狗IWDG_WriteAccessCmd(IWDG_WriteAccess_Enable); //使能对寄存器IWDG_PR和IWDG_RLR的写操作IWDG_SetPrescaler(pre); //设置IWDG预分频值IWDG_SetReload(rlr); //设置IWDG重装载值IWDG_ReloadCounter(); //按照IWDG重装载寄存器的值重装载IWDG计数器IWDG_Enable(); //使能IWDG
}void IWDG_Feed(void){ //喂狗程序IWDG_ReloadCounter();//固件库的喂狗函数
}

main.c

#include "stm32f10x.h" //STM32头文件
#include "sys.h"
#include "delay.h"
#include "relay.h"
#include "oled0561.h"
#include "led.h"
#include "key.h"#include "iwdg.h"int main (void){//主程序delay_ms(500); //上电时等待其他器件就绪RCC_Configuration(); //系统时钟初始化 RELAY_Init();//继电器初始化LED_Init();//LED KEY_Init();//KEYI2C_Configuration();//I2C初始化OLED0561_Init(); //OLED初始化---------------"OLED_DISPLAY_8x16_BUFFER(0,"   IWDG TEST    "); //显示字符串OLED_DISPLAY_8x16_BUFFER(4,"    RESET!      "); //显示字符串delay_ms(800); //OLED_DISPLAY_8x16_BUFFER(4,"                "); //显示字符串IWDG_Init(); //初始化并启动独立看门狗while(1){IWDG_Feed(); //喂狗if(!GPIO_ReadInputDataBit(KEYPORT,KEY1)){delay_s(2);	//延时2秒,使程序不能喂狗而导致复制}}
}

2.窗口看门狗测试程序

 新建文件夹

Basic文件夹——>wwdg文件夹——>wwdg.c  wwdg.h

wwdg.h

#ifndef __WWDG_H
#define __WWDG_H	 
#include "sys.h"//窗口看门狗定时时间计算公式:
//上窗口超时时间(单位us) = 4096*预分频值*(计数器初始值-窗口值)/APB1时钟频率(单位MHz)
//下窗口超时时间(单位us) = 4096*预分频值*(计数器初始值-0x40)/APB1时钟频率(单位MHz)#define WWDG_CNT	0x7F //计数器初始值,范围:0x40~0x7F
#define wr		0x50 //窗口值(上窗口边界),范围:0x40~0x7F
#define fprer	WWDG_Prescaler_8 //预分频值,取值:1,2,4,8//如上三个值是:0x7f,0x50,8时,上窗口48MS,下窗口64MS。void WWDG_Init(void);
void WWDG_NVIC_Init(void);
void WWDG_Feed(void);#endif

wwdg.c

#include "wwdg.h"void WWDG_Init(void){ //初始化窗口看门狗RCC_APB1PeriphClockCmd(RCC_APB1Periph_WWDG, ENABLE); // WWDG 时钟使能WWDG_SetPrescaler(fprer); //设置 IWDG 预分频值WWDG_SetWindowValue(wr); //设置窗口值WWDG_Enable(WWDG_CNT); //使能看门狗,设置 counterWWDG_ClearFlag(); //清除提前唤醒中断标志位WWDG_NVIC_Init(); //初始化窗口看门狗 NVICWWDG_EnableIT(); //开启窗口看门狗中断
}void WWDG_NVIC_Init(void){ //窗口看门狗中断服务程序(被WWDG_Init调用)NVIC_InitTypeDef NVIC_InitStructure;NVIC_InitStructure.NVIC_IRQChannel = WWDG_IRQn; //WWDG 中断NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2; //抢占 2 子优先级 3 组 2NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3; //抢占 2,子优先级 3,组 2NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;NVIC_Init(&NVIC_InitStructure); //NVIC 初始化
}void WWDG_Feed(void){ //窗口喂狗程序WWDG_SetCounter(WWDG_CNT); //固件库的喂狗函数
}void WWDG_IRQHandler(void){	//窗口看门狗中断处理程序WWDG_ClearFlag(); //清除提前唤醒中断标志位//此处加入在复位前需要处理的工作或保存数据
}

main.c

#include "stm32f10x.h" //STM32头文件
#include "sys.h"
#include "delay.h"
#include "relay.h"
#include "oled0561.h"
#include "led.h"
#include "key.h"#include "wwdg.h"int main (void){//主程序delay_ms(500); //上电时等待其他器件就绪RCC_Configuration(); //系统时钟初始化 RELAY_Init();//继电器初始化LED_Init();//LED KEY_Init();//KEYI2C_Configuration();//I2C初始化OLED0561_Init(); //OLED初始化---------------"OLED_DISPLAY_8x16_BUFFER(0,"   WWDG TEST    "); //显示字符串OLED_DISPLAY_8x16_BUFFER(4,"    RESET!      "); //显示字符串delay_ms(800); //OLED_DISPLAY_8x16_BUFFER(4,"                "); //显示字符串WWDG_Init(); //初始化并启动独立看门狗while(1){delay_ms(54); //用延时找到喂狗的窗口时间    避开计数初始值到上窗口边界这段时间WWDG_Feed(); //喂狗if(!GPIO_ReadInputDataBit(KEYPORT,KEY1)){delay_s(2);	//延时2秒,使程序不能喂狗而导致复制}}
}

三:TIM定时器

 

定时器的3种功能捕获器:测量波形的频率和宽度比较器:分为模拟比较器和输出比较器模拟比较器:比较两组输入电压的大小(STM32F103无此功能)输出比较器:产生可调频率和可调占空比的脉冲波形PWM:脉宽调制器,产生固定频率但占空比可调的脉冲波形普通定时器定时器可以用于独立时间计时功能,原理和嘀嗒定时器、看门狗基本相同定时时间到时,可等待CPU检查标志位(查寻方式),或产生“定时器中断”—般都是让定时器产生中断捕获器捕获什么?    输入接口的电平变化(上升沿或下降沿)上升沿:从低电平到高电平下降沿:从高电平到低电平有什么用?    可测量脉冲的宽度,或者测量脉冲频率宽度T1是上沿捕获的定时器值T2是下沿捕获的定时器值T2-T1=高电平宽度值频率T1是第1次上沿捕获值T2是第2次上沿捕获值T2-T1=一个周期时间值(频率)工作过程!    当接口产生上升沿或下降沿时,将当前定时器值保存输出比较器可输出脉冲,可调占空比和频率每一个周期的长度都可以不同每一个周期内的占空比都可以不同PWM只能调占空比(也是可以通过程序调频率,但不方便随时调)输出比较器可随时调占空比和频率输出比较器主要用于步进电机、伺服电机的控制

定时器中断测试程序

 新建文件夹

Basic文件夹——>tim文件夹——>tim.c  tim.h

tim.h

#ifndef  __PWM_H
#define  __PWM_H
#include "sys.h"void TIM3_Init(u16 arr,u16 psc);
void TIM3_NVIC_Init (void);#endif

tim.c

#include "led.h" //因在中断处理函数中用到LED驱动#include "tim.h"//定时器时间计算公式Tout = ((重装载值+1)*(预分频系数+1))/时钟频率;
//例如:1秒定时,重装载值=9999,预分频系数=7199void TIM3_Init(u16 arr,u16 psc){  //TIM3 初始化 arr重装载值 psc预分频系数TIM_TimeBaseInitTypeDef     TIM_TimeBaseInitStrue;RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE);//使能TIM3TIM3_NVIC_Init (); //开启TIM3中断向量TIM_TimeBaseInitStrue.TIM_Period=arr; //设置自动重装载值TIM_TimeBaseInitStrue.TIM_Prescaler=psc; //预分频系数TIM_TimeBaseInitStrue.TIM_CounterMode=TIM_CounterMode_Up; //计数器向上溢出TIM_TimeBaseInitStrue.TIM_ClockDivision=TIM_CKD_DIV1; //时钟的分频因子,起到了一点点的延时作用,一般设为TIM_CKD_DIV1TIM_TimeBaseInit(TIM3,&TIM_TimeBaseInitStrue); //TIM3初始化设置TIM_ITConfig(TIM3, TIM_IT_Update, ENABLE);//使能TIM3中断    TIM_Cmd(TIM3,ENABLE); //使能TIM3
}void TIM3_NVIC_Init (void){ //开启TIM3中断向量NVIC_InitTypeDef NVIC_InitStructure;NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn;	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x3;	//设置抢占和子优先级NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x3;NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;NVIC_Init(&NVIC_InitStructure);
}void TIM3_IRQHandler(void){ //TIM3中断处理函数if (TIM_GetITStatus(TIM3, TIM_IT_Update) != RESET){	//判断是否是TIM3中断TIM_ClearITPendingBit(TIM3, TIM_IT_Update);//此处写入用户自己的处理程序GPIO_WriteBit(LEDPORT,LED1,(BitAction)(1-GPIO_ReadOutputDataBit(LEDPORT,LED1))); //取反LED1}
}

main.c

#include "stm32f10x.h" //STM32头文件
#include "sys.h"
#include "delay.h"
#include "relay.h"
#include "oled0561.h"
#include "led.h"
#include "key.h"#include "tim.h"int main (void){//主程序delay_ms(500); //上电时等待其他器件就绪RCC_Configuration(); //系统时钟初始化 RELAY_Init();//继电器初始化LED_Init();//LED KEY_Init();//KEYI2C_Configuration();//I2C初始化OLED0561_Init(); //OLED初始化---------------"OLED_DISPLAY_8x16_BUFFER(0,"   TIM TEST     "); //显示字符串TIM3_Init(9999,7199);//定时器初始化,定时1秒(9999,7199)while(1){//写入用户的程序//LED1闪烁程序在TIM3的中断处理函数中执行}
}

四:CRC循环冗余校验计算单元与芯片ID

1.CRC功能测试程序

CRC(循环冗余校验)计算单元使用一个固定的多项式发生器,从一个32位的数据字产生一个CRC码在众多的应用中,基于CRC的技术被用于验证数据传输或存储的一致性在EN/IEC 60335-1标准的范围内,它提供了一种检测闪存存储器错误的手段,CRC计算单元可以用于实时地计算软件的签名,并与在链接和生成该软件时产生的签名对比。√CRC是用于数据正确性校验的√由一个32位的数据字产生√可应用在FALSH检测√可用于软件签名及对比特点:写入和读出都是同一个寄存器,但内容却不同

 

main.c

#include "stm32f10x.h" //STM32头文件
#include "sys.h"
#include "delay.h"
#include "relay.h"
#include "oled0561.h"
#include "led.h"
#include "key.h"int main (void){//主程序u32 a,b;u8 c;u32 y[3]={0x87654321,0x98765432,0x09876543};delay_ms(500); //上电时等待其他器件就绪RCC_Configuration(); //系统时钟初始化 RELAY_Init();//继电器初始化LED_Init();//LED KEY_Init();//KEYI2C_Configuration();//I2C初始化OLED0561_Init(); //OLED初始化---------------"OLED_DISPLAY_8x16_BUFFER(0,"   CRC TEST     "); //显示字符串RCC_AHBPeriphClockCmd(RCC_AHBPeriph_CRC, ENABLE);//开启CRC时钟while(1){CRC_ResetDR();//复位CRC,需要清0重新计算时先复位CRC_CalcCRC(0x12345678);//CRC计算一个32位数据。参数:32位数据。返回值:32位计算结果CRC_CalcCRC(0x23456789);//CRC计算一个32位数据。参数:32位数据。返回值:32位计算结果a = CRC_CalcCRC(0x34567890);//CRC计算一个32位数据。参数:32位数据。返回值:32位计算结果CRC_ResetDR();//复位CRC,需要清0重新计算时先复位b = CRC_CalcBlockCRC(y,3);//CRC计算一个32位数组。参数:32位数组名,数组长度。返回值:32位计算结果CRC_SetIDRegister(0x5a);//向独立寄存器CRC_IDR写数据。参数:8位数据。c = CRC_GetIDRegister();//从独立寄存器CRC_IDR读数据。返回值:8位数据。//此时,a存放的是3个独立数的CRC结果。(32位)//b存放的是数组y中3个数据CRC计算结果。(32位)//c存放的是我们写入的独立寄存器数据0x5a。(8位)}
}//	以下是CRC固件库函数,可在主程序中直接调用  ////	RCC_AHBPeriphClockCmd(RCC_AHBPeriph_CRC, ENABLE);//开启CRC时钟,主程序开始时调用
//	CRC_ResetDR();//复位CRC,需要清0重新计算时先复位
//	uint32_t CRC_CalcCRC(uint32_t Data);//CRC计算一个32位数据。参数:32位数据。返回值:32位计算结果
//	uint32_t CRC_CalcBlockCRC(uint32_t pBuffer[], uint32_t BufferLength);//CRC计算一个32位数组。参数:32位数组名,数组长度。返回值:32位计算结果
//	uint32_t CRC_GetCRC(void);//从CRC中读出计算结果。返回值:32位计算结果。//	void CRC_SetIDRegister(uint8_t IDValue);//向独立寄存器CRC_IDR写数据。参数:8位数据。
//	uint8_t CRC_GetIDRegister(void);//从独立寄存器CRC_IDR读数据。返回值:8位数据。

stm32f10x_crc. c包含了CRC的固件库函数

2.芯片ID读取程序

芯片ID√ 96位ID编码√可读出3个32位数据,或8个8位数据√可以以字节(8位)为单位读取,也可以以半字(16位)或者全字(32位)读取√每个芯片编码是唯一的,出厂时固化,不可修改√ 可用于产品序列号√用来作为密码,提高安全性    √用来保护程序的不可复制

 

main.c

#include "stm32f10x.h" //STM32头文件
#include "sys.h"
#include "delay.h"
#include "relay.h"
#include "oled0561.h"
#include "led.h"
#include "key.h"#include "usart.h"int main (void){//主程序u32 ID[3];delay_ms(500); //上电时等待其他器件就绪RCC_Configuration(); //系统时钟初始化 RELAY_Init();//继电器初始化LED_Init();//LED KEY_Init();//KEYUSART1_Init(115200); //串口初始化(参数是波特率)I2C_Configuration();//I2C初始化OLED0561_Init(); //OLED初始化---------------"OLED_DISPLAY_8x16_BUFFER(0,"  CHIP ID TEST  "); //显示字符串ID[0] = *(__IO u32 *)(0X1FFFF7E8); //读出3个32位ID 高字节ID[1] = *(__IO u32 *)(0X1FFFF7EC); // ID[2] = *(__IO u32 *)(0X1FFFF7F0); // 低字节//08表示后面的数据不足8位就补0显示printf("ChipID: %08X %08X %8X \r\n",ID[0],ID[1],ID[2]); //从串口输出16进制IDif(ID[0]==0x066EFF34 && ID[1]==0x3437534D && ID[2]==0x43232328){ //检查ID是否匹配printf("chipID OK! \r\n"); //匹配}else{printf("chipID error! \r\n"); //不同}while(1){}
}

五:还需要补充的知识

1.仿真仿真接口有JTAG、SW接口,仿真器又有ST-LINK、J-LINK等还有纯软件仿真Proteus等2.HEL库3.内置USB接口USB鼠标、键盘、U盘4.显示屏除OLED之外,还能外扩LCD1602、12864等显示屏的类型还有VOG屏、TFT屏等每种屏的接口也分好多种5.定时器的复杂功能TIM1高级定时器的使用单脉冲模式输出比较器的使用捕获器的使用定时器的DMA设置6.中断的复杂功能中断嵌套应用与优先级问题外部中断的端口映射问题7.单片机内部功能WIFI、蓝牙、GPS模块、2.4G模块、彩屏的人机界面、RTOS嵌入式操作系统....

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/26167.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Linux网络服务之部署yum仓库

yum ? yum ! 一、YUM概述1.1 yum简介1.2 yum工作原理 二、yum 配置文件2.1 yum主配置文件2.2 yum仓库设置文件2.2.1 配置文件主要格式2.2.2 软件仓库的提供方式2.2.3 日志文件 三、yum命令详解3.1 安装和升级3.2 查询3.2.1 显示可用的安装包 ----- yum list3.2.2 显…

Python程序设计基础:函数(一)

文章目录 一、函数的基本概念二、函数的定义和使用1、函数的定义与调用2、函数的参数3、返回多个值 一、函数的基本概念 在使用Python实现某些复杂的功能的时候,容易遇到一些重复率较高的代码,为了代码能够重复使用并提升代码的整洁度,函数这…

Vulnhub: ColddWorld: Immersion靶机

kali:192.168.111.111 靶机:192.168.111.183 信息收集 端口扫描 nmap -A -sC -v -sV -T5 -p- --scripthttp-enum 192.168.111.183 查看login的源码发现提示:page和文件/var/carls.txt 漏洞利用 wfuzz探测account.php页面发现文件包含&am…

Excel中——日期列后添加星期

需求:在日期列中添加星期几? 第一步:打开需要添加星期的Excel文件,在日期后面添加日期 第二步:选择日期列,点击鼠标右键,在下拉列表中,选择“设置单元格格式” 第三步: 在…

JVM基础篇-StringTable

StringTable 特性 常量池中的字符串仅是符号,第一次用到时才变为对象 利用串池的机制,来避免重复创建字符串对象 字符串变量拼接的原理是 StringBuilder (1.8) 字符串常量拼接的原理是编译期优化 可以使用 intern 方法&#…

【Spring】(一)Spring设计核心思想

文章目录 一、初识 Spring1.1 什么是 Spring1.2 什么是 容器1.3 什么是 IoC 二、对 IoC 的深入理解2.1 传统程序开发方式存在的问题2.2 控制反转式程序的开发2.3 对比总结 三、对 Spring IoC 的理解四、DI 的概念4.1 什么是 DI4.2 DI 与 IoC的关系 一、初识 Spring 1.1 什么是…

Mermaid系列之FlowChart流程图

一.欢迎来到我的酒馆 介绍mermaid下,Flowchat流程图语法。 目录 一.欢迎来到我的酒馆二.什么是mermiad工具三.在vs code中使用mermaid四.基本语法 二.什么是mermiad工具 2.1 mermaid可以让你使用代码来创建图表和可视化效果。mermaid是一款基于javascript语言的图表…

宝塔面板点击SSL闪退打不开怎么解决?

宝塔Linux面板点击SSL证书闪退如何解决?旧版本的宝塔Linux面板确实存在这种情况,如何解决?升级你的宝塔Linux面板即可。新手站长分享宝塔面板SSL闪退的解决方法: 宝塔面板点击SSL证书闪退解决方法 问题:宝塔Linux面板…

谈谈网络安全

目录 1.概念 2.发展现状 3.主要问题 1.概念 网络安全是指保护计算机网络和其中的数据免受未经授权访问、损坏、窃取或破坏的过程和技术。网络安全涉及预防和检测潜在的威胁和漏洞,并采取措施保护网络的机密性、完整性和可用性。 网络安全的概念包括以下几个方面&am…

vue2 todoapp案例(静态)

1.创建三个子组件(TodoHeader、TodoMain、TodoFooter)和两个(index.css、base.css)样式&#xff1b; TodoHeader页面 <template><header class"header"><h1>todos</h1><input id"toggle-all" class"toggle-all" typ…

【力扣】链表题目总结

文章目录 链表基础题型一、单链表翻转、反转、旋转1.反转链表2.反转链表II——反转部分链表3.旋转链表4.K个一组翻转链表5.反转偶数长度组的节点 二、删除单链表中的结点1.删除链表的结点2.删除未排序链表中的重复节点3.删除已排序链表中的重复元素I——重复元素只剩下一个4.删…

【ASP.NET MVC】第一个登录页面(8)

一、准备工作 先从网上&#xff08;站长之家、模板之家&#xff0c;甚至TB&#xff09;下载一个HTML模板&#xff0c;要求一整套的CSS和必要的JS&#xff0c;比如下图&#xff1a; 登录页面的效果是&#xff1a; 首页&#xff1a; 利用这些模板可以减少前台网页的设计——拿来…

vue+element中如何设置单个el-date-picker开始时间和结束时间关联

功能&#xff1a;选了开始时间&#xff0c;则结束时间只能选择开始时间之后的&#xff1b;选了结束时间&#xff0c;则开始时间只能选择结束时间之前的 重点是picker-options属性 图示&#xff1a; 代码展示: // body 内部<el-form-item><el-date-pickerv-model&qu…

Qt+联想电脑管家

1.自定义按钮类 效果&#xff1a; (1)仅当未选中&#xff0c;未悬浮时 (2)其他三种情况&#xff0c;均如图 #ifndef BTN_H #define BTN_H#include <QPushButton> class btn : public QPushButton {Q_OBJECT public:btn(QWidget * parent nullptr);void set_normal_icon(…

02_kafka_基本概念_基础架构

文章目录 常见的消息队列工作模式基本概念kafka 特性Kafka 基本架构topic 分区的 目的/ 好处 日志存储形式消费者&#xff0c;消费方式 逻辑消费组 高性能写入&#xff1a; 顺序写 mmap读取&#xff1a;零拷贝DMA 使用场景 常见的消息队列工作模式 至多一次&#xff1a;消息被…

pytorch实战-图像分类(二)(模型训练及验证)(基于迁移学习(理解+代码))

目录 1.迁移学习概念 2.数据预处理 3.训练模型&#xff08;基于迁移学习&#xff09; 3.1选择网络&#xff0c;这里用resnet 3.2如果用GPU训练&#xff0c;需要加入以下代码 3.3卷积层冻结模块 3.4加载resnet152模 3.5解释initialize_model函数 3.6迁移学习网络搭建 3.…

UE4/5 GAS技能系统入门2 - AttributeSet

在GAS系统中对属性进行修改需要用到GE&#xff08;Gameplay Effect&#xff09;&#xff0c;而这又涉及到AttributeSet这样的概念。 AttributeSet用于描述角色的属性集合&#xff0c;如攻击力、血量、防御力等&#xff0c;与GAS系统整合度较高&#xff0c;本文就来讲一讲Attri…

Consul屏蔽api

consul 没有设置密码 需要屏蔽api&#xff1a;/v1/internal/ui/nodes?dc&token 防止信息泄露 配置config.json {"http_config": {"block_endpoints": ["/v1/internal/ui/nodes"]} }启动consul时使用该配置&#xff1a; consul agent -de…

Java实现Google cloud storage 文件上传,Google oss

storage 控制台位置 创建一个bucket 点进bucket里面&#xff0c;权限配置里&#xff0c;公开访问&#xff0c;在互联网上公开&#xff0c;需要配置角色权限 新增一个访问权限 &#xff0c;账号这里可以模糊搜索&#xff0c; 角色配置 给allUser配置俩角色就可以出现 在互联…

0.CLIP

目录 前言背景缘起/摘要数据集拟解决问题 精读IntroductionModel2.1自然语言监督2.2 创建一个有效的大数据集选择一个有效的预训练方法2.4 选择模型&#xff08;选择Encoder&#xff09;2.5训练小结 实验 复现&#xff08;略&#xff09; 前言 本课程来自深度之眼《多模态》训…