stm32独立看门狗操作寄存器 库函数

stm32独立看门狗操作寄存器 库函数
stm32独立看门狗操作寄存器 库函数

stm32 独立看门狗[操作寄存器+库函数]

以单片机为核心的微型计算机系统中,单片机经常

会受到来自外界电磁场的干扰。

造成程序跑飞,只是程序的正常运行状态被打断而进入

死循环,从而使单片机控制的系统无法正常工作。看门

狗就是一种专门用于检测单片机程序运行状态的硬件结构。

stm32也是如此。

stm32 的独立看门狗由内部专门的40Khz低速时钟驱动,即使主时钟发生故障时,它也仍然有效。这里需要注意

的是独立看门狗的时钟是一个内部时钟,所以不是准确

的40Khz,而是在30~60Khz之间的一个可变化的时钟,

看门狗的时钟对时间的要求不是很精确,所以时钟有偏

差可以接受。

本例直接操作寄存器实现验证独立看门狗的复位功能,

设定一个800ms的喂狗时间,在主函数中实现LED闪烁,如果设定一个1s的延时,则触发独立看门狗复位,LED

常亮。

库函数实现当外部中断发生(按下PA0按键),长时间不喂狗,引发独立看门狗复位时,向外用串口输出复位提示。

直接操作寄存器

使用独立看门狗,需要了解一下寄存器:

键值寄存器:(IWDG_KR)

低16位有效的寄存器,只写寄存器,读出值恒为0x0000. 软件必须以一定的间隔写入0xAAAA,否则,当计数器为

0时,看门狗会产生复位。

写入0x5555表示允许访问IWDG_PR和IWDG_RLR寄存器。写入0xCCCC,启动看门狗工作。

预分频寄存器:(IWDG_PR)

第三位有效寄存器,用于设置看门狗的分频系数,最低

为4,最高位256.

通过设置PR[2:0]:位来选择计数器时钟的预分频因子。

要改变预分频因子,IWDG_SR寄存器的PVU位必须为0。

000: 预分频因子=4

100: 预分频因子=64

001: 预分频因子=8

101: 预分频因子=128

010: 预分频因子=16

110: 预分频因子=256

011: 预分频因子=32

111: 预分频因子=256

重装载寄存器:(IWDG_RLR)

低12位有效,RL[11:0]。用于定义看门狗计数器的重装载值。

每当向IWDG_KR寄存器写入0xAAAA时,重装载值会被传送到计数器中。随后计数器从这个值开始递减计数。看

门狗超时周期可通过此重装载值和时钟预分频值来计算。只有当IWDG_SR寄存器中的RVU位为0时,才能对此寄存器进行修改。

状态寄存器:(IWDG_SR)

只有低两位有效。都由硬件置’1’和清

’0’。

RVU[1]: 看门狗计数器重装载值更新

PVU[0]: 看门狗预分频值更新

代码如下:(system.h 和 stm32f10x_it.h 等相关代码参照 stm32 直接操作寄存器开发环境配置)

User/main.c

01 #include ;

02 #include "system.h"

03 #include "wdg.h"

04

05 #define LED1 PAout(4)

06 #define LED2 PAout(5)

07

08 void Gpio_Init(void);

09

10 int main(void)

