STM32f407学习之旅

一、基础知识

1.资料查找

(1)探索者STM32F4开发板光盘结构(必读).txt      ctrl+F查找

(2)I/O口---注意查找数据手册(pin definitions)凡是带FT标志的I/O口都是兼容5V的,从原理图上看带ADC的都不兼容5V。

(3)I/O资源分配、使用说明---注意查找 引脚分配表.xsl

2.例程文档

(1)readme.txt(必读,包含提示)

(2)开发指南(库函数)具体解释

(3)中文参考手册

3.驱动(设备管理器可查看)

(1)快捷方式查看设备管理器---win+R----输入命令:devmgmt.msc

(2)程序下载到开发板上的方法

          1.ISP串口下载:FLYMcu下载工具(D:\嵌入式开发STMF407V2\A盘-具体资料\6,软件资料\1,软件\STM32F4串口下载软件(FLYMCU))

         (注意:根据设备管理器选择正确的Port; bps最好选择76800; 选择正确的.hex文件; 一定要选择DTR低 RTS高)

         2.JLINK程序下载 :首先编译无误,小槌头配置(Debug:ST-Link  勾选Run to main()  settings里面port选择 SW  Flash Download选择1M),点击LOAD进行下载     

4.程序模板

(1)基础知识: 

1.FWLib 下面存放的是 ST 官方提供的固件库函数(引入src中相关外设固件库)

2.CORE 下面存放的是固件库必须的核心文件和启动文件。

3.SYSTEM ALIENTEK 提供的共用代码

4.HARDWARE 下面存放的是每个实验的外设驱动代码,他的实现是通过调用 FWLib 下面的固件库文件实现的

5.C语言/电路知识

(1) 什么叫上\下拉电阻呢?

  1. 上拉是对器件输入电流,即灌电流 
  2. 下拉是从器件输出电流,即拉电流

  • WK_UP 按键中电阻为下拉电阻,KEY按键中电阻为上拉电阻。
  • WK_UP下拉电阻,所以IO默认低电平。WK_UP 按键接VCC,当按键按下时WK_UP为高电平,给IO口输入高电平、 即高电平有效; 
  • KEY接上拉电阻,所以IO默认高电平。KEY0 KEY1 KEY2 接地,当按键按下时KEY为低电平,给IO口输入低电平、 即低电平有效

(2)static关键字作用

  1. 普通的局部变量创建后是放在栈区中,这种局部变量进入作用域时创建,出了作用域就销毁;但static修饰后的局部变量则放在静态区中,它改变了局部变量的存储位置,从而使得变量的生命周期延长,延长至程序结束才销毁
  2. 缩小作用域,仅能自己内部使用。全局变量本身是具有外部链接属性的,在A文件中定义的全局变量,在B文件中可以通过【链接】来使用;

    但如果全局变量被static修饰,那这个外部链接属性就会被修改成内部链接属性,此时这个全局变量就只能在自己的源文件中使用;

(3)位操作

C语言输出位二进制:

/*char* itoa(int value,char*string,int radix);
value: 要转换的整数,可以不是int类型但是整数必须在int的范围里           
string: 转换后的字符串  
radix: 转换进制数,范围是2~36 */

#define uint32 unsigned int
void FuncOutputBin(uint32 value)
{
	char string[32]={0};   //形参类型uint32最大为32位
	itoa(value, string, 2);  
	printf("库函数得到的二进制为:%s\r\n",string);
}
  1. 设置位(Set Bit):将特定位设置为1,通常使用按位或(OR)操作。例如,如果要将第3位设置为1,可以执行register |= (1 << 3);

  2. 清除位(Clear Bit):将特定位清除为0,通常使用按位与(AND)操作。例如,如果要将第5位清除为0,可以执行register &= ~(1 << 5);

  3. 切换位(Toggle Bit):将特定位的值取反,通常使用按位异或(XOR)操作。例如,如果要切换第2位的值,可以执行register ^= (1 << 2);

  4. 读取位(Read Bit):读取特定位的值,通常使用按位与(AND)操作。例如,要读取第4位的值,可以执行bit_value = (register >> 4) & 1;

  5. 检查位(Check Bit):检查特定位是否为1或0,通常使用按位与(AND)操作。例如,要检查第6位是否为1,可以执行bit_is_set = (register & (1 << 6)) != 0;

  6. 修改位(Modify Bit):通过先清除位然后再设置位的方式来修改特定位的值。例如,如果要将第1位修改为1,可以执行register = (register & ~(1 << 1)) | (1 << 1);

(4)条件编译

#ifdef  //标识符,常用ifndef 如果这个标识符没有被定义,就执行下面程序,防止命名重复
程序段1
#else
程序段2
#endif



