day5江协科技-TIM定时器

用一句话讲明功能就是可以定时在什么时间干什么事

我们在对rcc进行初始化的时候,需要想好我们要去怎么去设置

=================基本定时器================================================

预分频器,比如说当你选择去设定为0时,也就是将基准时钟去除以(0+1),设定为1的时候,也就是将基准时钟去除以(1+1),其余的都是同理;当我们设定好定时后,我们的计数器会不断的计数去和我们的自动重装载寄存器去进行比较,倘若到了设定的标准,则会进行中断啊等等,也叫做更新中断

===========主模式触发DAC的功能=============================================

通过这个触发信号来控制其他的外设

============================================通用计时器=====================

图片讲解的很清楚,红色框图(和普通计时器不同的是,不仅支持向上计数模式,还支持向下和中央计数模式,什么是向上计数模式,就是比如说你设定了一个自动装载值为10,从0-1-2-3-···-10,然后再归零,而向下计数就是,从10不断减到0回到装载值触发中断,然后反复;然后对于中央计数呢,就是从0开始,从0到重装值触发中断,然后回到0再触发中断,不断反复

下面的部分

=======================高级计数器==========================================

只是多加了一部分,不需要去多讲

===============本项目所讲的工程的基本结构====================================

这四个即为我们的所有时钟,进行挑选就行,而这里的中断输出控制这一块,就是说当我们进行输出中断的时候,我们需要给出是否需要,只有需要的时候,才会有中断输出控制

=============执行逻辑======================================================

这就是我们的一个预分频器的时序逻辑

CK_PSC:即为系统时钟所输出的频率

CNT_EN:可以理解为使能端,只有这个开启,我们的时钟才会进行

CK_CNT:可以从图表上看出,只有当我们的使能端开启的时候,计数器才会接收我们的时钟

计数器寄存器:从图上可以看出到达FC,此时寄存器会重新计数,改到2的时候,计数器的频率降低

更新事件:发现只有当到达FC的时候才会更新事件

预分频控制寄存器:当你改换时钟计数器计数频率的时候,只有到达重装值时,才会重新开始更换计数器的计数频率

下面的意思相同

=========================================================================

和上面的同理,但是要记住当你达到重装值的时候,就会产生更新时间,然后我们的中断标志在我们的状态寄存器中就会置1,会一直执行中断,所以使用的时候,必须要想到要定时对其进行清楚

其实本质区别就是,当你改换了重装值的时候,一个是直接进行改换,一个是等到下一次重装值结束后进行更改

========================rcc时钟数==========================================

===============项目一 定时器================================================

①:RCC初始化,开启时钟②:选择时钟源③:配置时基单元④:配置中断输出控制⑤:配置NVIC⑥:运行控制⑦写一个中断函数

============要用到的函数===================================================

即对应为③

和之前有一个函数一样

③即为运行控制④即为中断输出控制

函数5,6,7,8即为我们的选择时钟部分,根据我们的时钟选择需要的函数,可以在我们之前的那个,高级定时器那边看到

最后四个就是之前的状态寄存器里的标志位,一个是在主函数中去使用,一个是在中断中去使用

============================================================定时器计数=====

Timer.h

#include "stm32f10x.h"                  // Device header

void Timerinit(void)
{
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);
	//rcc初始化,为什么是TIM2,因为板子只有1-4
	//下一步开始选择时钟
	TIM_InternalClockConfig(TIM2);
	//选择了内部时钟,下面开始时基单元初始化
    TIM_TimeBaseInitTypeDef TimeBasestruct;
	TimeBasestruct.TIM_ClockDivision=TIM_CKD_DIV1;//这个其实没啥说法,后面在看看
	TimeBasestruct.TIM_CounterMode=TIM_CounterMode_Up;//这个就是向上计数,向下计数,中央计数啥的
	TimeBasestruct.TIM_Period=999;//TIM_Period = 目标计数次数 - 1
	TimeBasestruct.TIM_Prescaler=7199;//72MHz / 10kHz = 7200,TIM_Prescaler = 7200 - 1 = 7199
	TimeBasestruct.TIM_RepetitionCounter=0;//高级计数器的时候才会使用
	TIM_TimeBaseInit(TIM2,&TimeBasestruct);
	
	TIM_ClearFlag(TIM2, TIM_FLAG_Update);//配置好后,会默认有一个中断,要去除
	//下一步开始中断控制
	TIM_ITConfig(TIM2,TIM_IT_Update,ENABLE);
	//下一步进行NVIC优先级配置
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
	NVIC_InitTypeDef TimeBasestruct1;
	TimeBasestruct1.NVIC_IRQChannel=TIM2_IRQn;
	//指定中断通道为 TIM2 的中断通道,使 NVIC 识别并管理 TIM2 的中断请求
	TimeBasestruct1.NVIC_IRQChannelCmd=ENABLE;
	//使能 TIM2 的中断通道,允许 NVIC 响应 TIM2 的中断请求
	TimeBasestruct1.NVIC_IRQChannelPreemptionPriority=0;
	TimeBasestruct1.NVIC_IRQChannelSubPriority=0;
	NVIC_Init(&TimeBasestruct1);
	//最后一步进行使能
	TIM_Cmd(TIM2, ENABLE);
}
#ifndef __TIMER_H
#define __TIMER_H

