精华内容
下载资源
问答
  • 外部中断的一般配置步骤: 1.初始化IO口为输入。 GPIO_Init(); 2.开启IO口复用时钟。 RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE); 3.设置IO口与中断线的映射关系。 void GPIO_EXTILineConfig(); 4.初始化...

    外部中断的一般配置步骤:
    1.初始化IO口为输入。
    GPIO_Init();
    2.开启IO口复用时钟。
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);
    3.设置IO口与中断线的映射关系。
    void GPIO_EXTILineConfig();
    4.初始化线上中断,设置触发条件等。
    EXTI_Init();
    5.配置中断分组(NVIC),并使能中断。
    NVIC_Init();
    6.编写中断服务函数。
    EXTIx_IRQHandler();
    7.清除中断标志位
    EXTI_ClearITPendingBit();

    定时器配置:
    1.使能定时器时钟。
    RCC_APB1PeriphClockCmd();
    2.初始化定时器,配置ARR,PSC。
    TIM_TimeBaseInit();
    3.开启定时器中断,配置NVIC。
    void TIM_ITConfig();
    NVIC_Init();
    4.使能定时器。
    TIM_Cmd();
    5.编写中断服务函数。
    TIMx_IRQHandler();

    展开全文
  • STM32 外部中断使用方法总结

    千次阅读 2018-03-23 13:18:55
    STM32 中断分为外部中断定时器中断、串口中断。虽然名字不同,但是原理都是相同的,这一节我们将主要介绍一下外部中断以及中断函数的编写。按照如下步骤去编写函数配置函数即可完成对外部中断函数的配置。第一步...

    STM32 中断分为外部中断,定时器中断、串口中断。虽然名字不同,但是原理都是相同的,这一节我们将主要介绍一下外部中断以及中断函数的编写。

    按照如下步骤去编写函数和配置函数即可完成对外部中断函数的配置。

    第一步:配置GPIO,设置为中断模式。

    第二部:配置中断函数

                1、使能IO口复用功能,选择带有中断的引脚。

                2、设置外部中断结构体成员。

                3、设置中断优先级。

                4、配置中断服务函数。

    例子:按键触发的中断函数

    //GPIO 初始化
    void Init_LED(void)
    {
    GPIO_InitTypeDef GPIO_InitStructure;	//定义一个GPIO结构体变量
    
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC | RCC_APB2Periph_GPIOD | RCC_APB2Periph_GPIOE | RCC_APB2Periph_GPIOG, ENABLE);
    //使能各个端口时钟,
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_14|GPIO_Pin_13;	//板上LED编号 D2、D5
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOG, &GPIO_InitStructure);
    
    GPIO_Init(GPIOD, &GPIO_InitStructure);
    }



    中断函数编写
    void Init_EXTIX_TI(void)
    {
    
    EXTI_InitTypeDef EXTI_InitStructure;	//定义一个EXTI结构体变量
    NVIC_InitTypeDef NVIC_InitStructure;
    
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);	//使能IO复用功能,使用中断功能重要!!!
    
    /* 引脚选择 */
    GPIO_EXTILineConfig(GPIO_PortSourceGPIOC, GPIO_PinSource13);//配置端口C的13引脚为中断源	重要!! 板上标号INT2
    GPIO_EXTILineConfig(GPIO_PortSourceGPIOE, GPIO_PinSource0); //配置端口E的0引脚为中断源	重要!! 板上标号INT1
    
    
    /* 设置外部中断结构体的成员*/
    EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;	//中断模式为中断模式
    EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;	//下降沿触发
    EXTI_InitStructure.EXTI_Line = EXTI_Line0 | EXTI_Line13;
    EXTI_InitStructure.EXTI_LineCmd = ENABLE;	//使能中断线
    EXTI_Init(&EXTI_InitStructure);	//根据参数初始化中断寄存器
    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);	//设置中断优先级分组2
    
    NVIC_InitStructure.NVIC_IRQChannel = EXTI15_10_IRQn;	//设定中断源为PC13
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;	//中断占优先级为2
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;	//副优先级为0
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;	//使能中断
    NVIC_Init(&NVIC_InitStructure);	//根据参数初始化中断寄存器
    
    NVIC_InitStructure.NVIC_IRQChannel = EXTI0_IRQn;	//设定中断源为PE0
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;	//中断占优先级为1
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;	//副优先级为0
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;	//使能中断
    NVIC_Init(&NVIC_InitStructure);	//根据参数初始化中断寄存器
    
    }

    最后为配置中断服务函数(入口函数、中断处理函数)

    最后一步了,也是很重要的一步,配置中断服务函数,也有叫什么入口函数的。说白了,就是你想让你的这个中断做什么。

    /*************************************************************
    注意,中断服务程序虽然简单,但是在写入口函数的时候,注意函数名的写法,只有如下3种命名方式。
    (1)EXTI0_IRQHandler;EXTI Line 0
    EXTI1_IRQHandler;EXTI Line 1
    EXTI2_IRQHandler;EXTI Line 2
    EXTI3_IRQHandler;EXTI Line 3
    EXTI4_IRQHandler;EXTI Line 4
    (2)
    EXTI9_5_IRQHandler;EXTI Line 5-9
    (3)
    EXTI15_10_IRQHandler;EXTI Line 10-15

    只要是中断线5后的就不能像前四个那样命名,他们有自己的方式。
    ************************************************************/

    void EXTI15_10_IRQHandler(void) //pc13中断服务程序,也是中断子函数
    {
    //检测按键之前一般有个消抖延时,直接调用下面的延时函数即可
    
    if(EXTI_GetITStatus(EXTI_Line13)!= RESET) //判断是否发生中断,发生则中断标志置1
    {
    //	LED1=0;
    
    //	LED2=1;
    
    GPIO_ResetBits(GPIOG, GPIO_Pin_14); //GPIOG设置为低电平,
    GPIO_SetBits(GPIOD, GPIO_Pin_13); //GPIOD设置为高电平,其实这一部分也是可以写在主函数中的,在while那个死循环中。
    
    }
    
    EXTI_ClearITPendingBit(EXTI_Line13);	//利用库函数清除中断标志位,进入中断服务程序之后。首先就是清除标志位,	
    } //否则他会不响应中断,不进入中断函数
    这就是整个完整的外部中断处理函数,直接照葫芦画瓢就行。

    展开全文
  • C28x DSP内核总计有16个中断线,其中包括2个不可屏蔽中断(RESET和NMI)与...其余12个可屏蔽中断直接连接在外设中断扩展模块,供外部中断和处理器内部的外设单元使用。图2给出了F281O和F2812处理器的中断源和复用情况。
  • 定时器TIM)时钟源:stm32时钟系统框图(需要下载)外部中断得开启复用功能实验目的:定时1s让灯亮库:定时用到了stm3210x_tim.h库模版:工程模版+TIM3_IRQHandler模版 流程1.复制工程模版2.打开工程模版在app中...

    定时器TIM------->DMA
    (不用看功能直接忽略介绍)

    外部中断得开启复用功能

    定时器TIM)
    时钟源:stm32时钟系统框图(需要下载)
    外部中断得开启复用功能
    实验目的:定时1s让灯亮
    库:定时用到了stm3210x_tim.h库
    模版:工程模版+TIM3_IRQHandler模版

    流程
    1.复制工程模版
    2.打开工程模版在app中新建文件定时器
    3.新建time.h和time.c文件添加至app定时器中
    4.在time.h文件中写入声明voidtime_init
    (void),且修改#define _TIME_H
    5.在time.c文件中#include “time.h”,
    6.在app中添加time.c中文件
    7.在option中的c/c++中包含定时器路径
    8.由于使用定时器使用了stm32f10x_tim.h库,所以在存放所用库fwilb中添加stm32f10x_tim.h,并且在公共函数库public中添加#include "stm3210x_tim.h"
    9.开始在time.h中编写time_init()函数(查阅固件库中文手册)
    10.编写完毕后,在stmf10x_it.h文件中编写定时器中断函数void TIM3_IRQHandler(),没有声明需要在.h中进行声明
    11.编写主函数
    注意:
    1.我们用到了定时器,必须在此工程使用的头文件fwilb中添加此头文件
    而且得把这个头文件添加到公共头文件里面,不然会报错
    .\output\工程模板.axf: Error: L6218E: Undefined symbol TIM_TimeBaseInit (referred from time.o).
    2.每次编写中断函数的时候,必须先进行擦除操作,即 TIM_ClearITPendingBit(TIM3,TIM_IT_Update);

    以下是time_init()模版代码

     1 void time_init(void)
     2 {
     3     TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;  //定时结构体  
     4 
     5     NVIC_InitTypeDef NVIC_InitStructure;                 //中断结构体
     6 
     7     RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE);  //系统时钟,注意APB1和TIM3的关系
     8 
     9     TIM_ClearITPendingBit(TIM3,TIM_IT_Update);        //清除之前的中断数据,必须用,包括写中断函数的时候     
    10     TIM_TimeBaseInitStructure.TIM_Period = 2000;    
    11     TIM_TimeBaseInitStructure.TIM_Prescaler = 35999;  
    #计算定时时间=TIM_Period\72M\
    TIM_Prescaler+1
    12   TIM_TimeBaseInitStructure.TIM_ClockDivision = 0; //是否时钟分割 

    13   TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up; //计数模式
    14   TIM_TimeBaseInit(TIM3,&TIM_TimeBaseInitStructure);

    15  TIM_Cmd(TIM3,ENABLE); //使能
    16
    17  TIM_ITConfig(TIM3, TIM_IT_Update, ENABLE ); //设置中断参数TIM3
    18
    19
    20   NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1); //设置NVIC参数,注意groop_1

    21   NVIC_InitStructure.NVIC_IRQChannel=TIM3_IRQn; //全局中断设置

    22   NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=0; 配对groop_1

    23   NVIC_InitStructure.NVIC_IRQChannelSubPriority=1;

    24   NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //使能

    25   NVIC_Init(&NVIC_InitStructure);

    26 }

     

    打下划线的是根据自己需求而改的

    思路:定时1s的流水灯,需要使用定时器,所以使用tim.h库,通过配置time_init(计算定时时间=TIM_Period\72M\TIM_Prescaler+1)定时1s,编写中断函数void TIM3_IRQHandler()对灯进行控制

    可能对TIM3和APBx有疑问,在stm32时钟分配图中有介绍

     TIM1/8---->APB2    TIM2-7-------->APB1

    这也可以在库中可以找到

    stm32f10x.h  ,

    类似于结构体可以搜索InitStructure找到相关结构体写法,然后对xxxxxInitTypeDef使用go to definition直接找到结构体里面的参数

    转载于:https://www.cnblogs.com/bebox/p/7281198.html

    展开全文
  • 目前扩展串口的方法主要有以下方法, ①、采用串口扩展芯片实现,如ST16C550、... 一般的软件模拟扩展串口方法,使用1个I/O端口、1个INT外部中断和定时器,该方法扩展的串口有2个缺点,①、由于使用了INT外部中断,故
  • 目前扩展串口的方法主要有以下方法, ①、采用串口扩展芯片实现,如ST16C550、... 一般的软件模拟扩展串口方法,使用1个I/O端口、1个INT外部中断和定时器,该方法扩展的串口有2个缺点,①、由于使用了INT外部中断,故
  • MAXQ61H是一款低功耗、16位MAXQ?微控制器,设计用于通用遥控器、消费类电子白色...唤醒源包括外部中断、电源失效中断以及定时器中断。微控制器工作在1.70V至3.6V宽工作电压范围内。  引脚配置  关键特性  ●
  • MAXQ61H是一款低功耗、16位MAXQ?微控制器,设计用于通用遥控器、消费类电子白色...唤醒源包括外部中断、电源失效中断以及定时器中断。微控制器工作在1.70V至3.6V宽工作电压范围内。  引脚配置  关键特性  ●
  • ARM学习笔记基础STM32

    2019-10-15 14:45:09
    IO引脚的复用和映射 串口 串行通信方式 异步通信特点 串口配置方法 串口配置步骤(将PA9,PA10设置为串口1) 实验:串口通信 独立看门狗 实验:看门狗 窗口看门狗 窗口看门狗实验 通用定时器 实验:定时器...

    资料来源:正点原子STM32

    目录

    GPIO工作原理

    常用寄存器

    实验:跑马灯(库函数版本)

    实验步骤

    时钟

    IO引脚的复用和映射

    串口

    串行通信方式

    异步通信特点

    串口配置方法

    串口配置步骤(将PA9,PA10设置为串口1)

    实验:串口通信

    独立看门狗

    实验:看门狗

    窗口看门狗

    窗口看门狗实验

    通用定时器

    实验:定时器中断

    外部中断

    外部中断配置步骤

    ADC

    量程(模拟量输入范围)

    精度(分辨率resolution)

    转换速率(MSPS与conventor clock的不同)

    通道数

    转换模式

    ADC采样时间

    参数相关配置

    DMA

    请求映射

    流配置过程

    DMA中断

    库函数

    多重ADC

    三重ADC转换原理

    DMA模式请求

    三重ADC采样单通道信号ADC与DMA配置


    GPIO工作原理

    一个stm35包括7组IO,一组IO有16个IO口,一组IO口下面有10个寄存器用于配置这16个IO口的状
    态。 
    如果一个IO口需要两位寄存器控制,则一组IO口由32位的IO口控制。 
    如果一个IO口需要一位寄存器控制,则一组IO口由32位的IO口控制,其中只用到了低16位,高16
    位保留。
    GPIO工作方式: 
    4种输入模式: 
    输入浮空 
    输入上拉 
    输入下拉 
    模拟输入 
    4种输出模式: 
    开漏输出(带上拉或者下拉) 
    开漏复用功能(带上拉或者下拉) 
    推挽式输出(带上拉或者下拉) 
    推挽式复用功能(带上拉或者下拉)
    4种最大输出速度: 
    ­2MHZ 
    ­25MHz 
    ­50MHz 
    ­100MHz

    常用寄存器

    每组IO口都拥有以下常用寄存器: 
    一个端口模式寄存器(GPIOx_MODER) 
    一个端口输出类型寄存器(GPIOx_OTYPER) 
    一个端口输出速度寄存器(GPIOx_OSPEEDR) 
    一个端口上拉下拉寄存器(GPIOx_PUPDR) 
    一个端口输入数据寄存器(GPIOx_IDR) 
    一个端口输出数据寄存器(GPIOx_ODR) 
    一个端口置位/复位寄存器(GPIOx_BSRR) 
    一个端口配置锁存寄存器(GPIOx_LCKR) 
    两个复位功能寄存器(低位GPIOx_AFRL & GPIOx_AFRH)

    实验:跑马灯(库函数版本)

    以下是几个寄存器的库函数参数: 
    GPIO_InitTypeDef GPIO_InitStructure;
    MODER寄存器 
    端口模式控制寄存器,用于控制GPIOx的工作模式,每2位控制一个IO口,代码中属性为:
    GPIO_InitStructure.GPIO_Mode

    typedef enum
    {
    GPIO_Mode_IN = 0x00, /*!< GPIO Input Mode 输入模式*/
    GPIO_Mode_OUT = 0x01, /*!< GPIO Output Mode 输出模式*/
    GPIO_Mode_AF = 0x02, /*!< GPIO Alternate function Mode 复用功能模式*/
    GPIO_Mode_AN = 0x03 /*!< GPIO Analog Mode 模拟模式*/
    }GPIOMode_TypeDef;

    OTYPER寄存器 
    用于控制GPIOx的输出类型,每1位控制一个IO口,该寄存器仅用于输出模式,输入模式下不
    起作用,代码属性:GPIO_InitStructure.GPIO_OType

    typedef enum
    {
    GPIO_OType_PP = 0x00,/*输出推挽(复位状态)*/
    GPIO_OType_OD = 0x01/*输出开漏*/
    }GPIOOType_TypeDef;

    OSPEEDR寄存器 
    用于控制GPIOx的输出速度,每2位控制一个IO口,仅用于输出模式,代码中属性为:
    GPIO_InitStructure.GPIO_Speed

    #define GPIO_Speed_2MHz GPIO_Low_Speed
    #define GPIO_Speed_25MHz GPIO_Medium_Speed
    #define GPIO_Speed_50MHz GPIO_Fast_Speed
    #define GPIO_Speed_100MHz GPIO_High_Speed

    PUPDR寄存器 
    控制GPIOx的上拉/下拉,每2位控制一个IO口,代码属性位:GPIO_InitStructure.GPIO_PuPd

    typedef enum
    {
    GPIO_PuPd_NOPULL = 0x00, /*无上拉或下拉*/
    GPIO_PuPd_UP = 0x01, /*上拉*/
    GPIO_PuPd_DOWN = 0x02 /*下拉*/
    }GPIOPuPd_TypeDef;

    实验步骤

    1.模板文件夹新建HARDWARE文件,并且打开程序建立led.h,led.c保存。引入.h文件,添加头文件
    路径。 
    2.在头文件中定义初始化函数.

    #ifndef __LED_H
    #define __LED_H
    void LED_Init(void);
    #endif

    3.再.c重实现初始化函数

    #include "led.h"
    #include "stm32f4xx.h"
    void LED_Init(void)
    {
    GPIO_InitTypeDef GPIO_InitStructure;//设置一个结构体对GPIO各个状态的设置
    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOF,ENABLE);//设置GPIOF为始能状态
    //F9
    GPIO_InitStructure.GPIO_Pin=GPIO_Pin_9;//设置GPIOF9
    GPIO_InitStructure.GPIO_Mode=GPIO_Mode_OUT;//普通输出模式
    GPIO_InitStructure.GPIO_OType=GPIO_OType_PP;//推挽输出
    GPIO_InitStructure.GPIO_PuPd=GPIO_PuPd_UP;//上拉
    GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;//50MHZ
    GPIO_Init(GPIOF,&GPIO_InitStructure);//库函数中的初始化函数
    GPIO_SetBits(GPIOF,GPIO_Pin_9);//设置为1
    //F10
    GPIO_InitStructure.GPIO_Pin=GPIO_Pin_10;
    GPIO_InitStructure.GPIO_Mode=GPIO_Mode_OUT;
    GPIO_InitStructure.GPIO_OType=GPIO_OType_PP;
    GPIO_InitStructure.GPIO_PuPd=GPIO_PuPd_UP;
    GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
    GPIO_Init(GPIOF,&GPIO_InitStructure);
    GPIO_SetBits(GPIOF,GPIO_Pin_10);
    }

    4.main函数

    #include "stm32f4xx.h"
    #include "led.h"
    #include "delay.h"
    int main(void)
    {
    delay_init(168);
    LED_Init();
    while(1){
    GPIO_SetBits(GPIOF,GPIO_Pin_9);
    GPIO_SetBits(GPIOF,GPIO_Pin_10);
    delay_ms(500);
    GPIO_ResetBits(GPIOF,GPIO_Pin_9);
    GPIO_ResetBits(GPIOF,GPIO_Pin_10);
    delay_ms(500);
    }
    }

    时钟

    同一个电路,时钟越快功耗越大,同时抗电磁干扰能力也会越弱,可以理解为时钟就是执行命令的
    时间,始终越快,执行一条命令时间越短。时钟图:

    MCO1和MCO2是两个引脚用于输出芯片中的时钟,最大频率不超过100M
    CSS:时钟安全单元,如果系统时钟的输入HSE外部晶振出了问题,则CSS会将系统时钟切换
    到HSI时钟源 
    STM32 中有5个时钟源,HSI,HSE,LSI,LSE,PLL。 
    ①、LSI 是低速内部时钟,RC 振荡器,频率为 32kHz 左右。供独立看门狗和自动唤醒单元使
    用。 
    ②、LSE 是低速外部时钟,接频率为 32.768kHz 的石英晶体。这个主要是 RTC 的时钟源。 
    ③、HSE 是高速外部时钟,可接石英/陶瓷谐振器,或者接外部时钟源,频率范围为
    4MHz~26MHz。 
    我们的开发板接的是 8M 的晶振。HSE 也可以直接做为系统时钟或者 PLL 输入。 
    ④、HSI 是高速内部时钟,RC 振荡器,频率为 16MHz。可以直接作为系统时钟或者用作 PLL 
    输入。 
    ⑤、PLL 为锁相环倍频输出。STM32F4 有两个 PLL: 
    1) 主 PLL(PLL)由 HSE 或者 HSI 提供时钟信号,并具有两个不同的输出时钟。 
    第一个输出 PLLP 用于生成高速的系统时钟(最高 168MHz) 
    第二个输出 PLLQ 用于生成 USB OTG FS 的时钟(48MHz),随机数发生器的时钟和 SDIO 
    时钟。 
    2)专用 PLL(PLLI2S)用于生成精确时钟,从而在 I2S 接口实现高品质音频性能。
    主 PLL 时钟的时钟源要先经过一个分频系数为 M 的分频器,然后经过 
    倍频系数为 N 的倍频器出来之后的时候还需要经过一个分频系数为 P(第一个输出 PLLP)或 
    者 Q(第二个输出 PLLQ)的分频器分频之后,最后才生成最终的主 PLL 时钟。 
    例如我们的外部晶振选择 8MHz。同时我们设置相应的分频器 M=8,倍频器倍频系数 N=336, 
    分频器分频系数 P=2,那么主 PLL 生成的第一个输出高速时钟 PLLP 为: 
    PLL=8MHz * N/ (M*P)=8MHz* 336 /(8*2) = 168MHz
    系统初始化或者复位时,调用 SystemInit 函数对相关时钟进行默认配置,如果我们需要修改某些时
    钟源配置,我们则再RCC相关寄存器中配置。 
    STM32F4 的外设在使用之前,必须对时钟进行使能,如果没有使能时钟,那么外设是无法正常工
    作的。下面是外设始能相关函数:

    void RCC_AHB1PeriphClockCmd(uint32_t RCC_AHB1Periph, FunctionalState NewS
    tate);
    void RCC_AHB2PeriphClockCmd(uint32_t RCC_AHB2Periph, FunctionalState NewS
    tate);
    void RCC_AHB3PeriphClockCmd(uint32_t RCC_AHB3Periph, FunctionalState NewS
    tate);
    void RCC_APB1PeriphClockCmd(uint32_t RCC_APB1Periph, FunctionalState NewS
    tate);
    void RCC_APB2PeriphClockCmd(uint32_t RCC_APB2Periph, FunctionalState NewS
    tate);

    这里主要有5个外设始能函数,5个函数分别代表5个总线下面挂载的外设时钟,分别是AHB1 总
    线,AHB2 总线,AHB3 总线,APB1 总线以及 APB2 总线。要使能某个外设,调用对应的总线外
    设时钟使能函数即可。
    修改系统时钟: 
    在system_stm32f4xx.c中,代码721行设置HSE为系统时钟输入源,在316行设置各个分频系
    数,默认输出是168M的系统时钟
    初始化后的时钟: 
    SYSCLK(系统时钟) =168MHz 
    AHB总线时钟(HCLK=SYSCLK) =168MHz 
    APB1总线时钟(PCLK1=SYSCLK/4) =42MHz 
    APB2总线时钟(PCLK2=SYSCLK/2) =84MHz 
    PLL主时钟 =168MHz

    IO引脚的复用和映射

    STM32F4系列微控制器IO引脚通过一个复用器连接到内置外设或模块。该复用器一次只允许一个
    外设的复用功能(AF)连接到对应的IO口。这样可以确保共用同一个IO引脚的外设之间不会发生冲
    突。 
    每个IO引脚都有一个复用器,该复用器采用16路复用功能输入(AF0到AF15),可通过
    GPIOx_AFRL(针对引脚0­7)和GPIOx_AFRH(针对引脚8­15)寄存器对这些输入进行配置,每四
    位控制一路复用。 
    相当于每个IO口的引脚都有一个复用器,而这个复用器对每个IO口的功能进行配置。比如说有一个
    IO口PA2,他的一个复用器如图: 

    因为是引脚2,所以用寄存器AFPL进行配置,AFPL配置该引脚的复用器选择哪一个AF,则选定了
    该IO口的功能。
    接下来看AFRL的示意图:

    AFRL是一个32位寄存器,对于每一组IO口,一共16位IO,AFRL控制一个IO口的低8位,AFRH控
    制一组IO口的高8位,比如我们要控制GPIOA2引脚的复用功能则调用GPIOA 这组IO的寄存器
    AFRL,如上图,需要修改AFRL2的值来控制PA2 IO口,如果我们需要他的串口1功能,由图可以看
    出USART1接连到复用器的AF7,所以我们需要根据图选择AF7,就是把AFRL2设置为0111。
    接下来以PA9,PA10配置为串口1为例。 
    ①GPIO端口时钟使能。 
    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA,ENABLE);
    ②复用外设时钟使能。 
    比如你要将端口PA9,PA10复用为串口,所以要使能串口时钟。 
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);
    ③端口模式配置为复用功能。 GPIO_Init()函数。 
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;//复用功能 
    ④配置GPIOx_AFRL或者GPIOx_AFRH寄存器,将IO连接 
    到所需的AFx。
    /PA9连接AF7,复用为USART1_TX /
    GPIO_PinAFConfig(GPIOA,GPIO_PinSource9,GPIO_AF_USART1);
    /* PA10连接AF7,复用为USART1_RX*/ 
    GPIO_PinAFConfig(GPIOA,GPIO_PinSource10,GPIO_AF_USART1);

    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA,ENABLE); //使能GPIOA时钟 ①
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);//使能USART1时钟 ②
    //USART1端口配置③
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9 | GPIO_Pin_10; //GPIOA9与GPIOA10
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;//复用功能
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //速度50MHz
    GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; //推挽复用输出
    GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; //上拉
    GPIO_Init(GPIOA,&GPIO_InitStructure); //初始化PA9,PA10
    //串口1对应引脚复用映射 ④
    GPIO_PinAFConfig(GPIOA,GPIO_PinSource9,GPIO_AF_USART1); //GPIOA9复用为USAR
    T1
    GPIO_PinAFConfig(GPIOA,GPIO_PinSource10,GPIO_AF_USART1); //GPIOA10复用为US
    ART1

    串口

    串行通信方式

    按照数据传送方向,分为: 
    单工: 
    数据传输只支持数据在一个方向上传输 
    半双工: 
    允许数据在两个方向上传输,但是,在某一时刻,只允许数 
    据在一个方向上传输,它实际上是一种切换方向的单工通信; 
    全双工: 
    允许数据同时在两个方向上传输,因此,全双工通信是两个 
    单工通信方式的结合,它要求发送设备和接收设备都有独立 
    的接收和发送能力。

    按照时钟分类 
    同步通信:带时钟同步信号传输。(由时钟控制) 
    ­SPI,IIC通信接口 
    异步通信:不带时钟同步信号。(有一个约定) 
    ­UART(通用异步收发器),单总线
    常见串行通信接口

    stm32中的UART串口引脚:

    异步通信特点

    异步传输需要定义的参数: 
    起始位 
    数据位(8位或者9位) 
    奇偶校验位(第9位) 
    停止位(1,15,2位) 
    波特率设置

    奇偶校验的意思:比如数据位8位有偶数个1,进行偶校验,则第九位填0,若奇校验,则补1.

    串口配置方法

    相关寄存器: 
    USART_SR状态寄存器 
    USART_DR数据寄存器 
    USART_BRR波特率寄存器
    串口初始化方法: 
    void USART_Init(USART_TypeDef* USARTx, USART_InitTypeDef* USART_InitStruct); 
    第一个参数是串口几,第二个是一个结构体,结构体参数: 
    结构体就是一种约定

    typedef struct
    {
    uint32_t USART_BaudRate;//波特率
    uint16_t USART_WordLength; //字长,8还是9位
    uint16_t USART_StopBits; //停止位
    uint16_t USART_Parity; //奇偶校验
    uint16_t USART_Mode; //始能发送,接收选择
    uint16_t USART_HardwareFlowControl; //硬件流控制
    } USART_InitTypeDef;

    串口配置步骤(将PA9,PA10设置为串口1)

    1.同样打开模板,清空main函数,始能串口时钟与GPIO时钟

    RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);//串口时钟,始能AHB2,r
    cc.h
    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA,ENABLE);//GPIO时钟,始能GPI
    OA,IO口用AHB1

    2.引脚复用映射:

    GPIO_PinAFConfig(GPIOA,GPIO_PinSource9,GPIO_AF_USART1);//PA9映射到串口1
    GPIO_PinAFConfig(GPIOA,GPIO_PinSource10,GPIO_AF_USART1);//PA10映射到串
    口1

    3.对IO口进行初始化

    GPIO_InitTypeDef GPIO_InitStructure;
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9 | GPIO_Pin_10;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;//设置为复用模式
    GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
    GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
    GPIO_Init(GPIOA, &GPIO_InitStructure);

    4.对串口1进行初始化,并且始能:

    USART_InitTypeDef USART_InitStructure;
    USART_InitStructure.USART_BaudRate=115200;//约定波特率位115200
    USART_InitStructure.USART_HardwareFlowControl=USART_HardwareFlowControl_N
    one;//不需要硬件流控制
    USART_InitStructure.USART_Mode=USART_Mode_Rx |USART_Mode_Tx;//始能发送也接收
    USART_InitStructure.USART_Parity=USART_Parity_No;//不使用奇偶校验
    USART_InitStructure.USART_StopBits=USART_StopBits_1;//停止位设置为1
    USART_InitStructure.USART_WordLength=USART_WordLength_8b;//字长设置为8位字
    长。因为没有奇偶校验。
    USART_Init(USART1,&USART_InitStructure);//usart.h
    USART_Cmd(USART1,ENABLE);

    5.中断始能设置

    USART_ITConfig(USART1,USART_IT_RXNE,ENABLE);//始能中断

    第一个参数是中断发生的串口号,第二个是中断类型,RXNE为接受非空,所以这里只要接收到数
    据就产生中断
    6.中断分组设置: 
    在main函数中对中断进行分组:

    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//2位抢占优先级,2位相应优先级

    7.中断初始化设置

    NVIC_InitStructure.NVIC_IRQChannel=USART1_IRQn;;//设置通道为串口1
    NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;//始能通道
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=1;//设置抢占优先级
    NVIC_InitStructure.NVIC_IRQChannelSubPriority=1;//设置相应优先级
    NVIC_Init(&NVIC_InitStructure);//misc.h

    8.编写中断服务函数:

    void USART1_IRQHandler(void)
    {
    u8 res;
    if(USART_GetITStatus(USART1,USART_IT_RXNE))//判断前面始能的中断是否发生,
    如果发生则调用串口接收函数
    {
    res=USART_ReceiveData(USART1);//接收串口1的函数
    USART_SendData(USART1,res);//发数
    }
    }

    9.在main函数中完善

    int main(void)
    {
    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//2位抢占优先级,2位相应优
    先级
    My_USART1_Init();
    while(1);//等待中断的发生
    }

    实验:串口通信

    本次实验前面步骤与上一个串口讲解相同,前面省略,列出了步骤和代码:
    1.串口时钟使能:RCC_APBxPeriphClockCmd(); 
    GPIO时钟使能:RCC_AHB1PeriphClockCmd(); 
    ② 引脚复用映射: 
    GPIO_PinAFConfig();
    ③GPIO端口模式设置:GPIO_Init(); 模式设置为GPIO_Mode_AF 
    ④串口参数初始化:USART_Init(); 
    ⑤使能串口:USART_Cmd(); 
    ⑥开启中断并且初始化NVIC(如果需要开启中断才需要这个步骤) 
    NVIC_Init();
    USART_ITConfig(); 
    ⑦编写中断处理函数:USARTx_IRQHandler();

    //
    //加入以下代码,支持printf函数,而不需要选择use MicroLIB
    #if 1
    #pragma import(__use_no_semihosting)
    //标准库需要的支持函数
    struct __FILE
    {
    int handle;
    };
    FILE __stdout;
    //定义_sys_exit()以避免使用半主机模式
    _sys_exit(int x)
    {
    x = x;
    }
    //重定义fputc函数
    int fputc(int ch, FILE *f)
    {
    while((USART1->SR&0X40)==0);//循环发送,直到发送完毕
    USART1->DR = (u8) ch;
    return ch;
    }
    #endif
    #if EN_USART1_RX //如果使能了接收
    //串口1中断服务程序
    //注意,读取USARTx->SR能避免莫名其妙的错误
    u8 USART_RX_BUF[USART_REC_LEN]; //接收缓冲,最大USART_REC_LEN个字节.
    //接收状态
    //bit15, 接收完成标志
    //bit14, 接收到0x0d
    //bit13~0, 接收到的有效字节数目
    u16 USART_RX_STA=0; //接收状态标记
    //初始化IO 串口1
    //bound:波特率
    void uart_init(u32 bound){
    //GPIO端口设置
    GPIO_InitTypeDef GPIO_InitStructure;
    USART_InitTypeDef USART_InitStructure;
    NVIC_InitTypeDef NVIC_InitStructure;
    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA,ENABLE); //使能GPIOA时钟
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);//使能USART1时钟
    //串口1对应引脚复用映射
    GPIO_PinAFConfig(GPIOA,GPIO_PinSource9,GPIO_AF_USART1); //GPIOA9复用为
    USART1
    GPIO_PinAFConfig(GPIOA,GPIO_PinSource10,GPIO_AF_USART1); //GPIOA10复用
    为USART1
    //USART1端口配置
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9 | GPIO_Pin_10; //GPIOA9与GPIOA1
    0
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;//复用功能
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //速度50MHz
    GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; //推挽复用输出
    GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; //上拉
    GPIO_Init(GPIOA,&GPIO_InitStructure); //初始化PA9,PA10
    //USART1 初始化设置
    USART_InitStructure.USART_BaudRate = bound;//波特率设置
    USART_InitStructure.USART_WordLength = USART_WordLength_8b;//字长为8位
    数据格式
    USART_InitStructure.USART_StopBits = USART_StopBits_1;//一个停止位
    USART_InitStructure.USART_Parity = USART_Parity_No;//无奇偶校验位
    USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowCon
    trol_None;//无硬件数据流控制
    USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; //收发
    模式
    USART_Init(USART1, &USART_InitStructure); //初始化串口1
    USART_Cmd(USART1, ENABLE); //使能串口1
    //USART_ClearFlag(USART1, USART_FLAG_TC);
    #if EN_USART1_RX //该处是宏定义,1.
    USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);//开启相关中断
    //Usart1 NVIC 配置
    NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;//串口1中断通道
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=3;//抢占优先级3
    NVIC_InitStructure.NVIC_IRQChannelSubPriority =3; //子优先级3
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道使能
    NVIC_Init(&NVIC_InitStructure); //根据指定的参数初始化VIC寄存器、
    #endif
    }
    //下面中断处理函数完成的任务是来一个数据,触发一次中断,然后将来的数据存在USART_RX_BU
    F[USART_RX_STA&0X3FFF]数组中,存满USART_REC_LEN个后又重新存储。
    void USART1_IRQHandler(void) //串口1中断服务程序
    {
    u8 Res;
    #if SYSTEM_SUPPORT_OS //如果SYSTEM_SUPPORT_OS为真,则需要支持OS.
    OSIntEnter();
    #endif
    if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET) //接收中断(接收到
    的数据必须是0x0d 0x0a结尾)
    {
    Res =USART_ReceiveData(USART1);//(USART1->DR); //读取接收到的数据
    if((USART_RX_STA&0x8000)==0)//接收未完成?SART_RX_STA16位,接收状态标
    记,相当于检验最高位是否为0,最高位为0,if成立,没有接收完成。
    {
    //USART_RX_STA是一个16位的接收状态标记,本次接收的数据存在Res里,
    if(USART_RX_STA&0x4000)//检验高第二位是否为1,如果为1,则表示接收到
    了0X0d,进入if语句,否则进入else,//最后才会进入这个if
    {
    if(Res!=0x0a)USART_RX_STA=0;//接收错误,重新开始
    else USART_RX_STA|=0x8000; //接收完成了 ,将最高位标记为1
    }
    else //还没收到0X0D,
    {
    if(Res==0x0d)USART_RX_STA|=0x4000;///再进入第二个if
    else//程序首先进入本个第一个else
    {
    USART_RX_BUF[USART_RX_STA&0X3FFF]=Res ;//0011 1111 11
    11 1111
    USART_RX_STA++;
    if(USART_RX_STA>(USART_REC_LEN-1))
    USART_RX_STA=0;//接收数据错误,重新开始接收
    }
    }
    }
    }
    #if SYSTEM_SUPPORT_OS //如果SYSTEM_SUPPORT_OS为真,则需要支持OS.
    OSIntExit();
    #endif
    }
    #endif

    上述代码的头文件中添加了宏定义:

    #define USART_REC_LEN 200 //定义最大接收字节数 200
    #define EN_USART1_RX 1 //使能(1)/禁止(0)串口1接收
    extern u8 USART_RX_BUF[USART_REC_LEN]; //接收缓冲,最大USART_REC_LEN个字节.末
    字节为换行符
    extern u16 USART_RX_STA; //接收状态标记
    //如果想串口中断接收,请不要注释以下宏定义
    void uart_init(u32 bound);

    主函数实现了检测最高位,如果检测到最高位为1,则发送完成,然后将接收到的数据发送回去:

    #include "sys.h"
    #include "delay.h"
    #include "usart.h"
    #include "led.h"
    #include "beep.h"
    #include "key.h"
    //ALIENTEK 探索者STM32F407开发板 实验4
    //串口通信实验 -库函数版本
    //技术支持:www.openedv.com
    //淘宝店铺:http://eboard.taobao.com
    //广州市星翼电子科技有限公司
    //作者:正点原子 @ALIENTEK
    int main(void)
    {
    u8 t;
    u8 len;
    u16 times=0;
    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//设置系统中断优先级分组2
    delay_init(168); //延时初始化
    uart_init(115200); //串口初始化波特率为115200
    LED_Init(); //初始化与LED连接的硬件接口
    while(1)
    {
    if(USART_RX_STA&0x8000)//不停的判断最高位接收完成标志是否是1
    {
    len=USART_RX_STA&0x3fff;//得到此次接收到的数据长度
    printf("\r\n您发送的消息为:\r\n");
    for(t=0;t<len;t++)
    {
    USART_SendData(USART1, USART_RX_BUF[t]); //向串口1
    发送数据
    while(USART_GetFlagStatus(USART1,USART_FLAG_TC)!=SET);//等
    待发送结束,发送结束后,USART_FLAG_TC为1,不等于1时,发送未结束,一直在循环里等到发送
    结束标志位置1
    }
    printf("\r\n\r\n");//插入换行
    USART_RX_STA=0;
    }else
    {
    times++;
    if(times%5000==0)
    {
    printf("\r\nALIENTEK 探索者STM32F407开发板 串口实验\r\n");
    printf("正点原子@ALIENTEK\r\n\r\n\r\n");
    }
    if(times%200==0)printf("请输入数据,以回车键结束\r\n");
    if(times%30==0)LED0=!LED0;//闪烁LED,提示系统正在运行.
    delay_ms(10);
    }
    }
    }

    独立看门狗

     

    出于对单片机运行状态进行实时监测的考虑,便产生了一种专门用于监测单片机程序运行状态的模
    块或者芯片,俗称“看门狗”(watchdog) 。 
    在启动正常运行的时候,系统不能复位。 
    在系统跑飞(程序异常执行)的情况,系统复位,程序重新执行。 
    STM32有两个看门狗:
    独立看门狗(IWDG)由专用的低速时钟(LSI=32K)驱动,即使主时钟发生 故障它仍有效。独
    立看门狗适合应用于需要看门狗作为一个在主程序之外 能够完全独立工作,并且对时间精度要
    求低的场合。
    窗口看门狗由从APB1时钟分频后得到时钟驱动。通过可配置的时间窗口来检测应用程序非正
    常的过迟或过早操作。 窗口看门狗最适合那些要求看门狗在精确计时窗口起作用的程序。
    功能: 
    在键值寄存器(IWDG_KR)中写入0xCCCC,开始启用独立看门狗。此时计数器开始从其复位值
    0xFFF递减,当计数器值计数到尾值0x000时会产生一个复位信号(IWDG_RESET)。 
    无论何时,只要在键值寄存器IWDG_KR中写入0xAAAA(通常说的喂狗), 自动重装载寄存器
    IWDG_RLR的值就会重新加载到计数器,从而避免看门狗复位。 
    如果程序异常,就无法正常喂狗,从而系统复位。

    首先在IWDG_KR中写入0xCCCC,开启看门狗,LSI提供一个时钟,开启看门狗后,12位递减计数
    器中的数据开始递减,直到减到0,系统复位,如果在递减的过程中(比如递减到50),在IWDG_KR
    中输入0xAAAA,则12位的重装寄存器会把重载寄存器IWDG_RLR中的数据装配到递减计数器中,
    此时就从新装载进来的数值递减。如果这中途又喂狗了,又从IWDG_RL重装的计数值再一次递
    减,不断循环。

     

    实验:看门狗

    库函数: 
    void IWDG_WriteAccessCmd(uint16_t IWDG_WriteAccess);//取消写保护:0x5555使能 
    void IWDG_SetPrescaler(uint8_t IWDG_Prescaler);//设置预分频系数:写PR 
    void IWDG_SetReload(uint16_t Reload);//设置重装载值:写RLR 
    void IWDG_ReloadCounter(void);//喂狗:写0xAAAA到KR 
    void IWDG_Enable(void);//使能看门狗:写0xCCCC到KR 
    FlagStatus IWDG_GetFlagStatus(uint16_t IWDG_FLAG);//状态:重装载/预分频 更新
    溢出时间计算

     

    操作步骤: 
    1.取消寄存器写保护: 
    IWDG_WriteAccessCmd(); 
    ② 设置独立看门狗的预分频系数,确定时钟: 
    IWDG_SetPrescaler(); 
    ③ 设置看门狗重装载值,确定溢出时间: 
    IWDG_SetReload(); 
    ④ 使能看门狗 
    IWDG_Enable(); 
    ⑤ 应用程序喂狗: 
    IWDG_ReloadCounter();
    溢出时间计算: 
    Tout=((4×2^prer) ×rlr) /32 (M4)
    具体步骤: 
    1.本节利用案件实验3为基础,添加iwdg.c与iwdg.h文件,再.h文件中声明初始化函数:

    #ifndef __WDG_H
    #define __WDG_H
    #include "sys.h"
    void IWDG_Init(u8 prer,u16 rlr);//prer为分频系数,rlr为重装载值
    #endif

     

    2.添加看门狗固件库,在工程文件FWLIB上右键,添加,选取工程目录FWLIB中的src中的stm32法 
    xx_iwdg.c,添加进工程,编译添加的文件 
    3.在iwdg.c中编写Init函数

    #include "iwdg.h"
    void IWDG_Init(u8 prer,u16 rlr)
    {
    IWDG_WriteAccessCmd(IWDG_WriteAccess_Enable);//取消写保护
    IWDG_SetPrescaler(prer);//编写预分频系数
    IWDG_SetReload(rlr);//设置重装载值
    void IWDG_ReloadCounter(void);//喂狗,将0XAAAA加载到KR寄存器,那么系统就会
    喂狗
    IWDG_Enable();//看门狗始能
    }

    4.编写main函数

    #include "sys.h"
    #include "delay.h"
    #include "usart.h"
    #include "led.h"
    #include "beep.h"
    #include "key.h"
    #include "iwdg.h"
    int main(void)
    {
    u8 key; //保存键值
    delay_init(168); //初始化延时函数
    LED_Init(); //初始化LED端口 ,此时将LED灯电平拉高,灯灭
    BEEP_Init(); //初始化蜂鸣器端口
    KEY_Init(); //初始化与按键连接的硬件接口
    delay_ms(500); //为了看到复位的现象
    LED0=0; //先点亮红灯
    IWDG_Init(4,1000);//这里的4是16进制的,2s
    while(1)
    {
    if(KEY_Scan(0)==WKUP_PRES)
    {
    IWDG_ReloadCounter();
    }
    }
    }

    这里对main函数进行解释,首先看门狗的功能是在开启看门狗后(看门狗初始化函数里开启),系
    统会开始一个倒计时,倒计时结束后,系统复位,如果倒计时没有结束发生喂狗,则又开始新的倒
    计时,本节实验中,复位状态的LED是高电平,灯灭,延时500ms后,点亮led,在看门狗初始化
    后,每经过2s,灯回到复位状态,灭,然后又点亮。反复亮灭。在循环中,按下按钮,就会引发喂
    狗,这时又回到倒计时两秒,不会产生复位,那么灯就不会灭。 
    2s的算法

    这里IWDG_Init函数参数4是16进制的如图PR,相当于预分频选择64,看门狗LSI时钟是32K低俗时
    钟,分频后32/64=0.5KHZ,1/0.5=2ms,经过参数1000个周期,变为2000ms就是2s。

    窗口看门狗

    其喂狗时间是一个有上下限的范围内(窗口),你可以通过设定相关寄存器,设定其上限时间(下限
    固定)。喂狗的时间不能过早也不能过晚。 
    而独立看门狗限制喂狗时间在0­x内,x由相关寄存器决定。喂狗的时间不能过晚。 
    工作示意图:

    设置的倒计时时间是W[6:0],在W[6:0]上面的值,不允许刷新,就是不允许喂狗,如果喂狗则会复
    位,而在3Fh­W[6:0]之间可以喂狗,如果小于3Fh喂狗则又会复位。

    配置寄存器WWDG_CFR中存放看门狗值域上限,而下限是3Fh,3Fh换成二进制0011 1111,也就
    是说WWDG_CR中是一个7位的递减计数器,最高为为WDGA看门狗状态,如图,比如设置了上限
    CFR,当CR的值>CFR时,比较器比较结果为1,经过与门与或门,产生复位,这是第一种复位情
    况,第二种是当CR的递减减到3Fh时,T6变为0,T6出来的信号经过或门,产生复位。

    窗口看门狗超时时间

    窗口看门狗实验

    1. 使能看门狗时钟: 
    RCC_APB1PeriphClockCmd(); 
    ② 设置分频系数: 
    WWDG_SetPrescaler(); 
    ③ 设置上窗口值: 
    WWDG_SetWindowValue(); 
    ④ 开启提前唤醒中断并分组(可选): 
    WWDG_EnableIT(); 
    NVIC_Init(); 
    ⑤ 使能看门狗: 
    WWDG_Enable(); 
    ⑥ 喂狗: 
    WWDG_SetCounter(); 
    ⑦编写中断服务函数 
    WWDG_IRQHandler();
    看门狗初始化函数以及中断:

    void WWDG_Init(u8 tr,u8 wr,u32 fprer)
    {
    NVIC_InitTypeDef NVIC_InitStructure;
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_WWDG,ENABLE); //使能窗口看门狗时钟
    WWDG_CNT=tr&WWDG_CNT; //初始化WWDG_CNT计数器值. CR寄存器最高位是看门狗状
    态,只用到了低7位寄存器
    WWDG_SetPrescaler(fprer); //设置分频值
    WWDG_SetWindowValue(wr); //设置窗口值
    // WWDG_SetCounter(WWDG_CNT);//设置计数值
    WWDG_Enable(WWDG_CNT); //开启看门狗
    NVIC_InitStructure.NVIC_IRQChannel=WWDG_IRQn; //窗口看门狗中断
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=0x02; //抢占优先
    级为2
    NVIC_InitStructure.NVIC_IRQChannelSubPriority=0x03;
    //子优先级为3
    NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE; //使能窗口看门狗
    NVIC_Init(&NVIC_InitStructure);
    WWDG_ClearFlag();//清除提前唤醒中断标志位
    WWDG_EnableIT();//开启提前唤醒中断,开启后,到达3Fh后会进入中断
    }
    //窗口看门狗中断服务程序
    void WWDG_IRQHandler(void)
    {
    WWDG_SetCounter(WWDG_CNT); //重设窗口看门狗值
    WWDG_ClearFlag();//清除提前唤醒中断标志位
    LED1=!LED1;
    }

    先来看main函数,如果不加看门狗

    #include "sys.h"
    #include "delay.h"
    #include "usart.h"
    #include "led.h"
    #include "beep.h"
    #include "key.h"
    #include "wwdg.h"
    int main(void)
    {
    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//设置系统中断优先级分组2
    delay_init(168); //初始化延时函数
    LED_Init(); //初始化LED端口
    KEY_Init(); //初始化按键
    LED0=0; //点亮LED0
    delay_ms(1000);
    //WWDG_Init(0x7F,0X5F,WWDG_Prescaler_8); //计数器值为7f,窗口寄存器为5
    f,分频数为8
    while(1)
    {
    LED0=1; //熄灭LED灯
    }
    }

    没有加看门狗时,LED灯初始化时是灭的,然后亮一秒后熄灭。 
    再来看加入看门狗后,有提前提醒中断,在中断函数中设置到达最低阈值后,重新喂狗,并且点亮
    或熄灭led1作为标志,这样就不会复位,led0一直保持灭。

    通用定时器

    定时器分类:

    通用定时器可以向上计数、向下计数、向上向下双向计数模式。 
    ①向上计数模式:计数器从0计数到自动加载值(TIMx_ARR),然后重新从0开始计数并且产生一个
    计数器溢出事件。 
    ②向下计数模式:计数器从自动装入的值(TIMx_ARR)开始向下计数到0,然后从自动装入的值重新
    开始,并产生一个计数器向下溢出事件。 
    ③中央对齐模式(向上/向下计数):计数器从0开始计数到自动装入的值­1,产生一个计数器溢出
    事件,然后向下计数到1并且产生一个计数器溢出事件;然后再从0开始重新计数。

    定时器原理图

    标号1部分产生一个定时器时钟CK_PSC,并且控制定时器的递增或者递减,标号2为定时器基本单
    元。标号3为输入比较,标号4为输出比较.
    在标号1部分,计数器时钟可以由下列时钟提供: 
    内部时钟(CK_INT) 
    外部时钟模式1:外部输入脚(TIx) 
    外部时钟模式2:外部触发输入(ETR)(仅适用TIM2,3,4) 
    内部触发输入(ITRx):使用一个定时器作为另一个定时器的预分频器,如可以配置一个定时器
    Timer1而作为另一个定时器Timer2的预分频器
    相关寄存器:
    标号2中的当前值CNT

    标号2中的预分频PSC设置寄存器

    标号2中的自动重装寄存器ARR

     

    控制寄存器CR1

    中断始能寄存器DIER

    定时器参数初始化函数:

    void TIM_TimeBaseInit(TIM_TypeDef* TIMx, TIM_TimeBaseInitTypeDef* TIM_Ti
    meBaseInitStruct);

    结构体构造

    typedef struct
    {
    uint16_t TIM_Prescaler; //预分频系数
    uint16_t TIM_CounterMode; //模式(向上,向下计数),操控CR1寄存器
    uint16_t TIM_Period; //自动装载值
    uint16_t TIM_ClockDivision;
    uint8_t TIM_RepetitionCounter;
    } TIM_TimeBaseInitTypeDef;

    实验:定时器中断

    目的:通过定时器中断配置,每500ms中断一次,然后中断服务函数中控制LED实现LED1状态取反(闪烁)

    溢出时间的算法: 
    首先我们选择的是原理图中的内部时钟,内部时钟的选取方式:

    CK_ININT的时钟为84M,这的的84M就是公式的Tclk,84经过预分频(PSC+1)分频系数后频率
    =Tclk/(Psc+1)M,所以时钟周期等于频率的倒数(Psc+1)/Tclk,再乘以重装寄存器的数据,就
    是溢出时间。所以如果想要溢出时间是500ms,设置PSC是8399,则频率
    =84M/8400=10000Hz=10KHz,周期就为0.1ms,要为500ms,就应该乘以5000,所以ARR=4999.
    实验步骤: 
    1.实验从跑马灯实验为基础,在HARDWARE中新建timer.c与.h,将.c到工程的HARDWARE中,在.c
    中写#include “timer.h”,重新编译,.h自动被编辑进.c,再再锤子标志那里添加头文件路径。再在
    FWLIB中添加FWLIB/src中的tim库函数 
    2.选用定时器3,在.h中写

    #ifndef __TIMER_H
    #define __TIMER_H
    #include "sys.h"
    void TIM3_Int_Init(u16 arr,u16 psc);
    #endif

    3.在.c中编写函数: 
    始能定时器,并且初始化arr,psc与mode

    TIM_TimeBaseInitTypeDef TIM_TimBaseInitStrue;
    RCC_AHB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE);//始能定时器3时钟
    TIM_TimBaseInitStrue.TIM_Period=arr;//设置重装载值
    TIM_TimBaseInitStrue.TIM_Prescaler=psc;//预分频系数
    TIM_TimBaseInitStrue.TIM_CounterMode=TIM_CounterMode_Up;//向上计数
    TIM_TimBaseInitStrue.TIM_ClockDivision=TIM_CKD_DIV1;//(随便选的)
    TIM_TimeBaseInit(TIM1,&TIM_TimBaseInitStrue);

    开启定时器3中断并设置

    NVIC_InitTypeDef NVIC_InitStructure;
    TIM_ITConfig(TIM3,TIM_IT_Update,ENABLE);//始能定时器的更新中断
    NVIC_InitStructure.NVIC_IRQChannel=TIM3_IRQn; //定时器3中断
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=0x01; //抢占优先级1
    NVIC_InitStructure.NVIC_IRQChannelSubPriority=0x03; //子优先级3
    NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;
    NVIC_Init(&NVIC_InitStructure);

    始能定时器

    TIM_Cmd(TIM3,ENABLE);//始能定时器3

    编写中断服务函数(函数名在启动文件复制):

    void TIM3_IRQHandler(void)
    {
    if(TIM_GetITStatus(TIM3,TIM_IT_Update)==SET)//检验如果TIM3状态发生更新中
    断
    {
    LED1=!LED1;//反转LED
    }
    TIM_ClearITPendingBit(TIM3,TIM_IT_Update);//清除标志位
    }

    主函数: 
    设置中断优先级分组,(misc中复制函数)

    #include "sys.h"
    #include "delay.h"
    #include "usart.h"
    #include "led.h"
    #include "timer.h"
    int main(void)
    {
    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//设置系统中断优先级分组2
    delay_init(168); //初始化延时函数
    LED_Init(); //初始化LED端口
    TIM3_Int_Init(5000-1,8400-1); //定时器时钟84M,分频系数8400,所以84M/840
    0=10Khz的计数频率,计数5000次为500ms
    while(1)
    {
    LED0=!LED0;//DS0翻转
    delay_ms(200);//延时200ms
    };
    }

    外部中断

    IO口为正常IO口,Line1为外部中断线1,外部中断根据IO口电平状态触发,比如上升沿触发,当IO
    口变为上升沿时,中断触发,中断触发前后,对IO口的状态没有影响。 
    STM32F4xx系列的IO口中断分配:

    每组IO口的引脚数字ID相同的分配到一个中断线,比如PA,PB,PC….PI的0口都分配到中断线EXTI0
    上,对于每个中断线,我们可以设置相应的触发方式(上升沿触发,下降沿触发,边沿触发)以及
    使能。 
    中断线: 
    EXTI线0~15:对应外部IO口的输入中断。 
    EXTI线16:连接到PVD输出。 
    EXTI线17:连接到RTC闹钟事件。 
    EXTI线18:连接到USB OTG FS唤醒事件。 
    EXTI线19:连接到以太网唤醒事件。 
    EXTI线20:连接到USB OTG HS(在FS中配置)唤醒事件。 
    EXTI线21:连接到RTC入侵和时间戳事件。 
    EXTI线22:连接到RTC唤醒事件。 
    意思就是很多外部中断通过IO口(EXIT线0-15)连接到STM32,比如我们要使用PA0的中断,就直接将中断
    线0和GPIOA映射起来就OK了,我们再通过PA0配置连接在PA0连接的外设产生的中断处理.  
    我们来看中断线0­15,IO口的中断,一共16个中断线对应IO口,那么设置这16个中断线的函数共
    有7个中断服务函数: 
    EXTI0_IRQHandler
    EXTI1_IRQHandler
    EXTI2_IRQHandler
    EXTI3_IRQHandler
    EXTI4_IRQHandler
    EXTI9_5_IRQHandler
    EXTI15_10_IRQHandler
    他们的分配如下:

    从表中可以看出,外部中断线5~9分配一个中断向量,共用一个服务函数外部中断线10~15分配一
    个中断向量,共用一个中断服务函数。

    相关函数:
    ①void SYSCFG_EXTILineConfig(uint8_t EXTI_PortSourceGPIOx, uint8_t EXTI_PinSourcex); 
    //设置IO口与中断线的映射关系
    ②void EXTI_Init(EXTI_InitTypeDef* EXTI_InitStruct); 
    //初始化中断线:触发方式等 
    其中结构体成员

    typedef struct
    {
    uint32_t EXTI_Line; //外部中断线选择
    EXTIMode_TypeDef EXTI_Mode; //模式,可选值为中断EXTI_Mode_Interrupt
    和事件 EXTI_Mode_Event
    EXTITrigger_TypeDef EXTI_Trigger; //触发方式
    FunctionalState EXTI_LineCmd; //始能
    }EXTI_InitTypeDef;

    ③ITStatus EXTI_GetITStatus(uint32_t EXTI_Line); 
    //判断中断线中断状态,是否发生
    ④void EXTI_ClearITPendingBit(uint32_t EXTI_Line); 
    //清除中断线上的中断标志位
    ⑤RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE);//使能SYSCFG时钟 
    //这个函数非常重要,在使用外部中断的时候一定要先使能SYSCFG时钟

     

    外部中断配置步骤

    1.使能SYSCFG时钟:

    RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG,ENABLE);

    2.按照Key连接配置按键初始化(初始化GPIO)

    void KEY_Init(void)
    {
    GPIO_InitTypeDef GPIO_InitStructure;
    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA|RCC_AHB1Periph_GPIOE, ENABL
    E);//使能GPIOA,GPIOE时钟
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2|GPIO_Pin_3|GPIO_Pin_4; //KEY0
    KEY1 KEY2对应引脚
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN;//普通输入模式
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;//100M
    GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;//上拉
    GPIO_Init(GPIOE, &GPIO_InitStructure);//初始化GPIOE2,3,4
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;//WK_UP对应引脚PA0
    GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_DOWN ;//下拉
    GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化GPIOA0
    }

    3.设置IO口与中断线的映射关系。(按照原理图KEY0对应的PE4加入外部中断)

    SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOE,EXTI_PinSource4);

    4.初始化外部中断线:(按照原理图,Key0默认时高电平,按下后变为低点评,设置为下降沿触

    EXTI_InitTypeDef EXIT_InitStruct;
    EXIT_InitStruct.EXTI_Line =EXTI_Line4;//初始化中断线4
    EXIT_InitStruct.EXTI_LineCmd =ENABLE;
    EXIT_InitStruct.EXTI_Mode =EXTI_Mode_Interrupt;//模式为中断
    EXIT_InitStruct.EXTI_Trigger =EXTI_Trigger_Falling;//下降沿触发
    EXTI_Init(&EXIT_InitStruct);

    5.配置中断分组(NVIC),并使能中断。注意使用NVIC管理中断时需要在main函数中首先对中断
    进行分组

    NVIC_InitTypeDef NVIC_InitSture;
    NVIC_InitSture.NVIC_IRQChannel=EXTI4_IRQn;//设置中断通道为外部中断线4
    NVIC_InitSture.NVIC_IRQChannelCmd=ENABLE;
    NVIC_InitSture.NVIC_IRQChannelPreemptionPriority=1;//设置抢占优先级
    NVIC_InitSture.NVIC_IRQChannelSubPriority=1;//子优先级
    NVIC_Init(&NVIC_InitSture);

    6.编写中断服务函数。线4中断服务函数

    void EXTI4_IRQHandler(void)
    {
    delay_ms(10);//消除抖动
    if(KEY0==0)//确实按下
    {
    LED0=!LED0;
    LED1=!LED1;
    }
    EXTI_ClearITPendingBit(EXTI_Line4);
    }

    7.编写主函数

    #include "sys.h"
    #include "delay.h"
    #include "usart.h"
    #include "led.h"
    #include "beep.h"
    #include "key.h"
    #include "exti.h"
    int main(void)
    {
    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//设置系统中断优先级分组2
    delay_init(168); //初始化延时函数
    uart_init(115200); //串口初始化
    LED_Init(); //初始化LED端口
    BEEP_Init(); //初始化蜂鸣器端口
    EXTIX_Init(); //初始化外部中断输入
    LED0=0; //先点亮红灯
    while(1)
    {
    printf("OK\r\n"); //打印OK提示程序运行
    delay_ms(1000); //每隔1s打印一次
    }
    }

    ADC

    量程(模拟量输入范围)

    (1)AD转换器是一个电子器件,所以他只能输入电压信号。其他种类的模拟信号要先经过传感器
    (Sensor)的转换变成模拟的电压信号然后才能给AD。 
    (2)AD输入端的模拟电压要求有一个范围,一般是0~3.3V或0~5V或者是0~12V等等。模拟电压的
    范围是AD芯片本身的一个参数。实际工作时给AD的电压信号不能超过这个电压范围。

    精度(分辨率resolution)

    (1)AD转换输出的数字值是有一定的位数的(譬如说10位,意思就是输出的数字值是用10个二进制
    位来表示的,这种就叫10位AD)。这个位数就表示了转换精度。 
    (2)10位AD就相当于把整个范围分成了1024个格子,每个格子之间的间隔就是电压的表示精度。加
    入AD芯片的量程是0~3.3V,则每个格子代表的电压值是3.3V/1024=0.0032265V。如果此时AD转
    换后得到的数字量是447,则这个数字量代表的模拟值是:447×0.0032265V=1.44V。 
    (3)AD的位数越多,则每个格子表示的电压值越小,将来算出来的模拟电压值就越精确。 
    (4)AD的模拟量程一样的情况下,AD精度位数越多精度越高,测出来的值越准。但是如果AD的量程
    不一样。譬如2个AD,A的量程是0~50V,B的量程是0~0.5V,A是12位的,B是10位的,可能B的
    精度比A的还要高。(A的精度:50/1024=0.04883,B的精度:0.5/4096=0.000122)

    转换速率(MSPS与conventor clock的不同)

    (1)首先要明白:AD芯片进行AD转换是要耗费时间的。这个时间需要多久,不同的芯片是不一样
    的,同一颗芯片在配置不一样(譬如说精度配置为10位时时间比精度配置为12位时要小,譬如说有
    些AD可以配转换时钟,时钟频率高则转换时间短)时转换时间也不一样。 
    (2)详细的需要时间可以参考数据手册。一般数据手册中描述转换速率用的单位是MSPS(第一个M
    是兆,S是sample,就是采样;PS就是per second,总的意思就是兆样本每秒,每秒种转出来多少
    M个数字值) 
    (3)AD工作都需要一个时钟,这个时钟有一个范围,我们实际给他配置时不要超出这个范围就可以
    了。AD转换是在这个时钟下进行的,时钟的频率控制着AD转换的速率。注意:时钟频率和MSPS
    不是一回事,只是成正比不是完全相等。譬如S5PV210中的AD转换器,MSPS = 时钟频率/5

    通道数

    AD芯片有多少路analog input通道,代表了将来可以同时进行多少路模拟信号的输入。 
    STM32F4xx 系列一般都有 3 个 ADC,这些 ADC 可以独立使用,也可以使用双重/三重模式(提高
    采样率)。STM32F4 的 ADC 是 12 位逐次逼近型的模拟数字转换器。它有 19 个通道,可测量 16
    个外部源、2 个内部源和 Vbat 通道的信号。这些通道的 A/D 转换可以单次、连续、扫描或间断模
    式执行。ADC 的结果可以左对齐或右对齐方式存储在 16 位数据寄存器中。 
    1.规则通道组:相当正常运行的程序。最多16个通道。 
    规则通道和它的转换顺序在ADC_SQRx寄存器中选择,规则 
    组转换的总数应写入ADC_SQR1寄存器的L[3:0]中
    2. 注入通道组:相当于中断。最多4个通道。 
    注入组和它的转换顺序在ADC_JSQR寄存器中选择。注入组 
    里转化的总数应写入ADC_JSQR寄存器的L[1:0]中

    转换模式

    ADC单次转换:单次转换下,ADC执行一次转换,如果在规则通道中进行了单次转换,则转换的数
    据存储在16位ADC_DR寄存器中,其中EOC转换结束标志置1,若EOCIE位置为1则产生中断。如
    果在注入通道中进行单次转换,则转换的数据存储在ADC_JDR1中,JEOC转换结束标志置1,
    JEOCIE置1时产生中断。然后ADC停止。 
    ADC连续转换:

    扫描模式:在一个通道扫描完成后自动开始下一个通道的转换.在扫描模式时,规则组序列就有n个通道

    ADC采样时间

    这里0.5微秒的算法:ADCCLK的时钟为30MHz,分成15个周期,则每个周期2MHz的时钟,相当于
    0.5微秒采一次。 
    最小采样时间0.42us(ADC时钟=36MHz,采样周期为3周期下得到),ADC时钟不能超过36MHz 
    影响ADC采样时间的参数主要有两个: 
    1.ADC_CommonInit中的ADC_Prescaler时钟设置,分频越大,ADC时钟频率越小,ADC采样周期
    越长,精度越小。 
    2.ADC_RegularChannelConfig中的采样周期,采样周期越小,越精确

    参数相关配置

    void ADC_CommonInit(ADC_CommonInitTypeDef* ADC_CommonInitStruct)
    typedef struct
    {
    uint32_t ADC_Mode;//若有多重ADC,则可以选择多重ADC的工作模式
    uint32_t ADC_Prescaler;//ADC分频系数,ADC总线时84M,要求ADC不超过36M
    uint32_t ADC_DMAAccessMode; //多重ADC下的DMA工作模式
    uint32_t ADC_TwoSamplingDelay; //转换间隔
    }
    
    void ADC_Init(ADC_TypeDef* ADCx, ADC_InitTypeDef* ADC_InitStruct);
    typedef struct
    {
    uint32_t ADC_Resolution;//ADC分辨率
    FunctionalState ADC_ScanConvMode; //是否使用扫描模式。多通道时启用
    FunctionalState ADC_ContinuousConvMode; //单次转换OR连续转换,连续转换就是在
    完成一次AD转换后马上开启下一次AD转换,软件开启一次转换后就会一直转换,不用再循环里一直
    触发ADC转换
    uint32_t ADC_ExternalTrigConvEdge; //外部触发使能方式
    uint32_t ADC_ExternalTrigConv; //触发方式
    uint32_t ADC_DataAlign; //对齐方式:左对齐还是右对齐
    uint8_t ADC_NbrOfChannel;//规则通道序列长度,采样通道,如果只采一个脉冲就只用一
    个通道,那么采样通道只有1个
    }ADC_InitTypeDef;
    
    
    ADC_DeInit; //函数的功能是将外设ADCx的全部寄存器重设为默认值。
    3.ADC_Cmd //函数的功能是使能或失能指定的ADC,其中ADC_Cmd只能在其他ADC设置函数之后被
    调用
    ADC_Cmd(ADC1,ENABLE);
    4.ADC_DMACmd //函数的功能是使能或者失能指定的ADC的DMA请求。
    ADC_DMACmd(ADC1,ENABLE);
    5.ADC_ITConfig //函数的功能是使能或者失能指定的ADC的中断,其中可以是EOC/AWD/JEOC
    ADC_ITConfig(ADC2,ADC_IT_EOC|ADC_IT_AWD);
    6.ADC_ResetCalibration //函数的功能是重置指定的ADC的校准寄存器。
    ADC_ReserCalibration(ADC1);
    7.ADC_GetResetCalibrationSttaus //函数的功能是获取ADC重置校准寄存器的状态。
    FlagStatus Status
    Status = ADC_GetResetCalibrationSttaus(ADC2);
    8.ADC_StartCalibration //函数的功能是开始指定ADC的校准。
    ADC_StartCalibration(ADC2);
    9.ADC_GetCalibrationStatus //函数的功能是获取ADC的校准状态。具有返回值
    FlagStatus Status;
    Status = ADC_GetCalibrationStatus(ADC2);
    10.ADC_SoftwareStartConvCmd //函数的功能是使能或者失能指定的ADC的软件启动功能。
    ADC_SoftwareStartConvCmd(ADC1,ENABLE);
    11.ADC_DiscModeChannelCountConfig //函数的功能是对ADC规则通道配置间断模式。其中
    参数可以是1~8,间断模式计数器的值。
    ADC_DiscModeChannelCountConfig(ADC1,2);
    12.ADC_DiscModeCmd //函数的功能是使能或者失能指定的ADC规则组通道的间断模式。
    ADC_DiscModeCmd(ADC1,ENABLE);
    13.ADC_RegularChannelConfig //函数的功能是设置ADC的规则组通道,设置他们的转化顺序
    和采样时间,其中ADC_Channel指定了通过本函数来设置的ADC通道,可以是0~17,ADC_Sample
    Time设置了选中通道的ADC采样时间。
    ADC_RegularChannelConfig(ADC2,ADC_Channel_2,1,ADC_SampleTime_1Cycles5);
    14.ADC_ExternalTrigConvConfig //函数的功能是使能或者失能ADCx的经外部触发启动转换
    功能。
    ADC_ExternalTrigConvConfig(ADC2,ENABLE);
    15.ADC_GetConversionValue //函数的功能是返回最近一次ADCx规则组的转换结果。
    u16 DataValue;
    DataValue = ADC_GetConversionValue(ADC2);
    16.ADC_GetDuelModeConversionValue //函数的功能是返回最近一次双ADC模式下的转换结
    果。
    u32 DataValue;
    DataValue = ADC_GetDuelModeConversionValue();
    17.ADC_AutoInjectedConvCmd //函数的功能是使能或者失能指定ADC在规则组转化后自动开始
    注入组转换。
    ADC_AutoInjectedConvCmd(ADC2,ENABLE);
    18.ADC_InjectedDiscModeCmd //函数的功能是使能或者失能指定的ADC注入组间断模式。
    ADC_InjectedDiscModeCmd(ADC2,ENABLE);
    19.ADC_ExternalITrigInjectedConvConfig //函数的功能是配置ADCx外部触发启动注入组
    转换功能。其中ADC_ExternalITrigConv_IT可以取多种启动触发模式
    例:用定时器1的捕获比较4触发ADC1注入组转换功能。
    ADC_ExternalITrigInjectedConvConfig(ADC1,ADC_ExternalITrigConv_IT_CC4);
    20.ADC_ExternalITrigInjectedConvCmd //函数的功能是使能或者失能ADCx的经外部触发启
    动注入组转换功能。
    ADC_ExternalITrigInjectedConvCmd(ADC2,ENABLE);
    21.ADC_SoftwareStartInjectedConvCmd //函数的功能是使能或者失能ADCx软件启动注入组
    转换功能。
    ADC_SoftwareStartInjectedConvCmd(ADC2,ENABLE);
    22.ADC_GetSoftwareStartInjectedConvStatus //函数的功能是获取指定ADC的软件启动注
    入组转换状态,会返回一个ADC软件触发启动注入转换的新状态。
    FlagStatus Status;
    Status = ADC_GetSoftwareStartInjectedConvStatus(ADC2);
    23.ADC_InjectedChannelConfig //函数的功能是设置指定ADC的注入组通道,设置他们的转
    化顺序和采样时间。不过先决条件是之前必须调用函数ADC_InjectedSequencerLengthConfig
    来确定注入转换通道的数目,特别是在通道数目小于4的情况下,先正确配置每一个通道的转化顺
    序。
    例:配置ADC1第12通道采样周期28.5,第二个开始转换。
    ADC_InjectedChannelConfig(ADC1,ADC_Channel_12,2,ADC_SampleTime_28Cycles
    5);
    24.ADC_InjectedSequenceLengthConfig //函数的功能是设置注入组通道的转换序列长度。
    且序列长度的取值范围是~4。
    ADC_InjectedSequenceLengthConfig(ADC1,1);
    25.ADC_SetInjectefOffset //函数的功能是设置注入组通道的转换偏移值。选择注入通道可以
    是1~4.偏移量是16位值。
    ADC_SetInjectefOffset(ADC_InjectedChannel_1,0x100);
    26.ADC_GetInjectedConversionValue //函数的功能是返ADC指定注入通道的转换结果。
    u16 InjectedConversionValue;
    InjectedConversionValue = ADC_GetInjectedConversionValue(ADC1,ADC_Injecte
    dChannel_1);
    27.ADC_TampSensorVrefintCmd //函数的功能是使能或者失能温度传感器和内部参考电压通
    道。
    ADC_TempSensorVrefintCmd(ENABLE);
    28.ADC_GetFlagStatus //函数的功能是检查指定的ADC标志位是否置1.会返回一个新的ADC_
    FLAG值。其中指定标志位可以取5种值。
    FlagStatus Status;
    FlagStatus = ADC_GetFlagStatus(ADC1,ADC_FLAG_AWD);
    29.ADC_ClearFlag //函数的功能是清除ADCx待处理的标志位。在使用本函数之前是调用过了AD
    C_GetFlagStatus函数的。
    ADC_ClearFlag(ADC2,ADC_FLAG_AWD).
    30.ADC_DMARequestAfterLastTransferCmd //源变化时开启DMA传输
    ADC_DMARequestAfterLastTransferCmd(ADC1,ENABLE);
    31.ADC_DMACmd //始能ADC的DMA传输
    ADC_DMACmd(ADC1,ENABLE);
    }

    DMA

    STM32F4最多有2个DMA控制器,2个DMA控制器总共有16个数据流(每个控制器8个)。每个
    DMA控制器都用于管理一个或者多个外设的存储器访问请求。每个数据流总共可以有多达8个通道
    (或请求),每个通道都有一个仲裁器,用于处理DMA请求间的优先级。

    请求映射

    流配置过程

    DMA中断

    其中在写DMA的中断函数时,中断函数可以写在主函数里,中断标志位例如
    DMA_GetITStatus(DMA2_Stream2,DMA_IT_TCIF2)  
    表示的是DMA2数据流2某个通道传输完成,DMA_IT_TCIF2后面的数字是数据流的号,不是通道的号

    库函数

    typedef struct
    {
    uint32_t DMA_Channel; //DMA通道
    uint32_t DMA_PeripheralBaseAddr; //外设的基地址
    uint32_t DMA_Memory0BaseAddr; //存储器的基地址
    uint32_t DMA_DIR; // 数据传输方向
    uint32_t DMA_BufferSize; //传输的数据数量,不管传输的是32位还是16位。比如从
    外设传到数组,这里的buffersize就是数组的长度。
    uint32_t DMA_PeripheralInc; //传输数据时外设地址是否递增,外设一般都不增
    uint32_t DMA_MemoryInc; //传输数据时存储器地址是否递增,如果是数组,那
    么地址要递增
    uint32_t DMA_PeripheralDataSize; //外设传输的数据宽度
    uint32_t DMA_MemoryDataSize; //存储器传输的数据宽度
    uint32_t DMA_Mode; //是否开启循环模式,循环模式就是是否开启DMA 自动
    转换,比如ADC一直采集数据,然后开启循环模式,则ADC采到了数据就会通过DMA发送
    uint32_t DMA_Priority; //设置优先级
    uint32_t DMA_FIFOMode; //FIFO的配置
    uint32_t DMA_FIFOThreshold;
    uint32_t DMA_MemoryBurst; //存储器突发设置
    uint32_t DMA_PeripheralBurst; //外设的突发设置
    }DMA_InitTypeDef;

    DMA初始化(例子):

    void MYDMA_Config(DMA_Stream_TypeDef *DMA_Streamx,u32 chx,u32 par,u32 ma
    r,u16 ndtr)//(数据流,通道,外设基地址,存储器基地址,传输量)
    {
    DMA_InitTypeDef DMA_InitStructure;
    if((u32)DMA_Streamx>(u32)DMA2)//得到当前stream是属于DMA2还是DMA1
    {
    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2,ENABLE);//DMA2时钟使能
    }else
    {
    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA1,ENABLE);//DMA1时钟使能
    }
    DMA_DeInit(DMA_Streamx);
    while (DMA_GetCmdStatus(DMA_Streamx) != DISABLE){}//等待DMA可配置
    /* 配置 DMA Stream */
    DMA_InitStructure.DMA_Channel = chx; //通道选择
    DMA_InitStructure.DMA_PeripheralBaseAddr = par;//DMA外设地址
    DMA_InitStructure.DMA_Memory0BaseAddr = mar;//DMA 存储器地址
    DMA_InitStructure.DMA_DIR = DMA_DIR_MemoryToPeripheral;//存储器到外设模式
    DMA_InitStructure.DMA_BufferSize = ndtr;//数据传输量
    DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;//外设非
    增量模式
    DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;//存储器增量模式
    DMA_InitStructure.DMA_PeripheralDataSize =
    DMA_PeripheralDataSize_Byte;//外设数据长度:8位
    DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;//存储器数
    据长度:8位
    DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;// 使用普通模式
    DMA_InitStructure.DMA_Priority = DMA_Priority_Medium;//中等优先级
    DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable;
    DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_Full;
    DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;//存储器突发单
    次传输
    DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;//外
    设突发单次传输
    DMA_Init(DMA_Streamx, &DMA_InitStructure);//初始化DMA Stream
    DMA_Cmd(DMA_Streamx, ENABLE); //开启DMA传输
    }

    多重ADC

    三重ADC转换原理

    AD 转换包括采样阶段和转换阶段,在采样阶段才对通道数据进行采集;而在转换阶段只是将采集
    到的数据进行转换为数字量输出,此刻通道数据变化不会改变转换结果。独立模式的 ADC采集需要
    在一个通道采集并且转换完成后才会进行下一个通道的采集。双重或者三重 ADC的机制使用两个或
    以上 ADC同时采样两个或以上不同通道的数据或者使用两个或以上 ADC交叉采集同一通道的数
    据。双重或者三重 ADC模式较独立模式一个最大的优势就是转换速度快。 
    介绍三重 ADC交替模式,三重 ADC交替模式是针对同一通道的使用三个 ADC交叉采集,就是在
    ADC1 采样完等几个时钟周期后 ADC2 开始采样,此时 ADC1处在转换阶段,当 ADC2 采样完成再
    等几个时钟周期后 ADC3就进行采样此时 ADC1 和 ADC2 处在转换阶段,如果 ADC3 采样完成并且
    ADC1已经转换完成那么就可以准备下一轮的循环,这样充分利用转换阶段时间达到增快采样速度
    的效果。

    DMA模式请求

    DMA 模式 2:每发送一个 DMA 请求(两个数据项可用),就会以字的形式传输表 
    示两个 ADC 转换数据项的两个半字。在双重 ADC 模式下,发出第一个请求时会传输 ADC2 和
    ADC1 的数据(ADC2 数据占用高位半字,ADC1 数据占用低位半字),依此类推。 
    在三重 ADC 模式下,将生成三个 DMA 请求:发出第一个请求时,会传输 ADC2 和ADC1 的数据
    (ADC2 数据占用高位半字,ADC1 数据占用低位半字)。发出第二个请求时,会传输 ADC1 和
    ADC3 的数据(ADC1 数据占用高位半字,ADC3 数据占用地位半字)。发出第三个请求时,会传
    输 ADC3 和 ADC2 的数据(ADC3占用高位半字,ADC2 数据占用地位半字),依此类推。 
    DMA 模式 2 用于交替模式和常规同步模式(仅适用于双重 ADC 模式)。

    三重ADC采样单通道信号ADC与DMA配置

    ADC

    #include "adc.h"
    #include "sys.h"
    void MYADC_configure()//从adc中
    {
    GPIO_InitTypeDef GPIO_InitStructure;
    ADC_CommonInitTypeDef ADC_CommonInitStructure;
    ADC_InitTypeDef ADC_InitStructure;
    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOC,ENABLE);
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC3|RCC_APB2Periph_ADC1|RCC_AP
    B2Periph_ADC2, ENABLE);
    GPIO_InitStructure.GPIO_Pin=GPIO_Pin_0;
    GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AN;
    GPIO_InitStructure.GPIO_PuPd=GPIO_PuPd_NOPULL ;
    GPIO_Init(GPIOC,&GPIO_InitStructure);
    //复位ADC
    ADC_DeInit();
    //配置通用寄存器ADC_CCR
    ADC_CommonInitStructure.ADC_Mode=ADC_TripleMode_Interl;//三重交替模式
    ADC_CommonInitStructure.ADC_TwoSamplingDelay=ADC_TwoSamplingDelay_5Cy
    cles;
    ADC_CommonInitStructure.ADC_DMAAccessMode=ADC_DMAAccessMode_2;//DMA模
    式2
    ADC_CommonInitStructure.ADC_Prescaler=ADC_Prescaler_Div4;//84/4=21M
    ADC_CommonInit(&ADC_CommonInitStructure);
    //配置ADC
    ADC_InitStructure.ADC_Resolution=ADC_Resolution_12b;//分辨率12位
    ADC_InitStructure.ADC_ScanConvMode=DISABLE;//关闭扫描模式
    ADC_InitStructure.ADC_ContinuousConvMode=ENABLE;//开启连续转换 CR2
    ADC_InitStructure.ADC_ExternalTrigConvEdge=ADC_ExternalTrigConvEdge_N
    one;//不采用边沿触发
    //ADC_InitStructure.ADC_ExternalTrigConv=ADC_SOFTWARE_START;
    ADC_InitStructure.ADC_DataAlign=ADC_DataAlign_Right;//右齐
    ADC_InitStructure.ADC_NbrOfConversion=1;//采样通道1个
    ADC_Init(ADC1,&ADC_InitStructure);
    ADC_InitStructure.ADC_Resolution=ADC_Resolution_12b;//分辨率12位
    ADC_InitStructure.ADC_ScanConvMode=DISABLE;//关闭扫描模式
    ADC_InitStructure.ADC_ContinuousConvMode=ENABLE;//开启连续转换 CR2
    ADC_InitStructure.ADC_ExternalTrigConvEdge=ADC_ExternalTrigConvEdge_N
    one;//不采用边沿触发
    //ADC_InitStructure.ADC_ExternalTrigConv=ADC_ExternalTrigConv_T8_TRG
    O;
    ADC_InitStructure.ADC_DataAlign=ADC_DataAlign_Right;//右齐
    ADC_InitStructure.ADC_NbrOfConversion=1;//采样通道1个
    ADC_Init(ADC2,&ADC_InitStructure);
    ADC_InitStructure.ADC_Resolution=ADC_Resolution_12b;//分辨率12位
    ADC_InitStructure.ADC_ScanConvMode=DISABLE;//关闭扫描模式
    ADC_InitStructure.ADC_ContinuousConvMode=ENABLE;//开启连续转换 CR2
    ADC_InitStructure.ADC_ExternalTrigConvEdge=ADC_ExternalTrigConvEdge_N
    one;//不采用边沿触发
    //ADC_InitStructure.ADC_ExternalTrigConv=ADC_ExternalTrigConv_T8_TRG
    O;
    ADC_InitStructure.ADC_DataAlign=ADC_DataAlign_Right;//右齐
    ADC_InitStructure.ADC_NbrOfConversion=1;//采样通道1个
    ADC_Init(ADC3,&ADC_InitStructure);
    //始能ADC
    ADC_RegularChannelConfig(ADC1, ADC_Channel_10, 1, ADC_SampleTime_3Cyc
    les ); //配置通道优先级 SMPR2,SQR3
    ADC_RegularChannelConfig(ADC2, ADC_Channel_10, 1, ADC_SampleTime_3Cyc
    les ); //配置通道优先级 SMPR2,SQR3
    ADC_RegularChannelConfig(ADC3, ADC_Channel_10, 1, ADC_SampleTime_3Cyc
    les ); //配置通道优先级 SMPR2,SQR3
    ADC_DMACmd(ADC1,ENABLE);
    ADC_MultiModeDMARequestAfterLastTransferCmd(ENABLE);
    ADC_Cmd(ADC1, ENABLE);
    ADC_Cmd(ADC2, ENABLE);
    ADC_Cmd(ADC3, ENABLE);
    ADC_SoftwareStartConv(ADC1);
    }

    DMA

    #include "dma.h"
    #include "sys.h"
    void MYDMA_DMA_DIR_PeripheralToMemoryConfig(DMA_Stream_TypeDef *DMA_Strea
    mx,u32 chanlx,u32 par,u32 memory,u16 ndtr)//(数据流,通道,外设基地址,存储器
    基地址,传输量,不管是多少位的,传输量只是数据的个数,这里设置为数组的长度)
    {
    DMA_InitTypeDef DMA_InitStructure;
    if((u32)DMA_Streamx>(u32)DMA2)//得到当前stream是属于DMA2还是DMA1
    {
    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2,ENABLE);//DMA2时钟使能
    }else
    {
    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA1,ENABLE);//DMA1时钟使能
    }
    DMA_DeInit(DMA_Streamx);
    while (DMA_GetCmdStatus(DMA_Streamx) != DISABLE){}//等待DMA可配置
    /* 配置 DMA Stream */
    DMA_InitStructure.DMA_Channel = chanlx; //通道选择
    DMA_InitStructure.DMA_PeripheralBaseAddr = par;//DMA外设地址,S0PAR
    DMA_InitStructure.DMA_Memory0BaseAddr = memory;//DMA 存储器地址 S0M0AR
    DMA_InitStructure.DMA_DIR =DMA_DIR_PeripheralToMemory ;//外设到存储器
    DMA_InitStructure.DMA_BufferSize = ndtr;//数据传输量 ,NDTR
    DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;//外设非
    增量模式,S0CR
    DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;//存储器增量模式,S0
    CR
    DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Word;
    DMA_InitStructure.DMA_MemoryDataSize = DMA_PeripheralDataSize_Word;
    DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;// 循环模式,S0CR
    DMA_InitStructure.DMA_Priority = DMA_Priority_High;//高优先级,S0CR
    DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable;
    DMA_InitStructure.DMA_FIFOThreshold=DMA_FIFOThreshold_HalfFull;//
    DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;//存储器突发单
    次传输
    DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;//外
    设突发单次传输
    DMA_Init(DMA_Streamx, &DMA_InitStructure);//初始化DMA Stream
    DMA_Cmd(DMA_Streamx, ENABLE);
    }

     

    展开全文
  • MAXQ618是一种低功耗,16位MAXQ微控制器的低功耗应用,包括通用遥控器,消费电子白色家电设计。该器件结合了强大的16位RISC...中断源包括外部中断,电源失效中断以及定时器中断。微控制器运行从1.70V到3.6V宽工作电压
  • MAXQ618是一种低功耗,16位MAXQ微控制器的低功耗应用,包括通用遥控器,消费电子白色家电设计。该器件结合了强大的16位RISC微控制器...中断源包括外部中断,电源失效中断以及定时器中断。微控制器运行从1.70V到3.6V宽
  • MAXQ61C是一款低功耗、16位MAXQ?微控制器,设计用于通用遥控器、消费类电子白色家电等低...唤醒源包括外部中断、电源失效中断以及定时器中断。微控制器工作在1.70V至3.6V宽工作电压范围。  原理框图  关键特
  • MAXQ61C是一款低功耗、16位MAXQ?微控制器,设计用于通用遥控器、消费类电子白色家电等低...唤醒源包括外部中断、电源失效中断以及定时器中断。微控制器工作在1.70V至3.6V宽工作电压范围。  原理框图  关键特
  • 51单片机引线

    2014-11-23 14:56:08
    如上图。 I/O线: 在进行外部扩展时,P2口的8根引线为...作为第二功能使用时,P3.0~P3.7分别是串行输入、串行输出、外部中断0输入、外部中断1输入、定时器0外部计数脉冲输入、定时器1外部计数脉冲输入、外部数据存储
  • 51基础知识学习笔记

    2020-10-31 13:35:51
    5个中断功能:2个外部中断,2个定时器中断,一个串口中断 内置12M的时钟电路(注:需要一个外部晶振驱动) 2、8051的总线 8051具有8位数据总线,16位的地址总线,地址总线数据总线是复用的。再用哈佛结构,程序...
  • 2.1号,实验室总结

    2018-02-01 14:34:57
     一月21日至1月28日,我主要看了正点原子的关于STM32、跑马灯、蜂鸣器、按键输入、串口、IO引脚复用映射、NVIC中断优先级的管理、外部中断、通用定时器、看门狗、PWM输出实验、输入捕获实验等视频讲解。 1、了解...
  • 2020-07-31

    2020-07-31 16:36:52
    学习报告: 第2期 时间周期: 7月1日-7月30日 姓名、专业:闫春幸- 电子信息 ...又学习了串口的相关知识,比如串口使能、串口初始化和调用的相关函数,学习了外部中断和NVIC中断优先级设置。接下来对定时器的学习,主
  • 网上整理的,三条时钟总线上挂的外设简单列举如下: 1、AHB总线: (1)Flash 存储器;...(5)外部中断EXTI; (6)复用IO,AFIO; (7)通用IO:GPIOA~G; 3、APB1总线: (1)定时器TIM2到TIM7;
  • STM32F3-PWM输入捕获测量频率脉宽…

    千次阅读 2016-11-27 19:53:17
    使用时将相应的输入配置为对应定时器对应的复用功能,外部待测量波形从该引脚输入 再配置定时器输入捕获功能相应参数,选择主从模式,最后打开中断或者DMA读取测量数据 1. Enable TIM clock  2. Configure the ...
  • STM32-APB1,AB2,AHB总线外设分类 1、AHB总线: (1)Flash 存储器;...(5)外部中断EXTI; (6)复用IO,AFIO; (7)通用IO:GPIOA~G; 3、APB1总线: (1)定时器TIM2到TIM7; (2)RTC; (3)WDT看门狗
  • STM32总线外设分布

    2020-08-07 16:38:50
    1、AHB总线: (1)Flash 存储器;...(5)外部中断EXTI; (6)复用IO,AFIO; (7)通用IO:GPIOA~G; 3、APB1总线: (1)定时器TIM2到TIM7; (2)RTC; (3)WDT看门狗; (4)SPI2 、SPI3; (5)USART
  • 10-HAL库之ADC电压采集

    千次阅读 2018-09-19 09:50:47
    12位ADC是逐次趋近型模数转换器,有19个复用通道(可测量16个外部源,2个内部源1个VBAT通道的信号)。A/D转换可在单次、连续、扫描或不连续采样模式下进行,采样结果存储在1个16位数据寄存器中(实际只有12位数据...
  • STM32F10xxx参考手册

    2012-10-17 11:38:40
    8.4.5 外部中断配置寄存器3(AFIO_EXTICR3) 127 8.4.6 外部中断配置寄存器4(AFIO_EXTICR4) 128 8.5 GPIO 和AFIO寄存器地址映象 129 9 中断和事件 130 9.1 嵌套向量中断控制器 130 9.1.1 系统嘀嗒(SysTick)校准值...
  • ComaratorE是具有用于多达16个通道...• 反相同相端子输入多路复用 • 对于比较器输出软件可选RC滤波器 • 提供给定时器A捕捉的输入输出 • 端口输入缓冲器的软件控制 • 中断能力• 可选择的参考电压发生器,...
  • 3.5.2外部中断/事件控制器(EXTI) 3.5.3EXTI寄存器 3.6DMA控制器 3.6.1简介 3.6.2主要特性 3.6.3功能描述 3.6.4DMA寄存器 3.7实时时钟(RTC) 3.7.1简介 3.7.2主要特性 3.7.3功能描述 3.7.4RTC寄存器描述 3.8备份...
  • 3.5.2外部中断/事件控制器(EXTI) 3.5.3EXTI寄存器 3.6DMA控制器 3.6.1简介 3.6.2主要特性 3.6.3功能描述 3.6.4DMA寄存器 3.7实时时钟(RTC) 3.7.1简介 3.7.2主要特性 3.7.3功能描述 3.7.4RTC寄存器描述 3.8备份...
  • 3.5.2外部中断/事件控制器(EXTI) 3.5.3EXTI寄存器 3.6DMA控制器 3.6.1简介 3.6.2主要特性 3.6.3功能描述 3.6.4DMA寄存器 3.7实时时钟(RTC) 3.7.1简介 3.7.2主要特性 3.7.3功能描述 3.7.4RTC寄存器描述 3.8备份...
  • STM32F407ZGT6GK_V1.2.pdf

    2020-02-03 15:07:43
    9、多达17个定时器: 12个16位定时器2个频率高达 168 MHz 的 32 位定时器,每个定时器都带有 4 个输入捕获 / 输出比较 /PWM,或脉冲计数器与正交 ( 增量 ) 编码器输入 10、调试模式 – SWD & JTAG 接口 – ...
  • c8051f020的12位AD采样

    2015-07-31 09:44:57
    程序测量电压在外部ADC输入打印  / /结果通过UART终端窗口。  / /系统时钟使用内部24.5 mhz振荡器成倍增加  / / 49 mhz的芯片上的锁相环。结果输出到UART的循环  / /设定的速度基于定时器2的延迟。这个循环...

空空如也

空空如也

1 2
收藏数 35
精华内容 14
关键字:

外部中断和定时器中断复用