.h去判断一个标识符是否被使用过,避免重复定义
(
#ifndef  标识符
#define  标识符
 主体
#endif)

(5)extern

变量声明,可多次声明,定义只有一次

  extern的引用方式比包含头文件要简洁得多!extern的使用方法是直接了当的,想引用哪个函数就用extern声明哪个函数。 

(6)typedef(类型别名)

例如 typedef  WAN   wan;

以后WAN就可以叫wan

(7)数据类型定义

u8        unsigned char

u16      unsigned short

u32      unsigned int

二、固件库查找

1.GPIO 端口:stm32f4xx_gpio.h 和 stm32f4xx_gpio.c

二、实验-----初级

1.跑马灯---I/O口作为输出

(1)I/O口模式

(1)GPIO_Mode_AIN 模拟输入 :I/O端口的模拟信号(电压信号,而非电平信号)直接模拟输入到片上外设模块,比如ADC模块等等。

(2)GPIO_Mode_IN_FLOATING 浮空输入:在要读取外部信号时通常配置IO口为浮空输入模式。-----数据寄存器

(3)GPIO_Mode_IPD 下拉输入:在I/O端口悬空(在无信号输入)的情况下,输入端的电平可以保持在低电平;并且在I/O端口输入为高电平的时候,输入端为高电平。 -----数据寄存器

(4)GPIO_Mode_IPU 上拉输入:在I/O端口悬空(在无信号输入)的情况下,输入端的电平可以保持在高电平;并且在I/O端口输入为低电平的时候,输入端的电平为低电平。  -----数据寄存器

(5)GPIO_Mode_Out_OD 开漏输出:通过设置位设置/清除寄存器或者输出数据寄存器的值,控制MOS管的导通。这里要注意N-MOS管,当设置输出的值为高电平的时候,N-MOS管处于关闭状态,此时I/O端口的电平就不会由输出的高低电平决定,而是由I/O端口外部的上拉或者下拉决定;当设置输出的值为低电平的时候,N-MOS管处于开启状态,此时I/O端口的电平就是低电平。同时,I/O端口的电平也可以通过输入电路进行读取;注意,I/O端口的电平不一定是输出的电平。通常使用开漏输出时外部要加一个上拉电阻。

(6)GPIO_Mode_Out_PP 推挽输出:通过设置位设置/清除寄存器或者输出数据寄存器的值,控制P-MOS管和N-MOS管的导通来控制IO口输出高电平还是低电平。这里要注意P-MOS管和N-MOS管,当设置输出的值为1的时候,P-MOS管处于开启状态,N-MOS管处于关闭状态,此时I/O端口的电平就由P-MOS管决定为高电平;当设置输出的值为0的时候,P-MOS管处于关闭状态,N-MOS管处于开启状态,此时I/O端口的电平就由N-MOS管决定为低电平。同时,I/O端口的电平也可以通过输入电路进行读取;注意,此时I/O端口的电平一定是输出的电平。

(7)GPIO_Mode_AF_OD 复用开漏输出:与开漏输出模式很是类似。只是输出的高低电平的来源,不是让CPU直接写输出数据寄存器,取而代之利用片上外设模块的复用功能输出来决定的。

(8)GPIO_Mode_AF_PP 复用推挽输出:与推挽输出模式很是类似。只是输出的高低电平的来源,不是让CPU直接写输出数据寄存器,取而代之利用片上外设模块的复用功能输出来决定的。

///关键函数
RCC_AHB1PeriphClockCmd() //使能IO口时钟 
GPIO_Init()    //   初始化IO口模式  PF9,PF10
GPIO_SetBits();//操作IO口,输出高电平
GPIO_ResetBits();//操作IO口,输出低电平

2.蜂鸣器---I/O口作为输出

///关键函数
RCC_AHB1PeriphClockCmd() //使能IO口时钟 
GPIO_Init()    //   初始化IO口模式  PF8
GPIO_SetBits();//操作IO口,输出高电平
GPIO_ResetBits();//操作IO口,输出低电平

3.按键输入实验---I/O口作为输入

1. 调函数GPIO_ReadInputDataBit()来读取 来读取 IO口的状态
2.按键扫描(两种模式合二为一,是否支持连续按)的一般思路       
u8 KEY_Scan(u8 mode)   {
 static u8 key_up=1;     
 if(mode==1) key_up=1;//支持连续按       
if(key_up &&  KEY按下){         
delay_ms(10);//延时,防抖         
key_up=0;//标记这次key已经按下         
if(KEY确实按下) {            
return KEY_VALUE;           }        
 }else if(KEY没有按下)  
key_up=1;        
return 没有按下     } 
//第一次按下之后,进入if,key_up=0;//标记这次key已经按下 此时静态区存储的key_up=0,那么就无法进入if了

4.STM32时钟系统

(1)RTC:实时时钟

RCC:时钟配置,控制提供给各模块时钟信号的通断

任何一个外设在使用之前,必须首先使能其相应的时钟!!!!!

(2)时钟树

STM32 5个时钟源:HSIHSELSILSEPLL  STM32时钟系统主要的目的就是给相对独立的外设模块提供时钟,就是兼容不同速度的外设

所有外设时钟默认都是关闭状态(disable)当我们使用某个外设就要开启这个外设的时钟(enable)

系统时钟SYSCLK可来源于三个时钟源:

①、HSI振荡器时钟        

②、HSE振荡器时钟        

③、PLL时钟

STM32F4时钟信号输出MCO1(PA8)和MCO2(PC9)。

MCO1:用户可以配置预分频器(1~5)向MCO1引脚PA8输出4个不同的时钟源:  

HIS  

LSE  

HSE  

PLL

MCO2:用户可以配置预分频器(1~5)向MCO2引脚PC9输出4个不同的时钟源:

HSE

PLL

SYSCLK

PLL

I2S  

MCO最大输出时钟不超过100MHz

5.SystemInit()

位置:UESR  system_stm32f4xx.c

系统在调用main函数之前调用系统初始化函数

初始化之后的状态:   

 SYSCLK(系统时钟) =168MHz

AHB总线时钟(HCLK=SYSCLK)=168MHz

APB1总线时钟(PCLK1=SYSCLK/4) =42MHz     

APB2总线时钟(PCLK2=SYSCLK/2)=84MHz

PLL主时钟 =168MHz

初始化之后可以通过变量SystemCoreClock获取系统变量。如果SYSCLK=168MHz,那么变量SystemCoreClock=168000000。

6.Systick定时器

(1)用途:

  • 没有操作系统:只用于延时
  • 有操作系统(ucos2 ucos3 freertos....):为操作系统提供精准的定时中断(1ms~50ms)

(2)24位,只能递减,存在于内核,嵌套在NVIC中,到0从reload寄存器中取初值 ,重新计时,即使在睡眠的状态下也工作。

(3)要使用systick定时器,只需调用SysTick_Config(uint32_t ticks)函数即可,函数自动完成:重装载值的装载,时钟源选择,计数寄存器复位,中断优先级的设置(最低),开中断,开始计数的工作。

        2)要修改时钟源调用SysTick_CLKSourceConfig(uint32_t SysTick_CLKSource),也可按照SysTick_Config()中默认设置FCLK不变。

        3)要修改中断优先级调用 void NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority)