void Timerinit(void);



#endif
#include "stm32f10x.h"                  // Device header
#include "OLED.h"
#include "Countsensor.h"
#include "Timer.h"
int16_t NUM;

int main(void)
{
	OLED_Init();                            //TIM_GetCounter(TIM2)就是计数器在不停的进行计数
	Timerinit();                            //计数器到达一个重装值的时候,此时就会进行中断
	OLED_ShowString(1,1,"NUM:");            //然后我们的NUM就会加1
	while(1)
	{
	 OLED_ShowNum(1,5,NUM,5);
		OLED_ShowNum(2,5,TIM_GetCounter(TIM2),5);
	}
	
}
void TIM2_IRQHandler(void)
{
	if (TIM_GetITStatus(TIM2, TIM_IT_Update) == SET)		//判断是否是TIM2的更新事件触发的中断
	{
		NUM  ++;												//Num变量自增,用于测试定时中断
		TIM_ClearITPendingBit(TIM2, TIM_IT_Update);			//清除TIM2更新事件的中断标志位
			        									//中断标志位必须清除													//否则中断将连续不断地触发,导致主程序卡死
	}
}

照着这个思路写的

=============================外接时钟中断计数===============================

其实就是换了一个函数,使用了外部时钟源,然后多配置一个gpio接口就行

#include "stm32f10x.h"                  // Device header

