技术标签: stm32 # 一、STM32F407基础教程(寄存器) TIM arm 单片机
目录
使用的是正点原子的探索者开发板进行学习,芯片:STM32F407ZGTx
学习说明此文档为本人的学习笔记,注重实践,关于理论部分会给出相应的学习链接。
本文参考了《正点原子的寄存器开发指南》、《STM32F4参考手册》
详细介绍的时钟的配置与,定时器时钟如何从时钟树而来的。
包括TIM1和TIM8高级控制定时器、TIM2-5和TIM9-14通用定时器、TIM6和TIM7基本定时器。
STM32F4 的定时器除了 TIM6 和 7。其他的定时器都可以用来产生 PWM 输出。其中高级定时器 TIM1 和 TIM8 可以同时产生多达 7 路的 PWM 输出。而通用定时器也能同时产生多达 4路的 PWM 输出!这里我们仅使用 TIM14 的 CH1 产生一路 PWM 输出。
关于PWM在FPGA上的产生更加有助于理解
二、15【FPGA】呼吸灯实现_追逐者-桥的博客-程序员宅基地_fpga 呼吸灯
除了使用到了定时器中断的那几个寄存器外还用到了以下寄存器
在 t1~t2 之间,可能产生 N 次定时器溢出,这就要求我们对定时器溢出,做处理,防止高电平太长,导致数据不准确。如图15.1.1所示,t1~t2之间,CNT计数的次数等于:N*ARR+CCRx2,有了这个计数次数,再乘以 CNT 的计数周期,即可得到 t2-t1 的时间长度,即高电平持续时间。
STM32F4 的定时器,除了 TIM6 和 TIM7,其他定时器都有输入捕获功能。
//设置时钟频率:HSE=8M M=8 N=336 P=2 Q=7
//PLL=HSE/M=1M PLLCLK=PLL*N/P=168M USB=PLL*N/Q=48M
Stm32_Clock_Init(336,8,2,7);
想CFGR[12:10]位写5,即4分频,因此APB1=PLLCLK/4=42M
RCC->CFGR|=(0<<4)|(5<<10)|(4<<13);
TIM3挂载在APB1时钟总线上,
TIM3由于在配置APB1的时候使用了4分频,所以定时器进行了2倍频,为84MHz。
RCC->APB1ENR |= 1<<1;
时间计算公式:Tout = ( (arr+1) * (psc+1) ) / Tclk;
TIM3->ARR=arr; //设置TIM3的自动装载值
TIM3->PSC=psc; //预分频器设置
TIM3->DIER|=1<<0;
TIM3->CR1|=0x01;
使能定时计数器器,且为递增计数
MY_NVIC_Init(1,3,TIM3_IRQn,2);
TIMX-SR状态寄存器:
void TIM3_IRQHandler(void)
{
if(TIM3->SR&0X0001) //中断发生,最低位由硬件置1
{
LED1=!LED1;
}
TIM3->SR&=~(1<<0); //必须将最低位软件置0,等待下次中断的到来
}
TIM(定时器)=84MHz psc(分频系数)=8400 arr(重装在值)=5000
定时器计数频率 = 84MHz / 8400 =10KHz
Tout = 5000 / 10KHz = 0.5s
int main(void)
{
Stm32_Clock_Init(336,8,2,7); //pll=1M pllclk=168M
delay_init(168);
LED_Init();
TIM3_Int_Init(5000-1,8400-1); //arr psc
while(1)
{
LED0=!LED0;
delay_ms(200);
};
}
RCC->APB1ENR|=1<<8; //使能TIM13定时器的时钟
RCC->AHB1ENR|=1<<5; //使能端口FA9的端口时钟
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=arr; //重装载值
TIM14->PSC=psc; //分频系数
TIM14-CCMR1捕获比较寄存器1相关位描述
TIMx_CCER捕获/比较使能寄存器相关位描述
TIM14->CCMR1|=6<<4; //打开TIM14的CH1
TIM14->CCMR1|=1<<3; //使能与 TIM14_CCR1 相关的预装载寄存器
TIM14->CCER|=1<<0; //下降沿触发,低电平有效
TIM14->CCER|=1<<1; //使能CH1输出
TIM14->CR1|=1<<7; //自动装载进行缓存
TIM14->CR1|=1<<0; //定时计数器使能
#define LED0_PWM_VAL TIM14->CCR1
int main(void)
{
u16 led0pwmval=0; //TIM14-CCR1的值,及占空比的计数值
u8 dir=1;
Stm32_Clock_Init(336,8,2,7);
delay_init(168);
TIM14_PWM_Init(500-1,84-1); //1MHz的计数频率,PWM频率2KHz, T=0.5ms
while(1)
{
delay_ms(10); //10ms重载一次占空比,20次PWM的输出
if(dir)led0pwmval++; //占空比增加
else led0pwmval--; //占空比减小
if(led0pwmval>300)dir=0;
if(led0pwmval==0)dir=1;
LED0_PWM_VAL=led0pwmval; //重新装载占空比值
}
}
RCC->APB1ENR|=1<<3;
RCC->AHB1ENR|=1<<0;
GPIO_Set(GPIOA,PIN0,GPIO_MODE_AF,GPIO_OTYPE_PP,GPIO_SPEED_100M,GPIO_PUPD_PD);
GPIO_AF_Set(GPIOA,0,2); //PA0,AF2 (TIM5-CH1)
计数分频系数与计数器数设置,在定时器中断有相关描述
TIM5->ARR=arr;
TIM5->PSC=psc;
TIM5-CCMR1捕获比较寄存器1相关位描述
TIM5_CCER捕获/比较使能寄存器相关位描述
TIM5->CCMR1|=1<<0; //CCIS位,将CC1设置成输入且映射到TI1
TIM5->CCMR1|=0<<4; //IC1PSC,无分频
TIM5->CCMR1|=0<<10; //IC1F,无滤波器
TIM5->CCER|=0<<1; //CC1P,无反向,上升沿触发
TIM5->CCER|=1<<0; //CC1E,使能输入捕获
TIM5->DIER|=1<<1;
TIM5->DIER|=1<<0;
//设置软件控制产生更新事件,是载入PSC值立刻生效,否则要等到溢出后才生效
TIM5->EGR=1<<0;
TIM5->CR1|=0x01;
MY_NVIC_Init(2,0,TIM5_IRQn,2)
u8 TIM5CH1_CAPTURE_STA=0; //捕获标志0x40上升沿捕获,0x80下降沿捕获
u32 TIM5CH1_CAPTURE_VAL; //捕获计数值存储空间
void TIM5_IRQHandler(void)
{
u16 tsr;
tsr=TIM5->SR; //定时器状态寄存器
if((TIM5CH1_CAPTURE_STA&0X80)==0) //捕获未完成
{
if(tsr&0X01) //定时器溢出标志
{
if(TIM5CH1_CAPTURE_STA&0X40) //上升沿被捕获到后
{
if((TIM5CH1_CAPTURE_STA&0X3F)==0X3F) //达到计数器溢出值
{
TIM5CH1_CAPTURE_STA|=0X80; //标记捕获到了一个定时计数器周期
TIM5CH1_CAPTURE_VAL=0XFFFFFFFF; //保存一个完成的计数周期
}else TIM5CH1_CAPTURE_STA++; //计数器未溢出
}
}
if(tsr&0x02) //发生上升沿捕获事件进入中断
{
if(TIM5CH1_CAPTURE_STA&0X40) //上升沿捕获已完成,下降沿捕获中断进入
{
TIM5CH1_CAPTURE_STA|=0X80; //已经捕获到下降沿标志
TIM5CH1_CAPTURE_VAL=TIM5->CCR1; //储存捕获计数器值
TIM5->CCER&=~(1<<1); //设置为上升沿捕获进入中断
}else //将计数器清零,重新计数
{
TIM5CH1_CAPTURE_STA=0;
TIM5CH1_CAPTURE_VAL=0;
TIM5CH1_CAPTURE_STA|=0X40; //已经捕获到上升沿标志
TIM5->CR1&=~(1<<0); //使能定时器
TIM5->CNT=0; //清空计数器
TIM5->CCER|=1<<1; //设置为下降沿捕获进入中断
TIM5->CR1|=0x01; //开启定时器
}
}
}
TIM5->SR=0;
}
extern u8 TIM5CH1_CAPTURE_STA;
extern u32 TIM5CH1_CAPTURE_VAL;
int main(void)
{
long long temp=0;
Stm32_Clock_Init(336,8,2,7);
delay_init(168);
uart_init(84,115200);
TIM14_PWM_Init(500-1,84-1);
TIM5_CH1_Cap_Init(0XFFFFFFFF,84-1);
while(1)
{
delay_ms(10);
LED0_PWM_VAL++;
if(LED0_PWM_VAL==300)LED0_PWM_VAL=0;
if(TIM5CH1_CAPTURE_STA&0X80) //捕获到了一个定时器计数周期或者下降沿
{
temp=TIM5CH1_CAPTURE_STA&0X3F; //提取捕获值
temp*=0XFFFFFFFF; //计算捕获时间
temp+=TIM5CH1_CAPTURE_VAL; //加入定时器周期时间和下降沿捕获时间
printf("HIGH:%lld us\r\n",temp); //输出捕获总时间
TIM5CH1_CAPTURE_STA=0; //将捕获标志位清0,进入下一次捕获
}
}
}
电容触摸按键:电容按键是接触式的,点一下就松开(与微动开关类似),因此需要消除抖。在之前的微动开关使用时间延迟判断两次,状态相同时才认为是按下。这里同理,这里使用的是输入捕获即手指接触一定时间后到达B认为电容按键按下。
正点原子中的文档内容描述:
对于电容按键用的不是特别多,这里不进行实验,有需要的可以自己去看一下正点原子的相关实验。
文章浏览阅读2.5w次,点赞30次,收藏189次。文章目录前言一、流水线协议二、滑动窗口协议1.GBN(回退N重传协议)2.SR(选择重传协议)总结前言提示:以下是本篇文章正文内容一、流水线协议我们知道Rdt 3.0: 停等操作过程中浪费了大量的时间:从而在Rdt 3.0上引入了流水线机制:为了提高资源利用率流水线协议:允许发送方在收到ACK之前连续发送多个分组,更大的序列号范围,同时发送方和/或接收方需要更大的存储空间以缓存分组如图:二、滑动窗口协议滑动窗口协议:发送方和接收方各有一个缓存数组,发送方存放着:已发送且.._gbn协议
文章浏览阅读6.5k次,点赞8次,收藏51次。线性时序逻辑提供了一种非常直观但是在数学上又很精确的表示方法来描述LT性质,70年代后期,Pnueli提出将线性时序逻辑应用于验证复杂计算机系统。_线性时序逻辑
文章浏览阅读976次,点赞19次,收藏20次。同一个位置的两种高度值一般可以相差几十米,只是因为当地平均海平面是和地形有关的,凹凸不平没有规律。而ellipsoid height采用的基准是地球标准椭球模型,它的高度值和地形没有关系,只和到地心的距离有关。下文的mavros指ros1 noetic版本的,ros2版本的我还没研究。_椭球高转换海拔高
文章浏览阅读1.3k次。提取码: 2i5t++++++++++++++++++++收集了大宇的16个DOS游戏,WIN10可以直接玩,具体的都忘记了,有轩辕剑什么的但是阿猫阿狗大作战这个游戏画风可是真喜欢!!非常喜欢,这里就放出来给大家共享了。+++++++++++++++++++++++++++++++++++++++++《阿猫阿狗大作战Online》是由大宇集团旗下的上海软星于2005年研发的新一代3D休闲类网络对战..._win10 64位 怎么运行阿猫阿狗1
文章浏览阅读211次,点赞10次,收藏2次。本文使用AutoHotkey定义快捷键打开对话框,用户粘贴博客地址,通过命令行调用clean-mark将网页博客转为Markdown文件。
文章浏览阅读2.5k次,点赞5次,收藏42次。作者 |yyl424525来源 | 程序员宅基地文章目录1. 简介安装支持四种图绘制网络图基本流程2. Graph-无向图节点边属性有向图和无向图互转3. DiGrap..._多层复杂网络 绘制
文章浏览阅读356次。UIView//建立父子关系时,父视图,会保存一个子视图的强指针[self.view addSubView:view];//将视图插入到指定位置[self.view insertSubview:view addIndex:2];//将视图插入到指定视图的下面[self.view insertSubview:subView belowSubview:view]_有码 插入
文章浏览阅读9.4k次,点赞44次,收藏216次。Linux的进程软中断通信一、软中断信号二、函数介绍(1)wait函数(2)signal函数(3)sleep函数(4)kill函数三、示例一、软中断信号软中断信号(signalsignalsignal,又简称为信号)用来通知进程发生了事件。进程之间可以通过调用kill函数发送软中断信号。LinuxLinuxLinux 内核也可能给进程发送信号,通知进程发生了某个事件(例如内存越界)。注意:信号只是用来通知某进程发生了什么事件,无法给进程传递任何数据,进程对信号的处理方法有三种:① 忽略某个信号,对该_进程软中断通信
文章浏览阅读94次。java计算机毕业设计定西扶贫惠农推介系统源码+数据库+系统+lw文档+部署。springboot疫情期间中小学生作业线上管理系统设计与实现。ssh基于java的网上手机销售管理系统的开发与实现mysql。springboot基于JSP的企业办公管理系统设计与实现。springboot校园二手电动车交易平台的设计与实现。JSP网上商城与拍卖系统的设计与实现sqlserver。JSP宠物食品店系统的设计与实现sqlserver。springboot基于智慧推荐的在线教育管理系统。_基于java的西部惠农平台实验报告
文章浏览阅读1w次。3.主机系统管理Proxmox VE基于著名的DebianLinux发行版。这意味着您可以访问Debian软件包的整个领域,并且基本系统的文档记录非常详尽。在Debian的管理员手册可在网上,并提供了一个全面介绍了Debian的操作系统(请参阅[Hertzog13])。标准的Proxmox VE安装使用Debian的默认存储库,因此您可以通过该渠道获得错误修复和安全更新。此..._未启用proxmox ve存储库
文章浏览阅读426次。Java的数据类型包括基本数据类型和引用数据类型。基本数据类型有byte、short、int、long、float、double、char和boolean,用于处理简单类型的数据。引用数据类型有class、interface和array,用于处理复杂类型的数据。在程序开发中,应根据具体情况选择合适的数据类型,以实现数据存储和计算的需要。_java数据类型
文章浏览阅读9.6w次,点赞50次,收藏30次。latex中输入双引号时,如果都直接用键盘上的双引号键,打出的是一顺撇的。左面引号的正确输入法是:按两次“Tab上面,数字1左面那个键”。至于后边的引号,与老方法是一样的,即按两次单引号键(或一次SHIFT+单引号键---也就是一次双引号键啦怎么输入左单引号、左双引号、右单引号、有双引号?左单引号:`(键盘上1旁边的那个);左双引号:``;右单引号:'(键盘分号的右边那个);右双引号:''或"。在_latex 双引号