(4)应用说明:

        1)因systick是一个24位的定时器,故重装值最大值为2的24次方=16 777 215,要注意不要超出这个值。

        2)systick是cortex_m3的标配,不是外设。故不需要在RCC寄存器组打开他的时钟。

        3)每次systick溢出后会置位计数标志位和中断标志位,计数标志位在计数器重装载后被清除,而中断标志位也会随着中断服务程序的响应被清除,所以这两个标志位都不需要手动清除。

        4)采用使用库函数的方法,只能采用中断的方法响应定时器计时时间到,如要采用查询的方法,那只能采用设置systick的寄存器的方法,具体操作以后再做分析。

//相关函数
SysTick_CLKSourceConfig()    //Systick时钟源选择  misc.c文件中

SysTick_Config(uint32_t ticks) //初始化systick,时钟为HCLK,并开启中断
                                                    //core_cm3.h/core_cm4.h文件中

7.IO口引脚复用和映射

1. 端口复用定义STM32有很多的内置外设,这些外设的外部引脚都是与GPIO复用。也就是说,一个GPIO如果可以复用为内置外设的功能引脚,那么当这个GPIO作为内置外设使用的时候,就叫做复用。
2. 作用最大限度的利用端口资源

3.原理

STM32F4系列微 控制器IO引脚通过一个复用器连接到内置外设或模块。该复用器一次只允许一个外设的复用功能(AF)连接到对应的IO口。这样可以确保共用同一个IO引脚的外设之间不会发生冲突。

每个IO引脚都有一个复用器,该复用器采用16路复用功能输入(AF0AF15),可通过GPIOx_AFRL(针对引脚0-7)GPIOx_AFRH(针对引脚8-15)寄存器对这些输入进行配置,每四位控制一路复用。

4.在数据手册中有引脚功能详细描述

STM32F40x pin and ball definitions

5.例子

/*以PA9,PA10配置为串口1为例
时钟源的选择以及时钟使能等函数都是在 RCC 相关固件库文件 stm32f4xx_rcc.h 和 stm32f4xx_rcc.c 中声明和定义的。*/

RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA,ENABLE); //使能GPIOA时钟 ① RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);//使能USART1时钟 ②   

//USART1端口配置③
GPIO_InitTypeDef  GPIO_InitStructure;
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复用为USART1 GPIO_PinAFConfig(GPIOA,GPIO_PinSource10,GPIO_AF_USART1); //GPIOA10复用为USART1 

 8.NVIC中断优先级管理

 1.要产生中断,必须先配置好并使能中断线。根据需要的边沿检测设置 2 个触发寄存器,同时在