void Timerinit(void)
{
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
	GPIO_InitTypeDef  GPIO_InitStruct;
	GPIO_InitStruct.GPIO_Mode=GPIO_Mode_IPU;
	GPIO_InitStruct.GPIO_Pin=GPIO_Pin_0;
	GPIO_InitStruct.GPIO_Speed=GPIO_Speed_50MHz;
	GPIO_Init(GPIOA,&GPIO_InitStruct);
	//rcc初始化,为什么是TIM2,因为板子只有1-4
	//下一步开始选择时钟
	TIM_ETRClockMode2Config(TIM2,TIM_ExtTRGPSC_OFF,TIM_ExtTRGPolarity_NonInverted,6);
	//选择了外部时钟,下面开始时基单元初始化
    TIM_TimeBaseInitTypeDef TimeBasestruct;
	TimeBasestruct.TIM_ClockDivision=TIM_CKD_DIV1;//这个其实没啥说法,后面在看看
	TimeBasestruct.TIM_CounterMode=TIM_CounterMode_Up;//这个就是向上计数,向下计数,中央计数啥的
	TimeBasestruct.TIM_Period=10-1;//TIM_Period = 目标计数次数 - 1
	TimeBasestruct.TIM_Prescaler=1-1;//72MHz / 10kHz = 7200,TIM_Prescaler = 7200 - 1 = 7199-
	TimeBasestruct.TIM_RepetitionCounter=0;//高级计数器的时候才会使用
	TIM_TimeBaseInit(TIM2,&TimeBasestruct);
	
	TIM_ClearFlag(TIM2, TIM_FLAG_Update);//配置好后,会默认有一个中断,要去除
	//下一步开始中断控制
	TIM_ITConfig(TIM2,TIM_IT_Update,ENABLE);
	//下一步进行NVIC优先级配置
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
	NVIC_InitTypeDef TimeBasestruct1;
	TimeBasestruct1.NVIC_IRQChannel=TIM2_IRQn;
	//指定中断通道为 TIM2 的中断通道,使 NVIC 识别并管理 TIM2 的中断请求
	TimeBasestruct1.NVIC_IRQChannelCmd=ENABLE;
	//使能 TIM2 的中断通道,允许 NVIC 响应 TIM2 的中断请求
	TimeBasestruct1.NVIC_IRQChannelPreemptionPriority=0;
	TimeBasestruct1.NVIC_IRQChannelSubPriority=0;
	NVIC_Init(&TimeBasestruct1);
	//最后一步进行使能
	TIM_Cmd(TIM2, ENABLE);
}
#include "stm32f10x.h"                  // Device header
#include "OLED.h"
#include "Countsensor.h"
#include "Timer.h"
int16_t NUM;

int main(void)
{
	OLED_Init();                            //TIM_GetCounter(TIM2)就是计数器在不停的进行计数
	Timerinit();                            //计数器到达一个重装值的时候,此时就会进行中断
	OLED_ShowString(1,1,"NUM:");
	OLED_ShowString(2,1,"CNT:");            //然后我们的NUM就会加1
	while(1)
	{
	 OLED_ShowNum(1,5,NUM,5);
	 OLED_ShowNum(2,5,TIM_GetCounter(TIM2),5);
	}
	
}
void TIM2_IRQHandler(void)
{
	if (TIM_GetITStatus(TIM2, TIM_IT_Update) == SET)		//判断是否是TIM2的更新事件触发的中断
	{
		NUM++;												//Num变量自增,用于测试定时中断
		TIM_ClearITPendingBit(TIM2, TIM_IT_Update);			//清除TIM2更新事件的中断标志位
			        									//中断标志位必须清除													//否则中断将连续不断地触发,导致主程序卡死
	}
}