11 {

12

13

Rcc_Init(9);

//系统时钟设置

14

15

Gpio_Init();

16

17

Iwdg_Init(3,1000); //设定为800ms内喂狗

18

19

while(1){

20

21

LED1 = !LED1;

22

23

delay(100000);

//延时100ms后喂狗,LED闪烁

24

25

//delay(1000000);

//延时1000ms,引发独立看门狗复位,LED不闪烁

26

27

Iwdg_Feed(); //喂狗

28

29

}

30

32

33

34 void Gpio_Init(void)

35 {

36

RCC->;APB2ENR|=1;CRL&=0x0000FFFF; // PA0~3设置为浮空输入,PA4~7设置为推挽输出

39

GPIOA->;CRL|=0x33334444;

40

41 }

Library/wdg.c

(此文件包含了独立看门狗和窗口看门狗的驱动函数)

01 #include ;

02 #include "wdg.h"

03

04 /********************************************

06 *本文件包含窗口看门狗和独立看门口的相关函数

07 *

08

*********************************************/

09

10 u8 Wwdg_Cnt = 0x7F; //计数器值,默认为最大值127

11

12 //独立看门狗初始化

13 //参数说明:

14 //

pre:分频数(0~7),相应分频因子为4*(2^pre) 15 //

rlr:低12位有[11:0]

16 // 喂狗时间计算: T = (4*(2^pre)*rlr)/40;(ms)

17 void Iwdg_Init(u8 pre,u16 rlr)

18 {

19

IWDG ->;KR = 0x5555;

//使能对PR RLR寄存器的写操作

IWDG ->;PR = pre;

//设置分频数

21

IWDG ->;RLR = rlr;

//设定重装值

22

IWDG ->;KR = 0xAAAA;

//装载RLR值到看门狗计数器,即喂狗23

IWDG ->;KR = 0xCCCC;

//启动看门狗

24 }

25

26 //独立看门狗喂狗

27 void Iwdg_Feed()

28 {

IWDG ->; KR = 0xAAAA; //喂狗

30 }

31

32 //窗口看门狗初始化

33 //参数说明:

34 //

cnt

计数器的值,最大 127,0x7F

35 //

w_cnt

窗口值,最大 127,0x7F

36 //

pre

预分频器的时基值,低两位有效;实际时钟为:PLCK1/4096/2^pre

37 //需要再主函数中开启中断 WWDG_IRQChannel

38 //设定喂狗时间范围必须在:(WWDG时钟为PCLK1,36Mhz)

39 //

Tmax =(4096*2^pre*(cnt-63)/36) (us)

40 //

Tmin =(4096*2^pre*(cnt-w_cnt)/36)

(us)

41 //超出次时间喂狗复位

42

43 void Wwdg_Init(u8 cnt,u8 w_cnt,u8 pre)

44 {

45

u8 Cnt_Max = 0x7f;

//计数器最大值

46

47

Wwdg_Cnt = Cnt_Max&cnt;

//设定计数器的值,防止溢出

48

49

RCC->;APB1ENR |= 1; CFR |= pre ; CFR |= 1; CFR

&= 0xFF80;

//初始化低七位,即窗口值清0

55

WWDG ->; CFR |= w_cnt;

// 设定窗口值

56

57

WWDG ->; CR |= Wwdg_Cnt|(1;CR |= (Wwdg_Cnt&0x7F);

66

67 }

Library/wdg.h

1 #include ;

2

3 void Iwdg_Init(u8 pre,u16 rlr);

4 void Iwdg_Feed(void);

5

6 void Wwdg_Init(u8 cnt,u8 w_cnt,u8);

7 void Wwdg_Feed(void);

需要注意的是独立看门狗没有响应的中断。

库函数操作

main.c

view source

print?

001 #include "stm32f10x.h" 002 #include "stdio.h"

003

004 #define PRINTF_ON 1

005

006 void RCC_Configuration(void); 007 void GPIO_Configuration(void); 008 void NVIC_Configuration(void); 009 void USART_Configuration(void); 010 void IWDG_Configuration(void); 011 void EXTI_Configuration(void); 012

013 vu32 DelayTime;

014

015 int main(void)

016 {

017

RCC_Configuration();

018

GPIO_Configuration();

019

NVIC_Configuration();

020

USART_Configuration();

021

EXTI_Configuration();

022

IWDG_Configuration();

023

024

while(1){

025

if(RCC_GetFlagStatus(RCC_FLAG_IWDGRST) == SET) 026

{

027

printf("\r\n The Stm32 has been reset by IWDG .\r\n");

028

RCC_ClearFlag();

029

}

030

031

//do sth. here

032

DelayTime = 100000;

033

while(--DelayTime);

034

// 延时17ms

035

036

IWDG_ReloadCounter();

//80ms不喂狗复位

037

GPIO_WriteBit(GPIOA,GPIO_Pin_4,(BitAction)(1- GPIO_ReadOutputDataBit(GPIOA,GPIO_Pin_4)));

038

}

039 }

040

041 void EXTI_Configuration(void)

042 {

043

EXTI_InitTypeDef EXTI_InitStructure;

044

045

EXTI_InitStructure.EXTI_Line = EXTI_Line0; 046

EXTI_InitStructure.EXTI_Mode =

EXTI_Mode_Interrupt;

047

EXTI_InitStructure.EXTI_Trigger =

EXTI_Trigger_Falling;

048

EXTI_InitStructure.EXTI_LineCmd = ENABLE; 049

EXTI_Init(&EXTI_InitStructure);

050

051

GPIO_EXTILineConfig(GPIO_PortSourceGPIOA,GPIO_Pin Source0);

052

053 }

054

055 void GPIO_Configuration(void)

056 {

057

GPIO_InitTypeDef GPIO_InitStructure;

058

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;

059

GPIO_InitStructure.GPIO_Speed =

GPIO_Speed_50MHz;

060

GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; 061

GPIO_Init(GPIOA , &GPIO_InitStructure);

062

063

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4;

064

GPIO_InitStructure.GPIO_Mode =

GPIO_Mode_Out_PP;

065

GPIO_Init(GPIOA , &GPIO_InitStructure);

066

067

068

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;

069

GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; 070

GPIO_Init(GPIOA , &GPIO_InitStructure);

071

072

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;

073

GPIO_InitStructure.GPIO_Mode =

GPIO_Mode_IN_FLOATING;

074

GPIO_Init(GPIOA , &GPIO_InitStructure);

075

076 }

077

078 void IWDG_Configuration(void)

079 {

080

RCC_LSICmd(ENABLE);

//打开LSI

081

while(RCC_GetFlagStatus(RCC_FLAG_LSIRDY)==RESET); 082

083

IWDG_WriteAccessCmd(IWDG_WriteAccess_Enable); 084

IWDG_SetPrescaler(IWDG_Prescaler_32);

IWDG_SetReload(100);

//80ms ,max 0xFFF 0~4095

086

IWDG_ReloadCounter();

087

IWDG_Enable();

088 }

089

090

091 void RCC_Configuration(void)

092 {

093

/* 定义枚举类型变量 HSEStartUpStatus */ 094

ErrorStatus HSEStartUpStatus;

STM32库函数操作和寄存器操作

STM32库函数操作和寄存器操作 首先,两个都是C语言。从51过渡过来的话,就先说寄存器操作。每个MCU都有自己的寄存器,51是功能比较简单的一种,相应的寄存器也比较少,我们常用的就那么几个,像P0 P1 SMOD TMOD之类的,这些存在于标准头文件reg.h里面,因为少,所以大家就直接这么去操作了,每一位对应的意义随便翻一下手册就看得到,甚至做几个小项目就记的很清楚了。所以做51开发的时候大多数都是直接操作寄存器。 到了STM32,原理一样,也是有自己的寄存器,但是作为一款ARM 内核的芯片,功能多了非常多,寄存器自然也就多了很多,STM32的手册有一千多页,这时候想去像51那样记住每个寄存器已经不现实了,所以ST的工程师就给大家提供了库函数这么一个东西。这是个神器。库函数里面把STM32的所有寄存器用结构体一一对应并且封装起来,而且提供了基本的配置函数。我们要去操作配置某个外设的时候不需要再去翻眼花缭乱的数据手册,直接找到库函数描述拿来就可以用,这样就能把精力放在逻辑代码的开发上,而不是去费力的研究一个芯片的外设要怎么配置寄存器才能驱动起来。简单讲就是这些了,库函数是为了让开发者从大量繁琐的寄存器操作中脱离出来的一个文件包,在使用一个外设的时候让开发者直接去调用相应的驱动函数而不是自己去翻手册一个一个配置寄存器。有人说用库函数掌握不到芯片的精髓,见仁见智了。熟悉一款芯片是在不断的开发使用中逐渐了解并掌握的,调试的过程中会遇到很多问题,会要求我们去跟踪相关寄存器的状态,在整个框架都已经建立起来的基础上再去对照手册做具体到寄存器每一位的分析,代码对照现象,很快就能积累起来经验,祝成功。

STM32单片机的模拟看门狗的库函数设置

STM32单片机的模拟看门狗的库函数设置 ADC的模拟看门狗用于检查电压是否越界。他又上下两个边界,可分别在寄存器ADC_HTR和ADC_LTR中设置。库函数是使用ADC_AnalogWatchdogThresholdsConfig设置的,无论是常规通道还是注入通道,都非常简单。 当模拟看门狗检测到电压高于上限或者低于下限时将会产生看门狗中断。捕获这个中断,可以做出一些应对措施。 数据手册上特别之处的一个东西:模拟看门狗说使用的比较数据与ADC_CR2寄存器中设置的数据对齐方式无关。看门狗比较是在数据对齐之前完成的。先进行看门狗比较,再将数据放入ADC_DR数据寄存器。 在ST的库中,只有简单的三个与看门狗相关的函数: void ADC_AnalogWatchdogCmd(ADC_TypeDef* ADCx, uint32_t ADC_AnalogWatchdog);void ADC_AnalogWatchdogThresholdsConfig(ADC_TypeDef* ADCx, uint16_t HighThreshold,uint16_t LowThreshold);void ADC_AnalogWatchdogSingleChannelConfig(ADC_TypeDef* ADCx, uint8_t ADC_Channel); 使用ADC_AnalogWatchdogThresholdsConfig设置触发看门狗的上下限 使用ADC_AnalogWatchdogSingleChannelConfig配置要使用模拟看门狗的通道 配置完成后使用ADC_AnalogWatchdogCmd启动模拟看门狗。 我写的函数很简单,就这么三行。将模拟看门狗加在ADC1的CH1上。代码如下: void ADC_WatchdogConfig(void){ ADC_AnalogWatchdogSingleChannelConfig(ADC1,ADC_Chan nel_0); ADC_AnalogWatchdogThresholdsConfig(ADC1,1500,0xFFF); ADC_AnalogWatchdogCmd(ADC1,ADC_AnalogWatchdog_SingleRegEnable);} NVIC中初始化模拟看门狗: void NVIC_Config(void){ NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //设置中断优先级分组NVIC_InitStructure.NVIC_IRQChannel = ADC_IRQn; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;

STM32单片机GPIO寄存器的功能解析

STM32单片机GPIO寄存器的功能解析 1、GPIO的寄存器按照功能可以分为以下几类: A、配置寄存器 B、数据寄存器 C、位寄存器 D、锁定寄存器 2、对于GPIO端口,每个端口有16个引脚,每个引脚的模式由寄存器的四个位控制,每四位又分为两位控制引脚配置(CNFy[1:0]),两位控制引脚的模式及最高速度(MODEy [1:0]),其中y表示第y个引脚。配置GPIO引脚模式的一共有两个寄存器,CRH是高寄存器,用来配置高8位引脚,还有CRL配置低八位引脚。 3、端口位设置\清除寄存器(GPIOx_BSRR) 一个引脚y的输出数据由GPIOx_BSRR寄存器位的2个位来控制分别为BRy (Bit Reset y)和BSy (Bit Set y),BRy位用于写1清零,使引脚输出低电平,BSy位用来写1置1,使引脚输出高电平。而对这两个位进行写零都是无效的。 4、Cortex-M3有32根地址线,所以它的 寻址空间大小为2 bit=4GB。ARM公司设计时,预先把这4GB的寻址空间大致地分配好了。它把地址从0x4000 0000至0x5FFF FFFF(512MB )的地址分配给片上外设。 5、stm32f10x.h这个文件中重要的内容就是把STM32的所有寄存器进行地址映射。如同51单片机的头文件一样,stm32f10x.h像一个大表格,我们在使用的时候就是通过宏定义进行类似查表的操作。 6、STM32总线有AHB总线、APB2总线、APB1总线 7、时钟系统。 A、从时钟频率来说分为告诉时钟和低速时钟,高速时钟是提供给芯片主体时钟,而低速时钟只是提供给芯片中的RTC及独立看门狗使用。 B、从芯片角度来说,时钟源分为内部时钟与外部时钟源,内部时钟是在芯片内部RC振

STM32技术参考手册第11章窗口看门狗(WWDG)

11 窗口看门狗(WWDG) 11.1 简介 窗口看门狗通常被用来监测由外部干扰或不可预见的逻辑条件造成的应用程序背离正常的 运行序列而产生的软件故障。除非递减计数器的值在T6位变成0前被刷新,此看门狗电路在 达到可编程的时间周期时,会产生一个MCU复位。在递减计数器达到窗口寄存器值之前, 如果递减计数器值的第7位(在控制寄存器中) 被刷新,那么也将产生一个MCU复位。这表 明递减计数器需要在一个有限的窗口中被刷新。 11.2 主要特性 ● 可编程的自由运行递减计数器 ● 条件复位 ─当递减计数器的值小于40h,(若看门狗被启动)则产生复位。 ─当递减计数器在窗口外被重新装载,(若看门狗被启动)则产生复位。见图11-2。 11.3 功能描述 如果看门狗被启动(WWDG_CR寄存器中的WDGA位被置1),并且当7位(T[6:0])递减计 数器从40h翻转到3Fh(T6位清零)时,则产生一个复位。如果软件在计数器值大于窗口寄 存器中的值时重新装载计数器,将产生一个复位。 框图 看门狗框 图11-1 看门狗 应用程序在正常的运行过程中必须每隔一定的时间间隔写WWDG_CR寄存器以防止MCU 发生复位。只有当计数器值小于窗口寄存器的值时,才能进行这个写操作。这个要被储存 在WWDG_CR寄存器中的值必须在FFh和C0h之间: ● 启动看门狗 看门狗通常在复位后被禁止。设置WWDG_CR寄存器中的WDGA位将启动看门狗, 一旦被启动后,看门狗则不能再被关闭,除非发生复位。

● 控制递减计数器 递减计数器处于自由运行状态,即使看门狗被禁止,递减计数器仍继续递减计数。当看门狗被启用时,T6位必须被设置,以防止立即产生一个复位。 T[5:0]位包含了在看门狗产生复位之前的延时增量;复位前的延时时间在一个最小值和一个最大值之间变化,这是因为写入WWDG_CR 寄存器时,预分频值是未知的。 配置寄存器(WWDG_CFR) 中包含窗口的上限值:要避免产生复位,递减计数器必须在其值小于窗口寄存器的值并且大于3Fh 时被重新装载,图11-2描述了窗口寄存器的工作过程。 注: T6位可以被用来产生一个软件复位(WDGA 位被置位,T6位清零) 11.4 如何编写看门狗超时程序 图11-2显示了装载到看门狗计数器(CNT )中的6位计数值和看门狗的延迟时间之间的线性关系(以ms 为单位)。此图可用来做为快速计算的参考而未将时间的偏差考虑在内。如果需要更高的精度,可以使用图11-2提供的计算公式。 警告警告::当写入WWDG_CR 寄存器时寄存器时,,始终把T6位写1来避免来避免立即立即立即产生一个复位产生一个复位产生一个复位。。 图11-2 窗口看门狗时序图

STM32f103寄存器说明

CRC寄存器 (一种算法,用以确认发送过程中是否出错)数据寄存器:CRC_DR 可读写,复位值:0xFFFF FFFF; 独立数据寄存器:CRC_IDR 临时存放任何8位数据; 控制寄存器:CRC_CR 只零位可用,用于复位CRC,对其写1复位,由硬件清零; PWR电源控制(控制和管理电源) 电源控制寄存器:PWR_CR 控制选择系统的电源 电源控制/状态寄存器:PWR_CSR 睡眠或待机模式电源控制 BKP备份寄存器(用以控制和管理备份数据) 备份数据寄存器x:BKP_DRx (x = 1 … 10) 10个16位数据寄存器用以存储用户数据 RTC时钟校准寄存器:BKP_RTCCR 控制实时时钟的运行 备份控制寄存器:BKP_CR 控制选择清除备份数据的类型

备份控制/状态寄存器:BKP_CSR 对侵入事件的控制 RCC寄存器(时钟的选择、复位、分频) 时钟控制寄存器(RCC_CR) 各时钟状态显示 时钟配置寄存器(RCC_CFGR) 时钟分频 时钟中断寄存器(RCC_CIR) 控制就绪中断使能与否 APB2外设复位寄存器(RCC_APB2RSTR) APB1外设复位寄存器(RCC_APB1RSTR) 复位APB各功能寄存器 AHB外设时钟使能寄存器(RCC_AHBENR) AHB时钟使能控制 APB2外设时钟使能寄存器(RCC_APB2ENR) APB1外设时钟使能寄存器(RCC_APB1ENR) APB1时钟使能控制 备份域控制寄存器(RCC_BDCR) 备份域时钟控制 控制/状态寄存器(RCC_CSR) 复位标志寄存器 AHB外设时钟复位寄存器(RCC_AHBRSTR) 复位以太网MAC模块 时钟配置寄存器2(RCC_CFGR2) 时钟选择与分频

STM32使用BSRR和BRR寄存器快速操作

STM32使用BSRR和BRR寄存器快速操作 GPI0端口STM32的每个GPIO端口都有两个特别的寄存器,GPIOx_BSR和GPIOx_BRF寄存器,通过这两个寄存器可以直接对对应的GPIOx端口置“或置“ 0。“ GPIOx_BSRR勺高16位中每一位对应端口x的每个位,对高16位中的某位置“狈『端口x的对应位被清“0;“寄存器中的位置“0, “则对它对应的位不起作 用。 GPIOx_BSRR的氐16位中每一位也对应端口x的每个位,对低16位中的某位置“1则“它对应的端口位被置“1;“寄存器中的位置“0,“则对它对应的端口不起作用。 简单地说GPIOx_BSR的高16位称作清除寄存器,而GPIOx_BSR的低氐16 位称作设置寄存器。另一个寄存器GPIOx_BRfl只有低16位有用,与GPIOx_BSR 的高16位具有相同功能。 举个例子说明如何使用这两个寄存器和所体现的优势。例如GPIOE的16个IO都被设置成输出,而每次操作仅需要改变低8位的数据而保持高8位不变,假设新的8 位数据在变量Newdata 中, 这个要求可以通过操作这两个寄存器实现,STM32的固件库中有两个函数GPIO_SetBits和GPIO_ResetBits使用了这两个寄存器操作端口。 上述要求可以这样实现: GPI0_SetBits(GPI0E, Newdata & 0xff); GPI0_ResetBits(GPI0E, (~Newdata & 0xff)); 也可以直接操作这两个寄存器: GPI0E->BSRR = Newdata & 0xff; GPI0E->BRR = ~Newdata & 0xff; 当然还可以一次完成对8位的操作:

stm32 BKP寄存器操作操作寄存器+库函数

stm32 BKP 寄存器操作操作寄存器+库函数 BKP 是BACKUP 的缩写,stm32f103RCTE 的内部配备了10 个16 位宽度 的BKP 寄存器。在主电源切断或系统产生复位时间时,BKP 寄存器仍然可以 在备用电源的支持下保持其内容。BKP 在实际应用中可以存入重要数据,防止 被恶意查看,或用于断电等。本例实现对BKP 寄存器的读写操作,和入侵检 测和处理。主程序中写入寄存器后,依次打印出10 个BKP 寄存器数据,然后 触发GPIOC13 的入侵中断(输入低电平),在中断中打印出入侵事件发生后的 寄存器内容(复位为0 )。直接操作寄存器用到的寄存器描述如下:备份数据 寄存器x(BKP_DRx) (x = 1 10):低16 位[15:0]有效,用来写入或读出备份数据。备份控制寄存器(BKP_CR):低两位有效。TPAL[1]:侵入检测TAMPER 引脚有效电平(TAMPER pin active level)0:侵入检测TAMPER 引脚上的高电平会清除所有数据备份寄存器(如果TPE 位为1) 1:侵入检测TAMPER 引脚 上的低电平会清除所有数据备份寄存器(如果TPE 位为1)TPE[0]:启动侵入检 测TAMPER 引脚(TAMPER pin enable)0:侵入检测TAMPER 引脚作为通用IO 口使用1:开启侵入检测引脚作为侵入检测使用备份控制/状态寄存器 (BKP_CSR): TIF[9]:侵入中断标志(Tamper interrupt flag) 0:无侵入中断1:产生侵入中断当检测到有侵入事件且TPIE 位为1 时,此位由硬件置1。通过向CTI 位 写1 来清除此标志位(同时也清除了中断)。如果TPIE 位被清除,则此位也会被 清除。TEF[8]:侵入事件标志(Tamper event flag) 0:无侵入事件1:检测到侵入事件当检测到侵入事件时此位由硬件置1。通过向CTE 位写1 可清除此标 志位TPIE[2]:允许侵入TAMPER 引脚中断(TAMPER pin interrupt enable)0:禁止侵入检测中断1:允许侵入检测中断(BKP_CR 寄存器的TPE 位也必须被置1)注

STM32F103V IWDG 独立看门狗操作

STM32F103V IWDG 独立看门狗操作 最近编写一个程序,因为需要考虑到可靠性,所以需要在程序了添加看门 狗功能。查了下STM32 的相关资料,于是利用下库文件来实现IWDG 独立看 门狗操作。首先需要调用库文件#include “stm32f10x_iwdg.h”再配置下看门狗 相关参数 //////////独立看门狗IWDG 设置////////////////////////////////////void WatchDog_int(void) // 独立看门狗IWDG 设置{/* Enable write access to IWDG_PR and IWDG_RLR registers */ IWDG_WriteAccessCmd(IWDG_WriteAccess_Enable); /* IWDG counter clock: 32KHz(LSI) / 32 = 1KHz */ IWDG_SetPrescaler(IWDG_Prescaler_32); //独立看门狗预分频为32 /* Set counter reload value to 1000 */ IWDG_SetReload(1000);//设置IWDG 重装载值范围为0~0x0FFF; /* Reload IWDG counter */ IWDG_ReloadCounter();//按照重装载的寄存器的值来重装载IWDG 计数器 /* Enable IWDG (the LSI oscillator will be enabled by hardware) */ IWDG_Enable();//使能独立看门狗} 在主程序中实现喂狗的程序如下: ///////////主程序//////////////////int main(void){ RCC_Configuration(); //时钟配置NVIC_Configuration();//中断配置GPIO_Configuration();//GPIO 配置WatchDog_int();// 独立看门狗IWDG 设置/* 检查是否看门狗复位*/ if(RCC_GetFlagStatus(RCC_FLAG_IWDGRST) != RESET) { printf(“WatchDog Reset\r\n”); speakertest(); RCC_ClearFlag();//清除标志位} else {;} }

嵌入式系统看门狗实验报告

竭诚为您提供优质文档/双击可除嵌入式系统看门狗实验报告 篇一:《嵌入式系统原理与应用》实验报告04-看门狗实验 《嵌入式系统原理与接口技术》实验报告 实验序号:4实验项目名称:看门狗实验 1 2 3 4 篇二:嵌入式实验报告 目录 实验一跑马灯实验................................................. (1) 实验二按键输入实验................................................. .. (3)

实验三串口实验................................................. . (5) 实验四外部中断实验................................................. .. (8) 实验五独立看门狗实验................................................. (11) 实验七定时器中断实验................................................. (13) 实验十三ADc实验................................................. .. (15) 实验十五DmA实验................................................. .. (17) 实验十六I2c实验................................................. .. (21) 实验十七spI实

STM32窗口看门狗程序

STM32窗口看门狗程序 窗口看门狗(WWDG)通常被用来监测由外部干扰或不可预见的逻辑条件造成的应用程序背离正常的运行序列而产生的软件故障。除非递减计数器的值在T6位(WWDG->;CR的第六位)变成0前被刷新,看门狗电路在达到预置的时间周期时,会产生一个MCU复位。在递减计数器达到窗口配置寄存器(WWDG->;CFR)数值之前,如果7位的递减计数器数值(在控制寄存器中)被刷新,那么也将产生一个MCU复位。这表明递减计数器需要在一个有限的时间窗口中被刷新。

图 3.6.1.1中,T[6:0]就是WWDG_CR的低七位,W[6:0]即是WWDG->;CFR的低七位。T[6:0]就是窗口看门狗的计数器,而W[6:0]则是窗口看门狗的上窗口,下窗口值是固定的(0X40)。当窗口看门狗的计数器在上窗口值之外被刷新,或者低于下窗口值都会产生复位。 上窗口值(W[6:0])是由用户自己设定的,根据实际要求来设计窗口值,但是一定要确保窗口值大于0X40,否则窗口就不存在了。 窗口看门狗的超时公式如下: Twwdg=(4096×2^WDGTB×(T[5:0]+1)) /Fpclk1; 其中: Twwdg:WWDG超时时间(单位为ms) Fpclk1:APB1的时钟频率(单位为Khz) WDGTB:WWDG的预分频系数 T[5:0]:窗口看门狗的计数器低6位 窗口看门狗寄存器介绍:

如何使用窗口看门狗: 1)使能WWDG时钟 2)设置WWDG_CFR和WWDG_CR两个寄存器 在时钟使能完后,我们设置WWDG的CFR和CR两个寄存器,对WWDG进行配置。包括使能窗口看门狗、开启中断、设置计数器的初始值、设置窗口值并设置分频数WDGTB 3)开启WWDG中断并分组 4)编写中断服务函数 软件例程: //---------------------------wdg.c----------------------- #include "wdg.h" #include "led.h" u8 wwdg_cnt=0x7f; //窗口看门狗计数器初值 void wwdg_init(u8 tr,u8 wr,u8 fprer) { RCC->;APB1ENR|=1;CFR|=fprer;CFR|=1;CFR&=0xff80; //窗口值清零 WWDG->;CFR|=wr; //设定窗口值 WWDG->;CR|=(wwdg_cnt|1;CR|=(cnt&0x7f); //喂狗值 } void WWDG_IRQHandler(void)