中断屏蔽寄存器的相应位写“ 1 ”使能中断请求。当外部中断线上出现选定信号沿时,便会产
生中断请求,对应的挂起位也会置 1 。在挂起寄存器的对应位写“ 1 ”,将清除该中断请求。
要产生事件,必须先配置好并使能事件线。根据需要的边沿检测设置 2 个触发寄存器,同时
在事件屏蔽寄存器的相应位写“ 1 ”允许事件请求。当事件线上出现选定信号沿时,便会产
生事件脉冲,对应的挂起位不会置 1
通过在软件中对软件中断 / 事件寄存器写“ 1 ”,也可以产生中断 / 事件请求。

2.中断类型和说明————中文参考手册-向量表(表45 46)

中断管理方法:NVIC中断优先级分组

首先,对STM32中断进行分组,组0~4。同时,对每个中断设置一个抢占优先级和一个响应优先级值。
分组配置是在寄存器SCB->AIRCR中配置:

3.抢占优先级 & 响应优先级区别:

先比较抢占优先级,高的抢占优先级可以打断低的

抢占相等时,比较响应优先级,高的响应优先级先进行中断,但是高的响应优先级无法抢占已经开始的低的响应优先级中断

//中断优先级设置步骤NVIC(函数在FWLIB  misc.c):
//中断类型和服务函数(在core启动文件startup_stm32f40_41xx.c)

//系统运行后先设置中断优先级分组。调用函数: 
void NVIC_PriorityGroupConfig(uint32_t NVIC_PriorityGroup);  
//整个系统执行过程中,只设置一次中断分组。 

//②针对每个中断,设置对应的抢占优先级和响应优先级: 
void NVIC_Init(NVIC_InitTypeDef* NVIC_InitStruct);

 //③ 如果需要挂起/解挂,查看中断当前激活状态,分别调用相关函数即可。

9.USART串口通信

1.串口:数据传输,进行通信

2.常见通信模式:

全双工都是要有独立的 发送引脚和接收引脚

同步通信都要有 同步时钟

3.UART异步通信:通过RS232转换器使得双方TTL(电平信号)相同

4.USART_RX_STA接收状态标记

//串口配置的一般步骤,串口是一个外设
//串口时钟使能:
RCC_APBxPeriphClockCmd(); 
     
//GPIO时钟使能:
RCC_AHB1PeriphClockCmd(); 
 
//引脚复用映射:      
GPIO_PinAFConfig(); 

//GPIO端口模式设置,模式设置为(复用)GPIO_Mode_AF:
GPIO_Init();  

//串口参数初始化:
USART_Init(); 
typedef struct{
    uint32_t USART_BaudRate;//波特率
    uint32_t USART_WordLength;//字长
    uint32_t USART_StopBits;//停止位
    uint32_t USART_Parity;//校验位
    uint32_t USART_Mode;//USART模式
    uint32_t USART_HardwareFlowControl;//硬件流控制
}USART_InitTypeDef

//开启中断并且初始化NVIC(如果需要开启中断才需要这个步骤)       
NVIC_Init();     
  
//使能串口相关中断 
USART_ITConfig();

//使能串口:
USART_Cmd(); 

//编写中断处理函数:
USARTx_IRQHandler();

//串口数据收发: 
void USART_SendData();//发送数据到串口,DR 
uint16_t USART_ReceiveData();//接受数据,从DR读取接受到的数据 

//串口传输状态获取: 
FlagStatus USART_GetFlagStatus();//获取状态标志位 
void USART_ClearFlag();//清除状态标志位 
ITStatus USART_GetITStatus();//获取中断状态标志位 
void USART_ClearITPendingBit();//清除中断状态标志位 

10.外部中断实验EXIT

1.概述

STM32F4的每个IO都可以作为外部中断输入。

 STM32F4的中断控制器支持22个外部中断/事件请求:

EXTI线0~15:对应外部IO口的输入中断。每个外部中断线可以独立的配置触发方式(上升沿,下降沿或者双边沿触发),触发/屏蔽,专用的状态位。

IO口映射到外部中断线,通过根据引脚的序号不同将众多中断触发源分成不同的组,比如:PA0PB0PC0PD0PE0PF0PG0为第一组,每一组中同时只能有一个中断触发源工作,那么,最多工作的也就是16个外部中断。可以配置子优先级和抢占优先级

2.

IO口外部中断在中断向量表中只分配了7个中断向量,也就是只能使用7个中断服务函数。

EXTI0_IRQHandler          

EXTI1_IRQHandler

EXTI2_IRQHandler          

EXTI3_IRQHandler          

EXTI4_IRQHandler          

EXTI9_5_IRQHandler        

EXTI15_10_IRQHandler  

