STM32F407 纯寄存器操作定时器,PWM,ADC(专治花里胡哨)

定时器

在这里插入图片描述
真多啊,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;
}

发布了82 篇原创文章 · 获赞 72 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/fzf1996/article/details/98874442