(整理)基于STM32的LCD操作

嵌入式系统》课程报告 基于 STM32的 LCD 操作 组长:曾昭智 组员:邓 宁、张小扬、牛洪澄 光电学院 电信 2班、3 班 2014.05.29 姓名 学院 班级 完成日期

目录 1、原理方案(功能框图介绍) (1) 2、电路连线及资源分配. (2) 3、所用主要器件或模块说明. (3) 4、程序流程图. (4) 5、调试心得. (5) 6、源代码 (6)

1.TFT-LCD 原理 1.1 TFT-LCD 简介 TFT-LCD即薄膜晶体管液晶显示器。其英文全称为:Thin Film Transistor-Liquid Crystal Display 。TFT-LCD与无源TN-LCD、STN-LCD 的简单 矩阵不同,它在液晶显示屏的每一个象素上都设置有一个薄膜晶体管(TFT),可有效地克服非选通时的串扰,使显示液晶屏的静态特性与扫描线数无关,因此大大提高了图像质量。TFT-LCD也被叫做真彩液晶显示器。 上一节介绍了OLED模块,这一节,我们给大家介绍ALIENTEK TFTLC模D 块,该模块有如下特点: 1,2.4 '/2.8 '两种大小的屏幕可选。 2,320×240的分辨率。 3,16位真彩显示。 4,自带触摸屏,可以用来作为控制输入。 5,通用的接口,除了ALIENTEK MiniSTM32开发板,该液晶模块还可以使用在优异特、STMSK、Y 红牛等开发板上。 本节,我们以 2.8 寸的ALIENTEKT FTLCD模块为例介绍,该模块采用的是显尚光电的DST2001PHT FTLCD,DST2001PH的控制器为ILI9320 ,采用26 万色的TFTLCD 屏,分辨率为320×240,采用16 位的80并口。 1.2 80 并口 ALIENTEK TFTLCD 模块采用80并口口方与外部链接,采用16位数据线(低了速度太慢,用彩色就没什么效果了)。该模块的80并口有如下一些信号线:CS:TFTLCD 片选信号。 WR:向TFTLCD 写入数据。 RD:从TFTLCD 读取数据。 D[15:0] :16位双向数据线。 RST:硬复位TFTLCD 。 RS:命令/数据标志(0,读写命令;1,读写数据)。 TFTLCD 模块的RST信号线和OLED 模块一样,也是直接接到STM32 的复位脚上,并 不由软件控制,这样可以省下来一个IO 口。另外我们还需要一个背光控制线来控制TFTLCD 的背光。所以,我们总共需要的IO 口数目为21 个。 1.3 ILI9320 模块的控制器为ILI9320 ,该控制器自带显存,其显存总大小为172820 (240*320*18/8 ),即18位模式(26万色)下的显存量。模块的16位数据线与显寸的对应关系为565 方式,如下图所示: 1.4 GRAM显示方向设置