//外部中断配置的一般步骤
//1.使能SYSCFG时钟(时钟使能函数在FWLIB中rcc.h中):           RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE);
//2.初始化IO口为输入。        
GPIO_Init(); 
//3.设置IO口与中断线的映射关系(syscfg.h文件中)。
void SYSCFG_EXTILineConfig(); 
//初始化线上中断,设置触发条件等。 
EXTI_Init();
typedef struct {  
 uint32_t EXTI_Line;   //指定要配置的中断线              
 EXTIMode_TypeDef EXTI_Mode;   //模式:事件 OR中断   
 EXTITrigger_TypeDef EXTI_Trigger;//触发方式:上升沿/下降沿/双沿触发  
 FunctionalState EXTI_LineCmd;  //使能 OR失能 }EXTI_InitTypeDef; 
//配置中断分组(NVIC),并使能中断(NVIC_InitStructure.NVIC_IRQChannel = EXTI0_IRQn;//外部中断0  //在usart.c中stm32f4xx.h文件中找中断类型)。        
NVIC_Init(); 
//编写中断服务函数(在core文件中startup_stm32f40_41xxx.s启动文件中)。      
void EXTIx_IRQHandler(); 
//清除中断标志位       
EXTI_ClearITPendingBit();

11.IWDG独立看门狗实验

1.IWDG是一种外设---硬件定时器,用于监视系统的运行情况,如果系统由于某种原因(如软件错误、死循环等)导致停止响应,独立看门狗可以在预设的时间内没有收到系统的喂狗信号时,自动触发系统复位,从而确保系统的可靠性和稳定性。

STM32F4 的独立看门狗由内部专门的 32Khz 低速时钟( LSI )驱动,即使主时钟发生故障,
它也仍然有效。

2.独立看门狗通常由以下几个部分组成:

  1. 计数器(Counter):用于计数的硬件定时器,可以在设定的时间段内进行计数。

  2. 预分频器(Prescaler):用于将系统时钟频率分频,从而控制计数器的计数速度。

  3. 喂狗信号(Watchdog Refresh):由软件定时发送给独立看门狗,表示系统正常运行,否则在计数器超时时会触发看门狗复位。

3.运行机制:

键值寄存器IWDG_KR: 0~15位有效

预分频寄存器IWDG_PR:0~2位有效。具有写保护功能,要操作先取消写保护

重装载寄存器IWDG_RLR:0~11位有效。具有写保护功能,要操作先取消写保护。

状态寄存器IWDG_SR:0~1位有效

在键值寄存器(IWDG_KR)中写入0xCCCC,开始启用独立看门狗。此时计数器开始从其复位值0xFFF递减,当计数器值计数到尾值0x000时会产生一个复位信号(IWDG_RESET)。

无论何时,只要在键值寄存器IWDG_KR中写入0xAAAA(通常说的喂狗), 自动重装载寄存器IWDG_RLR的值就会重新加载到计数器,从而避免看门狗复位。

如果程序异常,就无法正常喂狗,从而系统复位。

4.溢出时间:确定了系统在未收到喂狗信号的情况下,独立看门狗将保持系统复位之前的等待时间。

溢出时间计算

prer:预分频系数

时钟频率LSI=32K, 一个看门狗时钟周期就是最短超时时间。

最长超时时间= (IWDG_RLR寄存器最大值)X看门狗时钟周期

  Tout=((4×2^prer) ×rlr) /32 (M4)

//独立看门狗操作步骤
void IWDG_Init(u8 prer,u16 rlr)  //预分频系数和重装载值
//1.取消寄存器写保护:      
 IWDG_WriteAccessCmd(); 
// 设置独立看门狗的预分频系数,确定时钟:      
IWDG_SetPrescaler(); 
//设置看门狗重装载值,确定溢出时间:     
IWDG_SetReload(); 
//应用程序喂狗,把RLD初值先装进去,不用从一个随意数字开始倒数:    
IWDG_ReloadCounter();  
//使能看门狗     
IWDG_Enable(); 
//喂独立看门狗
void IWDG_Feed(void)
{
	IWDG_ReloadCounter();//reload
}

12.通用定时器

1.STM32的通用定时器是一种非常灵活的外设,它们为STM32微控制器提供了广泛的定时和计数功能。虽然STM32微控制器内部有系统时钟用于提供基础的时钟信号,支持CPU运行和管理各种内部外设的时钟,但通用定时器提供的功能远不止于此。

2.定时器功能

  1. PWM(脉冲宽度调制)输出:通用定时器可以生成PWM信号,这在电机控制、LED亮度调节等应用中非常有用。

  2. 输入捕获:通用定时器可以捕获外部信号的时间特性,如频率和脉宽,这对于测量外部信号或实现高精度时间事件非常重要。

  3. 时间基准和延时:尽管有系统时钟,但通用定时器可以用来创建精确的时间基准和延时,这在需要精确控制时间间隔的任务中非常重要,例如任务调度或时间戳记录。

  4. 编码器接口:一些通用定时器可以与旋转编码器接口,用于测量旋转速度和位置,这在电机控制和定位系统中非常有用。

  5. 计数模式:通用定时器可以在不同的计数模式下工作,包括向上计数、向下计数和中心对齐模式,以支持各种应用需求。

三、实验-----中级

1.ADC

1.模数转换器:是指将连续变量的模拟信号转换为离散的数字信号的器件。

2.ADC外部通道和引脚对应关系:

   

3.ADC框图

   

   

4.规则通道组和注入通道组

  • 规则通道多达16个通道,而注入通道只有4个通道。
  • 每个注入通道均有一个用于储存转换结果的注入数据寄存器,而所有规则通道均共用一个规则数据寄存器。
  • 注入通道可以中断规则通道的转换,然后再恢复规则通道的转换。

5.STM32F4的ADC的各通道可以单次,连续,扫描 或者间断模式执行

6.ADC时钟配置

 

7.ADC采样时间

//ADC1的通道5(PA5)进行单次转化

//开启PA口时钟和ADC1时钟,设置PA1为模拟输入。
RCC_AHB1PeriphClockCmd (RCC_AHB1Periph_GPIOA, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);  
GPIO_Init();      

//复位ADC1,同时设置ADC1分频因子。
ADC_DeInit(ADC1);

//初始化ADC_CCR寄存器。
ADC_CommonInit();

//初始化ADC1参数,设置ADC1的工作模式以及规则序列的相关信息。
void ADC_Init(ADC_TypeDef* ADCx, ADC_InitTypeDef* ADC_InitStruct);

// 使能ADC
ADC_Cmd(ADC1, ENABLE);

//配置规则通道参数:
ADC_RegularChannelConfig();

//开启软件转换:
ADC_SoftwareStartConvCmd(ADC1);

// 等待转换完成,读取ADC值。
   ADC_GetConversionValue(ADC1);

2.内部温度传感器

1.有一个内部的温度传感器,可以用来测量CPU及周围的温度(TA)。

该温度传感器在内部和ADCx_IN16(F40xx/F41xx)或者ADCx_IN18(F42xx/F43xx)输入通道相连接,此通道把传感器输出的电压转换成数字值。

温度传感器模拟输入推荐采样时间是17.1μs。

内部温度传感器更适合于检测温度的变化,而不是测量绝对温度。

2.激活ADC的内部通道,这里通过ADC_CCR的TSVREFE位(bit23)设置。设置该位为1则启用内部温度传感器。

STM32F407的内部温度传感器固定的连接在ADC的通道16上,所以,我们在设置好ADC之后只要读取通道16的值,就是温度传感器返回来的电压值了。

3.计算公式如下:     

T(℃)={(get(temperate)-Vsense)/Avg_Slope}+25

上式中: V25=0.76 

                Avg_Slope=0.00025

4.开启内部温度传感器步骤:

        选择ADC_IN16或者ADC_IN16输入通道

        设置采样时间大于17.1us。 

        设置ADC_CCR的TSVREFE位,打开内部温度传感器

        设置ADC_CR2的SWSTART位启动转换

        读取ADC结果

        计算

3.光敏传感器(Light Sensor)

1.光敏传感器是利用光敏元件将光信号转换为电信号
的传感器。

2.照射光敏二极管的光强不同,通过光敏二极管的电流大小
就不同,所以可以通过检测电流大小,达到检测光强的目的。

利用这个电流变化,我们串接一个电阻,就可以转换成电压的变化,
从而通过 ADC 读取电压值,判断外部光线的强弱。

3.硬件连接(PF7)

4.DAC

1.数模转换器:是 12 位数字输入,电压输出型的 DAC 。DAC 模块有 2 个输出通道,每个通道都有单独的转换器。

2.STM32 的 DAC 模块主要特点有:
① 2 个 DAC 转换器:每个转换器对应 1 个输出通道
② 8 位或者 12 位单调输出
③ 12 位模式下数据左对齐或者右对齐
④ 同步更新功能
⑤ 噪声波形生成
⑥ 三角波形生成
⑦ 双 DAC 通道同时或者分别转换
⑧ 每个通道都有 DMA 功能

3.DAC框图

4.引脚

DAC_OUT1 ->PA4
DAC_OUT2 ->PA5

5.

5.PWM DAC实验

1.通过PWM信号来来改变输出的电压值

2.PWM原理:

(1)周期一定---ARR存入的计数值,高低电平占空比可以调节---CCR值改变

(2)T:stm32定时器计数周期,N是ARR-1的值,n是CCRx的值(一个周期中高电平计数脉冲个数),k为谐波次数,t为时间。

(3)输出的电压有直流分量、一次谐波分量、二次谐波分量。通过低通滤波器(电容)大致只剩下直流电流。

(4)硬件

6.DMA

1.直接存储器访问:数据直接传输,无需处理时,使用DMA直接将数据从地址A复制到地址B,通过硬件的形式为RAM和IO外设数据传输开辟了一条新通道,无需再通过CPU,减轻了CPU的负担。

2.主要特性:

(1)stm32最多有两个DMA,每个DMA控制器有8个数据流,每个数据流有8个外设请求通道。

(2)8个数据流中的每一个都连接到专用硬件DMA通道,DMA数据流请求之间的优先级可用软件编程,软件优先级相同时可以通过硬件决定优先级。

(3)通过硬件可以将每个数据流配置为支持外设到存储器,存储器到外设,存储器到存储器的常规通道,也支持存储器方双缓冲区通道。  (S(源)→D(目的))

(4)每个数据流有单独的四级32位先进先出存储器缓冲区(FIFO),可用于FIFO模式或直接模式:

1)FIFO模式:可通过软件将阈值级别选取为FIFO大小的1/4,1/2,3/4,全部数据??放入FIFO