<think>好的,用户现在想要设计一个LED依次显示数字0到5的功能,并且这个功能可能应用于交通灯系统。我需要结合之前的对话内容来思考如何回答这个问题。首先回顾之前的对话,用户之前询问了交通灯系统的设计,包括信号相位控制、传感器数据融合、紧急优先处理等模块。现在用户提到的LED显示0-5可能与交通灯的倒计时显示有关,比如每个相位的时间显示。比如主路绿灯20秒,黄灯5秒,支路绿灯20秒,黄灯5秒,引用[1]中提到的时间参数,可能LED显示0-5是倒计时的简化版本,或者用于其他指示,比如行人通行倒计时。接下来,我需要确定如何设计这个功能。首先,LED显示数字通常使用七段数码管,每个数字对应的段码需要定义。比如0到5的每个数字对应的a到g段的亮灭情况。然后需要控制这些段码通过微控制器输出,可能涉及到GPIO口的控制,如引用[2]中提到的蜂鸣器控制类似,这里需要控制LED的各个段。然后,时序控制是关键。用户提到要依次显示0-5,可能需要每个数字显示一定时间,比如1秒,这需要用到1Hz的时钟信号,如引用[1]中的clk_1Hz。这样每个时钟周期切换一次数字,依次从0到5循环。这可能和交通灯的倒计时有关,比如每个相位的时间显示,或者作为测试模式显示系统状态。硬件设计方面,需要确定使用共阴还是共阳数码管,并设计驱动电路,可能需要三极管或驱动芯片来增强电流。软件部分需要编写段码表,并实现定时切换。例如使用STM32的定时器中断,每1秒触发一次数字切换,更新GPIO输出的段码。 在交通灯系统中的具体应用,可能需要考虑多位数码管的情况,比如两位数码管显示剩余时间,但用户这里只需要显示0-5的单数字,可能用于简单的状态指示,比如相位编号(相位0到相位5),或者测试模式下的自检显示。 还需要考虑与现有交通灯系统的整合,比如当主路绿灯亮时,显示对应的倒计时,或者用数字表示当前相位。同时,需要考虑故障处理,比如引用之前提到的故障自检机制,当LED损坏时切换到黄灯闪烁。最后,生成相关问题时要围绕LED显示设计、硬件实现、与交通灯系统的整合、扩展功能等方面提问,帮助用户深入思考可能的需求和解决方案。</think>### LED数字显示功能设计与描述 在交通灯系统中,LED依次显示数字0-5的功能通常用于**相位倒计时指示**或**状态编码显示**,其设计需结合硬件驱动与软件控制逻辑。以下是关键设计要点: --- #### 一、功能需求分析 1. **显示模式定义** - 每个数字对应交通灯的特定状态: | 数字 | 交通灯状态 | 示例应用场景 | |------|---------------------|--------------------| | 0 | 主路绿灯倒计时开始 | 引用主路绿灯时间$T_{green}=20s$[^1] | | 1-4 | 倒计时过程 | 每秒递减显示 | | 5 | 黄灯缓冲阶段 | 黄灯时间$T_{yellow}=5s$[^1] | 2. **时序控制要求** - 显示刷新频率需满足人眼视觉暂留特性: $$f_{refresh} \geq 24Hz$$ - 数字切换间隔时间与交通灯系统时钟同步: $$\Delta t = \frac{1}{clk_{1Hz}} = 1s$$[^1] --- #### 二、硬件设计实现 1. **LED驱动电路** - 采用7段数码管实现数字显示,段码对应关系: ```c // 共阴数码管段码表(0-5) const uint8_t SEGMENT_CODE[6] = { 0x3F, // 0: ABCDEF 0x06, // 1: BC 0x5B, // 2: ABGED 0x4F, // 3: ABGCD 0x66, // 4: FBGC 0x6D // 5: AFGCD }; ``` - GPIO控制逻辑(以STM32为例): ```c #define SEG_PORT GPIOB void display_number(uint8_t num) { GPIO_Write(SEG_PORT, SEGMENT_CODE[num]); } ``` 2. **同步控制模块** - 利用定时器中断实现1秒间隔切换: ```c void TIM2_IRQHandler() { static uint8_t counter = 0; if(TIM_GetITStatus(TIM2, TIM_IT_Update)) { display_number(counter % 6); counter++; TIM_ClearITPendingBit(TIM2, TIM_IT_Update); } } ``` --- #### 三、系统集成方案 1. **与交通灯协同控制** - 当主路绿灯激活时,启动0-4递减显示: $$T_{display} = T_{green} - t_{current}$$ - 黄灯阶段固定显示数字5,直至$T_{yellow}$结束[^1] 2. **故障恢复机制** - 检测段码输出异常时,触发以下操作: $$S_{error} = \begin{cases} 1 & \text{if } I_{LED} < I_{threshold} \\ 0 & \text{otherwise} \end{cases}$$ 自动切换至备用显示模式(如全段闪烁)[^2] --- #### 四、性能优化方向 1. **亮度自适应调节** - 根据环境光强动态调整PWM占空比: $$DutyCycle = k \cdot \frac{L_{env}}{L_{max}}$$ $L_{env}$为光照传感器读数,$k$为校准系数 2. **低功耗设计** - 夜间模式关闭非必要段码: $$P_{night} = 0.2 \cdot P_{day} + 0.05W_{standby}$$ ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值