STM32_IO口操作

1、不使用库函数的IO口操作 Systick 部分内容属于NVIC控制部分,一共有4个寄存器 SysTick_CTRL, 0xE000E010 -- 控制寄存器默认值:0x0000 0004 SysTick_LOAD, 0xE000E014 -- 重载寄存器默认值:0x0000 0000 SysTick_VAL, 0xE000E018 -- 当前值寄存器默认值:0x0000 0000 SysTick_CALIB, 0xE000E01C -- 校准值寄存器默认值:0x0002328 SysTick_CTRL 寄存器内有4个bit具有意义 第0位:ENABLE,Systick 使能位(0:关闭Systick功能;1:开启Systick功能) 第1位:TICKINT,Systick 中断使能位(0:关闭Systick中断;1:开启Systick中断) 第2位:CLKSOURCE,Systick时钟源选择(0:使用HCLK/8 作为Systick时钟;1:使用HCLK 作为系统时钟) 第16位:COUNTFLAG,Systick计数比较标志 IO口的位操作实现 该部分代码实现对STM32各个IO口的位操作,包括读入和输出。当然在这些函数调用之前,必须先进行IO口时钟的使能和IO口功能定义。此部分仅仅对IO口进行输入输出读取和控制。代码如下: #define BITBAND(addr,bitnum) ((addr & 0xF0000000)+0x2000000+((addr &0xFFFFF)<<5)+(bitnum<<2)) #define MEM_ADDR(addr) *((volatile unsigned long *)(addr)) #define BIT_ADDR(addr,bitnum) MEM_ADDR(BITBAND(addr,bitnum)) //IO口地址映射 #define GPIOA_ODR_Addr (GPIOA_BASE+12) //0x4001080C #define GPIOB_ODR_Addr (GPIOB_BASE+12) //0x40010C0C #define GPIOC_ODR_Addr (GPIOC_BASE+12) //0x4001100C #define GPIOD_ODR_Addr (GPIOD_BASE+12) //0x4001140C #define GPIOE_ODR_Addr (GPIOE_BASE+12) //0x4001180C #define GPIOF_ODR_Addr (GPIOF_BASE+12) //0x40011A0C #define GPIOG_ODR_Addr (GPIOG_BASE+12) //0x40011E0C #define GPIOA_IDR_Addr (GPIOA_BASE+8) //0x40010808 #define GPIOB_IDR_Addr (GPIOB_BASE+8) //0x40010C08 #define GPIOC_IDR_Addr (GPIOC_BASE+8) //0x40011008 #define GPIOD_IDR_Addr (GPIOD_BASE+8) //0x40011408 #define GPIOE_IDR_Addr (GPIOE_BASE+8) //0x40011808 #define GPIOF_IDR_Addr (GPIOF_BASE+8) //0x40011A08 55