2)直接模式:每个DMA请求会立即启动对存储器的传输。(禁用FIFO)下将DMA请求配置为以存储器到外设模式传输数据时,DMA仅会将一个数据从存储器预加载到内部FIFO,从而确保一旦外设出发DMA请求立即传输数据。

(5)独立的源和目标传输宽度(字节8,半字16,字32):源和目标数据宽度不一致时,DMA自动封装/解封必要的传输数据来优化带宽(例S8→D32,每次传放入缓冲区,传满四次后一起发送给目标)。这个特性仅在FIFO模式下可用。

(6)要传输的数据项数目可由DMA控制器或外设管理

1)DMA流控制器:要传输的数据项目1~65535,可用软件编程

2)外设流控制器:外设通过硬件发出传输结束信号

(7)5个标志事件:DMA半传输、DMA传输完成、DMA传输错误、DMA FIFO错误、直接模式错误,产生每个数据流的单个中断请求。

(8)每个数据流都支持循环缓冲区管理

(9)支持4个、8个、16个节拍的增量突发传输。突发增量大小可由软件配置,通常等于外设FIFO大小的一半

3.DMA框图:

4.通道选择:

5.DMA数据流

6.DMA事物:

(1)传输时

         1)确定S和D的基地址

         2)加载数据

         3)确定传输方向

