定时器
真多啊,14个定时器,三种。
通用定时器
注意:
- 需要手动清除中断标志
- TIM3->ARR = 5000-1; //自动重载寄存器,10Khz 的计数频率,计数 5K 次为 500ms
TIM3->PSC = 8400-1; //预分频器
两个寄存器的计算
PSC预分频器
//这里时钟选择为 APB1 的 2 倍,而 APB1 为 42M,所以TIM3的时钟频率为84M
PSC=8400
f=84M/8400=10000Hz=10KHz
t=1/f=0.1ms
每次技术时间0.1ms
ARR=5000-1; //自动重载寄存器
计数5000次,共500ms
//定时器溢出时间计算方法:Tout=((arr+1)*(psc+1))/Ft us.
//Ft=定时器工作频率,单位:Mhz
完整代码
#include <stm32f4xx.h>
#include <sys.h>
#include <delay.h>
int main()
{
Stm32_Clock_Init(336,8,2,7); //系统时钟
delay_init(48);
SCB->AIRCR = 0x05FA0000 | 0x500;
NVIC->IP[29] = 0x50; //最低抢占优先级,最低响应优先级01 01 EXTI2中断
NVIC->ISER[0] |= (1<<29); //使能中断线29,也就是EXTI2中断
RCC->AHB1ENR |= 0x00000020; //使能GPIOF时钟
RCC->APB1ENR |= 1<<1;
GPIOF->MODER &= 0x00000000; //设置F9,F10 0001 0100 0000 0000 0000 0000
GPIOF->MODER |= 0x00140000;
GPIOF->OTYPER &= 0x00000600; //设置F9,F10推挽输出
GPIOF->OSPEEDR &= 0x00000000; //F9,F10 速度50m 0010 1000 0000 0000 0000 0000
GPIOF->OSPEEDR |= 0x00280000;
TIM3->ARR = 5000-1; //10Khz 的计数频率,计数 5K 次为 500ms
TIM3->PSC = 8400-1;
TIM3->DIER |=1<<0;
TIM3->CR1 |= 1<<0;
while(1)
{
GPIOF->BSRRL = 0x0200; //0000 0000 0010;
GPIOF->BSRRL = 0x0400;
}
}
void TIM3_IRQHandler()
{
if(TIM3->SR&0X0001)//溢出中断
{
GPIOF->BSRRH = 0x0200; //0000 0000 0010
GPIOF->BSRRH = 0x0400;
delay_ms(1000);
}
TIM3->SR&=~(1<<0);//清除中断标志位
}
PWM
#include <stm32f4xx.h>
#include <sys.h>
#include <delay.h>
int main()
{
u16 dir;
u16 led0pwmval;
Stm32_Clock_Init(336,8,2,7); //系统时钟
delay_init(48);
RCC->APB1ENR|=1<<8; //TIM14 时钟使能
RCC->AHB1ENR|=1<<5; //使能 PORTF 时钟
GPIO_Set(GPIOF,PIN9,GPIO_MODE_AF,GPIO_OTYPE_PP,GPIO_SPEED_100M,
GPIO_PUPD_PU);//复用功能,上拉输出
GPIO_AF_Set(GPIOF,9,9); //PF9,AF9
TIM14->ARR=500-1; //设定计数器自动重装值
TIM14->PSC=84-1; //预分频器不分频
TIM14->CCMR1|=6<<4; //CH1 PWM1 模式
TIM14->CCMR1|=1<<3; //CH1 预装载使能
TIM14->CCER|=1<<0; //OC1 输出使能
TIM14->CCER|=1<<1; //OC1 低电平有效
TIM14->CR1|=1<<7; //ARPE 使能
TIM14->CR1|=1<<0; //使能定时器 14
while(1)
{
delay_ms(10);
if(dir)led0pwmval++;
else led0pwmval--;
if(led0pwmval>300)dir=0;
if(led0pwmval==0)dir=1;
TIM14->CCR1 =led0pwmval;
}
}
ADC
#include <stm32f4xx.h>
#include <sys.h>
#include <delay.h>
#include <usart.h>
void Adc_Init(void); //ADC 初始化
u16 Get_Adc(u8 ch); //获得某个通道值
u16 Get_Adc_Average(u8 ch,u8 times);//得到某个通道给定次数采样的平均值
int main()
{
u16 adcx;
float temp;
Stm32_Clock_Init(336,8,2,7); //系统时钟
delay_init(168);
uart_init(84,115200);
Adc_Init(); //初始化 ADC
while(1)
{
adcx=Get_Adc_Average(5,20);
temp=(float)adcx*(3.3/4096);
adcx=temp; //整数
printf("%d.",adcx);
temp-=adcx; //小数
temp*=1000;
printf("%dV\n",(u16)temp);
delay_ms(1000);
}
}
//初始化 ADC
//这里我们仅以规则通道为例
//我们默认仅开启 ADC1_CH5
void Adc_Init(void)
{
//先初始化 IO 口
RCC->APB2ENR|=1<<8; //使能 ADC1 时钟
RCC->AHB1ENR|=1<<0; //使能 PORTA 时钟
GPIO_Set(GPIOA,PIN5,GPIO_MODE_AIN,0,0,GPIO_PUPD_PU); //PA5,模拟输入,下拉
RCC->APB2RSTR|=1<<8; //ADCs 复位
RCC->APB2RSTR&=~(1<<8); //复位结束
ADC->CCR=3<<16; //ADCCLK=PCLK2/4=84/4=21Mhz,ADC 时钟不要超过 36Mhz
ADC1->CR1=0; //CR1 设置清零
ADC1->CR2=0; //CR2 设置清零
ADC1->CR1|=0<<24; //12 位模式
ADC1->CR1|=0<<8; //非扫描模式
ADC1->CR2&=~(1<<1); //单次转换模式
ADC1->CR2&=~(1<<11); //右对齐
ADC1->CR2|=0<<28; //软件触发
ADC1->SQR1&=~(0XF<<20);
ADC1->SQR1|=0<<20; //1 个转换在规则序列中 也就是只转换规则序列 1
//设置通道 5 的采样时间
ADC1->SMPR2&=~(7<<(3*5)); //通道 5 采样时间清空
ADC1->SMPR2|=7<<(3*5); //通道 5 480 个周期,提高采样时间可以提高精确度
ADC1->CR2|=1<<0; //开启 AD 转换器
}
//获得 ADC 值
//ch:通道值 0~16
//返回值:转换结果
u16 Get_Adc(u8 ch)
{
ADC1->SQR3&=0XFFFFFFE0;//规则序列 1 通道 ch
ADC1->SQR3|=ch; //ch:通道值 0~16
ADC1->CR2|=1<<30; //启动规则转换通道
while(!(ADC1->SR&1<<1));//等待转换结束
return ADC1->DR; //返回 adc 值
}
//获取通道 ch 的转换值,取 times 次,然后平均
//ch:通道编号
//times:获取次数
//返回值:通道 ch 的 times 次转换结果平均值
u16 Get_Adc_Average(u8 ch,u8 times)
{
u32 temp_val=0;
u8 t;
for(t=0;t<times;t++)
{
temp_val+=Get_Adc(ch);
delay_ms(5);
}
return temp_val/times;
}