STM32开发笔记WWDG和IWDG的用法

STM32 独立看门狗IWDG 与窗口看门狗WWDG 2010年05月03日星期一21:54 独立看门狗Iwdg——有独立时钟(内部低速时钟LSI---40KHz),所以不受系统硬件影响的系统故障探测器。主要用于监视硬件错误。 窗口看门狗wwdg——时钟与系统相同。如果系统时钟不走了,这个狗也就失去作用了,主要用于监视软件错误。 一,独立看门狗 看门狗定时时限= IWDG_SetReload()的值/ 看门狗时钟频率 看门狗时钟频率=LSI(内部低速时钟)的频率(40KHz)/ 分频数 1.STM32 独立看门狗IWDG的时限定为280微秒。这个时限可能会随着LSI(内部低速时钟)的频率漂移而产生微小的变化。 /* IWDG timeout equal to 280 ms (the timeout may varies due to LSI frequency dispersion) ------------------------------------------------------------- */ /* Enable write access to IWDG_PR and IWDG_RLR registers */ IWDG_WriteAccessCmd(IWDG_WriteAccess_Enable); /* IWDG counter clock: 40KHz(LSI) / 32 = 1.25 KHz */ IWDG_SetPrescaler(IWDG_Prescaler_32); /* Set counter reload value to 349 */ IWDG_SetReload(349); /*该参数允许取值范围为0 –0x0FFF * /* Reload IWDG counter */ IWDG_ReloadCounter(); /* Enable IWDG (the LSI oscillator will be enabled by hardware) */ IWDG_Enable(); 2.独立看门狗(IWDG)由专用的40kHz 的低速时钟为驱动;因此,即使主时钟发生故障它也仍然有效。窗口看门狗由从APB1 时钟分频后得到的时钟驱动,通过可配置的时间窗口来检测应用程序非正常的过迟或过早的行为。可通过 IWDG_SetPrescaler(IWDG_Prescaler_32); 对其时钟进行分频,4-256, 通过以下方式喂狗: /* Reload IWDG counter */ IWDG_ReloadCounter(); 3. 1.25KHz 即每周期为0.8ms 共计时350 个周期,即350*0.8ms=280ms 看门狗定时时限= IWDG_SetReload()的值/ 看门狗时钟频率 看门狗时钟频率=LSI(内部低速时钟)的频率(40KHz)/ 分频数 二,窗口看门狗 STM32F的窗口看门狗中有一个7位的递减计数器,它会在出现下述2种情况之一时产生看