7.仲裁器

软件优先级→DMA_SxCR寄存器

8.指针递增

DMA_SxCR寄存器

9.循环模式

DMA_SxCR寄存器

10.数据宽度封装/解封

11.单次传输和突发传输

12.双缓冲区模式

存储器缓冲区1在传输数据的同时,存储器缓冲区2在填充数据


13.DMA中断

14.流配置过程

通道
优先级
数据传输方向
存储器 / 外设 数据宽度
存储器 / 外设 地址是否增量
循环模式
数据传输量
DMA配置程序过程(串口发送DMA)
//① 使能DMA时钟
   RCC_AHB1PeriphClockCmd();
//② 初始化DMA通道参数
   DMA_Init();
//③使能串口DMA发送,串口DMA使能函数:
  USART_DMACmd();
//④查询DMA的EN位,确保数据流就绪,可以配置
   DMA_GetCmdStatus();
//⑤设置通道当前剩余数据量
   DMA_SetCurrDataCounter();
//⑥使能DMA1通道,启动传输。
   DMA_Cmd();
//⑤查询DMA传输状态
  DMA_GetFlagStatus();
//⑥获取/设置通道当前剩余数据量:
  DMA_GetCurrDataCounter();
  
常用外设DMA使能库函数
void USART_DMACmd(USART_TypeDef* USARTx, uint16_t USART_DMAReq,
                                                                             FunctionalState NewState);
void ADC_DMACmd(ADC_TypeDef* ADCx, FunctionalState NewState);
void DAC_DMACmd(uint32_t DAC_Channel, FunctionalState NewState);
void I2C_DMACmd(I2C_TypeDef* I2Cx, FunctionalState NewState);
void SDIO_DMACmd(FunctionalState NewState);
void SPI_I2S_DMACmd(SPI_TypeDef* SPIx, uint16_t SPI_I2S_DMAReq, 
                                                                          FunctionalState NewState);

void TIM_DMAConfig(TIM_TypeDef* TIMx, uint16_t TIM_DMABase, 
                                                                      uint16_t TIM_DMABurstLength)
void TIM_DMACmd(TIM_TypeDef* TIMx, uint16_t TIM_DMASource,
                                                                       FunctionalState NewState);

7.I2C通信

1.IIC通信:半双工同步通信

两根线实现通信1)数据线SDA      时钟线SCL    可以发送和接收数据

高速IIC总线一般可达400kbps

2.IIC协议:

(1)空闲状态

SDA和SCL两条信号线同时处于高电平

(2)起始信号和停止信号

SCL处于高电平期间

1)起始:SDA由高到低跳变

2)停止:SDA由低到高跳变

3)应答信号

发送器每发送一个字节,就在时钟脉冲9期间释放数据线,由接收器反馈一个应答信号。

有效应答位ACK的要求是,接收器在第9个时钟脉冲之前的低电平期间将SDA线拉低,并且确保在该时钟的高电平期间为稳定的低电平。

4)数据的有效性

在SCL高电平期间传输数据,数据要保持稳定

