STM32介绍
基于ARM Cortex-M内核开发的32位微控制器
STM32F103C8T6
- 内核:ARM Cortex-M3
- 主频:72MHz
- RAM:20K(SRAM)
- ROM:64K(Flash)
- 供电:2.0~3.6V(标准3.3V)
- 封装:LQFP48
片上资源/外设
- NVIC嵌套向量中断控制器:内核里面用于管理中断的设备,比如配置中断优先级
- SysTick系统滴答定时器:内核里的定时器,给操作系统(如FreeRTOS、UCOS)提供定时服务,定时进行任务切换的功能
- RCC复位和时钟控制:外设在上电的情况下默认没有时钟,不给时钟情况下,操作无效,外设也不会工作,这样的目的是降低功耗。所以在操作外设前要先操作时钟,使用RCC完成时钟的使能。
- GPIO通用IO口
- AFIO复用IO口:完成复用功能端口的重定义,还有中断端口的配置
- EXTI外部中断:配置好外部中断后,当引脚有电平变化时,可以触发中断,让CPU来处理任务
- TIM定时器:高级定时器、通用定时器、基本定时器,不仅可以完成定时中断,还可以完成测频率、生成PWM波形、配置成专用的编码器接口等
- ADC模数转换器:STM32内置了12位的AD转换器,可以直接读取IO口的模拟电压值,无需外部连接AD芯片
- DMA直接内存访问:帮助CPU完成大量数据搬运功能
- USART同步/异步串口通信
- I2C通信、SPI通信:通信协议
- CAN通信:一般用于汽车领域
- RTC实时时钟:在STM32内部完成年月日、时分秒的计时功能,且可以接外部备用电池,即使掉电也能正常运行
- CRC校验:用于判断数据的正确性
- PWR电源控制:可以让芯片进入睡眠模式等状态,来达到省电的目的
- BKP备份寄存器:存储器,当系统掉电时,仍可由备用电池保持数据
- IWDG独立看门狗、WWDG窗口看门狗:当单片机因为电磁干扰死机或者程序设计不合理出现死循环时,看门狗可以及时复位芯片,保持系统稳定
- DAC数模转换器,可以在IO口直接输出模拟电压
- FSMC可变静态存储控制器:用于扩展内存,或者配置成其他总线协议,用于某些硬件操作
- USB OTG:USB主机接口,用OTG功能,可以让STM32作为USB主机去读取其他USB设备
系统结构
- 左上方Cortex-M3内核,引出3条总线,ICode指令总线、DCode数据总线、System系统总线,ICode与DCode主要用于连接Flash闪存,Flash里是编写的程序,ICode用来加载程序指令,DCode用来加载数据,System系统总线连接到其他上面,比如SRAM存储程序运行数据,AHB(先进高性能总线)系统总线用于挂在主要的外设,APB(先进外设总线)用于连接一般外设,由于AHB和APB的总线协议、总线速度、还有数据传送格式的差异,所以中间需要加两个桥接,来完成数据的转换和缓存。
- DMA可看作内核CPU的小秘书,比如一些大量的数据搬运。DMA通过DMA总线连接到总线矩阵上,可以拥有和CPU一样的总线控制权,用于访问这些外设。当需要DMA搬运数据时,外设就会通过请求线发送DMA请求,然后DMA就会获得总线控制权,访问并转运数据, 整个过程无需CPU的参与。
引脚定义
红色是电源相关引脚,蓝色是最小系统相关引脚,绿色是IO口、功能口引脚
启动配置
一般情况下,程序都是在Flash程序存储器开始执行,但是某些情况下可以让程序在别的地方开始执行,用来完成特殊的功能。
最小系统电路
新建工程
- 建立工程文件夹,keil中新建工程、选择型号
- 工程文件夹中建立Start、Library、User等文件夹,复制固件库中的文件到工程文件中
- 工程里对应建立Start、Library、User等同名称的分组,然后将文件夹内的文件添加到工程分组里
- 工程选项,C/C++,Include Paths内声明所有包含头文件的文件夹
- 工程选项,C/C++,Define内定义USE_STDPERIPH_DRIVER
- 工程选项,Debug,下拉列表选择对应调试器,Settings,Flash Download里勾选Reset and Run
工程架构
C语言
宏定义
- 关键字:#define
- 用途:用一个字符串代替一个数字,便于理解防止出错;提取程序中经常出现的参数,便于快速修改
- 定义宏定义:#define ABC 12345
- 引用宏定义:int a = ABC;//等效int a = 12345;
typedef
- 用途:将一个比较长的变量类型名换个名字,便于使用
- 定义:typedef unsigned char uint8_t;
- 引用 :uint8_t a;//等效于unsigned char a;
结构体
- 关键字:struct
- 用途:数据打包,不同类型变量的集合
- 定义结构体变量 struct{char x;int y;float z;} StructName; 因为结构体变量类型较长,所以通常用typedef更改其变量类型名
- 引用结构体成员: StructName.x = ‘A’; pStructName->x = ‘A’;//pStructName为结构体的地址
枚举
- 关键字:enum
- 用途:定义一个取值受限制的整形变量,用于限制变量取值范围;宏定义的集合
- 定义枚举变量:enum{FALSE = 0 , TRUE = 1} EnumName;
- 引用枚举成员:EnumName = FALSE;
GPIO
GPIO简介
- General Purpose Input Output通用输入输出口
- 可配置为8种输入输出模式
- 引脚电平0-3.3V,部分引脚可容忍5V
- 输出模式下可控制端口输出高低电平,用来驱动LED、控制蜂鸣器、模拟通信协议输出时序
- 输入模式下可读取端口的高低电平或电压,用于读取按键输入,外界模块电平信号输入、ADC电压采集、模拟通信协议接收数据
GPIO 基本结构
在STM32中,所有GPIO都挂载在APB2外设总线上,其中GPIO名称按照GPIOA、GPIOB…….来标注,每个GPIO外设总共有16个引脚从0到15。
寄存器是特殊的存储器,内核可以通过APB2总线对寄存器进行读写,这样可以完成输出电平和读取电平的功能。寄存器的每一位对应一个引脚,其中输出寄存器写1,对应的引脚就会输出高电平,反之输出低电平;输入寄存器读取为1,就证明对应的端口目前是高电平,反之为低电平。由于STM32为32位的单片机,所以STM32内部的寄存器都是32位的,但是端口只有16位,该寄存器只有低16位对应的有端口,高16位没用到。寄存器只负责存储数据,如要进行其他操作,还需要驱动器来负责增大驱动能力。
GPIO位结构
左侧为三个寄存器,中间为驱动器,右侧为某一个IO口的引脚。
整体可分为两个部分,上面为输入部分,下面为输出部分。VDD、VSS的两个开关,是为了给输入提供一个默认的输入电平(上拉、下拉、浮空),因为对应一个数字的端口,输入不是高电平就是低电平,如果浮空,引脚的输入电平会受外界干扰而改变。上拉输入可称作是默认为高电平的输入模式,下拉输入是默认为低电平的输入模式。
输入部分:
TTL肖特基触发器,其实就是施密特触发器,对输入电压进行整形,当输入电压大于某一阈值,输出电压为高电平,当输入电压小于某一阈值,输出电压为低电平。可以有效避免因信号波动造成的输出抖动现象。
经过施密特触发器整形的波形可以直接写入输入数据寄存器了,再用程序读取输入寄存器对应某一位的数据,就可以知道端口的输入电平。
模拟输入连接到ADC上,因为ADC需要接受模拟量,所以要接触发器前面。
复用功能输入是连接到其他需要读取端口的外设上的,接触发器后面。
**输出部分:**由输出数据寄存器和片上外设控制
两种控制方式通过数据选择器连接到了输出控制部分,如果选择通过输出数据寄存器进行控制,就是普通的IO口输出,写这个数据寄存器的某一位就可以操作对应的某个端口了。
位设置/清除寄存器,可以单独操作输出数据寄存器的某一位,而不影响其他位。因为这个输出数据寄存器同时控制16个端口,并且这个寄存器只能整体读写,所以如果想单独控制其中某一个端口而不影响其他端口,需要特殊的操作方式(按位与、设置位设置/清除寄存器)。
通过信号来控制MOS管开关的导通和关闭,开关负责将IO口接到ADD或者VSS,可选择推挽、开漏或关闭三种输出方式。①在推挽输出模式下,PMOS和NMOS均有效,数据寄存器位1时,上管导通下管断开,输出直接接到VDD,就是输出高电平,反之输出低电平。在此模式下,STM32对IO口具有绝对的控制权。②在开漏输出模式下,PMOS无效,只有NMOS在工作,数据寄存器为1时,输出相当于断开也就是高阻模式,数据寄存器为0时,下管导通,输出直接接到VSS,也就是低电平。这种模式下,只有低电平有驱动能力,高电平没有驱动能力。可作为通信协议的驱动方式,在多机通信的情况下,这个模式可以避免各个设备的相互干扰,另外还可用于输出5V的电平信号③在关闭模式下,是当引脚配置为输入模式时,两个MOS管都无效,端口的电平由外部信号来控制。
8种工作模式
| 模式名称 | 性质 | 特征 |
|---|---|---|
| 浮空输入 | 数字输入 | 可读取引脚电平,若引脚悬空,则电平不确定 |
| 上拉输入 | 数字输入 | 可读取引脚电平,内部连接上拉电阻,悬空时默认高电平 |
| 下拉输入 | 数字输入 | 可读取引脚电平,内部连接下拉电阻,悬空时默认低电平 |
| 模拟输入 | 模拟输入 | GPIO无效,引脚直接接入内部ADC |
| 开漏输出 | 数字输出 | 可输出引脚电平,高电平为高阻态,低电平接VSS |
| 推挽输出 | 数字输出 | 可输出引脚电平,高电平接VDD,低电平接VSS |
| 复用开漏输出 | 数字输出 | 由片上外设控制,高电平为高阻态,低电平接VSS |
| 复用推挽输出 | 数字输出 | 由片上外设控制,高电平接VDD,低电平接VSS |
浮空输入、上拉输入、下拉输入的电路结构基本一致,区别就是上拉电阻和下拉电阻的连接。在输入模式下,输出驱动器断开,只能输入而不能输出
模拟输入,是ADC模数转换器的专属配置,输出断开,输入的施密特触发器也是关闭的无效状态
开漏/推挽输出的区别在于高电平,开漏是高阻态,推挽是VDD
复用开漏/推挽输出的结构如下,都由片上外设控制
常用函数以及样例
初始化样例
|
|
GPIO_Init需要输入两个参数,第一个参数是指定GPIOx(其中X可以为A…G),第二个参数是一个指向GPIO_InitTypeDef结构的指针,因此我们还需要定义一个结构体,通过GPIO_InitTypeDef的方式定义,定义后需要对三个参数进行设置:
- GPIO_Mode设置:也就是对工作模式进行选择,模拟输入AIN、浮空输入IN_FLOATING、下拉输入IPD、上拉输入IPU、开漏输出Out_OD、推挽输出Out_PP、复用开漏输出AF_OD、复用推挽输出AF_PP
- GPIO_Pin设置:也就是对引脚进行选择,可以从GPIO_Pin_0~GPIO_Pin_15,共16个引脚,也可以使用GPIO_Pin_All对所有引脚进行选择,也可以使用或(|)的方式进行选择,GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2,使用此方式对引脚012进行选择
- GPIO_Speed设置:输出速度可选择GPIO_Speed_10MHz,GPIO_Speed_2MHz,GPIO_Speed_50MHz
按样例定义完成后,GPIOB外设的12号引脚就自动被配置为推挽输出、50MHz的速度了,它内部的主要执行逻辑就是读取结构体的参数,执行判断和运算,最后写入到GPIO配置寄存器中
输出操作
常用的四个操作如下
|
|
- SetBits完成对某GPIO外设的某引脚置1
- ResetBits完成对某GPIO外设的某引脚置0
- WriteBit(GPIOx,GPIO_Pin_X,Bit_SET/Bit_RESET)
- Write第一个参数是选定一个GPIO外设,第二个参数是一个4位16进制数,为16个二进制,对应着16个端口,最低位为PA0,如0x0001对应
0000 0000 0000 0001即Pin0置1,0x0003对应0000 0000 0000 0011即Pin0\Pin1置1
输入操作
按键介绍
按键:常见的输入设备,按下导通,松手断开
按键抖动:由于按键内部使用的是机械式弹簧片来进行通断的,所以在按下和松手的瞬间会伴有一连串的抖动
初始化按键可采用上拉输入IPU
|
|
传感器介绍
传感器元件的电阻会随外界模拟量的变化而变化,通过与定值电阻分压即可得到模拟电压输入,再通过电压比较器进行二值化即可得到数字电压输出
硬件电路
下接按键方式(通常普遍采用)
若采用左侧方式,必须采用上拉输入,否则会出现引脚悬空,输出不确定
上接按键方式
连接方式:VCC接3.3V提供电源,GND接地,DO数字输出随便接一个端口,用于读取数字量,AO模拟输出。
传感器端口可采用上拉输入IPU
输入代码
带有Bit是只读取一个位,无Bit是读取一整个的,每一个都以0/1表示
|
|
OLED
样例
| 函数 | 作用 |
|---|---|
| OLED_Init(); | 初始化 |
| OLED_Clear(); | 清屏 |
| OLED_ShowChar(1, 1, ‘A’); | 显示一个字符 |
| OLED_ShowString(1, 3, “HelloWorld!”); | 显示字符串 |
| OLED_ShowNum(2, 1, 12345, 5); | 显示十进制数字 |
| OLED_ShowSignedNum(2, 7, -66, 2); | 显示有符号十进制数字 |
| OLED_ShowHexNum(3, 1, 0xAA55, 4); | 显示十六进制数字 |
| OLED_ShowBinNum(4, 1, 0xAA55, 16); | 显示二进制数字 |
中断系统
中断概念
- 中断:在主程序运行进程中,出现了特定的中断触发条件,使得CPU暂停当前正在运行的程序,转而去处理中断程序,处理完成后又返回原来被暂停的位置继续运行
- 中断优先级:当有多个中断源同时申请中断,CPU会根据中断源的轻重缓急进行裁决,优先响应更加紧急的中断源
- 中断嵌套:当一个中断程序正在运行时,又有新的更高优先级的中断源申请中断,CPU再次暂停当前中断程序,转而去处理新的中断程序,处理完成后依次进行返回
STM32中断
- 68个可屏蔽中断通道,包含EXTI、TIM、ADC、USART、SPI、I2C、RTC等多个外设
- 使用NVIC统一管理中断,每个中断通道都有16个可编程的优先等级,可对优先级进行分组,进一步设置抢占优先级和响应优先级
NVIC基本结构
- NVIC的中断优先级由优先级寄存器的4位(0~15)决定,这4位可以进行切分,分为高n位的抢占优先级和低4-n位的响应优先级
- 抢占优先级高的可以中断嵌套,响应优先级高的可以优先排队,抢占优先级和响应优先级均相同的按中断号排队
| 分组方式 | 抢占优先级 | 响应优先级 |
|---|---|---|
| 分组0 | 0位,取值为0 | 4位,取值为0~15 |
| 分组1 | 1位,取值为0~1 | 3位,取值为0~7 |
| 分组2 | 2位,取值为0~3 | 2位,取值为0~3 |
| 分组3 | 3位,取值为0~7 | 1位,取值为0~1 |
| 分组4 | 4位,取值为0~15 | 0位,取值为0 |
EXTI外部中断
- EXTI可以监测指定GPIO口的电平信号,当其指定的GPIO口产生电平变化时,EXTI将立即向NVIC发出中断申请,经过NVIC裁决后即可中断CPU主程序,使CPU执行EXTI对应的中断程序
- 支持的触发方式:上升沿/下降沿/双边沿/软件触发
- 支持的GPIO口:所有GPIO口,但相同的Pin不能同时触发中断
- 通道数:16个GPIO_Pin,外加PVD输出、RTC闹钟、USB唤醒、以太网唤醒
- 触发响应方式:中断响应/事件响应(中断响应是正常的流程,引脚电平变化触发中断;事件响应不会触发中断,而是触发别的外设操作,属于外设之间的联合工作)
旋转编码器
- 旋转编码器:用来测量位置、速度或旋转方向的装置,当其旋转轴旋转时,其输出端可以输出与旋转速度和方向对应的方波信号,读取方波信号的频率和相位信息即可得知旋转轴的速度和方向
- 类型:机械触点式/霍尔传感器式/光栅式
基本流程
-
RCC时钟启用
1 2 3RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);//启用GPIOB RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);//启用AFIO //EXTI与NVIC本身时钟就启用,无需启动 -
GPIO端口配置
1 2 3 4 5GPIO_InitTypeDef GPIO_InitStructure;//定义结构体 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; GPIO_InitStructure.GPIO_Pin = GPIO_Pin_14; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOB,&GPIO_InitStructure);//初始化 -
AFIO引脚选择
1GPIO_EXTILineConfig(GPIO_PortSourceGPIOB,GPIO_PinSource14);//14脚使用GPIOB的Pin14 -
EXTI配置
1 2 3 4 5 6EXTI_InitTypeDef EXTI_InitStructure;//定义结构体 EXTI_InitStructure.EXTI_Line = EXTI_Line14;//启用14引脚 EXTI_InitStructure.EXTI_LineCmd = ENABLE;//使能 EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;//中断响应 EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;//下降沿触发 EXTI_Init(&EXTI_InitStructure);//初始化 -
NVIC配置
1 2 3 4 5 6 7NVIC_InitTypeDef NVIC_InitStructure;//定义结构体 NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//分组形式,2位抢占、2位响应 NVIC_InitStructure.NVIC_IRQChannel = EXTI15_10_IRQn;//指定要启用的通道 NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;//使能 NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;//抢占优先级 NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;//响应优先级 NVIC_Init(&NVIC_InitStructure);//初始化 -
NVIC配置后,可配置中断响应函数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40//对射式红外传感器计次 void EXTI15_10_IRQHandler(void)//名称与通道名对应 { if(EXTI_GetITStatus(EXTI_Line14) == SET) { CountSensor_Count++; Delay_ms(20); EXTI_ClearITPendingBit(EXTI_Line14); } } ------------------------------------------------------------ //旋转编码器计次 int16_t Encoder_Get(void) { int16_t Temp; Temp = Encoder_Count; Encoder_Count = 0; return Temp; } void EXTI0_IRQHandler(void) { if(EXTI_GetITStatus(EXTI_Line0) == SET) { if(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_1) == 0) Encoder_Count --; EXTI_ClearITPendingBit(EXTI_Line0); } } void EXTI1_IRQHandler(void) { if(EXTI_GetITStatus(EXTI_Line1) == SET) { if(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_0) == 0) Encoder_Count ++; EXTI_ClearITPendingBit(EXTI_Line1); } }
TIM定时器
简介
- 定时器可以对输入的时钟进行计数,并在计数值达到设定值时触发中断
- 16位计数器、预分频器、自动重装寄存器的时基单元,在72MHz计数时钟下可以实现最大59.65s的定时
- 不仅具备基本的定时中断功能,而且还包含内外时钟源选择、输入捕获、输出比较、编码器接口、主从触发模式等多种功能
- 根据复杂度和应用场景分为了高级定时器、通用定时器、基本定时器三种类型
| 类型 | 编号 | 总线 | 功能 |
|---|---|---|---|
| 高级定时器 | TIM1、TIM8 | APB2 | 拥有通用定时器全部功能,并额外具有重复计数器、死区生成、互补输出、刹车输入等功能 |
| 通用定时器 | TIM2、TIM3、TIM4、TIM5 | APB1 | 拥有基本定时器全部功能,并额外具有内外时钟源选择、输入捕获、输出比较、编码器接口、主从触发模式等功能 |
| 基本定时器 | TIM6、TIM7 | APB1 | 拥有定时中断、主模式触发DAC的功能 |
- STM32F103C8T6定时器资源:TIM1、TIM2、TIM3、TIM4
- 基本计时器只支持向上计数,通用定时器和高级定时器支持向上计数、向下计数、中央对齐三种模式
定时中断基本结构如下
预分频器时序如下(PSC)
计数器计数频率:CK_CNT = CK_PSC / (PSC + 1)
计数器时序如下(ARR)
计数器溢出频率:CK_CNT_OV = CK_CNT / (ARR + 1)= CK_PSC / (PSC + 1) / (ARR + 1)
计数器无预装与有预装时序
定时中断
-
RCC使能
1RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE); -
内部时钟模式
1TIM_InternalClockConfig(TIM2);//内部时钟 -
时基单元
1 2 3 4 5 6 7TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;//定义结构体 TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;//时钟分频 TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;//计数模式 TIM_TimeBaseInitStructure.TIM_Period = 10000-1;//周期 TIM_TimeBaseInitStructure.TIM_Prescaler = 7200-1;//预分频器 TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0;//重计数值 TIM_TimeBaseInit(TIM2,&TIM_TimeBaseInitStructure); -
使能中断
1TIM_ITConfig(TIM2,TIM_IT_Update,ENABLE);//更新时触发中断 -
NVIC
1 2 3 4 5 6 7NVIC_InitTypeDef NVIC_InitStructure; NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; NVIC_Init(&NVIC_InitStructure); -
启动定时器
1TIM_Cmd(TIM2,ENABLE);
外部时钟
-
RCC使能
1 2RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE); RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE); -
GPIO配置
1 2 3 4 5GPIO_InitTypeDef GPIO_InitStructure; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOA,&GPIO_InitStructure); -
外部时钟模式设置
1TIM_ETRClockMode2Config(TIM2,TIM_ExtTRGPSC_OFF,TIM_ExtTRGPolarity_NonInverted,0x0f); -
时基单元配置
1 2 3 4 5 6 7TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure; TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1; TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up; TIM_TimeBaseInitStructure.TIM_Period = 10-1; TIM_TimeBaseInitStructure.TIM_Prescaler = 1-1; TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0; TIM_TimeBaseInit(TIM2,&TIM_TimeBaseInitStructure); -
使能中断
1TIM_ITConfig(TIM2,TIM_IT_Update,ENABLE); -
NVIC配置
1 2 3 4 5 6 7NVIC_InitTypeDef NVIC_InitStructure; NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; NVIC_Init(&NVIC_InitStructure); -
启动定时器
1TIM_Cmd(TIM2,ENABLE);
输出比较
- OC(Output Compare)输出比较
输出比较可以通过比较CNT与CCR寄存器值的关系,来对输出电平进行置1、置0或翻转的操作,用于输出一定频率和占空比的PWM波形
每个高级定时器和通用定时器都拥有4个输出比较通道
高级定时器的前3个通道额外拥有死区生成和互补输出的功能
- PWM脉冲宽度调制
在具有惯性的系统中,可以通过对一系列脉冲的宽度进行调制,来等效地获得所需要的模拟参量,常应用于电机控速等领域
参数:频率 = 1 / TS 占空比 = TON / TS 分辨率 = 占空比变化步距
输出比较通道
输出比较模式
| 模式 | 描述 |
|---|---|
| 冻结 | CNT=CCR时,REF保持为原状态 |
| 匹配时置有效电平 | CNT=CCR时,REF置有效电平 |
| 匹配时置无效电平 | CNT=CCR时,REF置无效电平 |
| 匹配时电平翻转 | CNT=CCR时,REF电平翻转 |
| 强制为无效电平 | CNT与CCR无效,REF强制为无效电平 |
| 强制为有效电平 | CNT与CCR无效,REF强制为有效电平 |
| PWM模式1 | 向上计数:CNT<CCR时,REF置有效电平,CNT≥CCR时,REF置无效电平向下计数:CNT>CCR时,REF置无效电平,CNT≤CCR时,REF置有效电平 |
| PWM模式2 | 向上计数:CNT<CCR时,REF置无效电平,CNT≥CCR时,REF置有效电平向下计数:CNT>CCR时,REF置有效电平,CNT≤CCR时,REF置无效电平 |
PWM基本结构
参数计算
- PWM频率:Freq = CK_PSC / (PSC + 1) / (ARR + 1)
- PWM占空比:Duty = CCR / (ARR + 1)
- PWM分辨率:Reso = 1 / (ARR + 1)
LED呼吸灯
-
内部时钟配置
1TIM_InternalClockConfig(TIM2); -
时基单元
1 2 3 4 5 6 7TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure; TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1; TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up; TIM_TimeBaseInitStructure.TIM_Period = 100-1;//ARR TIM_TimeBaseInitStructure.TIM_Prescaler = 720-1;//PSC TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0; TIM_TimeBaseInit(TIM2,&TIM_TimeBaseInitStructure); -
输出比较单元
1 2 3 4 5 6 7TIM_OCInitTypeDef TIM_OCinitStructure; TIM_OCStructInit(&TIM_OCinitStructure);//给结构体赋初始值 TIM_OCinitStructure.TIM_OCMode = TIM_OCMode_PWM1;//输出比较模式 TIM_OCinitStructure.TIM_OCPolarity = TIM_OCPolarity_High;//极性 TIM_OCinitStructure.TIM_OutputState = TIM_OutputState_Enable;//输出使能 TIM_OCinitStructure.TIM_Pulse = 50;//CCR的值 TIM_OC1Init(TIM2,&TIM_OCinitStructure); -
GPIO
1 2 3 4 5GPIO_InitTypeDef GPIO_InitStructure; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;//复用推挽输出 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz ; GPIO_Init(GPIOA,&GPIO_InitStructure); -
启动定时器
1TIM_Cmd(TIM2,ENABLE); -
控制PMW调亮度
1 2 3 4void PWM_SetCompare1(uint16_t Compare) { TIM_SetCompare1(TIM2,Compare); }
舵机
舵机是一种根据输入PWM信号占空比来控制输出角度的装置
输入PWM信号要求:周期为20ms,高电平宽度为0.5ms~2.5ms
- PMW配置:内部时钟配置——时基单元——输出比较单元——GPIO——启动定时器
- 舵机角度函数配置
直流电机
直流电机是一种将电能转换为机械能的装置,有两个电极,当电极正接时,电机正转,当电极反接时,电机反转
直流电机属于大功率器件,GPIO口无法直接驱动,需要配合电机驱动电路来操作
TB6612是一款双路H桥型的直流电机驱动芯片,可以驱动两个直流电机并且控制其转速和方向
- PMW配置:内部时钟配置——时基单元——输出比较单元——GPIO——启动定时器
- 电机配置:复用推挽输出配置GPIO——速度配置函数
输入捕获
- IC(Input Capture)输入捕获
- 输入捕获模式下,当通道输入引脚出现指定电平跳变时,当前CNT的值将被锁存到CCR中,可用于测量PWM波形的频率、占空比、脉冲间隔、电平持续时间等参数
- 每个高级定时器和通用定时器都拥有4个输入捕获通道
- 可配置为PWMI模式,同时测量频率和占空比
- 可配合主从触发模式,实现硬件全自动测量
测频率
- 测频法:在闸门时间T内,对上升沿计次,得到N,则频率f_x=N / T
- 测周法:两个上升沿内,以标准频率fc计次,得到N ,则频率f_x=f_c / N
- 中界频率:测频法与测周法误差相等的频率点f_m=√f_c / T
测频法要求信号频率高一些,测周法要求信号频率低一些。都存在±1误差
测占空比
...