STM32中使用GPIO的总结超强

STM32 GPIO使用 操作步骤: 使能GPIO对应的外设时钟 例如://使能GPIOA、GPIOB、GPIOC对应的外设时钟 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB| RCC_APB2Periph_GPIOC , ENABLE); 声明一个GPIO_InitStructure结构体 例如: GPIO_InitTypeDef GPIO_InitStructure; 选择待设置的GPIO管脚 例如:/* 选择待设置的GPIO 7、8、9管脚位,中间加“|”符号*/ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7 | GPIO_Pin_8 | GPIO_Pin_9; 4. 设置选中GPIO管脚的速率 例如:/* 设置选中GPIO管脚的速率为最高速率2MHz */ GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz; //最高速率2MHz GPIO5. 设置选中管脚的模式*/ 设置选中GPIO管脚的模式为开漏输出模式/* 例如://开漏输出模式GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD; GPIOX

中指定的参数初始化外设6. 根据GPIO_InitStructureGPIOC */ GPIO_InitStructure中指定的参数初始化外设根据例如:/* 1 / 16 GPIO_Init(GPIOC, &GPIO_InitStructure); 7.其他应用 例:将端口GPIOA的 10、15脚置1(高电平) GPIO_SetBits(GPIOA, GPIO_Pin_10 | GPIO_Pin_15); 例:将端口GPIOA的 10、15脚置0(低电平) GPIO_ResetBits(GPIOA, GPIO_Pin_10 | GPIO_Pin_15); GPIO寄存器: 寄存器描述 端口配置低寄存器CRL 端口配置高寄存器CRH 端口输入数据寄存器IDR 端口输出数据寄存器ODR 端口位设置BSRR /复位寄存器 端口位复位寄存器BRR 端口配置锁定寄存器LCKR 事件控制寄存器EVCR

STM32的寄存器操作

STM32的寄存器操作和C51的操作有很大的不同。 要操作STM32可以通过库函数操作,也可直接操作寄存器。 下面分析一下寄存器的操作,以控制PE4脚输出高低电平为例: 首先找到GPIOE的寄存器基地址,如下图:(STM32F4xx中文参考手册.pdf) 找到GPIOE的基地址为:0x4002 1000 我们要操作PE4脚,首先找到BSRR位操作寄存器,如下图 BSRR寄存器偏移地址为:0x18 由于我我们要操作PE4,即操作BSRR寄存器的第4位。 下面编写代码: 首先定义一个指向uint32_t型的指针,之后将该指针指向BSRR寄存器地址:

0x4002 1018 = 0x4002 1000 + 0x0000 00018 此时要操作BSRR寄存器,直接向*p赋值就可以了,如下图: 该代码即可实现PE4脚的高低电平输出。 假如不加延时,如下图: 系统也可正常运行,但在这两行处打断点调试,会发现无法进入,分析原因是两行代码中间无延时,实际运行时几乎可以忽略该代码的操作,所以编译器在编译时自动优化了,此时我们只需要在声明变量的时候为其指明__IO类型变量(volatile)即可,如下图: 上面的例子从最基本的寄存器分析操作STM32的,下面来分析下官方库函数是如何操作寄存器的。 首先定义GPIO寄存器组,通过结构体将寄存器组封包,如下图:

由于以上寄存器地址是连续的,所以可以分在一个结构体中 然后定义GPIOE寄存器组 这里的GPIOE_BASE为GPIOE寄存器的基地址:0x4002 1000 定义了GPIO_TypeDef类型指针GPIOE,并指向了GPIOE寄存器的基地址。此时我们要操作PE4脚状态只需要操作GPIOE->BSRR就可以了, 其它寄存器的操作参考上面的分析即可实现。

Stm32之寄存器列表

学习STM32,官方提供一个库,但如果刚入手的话,肯定连功能都不太清楚,所以用不太习觉得还是操作寄存器来的直接,所以就整理了STM32的大部分寄存器共大家参考。版权归 基本上都是103的,其中107的RCC,USB,和以太网等一些不太重要的没有,但大部分都有我只是把数据手册中的寄存器整理了一下方便大家看。如果有什么不对的,请通知我,也好联系方式:qq 526083029 小树 PWR电源相关寄存器 PWR_CR(电源控制寄存器) 31302928272625242322212019181716 保留 1514131211109876543210保留DBP PLS[2:0]PVDE CSBF CWUF PDDS LPDS 8位:DBP取消后备区域写保护。复位值为0。定义:0为禁止写入,1为允许写入。注:如果rtc时钟是HSE/128,必须保持为1 7-5位:PVD电源电压检测器的电压阀值。定义:000(2.2v),001(2.3v),010(2.4v),011(2.5v),100(2.6v),101(2.7v),110(2.8v),4位:PVDE电源电压检测器(PVD)使能。定义:0(禁止PVD),1(开启PVD) 3位:CSBF清除待机位(始终输出为0)定义:0(无功效),1(清除SBF待机位(写) 2位:CWUF清除唤醒位(始终输出为0)定义:0(无功效),1(2个系统时钟周期后清除WUF唤醒位(写) 1位:PDDS掉电深睡眠(与LPDS位协同操作)定义:0(当CPU进入深睡眠时进入停机模式,调压器状态由LPDS位控制),1(CPU进入深睡眠时进入待机模0位:LPDS深睡眠下的低功耗(PDDS=0时,与PDDS位协同操作)定义:0(在待机模式下电压调压器开启),1(在待机模式下电压调压器处于低功耗模式 PWR_CSR(电源控制/状态寄存器) 31302928272625242322212019181716 保留 1514131211109876543210保留EWUP保留PVDO SBF WUF 8位:EWUP使能WKUP引脚。定义:0(WKUP为通用IO),1(用于待机唤醒模式,WKUP引脚被强置为输入下拉的配置(WKUP引脚上的上升沿将系统从待机模 注:复位时清除这一位 2位:PVDO-PVD输出(当PVD被PVDE位使能后该位才有效)定义:0(VDD/VDDA高于PLS[2-0]选定的PVD阀值),1(VDD/VDDA低于PLS[2-0]选定的PVD阀值 注:在待机模式下PVD被停止,因此,待机模式后或复位后,直到设置PVDE位之前,该位为0 1位:SBF待机标志位(该位由硬件设置,并只能由POR/PDR(上电/掉电复位)或设置电源控制寄存器(PWR_CR)的CSBUF位清除)定义:0(不在待机 0位:WUF唤醒标志(该位由硬件设置,并只能由POR/PDR(上电/掉电复位)或设置电源控制寄存器(PWR_CR)的CWUF位清除) 定义:0(没有唤醒事件),1(在WKUP引脚上发生唤醒事件或出现RTC脑中事件) 注:当WKUP引脚已经是高电平时,在(通过设置EWUP位)使能WKUP引脚时,会检测到一个额外事件 BKP——DRx(x=1...10)(备份数据寄存器) 1514131211109876543210 15-0位:备份数据由用户来写数据。注:BKP——DRx寄存器不会被系统复位,电源复位,待机唤醒所复位 它可以由备份域复位来复位或(如果入侵检测引脚TAMPER功能被开启时)由浸入引脚事件复位 BKP_RTCCR(RTC时钟校准寄存器) 1514131211109876543210

使用BSRR和BRR寄存器直接操作STM32的IO端口

STM32的每个GPIO端口都有两个特别的寄存器,GPIOx_BSRR和GPIOx_BRR寄存器,通过这两个寄存器可以直接对对应的GPIOx端口置'1'或置'0'。 GPIOx_BSRR的高16位中每一位对应端口x的每个位,对高16位中的某位置'1'则端口x的对应位被清'0';寄存器中的位置'0',则对它对应的位不起作用。 GPIOx_BSRR的低16位中每一位也对应端口x的每个位,对低16位中的某位置'1'则它对应的端口位被置'1';寄存器中的位置'0',则对它对应的端口不起作用。 简单地说GPIOx_BSRR的高16位称作清除寄存器,而GPIOx_BSRR的低16位称作设置寄存器。另一个寄存器GPIOx_BRR只有低16位有效,与GPIOx_BSRR的高16位具有相同功能。 举个例子说明如何使用这两个寄存器和所体现的优势。例如GPIOE的16个IO都被设置成输出,而每次操作仅需要改变低8位的数据而保持高8位不变,假设新的8位数据在变量Newdata 中, 这个要求可以通过操作这两个寄存器实现,STM32的固件库中有两个函数GPIO_SetBits()和GPIO_ResetBits()使用了这两个寄存器操作端口。 上述要求可以这样实现: GPIO_SetBits(GPIOE, Newdata & 0xff); GPIO_ResetBits(GPIOE, (~Newdata & 0xff)); 也可以直接操作这两个寄存器: GPIOE->BSRR = Newdata & 0xff; GPIOE->BRR = ~Newdata & 0xff; 当然还可以一次完成对8位的操作: GPIOE->BSRR = (Newdata & 0xff) | (~Newdata & 0xff)<<16; 从最后这个操作可以看出使用BSRR寄存器,可以实现8个端口位的同时修改操作。 如果不是用BRR和BSRR寄存器,则上述要求就需要这样实现: GPIOE->ODR = GPIOE->ODR & 0xff00 | Newdata; 使用BRR和BSRR寄存器可以方便地快速地实现对端口某些特定位的操作,而不影响其它位的状态。

STM32寄存器操作举例

如何用寄存器的方法操作STM32 这个文章是摘自阿莫论坛,觉得写得很不错,就收藏下来了,整理成文档,希望更多的人能看到 既然我们要操作IO 口,当然就要看IO口相关的知识。打开STM3210x参考手册.pdf ,我的目的只是操作GPIO 所以我只需要将第五章看完就OK了。章节比较多,懒得看,根据一般的经验(楼主,你缺经验了吧?),不说多 就AVR 和PIC 而已。操作IO一般是两个步骤,第一,操作IO控制寄存器,设置IO为输出,第二就是送数据。 那么很明显,只可能是GPIOx_CRL GPIOx_CRH ,GPIOx_ODR 三个寄存器会有想要 仔细阅读这几个寄存器的介绍后知道,GPIOx_CRL 是控制PIN 0-7 的属性的,GPIOx_CRH 控制PIN 8-15,ODR寄存器 当然就是输出数据了,将数据送到这里就行了。 然后,这几个寄存器的地址是多少?首先看stm32f103ve.pdf 这个是官方的datasheet、,看第四章,Mmeory Mapping 为什么看这章?会英文都能猜到吧?,看PORTB 的地址是0x40010C00 - 0x40010FFF ,这个就是基地址了。基地址 加上偏移量就能找到具体的寄存器。 例如我需要操作GPIOB_CRL 的偏移为00H ,(看STM3210x参考手册.pdf)ODR 寄存器的偏移为0CH 那么很自然得出 GPIOB_CRL = 0x40010C00 GPIOB_ODR = 0x40010C0C 怎么验证我的结论正确?先看keil 给的头文件\Keil\ARM\INC\ST\STM32F10x\stm32f10x_map.h #define PERIPH_BASE ((u32)0x40000000) #define APB2PERIPH_BASE (PERIPH_BASE + 0x10000) #define GPIOB_BASE (APB2PERIPH_BASE + 0x0C00) 这样怎么算都能算出0x40010C00 出来吧??ODR 寄存器同理 为了点亮LED ,我需要将PB5 (也就是GPIOB5)设置为输出,并且ODR相应的位写入1 ,看资料得出MODE5 是 bit 20 21 控制的,CNF5 是bit 22,23 MODE5应该设置10(0x2) 选择2MHZ 输出,CNF5 选择00(0x0),通用推挽模式,于是将这个值写入(*volatile unsigned long)0x40010C00 = (2<<20) | (0<<22); // 为简单起见,不管其他位了

相关文档
最新文档