数据在SCL的上升沿到来之前就需准备好。并在在下降沿到来之前必须稳定。

5)数据的传送

在I2C总线上传送的每一位数据都有一个时钟脉冲相对应(或同步控制),即在SCL串行时钟的配合下,在SDA上逐位地串行传送每一位数据。数据位的传输是边沿触发。

3.分析IIC底层驱动程序

(1)EEPROM(24C02)是指带电可擦可编程只读存储器。是一种掉电后数据不丢失的存储芯片。

正点原子中A2=A1=A0=0:

读的时候

Device Address=0xA1

写的时候

Device Address=0xA0

(2)24C02字节写时序:要知道写入设备地址,所写数据应写入的地址,所要写的数据

(3)24C02读时序:要先写入所要读的设备地址,读的数据所在地址,再读取设备地址,读取数据

8.SPI

1.SPI通信:全双工同步通信。读一个字节的同时发送一个字节。主要应用在 EEPROMFLASH,实时时钟,AD转换器,还有数字信号处理器和数字信号解码器之间

2.内部结构图:

SPI接口一般使用4条线通信:

MISO 主设备数据输入,从设备数据输出。

MOSI 主设备数据输出,从设备数据输入。

SCLK时钟信号,由主设备产生。

CS从设备片选信号,由主设备控制。

3.原理总结:

①硬件上为4根线。
②主机和从机都有一个串行移位寄存器,主机通过向它的SPI串行寄存器写入一个字节来发起一次传输。
③串行移位寄存器通过MOSI信号线将字节传送给从机,从机也将自己的串行移位寄存器中的内容通过MISO信号线返回给主机。这样,两个移位寄存器中的内容就被交换。
④外设的写操作和读操作是同步完成的。如果只进行写操作,主机只需忽略接收到的字节;反之,若主机要读取从机的一个字节,就必须发送一个空字节来引发从机的传输。

4.时钟的相位和极性(SPI_CR寄存器):

(1)CPOL(时钟极性):控制没有数据传输时空闲状态下电平

(2)CPHA (时钟相位):CPHA=0,数据在第一边沿被采集;CPHA=1,数据在第二个边沿被采集;

   

5.数据帧格式

6.状态标志位

7.SPI中断

8.硬件连接

程序配置过程
//①使能SPIx和IO口时钟
    RCC_AHBxPeriphClockCmd() / RCC_APBxPeriphClockCmd();
//②初始化IO口为复用功能
    void GPIO_Init(GPIO_TypeDef* GPIOx, GPIO_InitTypeDef* GPIO_InitStruct);
//③设置引脚复用映射:
    GPIO_PinAFConfig();
//②初始化SPIx,设置SPIx工作模式
    void SPI_Init(SPI_TypeDef* SPIx, SPI_InitTypeDef* SPI_InitStruct);
//③使能SPIx
    void SPI_Cmd(SPI_TypeDef* SPIx, FunctionalState NewState);
//④SPI传输数据
    void SPI_I2S_SendData(SPI_TypeDef* SPIx, uint16_t Data);
    uint16_t SPI_I2S_ReceiveData(SPI_TypeDef* SPIx) ;
//⑤查看SPI传输状态
   SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_RXNE);

9.485通信实验

1.串口:串口是一种接口标准,它规定了接口的电气标准,简单说只是物理层的一个标准。典型的串行通讯标准是RS232RS485,它们定义了电压,阻抗等,但不对软件协议给予定义。

2.RS485特点:

接口电平低,不易损坏芯片。 RS485 的电气特性:逻辑“ 1 ”以两线间的电压差为 +(2~6)V 表示;逻辑“ 0 ”以两线间的电压差为 -(2~6)V 表示。接口信号电平比 RS232 降低了,不易损坏接口电路的芯片

传输速率高。10米时,RS485的数据最高传输速率可达35Mbps,在1200m时,

     传输速度可达100Kbps

抗干扰能力强。RS485接口是采用平衡驱动器和差分接收器的组合,抗共模干

    扰能力增强,即抗噪声干扰性好。

传输距离远,支持节点多。RS485总线最长可以传输1200m以上(速率

   100Kbps)一般最大支持32个节点,如果使用特制的485芯片,可以达到128

   或者256个节点,最大的可以支持到400个节点。

3.总结

UART是生成串行通信时序的硬件模块,而TTL、RS232、RS422和RS485则分别代表了不同的电气接口标准和逻辑电平标准。在实际应用中,UART产生的TTL电平信号通常需要通过电平转换器转化为RS232、RS422或RS485标准的信号,以便在不同的物理环境中进行可靠的串行通信。
 

10.CAN通信

1.控制器区域网络

1.SDIO

1.EEPROM(24C02)是指带电可擦可编程只读存储器。是一种掉电后数据不丢失的存储芯片。

正点原子中A2=A1=A0=0:

读的时候

Device Address=0xA1

写的时候

Device Address=0xA0

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值